In the presence of modules, we can have multiple implicit instantiations of the same template. Teach RecursiveASTVisitor to visit all of those, not just one of them. This is difficult to test by itself, but will be covered by an upcoming change.

llvm-svn: 204175
This commit is contained in:
Richard Smith 2014-03-18 20:31:31 +00:00
parent aec21ce43e
commit 1b42d1c7ac
2 changed files with 121 additions and 81 deletions

View File

@ -1407,20 +1407,27 @@ template<typename Derived>
bool DataRecursiveASTVisitor<Derived>::TraverseClassInstantiations( bool DataRecursiveASTVisitor<Derived>::TraverseClassInstantiations(
ClassTemplateDecl *D) { ClassTemplateDecl *D) {
for (auto *SD : D->specializations()) { for (auto *SD : D->specializations()) {
switch (SD->getSpecializationKind()) { for (auto *RD : SD->redecls()) {
// Visit the implicit instantiations with the requested pattern. // We don't want to visit injected-class-names in this traversal.
case TSK_Undeclared: if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
case TSK_ImplicitInstantiation: continue;
TRY_TO(TraverseDecl(SD));
break;
// We don't need to do anything on an explicit instantiation switch (cast<ClassTemplateSpecializationDecl>(RD)->
// or explicit specialization because there will be an explicit getSpecializationKind()) {
// node for it elsewhere. // Visit the implicit instantiations with the requested pattern.
case TSK_ExplicitInstantiationDeclaration: case TSK_Undeclared:
case TSK_ExplicitInstantiationDefinition: case TSK_ImplicitInstantiation:
case TSK_ExplicitSpecialization: TRY_TO(TraverseDecl(RD));
break; break;
// We don't need to do anything on an explicit instantiation
// or explicit specialization because there will be an explicit
// node for it elsewhere.
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization:
break;
}
} }
} }
@ -1453,20 +1460,23 @@ template <typename Derived>
bool DataRecursiveASTVisitor<Derived>::TraverseVariableInstantiations( bool DataRecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
VarTemplateDecl *D) { VarTemplateDecl *D) {
for (auto *SD : D->specializations()) { for (auto *SD : D->specializations()) {
switch (SD->getSpecializationKind()) { for (auto *RD : SD->redecls()) {
// Visit the implicit instantiations with the requested pattern. switch (cast<VarTemplateSpecializationDecl>(RD)->
case TSK_Undeclared: getSpecializationKind()) {
case TSK_ImplicitInstantiation: // Visit the implicit instantiations with the requested pattern.
TRY_TO(TraverseDecl(SD)); case TSK_Undeclared:
break; case TSK_ImplicitInstantiation:
TRY_TO(TraverseDecl(RD));
break;
// We don't need to do anything on an explicit instantiation // We don't need to do anything on an explicit instantiation
// or explicit specialization because there will be an explicit // or explicit specialization because there will be an explicit
// node for it elsewhere. // node for it elsewhere.
case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition: case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization: case TSK_ExplicitSpecialization:
break; break;
}
} }
} }
@ -1501,21 +1511,25 @@ template<typename Derived>
bool DataRecursiveASTVisitor<Derived>::TraverseFunctionInstantiations( bool DataRecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
FunctionTemplateDecl *D) { FunctionTemplateDecl *D) {
for (auto *FD : D->specializations()) { for (auto *FD : D->specializations()) {
switch (FD->getTemplateSpecializationKind()) { for (auto *RD : FD->redecls()) {
case TSK_Undeclared: switch (RD->getTemplateSpecializationKind()) {
case TSK_ImplicitInstantiation: case TSK_Undeclared:
// We don't know what kind of FunctionDecl this is. case TSK_ImplicitInstantiation:
TRY_TO(TraverseDecl(FD)); // We don't know what kind of FunctionDecl this is.
break; TRY_TO(TraverseDecl(RD));
break;
// No need to visit explicit instantiations, we'll find the node // No need to visit explicit instantiations, we'll find the node
// eventually. // eventually.
case TSK_ExplicitInstantiationDeclaration: // FIXME: This is incorrect; there is no other node for an explicit
case TSK_ExplicitInstantiationDefinition: // instantiation of a function template specialization.
break; case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
break;
case TSK_ExplicitSpecialization: case TSK_ExplicitSpecialization:
break; break;
}
} }
} }

View File

@ -1488,35 +1488,59 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
return true; return true;
} }
#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ template<typename Derived>
/* A helper method for traversing the implicit instantiations of a bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
class or variable template. */ \ ClassTemplateDecl *D) {
template<typename Derived> \ for (auto *SD : D->specializations()) {
bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( \ for (auto *RD : SD->redecls()) {
TMPLDECLKIND##TemplateDecl *D) { \ // We don't want to visit injected-class-names in this traversal.
for (auto *SD : D->specializations()) { \ if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
switch (SD->getSpecializationKind()) { \ continue;
/* Visit the implicit instantiations with the requested pattern. */ \
case TSK_Undeclared: \ switch (cast<ClassTemplateSpecializationDecl>(RD)->
case TSK_ImplicitInstantiation: \ getSpecializationKind()) {
TRY_TO(TraverseDecl(SD)); \ // Visit the implicit instantiations with the requested pattern.
break; \ case TSK_Undeclared:
\ case TSK_ImplicitInstantiation:
/* We don't need to do anything on an explicit instantiation TRY_TO(TraverseDecl(RD));
or explicit specialization because there will be an explicit break;
node for it elsewhere. */ \
case TSK_ExplicitInstantiationDeclaration: \ // We don't need to do anything on an explicit instantiation
case TSK_ExplicitInstantiationDefinition: \ // or explicit specialization because there will be an explicit
case TSK_ExplicitSpecialization: \ // node for it elsewhere.
break; \ case TSK_ExplicitInstantiationDeclaration:
} \ case TSK_ExplicitInstantiationDefinition:
} \ case TSK_ExplicitSpecialization:
\ break;
return true; \ }
}
}
return true;
}
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
VarTemplateDecl *D) {
for (auto *SD : D->specializations()) {
for (auto *RD : SD->redecls()) {
switch (cast<VarTemplateSpecializationDecl>(RD)->
getSpecializationKind()) {
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
TRY_TO(TraverseDecl(RD));
break;
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization:
break;
}
}
}
return true;
} }
DEF_TRAVERSE_TMPL_INST(Class)
DEF_TRAVERSE_TMPL_INST(Var)
// A helper method for traversing the instantiations of a // A helper method for traversing the instantiations of a
// function while skipping its specializations. // function while skipping its specializations.
@ -1524,22 +1548,24 @@ template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations( bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
FunctionTemplateDecl *D) { FunctionTemplateDecl *D) {
for (auto *FD : D->specializations()) { for (auto *FD : D->specializations()) {
switch (FD->getTemplateSpecializationKind()) { for (auto *RD : FD->redecls()) {
case TSK_Undeclared: switch (RD->getTemplateSpecializationKind()) {
case TSK_ImplicitInstantiation: case TSK_Undeclared:
// We don't know what kind of FunctionDecl this is. case TSK_ImplicitInstantiation:
TRY_TO(TraverseDecl(FD)); // We don't know what kind of FunctionDecl this is.
break; TRY_TO(TraverseDecl(RD));
break;
// FIXME: For now traverse explicit instantiations here. Change that // FIXME: For now traverse explicit instantiations here. Change that
// once they are represented as dedicated nodes in the AST. // once they are represented as dedicated nodes in the AST.
case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition: case TSK_ExplicitInstantiationDefinition:
TRY_TO(TraverseDecl(FD)); TRY_TO(TraverseDecl(RD));
break; break;
case TSK_ExplicitSpecialization: case TSK_ExplicitSpecialization:
break; break;
}
} }
} }