Author: Haojian Wu Date: 2023-12-20T10:08:43+01:00 New Revision: 3b1f06e52712a56bf33757d596482c60013d63fd
URL: https://github.com/llvm/llvm-project/commit/3b1f06e52712a56bf33757d596482c60013d63fd DIFF: https://github.com/llvm/llvm-project/commit/3b1f06e52712a56bf33757d596482c60013d63fd.diff LOG: [AST] RecursiveASTVisitor: traverse the require clause for partial template specializations. (#75795) This fixes tooling (clangd, include-cleaner) bugs where we miss functionalities on concept AST nodes. Added: Modified: clang/include/clang/AST/RecursiveASTVisitor.h clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index c501801b95bd95..8f2714e142bbe3 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2036,12 +2036,7 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ /* The partial specialization. */ \ - if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ - I != E; ++I) { \ - TRY_TO(TraverseDecl(*I)); \ - } \ - } \ + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ /* The args that remains unspecialized. */ \ TRY_TO(TraverseTemplateArgumentLocsHelper( \ D->getTemplateArgsAsWritten()->getTemplateArgs(), \ diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp index 594b299b543694..6a8d91672f1d93 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp @@ -86,6 +86,25 @@ TEST(RecursiveASTVisitor, Concepts) { EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed); EXPECT_EQ(1, Visitor.ConceptReferencesTraversed); EXPECT_EQ(1, Visitor.ConceptReferencesVisited); + + Visitor = {}; + llvm::StringRef Code = + R"cpp( +template<typename T> concept True = false; +template <typename F> struct Foo {}; + +template <typename F> + requires requires { requires True<F>; } +struct Foo<F> {}; + +template <typename F> requires True<F> +struct Foo<F> {}; + )cpp"; + EXPECT_TRUE(Visitor.runOver(Code, ConceptVisitor::Lang_CXX2a)); + // Check that the concept references from the partial specializations are + // visited. + EXPECT_EQ(2, Visitor.ConceptReferencesTraversed); + EXPECT_EQ(2, Visitor.ConceptReferencesVisited); } struct VisitDeclOnlyOnce : ExpectedLocationVisitor<VisitDeclOnlyOnce> { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits