1//===--- Scope.h - Scope interface ------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the Scope interface. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_SEMA_SCOPE_H 15#define LLVM_CLANG_SEMA_SCOPE_H 16 17#include "clang/AST/Decl.h" 18#include "clang/Basic/Diagnostic.h" 19#include "llvm/ADT/PointerIntPair.h" 20#include "llvm/ADT/SmallPtrSet.h" 21#include "llvm/ADT/SmallVector.h" 22 23namespace llvm { 24 25class raw_ostream; 26 27} 28 29namespace clang { 30 31class Decl; 32class UsingDirectiveDecl; 33class VarDecl; 34 35/// Scope - A scope is a transient data structure that is used while parsing the 36/// program. It assists with resolving identifiers to the appropriate 37/// declaration. 38/// 39class Scope { 40public: 41 /// ScopeFlags - These are bitfields that are or'd together when creating a 42 /// scope, which defines the sorts of things the scope contains. 43 enum ScopeFlags { 44 /// \brief This indicates that the scope corresponds to a function, which 45 /// means that labels are set here. 46 FnScope = 0x01, 47 48 /// \brief This is a while, do, switch, for, etc that can have break 49 /// statements embedded into it. 50 BreakScope = 0x02, 51 52 /// \brief This is a while, do, for, which can have continue statements 53 /// embedded into it. 54 ContinueScope = 0x04, 55 56 /// \brief This is a scope that can contain a declaration. Some scopes 57 /// just contain loop constructs but don't contain decls. 58 DeclScope = 0x08, 59 60 /// \brief The controlling scope in a if/switch/while/for statement. 61 ControlScope = 0x10, 62 63 /// \brief The scope of a struct/union/class definition. 64 ClassScope = 0x20, 65 66 /// \brief This is a scope that corresponds to a block/closure object. 67 /// Blocks serve as top-level scopes for some objects like labels, they 68 /// also prevent things like break and continue. BlockScopes always have 69 /// the FnScope and DeclScope flags set as well. 70 BlockScope = 0x40, 71 72 /// \brief This is a scope that corresponds to the 73 /// template parameters of a C++ template. Template parameter 74 /// scope starts at the 'template' keyword and ends when the 75 /// template declaration ends. 76 TemplateParamScope = 0x80, 77 78 /// \brief This is a scope that corresponds to the 79 /// parameters within a function prototype. 80 FunctionPrototypeScope = 0x100, 81 82 /// \brief This is a scope that corresponds to the parameters within 83 /// a function prototype for a function declaration (as opposed to any 84 /// other kind of function declarator). Always has FunctionPrototypeScope 85 /// set as well. 86 FunctionDeclarationScope = 0x200, 87 88 /// \brief This is a scope that corresponds to the Objective-C 89 /// \@catch statement. 90 AtCatchScope = 0x400, 91 92 /// \brief This scope corresponds to an Objective-C method body. 93 /// It always has FnScope and DeclScope set as well. 94 ObjCMethodScope = 0x800, 95 96 /// \brief This is a scope that corresponds to a switch statement. 97 SwitchScope = 0x1000, 98 99 /// \brief This is the scope of a C++ try statement. 100 TryScope = 0x2000, 101 102 /// \brief This is the scope for a function-level C++ try or catch scope. 103 FnTryCatchScope = 0x4000, 104 105 /// \brief This is the scope of OpenMP executable directive. 106 OpenMPDirectiveScope = 0x8000, 107 108 /// \brief This is the scope of some OpenMP loop directive. 109 OpenMPLoopDirectiveScope = 0x10000, 110 111 /// \brief This is the scope of some OpenMP simd directive. 112 /// For example, it is used for 'omp simd', 'omp for simd'. 113 /// This flag is propagated to children scopes. 114 OpenMPSimdDirectiveScope = 0x20000, 115 116 /// This scope corresponds to an enum. 117 EnumScope = 0x40000, 118 119 /// This scope corresponds to an SEH try. 120 SEHTryScope = 0x80000, 121 122 /// This scope corresponds to an SEH except. 123 SEHExceptScope = 0x100000, 124 125 /// We are currently in the filter expression of an SEH except block. 126 SEHFilterScope = 0x200000, 127 128 /// This is a compound statement scope. 129 CompoundStmtScope = 0x400000, 130 }; 131private: 132 /// The parent scope for this scope. This is null for the translation-unit 133 /// scope. 134 Scope *AnyParent; 135 136 /// Flags - This contains a set of ScopeFlags, which indicates how the scope 137 /// interrelates with other control flow statements. 138 unsigned Flags; 139 140 /// Depth - This is the depth of this scope. The translation-unit scope has 141 /// depth 0. 142 unsigned short Depth; 143 144 /// \brief Declarations with static linkage are mangled with the number of 145 /// scopes seen as a component. 146 unsigned short MSLastManglingNumber; 147 148 unsigned short MSCurManglingNumber; 149 150 /// PrototypeDepth - This is the number of function prototype scopes 151 /// enclosing this scope, including this scope. 152 unsigned short PrototypeDepth; 153 154 /// PrototypeIndex - This is the number of parameters currently 155 /// declared in this scope. 156 unsigned short PrototypeIndex; 157 158 /// FnParent - If this scope has a parent scope that is a function body, this 159 /// pointer is non-null and points to it. This is used for label processing. 160 Scope *FnParent; 161 Scope *MSLastManglingParent; 162 163 /// BreakParent/ContinueParent - This is a direct link to the innermost 164 /// BreakScope/ContinueScope which contains the contents of this scope 165 /// for control flow purposes (and might be this scope itself), or null 166 /// if there is no such scope. 167 Scope *BreakParent, *ContinueParent; 168 169 /// BlockParent - This is a direct link to the immediately containing 170 /// BlockScope if this scope is not one, or null if there is none. 171 Scope *BlockParent; 172 173 /// TemplateParamParent - This is a direct link to the 174 /// immediately containing template parameter scope. In the 175 /// case of nested templates, template parameter scopes can have 176 /// other template parameter scopes as parents. 177 Scope *TemplateParamParent; 178 179 /// DeclsInScope - This keeps track of all declarations in this scope. When 180 /// the declaration is added to the scope, it is set as the current 181 /// declaration for the identifier in the IdentifierTable. When the scope is 182 /// popped, these declarations are removed from the IdentifierTable's notion 183 /// of current declaration. It is up to the current Action implementation to 184 /// implement these semantics. 185 typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy; 186 DeclSetTy DeclsInScope; 187 188 /// The DeclContext with which this scope is associated. For 189 /// example, the entity of a class scope is the class itself, the 190 /// entity of a function scope is a function, etc. 191 DeclContext *Entity; 192 193 typedef SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy; 194 UsingDirectivesTy UsingDirectives; 195 196 /// \brief Used to determine if errors occurred in this scope. 197 DiagnosticErrorTrap ErrorTrap; 198 199 /// A lattice consisting of undefined, a single NRVO candidate variable in 200 /// this scope, or over-defined. The bit is true when over-defined. 201 llvm::PointerIntPair<VarDecl *, 1, bool> NRVO; 202 203 void setFlags(Scope *Parent, unsigned F); 204 205public: 206 Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag) 207 : ErrorTrap(Diag) { 208 Init(Parent, ScopeFlags); 209 } 210 211 /// getFlags - Return the flags for this scope. 212 /// 213 unsigned getFlags() const { return Flags; } 214 void setFlags(unsigned F) { setFlags(getParent(), F); } 215 216 /// isBlockScope - Return true if this scope correspond to a closure. 217 bool isBlockScope() const { return Flags & BlockScope; } 218 219 /// getParent - Return the scope that this is nested in. 220 /// 221 const Scope *getParent() const { return AnyParent; } 222 Scope *getParent() { return AnyParent; } 223 224 /// getFnParent - Return the closest scope that is a function body. 225 /// 226 const Scope *getFnParent() const { return FnParent; } 227 Scope *getFnParent() { return FnParent; } 228 229 const Scope *getMSLastManglingParent() const { 230 return MSLastManglingParent; 231 } 232 Scope *getMSLastManglingParent() { return MSLastManglingParent; } 233 234 /// getContinueParent - Return the closest scope that a continue statement 235 /// would be affected by. 236 Scope *getContinueParent() { 237 return ContinueParent; 238 } 239 240 const Scope *getContinueParent() const { 241 return const_cast<Scope*>(this)->getContinueParent(); 242 } 243 244 /// getBreakParent - Return the closest scope that a break statement 245 /// would be affected by. 246 Scope *getBreakParent() { 247 return BreakParent; 248 } 249 const Scope *getBreakParent() const { 250 return const_cast<Scope*>(this)->getBreakParent(); 251 } 252 253 Scope *getBlockParent() { return BlockParent; } 254 const Scope *getBlockParent() const { return BlockParent; } 255 256 Scope *getTemplateParamParent() { return TemplateParamParent; } 257 const Scope *getTemplateParamParent() const { return TemplateParamParent; } 258 259 /// Returns the number of function prototype scopes in this scope 260 /// chain. 261 unsigned getFunctionPrototypeDepth() const { 262 return PrototypeDepth; 263 } 264 265 /// Return the number of parameters declared in this function 266 /// prototype, increasing it by one for the next call. 267 unsigned getNextFunctionPrototypeIndex() { 268 assert(isFunctionPrototypeScope()); 269 return PrototypeIndex++; 270 } 271 272 typedef llvm::iterator_range<DeclSetTy::iterator> decl_range; 273 decl_range decls() const { 274 return decl_range(DeclsInScope.begin(), DeclsInScope.end()); 275 } 276 bool decl_empty() const { return DeclsInScope.empty(); } 277 278 void AddDecl(Decl *D) { 279 DeclsInScope.insert(D); 280 } 281 282 void RemoveDecl(Decl *D) { 283 DeclsInScope.erase(D); 284 } 285 286 void incrementMSManglingNumber() { 287 if (Scope *MSLMP = getMSLastManglingParent()) { 288 MSLMP->MSLastManglingNumber += 1; 289 MSCurManglingNumber += 1; 290 } 291 } 292 293 void decrementMSManglingNumber() { 294 if (Scope *MSLMP = getMSLastManglingParent()) { 295 MSLMP->MSLastManglingNumber -= 1; 296 MSCurManglingNumber -= 1; 297 } 298 } 299 300 unsigned getMSLastManglingNumber() const { 301 if (const Scope *MSLMP = getMSLastManglingParent()) 302 return MSLMP->MSLastManglingNumber; 303 return 1; 304 } 305 306 unsigned getMSCurManglingNumber() const { 307 return MSCurManglingNumber; 308 } 309 310 /// isDeclScope - Return true if this is the scope that the specified decl is 311 /// declared in. 312 bool isDeclScope(Decl *D) { 313 return DeclsInScope.count(D) != 0; 314 } 315 316 DeclContext *getEntity() const { return Entity; } 317 void setEntity(DeclContext *E) { Entity = E; } 318 319 bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); } 320 321 bool hasUnrecoverableErrorOccurred() const { 322 return ErrorTrap.hasUnrecoverableErrorOccurred(); 323 } 324 325 /// isFunctionScope() - Return true if this scope is a function scope. 326 bool isFunctionScope() const { return (getFlags() & Scope::FnScope); } 327 328 /// isClassScope - Return true if this scope is a class/struct/union scope. 329 bool isClassScope() const { 330 return (getFlags() & Scope::ClassScope); 331 } 332 333 /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline 334 /// method scope or is inside one. 335 bool isInCXXInlineMethodScope() const { 336 if (const Scope *FnS = getFnParent()) { 337 assert(FnS->getParent() && "TUScope not created?"); 338 return FnS->getParent()->isClassScope(); 339 } 340 return false; 341 } 342 343 /// isInObjcMethodScope - Return true if this scope is, or is contained in, an 344 /// Objective-C method body. Note that this method is not constant time. 345 bool isInObjcMethodScope() const { 346 for (const Scope *S = this; S; S = S->getParent()) { 347 // If this scope is an objc method scope, then we succeed. 348 if (S->getFlags() & ObjCMethodScope) 349 return true; 350 } 351 return false; 352 } 353 354 /// isInObjcMethodOuterScope - Return true if this scope is an 355 /// Objective-C method outer most body. 356 bool isInObjcMethodOuterScope() const { 357 if (const Scope *S = this) { 358 // If this scope is an objc method scope, then we succeed. 359 if (S->getFlags() & ObjCMethodScope) 360 return true; 361 } 362 return false; 363 } 364 365 366 /// isTemplateParamScope - Return true if this scope is a C++ 367 /// template parameter scope. 368 bool isTemplateParamScope() const { 369 return getFlags() & Scope::TemplateParamScope; 370 } 371 372 /// isFunctionPrototypeScope - Return true if this scope is a 373 /// function prototype scope. 374 bool isFunctionPrototypeScope() const { 375 return getFlags() & Scope::FunctionPrototypeScope; 376 } 377 378 /// isAtCatchScope - Return true if this scope is \@catch. 379 bool isAtCatchScope() const { 380 return getFlags() & Scope::AtCatchScope; 381 } 382 383 /// isSwitchScope - Return true if this scope is a switch scope. 384 bool isSwitchScope() const { 385 for (const Scope *S = this; S; S = S->getParent()) { 386 if (S->getFlags() & Scope::SwitchScope) 387 return true; 388 else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope | 389 Scope::BlockScope | Scope::TemplateParamScope | 390 Scope::FunctionPrototypeScope | 391 Scope::AtCatchScope | Scope::ObjCMethodScope)) 392 return false; 393 } 394 return false; 395 } 396 397 /// \brief Determines whether this scope is the OpenMP directive scope 398 bool isOpenMPDirectiveScope() const { 399 return (getFlags() & Scope::OpenMPDirectiveScope); 400 } 401 402 /// \brief Determine whether this scope is some OpenMP loop directive scope 403 /// (for example, 'omp for', 'omp simd'). 404 bool isOpenMPLoopDirectiveScope() const { 405 if (getFlags() & Scope::OpenMPLoopDirectiveScope) { 406 assert(isOpenMPDirectiveScope() && 407 "OpenMP loop directive scope is not a directive scope"); 408 return true; 409 } 410 return false; 411 } 412 413 /// \brief Determine whether this scope is (or is nested into) some OpenMP 414 /// loop simd directive scope (for example, 'omp simd', 'omp for simd'). 415 bool isOpenMPSimdDirectiveScope() const { 416 return getFlags() & Scope::OpenMPSimdDirectiveScope; 417 } 418 419 /// \brief Determine whether this scope is a loop having OpenMP loop 420 /// directive attached. 421 bool isOpenMPLoopScope() const { 422 const Scope *P = getParent(); 423 return P && P->isOpenMPLoopDirectiveScope(); 424 } 425 426 /// \brief Determine whether this scope is a C++ 'try' block. 427 bool isTryScope() const { return getFlags() & Scope::TryScope; } 428 429 /// \brief Determine whether this scope is a SEH '__try' block. 430 bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; } 431 432 /// \brief Determine whether this scope is a SEH '__except' block. 433 bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; } 434 435 /// \brief Determine whether this scope is a compound statement scope. 436 bool isCompoundStmtScope() const { 437 return getFlags() & Scope::CompoundStmtScope; 438 } 439 440 /// \brief Returns if rhs has a higher scope depth than this. 441 /// 442 /// The caller is responsible for calling this only if one of the two scopes 443 /// is an ancestor of the other. 444 bool Contains(const Scope& rhs) const { return Depth < rhs.Depth; } 445 446 /// containedInPrototypeScope - Return true if this or a parent scope 447 /// is a FunctionPrototypeScope. 448 bool containedInPrototypeScope() const; 449 450 void PushUsingDirective(UsingDirectiveDecl *UDir) { 451 UsingDirectives.push_back(UDir); 452 } 453 454 typedef llvm::iterator_range<UsingDirectivesTy::iterator> 455 using_directives_range; 456 457 using_directives_range using_directives() { 458 return using_directives_range(UsingDirectives.begin(), 459 UsingDirectives.end()); 460 } 461 462 void addNRVOCandidate(VarDecl *VD) { 463 if (NRVO.getInt()) 464 return; 465 if (NRVO.getPointer() == nullptr) { 466 NRVO.setPointer(VD); 467 return; 468 } 469 if (NRVO.getPointer() != VD) 470 setNoNRVO(); 471 } 472 473 void setNoNRVO() { 474 NRVO.setInt(1); 475 NRVO.setPointer(nullptr); 476 } 477 478 void mergeNRVOIntoParent(); 479 480 /// Init - This is used by the parser to implement scope caching. 481 /// 482 void Init(Scope *parent, unsigned flags); 483 484 /// \brief Sets up the specified scope flags and adjusts the scope state 485 /// variables accordingly. 486 /// 487 void AddFlags(unsigned Flags); 488 489 void dumpImpl(raw_ostream &OS) const; 490 void dump() const; 491}; 492 493} // end namespace clang 494 495#endif 496