From 3b1f06e52712a56bf33757d596482c60013d63fd Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Wed, 20 Dec 2023 10:08:43 +0100 Subject: [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. --- clang/include/clang/AST/RecursiveASTVisitor.h | 7 +------ .../Tooling/RecursiveASTVisitorTests/Concept.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index c501801..8f2714e 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2036,12 +2036,7 @@ bool RecursiveASTVisitor::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 594b299..6a8d916 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 concept True = false; +template struct Foo {}; + +template + requires requires { requires True; } +struct Foo {}; + +template requires True +struct Foo {}; + )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 { -- cgit v1.1