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