]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Sema/Scope.cpp
Vendor import of clang trunk r338150:
[FreeBSD/FreeBSD.git] / lib / Sema / Scope.cpp
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::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
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
98 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
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
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
137 LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
138
139 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   std::pair<unsigned, const char *> FlagInfo[] = {
147       {FnScope, "FnScope"},
148       {BreakScope, "BreakScope"},
149       {ContinueScope, "ContinueScope"},
150       {DeclScope, "DeclScope"},
151       {ControlScope, "ControlScope"},
152       {ClassScope, "ClassScope"},
153       {BlockScope, "BlockScope"},
154       {TemplateParamScope, "TemplateParamScope"},
155       {FunctionPrototypeScope, "FunctionPrototypeScope"},
156       {FunctionDeclarationScope, "FunctionDeclarationScope"},
157       {AtCatchScope, "AtCatchScope"},
158       {ObjCMethodScope, "ObjCMethodScope"},
159       {SwitchScope, "SwitchScope"},
160       {TryScope, "TryScope"},
161       {FnTryCatchScope, "FnTryCatchScope"},
162       {OpenMPDirectiveScope, "OpenMPDirectiveScope"},
163       {OpenMPLoopDirectiveScope, "OpenMPLoopDirectiveScope"},
164       {OpenMPSimdDirectiveScope, "OpenMPSimdDirectiveScope"},
165       {EnumScope, "EnumScope"},
166       {SEHTryScope, "SEHTryScope"},
167       {SEHExceptScope, "SEHExceptScope"},
168       {SEHFilterScope, "SEHFilterScope"},
169       {CompoundStmtScope, "CompoundStmtScope"},
170       {ClassInheritanceScope, "ClassInheritanceScope"}};
171
172   for (auto Info : FlagInfo) {
173     if (Flags & Info.first) {
174       OS << Info.second;
175       Flags &= ~Info.first;
176       if (Flags)
177         OS << " | ";
178     }
179   }
180
181   assert(Flags == 0 && "Unknown scope flags");
182
183   if (HasFlags)
184     OS << '\n';
185
186   if (const Scope *Parent = getParent())
187     OS << "Parent: (clang::Scope*)" << Parent << '\n';
188
189   OS << "Depth: " << Depth << '\n';
190   OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
191   OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
192   if (const DeclContext *DC = getEntity())
193     OS << "Entity : (clang::DeclContext*)" << DC << '\n';
194
195   if (NRVO.getInt())
196     OS << "NRVO not allowed\n";
197   else if (NRVO.getPointer())
198     OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
199 }