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

source code of clang/include/clang/Sema/Scope.h