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