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