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 000000000000..4229c6c62748 --- /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  | 
