1 //===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the Scope class, which is used for recording
10 // information about a lexical scope.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Sema/Scope.h"
15 #include "clang/AST/Decl.h"
16 #include "llvm/Support/raw_ostream.h"
18 using namespace clang;
20 void Scope::setFlags(Scope *parent, unsigned flags) {
24 if (parent && !(flags & FnScope)) {
25 BreakParent = parent->BreakParent;
26 ContinueParent = parent->ContinueParent;
28 // Control scopes do not contain the contents of nested function scopes for
29 // control flow purposes.
30 BreakParent = ContinueParent = nullptr;
34 Depth = parent->Depth + 1;
35 PrototypeDepth = parent->PrototypeDepth;
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)) ==
45 Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
50 MSLastManglingParent = FnParent = BlockParent = nullptr;
51 TemplateParamParent = nullptr;
52 MSLastManglingNumber = 1;
53 MSCurManglingNumber = 1;
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;
65 if (flags & BreakScope) BreakParent = this;
66 if (flags & ContinueScope) ContinueParent = this;
67 if (flags & BlockScope) BlockParent = this;
68 if (flags & TemplateParamScope) TemplateParamParent = this;
70 // If this is a prototype scope, record that.
71 if (flags & FunctionPrototypeScope) PrototypeDepth++;
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.
83 incrementMSManglingNumber();
87 void Scope::Init(Scope *parent, unsigned flags) {
88 setFlags(parent, flags);
91 UsingDirectives.clear();
94 NRVO.setPointerAndInt(nullptr, 0);
97 bool Scope::containedInPrototypeScope() const {
98 const Scope *S = this;
100 if (S->isFunctionPrototypeScope())
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");
114 if (FlagsToSet & ContinueScope) {
115 assert((Flags & ContinueScope) == 0 && "Already set");
116 ContinueParent = this;
121 void Scope::mergeNRVOIntoParent() {
122 if (VarDecl *Candidate = NRVO.getPointer()) {
123 if (isDeclScope(Candidate))
124 Candidate->setNRVOVariable(true);
131 getParent()->setNoNRVO();
132 else if (NRVO.getPointer())
133 getParent()->addNRVOCandidate(NRVO.getPointer());
136 LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
138 void Scope::dumpImpl(raw_ostream &OS) const {
139 unsigned Flags = getFlags();
140 bool HasFlags = Flags != 0;
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"},
173 for (auto Info : FlagInfo) {
174 if (Flags & Info.first) {
176 Flags &= ~Info.first;
182 assert(Flags == 0 && "Unknown scope flags");
187 if (const Scope *Parent = getParent())
188 OS << "Parent: (clang::Scope*)" << Parent << '\n';
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';
197 OS << "NRVO not allowed\n";
198 else if (NRVO.getPointer())
199 OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';