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
setFlags(Scope * parent,unsigned flags)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
Init(Scope * parent,unsigned flags)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
containedInPrototypeScope() const98 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
AddFlags(unsigned FlagsToSet)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
mergeNRVOIntoParent()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
dump() const137 LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
138
dumpImpl(raw_ostream & OS) const139 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 }
200