1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_SEMA_SCOPE_H |
14 | #define LLVM_CLANG_SEMA_SCOPE_H |
15 | |
16 | #include "clang/AST/Decl.h" |
17 | #include "clang/Basic/Diagnostic.h" |
18 | #include "llvm/ADT/PointerIntPair.h" |
19 | #include "llvm/ADT/SmallPtrSet.h" |
20 | #include "llvm/ADT/SmallVector.h" |
21 | #include "llvm/ADT/iterator_range.h" |
22 | #include <cassert> |
23 | |
24 | namespace llvm { |
25 | |
26 | class raw_ostream; |
27 | |
28 | } |
29 | |
30 | namespace clang { |
31 | |
32 | class Decl; |
33 | class DeclContext; |
34 | class UsingDirectiveDecl; |
35 | class VarDecl; |
36 | |
37 | |
38 | |
39 | |
40 | class Scope { |
41 | public: |
42 | |
43 | |
44 | enum ScopeFlags { |
45 | |
46 | |
47 | FnScope = 0x01, |
48 | |
49 | |
50 | |
51 | BreakScope = 0x02, |
52 | |
53 | |
54 | |
55 | ContinueScope = 0x04, |
56 | |
57 | |
58 | |
59 | DeclScope = 0x08, |
60 | |
61 | |
62 | ControlScope = 0x10, |
63 | |
64 | |
65 | ClassScope = 0x20, |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | BlockScope = 0x40, |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | TemplateParamScope = 0x80, |
78 | |
79 | |
80 | |
81 | FunctionPrototypeScope = 0x100, |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | FunctionDeclarationScope = 0x200, |
88 | |
89 | |
90 | |
91 | AtCatchScope = 0x400, |
92 | |
93 | |
94 | |
95 | ObjCMethodScope = 0x800, |
96 | |
97 | |
98 | SwitchScope = 0x1000, |
99 | |
100 | |
101 | TryScope = 0x2000, |
102 | |
103 | |
104 | FnTryCatchScope = 0x4000, |
105 | |
106 | |
107 | OpenMPDirectiveScope = 0x8000, |
108 | |
109 | |
110 | OpenMPLoopDirectiveScope = 0x10000, |
111 | |
112 | |
113 | |
114 | |
115 | OpenMPSimdDirectiveScope = 0x20000, |
116 | |
117 | |
118 | EnumScope = 0x40000, |
119 | |
120 | |
121 | SEHTryScope = 0x80000, |
122 | |
123 | |
124 | SEHExceptScope = 0x100000, |
125 | |
126 | |
127 | SEHFilterScope = 0x200000, |
128 | |
129 | |
130 | CompoundStmtScope = 0x400000, |
131 | |
132 | |
133 | ClassInheritanceScope = 0x800000, |
134 | |
135 | |
136 | CatchScope = 0x1000000, |
137 | }; |
138 | |
139 | private: |
140 | |
141 | |
142 | Scope *AnyParent; |
143 | |
144 | |
145 | |
146 | unsigned Flags; |
147 | |
148 | |
149 | |
150 | unsigned short Depth; |
151 | |
152 | |
153 | |
154 | unsigned short MSLastManglingNumber; |
155 | |
156 | unsigned short MSCurManglingNumber; |
157 | |
158 | |
159 | |
160 | unsigned short PrototypeDepth; |
161 | |
162 | |
163 | |
164 | unsigned short PrototypeIndex; |
165 | |
166 | |
167 | |
168 | Scope *FnParent; |
169 | Scope *MSLastManglingParent; |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | Scope *BreakParent, *ContinueParent; |
176 | |
177 | |
178 | |
179 | Scope *BlockParent; |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | Scope *TemplateParamParent; |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>; |
194 | DeclSetTy DeclsInScope; |
195 | |
196 | |
197 | |
198 | |
199 | DeclContext *Entity; |
200 | |
201 | using UsingDirectivesTy = SmallVector<UsingDirectiveDecl *, 2>; |
202 | UsingDirectivesTy UsingDirectives; |
203 | |
204 | |
205 | DiagnosticErrorTrap ErrorTrap; |
206 | |
207 | |
208 | |
209 | llvm::PointerIntPair<VarDecl *, 1, bool> NRVO; |
210 | |
211 | void setFlags(Scope *Parent, unsigned F); |
212 | |
213 | public: |
214 | Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag) |
215 | : ErrorTrap(Diag) { |
216 | Init(Parent, ScopeFlags); |
217 | } |
218 | |
219 | |
220 | unsigned getFlags() const { return Flags; } |
221 | |
222 | void setFlags(unsigned F) { setFlags(getParent(), F); } |
223 | |
224 | |
225 | bool isBlockScope() const { return Flags & BlockScope; } |
226 | |
227 | |
228 | const Scope *getParent() const { return AnyParent; } |
229 | Scope *getParent() { return AnyParent; } |
230 | |
231 | |
232 | const Scope *getFnParent() const { return FnParent; } |
233 | Scope *getFnParent() { return FnParent; } |
234 | |
235 | const Scope *getMSLastManglingParent() const { |
236 | return MSLastManglingParent; |
237 | } |
238 | Scope *getMSLastManglingParent() { return MSLastManglingParent; } |
239 | |
240 | |
241 | |
242 | Scope *getContinueParent() { |
243 | return ContinueParent; |
244 | } |
245 | |
246 | const Scope *getContinueParent() const { |
247 | return const_cast<Scope*>(this)->getContinueParent(); |
248 | } |
249 | |
250 | |
251 | |
252 | Scope *getBreakParent() { |
253 | return BreakParent; |
254 | } |
255 | const Scope *getBreakParent() const { |
256 | return const_cast<Scope*>(this)->getBreakParent(); |
257 | } |
258 | |
259 | Scope *getBlockParent() { return BlockParent; } |
260 | const Scope *getBlockParent() const { return BlockParent; } |
261 | |
262 | Scope *getTemplateParamParent() { return TemplateParamParent; } |
263 | const Scope *getTemplateParamParent() const { return TemplateParamParent; } |
264 | |
265 | |
266 | unsigned getDepth() const { return Depth; } |
267 | |
268 | |
269 | |
270 | unsigned getFunctionPrototypeDepth() const { |
271 | return PrototypeDepth; |
272 | } |
273 | |
274 | |
275 | |
276 | unsigned getNextFunctionPrototypeIndex() { |
277 | assert(isFunctionPrototypeScope()); |
278 | return PrototypeIndex++; |
279 | } |
280 | |
281 | using decl_range = llvm::iterator_range<DeclSetTy::iterator>; |
282 | |
283 | decl_range decls() const { |
284 | return decl_range(DeclsInScope.begin(), DeclsInScope.end()); |
285 | } |
286 | |
287 | bool decl_empty() const { return DeclsInScope.empty(); } |
288 | |
289 | void AddDecl(Decl *D) { |
290 | DeclsInScope.insert(D); |
291 | } |
292 | |
293 | void RemoveDecl(Decl *D) { |
294 | DeclsInScope.erase(D); |
295 | } |
296 | |
297 | void incrementMSManglingNumber() { |
298 | if (Scope *MSLMP = getMSLastManglingParent()) { |
299 | MSLMP->MSLastManglingNumber += 1; |
300 | MSCurManglingNumber += 1; |
301 | } |
302 | } |
303 | |
304 | void decrementMSManglingNumber() { |
305 | if (Scope *MSLMP = getMSLastManglingParent()) { |
306 | MSLMP->MSLastManglingNumber -= 1; |
307 | MSCurManglingNumber -= 1; |
308 | } |
309 | } |
310 | |
311 | unsigned getMSLastManglingNumber() const { |
312 | if (const Scope *MSLMP = getMSLastManglingParent()) |
313 | return MSLMP->MSLastManglingNumber; |
314 | return 1; |
315 | } |
316 | |
317 | unsigned getMSCurManglingNumber() const { |
318 | return MSCurManglingNumber; |
319 | } |
320 | |
321 | |
322 | |
323 | bool isDeclScope(Decl *D) { |
324 | return DeclsInScope.count(D) != 0; |
325 | } |
326 | |
327 | DeclContext *getEntity() const { return Entity; } |
328 | void setEntity(DeclContext *E) { Entity = E; } |
329 | |
330 | bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); } |
331 | |
332 | bool hasUnrecoverableErrorOccurred() const { |
333 | return ErrorTrap.hasUnrecoverableErrorOccurred(); |
334 | } |
335 | |
336 | |
337 | bool isFunctionScope() const { return (getFlags() & Scope::FnScope); } |
338 | |
339 | |
340 | bool isClassScope() const { |
341 | return (getFlags() & Scope::ClassScope); |
342 | } |
343 | |
344 | |
345 | |
346 | bool isInCXXInlineMethodScope() const { |
347 | if (const Scope *FnS = getFnParent()) { |
348 | (0) . __assert_fail ("FnS->getParent() && \"TUScope not created?\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/Scope.h", 348, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(FnS->getParent() && "TUScope not created?"); |
349 | return FnS->getParent()->isClassScope(); |
350 | } |
351 | return false; |
352 | } |
353 | |
354 | |
355 | |
356 | bool isInObjcMethodScope() const { |
357 | for (const Scope *S = this; S; S = S->getParent()) { |
358 | |
359 | if (S->getFlags() & ObjCMethodScope) |
360 | return true; |
361 | } |
362 | return false; |
363 | } |
364 | |
365 | |
366 | |
367 | bool isInObjcMethodOuterScope() const { |
368 | if (const Scope *S = this) { |
369 | |
370 | if (S->getFlags() & ObjCMethodScope) |
371 | return true; |
372 | } |
373 | return false; |
374 | } |
375 | |
376 | |
377 | |
378 | bool isTemplateParamScope() const { |
379 | return getFlags() & Scope::TemplateParamScope; |
380 | } |
381 | |
382 | |
383 | |
384 | bool isFunctionPrototypeScope() const { |
385 | return getFlags() & Scope::FunctionPrototypeScope; |
386 | } |
387 | |
388 | |
389 | bool isAtCatchScope() const { |
390 | return getFlags() & Scope::AtCatchScope; |
391 | } |
392 | |
393 | |
394 | bool isSwitchScope() const { |
395 | for (const Scope *S = this; S; S = S->getParent()) { |
396 | if (S->getFlags() & Scope::SwitchScope) |
397 | return true; |
398 | else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope | |
399 | Scope::BlockScope | Scope::TemplateParamScope | |
400 | Scope::FunctionPrototypeScope | |
401 | Scope::AtCatchScope | Scope::ObjCMethodScope)) |
402 | return false; |
403 | } |
404 | return false; |
405 | } |
406 | |
407 | |
408 | bool isOpenMPDirectiveScope() const { |
409 | return (getFlags() & Scope::OpenMPDirectiveScope); |
410 | } |
411 | |
412 | |
413 | |
414 | bool isOpenMPLoopDirectiveScope() const { |
415 | if (getFlags() & Scope::OpenMPLoopDirectiveScope) { |
416 | (0) . __assert_fail ("isOpenMPDirectiveScope() && \"OpenMP loop directive scope is not a directive scope\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/Scope.h", 417, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(isOpenMPDirectiveScope() && |
417 | (0) . __assert_fail ("isOpenMPDirectiveScope() && \"OpenMP loop directive scope is not a directive scope\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Sema/Scope.h", 417, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "OpenMP loop directive scope is not a directive scope"); |
418 | return true; |
419 | } |
420 | return false; |
421 | } |
422 | |
423 | |
424 | |
425 | bool isOpenMPSimdDirectiveScope() const { |
426 | return getFlags() & Scope::OpenMPSimdDirectiveScope; |
427 | } |
428 | |
429 | |
430 | |
431 | bool isOpenMPLoopScope() const { |
432 | const Scope *P = getParent(); |
433 | return P && P->isOpenMPLoopDirectiveScope(); |
434 | } |
435 | |
436 | |
437 | bool isTryScope() const { return getFlags() & Scope::TryScope; } |
438 | |
439 | |
440 | bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; } |
441 | |
442 | |
443 | bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; } |
444 | |
445 | |
446 | bool isCompoundStmtScope() const { |
447 | return getFlags() & Scope::CompoundStmtScope; |
448 | } |
449 | |
450 | |
451 | |
452 | |
453 | |
454 | bool Contains(const Scope& rhs) const { return Depth < rhs.Depth; } |
455 | |
456 | |
457 | |
458 | bool containedInPrototypeScope() const; |
459 | |
460 | void PushUsingDirective(UsingDirectiveDecl *UDir) { |
461 | UsingDirectives.push_back(UDir); |
462 | } |
463 | |
464 | using using_directives_range = |
465 | llvm::iterator_range<UsingDirectivesTy::iterator>; |
466 | |
467 | using_directives_range using_directives() { |
468 | return using_directives_range(UsingDirectives.begin(), |
469 | UsingDirectives.end()); |
470 | } |
471 | |
472 | void addNRVOCandidate(VarDecl *VD) { |
473 | if (NRVO.getInt()) |
474 | return; |
475 | if (NRVO.getPointer() == nullptr) { |
476 | NRVO.setPointer(VD); |
477 | return; |
478 | } |
479 | if (NRVO.getPointer() != VD) |
480 | setNoNRVO(); |
481 | } |
482 | |
483 | void setNoNRVO() { |
484 | NRVO.setInt(true); |
485 | NRVO.setPointer(nullptr); |
486 | } |
487 | |
488 | void mergeNRVOIntoParent(); |
489 | |
490 | |
491 | void Init(Scope *parent, unsigned flags); |
492 | |
493 | |
494 | |
495 | void AddFlags(unsigned Flags); |
496 | |
497 | void dumpImpl(raw_ostream &OS) const; |
498 | void dump() const; |
499 | }; |
500 | |
501 | } |
502 | |
503 | #endif |
504 | |