• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
setFlags(Scope * parent,unsigned flags)21 void Scope::setFlags(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 
Init(Scope * parent,unsigned flags)88 void Scope::Init(Scope *parent, unsigned flags) {
89   setFlags(parent, flags);
90 
91   DeclsInScope.clear();
92   UsingDirectives.clear();
93   Entity = nullptr;
94   ErrorTrap.reset();
95   NRVO.setPointerAndInt(nullptr, 0);
96 }
97 
containedInPrototypeScope() const98 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 
AddFlags(unsigned FlagsToSet)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 
mergeNRVOIntoParent()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 
dump() const137 LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
138 
dumpImpl(raw_ostream & OS) const139 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 & SEHExceptScope) {
196       OS << "SEHExceptScope";
197       Flags &= ~SEHExceptScope;
198     } else if (Flags & OpenMPDirectiveScope) {
199       OS << "OpenMPDirectiveScope";
200       Flags &= ~OpenMPDirectiveScope;
201     } else if (Flags & OpenMPLoopDirectiveScope) {
202       OS << "OpenMPLoopDirectiveScope";
203       Flags &= ~OpenMPLoopDirectiveScope;
204     } else if (Flags & OpenMPSimdDirectiveScope) {
205       OS << "OpenMPSimdDirectiveScope";
206       Flags &= ~OpenMPSimdDirectiveScope;
207     }
208 
209     if (Flags)
210       OS << " | ";
211   }
212   if (HasFlags)
213     OS << '\n';
214 
215   if (const Scope *Parent = getParent())
216     OS << "Parent: (clang::Scope*)" << Parent << '\n';
217 
218   OS << "Depth: " << Depth << '\n';
219   OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
220   OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
221   if (const DeclContext *DC = getEntity())
222     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
223 
224   if (NRVO.getInt())
225     OS << "NRVO not allowed\n";
226   else if (NRVO.getPointer())
227     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
228 }
229