diff options
Diffstat (limited to 'clang/lib/ASTMatchers/ASTMatchFinder.cpp')
| -rw-r--r-- | clang/lib/ASTMatchers/ASTMatchFinder.cpp | 104 |
1 files changed, 80 insertions, 24 deletions
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index c51fd630e64b..0d1f713db8d3 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -59,10 +59,12 @@ struct MatchKey { DynTypedMatcher::MatcherIDType MatcherID; ast_type_traits::DynTypedNode Node; BoundNodesTreeBuilder BoundNodes; + ast_type_traits::TraversalKind Traversal = ast_type_traits::TK_AsIs; bool operator<(const MatchKey &Other) const { - return std::tie(MatcherID, Node, BoundNodes) < - std::tie(Other.MatcherID, Other.Node, Other.BoundNodes); + return std::tie(MatcherID, Node, BoundNodes, Traversal) < + std::tie(Other.MatcherID, Other.Node, Other.BoundNodes, + Other.Traversal); } }; @@ -136,18 +138,32 @@ public: ScopedIncrement ScopedDepth(&CurrentDepth); return (DeclNode == nullptr) || traverse(*DeclNode); } - bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) { - // If we need to keep track of the depth, we can't perform data recursion. - if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX)) - Queue = nullptr; - ScopedIncrement ScopedDepth(&CurrentDepth); + Stmt *getStmtToTraverse(Stmt *StmtNode) { Stmt *StmtToTraverse = StmtNode; + if (auto *ExprNode = dyn_cast_or_null<Expr>(StmtNode)) { + auto *LambdaNode = dyn_cast_or_null<LambdaExpr>(StmtNode); + if (LambdaNode && Finder->getASTContext().getTraversalKind() == + ast_type_traits::TK_IgnoreUnlessSpelledInSource) + StmtToTraverse = LambdaNode; + else + StmtToTraverse = Finder->getASTContext().traverseIgnored(ExprNode); + } if (Traversal == ast_type_traits::TraversalKind::TK_IgnoreImplicitCastsAndParentheses) { if (Expr *ExprNode = dyn_cast_or_null<Expr>(StmtNode)) StmtToTraverse = ExprNode->IgnoreParenImpCasts(); } + return StmtToTraverse; + } + + bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr) { + // If we need to keep track of the depth, we can't perform data recursion. + if (CurrentDepth == 0 || (CurrentDepth <= MaxDepth && MaxDepth < INT_MAX)) + Queue = nullptr; + + ScopedIncrement ScopedDepth(&CurrentDepth); + Stmt *StmtToTraverse = getStmtToTraverse(StmtNode); if (!StmtToTraverse) return true; if (!match(*StmtToTraverse)) @@ -199,6 +215,41 @@ public: ScopedIncrement ScopedDepth(&CurrentDepth); return traverse(*CtorInit); } + bool TraverseLambdaExpr(LambdaExpr *Node) { + if (Finder->getASTContext().getTraversalKind() != + ast_type_traits::TK_IgnoreUnlessSpelledInSource) + return VisitorBase::TraverseLambdaExpr(Node); + if (!Node) + return true; + ScopedIncrement ScopedDepth(&CurrentDepth); + + for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) { + const auto *C = Node->capture_begin() + I; + if (!C->isExplicit()) + continue; + if (Node->isInitCapture(C) && !match(*C->getCapturedVar())) + return false; + if (!match(*Node->capture_init_begin()[I])) + return false; + } + + if (const auto *TPL = Node->getTemplateParameterList()) { + for (const auto *TP : *TPL) { + if (!match(*TP)) + return false; + } + } + + for (const auto *P : Node->getCallOperator()->parameters()) { + if (!match(*P)) + return false; + } + + if (!match(*Node->getBody())) + return false; + + return true; + } bool shouldVisitTemplateInstantiations() const { return true; } bool shouldVisitImplicitCode() const { return true; } @@ -390,6 +441,7 @@ public: // Matches children or descendants of 'Node' with 'BaseMatcher'. bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node, + ASTContext &Ctx, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, int MaxDepth, ast_type_traits::TraversalKind Traversal, @@ -404,6 +456,7 @@ public: Key.Node = Node; // Note that we key on the bindings *before* the match. Key.BoundNodes = *Builder; + Key.Traversal = Ctx.getTraversalKind(); MemoizationMap::iterator I = ResultCache.find(Key); if (I != ResultCache.end()) { @@ -446,36 +499,36 @@ public: // Implements ASTMatchFinder::matchesChildOf. bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, - const DynTypedMatcher &Matcher, + ASTContext &Ctx, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, ast_type_traits::TraversalKind Traversal, BindKind Bind) override { if (ResultCache.size() > MaxMemoizationEntries) ResultCache.clear(); - return memoizedMatchesRecursively(Node, Matcher, Builder, 1, Traversal, + return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, 1, Traversal, Bind); } // Implements ASTMatchFinder::matchesDescendantOf. bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node, - const DynTypedMatcher &Matcher, + ASTContext &Ctx, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, BindKind Bind) override { if (ResultCache.size() > MaxMemoizationEntries) ResultCache.clear(); - return memoizedMatchesRecursively(Node, Matcher, Builder, INT_MAX, + return memoizedMatchesRecursively(Node, Ctx, Matcher, Builder, INT_MAX, ast_type_traits::TraversalKind::TK_AsIs, Bind); } // Implements ASTMatchFinder::matchesAncestorOf. bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node, - const DynTypedMatcher &Matcher, + ASTContext &Ctx, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) override { // Reset the cache outside of the recursive call to make sure we // don't invalidate any iterators. if (ResultCache.size() > MaxMemoizationEntries) ResultCache.clear(); - return memoizedMatchesAncestorOfRecursively(Node, Matcher, Builder, + return memoizedMatchesAncestorOfRecursively(Node, Ctx, Matcher, Builder, MatchMode); } @@ -576,7 +629,7 @@ private: if (EnableCheckProfiling) Timer.setBucket(&TimeByBucket[MP.second->getID()]); BoundNodesTreeBuilder Builder; - if (MP.first.matchesNoKindCheck(DynNode, this, &Builder)) { + if (MP.first.matches(DynNode, this, &Builder)) { MatchVisitor Visitor(ActiveASTContext, MP.second); Builder.visitMatches(&Visitor); } @@ -640,16 +693,19 @@ private: // allow simple memoization on the ancestors. Thus, we only memoize as long // as there is a single parent. bool memoizedMatchesAncestorOfRecursively( - const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, - BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) { + const ast_type_traits::DynTypedNode &Node, ASTContext &Ctx, + const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, + AncestorMatchMode MatchMode) { // For AST-nodes that don't have an identity, we can't memoize. if (!Builder->isComparable()) - return matchesAncestorOfRecursively(Node, Matcher, Builder, MatchMode); + return matchesAncestorOfRecursively(Node, Ctx, Matcher, Builder, + MatchMode); MatchKey Key; Key.MatcherID = Matcher.getID(); Key.Node = Node; Key.BoundNodes = *Builder; + Key.Traversal = Ctx.getTraversalKind(); // Note that we cannot use insert and reuse the iterator, as recursive // calls to match might invalidate the result cache iterators. @@ -661,8 +717,8 @@ private: MemoizedMatchResult Result; Result.Nodes = *Builder; - Result.ResultOfMatch = - matchesAncestorOfRecursively(Node, Matcher, &Result.Nodes, MatchMode); + Result.ResultOfMatch = matchesAncestorOfRecursively( + Node, Ctx, Matcher, &Result.Nodes, MatchMode); MemoizedMatchResult &CachedResult = ResultCache[Key]; CachedResult = std::move(Result); @@ -672,6 +728,7 @@ private: } bool matchesAncestorOfRecursively(const ast_type_traits::DynTypedNode &Node, + ASTContext &Ctx, const DynTypedMatcher &Matcher, BoundNodesTreeBuilder *Builder, AncestorMatchMode MatchMode) { @@ -705,8 +762,8 @@ private: return true; } if (MatchMode != ASTMatchFinder::AMM_ParentOnly) { - return memoizedMatchesAncestorOfRecursively(Parent, Matcher, Builder, - MatchMode); + return memoizedMatchesAncestorOfRecursively(Parent, Ctx, Matcher, + Builder, MatchMode); // Once we get back from the recursive call, the result will be the // same as the parent's result. } @@ -804,8 +861,6 @@ private: /// kind (and derived kinds) so it is a waste to try every matcher on every /// node. /// We precalculate a list of matchers that pass the toplevel restrict check. - /// This also allows us to skip the restrict check at matching time. See - /// use \c matchesNoKindCheck() above. llvm::DenseMap<ast_type_traits::ASTNodeKind, std::vector<unsigned short>> MatcherFiltersMap; @@ -904,8 +959,9 @@ bool MatchASTVisitor::objcClassIsDerivedFrom( if (Base.matches(*ClassDecl, this, Builder)) return true; + // Not `return false` as a temporary workaround for PR43879. if (Directly) - return false; + break; } return false; |
