diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -473,6 +473,8 @@ bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); + bool TraverseFunctionHelper(FunctionDecl *D); + private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); @@ -488,7 +490,6 @@ bool TraverseCXXRecordHelper(CXXRecordDecl *D); bool TraverseDeclaratorHelper(DeclaratorDecl *D); bool TraverseDeclContextHelper(DeclContext *DC); - bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); bool TraverseOMPLoopDirective(OMPLoopDirective *S); @@ -2079,28 +2080,28 @@ // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). ShouldVisitChildren = false; - ReturnValue = TraverseFunctionHelper(D); + ReturnValue = getDerived().TraverseFunctionHelper(D); }) DEF_TRAVERSE_DECL(CXXDeductionGuideDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). ShouldVisitChildren = false; - ReturnValue = TraverseFunctionHelper(D); + ReturnValue = getDerived().TraverseFunctionHelper(D); }) DEF_TRAVERSE_DECL(CXXMethodDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). ShouldVisitChildren = false; - ReturnValue = TraverseFunctionHelper(D); + ReturnValue = getDerived().TraverseFunctionHelper(D); }) DEF_TRAVERSE_DECL(CXXConstructorDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). ShouldVisitChildren = false; - ReturnValue = TraverseFunctionHelper(D); + ReturnValue = getDerived().TraverseFunctionHelper(D); }) // CXXConversionDecl is the declaration of a type conversion operator. @@ -2109,14 +2110,14 @@ // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). ShouldVisitChildren = false; - ReturnValue = TraverseFunctionHelper(D); + ReturnValue = getDerived().TraverseFunctionHelper(D); }) DEF_TRAVERSE_DECL(CXXDestructorDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). ShouldVisitChildren = false; - ReturnValue = TraverseFunctionHelper(D); + ReturnValue = getDerived().TraverseFunctionHelper(D); }) template diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp --- a/clang/lib/AST/ParentMapContext.cpp +++ b/clang/lib/AST/ParentMapContext.cpp @@ -345,7 +345,7 @@ class ParentMapContext::ParentMap::ASTVisitor : public RecursiveASTVisitor { public: - ASTVisitor(ParentMap &Map) : Map(Map) {} + ASTVisitor(ParentMap &Map, ASTContext &Ctx) : Map(Map), Ctx(Ctx) {} private: friend class RecursiveASTVisitor; @@ -422,6 +422,19 @@ &Map.PointerParents); } bool TraverseTypeLoc(TypeLoc TypeLocNode) { + if (Ctx.getParentMapContext().getTraversalKind() == + TK_IgnoreUnlessSpelledInSource) { + if (auto FPTL = TypeLocNode.getAs()) { + for (unsigned I = 0, E = FPTL.getNumParams(); I != E; ++I) { + if (auto *P = FPTL.getParam(I)) { + if (!TraverseDecl(P)) + return false; + } + } + return true; + } + } + return TraverseNode( TypeLocNode, DynTypedNode::create(TypeLocNode), [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, @@ -446,11 +459,12 @@ } ParentMap ⤅ + ASTContext &Ctx; llvm::SmallVector ParentStack; }; ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) { - ASTVisitor(*this).TraverseAST(Ctx); + ASTVisitor(*this, Ctx).TraverseAST(Ctx); } DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) { diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -143,6 +143,17 @@ return Matches; } + bool TraverseFunctionHelper(FunctionDecl *FD) { + if (Finder->isTraversalIgnoringImplicitNodes()) { + for (auto *P : FD->parameters()) { + if (!TraverseDecl(P)) + return false; + } + } + return RecursiveASTVisitor::TraverseFunctionHelper( + FD); + } + // The following are overriding methods from the base visitor class. // They are public only to allow CRTP to work. They are *not *part // of the public API of this class. diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -2068,6 +2068,41 @@ Constructor1Arg)); } +TEST(ASTMatchersTest, has_parmVarDecl) { + + auto Code = R"cpp( +void f(int ii) +{ + +} +)cpp"; + + EXPECT_TRUE(matches( + Code, + traverse(TK_AsIs, + functionDecl(hasName("f"), + has(typeLoc(has(parmVarDecl(hasName("ii"))))))), + langCxx20OrLater())); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + functionDecl(hasName("f"), has(parmVarDecl(hasName("ii"))))), + langCxx20OrLater())); + + EXPECT_TRUE( + matches(Code, + traverse(TK_AsIs, parmVarDecl(hasName("ii"), + hasParent(typeLoc(hasParent( + functionDecl(hasName("f"))))))), + langCxx20OrLater())); + EXPECT_TRUE( + matches(Code, + traverse(TK_IgnoreUnlessSpelledInSource, + parmVarDecl(hasName("ii"), + hasParent(functionDecl(hasName("f"))))), + langCxx20OrLater())); +} + TEST(ASTMatchersTest, NamesMember_CXXDependentScopeMemberExpr) { // Member functions: diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -3551,6 +3551,14 @@ forFunction(functionDecl(hasName("func13"))))))), langCxx20OrLater())); + EXPECT_TRUE( + matches(Code, + traverse(TK_IgnoreUnlessSpelledInSource, + parmVarDecl(hasName("d"), + hasParent(lambdaExpr(forFunction( + functionDecl(hasName("func13"))))))), + langCxx20OrLater())); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, compoundStmt(hasParent(lambdaExpr(forFunction(