1 | //===- Scope.h - Scope interface --------------------------------*- 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 | // This file defines the Scope interface. |
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 | #include <optional> |
24 | |
25 | namespace llvm { |
26 | |
27 | class raw_ostream; |
28 | |
29 | } // namespace llvm |
30 | |
31 | namespace clang { |
32 | |
33 | class Decl; |
34 | class DeclContext; |
35 | class UsingDirectiveDecl; |
36 | class VarDecl; |
37 | |
38 | /// Scope - A scope is a transient data structure that is used while parsing the |
39 | /// program. It assists with resolving identifiers to the appropriate |
40 | /// declaration. |
41 | class Scope { |
42 | public: |
43 | /// ScopeFlags - These are bitfields that are or'd together when creating a |
44 | /// scope, which defines the sorts of things the scope contains. |
45 | enum ScopeFlags { |
46 | // A bitfield value representing no scopes. |
47 | NoScope = 0, |
48 | |
49 | /// This indicates that the scope corresponds to a function, which |
50 | /// means that labels are set here. |
51 | FnScope = 0x01, |
52 | |
53 | /// This is a while, do, switch, for, etc that can have break |
54 | /// statements embedded into it. |
55 | BreakScope = 0x02, |
56 | |
57 | /// This is a while, do, for, which can have continue statements |
58 | /// embedded into it. |
59 | ContinueScope = 0x04, |
60 | |
61 | /// This is a scope that can contain a declaration. Some scopes |
62 | /// just contain loop constructs but don't contain decls. |
63 | DeclScope = 0x08, |
64 | |
65 | /// The controlling scope in a if/switch/while/for statement. |
66 | ControlScope = 0x10, |
67 | |
68 | /// The scope of a struct/union/class definition. |
69 | ClassScope = 0x20, |
70 | |
71 | /// This is a scope that corresponds to a block/closure object. |
72 | /// Blocks serve as top-level scopes for some objects like labels, they |
73 | /// also prevent things like break and continue. BlockScopes always have |
74 | /// the FnScope and DeclScope flags set as well. |
75 | BlockScope = 0x40, |
76 | |
77 | /// This is a scope that corresponds to the |
78 | /// template parameters of a C++ template. Template parameter |
79 | /// scope starts at the 'template' keyword and ends when the |
80 | /// template declaration ends. |
81 | TemplateParamScope = 0x80, |
82 | |
83 | /// This is a scope that corresponds to the |
84 | /// parameters within a function prototype. |
85 | FunctionPrototypeScope = 0x100, |
86 | |
87 | /// This is a scope that corresponds to the parameters within |
88 | /// a function prototype for a function declaration (as opposed to any |
89 | /// other kind of function declarator). Always has FunctionPrototypeScope |
90 | /// set as well. |
91 | FunctionDeclarationScope = 0x200, |
92 | |
93 | /// This is a scope that corresponds to the Objective-C |
94 | /// \@catch statement. |
95 | AtCatchScope = 0x400, |
96 | |
97 | /// This scope corresponds to an Objective-C method body. |
98 | /// It always has FnScope and DeclScope set as well. |
99 | ObjCMethodScope = 0x800, |
100 | |
101 | /// This is a scope that corresponds to a switch statement. |
102 | SwitchScope = 0x1000, |
103 | |
104 | /// This is the scope of a C++ try statement. |
105 | TryScope = 0x2000, |
106 | |
107 | /// This is the scope for a function-level C++ try or catch scope. |
108 | FnTryCatchScope = 0x4000, |
109 | |
110 | /// This is the scope of OpenMP executable directive. |
111 | OpenMPDirectiveScope = 0x8000, |
112 | |
113 | /// This is the scope of some OpenMP loop directive. |
114 | OpenMPLoopDirectiveScope = 0x10000, |
115 | |
116 | /// This is the scope of some OpenMP simd directive. |
117 | /// For example, it is used for 'omp simd', 'omp for simd'. |
118 | /// This flag is propagated to children scopes. |
119 | OpenMPSimdDirectiveScope = 0x20000, |
120 | |
121 | /// This scope corresponds to an enum. |
122 | EnumScope = 0x40000, |
123 | |
124 | /// This scope corresponds to an SEH try. |
125 | SEHTryScope = 0x80000, |
126 | |
127 | /// This scope corresponds to an SEH except. |
128 | SEHExceptScope = 0x100000, |
129 | |
130 | /// We are currently in the filter expression of an SEH except block. |
131 | SEHFilterScope = 0x200000, |
132 | |
133 | /// This is a compound statement scope. |
134 | CompoundStmtScope = 0x400000, |
135 | |
136 | /// We are between inheritance colon and the real class/struct definition |
137 | /// scope. |
138 | ClassInheritanceScope = 0x800000, |
139 | |
140 | /// This is the scope of a C++ catch statement. |
141 | CatchScope = 0x1000000, |
142 | |
143 | /// This is a scope in which a condition variable is currently being |
144 | /// parsed. If such a scope is a ContinueScope, it's invalid to jump to the |
145 | /// continue block from here. |
146 | ConditionVarScope = 0x2000000, |
147 | |
148 | /// This is a scope of some OpenMP directive with |
149 | /// order clause which specifies concurrent |
150 | OpenMPOrderClauseScope = 0x4000000, |
151 | /// This is the scope for a lambda, after the lambda introducer. |
152 | /// Lambdas need two FunctionPrototypeScope scopes (because there is a |
153 | /// template scope in between), the outer scope does not increase the |
154 | /// depth of recursion. |
155 | LambdaScope = 0x8000000, |
156 | /// This is the scope of an OpenACC Compute Construct, which restricts |
157 | /// jumping into/out of it. |
158 | OpenACCComputeConstructScope = 0x10000000, |
159 | |
160 | /// This is a scope of type alias declaration. |
161 | TypeAliasScope = 0x20000000, |
162 | }; |
163 | |
164 | private: |
165 | /// The parent scope for this scope. This is null for the translation-unit |
166 | /// scope. |
167 | Scope *AnyParent; |
168 | |
169 | /// Flags - This contains a set of ScopeFlags, which indicates how the scope |
170 | /// interrelates with other control flow statements. |
171 | unsigned Flags; |
172 | |
173 | /// Depth - This is the depth of this scope. The translation-unit scope has |
174 | /// depth 0. |
175 | unsigned short Depth; |
176 | |
177 | /// Declarations with static linkage are mangled with the number of |
178 | /// scopes seen as a component. |
179 | unsigned short MSLastManglingNumber; |
180 | |
181 | unsigned short MSCurManglingNumber; |
182 | |
183 | /// PrototypeDepth - This is the number of function prototype scopes |
184 | /// enclosing this scope, including this scope. |
185 | unsigned short PrototypeDepth; |
186 | |
187 | /// PrototypeIndex - This is the number of parameters currently |
188 | /// declared in this scope. |
189 | unsigned short PrototypeIndex; |
190 | |
191 | /// FnParent - If this scope has a parent scope that is a function body, this |
192 | /// pointer is non-null and points to it. This is used for label processing. |
193 | Scope *FnParent; |
194 | Scope *MSLastManglingParent; |
195 | |
196 | /// BreakParent/ContinueParent - This is a direct link to the innermost |
197 | /// BreakScope/ContinueScope which contains the contents of this scope |
198 | /// for control flow purposes (and might be this scope itself), or null |
199 | /// if there is no such scope. |
200 | Scope *BreakParent, *ContinueParent; |
201 | |
202 | /// BlockParent - This is a direct link to the immediately containing |
203 | /// BlockScope if this scope is not one, or null if there is none. |
204 | Scope *BlockParent; |
205 | |
206 | /// TemplateParamParent - This is a direct link to the |
207 | /// immediately containing template parameter scope. In the |
208 | /// case of nested templates, template parameter scopes can have |
209 | /// other template parameter scopes as parents. |
210 | Scope *TemplateParamParent; |
211 | |
212 | /// DeclScopeParent - This is a direct link to the immediately containing |
213 | /// DeclScope, i.e. scope which can contain declarations. |
214 | Scope *DeclParent; |
215 | |
216 | /// DeclsInScope - This keeps track of all declarations in this scope. When |
217 | /// the declaration is added to the scope, it is set as the current |
218 | /// declaration for the identifier in the IdentifierTable. When the scope is |
219 | /// popped, these declarations are removed from the IdentifierTable's notion |
220 | /// of current declaration. It is up to the current Action implementation to |
221 | /// implement these semantics. |
222 | using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>; |
223 | DeclSetTy DeclsInScope; |
224 | |
225 | /// The DeclContext with which this scope is associated. For |
226 | /// example, the entity of a class scope is the class itself, the |
227 | /// entity of a function scope is a function, etc. |
228 | DeclContext *Entity; |
229 | |
230 | using UsingDirectivesTy = SmallVector<UsingDirectiveDecl *, 2>; |
231 | UsingDirectivesTy UsingDirectives; |
232 | |
233 | /// Used to determine if errors occurred in this scope. |
234 | DiagnosticErrorTrap ErrorTrap; |
235 | |
236 | /// A single NRVO candidate variable in this scope. |
237 | /// There are three possible values: |
238 | /// 1) pointer to VarDecl that denotes NRVO candidate itself. |
239 | /// 2) nullptr value means that NRVO is not allowed in this scope |
240 | /// (e.g. return a function parameter). |
241 | /// 3) std::nullopt value means that there is no NRVO candidate in this scope |
242 | /// (i.e. there are no return statements in this scope). |
243 | std::optional<VarDecl *> NRVO; |
244 | |
245 | /// Represents return slots for NRVO candidates in the current scope. |
246 | /// If a variable is present in this set, it means that a return slot is |
247 | /// available for this variable in the current scope. |
248 | llvm::SmallPtrSet<VarDecl *, 8> ReturnSlots; |
249 | |
250 | void setFlags(Scope *Parent, unsigned F); |
251 | |
252 | public: |
253 | Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag) |
254 | : ErrorTrap(Diag) { |
255 | Init(parent: Parent, flags: ScopeFlags); |
256 | } |
257 | |
258 | /// getFlags - Return the flags for this scope. |
259 | unsigned getFlags() const { return Flags; } |
260 | |
261 | void setFlags(unsigned F) { setFlags(Parent: getParent(), F); } |
262 | |
263 | /// isBlockScope - Return true if this scope correspond to a closure. |
264 | bool isBlockScope() const { return Flags & BlockScope; } |
265 | |
266 | /// getParent - Return the scope that this is nested in. |
267 | const Scope *getParent() const { return AnyParent; } |
268 | Scope *getParent() { return AnyParent; } |
269 | |
270 | /// getFnParent - Return the closest scope that is a function body. |
271 | const Scope *getFnParent() const { return FnParent; } |
272 | Scope *getFnParent() { return FnParent; } |
273 | |
274 | const Scope *getMSLastManglingParent() const { |
275 | return MSLastManglingParent; |
276 | } |
277 | Scope *getMSLastManglingParent() { return MSLastManglingParent; } |
278 | |
279 | /// getContinueParent - Return the closest scope that a continue statement |
280 | /// would be affected by. |
281 | Scope *getContinueParent() { |
282 | return ContinueParent; |
283 | } |
284 | |
285 | const Scope *getContinueParent() const { |
286 | return const_cast<Scope*>(this)->getContinueParent(); |
287 | } |
288 | |
289 | // Set whether we're in the scope of a condition variable, where 'continue' |
290 | // is disallowed despite being a continue scope. |
291 | void setIsConditionVarScope(bool InConditionVarScope) { |
292 | Flags = (Flags & ~ConditionVarScope) | |
293 | (InConditionVarScope ? ConditionVarScope : 0); |
294 | } |
295 | |
296 | bool isConditionVarScope() const { |
297 | return Flags & ConditionVarScope; |
298 | } |
299 | |
300 | /// getBreakParent - Return the closest scope that a break statement |
301 | /// would be affected by. |
302 | Scope *getBreakParent() { |
303 | return BreakParent; |
304 | } |
305 | const Scope *getBreakParent() const { |
306 | return const_cast<Scope*>(this)->getBreakParent(); |
307 | } |
308 | |
309 | Scope *getBlockParent() { return BlockParent; } |
310 | const Scope *getBlockParent() const { return BlockParent; } |
311 | |
312 | Scope *getTemplateParamParent() { return TemplateParamParent; } |
313 | const Scope *getTemplateParamParent() const { return TemplateParamParent; } |
314 | |
315 | Scope *getDeclParent() { return DeclParent; } |
316 | const Scope *getDeclParent() const { return DeclParent; } |
317 | |
318 | /// Returns the depth of this scope. The translation-unit has scope depth 0. |
319 | unsigned getDepth() const { return Depth; } |
320 | |
321 | /// Returns the number of function prototype scopes in this scope |
322 | /// chain. |
323 | unsigned getFunctionPrototypeDepth() const { |
324 | return PrototypeDepth; |
325 | } |
326 | |
327 | /// Return the number of parameters declared in this function |
328 | /// prototype, increasing it by one for the next call. |
329 | unsigned getNextFunctionPrototypeIndex() { |
330 | assert(isFunctionPrototypeScope()); |
331 | return PrototypeIndex++; |
332 | } |
333 | |
334 | using decl_range = llvm::iterator_range<DeclSetTy::iterator>; |
335 | |
336 | decl_range decls() const { |
337 | return decl_range(DeclsInScope.begin(), DeclsInScope.end()); |
338 | } |
339 | |
340 | bool decl_empty() const { return DeclsInScope.empty(); } |
341 | |
342 | void AddDecl(Decl *D) { |
343 | if (auto *VD = dyn_cast<VarDecl>(Val: D)) |
344 | if (!isa<ParmVarDecl>(Val: VD)) |
345 | ReturnSlots.insert(Ptr: VD); |
346 | |
347 | DeclsInScope.insert(Ptr: D); |
348 | } |
349 | |
350 | void RemoveDecl(Decl *D) { DeclsInScope.erase(Ptr: D); } |
351 | |
352 | void incrementMSManglingNumber() { |
353 | if (Scope *MSLMP = getMSLastManglingParent()) { |
354 | MSLMP->MSLastManglingNumber += 1; |
355 | MSCurManglingNumber += 1; |
356 | } |
357 | } |
358 | |
359 | void decrementMSManglingNumber() { |
360 | if (Scope *MSLMP = getMSLastManglingParent()) { |
361 | MSLMP->MSLastManglingNumber -= 1; |
362 | MSCurManglingNumber -= 1; |
363 | } |
364 | } |
365 | |
366 | unsigned getMSLastManglingNumber() const { |
367 | if (const Scope *MSLMP = getMSLastManglingParent()) |
368 | return MSLMP->MSLastManglingNumber; |
369 | return 1; |
370 | } |
371 | |
372 | unsigned getMSCurManglingNumber() const { |
373 | return MSCurManglingNumber; |
374 | } |
375 | |
376 | /// isDeclScope - Return true if this is the scope that the specified decl is |
377 | /// declared in. |
378 | bool isDeclScope(const Decl *D) const { return DeclsInScope.contains(Ptr: D); } |
379 | |
380 | /// Get the entity corresponding to this scope. |
381 | DeclContext *getEntity() const { |
382 | return isTemplateParamScope() ? nullptr : Entity; |
383 | } |
384 | |
385 | /// Get the DeclContext in which to continue unqualified lookup after a |
386 | /// lookup in this scope. |
387 | DeclContext *getLookupEntity() const { return Entity; } |
388 | |
389 | void setEntity(DeclContext *E) { |
390 | assert(!isTemplateParamScope() && |
391 | "entity associated with template param scope" ); |
392 | Entity = E; |
393 | } |
394 | void setLookupEntity(DeclContext *E) { Entity = E; } |
395 | |
396 | /// Determine whether any unrecoverable errors have occurred within this |
397 | /// scope. Note that this may return false even if the scope contains invalid |
398 | /// declarations or statements, if the errors for those invalid constructs |
399 | /// were suppressed because some prior invalid construct was referenced. |
400 | bool hasUnrecoverableErrorOccurred() const { |
401 | return ErrorTrap.hasUnrecoverableErrorOccurred(); |
402 | } |
403 | |
404 | /// isFunctionScope() - Return true if this scope is a function scope. |
405 | bool isFunctionScope() const { return getFlags() & Scope::FnScope; } |
406 | |
407 | /// isClassScope - Return true if this scope is a class/struct/union scope. |
408 | bool isClassScope() const { return getFlags() & Scope::ClassScope; } |
409 | |
410 | /// Determines whether this scope is between inheritance colon and the real |
411 | /// class/struct definition. |
412 | bool isClassInheritanceScope() const { |
413 | return getFlags() & Scope::ClassInheritanceScope; |
414 | } |
415 | |
416 | /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline |
417 | /// method scope or is inside one. |
418 | bool isInCXXInlineMethodScope() const { |
419 | if (const Scope *FnS = getFnParent()) { |
420 | assert(FnS->getParent() && "TUScope not created?" ); |
421 | return FnS->getParent()->isClassScope(); |
422 | } |
423 | return false; |
424 | } |
425 | |
426 | /// isInObjcMethodScope - Return true if this scope is, or is contained in, an |
427 | /// Objective-C method body. Note that this method is not constant time. |
428 | bool isInObjcMethodScope() const { |
429 | for (const Scope *S = this; S; S = S->getParent()) { |
430 | // If this scope is an objc method scope, then we succeed. |
431 | if (S->getFlags() & ObjCMethodScope) |
432 | return true; |
433 | } |
434 | return false; |
435 | } |
436 | |
437 | /// isInObjcMethodOuterScope - Return true if this scope is an |
438 | /// Objective-C method outer most body. |
439 | bool isInObjcMethodOuterScope() const { |
440 | if (const Scope *S = this) { |
441 | // If this scope is an objc method scope, then we succeed. |
442 | if (S->getFlags() & ObjCMethodScope) |
443 | return true; |
444 | } |
445 | return false; |
446 | } |
447 | |
448 | /// isTemplateParamScope - Return true if this scope is a C++ |
449 | /// template parameter scope. |
450 | bool isTemplateParamScope() const { |
451 | return getFlags() & Scope::TemplateParamScope; |
452 | } |
453 | |
454 | /// isFunctionPrototypeScope - Return true if this scope is a |
455 | /// function prototype scope. |
456 | bool isFunctionPrototypeScope() const { |
457 | return getFlags() & Scope::FunctionPrototypeScope; |
458 | } |
459 | |
460 | /// isFunctionDeclarationScope - Return true if this scope is a |
461 | /// function prototype scope. |
462 | bool isFunctionDeclarationScope() const { |
463 | return getFlags() & Scope::FunctionDeclarationScope; |
464 | } |
465 | |
466 | /// isAtCatchScope - Return true if this scope is \@catch. |
467 | bool isAtCatchScope() const { |
468 | return getFlags() & Scope::AtCatchScope; |
469 | } |
470 | |
471 | /// isCatchScope - Return true if this scope is a C++ catch statement. |
472 | bool isCatchScope() const { return getFlags() & Scope::CatchScope; } |
473 | |
474 | /// isSwitchScope - Return true if this scope is a switch scope. |
475 | bool isSwitchScope() const { |
476 | for (const Scope *S = this; S; S = S->getParent()) { |
477 | if (S->getFlags() & Scope::SwitchScope) |
478 | return true; |
479 | else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope | |
480 | Scope::BlockScope | Scope::TemplateParamScope | |
481 | Scope::FunctionPrototypeScope | |
482 | Scope::AtCatchScope | Scope::ObjCMethodScope)) |
483 | return false; |
484 | } |
485 | return false; |
486 | } |
487 | |
488 | /// Return true if this scope is a loop. |
489 | bool isLoopScope() const { |
490 | // 'switch' is the only loop that is not a 'break' scope as well, so we can |
491 | // just check BreakScope and not SwitchScope. |
492 | return (getFlags() & Scope::BreakScope) && |
493 | !(getFlags() & Scope::SwitchScope); |
494 | } |
495 | |
496 | /// Determines whether this scope is the OpenMP directive scope |
497 | bool isOpenMPDirectiveScope() const { |
498 | return (getFlags() & Scope::OpenMPDirectiveScope); |
499 | } |
500 | |
501 | /// Determine whether this scope is some OpenMP loop directive scope |
502 | /// (for example, 'omp for', 'omp simd'). |
503 | bool isOpenMPLoopDirectiveScope() const { |
504 | if (getFlags() & Scope::OpenMPLoopDirectiveScope) { |
505 | assert(isOpenMPDirectiveScope() && |
506 | "OpenMP loop directive scope is not a directive scope" ); |
507 | return true; |
508 | } |
509 | return false; |
510 | } |
511 | |
512 | /// Determine whether this scope is (or is nested into) some OpenMP |
513 | /// loop simd directive scope (for example, 'omp simd', 'omp for simd'). |
514 | bool isOpenMPSimdDirectiveScope() const { |
515 | return getFlags() & Scope::OpenMPSimdDirectiveScope; |
516 | } |
517 | |
518 | /// Determine whether this scope is a loop having OpenMP loop |
519 | /// directive attached. |
520 | bool isOpenMPLoopScope() const { |
521 | const Scope *P = getParent(); |
522 | return P && P->isOpenMPLoopDirectiveScope(); |
523 | } |
524 | |
525 | /// Determine whether this scope is some OpenMP directive with |
526 | /// order clause which specifies concurrent scope. |
527 | bool isOpenMPOrderClauseScope() const { |
528 | return getFlags() & Scope::OpenMPOrderClauseScope; |
529 | } |
530 | |
531 | /// Determine whether this scope is the statement associated with an OpenACC |
532 | /// Compute construct directive. |
533 | bool isOpenACCComputeConstructScope() const { |
534 | return getFlags() & Scope::OpenACCComputeConstructScope; |
535 | } |
536 | |
537 | /// Determine if this scope (or its parents) are a compute construct. If the |
538 | /// argument is provided, the search will stop at any of the specified scopes. |
539 | /// Otherwise, it will stop only at the normal 'no longer search' scopes. |
540 | bool isInOpenACCComputeConstructScope(ScopeFlags Flags = NoScope) const { |
541 | for (const Scope *S = this; S; S = S->getParent()) { |
542 | if (S->isOpenACCComputeConstructScope()) |
543 | return true; |
544 | |
545 | if (S->getFlags() & Flags) |
546 | return false; |
547 | |
548 | else if (S->getFlags() & |
549 | (Scope::FnScope | Scope::ClassScope | Scope::BlockScope | |
550 | Scope::TemplateParamScope | Scope::FunctionPrototypeScope | |
551 | Scope::AtCatchScope | Scope::ObjCMethodScope)) |
552 | return false; |
553 | } |
554 | return false; |
555 | } |
556 | |
557 | /// Determine whether this scope is a while/do/for statement, which can have |
558 | /// continue statements embedded into it. |
559 | bool isContinueScope() const { |
560 | return getFlags() & ScopeFlags::ContinueScope; |
561 | } |
562 | |
563 | /// Determine whether this scope is a C++ 'try' block. |
564 | bool isTryScope() const { return getFlags() & Scope::TryScope; } |
565 | |
566 | /// Determine whether this scope is a function-level C++ try or catch scope. |
567 | bool isFnTryCatchScope() const { |
568 | return getFlags() & ScopeFlags::FnTryCatchScope; |
569 | } |
570 | |
571 | /// Determine whether this scope is a SEH '__try' block. |
572 | bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; } |
573 | |
574 | /// Determine whether this scope is a SEH '__except' block. |
575 | bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; } |
576 | |
577 | /// Determine whether this scope is a compound statement scope. |
578 | bool isCompoundStmtScope() const { |
579 | return getFlags() & Scope::CompoundStmtScope; |
580 | } |
581 | |
582 | /// Determine whether this scope is a controlling scope in a |
583 | /// if/switch/while/for statement. |
584 | bool isControlScope() const { return getFlags() & Scope::ControlScope; } |
585 | |
586 | /// Determine whether this scope is a type alias scope. |
587 | bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; } |
588 | |
589 | /// Returns if rhs has a higher scope depth than this. |
590 | /// |
591 | /// The caller is responsible for calling this only if one of the two scopes |
592 | /// is an ancestor of the other. |
593 | bool Contains(const Scope& rhs) const { return Depth < rhs.Depth; } |
594 | |
595 | /// containedInPrototypeScope - Return true if this or a parent scope |
596 | /// is a FunctionPrototypeScope. |
597 | bool containedInPrototypeScope() const; |
598 | |
599 | void PushUsingDirective(UsingDirectiveDecl *UDir) { |
600 | UsingDirectives.push_back(Elt: UDir); |
601 | } |
602 | |
603 | using using_directives_range = |
604 | llvm::iterator_range<UsingDirectivesTy::iterator>; |
605 | |
606 | using_directives_range using_directives() { |
607 | return using_directives_range(UsingDirectives.begin(), |
608 | UsingDirectives.end()); |
609 | } |
610 | |
611 | void updateNRVOCandidate(VarDecl *VD); |
612 | |
613 | void applyNRVO(); |
614 | |
615 | /// Init - This is used by the parser to implement scope caching. |
616 | void Init(Scope *parent, unsigned flags); |
617 | |
618 | /// Sets up the specified scope flags and adjusts the scope state |
619 | /// variables accordingly. |
620 | void AddFlags(unsigned Flags); |
621 | |
622 | void dumpImpl(raw_ostream &OS) const; |
623 | void dump() const; |
624 | }; |
625 | |
626 | } // namespace clang |
627 | |
628 | #endif // LLVM_CLANG_SEMA_SCOPE_H |
629 | |