/// \endcode
AST_MATCHER_P(CXXMethodDecl, ofClass,
internal::Matcher<CXXRecordDecl>, InnerMatcher) {
+
+ ASTChildrenNotSpelledInSourceScope RAII(Finder, false);
+
const CXXRecordDecl *Parent = Node.getParent();
return (Parent != nullptr &&
InnerMatcher.matches(*Parent, Finder, Builder));
ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(&Node);
if (!ES.getExpr())
return false;
+
+ ASTChildrenNotSpelledInSourceScope RAII(Finder, false);
+
return InnerMatcher.matches(*ES.getExpr(), Finder, Builder);
}
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.
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;
}
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) {}
}
ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
- ASTChildrenNotSpelledInSource RAII2(this, ScopedChildren);
+ ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren);
match(*DeclNode);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
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 <typename MatcherT>