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 |