steveire updated this revision to Diff 305777.
steveire added a comment.
Update
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D90984/new/
https://reviews.llvm.org/D90984
Files:
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/include/clang/ASTMatchers/ASTMatchersInternal.h
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
clang/unittests/Tooling/TransformerTest.cpp
Index: clang/unittests/Tooling/TransformerTest.cpp
===================================================================
--- clang/unittests/Tooling/TransformerTest.cpp
+++ clang/unittests/Tooling/TransformerTest.cpp
@@ -1245,6 +1245,32 @@
testRuleFailure(makeRule(traverse(TK_AsIs, MatchedLoop), RewriteRule),
RewriteInput);
}
+ {
+ auto MatchedLoop = forStmt(
+ hasLoopInit(declStmt(
+ hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))
+ .bind("loopVar")))),
+ hasCondition(binaryOperator(hasOperatorName("!="),
+ hasLHS(ignoringImplicit(declRefExpr(to(
+ varDecl(equalsBoundNode("loopVar")))))),
+ hasRHS(expr().bind("upperBoundExpr")))),
+ hasIncrement(unaryOperator(hasOperatorName("++"),
+ hasUnaryOperand(declRefExpr(to(
+ varDecl(equalsBoundNode("loopVar"))))))
+ .bind("incrementOp")));
+
+ auto RewriteRule =
+ changeTo(transformer::enclose(node("loopVar"), node("incrementOp")),
+ cat("auto ", name("loopVar"), " : boost::irange(",
+ node("upperBoundExpr"), ")"));
+
+ testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedLoop),
+ RewriteRule),
+ RewriteInput, RewriteOutput);
+
+ testRuleFailure(makeRule(traverse(TK_AsIs, MatchedLoop), RewriteRule),
+ RewriteInput);
+ }
}
TEST_F(TransformerTest, TemplateInstantiation) {
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -2335,8 +2335,8 @@
StringRef Code = R"cpp(
struct NonTrivial {
NonTrivial() {}
- NonTrivial(NonTrivial&) {}
- NonTrivial& operator=(NonTrivial&) { return *this; }
+ NonTrivial(const NonTrivial &) {}
+ NonTrivial& operator=(const NonTrivial &) { return *this; }
~NonTrivial() {}
};
@@ -2347,7 +2347,7 @@
struct ContainsArray {
NonTrivial arr[2];
- ContainsArray& operator=(ContainsArray &other) = default;
+ ContainsArray& operator=(const ContainsArray &other) = default;
};
void copyIt()
@@ -2368,6 +2368,13 @@
HasCtorInits() : NoSpecialMethods(), m_i(42) {}
};
+struct CtorInitsNonTrivial : NonTrivial
+{
+ int m_i;
+ NonTrivial m_nt;
+ CtorInitsNonTrivial() : NonTrivial(), m_i(42) {}
+};
+
)cpp";
{
auto M = cxxRecordDecl(hasName("NoSpecialMethods"),
@@ -2393,6 +2400,35 @@
M = cxxRecordDecl(hasName("NoSpecialMethods"), has(cxxDestructorDecl()));
EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+
+ M = cxxRecordDecl(hasName("NoSpecialMethods"),
+ hasMethod(cxxConstructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+
+ M = cxxRecordDecl(hasName("NoSpecialMethods"),
+ hasMethod(cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+
+ M = cxxRecordDecl(hasName("NoSpecialMethods"),
+ hasMethod(cxxConstructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+
+ M = cxxRecordDecl(hasName("NoSpecialMethods"),
+ hasMethod(cxxDestructorDecl()));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ // Because the copy-assignment operator is not spelled in the
+ // source (ie, isImplicit()), we don't match it
+ auto M =
+ cxxOperatorCallExpr(hasType(cxxRecordDecl(hasName("NoSpecialMethods"))),
+ callee(cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
}
{
// Compiler generates a forStmt to copy the array
@@ -2414,6 +2450,24 @@
EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDef)));
EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDef)));
+ auto MBody = cxxMethodDecl(MDecl, hasBody(compoundStmt()));
+
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MBody)));
+ EXPECT_FALSE(
+ matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MBody)));
+
+ auto MIsDefn = cxxMethodDecl(MDecl, isDefinition());
+
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MIsDefn)));
+ EXPECT_TRUE(
+ matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsDefn)));
+
+ auto MIsInline = cxxMethodDecl(MDecl, isInline());
+
+ EXPECT_FALSE(matches(Code, traverse(TK_AsIs, MIsInline)));
+ EXPECT_FALSE(
+ matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsInline)));
+
// The parameter of the defaulted method can still be matched.
auto MParm =
cxxMethodDecl(MDecl, hasParameter(0, parmVarDecl(hasName("other"))));
@@ -2435,19 +2489,34 @@
EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
}
+ {
+ auto M = cxxConstructorDecl(hasName("HasCtorInits"),
+ hasAnyConstructorInitializer(cxxCtorInitializer(
+ forField(hasName("m_nt")))));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M =
+ cxxConstructorDecl(hasName("HasCtorInits"),
+ forEachConstructorInitializer(
+ cxxCtorInitializer(forField(hasName("m_nt")))));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
{
auto M = cxxConstructorDecl(
- hasName("HasCtorInits"),
- has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(
- cxxConstructorDecl(hasName("NoSpecialMethods"))))))));
+ hasName("CtorInitsNonTrivial"),
+ has(cxxCtorInitializer(withInitializer(cxxConstructExpr(
+ hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));
EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
}
{
auto M = cxxConstructorDecl(
hasName("HasCtorInits"),
- has(cxxCtorInitializer(withInitializer(cxxConstructExpr(
- hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));
+ has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(
+ cxxConstructorDecl(hasName("NoSpecialMethods"))))))));
EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
}
@@ -2573,13 +2642,37 @@
hasDefaultArg(42);
}
)cpp";
+ auto hasDefaultArgCall = [](auto InnerMatcher) {
+ return callExpr(callee(functionDecl(hasName("hasDefaultArg"))),
+ InnerMatcher);
+ };
{
- auto M = callExpr(has(integerLiteral(equals(42))));
+ auto M = hasDefaultArgCall(has(integerLiteral(equals(42))));
EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
}
{
- auto M = callExpr(has(cxxDefaultArgExpr()));
+ auto M = hasDefaultArgCall(has(cxxDefaultArgExpr()));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M = hasDefaultArgCall(argumentCountIs(2));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M = hasDefaultArgCall(argumentCountIs(1));
+ EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M = hasDefaultArgCall(hasArgument(1, cxxDefaultArgExpr()));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M = hasDefaultArgCall(hasAnyArgument(cxxDefaultArgExpr()));
EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
}
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -619,6 +619,130 @@
return Matcher<T>(Implementation);
}
+/// Interface that allows matchers to traverse the AST.
+/// FIXME: Find a better name.
+///
+/// This provides three entry methods for each base node type in the AST:
+/// - \c matchesChildOf:
+/// Matches a matcher on every child node of the given node. Returns true
+/// if at least one child node could be matched.
+/// - \c matchesDescendantOf:
+/// Matches a matcher on all descendant nodes of the given node. Returns true
+/// if at least one descendant matched.
+/// - \c matchesAncestorOf:
+/// Matches a matcher on all ancestors of the given node. Returns true if
+/// at least one ancestor matched.
+///
+/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal.
+/// In the future, we want to implement this for all nodes for which it makes
+/// sense. In the case of matchesAncestorOf, we'll want to implement it for
+/// all nodes, as all nodes have ancestors.
+class ASTMatchFinder {
+public:
+ /// Defines how bindings are processed on recursive matches.
+ enum BindKind {
+ /// Stop at the first match and only bind the first match.
+ BK_First,
+
+ /// Create results for all combinations of bindings that match.
+ BK_All
+ };
+
+ /// Defines which ancestors are considered for a match.
+ enum AncestorMatchMode {
+ /// All ancestors.
+ AMM_All,
+
+ /// Direct parent only.
+ AMM_ParentOnly
+ };
+
+ virtual ~ASTMatchFinder() = default;
+
+ /// Returns true if the given C++ class is directly or indirectly derived
+ /// from a base type matching \c base.
+ ///
+ /// A class is not considered to be derived from itself.
+ virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder,
+ bool Directly) = 0;
+
+ /// Returns true if the given Objective-C class is directly or indirectly
+ /// derived from a base class matching \c base.
+ ///
+ /// A class is not considered to be derived from itself.
+ virtual bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
+ const Matcher<NamedDecl> &Base,
+ BoundNodesTreeBuilder *Builder,
+ bool Directly) = 0;
+
+ template <typename T>
+ bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder, TraversalKind Traverse,
+ BindKind Bind) {
+ static_assert(std::is_base_of<Decl, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<NestedNameSpecifier, T>::value ||
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<TypeLoc, T>::value ||
+ std::is_base_of<QualType, T>::value,
+ "unsupported type for recursive matching");
+ return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
+ Builder, Traverse, Bind);
+ }
+
+ template <typename T>
+ bool matchesDescendantOf(const T &Node, const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder, BindKind Bind) {
+ static_assert(std::is_base_of<Decl, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<NestedNameSpecifier, T>::value ||
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<TypeLoc, T>::value ||
+ std::is_base_of<QualType, T>::value,
+ "unsupported type for recursive matching");
+ return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
+ Matcher, Builder, Bind);
+ }
+
+ // FIXME: Implement support for BindKind.
+ template <typename T>
+ bool matchesAncestorOf(const T &Node, const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ AncestorMatchMode MatchMode) {
+ static_assert(std::is_base_of<Decl, T>::value ||
+ std::is_base_of<NestedNameSpecifierLoc, T>::value ||
+ std::is_base_of<Stmt, T>::value ||
+ std::is_base_of<TypeLoc, T>::value,
+ "type not allowed for recursive matching");
+ return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
+ Matcher, Builder, MatchMode);
+ }
+
+ virtual ASTContext &getASTContext() const = 0;
+
+ virtual bool IsMatchingInASTNodeNotSpelledInSource() const = 0;
+
+ bool isTraversalIgnoringImplicitNodes() const;
+
+protected:
+ virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ TraversalKind Traverse, BindKind Bind) = 0;
+
+ virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ BindKind Bind) = 0;
+
+ virtual bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ AncestorMatchMode MatchMode) = 0;
+};
+
/// Specialization of the conversion functions for QualType.
///
/// This specialization provides the Matcher<Type>->Matcher<QualType>
@@ -665,6 +789,15 @@
return End;
}
+template <typename T, std::enable_if_t<!std::is_base_of<FunctionDecl, T>::value>
+ * = nullptr>
+inline bool isDefaultedHelper(const T *) {
+ return false;
+}
+inline bool isDefaultedHelper(const FunctionDecl *FD) {
+ return FD->isDefaulted();
+}
+
// Metafunction to determine if type T has a member called getDecl.
template <typename Ty>
class has_getDecl {
@@ -932,6 +1065,8 @@
/// is \c NULL.
bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
+ if (Finder->isTraversalIgnoringImplicitNodes() && Node->isImplicit())
+ return false;
return Node != nullptr && this->InnerMatcher.matches(
DynTypedNode::create(*Node), Finder, Builder);
}
@@ -953,134 +1088,6 @@
template <typename T>
const bool IsBaseType<T>::value;
-/// Interface that allows matchers to traverse the AST.
-/// FIXME: Find a better name.
-///
-/// This provides three entry methods for each base node type in the AST:
-/// - \c matchesChildOf:
-/// Matches a matcher on every child node of the given node. Returns true
-/// if at least one child node could be matched.
-/// - \c matchesDescendantOf:
-/// Matches a matcher on all descendant nodes of the given node. Returns true
-/// if at least one descendant matched.
-/// - \c matchesAncestorOf:
-/// Matches a matcher on all ancestors of the given node. Returns true if
-/// at least one ancestor matched.
-///
-/// FIXME: Currently we only allow Stmt and Decl nodes to start a traversal.
-/// In the future, we want to implement this for all nodes for which it makes
-/// sense. In the case of matchesAncestorOf, we'll want to implement it for
-/// all nodes, as all nodes have ancestors.
-class ASTMatchFinder {
-public:
-
- /// Defines how bindings are processed on recursive matches.
- enum BindKind {
- /// Stop at the first match and only bind the first match.
- BK_First,
-
- /// Create results for all combinations of bindings that match.
- BK_All
- };
-
- /// Defines which ancestors are considered for a match.
- enum AncestorMatchMode {
- /// All ancestors.
- AMM_All,
-
- /// Direct parent only.
- AMM_ParentOnly
- };
-
- virtual ~ASTMatchFinder() = default;
-
- /// Returns true if the given C++ class is directly or indirectly derived
- /// from a base type matching \c base.
- ///
- /// A class is not considered to be derived from itself.
- virtual bool classIsDerivedFrom(const CXXRecordDecl *Declaration,
- const Matcher<NamedDecl> &Base,
- BoundNodesTreeBuilder *Builder,
- bool Directly) = 0;
-
- /// Returns true if the given Objective-C class is directly or indirectly
- /// derived from a base class matching \c base.
- ///
- /// A class is not considered to be derived from itself.
- virtual bool objcClassIsDerivedFrom(const ObjCInterfaceDecl *Declaration,
- const Matcher<NamedDecl> &Base,
- BoundNodesTreeBuilder *Builder,
- bool Directly) = 0;
-
- template <typename T>
- bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder, TraversalKind Traverse,
- BindKind Bind) {
- static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<Stmt, T>::value ||
- std::is_base_of<NestedNameSpecifier, T>::value ||
- std::is_base_of<NestedNameSpecifierLoc, T>::value ||
- std::is_base_of<TypeLoc, T>::value ||
- std::is_base_of<QualType, T>::value,
- "unsupported type for recursive matching");
- return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
- Builder, Traverse, Bind);
- }
-
- template <typename T>
- bool matchesDescendantOf(const T &Node,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- BindKind Bind) {
- static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<Stmt, T>::value ||
- std::is_base_of<NestedNameSpecifier, T>::value ||
- std::is_base_of<NestedNameSpecifierLoc, T>::value ||
- std::is_base_of<TypeLoc, T>::value ||
- std::is_base_of<QualType, T>::value,
- "unsupported type for recursive matching");
- return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
- Matcher, Builder, Bind);
- }
-
- // FIXME: Implement support for BindKind.
- template <typename T>
- bool matchesAncestorOf(const T &Node,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- AncestorMatchMode MatchMode) {
- static_assert(std::is_base_of<Decl, T>::value ||
- std::is_base_of<NestedNameSpecifierLoc, T>::value ||
- std::is_base_of<Stmt, T>::value ||
- std::is_base_of<TypeLoc, T>::value,
- "type not allowed for recursive matching");
- return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
- Matcher, Builder, MatchMode);
- }
-
- virtual ASTContext &getASTContext() const = 0;
-
- virtual bool IsMatchingInASTNodeNotSpelledInSource() const = 0;
-
- bool isTraversalIgnoringImplicitNodes() const;
-
-protected:
- virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- TraversalKind Traverse, BindKind Bind) = 0;
-
- virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- BindKind Bind) = 0;
-
- virtual bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx,
- const DynTypedMatcher &Matcher,
- BoundNodesTreeBuilder *Builder,
- AncestorMatchMode MatchMode) = 0;
-};
-
/// A type-list implementation.
///
/// A "linked list" of types, accessible by using the ::head and ::tail
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3106,9 +3106,16 @@
/// \c A but not \c B.
AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>,
InnerMatcher) {
- return matchesFirstInPointerRange(InnerMatcher, Node.method_begin(),
- Node.method_end(), Finder,
- Builder) != Node.method_end();
+ BoundNodesTreeBuilder Result(*Builder);
+ auto MatchIt = matchesFirstInPointerRange(InnerMatcher, Node.method_begin(),
+ Node.method_end(), Finder, &Result);
+ if (MatchIt == Node.method_end())
+ return false;
+
+ if (Finder->isTraversalIgnoringImplicitNodes() && (*MatchIt)->isImplicit())
+ return false;
+ *Builder = std::move(Result);
+ return true;
}
/// Matches the generated class of lambda expressions.
@@ -4044,7 +4051,15 @@
CallExpr, CXXConstructExpr,
CXXUnresolvedConstructExpr, ObjCMessageExpr),
unsigned, N) {
- return Node.getNumArgs() == N;
+ unsigned NumArgs = Node.getNumArgs();
+ if (!Finder->isTraversalIgnoringImplicitNodes())
+ return NumArgs == N;
+ while (NumArgs) {
+ if (!isa<CXXDefaultArgExpr>(Node.getArg(NumArgs - 1)))
+ break;
+ --NumArgs;
+ }
+ return NumArgs == N;
}
/// Matches the n'th argument of a call expression or a constructor
@@ -4060,9 +4075,12 @@
CallExpr, CXXConstructExpr,
CXXUnresolvedConstructExpr, ObjCMessageExpr),
unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
- return (N < Node.getNumArgs() &&
- InnerMatcher.matches(
- *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
+ if (N >= Node.getNumArgs())
+ return false;
+ const Expr *Arg = Node.getArg(N);
+ if (Finder->isTraversalIgnoringImplicitNodes() && isa<CXXDefaultArgExpr>(Arg))
+ return false;
+ return InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, Builder);
}
/// Matches the n'th item of an initializer list expression.
@@ -4154,9 +4172,11 @@
/// record matches Foo, hasAnyConstructorInitializer matches foo_(1)
AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer,
internal::Matcher<CXXCtorInitializer>, InnerMatcher) {
- return matchesFirstInPointerRange(InnerMatcher, Node.init_begin(),
- Node.init_end(), Finder,
- Builder) != Node.init_end();
+ auto MatchIt = matchesFirstInPointerRange(InnerMatcher, Node.init_begin(),
+ Node.init_end(), Finder, Builder);
+ if (MatchIt == Node.init_end())
+ return false;
+ return (*MatchIt)->isWritten() || !Finder->isTraversalIgnoringImplicitNodes();
}
/// Matches the field declaration of a constructor initializer.
@@ -4281,6 +4301,9 @@
CXXUnresolvedConstructExpr, ObjCMessageExpr),
internal::Matcher<Expr>, InnerMatcher) {
for (const Expr *Arg : Node.arguments()) {
+ if (Finder->isTraversalIgnoringImplicitNodes() &&
+ isa<CXXDefaultArgExpr>(Arg))
+ break;
BoundNodesTreeBuilder Result(*Builder);
if (InnerMatcher.matches(*Arg, Finder, &Result)) {
*Builder = std::move(Result);
@@ -4998,6 +5021,8 @@
CXXForRangeStmt,
FunctionDecl),
internal::Matcher<Stmt>, InnerMatcher) {
+ if (Finder->isTraversalIgnoringImplicitNodes() && isDefaultedHelper(&Node))
+ return false;
const Stmt *const Statement = internal::GetBodyMatcher<NodeType>::get(Node);
return (Statement != nullptr &&
InnerMatcher.matches(*Statement, Finder, Builder));
@@ -6880,6 +6905,8 @@
BoundNodesTreeBuilder Result;
bool Matched = false;
for (const auto *I : Node.inits()) {
+ if (Finder->isTraversalIgnoringImplicitNodes() && !I->isWritten())
+ continue;
BoundNodesTreeBuilder InitBuilder(*Builder);
if (InnerMatcher.matches(*I, Finder, &InitBuilder)) {
Matched = true;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits