1 //===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the Scope class, which is used for recording
10 // information about a lexical scope.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/Sema/Scope.h"
15 #include "clang/AST/Decl.h"
16 #include "llvm/Support/raw_ostream.h"
17
18 using namespace clang;
19
setFlags(Scope * parent,unsigned flags)20 void Scope::setFlags(Scope *parent, unsigned flags) {
21 AnyParent = parent;
22 Flags = flags;
23
24 if (parent && !(flags & FnScope)) {
25 BreakParent = parent->BreakParent;
26 ContinueParent = parent->ContinueParent;
27 } else {
28 // Control scopes do not contain the contents of nested function scopes for
29 // control flow purposes.
30 BreakParent = ContinueParent = nullptr;
31 }
32
33 if (parent) {
34 Depth = parent->Depth + 1;
35 PrototypeDepth = parent->PrototypeDepth;
36 PrototypeIndex = 0;
37 FnParent = parent->FnParent;
38 BlockParent = parent->BlockParent;
39 TemplateParamParent = parent->TemplateParamParent;
40 MSLastManglingParent = parent->MSLastManglingParent;
41 MSCurManglingNumber = getMSLastManglingNumber();
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 MSLastManglingParent = FnParent = BlockParent = nullptr;
51 TemplateParamParent = nullptr;
52 MSLastManglingNumber = 1;
53 MSCurManglingNumber = 1;
54 }
55
56 // If this scope is a function or contains breaks/continues, remember it.
57 if (flags & FnScope) FnParent = this;
58 // The MS mangler uses the number of scopes that can hold declarations as
59 // part of an external name.
60 if (Flags & (ClassScope | FnScope)) {
61 MSLastManglingNumber = getMSLastManglingNumber();
62 MSLastManglingParent = this;
63 MSCurManglingNumber = 1;
64 }
65 if (flags & BreakScope) BreakParent = this;
66 if (flags & ContinueScope) ContinueParent = this;
67 if (flags & BlockScope) BlockParent = this;
68 if (flags & TemplateParamScope) TemplateParamParent = this;
69
70 // If this is a prototype scope, record that.
71 if (flags & FunctionPrototypeScope) PrototypeDepth++;
72
73 if (flags & DeclScope) {
74 if (flags & FunctionPrototypeScope)
75 ; // Prototype scopes are uninteresting.
76 else if ((flags & ClassScope) && getParent()->isClassScope())
77 ; // Nested class scopes aren't ambiguous.
78 else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
79 ; // Classes inside of namespaces aren't ambiguous.
80 else if ((flags & EnumScope))
81 ; // Don't increment for enum scopes.
82 else
83 incrementMSManglingNumber();
84 }
85 }
86
Init(Scope * parent,unsigned flags)87 void Scope::Init(Scope *parent, unsigned flags) {
88 setFlags(parent, flags);
89
90 DeclsInScope.clear();
91 UsingDirectives.clear();
92 Entity = nullptr;
93 ErrorTrap.reset();
94 NRVO.setPointerAndInt(nullptr, 0);
95 }
96
containedInPrototypeScope() const97 bool Scope::containedInPrototypeScope() const {
98 const Scope *S = this;
99 while (S) {
100 if (S->isFunctionPrototypeScope())
101 return true;
102 S = S->getParent();
103 }
104 return false;
105 }
106
AddFlags(unsigned FlagsToSet)107 void Scope::AddFlags(unsigned FlagsToSet) {
108 assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
109 "Unsupported scope flags");
110 if (FlagsToSet & BreakScope) {
111 assert((Flags & BreakScope) == 0 && "Already set");
112 BreakParent = this;
113 }
114 if (FlagsToSet & ContinueScope) {
115 assert((Flags & ContinueScope) == 0 && "Already set");
116 ContinueParent = this;
117 }
118 Flags |= FlagsToSet;
119 }
120
mergeNRVOIntoParent()121 void Scope::mergeNRVOIntoParent() {
122 if (VarDecl *Candidate = NRVO.getPointer()) {
123 if (isDeclScope(Candidate))
124 Candidate->setNRVOVariable(true);
125 }
126
127 if (getEntity())
128 return;
129
130 if (NRVO.getInt())
131 getParent()->setNoNRVO();
132 else if (NRVO.getPointer())
133 getParent()->addNRVOCandidate(NRVO.getPointer());
134 }
135
dump() const136 LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
137
dumpImpl(raw_ostream & OS) const138 void Scope::dumpImpl(raw_ostream &OS) const {
139 unsigned Flags = getFlags();
140 bool HasFlags = Flags != 0;
141
142 if (HasFlags)
143 OS << "Flags: ";
144
145 std::pair<unsigned, const char *> FlagInfo[] = {
146 {FnScope, "FnScope"},
147 {BreakScope, "BreakScope"},
148 {ContinueScope, "ContinueScope"},
149 {DeclScope, "DeclScope"},
150 {ControlScope, "ControlScope"},
151 {ClassScope, "ClassScope"},
152 {BlockScope, "BlockScope"},
153 {TemplateParamScope, "TemplateParamScope"},
154 {FunctionPrototypeScope, "FunctionPrototypeScope"},
155 {FunctionDeclarationScope, "FunctionDeclarationScope"},
156 {AtCatchScope, "AtCatchScope"},
157 {ObjCMethodScope, "ObjCMethodScope"},
158 {SwitchScope, "SwitchScope"},
159 {TryScope, "TryScope"},
160 {FnTryCatchScope, "FnTryCatchScope"},
161 {OpenMPDirectiveScope, "OpenMPDirectiveScope"},
162 {OpenMPLoopDirectiveScope, "OpenMPLoopDirectiveScope"},
163 {OpenMPSimdDirectiveScope, "OpenMPSimdDirectiveScope"},
164 {EnumScope, "EnumScope"},
165 {SEHTryScope, "SEHTryScope"},
166 {SEHExceptScope, "SEHExceptScope"},
167 {SEHFilterScope, "SEHFilterScope"},
168 {CompoundStmtScope, "CompoundStmtScope"},
169 {ClassInheritanceScope, "ClassInheritanceScope"},
170 {CatchScope, "CatchScope"},
171 };
172
173 for (auto Info : FlagInfo) {
174 if (Flags & Info.first) {
175 OS << Info.second;
176 Flags &= ~Info.first;
177 if (Flags)
178 OS << " | ";
179 }
180 }
181
182 assert(Flags == 0 && "Unknown scope flags");
183
184 if (HasFlags)
185 OS << '\n';
186
187 if (const Scope *Parent = getParent())
188 OS << "Parent: (clang::Scope*)" << Parent << '\n';
189
190 OS << "Depth: " << Depth << '\n';
191 OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
192 OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
193 if (const DeclContext *DC = getEntity())
194 OS << "Entity : (clang::DeclContext*)" << DC << '\n';
195
196 if (NRVO.getInt())
197 OS << "NRVO not allowed\n";
198 else if (NRVO.getPointer())
199 OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
200 }
201