diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -234,6 +234,9 @@ has been changed to no longer match on template instantiations or on implicit nodes which are not spelled in the source. +- The behavior of the forEach() matcher was changed to not internally ignore + implicit and parenthesis nodes. + clang-format ------------ 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 @@ -679,8 +679,7 @@ template bool matchesChildOf(const T &Node, const DynTypedMatcher &Matcher, - BoundNodesTreeBuilder *Builder, TraversalKind Traverse, - BindKind Bind) { + BoundNodesTreeBuilder *Builder, BindKind Bind) { static_assert(std::is_base_of::value || std::is_base_of::value || std::is_base_of::value || @@ -689,7 +688,7 @@ std::is_base_of::value, "unsupported type for recursive matching"); return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher, - Builder, Traverse, Bind); + Builder, Bind); } template @@ -730,7 +729,7 @@ virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, - TraversalKind Traverse, BindKind Bind) = 0; + BindKind Bind) = 0; virtual bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx, const DynTypedMatcher &Matcher, @@ -1367,7 +1366,6 @@ bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { return Finder->matchesChildOf(Node, this->InnerMatcher, Builder, - TraversalKind::TK_AsIs, ASTMatchFinder::BK_First); } }; @@ -1392,7 +1390,6 @@ BoundNodesTreeBuilder *Builder) const override { return Finder->matchesChildOf( Node, this->InnerMatcher, Builder, - TraversalKind::TK_IgnoreImplicitCastsAndParentheses, ASTMatchFinder::BK_All); } }; 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 @@ -95,12 +95,11 @@ // matching the descendants. MatchChildASTVisitor(const DynTypedMatcher *Matcher, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, int MaxDepth, - TraversalKind Traversal, bool IgnoreImplicitChildren, + bool IgnoreImplicitChildren, ASTMatchFinder::BindKind Bind) : Matcher(Matcher), Finder(Finder), Builder(Builder), CurrentDepth(0), - MaxDepth(MaxDepth), Traversal(Traversal), - IgnoreImplicitChildren(IgnoreImplicitChildren), Bind(Bind), - Matches(false) {} + MaxDepth(MaxDepth), IgnoreImplicitChildren(IgnoreImplicitChildren), + Bind(Bind), Matches(false) {} // Returns true if a match is found in the subtree rooted at the // given AST node. This is done via a set of mutually recursive @@ -168,10 +167,6 @@ Finder->getASTContext().getParentMapContext().traverseIgnored( ExprNode); } - if (Traversal == TraversalKind::TK_IgnoreImplicitCastsAndParentheses) { - if (Expr *ExprNode = dyn_cast_or_null(StmtNode)) - StmtToTraverse = ExprNode->IgnoreParenImpCasts(); - } return StmtToTraverse; } @@ -371,7 +366,6 @@ BoundNodesTreeBuilder ResultBindings; int CurrentDepth; const int MaxDepth; - const TraversalKind Traversal; const bool IgnoreImplicitChildren; const ASTMatchFinder::BindKind Bind; bool Matches; @@ -473,11 +467,10 @@ bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, int MaxDepth, - TraversalKind Traversal, BindKind Bind) { + BindKind Bind) { // For AST-nodes that don't have an identity, we can't memoize. if (!Node.getMemoizationData() || !Builder->isComparable()) - return matchesRecursively(Node, Matcher, Builder, MaxDepth, Traversal, - Bind); + return matchesRecursively(Node, Matcher, Builder, MaxDepth, Bind); MatchKey Key; Key.MatcherID = Matcher.getID(); @@ -495,8 +488,8 @@ MemoizedMatchResult Result; Result.Nodes = *Builder; - Result.ResultOfMatch = matchesRecursively(Node, Matcher, &Result.Nodes, - MaxDepth, Traversal, Bind); + Result.ResultOfMatch = + matchesRecursively(Node, Matcher, &Result.Nodes, MaxDepth, Bind); MemoizedMatchResult &CachedResult = ResultCache[Key]; CachedResult = std::move(Result); @@ -509,7 +502,7 @@ bool matchesRecursively(const DynTypedNode &Node, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, int MaxDepth, - TraversalKind Traversal, BindKind Bind) { + BindKind Bind) { bool ScopedTraversal = TraversingASTNodeNotSpelledInSource || TraversingASTChildrenNotSpelledInSource; @@ -523,7 +516,7 @@ ASTNodeNotSpelledInSourceScope RAII(this, ScopedTraversal); - MatchChildASTVisitor Visitor(&Matcher, this, Builder, MaxDepth, Traversal, + MatchChildASTVisitor Visitor(&Matcher, this, Builder, MaxDepth, IgnoreImplicitChildren, Bind); return Visitor.findMatch(Node); } @@ -541,12 +534,10 @@ // Implements ASTMatchFinder::matchesChildOf. bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx, const DynTypedMatcher &Matcher, - BoundNodesTreeBuilder *Builder, TraversalKind Traversal, - BindKind Bind) override { + BoundNodesTreeBuilder *Builder, BindKind Bind) override { if (ResultCache.size() > MaxMemoizationEntries) ResultCache.clear(); - return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Traversal, - Bind); + return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Bind); } // Implements ASTMatchFinder::matchesDescendantOf. bool matchesDescendantOf(const DynTypedNode &Node, ASTContext &Ctx, @@ -556,7 +547,7 @@ if (ResultCache.size() > MaxMemoizationEntries) ResultCache.clear(); return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, INT_MAX, - TraversalKind::TK_AsIs, Bind); + Bind); } // Implements ASTMatchFinder::matchesAncestorOf. bool matchesAncestorOf(const DynTypedNode &Node, ASTContext &Ctx, diff --git a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp @@ -70,7 +70,6 @@ internal::Matcher, AMatcher) { return Finder->matchesChildOf( Node, AMatcher, Builder, - TraversalKind::TK_IgnoreImplicitCastsAndParentheses, ASTMatchFinder::BK_First); } 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 @@ -3370,6 +3370,38 @@ std::make_unique>("f", 4))); } +TEST(ForEach, DoesNotIgnoreImplicit) { + StringRef Code = R"cpp( +void foo() +{ + int i = 0; + int b = 4; + i < b; +} +)cpp"; + EXPECT_TRUE(matchAndVerifyResultFalse( + Code, binaryOperator(forEach(declRefExpr().bind("dre"))), + std::make_unique>("dre", 0))); + + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, + binaryOperator(forEach( + implicitCastExpr(hasSourceExpression(declRefExpr().bind("dre"))))), + std::make_unique>("dre", 2))); + + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, + binaryOperator( + forEach(expr(ignoringImplicit(declRefExpr().bind("dre"))))), + std::make_unique>("dre", 2))); + + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + binaryOperator(forEach(declRefExpr().bind("dre")))), + std::make_unique>("dre", 2))); +} + TEST(ForEachDescendant, BindsOneNode) { EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };", recordDecl(hasName("C"),