20 using namespace clang;
42 llvm_unreachable(
"Invalid Traversal type!");
46 if (
const auto *E = N.
get<
Expr>()) {
52 template <
typename T,
typename...
U>
61 template <
typename,
typename...>
friend struct ::MatchParents;
69 using ParentMapPointers =
70 llvm::DenseMap<
const void *,
71 llvm::PointerUnion<
const Decl *,
const Stmt *,
76 using ParentMapOtherNodes =
78 llvm::PointerUnion<
const Decl *,
const Stmt *,
81 ParentMapPointers PointerParents;
82 ParentMapOtherNodes OtherParents;
86 getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type
U) {
87 if (
const auto *D =
U.dyn_cast<
const Decl *>())
89 if (
const auto *S =
U.dyn_cast<
const Stmt *>())
94 template <
typename NodeTy,
typename MapTy>
97 auto I = Map.find(
Node);
101 if (
const auto *
V = I->second.template dyn_cast<ParentVector *>()) {
102 return llvm::makeArrayRef(*
V);
104 return getSingleDynTypedNodeFromParentMap(I->second);
110 for (
const auto &Entry : PointerParents) {
117 for (
const auto &Entry : OtherParents) {
140 auto RewrittenBinOpParentsList = ParentList;
142 while (ChildExpr && RewrittenBinOpParentsList.size() == 1 &&
144 const auto *S = RewrittenBinOpParentsList[0].get<
Stmt>();
148 const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S);
150 RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents);
153 if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr &&
154 RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr)
160 const auto *ParentExpr = ParentList[0].get<
Expr>();
161 if (ParentExpr && ChildExpr)
162 return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr);
166 matchParents<DeclStmt, CXXForRangeStmt>(ParentList,
this);
167 if (std::get<bool>(AncestorNodes) &&
168 std::get<const CXXForRangeStmt *>(AncestorNodes)
169 ->getLoopVarStmt() ==
170 std::get<const DeclStmt *>(AncestorNodes))
171 return std::get<DynTypedNodeList>(AncestorNodes);
174 auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>(
176 if (std::get<bool>(AncestorNodes) &&
177 std::get<const CXXForRangeStmt *>(AncestorNodes)
179 std::get<const DeclStmt *>(AncestorNodes))
180 return std::get<DynTypedNodeList>(AncestorNodes);
184 matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList,
186 if (std::get<bool>(AncestorNodes))
187 return std::get<DynTypedNodeList>(AncestorNodes);
191 matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>(
193 if (std::get<bool>(AncestorNodes))
194 return std::get<DynTypedNodeList>(AncestorNodes);
199 return getDynNodeFromMap(
Node, OtherParents);
205 auto ShouldSkip = [](
const Expr *E,
const Expr *Child) {
206 if (isa<ImplicitCastExpr>(E))
209 if (isa<FullExpr>(E))
212 if (isa<MaterializeTemporaryExpr>(E))
215 if (isa<CXXBindTemporaryExpr>(E))
218 if (isa<ParenExpr>(E))
221 if (isa<ExprWithCleanups>(E))
224 auto SR = Child->getSourceRange();
226 if (
const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) {
227 if (C->getSourceRange() == SR)
231 if (
const auto *C = dyn_cast<CXXConstructExpr>(E)) {
232 if (C->getSourceRange() == SR || C->isElidable())
236 if (
const auto *C = dyn_cast<CXXMemberCallExpr>(E)) {
237 if (C->getSourceRange() == SR)
241 if (
const auto *C = dyn_cast<MemberExpr>(E)) {
242 if (C->getSourceRange() == SR)
248 while (ShouldSkip(E, Child)) {
249 auto It = PointerParents.find(E);
250 if (It == PointerParents.end())
252 const auto *S = It->second.dyn_cast<
const Stmt *>();
255 return llvm::makeArrayRef(*Vec);
256 return getSingleDynTypedNodeFromParentMap(It->second);
258 const auto *
P = dyn_cast<Expr>(S);
270 return std::make_tuple(std::get<1 + Is>(tuple)...);
275 tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
282 if (
const auto *TypedNode = NodeList[0].get<T>()) {
283 auto NextParentList =
285 if (NextParentList.size() == 1) {
287 if (std::get<bool>(TailTuple)) {
288 return std::tuple_cat(
289 std::make_tuple(
true, std::get<DynTypedNodeList>(TailTuple),
295 return std::tuple_cat(std::make_tuple(
false, NodeList),
296 std::tuple<const T *, const U *...>());
301 static std::tuple<bool, DynTypedNodeList, const T *>
304 if (
const auto *TypedNode = NodeList[0].get<T>()) {
305 auto NextParentList =
307 if (NextParentList.size() == 1)
308 return std::make_tuple(
true, NodeList, TypedNode);
310 return std::make_tuple(
false, NodeList,
nullptr);
314 template <
typename T,
typename...
U>
351 bool shouldVisitTemplateInstantiations()
const {
return true; }
353 bool shouldVisitImplicitCode()
const {
return true; }
358 template <
typename MapNodeTy,
typename MapTy>
359 void addParent(MapNodeTy MapNode,
MapTy *Parents) {
360 if (ParentStack.empty())
373 auto &NodeOrVector = (*Parents)[MapNode];
374 if (NodeOrVector.isNull()) {
375 if (
const auto *D = ParentStack.back().get<
Decl>())
377 else if (
const auto *S = ParentStack.back().get<
Stmt>())
382 if (!NodeOrVector.template is<ParentVector *>()) {
383 auto *Vector =
new ParentVector(
384 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
385 delete NodeOrVector.template dyn_cast<DynTypedNode *>();
386 NodeOrVector = Vector;
389 auto *Vector = NodeOrVector.template get<ParentVector *>();
394 bool Found = ParentStack.back().getMemoizationData() &&
395 std::find(Vector->begin(), Vector->end(),
396 ParentStack.back()) != Vector->end();
398 Vector->push_back(ParentStack.back());
402 template <
typename T,
typename MapNodeTy,
typename BaseTraverseFn,
404 bool TraverseNode(T
Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
408 addParent(MapNode, Parents);
410 bool Result = BaseTraverse();
411 ParentStack.pop_back();
415 bool TraverseDecl(
Decl *DeclNode) {
418 &Map.PointerParents);
420 bool TraverseTypeLoc(
TypeLoc TypeLocNode) {
434 bool dataTraverseStmtPre(
Stmt *StmtNode) {
435 addParent(StmtNode, &Map.PointerParents);
439 bool dataTraverseStmtPost(
Stmt *StmtNode) {
440 ParentStack.pop_back();
456 Parents = std::make_unique<ParentMap>(ASTCtx);
457 return Parents->getParents(getTraversalKind(),
Node);