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 "llvm/Support/raw_ostream.h" 17 18 using namespace clang; 19 20 void Scope::Init(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 = 0; 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 MSLocalManglingParent = parent->MSLocalManglingParent; 41 } else { 42 Depth = 0; 43 PrototypeDepth = 0; 44 PrototypeIndex = 0; 45 MSLocalManglingParent = FnParent = BlockParent = 0; 46 TemplateParamParent = 0; 47 MSLocalManglingNumber = 1; 48 } 49 50 // If this scope is a function or contains breaks/continues, remember it. 51 if (flags & FnScope) FnParent = this; 52 // The MS mangler uses the number of scopes that can hold declarations as 53 // part of an external name. 54 if (Flags & (ClassScope | FnScope)) { 55 MSLocalManglingNumber = getMSLocalManglingNumber(); 56 MSLocalManglingParent = this; 57 } 58 if (flags & BreakScope) BreakParent = this; 59 if (flags & ContinueScope) ContinueParent = this; 60 if (flags & BlockScope) BlockParent = this; 61 if (flags & TemplateParamScope) TemplateParamParent = this; 62 63 // If this is a prototype scope, record that. 64 if (flags & FunctionPrototypeScope) PrototypeDepth++; 65 if (flags & DeclScope) { 66 if (flags & FunctionPrototypeScope) 67 ; // Prototype scopes are uninteresting. 68 else if ((flags & ClassScope) && getParent()->isClassScope()) 69 ; // Nested class scopes aren't ambiguous. 70 else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope) 71 ; // Classes inside of namespaces aren't ambiguous. 72 else 73 incrementMSLocalManglingNumber(); 74 } 75 76 DeclsInScope.clear(); 77 UsingDirectives.clear(); 78 Entity = 0; 79 ErrorTrap.reset(); 80 } 81 82 bool Scope::containedInPrototypeScope() const { 83 const Scope *S = this; 84 while (S) { 85 if (S->isFunctionPrototypeScope()) 86 return true; 87 S = S->getParent(); 88 } 89 return false; 90 } 91 92 void Scope::AddFlags(unsigned FlagsToSet) { 93 assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 && 94 "Unsupported scope flags"); 95 if (FlagsToSet & BreakScope) { 96 assert((Flags & BreakScope) == 0 && "Already set"); 97 BreakParent = this; 98 } 99 if (FlagsToSet & ContinueScope) { 100 assert((Flags & ContinueScope) == 0 && "Already set"); 101 ContinueParent = this; 102 } 103 Flags |= FlagsToSet; 104 } 105 106 void Scope::dump() const { dumpImpl(llvm::errs()); } 107 108 void Scope::dumpImpl(raw_ostream &OS) const { 109 unsigned Flags = getFlags(); 110 bool HasFlags = Flags != 0; 111 112 if (HasFlags) 113 OS << "Flags: "; 114 115 while (Flags) { 116 if (Flags & FnScope) { 117 OS << "FnScope"; 118 Flags &= ~FnScope; 119 } else if (Flags & BreakScope) { 120 OS << "BreakScope"; 121 Flags &= ~BreakScope; 122 } else if (Flags & ContinueScope) { 123 OS << "ContinueScope"; 124 Flags &= ~ContinueScope; 125 } else if (Flags & DeclScope) { 126 OS << "DeclScope"; 127 Flags &= ~DeclScope; 128 } else if (Flags & ControlScope) { 129 OS << "ControlScope"; 130 Flags &= ~ControlScope; 131 } else if (Flags & ClassScope) { 132 OS << "ClassScope"; 133 Flags &= ~ClassScope; 134 } else if (Flags & BlockScope) { 135 OS << "BlockScope"; 136 Flags &= ~BlockScope; 137 } else if (Flags & TemplateParamScope) { 138 OS << "TemplateParamScope"; 139 Flags &= ~TemplateParamScope; 140 } else if (Flags & FunctionPrototypeScope) { 141 OS << "FunctionPrototypeScope"; 142 Flags &= ~FunctionPrototypeScope; 143 } else if (Flags & FunctionDeclarationScope) { 144 OS << "FunctionDeclarationScope"; 145 Flags &= ~FunctionDeclarationScope; 146 } else if (Flags & AtCatchScope) { 147 OS << "AtCatchScope"; 148 Flags &= ~AtCatchScope; 149 } else if (Flags & ObjCMethodScope) { 150 OS << "ObjCMethodScope"; 151 Flags &= ~ObjCMethodScope; 152 } else if (Flags & SwitchScope) { 153 OS << "SwitchScope"; 154 Flags &= ~SwitchScope; 155 } else if (Flags & TryScope) { 156 OS << "TryScope"; 157 Flags &= ~TryScope; 158 } else if (Flags & FnTryCatchScope) { 159 OS << "FnTryCatchScope"; 160 Flags &= ~FnTryCatchScope; 161 } else if (Flags & OpenMPDirectiveScope) { 162 OS << "OpenMPDirectiveScope"; 163 Flags &= ~OpenMPDirectiveScope; 164 } 165 166 if (Flags) 167 OS << " | "; 168 } 169 if (HasFlags) 170 OS << '\n'; 171 172 if (const Scope *Parent = getParent()) 173 OS << "Parent: (clang::Scope*)" << Parent << '\n'; 174 175 OS << "Depth: " << Depth << '\n'; 176 OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n'; 177 if (const DeclContext *DC = getEntity()) 178 OS << "Entity : (clang::DeclContext*)" << DC << '\n'; 179 } 180