clang API Documentation

Scope.cpp
Go to the documentation of this file.
00001 //===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the Scope class, which is used for recording
00011 // information about a lexical scope.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "clang/Sema/Scope.h"
00016 #include "clang/AST/Decl.h"
00017 #include "llvm/Support/raw_ostream.h"
00018 
00019 using namespace clang;
00020 
00021 void Scope::Init(Scope *parent, unsigned flags) {
00022   AnyParent = parent;
00023   Flags = flags;
00024 
00025   if (parent && !(flags & FnScope)) {
00026     BreakParent    = parent->BreakParent;
00027     ContinueParent = parent->ContinueParent;
00028   } else {
00029     // Control scopes do not contain the contents of nested function scopes for
00030     // control flow purposes.
00031     BreakParent = ContinueParent = nullptr;
00032   }
00033 
00034   if (parent) {
00035     Depth = parent->Depth + 1;
00036     PrototypeDepth = parent->PrototypeDepth;
00037     PrototypeIndex = 0;
00038     FnParent       = parent->FnParent;
00039     BlockParent    = parent->BlockParent;
00040     TemplateParamParent = parent->TemplateParamParent;
00041     MSLocalManglingParent = parent->MSLocalManglingParent;
00042     if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
00043                   FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
00044         0)
00045       Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
00046   } else {
00047     Depth = 0;
00048     PrototypeDepth = 0;
00049     PrototypeIndex = 0;
00050     MSLocalManglingParent = FnParent = BlockParent = nullptr;
00051     TemplateParamParent = nullptr;
00052     MSLocalManglingNumber = 1;
00053   }
00054 
00055   // If this scope is a function or contains breaks/continues, remember it.
00056   if (flags & FnScope)            FnParent = this;
00057   // The MS mangler uses the number of scopes that can hold declarations as
00058   // part of an external name.
00059   if (Flags & (ClassScope | FnScope)) {
00060     MSLocalManglingNumber = getMSLocalManglingNumber();
00061     MSLocalManglingParent = this;
00062   }
00063   if (flags & BreakScope)         BreakParent = this;
00064   if (flags & ContinueScope)      ContinueParent = this;
00065   if (flags & BlockScope)         BlockParent = this;
00066   if (flags & TemplateParamScope) TemplateParamParent = this;
00067 
00068   // If this is a prototype scope, record that.
00069   if (flags & FunctionPrototypeScope) PrototypeDepth++;
00070 
00071   if (flags & DeclScope) {
00072     if (flags & FunctionPrototypeScope)
00073       ; // Prototype scopes are uninteresting.
00074     else if ((flags & ClassScope) && getParent()->isClassScope())
00075       ; // Nested class scopes aren't ambiguous.
00076     else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
00077       ; // Classes inside of namespaces aren't ambiguous.
00078     else if ((flags & EnumScope))
00079       ; // Don't increment for enum scopes.
00080     else
00081       incrementMSLocalManglingNumber();
00082   }
00083 
00084   DeclsInScope.clear();
00085   UsingDirectives.clear();
00086   Entity = nullptr;
00087   ErrorTrap.reset();
00088   NRVO.setPointerAndInt(nullptr, 0);
00089 }
00090 
00091 bool Scope::containedInPrototypeScope() const {
00092   const Scope *S = this;
00093   while (S) {
00094     if (S->isFunctionPrototypeScope())
00095       return true;
00096     S = S->getParent();
00097   }
00098   return false;
00099 }
00100 
00101 void Scope::AddFlags(unsigned FlagsToSet) {
00102   assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
00103          "Unsupported scope flags");
00104   if (FlagsToSet & BreakScope) {
00105     assert((Flags & BreakScope) == 0 && "Already set");
00106     BreakParent = this;
00107   }
00108   if (FlagsToSet & ContinueScope) {
00109     assert((Flags & ContinueScope) == 0 && "Already set");
00110     ContinueParent = this;
00111   }
00112   Flags |= FlagsToSet;
00113 }
00114 
00115 void Scope::mergeNRVOIntoParent() {
00116   if (VarDecl *Candidate = NRVO.getPointer()) {
00117     if (isDeclScope(Candidate))
00118       Candidate->setNRVOVariable(true);
00119   }
00120 
00121   if (getEntity())
00122     return;
00123 
00124   if (NRVO.getInt())
00125     getParent()->setNoNRVO();
00126   else if (NRVO.getPointer())
00127     getParent()->addNRVOCandidate(NRVO.getPointer());
00128 }
00129 
00130 void Scope::dump() const { dumpImpl(llvm::errs()); }
00131 
00132 void Scope::dumpImpl(raw_ostream &OS) const {
00133   unsigned Flags = getFlags();
00134   bool HasFlags = Flags != 0;
00135 
00136   if (HasFlags)
00137     OS << "Flags: ";
00138 
00139   while (Flags) {
00140     if (Flags & FnScope) {
00141       OS << "FnScope";
00142       Flags &= ~FnScope;
00143     } else if (Flags & BreakScope) {
00144       OS << "BreakScope";
00145       Flags &= ~BreakScope;
00146     } else if (Flags & ContinueScope) {
00147       OS << "ContinueScope";
00148       Flags &= ~ContinueScope;
00149     } else if (Flags & DeclScope) {
00150       OS << "DeclScope";
00151       Flags &= ~DeclScope;
00152     } else if (Flags & ControlScope) {
00153       OS << "ControlScope";
00154       Flags &= ~ControlScope;
00155     } else if (Flags & ClassScope) {
00156       OS << "ClassScope";
00157       Flags &= ~ClassScope;
00158     } else if (Flags & BlockScope) {
00159       OS << "BlockScope";
00160       Flags &= ~BlockScope;
00161     } else if (Flags & TemplateParamScope) {
00162       OS << "TemplateParamScope";
00163       Flags &= ~TemplateParamScope;
00164     } else if (Flags & FunctionPrototypeScope) {
00165       OS << "FunctionPrototypeScope";
00166       Flags &= ~FunctionPrototypeScope;
00167     } else if (Flags & FunctionDeclarationScope) {
00168       OS << "FunctionDeclarationScope";
00169       Flags &= ~FunctionDeclarationScope;
00170     } else if (Flags & AtCatchScope) {
00171       OS << "AtCatchScope";
00172       Flags &= ~AtCatchScope;
00173     } else if (Flags & ObjCMethodScope) {
00174       OS << "ObjCMethodScope";
00175       Flags &= ~ObjCMethodScope;
00176     } else if (Flags & SwitchScope) {
00177       OS << "SwitchScope";
00178       Flags &= ~SwitchScope;
00179     } else if (Flags & TryScope) {
00180       OS << "TryScope";
00181       Flags &= ~TryScope;
00182     } else if (Flags & FnTryCatchScope) {
00183       OS << "FnTryCatchScope";
00184       Flags &= ~FnTryCatchScope;
00185     } else if (Flags & SEHTryScope) {
00186       OS << "SEHTryScope";
00187       Flags &= ~SEHTryScope;
00188     } else if (Flags & OpenMPDirectiveScope) {
00189       OS << "OpenMPDirectiveScope";
00190       Flags &= ~OpenMPDirectiveScope;
00191     } else if (Flags & OpenMPLoopDirectiveScope) {
00192       OS << "OpenMPLoopDirectiveScope";
00193       Flags &= ~OpenMPLoopDirectiveScope;
00194     } else if (Flags & OpenMPSimdDirectiveScope) {
00195       OS << "OpenMPSimdDirectiveScope";
00196       Flags &= ~OpenMPSimdDirectiveScope;
00197     }
00198 
00199     if (Flags)
00200       OS << " | ";
00201   }
00202   if (HasFlags)
00203     OS << '\n';
00204 
00205   if (const Scope *Parent = getParent())
00206     OS << "Parent: (clang::Scope*)" << Parent << '\n';
00207 
00208   OS << "Depth: " << Depth << '\n';
00209   OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
00210   if (const DeclContext *DC = getEntity())
00211     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
00212 
00213   if (NRVO.getInt())
00214     OS << "NRVO not allowed";
00215   else if (NRVO.getPointer())
00216     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
00217 }