ParentMapContext.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. //===- ParentMapContext.cpp - Map of parents using DynTypedNode -*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Similar to ParentMap.cpp, but generalizes to non-Stmt nodes, which can have
  10. // multiple parents.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/AST/ParentMapContext.h"
  14. #include "clang/AST/RecursiveASTVisitor.h"
  15. #include "clang/AST/Decl.h"
  16. #include "clang/AST/Expr.h"
  17. #include "clang/AST/TemplateBase.h"
  18. using namespace clang;
  19. ParentMapContext::ParentMapContext(ASTContext &Ctx) : ASTCtx(Ctx) {}
  20. ParentMapContext::~ParentMapContext() = default;
  21. void ParentMapContext::clear() { Parents.reset(); }
  22. const Expr *ParentMapContext::traverseIgnored(const Expr *E) const {
  23. return traverseIgnored(const_cast<Expr *>(E));
  24. }
  25. Expr *ParentMapContext::traverseIgnored(Expr *E) const {
  26. if (!E)
  27. return nullptr;
  28. switch (Traversal) {
  29. case TK_AsIs:
  30. return E;
  31. case TK_IgnoreUnlessSpelledInSource:
  32. return E->IgnoreUnlessSpelledInSource();
  33. }
  34. llvm_unreachable("Invalid Traversal type!");
  35. }
  36. DynTypedNode ParentMapContext::traverseIgnored(const DynTypedNode &N) const {
  37. if (const auto *E = N.get<Expr>()) {
  38. return DynTypedNode::create(*traverseIgnored(E));
  39. }
  40. return N;
  41. }
  42. template <typename T, typename... U>
  43. std::tuple<bool, DynTypedNodeList, const T *, const U *...>
  44. matchParents(const DynTypedNodeList &NodeList,
  45. ParentMapContext::ParentMap *ParentMap);
  46. template <typename, typename...> struct MatchParents;
  47. class ParentMapContext::ParentMap {
  48. template <typename, typename...> friend struct ::MatchParents;
  49. /// Contains parents of a node.
  50. using ParentVector = llvm::SmallVector<DynTypedNode, 2>;
  51. /// Maps from a node to its parents. This is used for nodes that have
  52. /// pointer identity only, which are more common and we can save space by
  53. /// only storing a unique pointer to them.
  54. using ParentMapPointers =
  55. llvm::DenseMap<const void *,
  56. llvm::PointerUnion<const Decl *, const Stmt *,
  57. DynTypedNode *, ParentVector *>>;
  58. /// Parent map for nodes without pointer identity. We store a full
  59. /// DynTypedNode for all keys.
  60. using ParentMapOtherNodes =
  61. llvm::DenseMap<DynTypedNode,
  62. llvm::PointerUnion<const Decl *, const Stmt *,
  63. DynTypedNode *, ParentVector *>>;
  64. ParentMapPointers PointerParents;
  65. ParentMapOtherNodes OtherParents;
  66. class ASTVisitor;
  67. static DynTypedNode
  68. getSingleDynTypedNodeFromParentMap(ParentMapPointers::mapped_type U) {
  69. if (const auto *D = U.dyn_cast<const Decl *>())
  70. return DynTypedNode::create(*D);
  71. if (const auto *S = U.dyn_cast<const Stmt *>())
  72. return DynTypedNode::create(*S);
  73. return *U.get<DynTypedNode *>();
  74. }
  75. template <typename NodeTy, typename MapTy>
  76. static DynTypedNodeList getDynNodeFromMap(const NodeTy &Node,
  77. const MapTy &Map) {
  78. auto I = Map.find(Node);
  79. if (I == Map.end()) {
  80. return llvm::ArrayRef<DynTypedNode>();
  81. }
  82. if (const auto *V = I->second.template dyn_cast<ParentVector *>()) {
  83. return llvm::makeArrayRef(*V);
  84. }
  85. return getSingleDynTypedNodeFromParentMap(I->second);
  86. }
  87. public:
  88. ParentMap(ASTContext &Ctx);
  89. ~ParentMap() {
  90. for (const auto &Entry : PointerParents) {
  91. if (Entry.second.is<DynTypedNode *>()) {
  92. delete Entry.second.get<DynTypedNode *>();
  93. } else if (Entry.second.is<ParentVector *>()) {
  94. delete Entry.second.get<ParentVector *>();
  95. }
  96. }
  97. for (const auto &Entry : OtherParents) {
  98. if (Entry.second.is<DynTypedNode *>()) {
  99. delete Entry.second.get<DynTypedNode *>();
  100. } else if (Entry.second.is<ParentVector *>()) {
  101. delete Entry.second.get<ParentVector *>();
  102. }
  103. }
  104. }
  105. DynTypedNodeList getParents(TraversalKind TK, const DynTypedNode &Node) {
  106. if (Node.getNodeKind().hasPointerIdentity()) {
  107. auto ParentList =
  108. getDynNodeFromMap(Node.getMemoizationData(), PointerParents);
  109. if (ParentList.size() > 0 && TK == TK_IgnoreUnlessSpelledInSource) {
  110. const auto *ChildExpr = Node.get<Expr>();
  111. {
  112. // Don't match explicit node types because different stdlib
  113. // implementations implement this in different ways and have
  114. // different intermediate nodes.
  115. // Look up 4 levels for a cxxRewrittenBinaryOperator as that is
  116. // enough for the major stdlib implementations.
  117. auto RewrittenBinOpParentsList = ParentList;
  118. int I = 0;
  119. while (ChildExpr && RewrittenBinOpParentsList.size() == 1 &&
  120. I++ < 4) {
  121. const auto *S = RewrittenBinOpParentsList[0].get<Stmt>();
  122. if (!S)
  123. break;
  124. const auto *RWBO = dyn_cast<CXXRewrittenBinaryOperator>(S);
  125. if (!RWBO) {
  126. RewrittenBinOpParentsList = getDynNodeFromMap(S, PointerParents);
  127. continue;
  128. }
  129. if (RWBO->getLHS()->IgnoreUnlessSpelledInSource() != ChildExpr &&
  130. RWBO->getRHS()->IgnoreUnlessSpelledInSource() != ChildExpr)
  131. break;
  132. return DynTypedNode::create(*RWBO);
  133. }
  134. }
  135. const auto *ParentExpr = ParentList[0].get<Expr>();
  136. if (ParentExpr && ChildExpr)
  137. return AscendIgnoreUnlessSpelledInSource(ParentExpr, ChildExpr);
  138. {
  139. auto AncestorNodes =
  140. matchParents<DeclStmt, CXXForRangeStmt>(ParentList, this);
  141. if (std::get<bool>(AncestorNodes) &&
  142. std::get<const CXXForRangeStmt *>(AncestorNodes)
  143. ->getLoopVarStmt() ==
  144. std::get<const DeclStmt *>(AncestorNodes))
  145. return std::get<DynTypedNodeList>(AncestorNodes);
  146. }
  147. {
  148. auto AncestorNodes = matchParents<VarDecl, DeclStmt, CXXForRangeStmt>(
  149. ParentList, this);
  150. if (std::get<bool>(AncestorNodes) &&
  151. std::get<const CXXForRangeStmt *>(AncestorNodes)
  152. ->getRangeStmt() ==
  153. std::get<const DeclStmt *>(AncestorNodes))
  154. return std::get<DynTypedNodeList>(AncestorNodes);
  155. }
  156. {
  157. auto AncestorNodes =
  158. matchParents<CXXMethodDecl, CXXRecordDecl, LambdaExpr>(ParentList,
  159. this);
  160. if (std::get<bool>(AncestorNodes))
  161. return std::get<DynTypedNodeList>(AncestorNodes);
  162. }
  163. {
  164. auto AncestorNodes =
  165. matchParents<FunctionTemplateDecl, CXXRecordDecl, LambdaExpr>(
  166. ParentList, this);
  167. if (std::get<bool>(AncestorNodes))
  168. return std::get<DynTypedNodeList>(AncestorNodes);
  169. }
  170. }
  171. return ParentList;
  172. }
  173. return getDynNodeFromMap(Node, OtherParents);
  174. }
  175. DynTypedNodeList AscendIgnoreUnlessSpelledInSource(const Expr *E,
  176. const Expr *Child) {
  177. auto ShouldSkip = [](const Expr *E, const Expr *Child) {
  178. if (isa<ImplicitCastExpr>(E))
  179. return true;
  180. if (isa<FullExpr>(E))
  181. return true;
  182. if (isa<MaterializeTemporaryExpr>(E))
  183. return true;
  184. if (isa<CXXBindTemporaryExpr>(E))
  185. return true;
  186. if (isa<ParenExpr>(E))
  187. return true;
  188. if (isa<ExprWithCleanups>(E))
  189. return true;
  190. auto SR = Child->getSourceRange();
  191. if (const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) {
  192. if (C->getSourceRange() == SR)
  193. return true;
  194. }
  195. if (const auto *C = dyn_cast<CXXConstructExpr>(E)) {
  196. if (C->getSourceRange() == SR || C->isElidable())
  197. return true;
  198. }
  199. if (const auto *C = dyn_cast<CXXMemberCallExpr>(E)) {
  200. if (C->getSourceRange() == SR)
  201. return true;
  202. }
  203. if (const auto *C = dyn_cast<MemberExpr>(E)) {
  204. if (C->getSourceRange() == SR)
  205. return true;
  206. }
  207. return false;
  208. };
  209. while (ShouldSkip(E, Child)) {
  210. auto It = PointerParents.find(E);
  211. if (It == PointerParents.end())
  212. break;
  213. const auto *S = It->second.dyn_cast<const Stmt *>();
  214. if (!S) {
  215. if (auto *Vec = It->second.dyn_cast<ParentVector *>())
  216. return llvm::makeArrayRef(*Vec);
  217. return getSingleDynTypedNodeFromParentMap(It->second);
  218. }
  219. const auto *P = dyn_cast<Expr>(S);
  220. if (!P)
  221. return DynTypedNode::create(*S);
  222. Child = E;
  223. E = P;
  224. }
  225. return DynTypedNode::create(*E);
  226. }
  227. };
  228. template <typename Tuple, std::size_t... Is>
  229. auto tuple_pop_front_impl(const Tuple &tuple, std::index_sequence<Is...>) {
  230. return std::make_tuple(std::get<1 + Is>(tuple)...);
  231. }
  232. template <typename Tuple> auto tuple_pop_front(const Tuple &tuple) {
  233. return tuple_pop_front_impl(
  234. tuple, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>());
  235. }
  236. template <typename T, typename... U> struct MatchParents {
  237. static std::tuple<bool, DynTypedNodeList, const T *, const U *...>
  238. match(const DynTypedNodeList &NodeList,
  239. ParentMapContext::ParentMap *ParentMap) {
  240. if (const auto *TypedNode = NodeList[0].get<T>()) {
  241. auto NextParentList =
  242. ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
  243. if (NextParentList.size() == 1) {
  244. auto TailTuple = MatchParents<U...>::match(NextParentList, ParentMap);
  245. if (std::get<bool>(TailTuple)) {
  246. return std::tuple_cat(
  247. std::make_tuple(true, std::get<DynTypedNodeList>(TailTuple),
  248. TypedNode),
  249. tuple_pop_front(tuple_pop_front(TailTuple)));
  250. }
  251. }
  252. }
  253. return std::tuple_cat(std::make_tuple(false, NodeList),
  254. std::tuple<const T *, const U *...>());
  255. }
  256. };
  257. template <typename T> struct MatchParents<T> {
  258. static std::tuple<bool, DynTypedNodeList, const T *>
  259. match(const DynTypedNodeList &NodeList,
  260. ParentMapContext::ParentMap *ParentMap) {
  261. if (const auto *TypedNode = NodeList[0].get<T>()) {
  262. auto NextParentList =
  263. ParentMap->getDynNodeFromMap(TypedNode, ParentMap->PointerParents);
  264. if (NextParentList.size() == 1)
  265. return std::make_tuple(true, NodeList, TypedNode);
  266. }
  267. return std::make_tuple(false, NodeList, nullptr);
  268. }
  269. };
  270. template <typename T, typename... U>
  271. std::tuple<bool, DynTypedNodeList, const T *, const U *...>
  272. matchParents(const DynTypedNodeList &NodeList,
  273. ParentMapContext::ParentMap *ParentMap) {
  274. return MatchParents<T, U...>::match(NodeList, ParentMap);
  275. }
  276. /// Template specializations to abstract away from pointers and TypeLocs.
  277. /// @{
  278. template <typename T> static DynTypedNode createDynTypedNode(const T &Node) {
  279. return DynTypedNode::create(*Node);
  280. }
  281. template <> DynTypedNode createDynTypedNode(const TypeLoc &Node) {
  282. return DynTypedNode::create(Node);
  283. }
  284. template <>
  285. DynTypedNode createDynTypedNode(const NestedNameSpecifierLoc &Node) {
  286. return DynTypedNode::create(Node);
  287. }
  288. /// @}
  289. /// A \c RecursiveASTVisitor that builds a map from nodes to their
  290. /// parents as defined by the \c RecursiveASTVisitor.
  291. ///
  292. /// Note that the relationship described here is purely in terms of AST
  293. /// traversal - there are other relationships (for example declaration context)
  294. /// in the AST that are better modeled by special matchers.
  295. class ParentMapContext::ParentMap::ASTVisitor
  296. : public RecursiveASTVisitor<ASTVisitor> {
  297. public:
  298. ASTVisitor(ParentMap &Map) : Map(Map) {}
  299. private:
  300. friend class RecursiveASTVisitor<ASTVisitor>;
  301. using VisitorBase = RecursiveASTVisitor<ASTVisitor>;
  302. bool shouldVisitTemplateInstantiations() const { return true; }
  303. bool shouldVisitImplicitCode() const { return true; }
  304. /// Record the parent of the node we're visiting.
  305. /// MapNode is the child, the parent is on top of ParentStack.
  306. /// Parents is the parent storage (either PointerParents or OtherParents).
  307. template <typename MapNodeTy, typename MapTy>
  308. void addParent(MapNodeTy MapNode, MapTy *Parents) {
  309. if (ParentStack.empty())
  310. return;
  311. // FIXME: Currently we add the same parent multiple times, but only
  312. // when no memoization data is available for the type.
  313. // For example when we visit all subexpressions of template
  314. // instantiations; this is suboptimal, but benign: the only way to
  315. // visit those is with hasAncestor / hasParent, and those do not create
  316. // new matches.
  317. // The plan is to enable DynTypedNode to be storable in a map or hash
  318. // map. The main problem there is to implement hash functions /
  319. // comparison operators for all types that DynTypedNode supports that
  320. // do not have pointer identity.
  321. auto &NodeOrVector = (*Parents)[MapNode];
  322. if (NodeOrVector.isNull()) {
  323. if (const auto *D = ParentStack.back().get<Decl>())
  324. NodeOrVector = D;
  325. else if (const auto *S = ParentStack.back().get<Stmt>())
  326. NodeOrVector = S;
  327. else
  328. NodeOrVector = new DynTypedNode(ParentStack.back());
  329. } else {
  330. if (!NodeOrVector.template is<ParentVector *>()) {
  331. auto *Vector = new ParentVector(
  332. 1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
  333. delete NodeOrVector.template dyn_cast<DynTypedNode *>();
  334. NodeOrVector = Vector;
  335. }
  336. auto *Vector = NodeOrVector.template get<ParentVector *>();
  337. // Skip duplicates for types that have memoization data.
  338. // We must check that the type has memoization data before calling
  339. // llvm::is_contained() because DynTypedNode::operator== can't compare all
  340. // types.
  341. bool Found = ParentStack.back().getMemoizationData() &&
  342. llvm::is_contained(*Vector, ParentStack.back());
  343. if (!Found)
  344. Vector->push_back(ParentStack.back());
  345. }
  346. }
  347. template <typename T, typename MapNodeTy, typename BaseTraverseFn,
  348. typename MapTy>
  349. bool TraverseNode(T Node, MapNodeTy MapNode, BaseTraverseFn BaseTraverse,
  350. MapTy *Parents) {
  351. if (!Node)
  352. return true;
  353. addParent(MapNode, Parents);
  354. ParentStack.push_back(createDynTypedNode(Node));
  355. bool Result = BaseTraverse();
  356. ParentStack.pop_back();
  357. return Result;
  358. }
  359. bool TraverseDecl(Decl *DeclNode) {
  360. return TraverseNode(
  361. DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); },
  362. &Map.PointerParents);
  363. }
  364. bool TraverseTypeLoc(TypeLoc TypeLocNode) {
  365. return TraverseNode(
  366. TypeLocNode, DynTypedNode::create(TypeLocNode),
  367. [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); },
  368. &Map.OtherParents);
  369. }
  370. bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) {
  371. return TraverseNode(
  372. NNSLocNode, DynTypedNode::create(NNSLocNode),
  373. [&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); },
  374. &Map.OtherParents);
  375. }
  376. bool TraverseAttr(Attr *AttrNode) {
  377. return TraverseNode(
  378. AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); },
  379. &Map.PointerParents);
  380. }
  381. // Using generic TraverseNode for Stmt would prevent data-recursion.
  382. bool dataTraverseStmtPre(Stmt *StmtNode) {
  383. addParent(StmtNode, &Map.PointerParents);
  384. ParentStack.push_back(DynTypedNode::create(*StmtNode));
  385. return true;
  386. }
  387. bool dataTraverseStmtPost(Stmt *StmtNode) {
  388. ParentStack.pop_back();
  389. return true;
  390. }
  391. ParentMap &Map;
  392. llvm::SmallVector<DynTypedNode, 16> ParentStack;
  393. };
  394. ParentMapContext::ParentMap::ParentMap(ASTContext &Ctx) {
  395. ASTVisitor(*this).TraverseAST(Ctx);
  396. }
  397. DynTypedNodeList ParentMapContext::getParents(const DynTypedNode &Node) {
  398. if (!Parents)
  399. // We build the parent map for the traversal scope (usually whole TU), as
  400. // hasAncestor can escape any subtree.
  401. Parents = std::make_unique<ParentMap>(ASTCtx);
  402. return Parents->getParents(getTraversalKind(), Node);
  403. }