xref: /aosp_15_r20/external/clang/lib/Sema/Scope.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file implements the Scope class, which is used for recording
11*67e74705SXin Li // information about a lexical scope.
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li 
15*67e74705SXin Li #include "clang/Sema/Scope.h"
16*67e74705SXin Li #include "clang/AST/Decl.h"
17*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
18*67e74705SXin Li 
19*67e74705SXin Li using namespace clang;
20*67e74705SXin Li 
setFlags(Scope * parent,unsigned flags)21*67e74705SXin Li void Scope::setFlags(Scope *parent, unsigned flags) {
22*67e74705SXin Li   AnyParent = parent;
23*67e74705SXin Li   Flags = flags;
24*67e74705SXin Li 
25*67e74705SXin Li   if (parent && !(flags & FnScope)) {
26*67e74705SXin Li     BreakParent    = parent->BreakParent;
27*67e74705SXin Li     ContinueParent = parent->ContinueParent;
28*67e74705SXin Li   } else {
29*67e74705SXin Li     // Control scopes do not contain the contents of nested function scopes for
30*67e74705SXin Li     // control flow purposes.
31*67e74705SXin Li     BreakParent = ContinueParent = nullptr;
32*67e74705SXin Li   }
33*67e74705SXin Li 
34*67e74705SXin Li   if (parent) {
35*67e74705SXin Li     Depth = parent->Depth + 1;
36*67e74705SXin Li     PrototypeDepth = parent->PrototypeDepth;
37*67e74705SXin Li     PrototypeIndex = 0;
38*67e74705SXin Li     FnParent       = parent->FnParent;
39*67e74705SXin Li     BlockParent    = parent->BlockParent;
40*67e74705SXin Li     TemplateParamParent = parent->TemplateParamParent;
41*67e74705SXin Li     MSLastManglingParent = parent->MSLastManglingParent;
42*67e74705SXin Li     MSCurManglingNumber = getMSLastManglingNumber();
43*67e74705SXin Li     if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
44*67e74705SXin Li                   FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
45*67e74705SXin Li         0)
46*67e74705SXin Li       Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
47*67e74705SXin Li   } else {
48*67e74705SXin Li     Depth = 0;
49*67e74705SXin Li     PrototypeDepth = 0;
50*67e74705SXin Li     PrototypeIndex = 0;
51*67e74705SXin Li     MSLastManglingParent = FnParent = BlockParent = nullptr;
52*67e74705SXin Li     TemplateParamParent = nullptr;
53*67e74705SXin Li     MSLastManglingNumber = 1;
54*67e74705SXin Li     MSCurManglingNumber = 1;
55*67e74705SXin Li   }
56*67e74705SXin Li 
57*67e74705SXin Li   // If this scope is a function or contains breaks/continues, remember it.
58*67e74705SXin Li   if (flags & FnScope)            FnParent = this;
59*67e74705SXin Li   // The MS mangler uses the number of scopes that can hold declarations as
60*67e74705SXin Li   // part of an external name.
61*67e74705SXin Li   if (Flags & (ClassScope | FnScope)) {
62*67e74705SXin Li     MSLastManglingNumber = getMSLastManglingNumber();
63*67e74705SXin Li     MSLastManglingParent = this;
64*67e74705SXin Li     MSCurManglingNumber = 1;
65*67e74705SXin Li   }
66*67e74705SXin Li   if (flags & BreakScope)         BreakParent = this;
67*67e74705SXin Li   if (flags & ContinueScope)      ContinueParent = this;
68*67e74705SXin Li   if (flags & BlockScope)         BlockParent = this;
69*67e74705SXin Li   if (flags & TemplateParamScope) TemplateParamParent = this;
70*67e74705SXin Li 
71*67e74705SXin Li   // If this is a prototype scope, record that.
72*67e74705SXin Li   if (flags & FunctionPrototypeScope) PrototypeDepth++;
73*67e74705SXin Li 
74*67e74705SXin Li   if (flags & DeclScope) {
75*67e74705SXin Li     if (flags & FunctionPrototypeScope)
76*67e74705SXin Li       ; // Prototype scopes are uninteresting.
77*67e74705SXin Li     else if ((flags & ClassScope) && getParent()->isClassScope())
78*67e74705SXin Li       ; // Nested class scopes aren't ambiguous.
79*67e74705SXin Li     else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
80*67e74705SXin Li       ; // Classes inside of namespaces aren't ambiguous.
81*67e74705SXin Li     else if ((flags & EnumScope))
82*67e74705SXin Li       ; // Don't increment for enum scopes.
83*67e74705SXin Li     else
84*67e74705SXin Li       incrementMSManglingNumber();
85*67e74705SXin Li   }
86*67e74705SXin Li }
87*67e74705SXin Li 
Init(Scope * parent,unsigned flags)88*67e74705SXin Li void Scope::Init(Scope *parent, unsigned flags) {
89*67e74705SXin Li   setFlags(parent, flags);
90*67e74705SXin Li 
91*67e74705SXin Li   DeclsInScope.clear();
92*67e74705SXin Li   UsingDirectives.clear();
93*67e74705SXin Li   Entity = nullptr;
94*67e74705SXin Li   ErrorTrap.reset();
95*67e74705SXin Li   NRVO.setPointerAndInt(nullptr, 0);
96*67e74705SXin Li }
97*67e74705SXin Li 
containedInPrototypeScope() const98*67e74705SXin Li bool Scope::containedInPrototypeScope() const {
99*67e74705SXin Li   const Scope *S = this;
100*67e74705SXin Li   while (S) {
101*67e74705SXin Li     if (S->isFunctionPrototypeScope())
102*67e74705SXin Li       return true;
103*67e74705SXin Li     S = S->getParent();
104*67e74705SXin Li   }
105*67e74705SXin Li   return false;
106*67e74705SXin Li }
107*67e74705SXin Li 
AddFlags(unsigned FlagsToSet)108*67e74705SXin Li void Scope::AddFlags(unsigned FlagsToSet) {
109*67e74705SXin Li   assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
110*67e74705SXin Li          "Unsupported scope flags");
111*67e74705SXin Li   if (FlagsToSet & BreakScope) {
112*67e74705SXin Li     assert((Flags & BreakScope) == 0 && "Already set");
113*67e74705SXin Li     BreakParent = this;
114*67e74705SXin Li   }
115*67e74705SXin Li   if (FlagsToSet & ContinueScope) {
116*67e74705SXin Li     assert((Flags & ContinueScope) == 0 && "Already set");
117*67e74705SXin Li     ContinueParent = this;
118*67e74705SXin Li   }
119*67e74705SXin Li   Flags |= FlagsToSet;
120*67e74705SXin Li }
121*67e74705SXin Li 
mergeNRVOIntoParent()122*67e74705SXin Li void Scope::mergeNRVOIntoParent() {
123*67e74705SXin Li   if (VarDecl *Candidate = NRVO.getPointer()) {
124*67e74705SXin Li     if (isDeclScope(Candidate))
125*67e74705SXin Li       Candidate->setNRVOVariable(true);
126*67e74705SXin Li   }
127*67e74705SXin Li 
128*67e74705SXin Li   if (getEntity())
129*67e74705SXin Li     return;
130*67e74705SXin Li 
131*67e74705SXin Li   if (NRVO.getInt())
132*67e74705SXin Li     getParent()->setNoNRVO();
133*67e74705SXin Li   else if (NRVO.getPointer())
134*67e74705SXin Li     getParent()->addNRVOCandidate(NRVO.getPointer());
135*67e74705SXin Li }
136*67e74705SXin Li 
dump() const137*67e74705SXin Li LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
138*67e74705SXin Li 
dumpImpl(raw_ostream & OS) const139*67e74705SXin Li void Scope::dumpImpl(raw_ostream &OS) const {
140*67e74705SXin Li   unsigned Flags = getFlags();
141*67e74705SXin Li   bool HasFlags = Flags != 0;
142*67e74705SXin Li 
143*67e74705SXin Li   if (HasFlags)
144*67e74705SXin Li     OS << "Flags: ";
145*67e74705SXin Li 
146*67e74705SXin Li   while (Flags) {
147*67e74705SXin Li     if (Flags & FnScope) {
148*67e74705SXin Li       OS << "FnScope";
149*67e74705SXin Li       Flags &= ~FnScope;
150*67e74705SXin Li     } else if (Flags & BreakScope) {
151*67e74705SXin Li       OS << "BreakScope";
152*67e74705SXin Li       Flags &= ~BreakScope;
153*67e74705SXin Li     } else if (Flags & ContinueScope) {
154*67e74705SXin Li       OS << "ContinueScope";
155*67e74705SXin Li       Flags &= ~ContinueScope;
156*67e74705SXin Li     } else if (Flags & DeclScope) {
157*67e74705SXin Li       OS << "DeclScope";
158*67e74705SXin Li       Flags &= ~DeclScope;
159*67e74705SXin Li     } else if (Flags & ControlScope) {
160*67e74705SXin Li       OS << "ControlScope";
161*67e74705SXin Li       Flags &= ~ControlScope;
162*67e74705SXin Li     } else if (Flags & ClassScope) {
163*67e74705SXin Li       OS << "ClassScope";
164*67e74705SXin Li       Flags &= ~ClassScope;
165*67e74705SXin Li     } else if (Flags & BlockScope) {
166*67e74705SXin Li       OS << "BlockScope";
167*67e74705SXin Li       Flags &= ~BlockScope;
168*67e74705SXin Li     } else if (Flags & TemplateParamScope) {
169*67e74705SXin Li       OS << "TemplateParamScope";
170*67e74705SXin Li       Flags &= ~TemplateParamScope;
171*67e74705SXin Li     } else if (Flags & FunctionPrototypeScope) {
172*67e74705SXin Li       OS << "FunctionPrototypeScope";
173*67e74705SXin Li       Flags &= ~FunctionPrototypeScope;
174*67e74705SXin Li     } else if (Flags & FunctionDeclarationScope) {
175*67e74705SXin Li       OS << "FunctionDeclarationScope";
176*67e74705SXin Li       Flags &= ~FunctionDeclarationScope;
177*67e74705SXin Li     } else if (Flags & AtCatchScope) {
178*67e74705SXin Li       OS << "AtCatchScope";
179*67e74705SXin Li       Flags &= ~AtCatchScope;
180*67e74705SXin Li     } else if (Flags & ObjCMethodScope) {
181*67e74705SXin Li       OS << "ObjCMethodScope";
182*67e74705SXin Li       Flags &= ~ObjCMethodScope;
183*67e74705SXin Li     } else if (Flags & SwitchScope) {
184*67e74705SXin Li       OS << "SwitchScope";
185*67e74705SXin Li       Flags &= ~SwitchScope;
186*67e74705SXin Li     } else if (Flags & TryScope) {
187*67e74705SXin Li       OS << "TryScope";
188*67e74705SXin Li       Flags &= ~TryScope;
189*67e74705SXin Li     } else if (Flags & FnTryCatchScope) {
190*67e74705SXin Li       OS << "FnTryCatchScope";
191*67e74705SXin Li       Flags &= ~FnTryCatchScope;
192*67e74705SXin Li     } else if (Flags & SEHTryScope) {
193*67e74705SXin Li       OS << "SEHTryScope";
194*67e74705SXin Li       Flags &= ~SEHTryScope;
195*67e74705SXin Li     } else if (Flags & SEHExceptScope) {
196*67e74705SXin Li       OS << "SEHExceptScope";
197*67e74705SXin Li       Flags &= ~SEHExceptScope;
198*67e74705SXin Li     } else if (Flags & OpenMPDirectiveScope) {
199*67e74705SXin Li       OS << "OpenMPDirectiveScope";
200*67e74705SXin Li       Flags &= ~OpenMPDirectiveScope;
201*67e74705SXin Li     } else if (Flags & OpenMPLoopDirectiveScope) {
202*67e74705SXin Li       OS << "OpenMPLoopDirectiveScope";
203*67e74705SXin Li       Flags &= ~OpenMPLoopDirectiveScope;
204*67e74705SXin Li     } else if (Flags & OpenMPSimdDirectiveScope) {
205*67e74705SXin Li       OS << "OpenMPSimdDirectiveScope";
206*67e74705SXin Li       Flags &= ~OpenMPSimdDirectiveScope;
207*67e74705SXin Li     }
208*67e74705SXin Li 
209*67e74705SXin Li     if (Flags)
210*67e74705SXin Li       OS << " | ";
211*67e74705SXin Li   }
212*67e74705SXin Li   if (HasFlags)
213*67e74705SXin Li     OS << '\n';
214*67e74705SXin Li 
215*67e74705SXin Li   if (const Scope *Parent = getParent())
216*67e74705SXin Li     OS << "Parent: (clang::Scope*)" << Parent << '\n';
217*67e74705SXin Li 
218*67e74705SXin Li   OS << "Depth: " << Depth << '\n';
219*67e74705SXin Li   OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
220*67e74705SXin Li   OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
221*67e74705SXin Li   if (const DeclContext *DC = getEntity())
222*67e74705SXin Li     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
223*67e74705SXin Li 
224*67e74705SXin Li   if (NRVO.getInt())
225*67e74705SXin Li     OS << "NRVO not allowed\n";
226*67e74705SXin Li   else if (NRVO.getPointer())
227*67e74705SXin Li     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
228*67e74705SXin Li }
229