diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -5490,6 +5490,9 @@ /// \endcode AST_MATCHER_P(CXXMethodDecl, ofClass, internal::Matcher, InnerMatcher) { + + ASTChildrenNotSpelledInSourceScope RAII(Finder, false); + const CXXRecordDecl *Parent = Node.getParent(); return (Parent != nullptr && InnerMatcher.matches(*Parent, Finder, Builder)); @@ -7037,6 +7040,9 @@ ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(&Node); if (!ES.getExpr()) return false; + + ASTChildrenNotSpelledInSourceScope RAII(Finder, false); + return InnerMatcher.matches(*ES.getExpr(), Finder, Builder); } diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -742,6 +742,24 @@ const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) = 0; +private: + friend struct ASTChildrenNotSpelledInSourceScope; + virtual bool isMatchingChildrenNotSpelledInSource() const = 0; + virtual void setMatchingChildrenNotSpelledInSource(bool Set) = 0; +}; + +struct ASTChildrenNotSpelledInSourceScope { + ASTChildrenNotSpelledInSourceScope(ASTMatchFinder *V, bool B) + : MV(V), MB(V->isMatchingChildrenNotSpelledInSource()) { + V->setMatchingChildrenNotSpelledInSource(B); + } + ~ASTChildrenNotSpelledInSourceScope() { + MV->setMatchingChildrenNotSpelledInSource(MB); + } + +private: + ASTMatchFinder *MV; + bool MB; }; /// Specialization of the conversion functions for QualType. 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 @@ -666,6 +666,13 @@ bool IsMatchingInASTNodeNotSpelledInSource() const override { return TraversingASTNodeNotSpelledInSource; } + bool isMatchingChildrenNotSpelledInSource() const override { + return TraversingASTChildrenNotSpelledInSource; + } + void setMatchingChildrenNotSpelledInSource(bool Set) override { + TraversingASTChildrenNotSpelledInSource = Set; + } + bool IsMatchingInASTNodeNotAsIs() const override { return TraversingASTNodeNotAsIs; } @@ -719,20 +726,6 @@ bool MB; }; - struct ASTChildrenNotSpelledInSource { - ASTChildrenNotSpelledInSource(MatchASTVisitor *V, bool B) - : MV(V), MB(V->TraversingASTChildrenNotSpelledInSource) { - V->TraversingASTChildrenNotSpelledInSource = B; - } - ~ASTChildrenNotSpelledInSource() { - MV->TraversingASTChildrenNotSpelledInSource = MB; - } - - private: - MatchASTVisitor *MV; - bool MB; - }; - class TimeBucketRegion { public: TimeBucketRegion() : Bucket(nullptr) {} @@ -1168,7 +1161,7 @@ } ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal); - ASTChildrenNotSpelledInSource RAII2(this, ScopedChildren); + ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren); match(*DeclNode); return RecursiveASTVisitor::TraverseDecl(DeclNode); 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 @@ -2706,6 +2706,52 @@ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); } + Code = R"cpp( +struct A +{ + ~A(); +private: + int i; +}; + +A::~A() = default; +)cpp"; + { + auto M = cxxDestructorDecl(isDefaulted(), + ofClass(cxxRecordDecl(has(fieldDecl())))); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + Code = R"cpp( +struct S +{ + static constexpr bool getTrue() { return true; } +}; + +struct A +{ + explicit(S::getTrue()) A(); +}; + +A::A() = default; +)cpp"; + { + EXPECT_TRUE(matchesConditionally( + Code, + traverse(TK_AsIs, + cxxConstructorDecl( + isDefaulted(), + hasExplicitSpecifier(expr(ignoringImplicit( + callExpr(has(ignoringImplicit(declRefExpr())))))))), + true, {"-std=c++20"})); + EXPECT_TRUE(matchesConditionally( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + cxxConstructorDecl( + isDefaulted(), + hasExplicitSpecifier(callExpr(has(declRefExpr()))))), + true, {"-std=c++20"})); + } } template