1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H |
15 | #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H |
16 | |
17 | #include "clang/AST/Decl.h" |
18 | #include "clang/AST/DeclBase.h" |
19 | #include "clang/AST/DeclCXX.h" |
20 | #include "clang/AST/DeclarationName.h" |
21 | #include "llvm/ADT/DenseMap.h" |
22 | #include "llvm/ADT/PointerIntPair.h" |
23 | #include "llvm/ADT/PointerUnion.h" |
24 | #include "llvm/ADT/SmallVector.h" |
25 | #include <algorithm> |
26 | #include <cassert> |
27 | |
28 | namespace clang { |
29 | |
30 | class DependentDiagnostic; |
31 | |
32 | |
33 | |
34 | struct StoredDeclsList { |
35 | |
36 | using DeclsTy = SmallVector<NamedDecl *, 4>; |
37 | |
38 | |
39 | |
40 | using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>; |
41 | |
42 | |
43 | |
44 | |
45 | llvm::PointerUnion<NamedDecl *, DeclsAndHasExternalTy> Data; |
46 | |
47 | public: |
48 | StoredDeclsList() = default; |
49 | |
50 | StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) { |
51 | RHS.Data = (NamedDecl *)nullptr; |
52 | } |
53 | |
54 | ~StoredDeclsList() { |
55 | |
56 | if (DeclsTy *Vector = getAsVector()) |
57 | delete Vector; |
58 | } |
59 | |
60 | StoredDeclsList &operator=(StoredDeclsList &&RHS) { |
61 | if (DeclsTy *Vector = getAsVector()) |
62 | delete Vector; |
63 | Data = RHS.Data; |
64 | RHS.Data = (NamedDecl *)nullptr; |
65 | return *this; |
66 | } |
67 | |
68 | bool isNull() const { return Data.isNull(); } |
69 | |
70 | NamedDecl *getAsDecl() const { |
71 | return Data.dyn_cast<NamedDecl *>(); |
72 | } |
73 | |
74 | DeclsAndHasExternalTy getAsVectorAndHasExternal() const { |
75 | return Data.dyn_cast<DeclsAndHasExternalTy>(); |
76 | } |
77 | |
78 | DeclsTy *getAsVector() const { |
79 | return getAsVectorAndHasExternal().getPointer(); |
80 | } |
81 | |
82 | bool hasExternalDecls() const { |
83 | return getAsVectorAndHasExternal().getInt(); |
84 | } |
85 | |
86 | void setHasExternalDecls() { |
87 | if (DeclsTy *Vec = getAsVector()) |
88 | Data = DeclsAndHasExternalTy(Vec, true); |
89 | else { |
90 | DeclsTy *VT = new DeclsTy(); |
91 | if (NamedDecl *OldD = getAsDecl()) |
92 | VT->push_back(OldD); |
93 | Data = DeclsAndHasExternalTy(VT, true); |
94 | } |
95 | } |
96 | |
97 | void setOnlyValue(NamedDecl *ND) { |
98 | (0) . __assert_fail ("!getAsVector() && \"Not inline\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 98, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!getAsVector() && "Not inline"); |
99 | Data = ND; |
100 | |
101 | |
102 | (0) . __assert_fail ("*(NamedDecl **)&Data == ND && \"PointerUnion mangles the NamedDecl pointer!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 103, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(*(NamedDecl **)&Data == ND && |
103 | (0) . __assert_fail ("*(NamedDecl **)&Data == ND && \"PointerUnion mangles the NamedDecl pointer!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 103, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "PointerUnion mangles the NamedDecl pointer!"); |
104 | } |
105 | |
106 | void remove(NamedDecl *D) { |
107 | (0) . __assert_fail ("!isNull() && \"removing from empty list\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 107, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!isNull() && "removing from empty list"); |
108 | if (NamedDecl *Singleton = getAsDecl()) { |
109 | (0) . __assert_fail ("Singleton == D && \"list is different singleton\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 109, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Singleton == D && "list is different singleton"); |
110 | (void)Singleton; |
111 | Data = (NamedDecl *)nullptr; |
112 | return; |
113 | } |
114 | |
115 | DeclsTy &Vec = *getAsVector(); |
116 | DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D); |
117 | (0) . __assert_fail ("I != Vec.end() && \"list does not contain decl\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 117, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(I != Vec.end() && "list does not contain decl"); |
118 | Vec.erase(I); |
119 | |
120 | (0) . __assert_fail ("std..find(Vec.begin(), Vec.end(), D) == Vec.end() && \"list still contains decl\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 121, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(std::find(Vec.begin(), Vec.end(), D) |
121 | (0) . __assert_fail ("std..find(Vec.begin(), Vec.end(), D) == Vec.end() && \"list still contains decl\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 121, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> == Vec.end() && "list still contains decl"); |
122 | } |
123 | |
124 | |
125 | |
126 | void removeExternalDecls() { |
127 | if (isNull()) { |
128 | |
129 | } else if (NamedDecl *Singleton = getAsDecl()) { |
130 | if (Singleton->isFromASTFile()) |
131 | *this = StoredDeclsList(); |
132 | } else { |
133 | DeclsTy &Vec = *getAsVector(); |
134 | Vec.erase(std::remove_if(Vec.begin(), Vec.end(), |
135 | [](Decl *D) { return D->isFromASTFile(); }), |
136 | Vec.end()); |
137 | |
138 | Data = DeclsAndHasExternalTy(&Vec, false); |
139 | } |
140 | } |
141 | |
142 | |
143 | |
144 | DeclContext::lookup_result getLookupResult() { |
145 | if (isNull()) |
146 | return DeclContext::lookup_result(); |
147 | |
148 | |
149 | if (NamedDecl *ND = getAsDecl()) { |
150 | (0) . __assert_fail ("!isNull() && \"Empty list isn't allowed\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 150, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!isNull() && "Empty list isn't allowed"); |
151 | |
152 | |
153 | return DeclContext::lookup_result(ND); |
154 | } |
155 | |
156 | (0) . __assert_fail ("getAsVector() && \"Must have a vector at this point\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 156, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(getAsVector() && "Must have a vector at this point"); |
157 | DeclsTy &Vector = *getAsVector(); |
158 | |
159 | |
160 | return DeclContext::lookup_result(Vector); |
161 | } |
162 | |
163 | |
164 | |
165 | bool HandleRedeclaration(NamedDecl *D, bool IsKnownNewer) { |
166 | |
167 | if (NamedDecl *OldD = getAsDecl()) { |
168 | if (!D->declarationReplaces(OldD, IsKnownNewer)) |
169 | return false; |
170 | setOnlyValue(D); |
171 | return true; |
172 | } |
173 | |
174 | |
175 | DeclsTy &Vec = *getAsVector(); |
176 | for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); |
177 | OD != ODEnd; ++OD) { |
178 | NamedDecl *OldD = *OD; |
179 | if (D->declarationReplaces(OldD, IsKnownNewer)) { |
180 | *OD = D; |
181 | return true; |
182 | } |
183 | } |
184 | |
185 | return false; |
186 | } |
187 | |
188 | |
189 | |
190 | void AddSubsequentDecl(NamedDecl *D) { |
191 | (0) . __assert_fail ("!isNull() && \"don't AddSubsequentDecl when we have no decls\"", "/home/seafit/code_projects/clang_source/clang/include/clang/AST/DeclContextInternals.h", 191, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!isNull() && "don't AddSubsequentDecl when we have no decls"); |
192 | |
193 | |
194 | |
195 | if (NamedDecl *OldD = getAsDecl()) { |
196 | DeclsTy *VT = new DeclsTy(); |
197 | VT->push_back(OldD); |
198 | Data = DeclsAndHasExternalTy(VT, false); |
199 | } |
200 | |
201 | DeclsTy &Vec = *getAsVector(); |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | if (D->hasTagIdentifierNamespace()) |
212 | Vec.push_back(D); |
213 | |
214 | |
215 | |
216 | |
217 | |
218 | else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { |
219 | DeclsTy::iterator I = Vec.begin(); |
220 | if (D->getIdentifierNamespace() != Decl::IDNS_Using) { |
221 | while (I != Vec.end() && |
222 | (*I)->getIdentifierNamespace() == Decl::IDNS_Using) |
223 | ++I; |
224 | } |
225 | Vec.insert(I, D); |
226 | |
227 | |
228 | |
229 | |
230 | } else if (!Vec.empty() && Vec.back()->hasTagIdentifierNamespace()) { |
231 | NamedDecl *TagD = Vec.back(); |
232 | Vec.back() = D; |
233 | Vec.push_back(TagD); |
234 | } else |
235 | Vec.push_back(D); |
236 | } |
237 | }; |
238 | |
239 | class StoredDeclsMap |
240 | : public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> { |
241 | public: |
242 | static void DestroyAll(StoredDeclsMap *Map, bool Dependent); |
243 | |
244 | private: |
245 | friend class ASTContext; |
246 | friend class DeclContext; |
247 | |
248 | llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; |
249 | }; |
250 | |
251 | class DependentStoredDeclsMap : public StoredDeclsMap { |
252 | public: |
253 | DependentStoredDeclsMap() = default; |
254 | |
255 | private: |
256 | friend class DeclContext; |
257 | friend class DependentDiagnostic; |
258 | |
259 | DependentDiagnostic *FirstDiagnostic = nullptr; |
260 | }; |
261 | |
262 | } |
263 | |
264 | #endif |
265 | |