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