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 
Init(Scope * parent,unsigned flags)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     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   DeclsInScope.clear();
88   UsingDirectives.clear();
89   Entity = nullptr;
90   ErrorTrap.reset();
91   NRVO.setPointerAndInt(nullptr, 0);
92 }
93 
containedInPrototypeScope() const94 bool Scope::containedInPrototypeScope() const {
95   const Scope *S = this;
96   while (S) {
97     if (S->isFunctionPrototypeScope())
98       return true;
99     S = S->getParent();
100   }
101   return false;
102 }
103 
AddFlags(unsigned FlagsToSet)104 void Scope::AddFlags(unsigned FlagsToSet) {
105   assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
106          "Unsupported scope flags");
107   if (FlagsToSet & BreakScope) {
108     assert((Flags & BreakScope) == 0 && "Already set");
109     BreakParent = this;
110   }
111   if (FlagsToSet & ContinueScope) {
112     assert((Flags & ContinueScope) == 0 && "Already set");
113     ContinueParent = this;
114   }
115   Flags |= FlagsToSet;
116 }
117 
mergeNRVOIntoParent()118 void Scope::mergeNRVOIntoParent() {
119   if (VarDecl *Candidate = NRVO.getPointer()) {
120     if (isDeclScope(Candidate))
121       Candidate->setNRVOVariable(true);
122   }
123 
124   if (getEntity())
125     return;
126 
127   if (NRVO.getInt())
128     getParent()->setNoNRVO();
129   else if (NRVO.getPointer())
130     getParent()->addNRVOCandidate(NRVO.getPointer());
131 }
132 
dump() const133 void Scope::dump() const { dumpImpl(llvm::errs()); }
134 
dumpImpl(raw_ostream & OS) const135 void Scope::dumpImpl(raw_ostream &OS) const {
136   unsigned Flags = getFlags();
137   bool HasFlags = Flags != 0;
138 
139   if (HasFlags)
140     OS << "Flags: ";
141 
142   while (Flags) {
143     if (Flags & FnScope) {
144       OS << "FnScope";
145       Flags &= ~FnScope;
146     } else if (Flags & BreakScope) {
147       OS << "BreakScope";
148       Flags &= ~BreakScope;
149     } else if (Flags & ContinueScope) {
150       OS << "ContinueScope";
151       Flags &= ~ContinueScope;
152     } else if (Flags & DeclScope) {
153       OS << "DeclScope";
154       Flags &= ~DeclScope;
155     } else if (Flags & ControlScope) {
156       OS << "ControlScope";
157       Flags &= ~ControlScope;
158     } else if (Flags & ClassScope) {
159       OS << "ClassScope";
160       Flags &= ~ClassScope;
161     } else if (Flags & BlockScope) {
162       OS << "BlockScope";
163       Flags &= ~BlockScope;
164     } else if (Flags & TemplateParamScope) {
165       OS << "TemplateParamScope";
166       Flags &= ~TemplateParamScope;
167     } else if (Flags & FunctionPrototypeScope) {
168       OS << "FunctionPrototypeScope";
169       Flags &= ~FunctionPrototypeScope;
170     } else if (Flags & FunctionDeclarationScope) {
171       OS << "FunctionDeclarationScope";
172       Flags &= ~FunctionDeclarationScope;
173     } else if (Flags & AtCatchScope) {
174       OS << "AtCatchScope";
175       Flags &= ~AtCatchScope;
176     } else if (Flags & ObjCMethodScope) {
177       OS << "ObjCMethodScope";
178       Flags &= ~ObjCMethodScope;
179     } else if (Flags & SwitchScope) {
180       OS << "SwitchScope";
181       Flags &= ~SwitchScope;
182     } else if (Flags & TryScope) {
183       OS << "TryScope";
184       Flags &= ~TryScope;
185     } else if (Flags & FnTryCatchScope) {
186       OS << "FnTryCatchScope";
187       Flags &= ~FnTryCatchScope;
188     } else if (Flags & SEHTryScope) {
189       OS << "SEHTryScope";
190       Flags &= ~SEHTryScope;
191     } else if (Flags & SEHExceptScope) {
192       OS << "SEHExceptScope";
193       Flags &= ~SEHExceptScope;
194     } else if (Flags & OpenMPDirectiveScope) {
195       OS << "OpenMPDirectiveScope";
196       Flags &= ~OpenMPDirectiveScope;
197     } else if (Flags & OpenMPLoopDirectiveScope) {
198       OS << "OpenMPLoopDirectiveScope";
199       Flags &= ~OpenMPLoopDirectiveScope;
200     } else if (Flags & OpenMPSimdDirectiveScope) {
201       OS << "OpenMPSimdDirectiveScope";
202       Flags &= ~OpenMPSimdDirectiveScope;
203     }
204 
205     if (Flags)
206       OS << " | ";
207   }
208   if (HasFlags)
209     OS << '\n';
210 
211   if (const Scope *Parent = getParent())
212     OS << "Parent: (clang::Scope*)" << Parent << '\n';
213 
214   OS << "Depth: " << Depth << '\n';
215   OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
216   OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
217   if (const DeclContext *DC = getEntity())
218     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
219 
220   if (NRVO.getInt())
221     OS << "NRVO not allowed\n";
222   else if (NRVO.getPointer())
223     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
224 }
225