• 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 
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     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 
71   if (flags & DeclScope) {
72     if (flags & FunctionPrototypeScope)
73       ; // Prototype scopes are uninteresting.
74     else if ((flags & ClassScope) && getParent()->isClassScope())
75       ; // Nested class scopes aren't ambiguous.
76     else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
77       ; // Classes inside of namespaces aren't ambiguous.
78     else if ((flags & EnumScope))
79       ; // Don't increment for enum scopes.
80     else
81       incrementMSLocalManglingNumber();
82   }
83 
84   DeclsInScope.clear();
85   UsingDirectives.clear();
86   Entity = nullptr;
87   ErrorTrap.reset();
88   NRVO.setPointerAndInt(nullptr, 0);
89 }
90 
containedInPrototypeScope() const91 bool Scope::containedInPrototypeScope() const {
92   const Scope *S = this;
93   while (S) {
94     if (S->isFunctionPrototypeScope())
95       return true;
96     S = S->getParent();
97   }
98   return false;
99 }
100 
AddFlags(unsigned FlagsToSet)101 void Scope::AddFlags(unsigned FlagsToSet) {
102   assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
103          "Unsupported scope flags");
104   if (FlagsToSet & BreakScope) {
105     assert((Flags & BreakScope) == 0 && "Already set");
106     BreakParent = this;
107   }
108   if (FlagsToSet & ContinueScope) {
109     assert((Flags & ContinueScope) == 0 && "Already set");
110     ContinueParent = this;
111   }
112   Flags |= FlagsToSet;
113 }
114 
mergeNRVOIntoParent()115 void Scope::mergeNRVOIntoParent() {
116   if (VarDecl *Candidate = NRVO.getPointer()) {
117     if (isDeclScope(Candidate))
118       Candidate->setNRVOVariable(true);
119   }
120 
121   if (getEntity())
122     return;
123 
124   if (NRVO.getInt())
125     getParent()->setNoNRVO();
126   else if (NRVO.getPointer())
127     getParent()->addNRVOCandidate(NRVO.getPointer());
128 }
129 
dump() const130 void Scope::dump() const { dumpImpl(llvm::errs()); }
131 
dumpImpl(raw_ostream & OS) const132 void Scope::dumpImpl(raw_ostream &OS) const {
133   unsigned Flags = getFlags();
134   bool HasFlags = Flags != 0;
135 
136   if (HasFlags)
137     OS << "Flags: ";
138 
139   while (Flags) {
140     if (Flags & FnScope) {
141       OS << "FnScope";
142       Flags &= ~FnScope;
143     } else if (Flags & BreakScope) {
144       OS << "BreakScope";
145       Flags &= ~BreakScope;
146     } else if (Flags & ContinueScope) {
147       OS << "ContinueScope";
148       Flags &= ~ContinueScope;
149     } else if (Flags & DeclScope) {
150       OS << "DeclScope";
151       Flags &= ~DeclScope;
152     } else if (Flags & ControlScope) {
153       OS << "ControlScope";
154       Flags &= ~ControlScope;
155     } else if (Flags & ClassScope) {
156       OS << "ClassScope";
157       Flags &= ~ClassScope;
158     } else if (Flags & BlockScope) {
159       OS << "BlockScope";
160       Flags &= ~BlockScope;
161     } else if (Flags & TemplateParamScope) {
162       OS << "TemplateParamScope";
163       Flags &= ~TemplateParamScope;
164     } else if (Flags & FunctionPrototypeScope) {
165       OS << "FunctionPrototypeScope";
166       Flags &= ~FunctionPrototypeScope;
167     } else if (Flags & FunctionDeclarationScope) {
168       OS << "FunctionDeclarationScope";
169       Flags &= ~FunctionDeclarationScope;
170     } else if (Flags & AtCatchScope) {
171       OS << "AtCatchScope";
172       Flags &= ~AtCatchScope;
173     } else if (Flags & ObjCMethodScope) {
174       OS << "ObjCMethodScope";
175       Flags &= ~ObjCMethodScope;
176     } else if (Flags & SwitchScope) {
177       OS << "SwitchScope";
178       Flags &= ~SwitchScope;
179     } else if (Flags & TryScope) {
180       OS << "TryScope";
181       Flags &= ~TryScope;
182     } else if (Flags & FnTryCatchScope) {
183       OS << "FnTryCatchScope";
184       Flags &= ~FnTryCatchScope;
185     } else if (Flags & SEHTryScope) {
186       OS << "SEHTryScope";
187       Flags &= ~SEHTryScope;
188     } else if (Flags & OpenMPDirectiveScope) {
189       OS << "OpenMPDirectiveScope";
190       Flags &= ~OpenMPDirectiveScope;
191     } else if (Flags & OpenMPLoopDirectiveScope) {
192       OS << "OpenMPLoopDirectiveScope";
193       Flags &= ~OpenMPLoopDirectiveScope;
194     } else if (Flags & OpenMPSimdDirectiveScope) {
195       OS << "OpenMPSimdDirectiveScope";
196       Flags &= ~OpenMPSimdDirectiveScope;
197     }
198 
199     if (Flags)
200       OS << " | ";
201   }
202   if (HasFlags)
203     OS << '\n';
204 
205   if (const Scope *Parent = getParent())
206     OS << "Parent: (clang::Scope*)" << Parent << '\n';
207 
208   OS << "Depth: " << Depth << '\n';
209   OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
210   if (const DeclContext *DC = getEntity())
211     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
212 
213   if (NRVO.getInt())
214     OS << "NRVO not allowed";
215   else if (NRVO.getPointer())
216     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
217 }
218