When we form a new function/class template specialization, we first

search for the specialization (in a folding set) and, if not found
form a *Decl that is then inserted into that folding set. In rare
cases, the folding set may be reallocated between the search and the
insertion, causing a crash. No test case, because triggering rehashing
consistently in a small test case is not feasible. Fixes
<rdar://problem/11115071>.

llvm-svn: 153575
This commit is contained in:
Douglas Gregor 2012-03-28 14:34:23 +00:00
parent 20b32d2da6
commit ce9978ff1f
3 changed files with 27 additions and 24 deletions

View File

@ -2255,22 +2255,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
TemplateArgsAsWritten, TemplateArgsAsWritten,
PointOfInstantiation); PointOfInstantiation);
TemplateOrSpecialization = Info; TemplateOrSpecialization = Info;
Template->addSpecialization(Info, InsertPos);
// Insert this function template specialization into the set of known
// function template specializations.
if (InsertPos)
Template->addSpecialization(Info, InsertPos);
else {
// Try to insert the new node. If there is an existing node, leave it, the
// set will contain the canonical decls while
// FunctionTemplateDecl::findSpecialization will return
// the most recent redeclarations.
FunctionTemplateSpecializationInfo *Existing
= Template->getSpecializations().GetOrInsertNode(Info);
(void)Existing;
assert((!Existing || Existing->Function->isCanonicalDecl()) &&
"Set is supposed to only contain canonical decls");
}
} }
void void

View File

@ -238,7 +238,10 @@ FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
void FunctionTemplateDecl::addSpecialization( void FunctionTemplateDecl::addSpecialization(
FunctionTemplateSpecializationInfo *Info, void *InsertPos) { FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
getSpecializations().InsertNode(Info, InsertPos); if (InsertPos)
getSpecializations().InsertNode(Info, InsertPos);
else
getSpecializations().GetOrInsertNode(Info);
if (ASTMutationListener *L = getASTMutationListener()) if (ASTMutationListener *L = getASTMutationListener())
L->AddedCXXTemplateSpecialization(this, Info->Function); L->AddedCXXTemplateSpecialization(this, Info->Function);
} }
@ -322,7 +325,14 @@ ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
void *InsertPos) { void *InsertPos) {
getSpecializations().InsertNode(D, InsertPos); if (InsertPos)
getSpecializations().InsertNode(D, InsertPos);
else {
ClassTemplateSpecializationDecl *Existing
= getSpecializations().GetOrInsertNode(D);
(void)Existing;
assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
}
if (ASTMutationListener *L = getASTMutationListener()) if (ASTMutationListener *L = getASTMutationListener())
L->AddedCXXTemplateSpecialization(this, D); L->AddedCXXTemplateSpecialization(this, D);
} }
@ -338,7 +348,15 @@ ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
void ClassTemplateDecl::AddPartialSpecialization( void ClassTemplateDecl::AddPartialSpecialization(
ClassTemplatePartialSpecializationDecl *D, ClassTemplatePartialSpecializationDecl *D,
void *InsertPos) { void *InsertPos) {
getPartialSpecializations().InsertNode(D, InsertPos); if (InsertPos)
getPartialSpecializations().InsertNode(D, InsertPos);
else {
ClassTemplatePartialSpecializationDecl *Existing
= getPartialSpecializations().GetOrInsertNode(D);
(void)Existing;
assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
}
if (ASTMutationListener *L = getASTMutationListener()) if (ASTMutationListener *L = getASTMutationListener())
L->AddedCXXTemplateSpecialization(this, D); L->AddedCXXTemplateSpecialization(this, D);
} }

View File

@ -1014,11 +1014,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
// Check whether there is already a function template specialization for // Check whether there is already a function template specialization for
// this declaration. // this declaration.
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
void *InsertPos = 0;
if (FunctionTemplate && !TemplateParams) { if (FunctionTemplate && !TemplateParams) {
std::pair<const TemplateArgument *, unsigned> Innermost std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost(); = TemplateArgs.getInnermost();
void *InsertPos = 0;
FunctionDecl *SpecFunc FunctionDecl *SpecFunc
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
InsertPos); InsertPos);
@ -1148,7 +1148,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateArgumentList::CreateCopy(SemaRef.Context, TemplateArgumentList::CreateCopy(SemaRef.Context,
Innermost.first, Innermost.first,
Innermost.second), Innermost.second),
InsertPos); /*InsertPos=*/0);
} else if (isFriend) { } else if (isFriend) {
// Note, we need this connection even if the friend doesn't have a body. // Note, we need this connection even if the friend doesn't have a body.
// Its body may exist but not have been attached yet due to deferred // Its body may exist but not have been attached yet due to deferred
@ -1316,7 +1316,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
TemplateParameterList *TemplateParams, TemplateParameterList *TemplateParams,
bool IsClassScopeSpecialization) { bool IsClassScopeSpecialization) {
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
void *InsertPos = 0;
if (FunctionTemplate && !TemplateParams) { if (FunctionTemplate && !TemplateParams) {
// We are creating a function template specialization from a function // We are creating a function template specialization from a function
// template. Check whether there is already a function template // template. Check whether there is already a function template
@ -1324,6 +1323,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
std::pair<const TemplateArgument *, unsigned> Innermost std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost(); = TemplateArgs.getInnermost();
void *InsertPos = 0;
FunctionDecl *SpecFunc FunctionDecl *SpecFunc
= FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
InsertPos); InsertPos);
@ -1476,7 +1476,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
TemplateArgumentList::CreateCopy(SemaRef.Context, TemplateArgumentList::CreateCopy(SemaRef.Context,
Innermost.first, Innermost.first,
Innermost.second), Innermost.second),
InsertPos); /*InsertPos=*/0);
} else if (!isFriend) { } else if (!isFriend) {
// Record that this is an instantiation of a member function. // Record that this is an instantiation of a member function.
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
@ -2125,7 +2125,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Add this partial specialization to the set of class template partial // Add this partial specialization to the set of class template partial
// specializations. // specializations.
ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos); ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);
return InstPartialSpec; return InstPartialSpec;
} }