xref: /openbsd/gnu/llvm/clang/include/clang/Sema/Scope.h (revision 12c85518)
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:
Scope(Scope * Parent,unsigned ScopeFlags,DiagnosticsEngine & Diag)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.
getFlags()241   unsigned getFlags() const { return Flags; }
242 
setFlags(unsigned F)243   void setFlags(unsigned F) { setFlags(getParent(), F); }
244 
245   /// isBlockScope - Return true if this scope correspond to a closure.
isBlockScope()246   bool isBlockScope() const { return Flags & BlockScope; }
247 
248   /// getParent - Return the scope that this is nested in.
getParent()249   const Scope *getParent() const { return AnyParent; }
getParent()250   Scope *getParent() { return AnyParent; }
251 
252   /// getFnParent - Return the closest scope that is a function body.
getFnParent()253   const Scope *getFnParent() const { return FnParent; }
getFnParent()254   Scope *getFnParent() { return FnParent; }
255 
getMSLastManglingParent()256   const Scope *getMSLastManglingParent() const {
257     return MSLastManglingParent;
258   }
getMSLastManglingParent()259   Scope *getMSLastManglingParent() { return MSLastManglingParent; }
260 
261   /// getContinueParent - Return the closest scope that a continue statement
262   /// would be affected by.
getContinueParent()263   Scope *getContinueParent() {
264     return ContinueParent;
265   }
266 
getContinueParent()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.
setIsConditionVarScope(bool InConditionVarScope)273   void setIsConditionVarScope(bool InConditionVarScope) {
274     Flags = (Flags & ~ConditionVarScope) |
275             (InConditionVarScope ? ConditionVarScope : 0);
276   }
277 
isConditionVarScope()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.
getBreakParent()284   Scope *getBreakParent() {
285     return BreakParent;
286   }
getBreakParent()287   const Scope *getBreakParent() const {
288     return const_cast<Scope*>(this)->getBreakParent();
289   }
290 
getBlockParent()291   Scope *getBlockParent() { return BlockParent; }
getBlockParent()292   const Scope *getBlockParent() const { return BlockParent; }
293 
getTemplateParamParent()294   Scope *getTemplateParamParent() { return TemplateParamParent; }
getTemplateParamParent()295   const Scope *getTemplateParamParent() const { return TemplateParamParent; }
296 
297   /// Returns the depth of this scope. The translation-unit has scope depth 0.
getDepth()298   unsigned getDepth() const { return Depth; }
299 
300   /// Returns the number of function prototype scopes in this scope
301   /// chain.
getFunctionPrototypeDepth()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.
getNextFunctionPrototypeIndex()308   unsigned getNextFunctionPrototypeIndex() {
309     assert(isFunctionPrototypeScope());
310     return PrototypeIndex++;
311   }
312 
313   using decl_range = llvm::iterator_range<DeclSetTy::iterator>;
314 
decls()315   decl_range decls() const {
316     return decl_range(DeclsInScope.begin(), DeclsInScope.end());
317   }
318 
decl_empty()319   bool decl_empty() const { return DeclsInScope.empty(); }
320 
AddDecl(Decl * D)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 
RemoveDecl(Decl * D)329   void RemoveDecl(Decl *D) { DeclsInScope.erase(D); }
330 
incrementMSManglingNumber()331   void incrementMSManglingNumber() {
332     if (Scope *MSLMP = getMSLastManglingParent()) {
333       MSLMP->MSLastManglingNumber += 1;
334       MSCurManglingNumber += 1;
335     }
336   }
337 
decrementMSManglingNumber()338   void decrementMSManglingNumber() {
339     if (Scope *MSLMP = getMSLastManglingParent()) {
340       MSLMP->MSLastManglingNumber -= 1;
341       MSCurManglingNumber -= 1;
342     }
343   }
344 
getMSLastManglingNumber()345   unsigned getMSLastManglingNumber() const {
346     if (const Scope *MSLMP = getMSLastManglingParent())
347       return MSLMP->MSLastManglingNumber;
348     return 1;
349   }
350 
getMSCurManglingNumber()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.
isDeclScope(const Decl * D)357   bool isDeclScope(const Decl *D) const { return DeclsInScope.contains(D); }
358 
359   /// Get the entity corresponding to this scope.
getEntity()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.
getLookupEntity()366   DeclContext *getLookupEntity() const { return Entity; }
367 
setEntity(DeclContext * E)368   void setEntity(DeclContext *E) {
369     assert(!isTemplateParamScope() &&
370            "entity associated with template param scope");
371     Entity = E;
372   }
setLookupEntity(DeclContext * E)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.
hasUnrecoverableErrorOccurred()379   bool hasUnrecoverableErrorOccurred() const {
380     return ErrorTrap.hasUnrecoverableErrorOccurred();
381   }
382 
383   /// isFunctionScope() - Return true if this scope is a function scope.
isFunctionScope()384   bool isFunctionScope() const { return getFlags() & Scope::FnScope; }
385 
386   /// isClassScope - Return true if this scope is a class/struct/union scope.
isClassScope()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.
isClassInheritanceScope()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.
isInCXXInlineMethodScope()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.
isInObjcMethodScope()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.
isInObjcMethodOuterScope()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.
isTemplateParamScope()429   bool isTemplateParamScope() const {
430     return getFlags() & Scope::TemplateParamScope;
431   }
432 
433   /// isFunctionPrototypeScope - Return true if this scope is a
434   /// function prototype scope.
isFunctionPrototypeScope()435   bool isFunctionPrototypeScope() const {
436     return getFlags() & Scope::FunctionPrototypeScope;
437   }
438 
439   /// isFunctionDeclarationScope - Return true if this scope is a
440   /// function prototype scope.
isFunctionDeclarationScope()441   bool isFunctionDeclarationScope() const {
442     return getFlags() & Scope::FunctionDeclarationScope;
443   }
444 
445   /// isAtCatchScope - Return true if this scope is \@catch.
isAtCatchScope()446   bool isAtCatchScope() const {
447     return getFlags() & Scope::AtCatchScope;
448   }
449 
450   /// isCatchScope - Return true if this scope is a C++ catch statement.
isCatchScope()451   bool isCatchScope() const { return getFlags() & Scope::CatchScope; }
452 
453   /// isSwitchScope - Return true if this scope is a switch scope.
isSwitchScope()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
isOpenMPDirectiveScope()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').
isOpenMPLoopDirectiveScope()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').
isOpenMPSimdDirectiveScope()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.
isOpenMPLoopScope()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.
isOpenMPOrderClauseScope()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.
isContinueScope()504   bool isContinueScope() const {
505     return getFlags() & ScopeFlags::ContinueScope;
506   }
507 
508   /// Determine whether this scope is a C++ 'try' block.
isTryScope()509   bool isTryScope() const { return getFlags() & Scope::TryScope; }
510 
511   /// Determine whether this scope is a function-level C++ try or catch scope.
isFnTryCatchScope()512   bool isFnTryCatchScope() const {
513     return getFlags() & ScopeFlags::FnTryCatchScope;
514   }
515 
516   /// Determine whether this scope is a SEH '__try' block.
isSEHTryScope()517   bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; }
518 
519   /// Determine whether this scope is a SEH '__except' block.
isSEHExceptScope()520   bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; }
521 
522   /// Determine whether this scope is a compound statement scope.
isCompoundStmtScope()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.
isControlScope()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.
Contains(const Scope & rhs)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 
PushUsingDirective(UsingDirectiveDecl * UDir)541   void PushUsingDirective(UsingDirectiveDecl *UDir) {
542     UsingDirectives.push_back(UDir);
543   }
544 
545   using using_directives_range =
546       llvm::iterator_range<UsingDirectivesTy::iterator>;
547 
using_directives()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
571