forked from OSchip/llvm-project
[ASTMatchers] Fix traversal matchers with explicit and defaulted methods
Differential Revision: https://reviews.llvm.org/D94030
This commit is contained in:
parent
3d5b18a3fd
commit
7e4f53f748
|
@ -5490,6 +5490,9 @@ AST_MATCHER(FunctionDecl, isVariadic) {
|
|||
/// \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));
|
||||
|
@ -7037,6 +7040,9 @@ AST_MATCHER_P(FunctionDecl, hasExplicitSpecifier, internal::Matcher<Expr>,
|
|||
ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(&Node);
|
||||
if (!ES.getExpr())
|
||||
return false;
|
||||
|
||||
ASTChildrenNotSpelledInSourceScope RAII(Finder, false);
|
||||
|
||||
return InnerMatcher.matches(*ES.getExpr(), Finder, Builder);
|
||||
}
|
||||
|
||||
|
|
|
@ -742,6 +742,24 @@ protected:
|
|||
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.
|
||||
|
|
|
@ -666,6 +666,13 @@ public:
|
|||
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 @@ private:
|
|||
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 @@ bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) {
|
|||
}
|
||||
|
||||
ASTNodeNotSpelledInSourceScope RAII1(this, ScopedTraversal);
|
||||
ASTChildrenNotSpelledInSource RAII2(this, ScopedChildren);
|
||||
ASTChildrenNotSpelledInSourceScope RAII2(this, ScopedChildren);
|
||||
|
||||
match(*DeclNode);
|
||||
return RecursiveASTVisitor<MatchASTVisitor>::TraverseDecl(DeclNode);
|
||||
|
|
|
@ -2706,6 +2706,52 @@ void callDefaultArg()
|
|||
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>
|
||||
|
|
Loading…
Reference in New Issue