diff --git a/clang/include/clang/AST/DataRecursiveASTVisitor.h b/clang/include/clang/AST/DataRecursiveASTVisitor.h index 57f404338966..5afa9cd679c3 100644 --- a/clang/include/clang/AST/DataRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DataRecursiveASTVisitor.h @@ -1407,20 +1407,27 @@ template bool DataRecursiveASTVisitor::TraverseClassInstantiations( ClassTemplateDecl *D) { for (auto *SD : D->specializations()) { - switch (SD->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(SD)); - break; + for (auto *RD : SD->redecls()) { + // We don't want to visit injected-class-names in this traversal. + if (cast(RD)->isInjectedClassName()) + continue; - // 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; + switch (cast(RD)-> + getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(RD)); + 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 bool DataRecursiveASTVisitor::TraverseVariableInstantiations( VarTemplateDecl *D) { for (auto *SD : D->specializations()) { - switch (SD->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(SD)); - break; + for (auto *RD : SD->redecls()) { + switch (cast(RD)-> + getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(RD)); + 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; + // 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; + } } } @@ -1501,21 +1511,25 @@ template bool DataRecursiveASTVisitor::TraverseFunctionInstantiations( FunctionTemplateDecl *D) { for (auto *FD : D->specializations()) { - switch (FD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - // We don't know what kind of FunctionDecl this is. - TRY_TO(TraverseDecl(FD)); - break; + for (auto *RD : FD->redecls()) { + switch (RD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + // We don't know what kind of FunctionDecl this is. + TRY_TO(TraverseDecl(RD)); + break; - // No need to visit explicit instantiations, we'll find the node - // eventually. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - break; + // No need to visit explicit instantiations, we'll find the node + // eventually. + // FIXME: This is incorrect; there is no other node for an explicit + // instantiation of a function template specialization. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + break; - case TSK_ExplicitSpecialization: - break; + case TSK_ExplicitSpecialization: + break; + } } } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 54412bf4bca6..3226c3c32d86 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1488,35 +1488,59 @@ bool RecursiveASTVisitor::TraverseTemplateParameterListHelper( return true; } -#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ -/* A helper method for traversing the implicit instantiations of a - class or variable template. */ \ -template \ -bool RecursiveASTVisitor::TraverseTemplateInstantiations( \ - TMPLDECLKIND##TemplateDecl *D) { \ - for (auto *SD : D->specializations()) { \ - switch (SD->getSpecializationKind()) { \ - /* Visit the implicit instantiations with the requested pattern. */ \ - case TSK_Undeclared: \ - case TSK_ImplicitInstantiation: \ - TRY_TO(TraverseDecl(SD)); \ - 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; \ - } \ - } \ - \ - return true; \ +template +bool RecursiveASTVisitor::TraverseTemplateInstantiations( + ClassTemplateDecl *D) { + for (auto *SD : D->specializations()) { + for (auto *RD : SD->redecls()) { + // We don't want to visit injected-class-names in this traversal. + if (cast(RD)->isInjectedClassName()) + continue; + + switch (cast(RD)-> + getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(RD)); + 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; + } + } + } + + return true; +} + +template +bool RecursiveASTVisitor::TraverseTemplateInstantiations( + VarTemplateDecl *D) { + for (auto *SD : D->specializations()) { + for (auto *RD : SD->redecls()) { + switch (cast(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 // function while skipping its specializations. @@ -1524,22 +1548,24 @@ template bool RecursiveASTVisitor::TraverseTemplateInstantiations( FunctionTemplateDecl *D) { for (auto *FD : D->specializations()) { - switch (FD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - // We don't know what kind of FunctionDecl this is. - TRY_TO(TraverseDecl(FD)); - break; + for (auto *RD : FD->redecls()) { + switch (RD->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + // We don't know what kind of FunctionDecl this is. + TRY_TO(TraverseDecl(RD)); + break; - // FIXME: For now traverse explicit instantiations here. Change that - // once they are represented as dedicated nodes in the AST. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - TRY_TO(TraverseDecl(FD)); - break; + // FIXME: For now traverse explicit instantiations here. Change that + // once they are represented as dedicated nodes in the AST. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + TRY_TO(TraverseDecl(RD)); + break; - case TSK_ExplicitSpecialization: - break; + case TSK_ExplicitSpecialization: + break; + } } }