Home | History | Annotate | Download | only in Sema
      1 //===- Scope.cpp - Lexical scope information --------------------*- 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 implements the Scope class, which is used for recording
     11 // information about a lexical scope.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "clang/Sema/Scope.h"
     16 #include "clang/AST/Decl.h"
     17 #include "llvm/Support/raw_ostream.h"
     18 
     19 using namespace clang;
     20 
     21 void Scope::Init(Scope *parent, unsigned flags) {
     22   AnyParent = parent;
     23   Flags = flags;
     24 
     25   if (parent && !(flags & FnScope)) {
     26     BreakParent    = parent->BreakParent;
     27     ContinueParent = parent->ContinueParent;
     28   } else {
     29     // Control scopes do not contain the contents of nested function scopes for
     30     // control flow purposes.
     31     BreakParent = ContinueParent = nullptr;
     32   }
     33 
     34   if (parent) {
     35     Depth = parent->Depth + 1;
     36     PrototypeDepth = parent->PrototypeDepth;
     37     PrototypeIndex = 0;
     38     FnParent       = parent->FnParent;
     39     BlockParent    = parent->BlockParent;
     40     TemplateParamParent = parent->TemplateParamParent;
     41     MSLocalManglingParent = parent->MSLocalManglingParent;
     42     if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
     43                   FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
     44         0)
     45       Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
     46   } else {
     47     Depth = 0;
     48     PrototypeDepth = 0;
     49     PrototypeIndex = 0;
     50     MSLocalManglingParent = FnParent = BlockParent = nullptr;
     51     TemplateParamParent = nullptr;
     52     MSLocalManglingNumber = 1;
     53   }
     54 
     55   // If this scope is a function or contains breaks/continues, remember it.
     56   if (flags & FnScope)            FnParent = this;
     57   // The MS mangler uses the number of scopes that can hold declarations as
     58   // part of an external name.
     59   if (Flags & (ClassScope | FnScope)) {
     60     MSLocalManglingNumber = getMSLocalManglingNumber();
     61     MSLocalManglingParent = this;
     62   }
     63   if (flags & BreakScope)         BreakParent = this;
     64   if (flags & ContinueScope)      ContinueParent = this;
     65   if (flags & BlockScope)         BlockParent = this;
     66   if (flags & TemplateParamScope) TemplateParamParent = this;
     67 
     68   // If this is a prototype scope, record that.
     69   if (flags & FunctionPrototypeScope) PrototypeDepth++;
     70 
     71   if (flags & DeclScope) {
     72     if (flags & FunctionPrototypeScope)
     73       ; // Prototype scopes are uninteresting.
     74     else if ((flags & ClassScope) && getParent()->isClassScope())
     75       ; // Nested class scopes aren't ambiguous.
     76     else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
     77       ; // Classes inside of namespaces aren't ambiguous.
     78     else if ((flags & EnumScope))
     79       ; // Don't increment for enum scopes.
     80     else
     81       incrementMSLocalManglingNumber();
     82   }
     83 
     84   DeclsInScope.clear();
     85   UsingDirectives.clear();
     86   Entity = nullptr;
     87   ErrorTrap.reset();
     88   NRVO.setPointerAndInt(nullptr, 0);
     89 }
     90 
     91 bool Scope::containedInPrototypeScope() const {
     92   const Scope *S = this;
     93   while (S) {
     94     if (S->isFunctionPrototypeScope())
     95       return true;
     96     S = S->getParent();
     97   }
     98   return false;
     99 }
    100 
    101 void Scope::AddFlags(unsigned FlagsToSet) {
    102   assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
    103          "Unsupported scope flags");
    104   if (FlagsToSet & BreakScope) {
    105     assert((Flags & BreakScope) == 0 && "Already set");
    106     BreakParent = this;
    107   }
    108   if (FlagsToSet & ContinueScope) {
    109     assert((Flags & ContinueScope) == 0 && "Already set");
    110     ContinueParent = this;
    111   }
    112   Flags |= FlagsToSet;
    113 }
    114 
    115 void Scope::mergeNRVOIntoParent() {
    116   if (VarDecl *Candidate = NRVO.getPointer()) {
    117     if (isDeclScope(Candidate))
    118       Candidate->setNRVOVariable(true);
    119   }
    120 
    121   if (getEntity())
    122     return;
    123 
    124   if (NRVO.getInt())
    125     getParent()->setNoNRVO();
    126   else if (NRVO.getPointer())
    127     getParent()->addNRVOCandidate(NRVO.getPointer());
    128 }
    129 
    130 void Scope::dump() const { dumpImpl(llvm::errs()); }
    131 
    132 void Scope::dumpImpl(raw_ostream &OS) const {
    133   unsigned Flags = getFlags();
    134   bool HasFlags = Flags != 0;
    135 
    136   if (HasFlags)
    137     OS << "Flags: ";
    138 
    139   while (Flags) {
    140     if (Flags & FnScope) {
    141       OS << "FnScope";
    142       Flags &= ~FnScope;
    143     } else if (Flags & BreakScope) {
    144       OS << "BreakScope";
    145       Flags &= ~BreakScope;
    146     } else if (Flags & ContinueScope) {
    147       OS << "ContinueScope";
    148       Flags &= ~ContinueScope;
    149     } else if (Flags & DeclScope) {
    150       OS << "DeclScope";
    151       Flags &= ~DeclScope;
    152     } else if (Flags & ControlScope) {
    153       OS << "ControlScope";
    154       Flags &= ~ControlScope;
    155     } else if (Flags & ClassScope) {
    156       OS << "ClassScope";
    157       Flags &= ~ClassScope;
    158     } else if (Flags & BlockScope) {
    159       OS << "BlockScope";
    160       Flags &= ~BlockScope;
    161     } else if (Flags & TemplateParamScope) {
    162       OS << "TemplateParamScope";
    163       Flags &= ~TemplateParamScope;
    164     } else if (Flags & FunctionPrototypeScope) {
    165       OS << "FunctionPrototypeScope";
    166       Flags &= ~FunctionPrototypeScope;
    167     } else if (Flags & FunctionDeclarationScope) {
    168       OS << "FunctionDeclarationScope";
    169       Flags &= ~FunctionDeclarationScope;
    170     } else if (Flags & AtCatchScope) {
    171       OS << "AtCatchScope";
    172       Flags &= ~AtCatchScope;
    173     } else if (Flags & ObjCMethodScope) {
    174       OS << "ObjCMethodScope";
    175       Flags &= ~ObjCMethodScope;
    176     } else if (Flags & SwitchScope) {
    177       OS << "SwitchScope";
    178       Flags &= ~SwitchScope;
    179     } else if (Flags & TryScope) {
    180       OS << "TryScope";
    181       Flags &= ~TryScope;
    182     } else if (Flags & FnTryCatchScope) {
    183       OS << "FnTryCatchScope";
    184       Flags &= ~FnTryCatchScope;
    185     } else if (Flags & SEHTryScope) {
    186       OS << "SEHTryScope";
    187       Flags &= ~SEHTryScope;
    188     } else if (Flags & OpenMPDirectiveScope) {
    189       OS << "OpenMPDirectiveScope";
    190       Flags &= ~OpenMPDirectiveScope;
    191     } else if (Flags & OpenMPLoopDirectiveScope) {
    192       OS << "OpenMPLoopDirectiveScope";
    193       Flags &= ~OpenMPLoopDirectiveScope;
    194     } else if (Flags & OpenMPSimdDirectiveScope) {
    195       OS << "OpenMPSimdDirectiveScope";
    196       Flags &= ~OpenMPSimdDirectiveScope;
    197     }
    198 
    199     if (Flags)
    200       OS << " | ";
    201   }
    202   if (HasFlags)
    203     OS << '\n';
    204 
    205   if (const Scope *Parent = getParent())
    206     OS << "Parent: (clang::Scope*)" << Parent << '\n';
    207 
    208   OS << "Depth: " << Depth << '\n';
    209   OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
    210   if (const DeclContext *DC = getEntity())
    211     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
    212 
    213   if (NRVO.getInt())
    214     OS << "NRVO not allowed";
    215   else if (NRVO.getPointer())
    216     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
    217 }
    218