| //===--- 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_PARSE_SCOPE_H |
| #define LLVM_CLANG_PARSE_SCOPE_H |
| |
| #include "clang/Parse/Action.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| |
| namespace clang { |
| |
| /// 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 have the |
| /// other 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 |
| }; |
| 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 Depth : 16; |
| |
| /// Flags - This contains a set of ScopeFlags, which indicates how the scope |
| /// interrelates with other control flow statements. |
| unsigned Flags : 10; |
| |
| /// WithinElse - Whether this scope is part of the "else" branch in |
| /// its parent ControlScope. |
| bool WithinElse : 1; |
| |
| /// 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<Action::DeclPtrTy, 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<Action::DeclPtrTy, 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; } |
| |
| /// 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(Action::DeclPtrTy D) { |
| DeclsInScope.insert(D); |
| } |
| |
| void RemoveDecl(Action::DeclPtrTy D) { |
| DeclsInScope.erase(D); |
| } |
| |
| /// isDeclScope - Return true if this is the scope that the specified decl is |
| /// declared in. |
| bool isDeclScope(Action::DeclPtrTy 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; |
| } |
| |
| /// 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; |
| } |
| |
| /// isWithinElse - Whether we are within the "else" of the |
| /// ControlParent (if any). |
| bool isWithinElse() const { return WithinElse; } |
| |
| void setWithinElse(bool WE) { WithinElse = WE; } |
| |
| typedef UsingDirectivesTy::iterator udir_iterator; |
| typedef UsingDirectivesTy::const_iterator const_udir_iterator; |
| |
| void PushUsingDirective(Action::DeclPtrTy 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; |
| WithinElse = false; |
| |
| 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 |