diff options
Diffstat (limited to 'include/clang/Sema/Scope.h')
-rw-r--r-- | include/clang/Sema/Scope.h | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h new file mode 100644 index 0000000..4229c6c --- /dev/null +++ b/include/clang/Sema/Scope.h @@ -0,0 +1,327 @@ +//===--- Scope.h - Scope interface ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Scope interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SCOPE_H +#define LLVM_CLANG_SEMA_SCOPE_H + +#include "llvm/ADT/SmallPtrSet.h" + +namespace clang { + +class Decl; +class UsingDirectiveDecl; + +/// Scope - A scope is a transient data structure that is used while parsing the +/// program. It assists with resolving identifiers to the appropriate +/// declaration. +/// +class Scope { +public: + /// ScopeFlags - These are bitfields that are or'd together when creating a + /// scope, which defines the sorts of things the scope contains. + enum ScopeFlags { + /// FnScope - This indicates that the scope corresponds to a function, which + /// means that labels are set here. + FnScope = 0x01, + + /// BreakScope - This is a while,do,switch,for, etc that can have break + /// stmts embedded into it. + BreakScope = 0x02, + + /// ContinueScope - This is a while,do,for, which can have continue + /// stmt embedded into it. + ContinueScope = 0x04, + + /// DeclScope - This is a scope that can contain a declaration. Some scopes + /// just contain loop constructs but don't contain decls. + DeclScope = 0x08, + + /// ControlScope - The controlling scope in a if/switch/while/for statement. + ControlScope = 0x10, + + /// ClassScope - The scope of a struct/union/class definition. + ClassScope = 0x20, + + /// BlockScope - This is a scope that corresponds to a block object. + /// Blocks serve as top-level scopes for some objects like labels, they + /// also prevent things like break and continue. BlockScopes always have + /// the FnScope, BreakScope, ContinueScope, and DeclScope flags set as well. + BlockScope = 0x40, + + /// TemplateParamScope - This is a scope that corresponds to the + /// template parameters of a C++ template. Template parameter + /// scope starts at the 'template' keyword and ends when the + /// template declaration ends. + TemplateParamScope = 0x80, + + /// FunctionPrototypeScope - This is a scope that corresponds to the + /// parameters within a function prototype. + FunctionPrototypeScope = 0x100, + + /// AtCatchScope - This is a scope that corresponds to the Objective-C + /// @catch statement. + AtCatchScope = 0x200, + + /// ObjCMethodScope - This scope corresponds to an Objective-C method body. + /// It always has FnScope and DeclScope set as well. + ObjCMethodScope = 0x400 + }; +private: + /// The parent scope for this scope. This is null for the translation-unit + /// scope. + Scope *AnyParent; + + /// Depth - This is the depth of this scope. The translation-unit scope has + /// depth 0. + unsigned short Depth; + + /// Flags - This contains a set of ScopeFlags, which indicates how the scope + /// interrelates with other control flow statements. + unsigned short Flags; + + /// FnParent - If this scope has a parent scope that is a function body, this + /// pointer is non-null and points to it. This is used for label processing. + Scope *FnParent; + + /// BreakParent/ContinueParent - This is a direct link to the immediately + /// preceeding BreakParent/ContinueParent if this scope is not one, or null if + /// there is no containing break/continue scope. + Scope *BreakParent, *ContinueParent; + + /// ControlParent - This is a direct link to the immediately + /// preceeding ControlParent if this scope is not one, or null if + /// there is no containing control scope. + Scope *ControlParent; + + /// BlockParent - This is a direct link to the immediately containing + /// BlockScope if this scope is not one, or null if there is none. + Scope *BlockParent; + + /// TemplateParamParent - This is a direct link to the + /// immediately containing template parameter scope. In the + /// case of nested templates, template parameter scopes can have + /// other template parameter scopes as parents. + Scope *TemplateParamParent; + + /// DeclsInScope - This keeps track of all declarations in this scope. When + /// the declaration is added to the scope, it is set as the current + /// declaration for the identifier in the IdentifierTable. When the scope is + /// popped, these declarations are removed from the IdentifierTable's notion + /// of current declaration. It is up to the current Action implementation to + /// implement these semantics. + typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy; + DeclSetTy DeclsInScope; + + /// Entity - The entity with which this scope is associated. For + /// example, the entity of a class scope is the class itself, the + /// entity of a function scope is a function, etc. This field is + /// maintained by the Action implementation. + void *Entity; + + typedef llvm::SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy; + UsingDirectivesTy UsingDirectives; + + /// \brief The number of errors at the start of the given scope. + unsigned NumErrorsAtStart; + +public: + Scope(Scope *Parent, unsigned ScopeFlags) { + Init(Parent, ScopeFlags); + } + + /// getFlags - Return the flags for this scope. + /// + unsigned getFlags() const { return Flags; } + void setFlags(unsigned F) { Flags = F; } + + /// isBlockScope - Return true if this scope does not correspond to a + /// closure. + bool isBlockScope() const { return Flags & BlockScope; } + + /// getParent - Return the scope that this is nested in. + /// + const Scope *getParent() const { return AnyParent; } + Scope *getParent() { return AnyParent; } + + /// getFnParent - Return the closest scope that is a function body. + /// + const Scope *getFnParent() const { return FnParent; } + Scope *getFnParent() { return FnParent; } + + /// getContinueParent - Return the closest scope that a continue statement + /// would be affected by. If the closest scope is a closure scope, we know + /// that there is no loop *inside* the closure. + Scope *getContinueParent() { + if (ContinueParent && !ContinueParent->isBlockScope()) + return ContinueParent; + return 0; + } + + const Scope *getContinueParent() const { + return const_cast<Scope*>(this)->getContinueParent(); + } + + /// getBreakParent - Return the closest scope that a break statement + /// would be affected by. If the closest scope is a block scope, we know + /// that there is no loop *inside* the block. + Scope *getBreakParent() { + if (BreakParent && !BreakParent->isBlockScope()) + return BreakParent; + return 0; + } + const Scope *getBreakParent() const { + return const_cast<Scope*>(this)->getBreakParent(); + } + + Scope *getControlParent() { return ControlParent; } + const Scope *getControlParent() const { return ControlParent; } + + Scope *getBlockParent() { return BlockParent; } + const Scope *getBlockParent() const { return BlockParent; } + + Scope *getTemplateParamParent() { return TemplateParamParent; } + const Scope *getTemplateParamParent() const { return TemplateParamParent; } + + typedef DeclSetTy::iterator decl_iterator; + decl_iterator decl_begin() const { return DeclsInScope.begin(); } + decl_iterator decl_end() const { return DeclsInScope.end(); } + bool decl_empty() const { return DeclsInScope.empty(); } + + void AddDecl(Decl *D) { + DeclsInScope.insert(D); + } + + void RemoveDecl(Decl *D) { + DeclsInScope.erase(D); + } + + /// isDeclScope - Return true if this is the scope that the specified decl is + /// declared in. + bool isDeclScope(Decl *D) { + return DeclsInScope.count(D) != 0; + } + + void* getEntity() const { return Entity; } + void setEntity(void *E) { Entity = E; } + + /// \brief Retrieve the number of errors that had been emitted when we + /// entered this scope. + unsigned getNumErrorsAtStart() const { return NumErrorsAtStart; } + + void setNumErrorsAtStart(unsigned NumErrors) { + NumErrorsAtStart = NumErrors; + } + + /// isClassScope - Return true if this scope is a class/struct/union scope. + bool isClassScope() const { + return (getFlags() & Scope::ClassScope); + } + + /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline + /// method scope or is inside one. + bool isInCXXInlineMethodScope() const { + if (const Scope *FnS = getFnParent()) { + assert(FnS->getParent() && "TUScope not created?"); + return FnS->getParent()->isClassScope(); + } + return false; + } + + /// isInObjcMethodScope - Return true if this scope is, or is contained in, an + /// Objective-C method body. Note that this method is not constant time. + bool isInObjcMethodScope() const { + for (const Scope *S = this; S; S = S->getParent()) { + // If this scope is an objc method scope, then we succeed. + if (S->getFlags() & ObjCMethodScope) + return true; + } + return false; + } + + /// isTemplateParamScope - Return true if this scope is a C++ + /// template parameter scope. + bool isTemplateParamScope() const { + return getFlags() & Scope::TemplateParamScope; + } + + /// isFunctionPrototypeScope - Return true if this scope is a + /// function prototype scope. + bool isFunctionPrototypeScope() const { + return getFlags() & Scope::FunctionPrototypeScope; + } + + /// isAtCatchScope - Return true if this scope is @catch. + bool isAtCatchScope() const { + return getFlags() & Scope::AtCatchScope; + } + + typedef UsingDirectivesTy::iterator udir_iterator; + typedef UsingDirectivesTy::const_iterator const_udir_iterator; + + void PushUsingDirective(UsingDirectiveDecl *UDir) { + UsingDirectives.push_back(UDir); + } + + udir_iterator using_directives_begin() { + return UsingDirectives.begin(); + } + + udir_iterator using_directives_end() { + return UsingDirectives.end(); + } + + const_udir_iterator using_directives_begin() const { + return UsingDirectives.begin(); + } + + const_udir_iterator using_directives_end() const { + return UsingDirectives.end(); + } + + /// Init - This is used by the parser to implement scope caching. + /// + void Init(Scope *Parent, unsigned ScopeFlags) { + AnyParent = Parent; + Depth = AnyParent ? AnyParent->Depth+1 : 0; + Flags = ScopeFlags; + + if (AnyParent) { + FnParent = AnyParent->FnParent; + BreakParent = AnyParent->BreakParent; + ContinueParent = AnyParent->ContinueParent; + ControlParent = AnyParent->ControlParent; + BlockParent = AnyParent->BlockParent; + TemplateParamParent = AnyParent->TemplateParamParent; + } else { + FnParent = BreakParent = ContinueParent = BlockParent = 0; + ControlParent = 0; + TemplateParamParent = 0; + } + + // If this scope is a function or contains breaks/continues, remember it. + if (Flags & FnScope) FnParent = this; + if (Flags & BreakScope) BreakParent = this; + if (Flags & ContinueScope) ContinueParent = this; + if (Flags & ControlScope) ControlParent = this; + if (Flags & BlockScope) BlockParent = this; + if (Flags & TemplateParamScope) TemplateParamParent = this; + DeclsInScope.clear(); + UsingDirectives.clear(); + Entity = 0; + NumErrorsAtStart = 0; + } +}; + +} // end namespace clang + +#endif |