DeclContextInternals.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- DeclContextInternals.h - DeclContext Representation ------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines the data structures used in the implementation
  15. // of DeclContext.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
  19. #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
  20. #include "clang/AST/ASTContext.h"
  21. #include "clang/AST/Decl.h"
  22. #include "clang/AST/DeclBase.h"
  23. #include "clang/AST/DeclCXX.h"
  24. #include "clang/AST/DeclarationName.h"
  25. #include "llvm/ADT/DenseMap.h"
  26. #include "llvm/ADT/PointerIntPair.h"
  27. #include "llvm/ADT/PointerUnion.h"
  28. #include <cassert>
  29. namespace clang {
  30. class DependentDiagnostic;
  31. /// An array of decls optimized for the common case of only containing
  32. /// one entry.
  33. class StoredDeclsList {
  34. using Decls = DeclListNode::Decls;
  35. /// A collection of declarations, with a flag to indicate if we have
  36. /// further external declarations.
  37. using DeclsAndHasExternalTy = llvm::PointerIntPair<Decls, 1, bool>;
  38. /// The stored data, which will be either a pointer to a NamedDecl,
  39. /// or a pointer to a list with a flag to indicate if there are further
  40. /// external declarations.
  41. DeclsAndHasExternalTy Data;
  42. template<typename Fn>
  43. void erase_if(Fn ShouldErase) {
  44. Decls List = Data.getPointer();
  45. if (!List)
  46. return;
  47. ASTContext &C = getASTContext();
  48. DeclListNode::Decls NewHead = nullptr;
  49. DeclListNode::Decls *NewLast = nullptr;
  50. DeclListNode::Decls *NewTail = &NewHead;
  51. while (true) {
  52. if (!ShouldErase(*DeclListNode::iterator(List))) {
  53. NewLast = NewTail;
  54. *NewTail = List;
  55. if (auto *Node = List.dyn_cast<DeclListNode*>()) {
  56. NewTail = &Node->Rest;
  57. List = Node->Rest;
  58. } else {
  59. break;
  60. }
  61. } else if (DeclListNode *N = List.dyn_cast<DeclListNode*>()) {
  62. List = N->Rest;
  63. C.DeallocateDeclListNode(N);
  64. } else {
  65. // We're discarding the last declaration in the list. The last node we
  66. // want to keep (if any) will be of the form DeclListNode(D, <rest>);
  67. // replace it with just D.
  68. if (NewLast) {
  69. DeclListNode *Node = NewLast->get<DeclListNode*>();
  70. *NewLast = Node->D;
  71. C.DeallocateDeclListNode(Node);
  72. }
  73. break;
  74. }
  75. }
  76. Data.setPointer(NewHead);
  77. assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!");
  78. }
  79. void erase(NamedDecl *ND) {
  80. erase_if([ND](NamedDecl *D) { return D == ND; });
  81. }
  82. public:
  83. StoredDeclsList() = default;
  84. StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
  85. RHS.Data.setPointer(nullptr);
  86. RHS.Data.setInt(false);
  87. }
  88. void MaybeDeallocList() {
  89. if (isNull())
  90. return;
  91. // If this is a list-form, free the list.
  92. ASTContext &C = getASTContext();
  93. Decls List = Data.getPointer();
  94. while (DeclListNode *ToDealloc = List.dyn_cast<DeclListNode *>()) {
  95. List = ToDealloc->Rest;
  96. C.DeallocateDeclListNode(ToDealloc);
  97. }
  98. }
  99. ~StoredDeclsList() {
  100. MaybeDeallocList();
  101. }
  102. StoredDeclsList &operator=(StoredDeclsList &&RHS) {
  103. MaybeDeallocList();
  104. Data = RHS.Data;
  105. RHS.Data.setPointer(nullptr);
  106. RHS.Data.setInt(false);
  107. return *this;
  108. }
  109. bool isNull() const { return Data.getPointer().isNull(); }
  110. ASTContext &getASTContext() {
  111. assert(!isNull() && "No ASTContext.");
  112. if (NamedDecl *ND = getAsDecl())
  113. return ND->getASTContext();
  114. return getAsList()->D->getASTContext();
  115. }
  116. DeclsAndHasExternalTy getAsListAndHasExternal() const { return Data; }
  117. NamedDecl *getAsDecl() const {
  118. return getAsListAndHasExternal().getPointer().dyn_cast<NamedDecl *>();
  119. }
  120. DeclListNode *getAsList() const {
  121. return getAsListAndHasExternal().getPointer().dyn_cast<DeclListNode*>();
  122. }
  123. bool hasExternalDecls() const {
  124. return getAsListAndHasExternal().getInt();
  125. }
  126. void setHasExternalDecls() {
  127. Data.setInt(true);
  128. }
  129. void remove(NamedDecl *D) {
  130. assert(!isNull() && "removing from empty list");
  131. erase(D);
  132. }
  133. /// Remove any declarations which were imported from an external AST source.
  134. void removeExternalDecls() {
  135. erase_if([](NamedDecl *ND) { return ND->isFromASTFile(); });
  136. // Don't have any pending external decls any more.
  137. Data.setInt(false);
  138. }
  139. void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) {
  140. // Remove all declarations that are either external or are replaced with
  141. // external declarations.
  142. erase_if([Decls](NamedDecl *ND) {
  143. if (ND->isFromASTFile())
  144. return true;
  145. for (NamedDecl *D : Decls)
  146. if (D->declarationReplaces(ND, /*IsKnownNewer=*/false))
  147. return true;
  148. return false;
  149. });
  150. // Don't have any pending external decls any more.
  151. Data.setInt(false);
  152. if (Decls.empty())
  153. return;
  154. // Convert Decls into a list, in order.
  155. ASTContext &C = Decls.front()->getASTContext();
  156. DeclListNode::Decls DeclsAsList = Decls.back();
  157. for (size_t I = Decls.size() - 1; I != 0; --I) {
  158. DeclListNode *Node = C.AllocateDeclListNode(Decls[I - 1]);
  159. Node->Rest = DeclsAsList;
  160. DeclsAsList = Node;
  161. }
  162. DeclListNode::Decls Head = Data.getPointer();
  163. if (Head.isNull()) {
  164. Data.setPointer(DeclsAsList);
  165. return;
  166. }
  167. // Find the end of the existing list.
  168. // FIXME: It would be possible to preserve information from erase_if to
  169. // avoid this rescan looking for the end of the list.
  170. DeclListNode::Decls *Tail = &Head;
  171. while (DeclListNode *Node = Tail->dyn_cast<DeclListNode *>())
  172. Tail = &Node->Rest;
  173. // Append the Decls.
  174. DeclListNode *Node = C.AllocateDeclListNode(Tail->get<NamedDecl *>());
  175. Node->Rest = DeclsAsList;
  176. *Tail = Node;
  177. Data.setPointer(Head);
  178. }
  179. /// Return an array of all the decls that this list represents.
  180. DeclContext::lookup_result getLookupResult() const {
  181. return DeclContext::lookup_result(Data.getPointer());
  182. }
  183. /// If this is a redeclaration of an existing decl, replace the old one with
  184. /// D. Otherwise, append D.
  185. void addOrReplaceDecl(NamedDecl *D) {
  186. const bool IsKnownNewer = true;
  187. if (isNull()) {
  188. Data.setPointer(D);
  189. return;
  190. }
  191. // Most decls only have one entry in their list, special case it.
  192. if (NamedDecl *OldD = getAsDecl()) {
  193. if (D->declarationReplaces(OldD, IsKnownNewer)) {
  194. Data.setPointer(D);
  195. return;
  196. }
  197. // Add D after OldD.
  198. ASTContext &C = D->getASTContext();
  199. DeclListNode *Node = C.AllocateDeclListNode(OldD);
  200. Node->Rest = D;
  201. Data.setPointer(Node);
  202. return;
  203. }
  204. // FIXME: Move the assert before the single decl case when we fix the
  205. // duplication coming from the ASTReader reading builtin types.
  206. assert(!llvm::is_contained(getLookupResult(), D) && "Already exists!");
  207. // Determine if this declaration is actually a redeclaration.
  208. for (DeclListNode *N = getAsList(); /*return in loop*/;
  209. N = N->Rest.dyn_cast<DeclListNode *>()) {
  210. if (D->declarationReplaces(N->D, IsKnownNewer)) {
  211. N->D = D;
  212. return;
  213. }
  214. if (auto *ND = N->Rest.dyn_cast<NamedDecl *>()) {
  215. if (D->declarationReplaces(ND, IsKnownNewer)) {
  216. N->Rest = D;
  217. return;
  218. }
  219. // Add D after ND.
  220. ASTContext &C = D->getASTContext();
  221. DeclListNode *Node = C.AllocateDeclListNode(ND);
  222. N->Rest = Node;
  223. Node->Rest = D;
  224. return;
  225. }
  226. }
  227. }
  228. /// Add a declaration to the list without checking if it replaces anything.
  229. void prependDeclNoReplace(NamedDecl *D) {
  230. if (isNull()) {
  231. Data.setPointer(D);
  232. return;
  233. }
  234. ASTContext &C = D->getASTContext();
  235. DeclListNode *Node = C.AllocateDeclListNode(D);
  236. Node->Rest = Data.getPointer();
  237. Data.setPointer(Node);
  238. }
  239. LLVM_DUMP_METHOD void dump() const {
  240. Decls D = Data.getPointer();
  241. if (!D) {
  242. llvm::errs() << "<null>\n";
  243. return;
  244. }
  245. while (true) {
  246. if (auto *Node = D.dyn_cast<DeclListNode*>()) {
  247. llvm::errs() << '[' << Node->D << "] -> ";
  248. D = Node->Rest;
  249. } else {
  250. llvm::errs() << '[' << D.get<NamedDecl*>() << "]\n";
  251. return;
  252. }
  253. }
  254. }
  255. };
  256. class StoredDeclsMap
  257. : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
  258. friend class ASTContext; // walks the chain deleting these
  259. friend class DeclContext;
  260. llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
  261. public:
  262. static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
  263. };
  264. class DependentStoredDeclsMap : public StoredDeclsMap {
  265. friend class DeclContext; // iterates over diagnostics
  266. friend class DependentDiagnostic;
  267. DependentDiagnostic *FirstDiagnostic = nullptr;
  268. public:
  269. DependentStoredDeclsMap() = default;
  270. };
  271. } // namespace clang
  272. #endif // LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
  273. #ifdef __GNUC__
  274. #pragma GCC diagnostic pop
  275. #endif