19#include "llvm/ADT/SmallPtrSet.h"
43 llvm_unreachable(
"Invalid Traversal type!");
53template <
typename T,
typename...
U>
62 template <
typename,
typename...>
friend struct ::MatchParents;
67 ParentVector() =
default;
74 const void *Identity =
Value.getMemoizationData();
76 return Dedup.contains(Identity);
79 const void *Identity =
Value.getMemoizationData();
80 if (!Identity || Dedup.insert(Identity).second) {
81 Items.push_back(
Value);
94 using ParentMapPointers =
95 llvm::DenseMap<
const void *,
96 llvm::PointerUnion<
const Decl *,
const Stmt *,
101 using ParentMapOtherNodes =
103 llvm::PointerUnion<
const Decl *,
const Stmt *,
106 ParentMapPointers PointerParents;
107 ParentMapOtherNodes OtherParents;
111 getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type
U) {
112 if (
const auto *
D = dyn_cast<const Decl *>(
U))
114 if (
const auto *S = dyn_cast<const Stmt *>(
U))
116 return *cast<DynTypedNode *>(
U);
119 template <
typename NodeTy,
typename MapTy>
122 auto I = Map.find(
Node);
123 if (I == Map.end()) {
126 if (
const auto *
V = dyn_cast<ParentVector *>(I->second)) {
129 return getSingleDynTypedNodeFromParentMap(I->second);
135 for (
const auto &Entry : PointerParents) {
136 if (
auto *DTN = dyn_cast<DynTypedNode *>(Entry.second)) {
138 }
else if (
auto *PV = dyn_cast<ParentVector *>(Entry.second)) {
142 for (
const auto &Entry : OtherParents) {
143 if (
auto *DTN = dyn_cast<DynTypedNode *>(Entry.second)) {
145 }
else if (
auto *PV = dyn_cast<ParentVector *>(Entry.second)) {
165 auto RewrittenBinOpParentsList = ParentList;
167 while (ChildExpr && RewrittenBinOpParentsList.size() == 1 &&
169 const auto *S = RewrittenBinOpParentsList[0].get<
Stmt>();
173 const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S);
175 RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents);
178 if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr &&
179 RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr)
185 const auto *ParentExpr = ParentList[0].get<
Expr>();
186 if (ParentExpr && ChildExpr)
187 return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr);
191 matchParents<DeclStmt, CXXForRangeStmt>(ParentList,
this);
192 if (std::get<bool>(AncestorNodes) &&
193 std::get<const CXXForRangeStmt *>(AncestorNodes)
194 ->getLoopVarStmt() ==
195 std::get<const DeclStmt *>(AncestorNodes))
196 return std::get<DynTypedNodeList>(AncestorNodes);
199 auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>(
201 if (std::get<bool>(AncestorNodes) &&
202 std::get<const CXXForRangeStmt *>(AncestorNodes)
204 std::get<const DeclStmt *>(AncestorNodes))
205 return std::get<DynTypedNodeList>(AncestorNodes);
209 matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList,
211 if (std::get<bool>(AncestorNodes))
212 return std::get<DynTypedNodeList>(AncestorNodes);
216 matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>(
218 if (std::get<bool>(AncestorNodes))
219 return std::get<DynTypedNodeList>(AncestorNodes);
224 return getDynNodeFromMap(
Node, OtherParents);
230 auto ShouldSkip = [](
const Expr *
E,
const Expr *Child) {
231 if (isa<ImplicitCastExpr>(
E))
234 if (isa<FullExpr>(
E))
237 if (isa<MaterializeTemporaryExpr>(
E))
240 if (isa<CXXBindTemporaryExpr>(
E))
243 if (isa<ParenExpr>(
E))
246 if (isa<ExprWithCleanups>(
E))
249 auto SR = Child->getSourceRange();
251 if (
const auto *
C = dyn_cast<CXXFunctionalCastExpr>(
E)) {
252 if (
C->getSourceRange() == SR)
256 if (
const auto *
C = dyn_cast<CXXConstructExpr>(
E)) {
257 if (
C->getSourceRange() == SR ||
C->isElidable())
261 if (
const auto *
C = dyn_cast<CXXMemberCallExpr>(
E)) {
262 if (
C->getSourceRange() == SR)
266 if (
const auto *
C = dyn_cast<MemberExpr>(
E)) {
267 if (
C->getSourceRange() == SR)
273 while (ShouldSkip(
E, Child)) {
274 auto It = PointerParents.find(
E);
275 if (It == PointerParents.end())
277 const auto *S = dyn_cast<const Stmt *>(It->second);
279 if (
auto *Vec = dyn_cast<ParentVector *>(It->second))
281 return getSingleDynTypedNodeFromParentMap(It->second);
283 const auto *
P = dyn_cast<Expr>(S);
297 if (
const auto *TypedNode = NodeList[0].get<T>()) {
298 auto NextParentList =
300 if (NextParentList.size() == 1) {
302 if (std::get<bool>(TailTuple)) {
305 return std::make_tuple(
true, NodeList, TypedNode, TupleTail...);
311 return std::tuple_cat(std::make_tuple(
false, NodeList),
312 std::tuple<const T *, const U *...>());
317 static std::tuple<bool, DynTypedNodeList, const T *>
320 if (
const auto *TypedNode = NodeList[0].get<T>()) {
321 auto NextParentList =
323 if (NextParentList.size() == 1)
324 return std::make_tuple(
true, NodeList, TypedNode);
326 return std::make_tuple(
false, NodeList,
nullptr);
330template <
typename T,
typename...
U>
370 bool shouldVisitTemplateInstantiations()
const {
return true; }
372 bool shouldVisitImplicitCode()
const {
return true; }
377 template <
typename MapNodeTy,
typename MapTy>
378 void addParent(MapNodeTy MapNode,
MapTy *Parents) {
379 if (ParentStack.empty())
392 auto &NodeOrVector = (*Parents)[MapNode];
393 if (NodeOrVector.isNull()) {
394 if (
const auto *
D = ParentStack.back().get<
Decl>())
396 else if (
const auto *S = ParentStack.back().get<
Stmt>())
401 if (!isa<ParentVector *>(NodeOrVector)) {
402 auto *
Vector =
new ParentVector(
403 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
404 delete dyn_cast<DynTypedNode *>(NodeOrVector);
408 auto *
Vector = cast<ParentVector *>(NodeOrVector);
413 bool Found = ParentStack.back().getMemoizationData() &&
414 llvm::is_contained(*
Vector, ParentStack.back());
416 Vector->push_back(ParentStack.back());
420 template <
typename T>
static bool isNull(
T Node) {
return !
Node; }
423 template <
typename T,
typename MapNodeTy,
typename BaseTraverseFn,
425 bool TraverseNode(
T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
429 addParent(MapNode, Parents);
431 bool Result = BaseTraverse();
432 ParentStack.pop_back();
436 bool TraverseDecl(
Decl *DeclNode) {
439 &Map.PointerParents);
441 bool TraverseTypeLoc(
TypeLoc TypeLocNode,
bool TraverseQualifier =
true) {
455 bool TraverseAttr(
Attr *AttrNode) {
458 &Map.PointerParents);
468 bool dataTraverseStmtPre(
Stmt *StmtNode) {
469 addParent(StmtNode, &Map.PointerParents);
473 bool dataTraverseStmtPost(
Stmt *StmtNode) {
474 ParentStack.pop_back();
490 Parents = std::make_unique<ParentMap>(ASTCtx);
static DynTypedNode createDynTypedNode(const T &Node)
Template specializations to abstract away from pointers and TypeLocs.
static std::tuple< bool, DynTypedNodeList, const T *, const U *... > matchParents(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)
llvm::DenseMap< Stmt *, Stmt * > MapTy
static bool contains(const std::set< tok::TokenKind > &Terminators, const Token &Tok)
A RecursiveASTVisitor that builds a map from nodes to their parents as defined by the RecursiveASTVis...
ASTVisitor(ParentMap &Map)
DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node)
DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E, const Expr *Child)
ParentMap(ASTContext &Ctx)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
constexpr bool hasPointerIdentity() const
Check if the given ASTNodeKind identifies a type that offers pointer identity.
Attr - This represents one attribute.
Decl - This represents one declaration (or definition), e.g.
Container for either a single DynTypedNode or for an ArrayRef to DynTypedNode.
A dynamically typed AST node container.
ASTNodeKind getNodeKind() const
const T * get() const
Retrieve the stored node as type T.
static DynTypedNode create(const T &Node)
Creates a DynTypedNode from Node.
const void * getMemoizationData() const
Returns a pointer that identifies the stored AST node.
This represents one expression.
Expr * IgnoreUnlessSpelledInSource()
Skip past any invisible AST nodes which might surround this statement, such as ExprWithCleanups or Im...
A C++ nested-name-specifier augmented with source location information.
const Expr * traverseIgnored(const Expr *E) const
void clear()
Clear parent maps.
TraversalKind getTraversalKind() const
DynTypedNodeList getParents(const NodeT &Node)
Returns the parents of the given node (within the traversal scope).
ParentMapContext(ASTContext &Ctx)
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc)
Recursively visit an Objective-C protocol reference with location information.
bool TraverseAST(ASTContext &AST)
Recursively visits an entire AST, starting from the TranslationUnitDecl.
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)
Recursively visit a C++ nested-name-specifier with location information.
bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier=true)
Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
bool TraverseAttr(Attr *At)
Recursively visit an attribute, by dispatching to Traverse*Attr() based on the argument's dynamic typ...
Stmt - This represents one statement.
Base wrapper for a particular "section" of type source info.
The JSON file list parser is used to communicate input to InstallAPI.
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
TraversalKind
Defines how we descend a level in the AST when we pass through expressions.
@ TK_AsIs
Will traverse all child nodes.
@ TK_IgnoreUnlessSpelledInSource
Ignore AST nodes not written in the source.
@ Result
The result type of a method or function.
const FunctionProtoType * T
static std::tuple< bool, DynTypedNodeList, const T * > match(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)
static std::tuple< bool, DynTypedNodeList, const T *, const U *... > match(const DynTypedNodeList &NodeList, ParentMapContext::ParentMap *ParentMap)