diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3024,7 +3024,7 @@ std::vector TraversalScope; class ParentMap; - std::map> Parents; + std::unique_ptr Parents; std::unique_ptr VTContext; diff --git a/clang/include/clang/AST/ExprTraversal.h b/clang/include/clang/AST/ExprTraversal.h --- a/clang/include/clang/AST/ExprTraversal.h +++ b/clang/include/clang/AST/ExprTraversal.h @@ -33,6 +33,8 @@ static Expr *DescendIgnoreParenBaseCasts(Expr *E); static Expr *DescendIgnoreParenNoopCasts(const ASTContext &Ctx, Expr *E); static Expr *DescendIgnoreUnlessSpelledInSource(Expr *E); + + static bool AscendSkipUnlessSpelledInSource(const Expr *E, const Expr *Child); }; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -31,6 +31,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprTraversal.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Mangle.h" #include "clang/AST/MangleNumberingContext.h" @@ -1059,16 +1060,42 @@ } } - DynTypedNodeList getParents(const ast_type_traits::DynTypedNode &Node) { - if (Node.getNodeKind().hasPointerIdentity()) - return getDynNodeFromMap(Node.getMemoizationData(), PointerParents); + DynTypedNodeList getParents(ast_type_traits::TraversalKind TK, const ast_type_traits::DynTypedNode &Node) { + if (Node.getNodeKind().hasPointerIdentity()) { + auto ParentList = getDynNodeFromMap(Node.getMemoizationData(), PointerParents); + if (ParentList.size() == 1 && TK == ast_type_traits::TK_IgnoreUnlessSpelledInSource) { + const Expr* E = ParentList[0].get(); + const Expr* Child = Node.get(); + if (E && Child) + return AscendIgnoreUnlessSpelledInSource(E, Child); + } + return ParentList; + } return getDynNodeFromMap(Node, OtherParents); } + + ast_type_traits::DynTypedNode AscendIgnoreUnlessSpelledInSource(const Expr* E, const Expr* Child) + { + while (ExprTraversal::AscendSkipUnlessSpelledInSource(E, Child)) { + auto It = PointerParents.find(E); + if (It == PointerParents.end()) + break; + auto *S = It->second.dyn_cast(); + if (!S) + return getSingleDynTypedNodeFromParentMap(It->second); + auto *P = dyn_cast(S); + if (!P) + return ast_type_traits::DynTypedNode::create(*S); + Child = E; + E = P; + } + return ast_type_traits::DynTypedNode::create(*E); + } }; void ASTContext::setTraversalScope(const std::vector &TopLevelDecls) { TraversalScope = TopLevelDecls; - Parents.clear(); + Parents.reset(); } void ASTContext::AddDeallocation(void (*Callback)(void *), void *Data) const { @@ -10536,8 +10563,8 @@ class ASTContext::ParentMap::ASTVisitor : public RecursiveASTVisitor { public: - ASTVisitor(ParentMap &Map, ASTContext &Context) - : Map(Map), Context(Context) {} + ASTVisitor(ParentMap &Map) + : Map(Map) {} private: friend class RecursiveASTVisitor; @@ -10607,11 +10634,8 @@ } bool TraverseStmt(Stmt *StmtNode) { - Stmt *FilteredNode = StmtNode; - if (auto *ExprNode = dyn_cast_or_null(FilteredNode)) - FilteredNode = Context.traverseIgnored(ExprNode); - return TraverseNode(FilteredNode, FilteredNode, - [&] { return VisitorBase::TraverseStmt(FilteredNode); }, + return TraverseNode(StmtNode, StmtNode, + [&] { return VisitorBase::TraverseStmt(StmtNode); }, &Map.PointerParents); } @@ -10630,22 +10654,20 @@ } ParentMap ⤅ - ASTContext &Context; llvm::SmallVector ParentStack; }; ASTContext::ParentMap::ParentMap(ASTContext &Ctx) { - ASTVisitor(*this, Ctx).TraverseAST(Ctx); + ASTVisitor(*this).TraverseAST(Ctx); } ASTContext::DynTypedNodeList ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { - std::unique_ptr &P = Parents[Traversal]; - if (!P) + if (!Parents) // We build the parent map for the traversal scope (usually whole TU), as // hasAncestor can escape any subtree. - P = std::make_unique(*this); - return P->getParents(Node); + Parents = std::make_unique(*this); + return Parents->getParents(getTraversalKind(), Node); } bool diff --git a/clang/lib/AST/ExprTraversal.cpp b/clang/lib/AST/ExprTraversal.cpp --- a/clang/lib/AST/ExprTraversal.cpp +++ b/clang/lib/AST/ExprTraversal.cpp @@ -253,3 +253,41 @@ return E; } + +bool ExprTraversal::AscendSkipUnlessSpelledInSource(const Expr *E, const Expr* Child) { + if (isa(E)) + return true; + + if (isa(E)) + return true; + + if (isa(E)) + return true; + + if (isa(E)) + return true; + + if (isa(E)) + return true; + + if (isa(E)) + return true; + + auto SR = Child->getSourceRange(); + + if (auto *C = dyn_cast(E)) { + if (C->getSourceRange() == SR || !isa(C)) + return true; + } + + if (auto *C = dyn_cast(E)) { + if (C->getSourceRange() == SR) + return true; + } + + if (auto *C = dyn_cast(E)) { + if (C->getSourceRange() == SR) + return true; + } + return false; +}