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