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