blob: 09940688efaf04ecaabaa8d3391caffa632d2315 [file] [log] [blame]
John McCall8fb0d9d2011-05-01 22:35:37 +00001//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
John McCall8fb0d9d2011-05-01 22:35:37 +00006//
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"
Nick Lewyckyd78f92f2014-05-03 00:41:18 +000015#include "clang/AST/Decl.h"
David Majnemer2206bf52014-03-05 08:57:59 +000016#include "llvm/Support/raw_ostream.h"
John McCall8fb0d9d2011-05-01 22:35:37 +000017
18using namespace clang;
19
Akira Hatanaka10aced82016-04-29 02:24:14 +000020void Scope::setFlags(Scope *parent, unsigned flags) {
John McCall8fb0d9d2011-05-01 22:35:37 +000021 AnyParent = parent;
22 Flags = flags;
Richard Smith1002d102012-02-17 01:35:32 +000023
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.
Craig Topperc3ec1492014-05-26 06:22:03 +000030 BreakParent = ContinueParent = nullptr;
Richard Smith1002d102012-02-17 01:35:32 +000031 }
32
John McCall8fb0d9d2011-05-01 22:35:37 +000033 if (parent) {
34 Depth = parent->Depth + 1;
35 PrototypeDepth = parent->PrototypeDepth;
36 PrototypeIndex = 0;
37 FnParent = parent->FnParent;
John McCall8fb0d9d2011-05-01 22:35:37 +000038 BlockParent = parent->BlockParent;
39 TemplateParamParent = parent->TemplateParamParent;
David Majnemera7f8c462015-03-19 21:54:30 +000040 MSLastManglingParent = parent->MSLastManglingParent;
41 MSCurManglingNumber = getMSLastManglingNumber();
Alexander Musmana8e9d2e2014-06-03 10:16:47 +000042 if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
43 FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
44 0)
45 Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
John McCall8fb0d9d2011-05-01 22:35:37 +000046 } else {
47 Depth = 0;
48 PrototypeDepth = 0;
49 PrototypeIndex = 0;
David Majnemera7f8c462015-03-19 21:54:30 +000050 MSLastManglingParent = FnParent = BlockParent = nullptr;
Craig Topperc3ec1492014-05-26 06:22:03 +000051 TemplateParamParent = nullptr;
David Majnemera7f8c462015-03-19 21:54:30 +000052 MSLastManglingNumber = 1;
53 MSCurManglingNumber = 1;
John McCall8fb0d9d2011-05-01 22:35:37 +000054 }
55
56 // If this scope is a function or contains breaks/continues, remember it.
57 if (flags & FnScope) FnParent = this;
David Majnemer2206bf52014-03-05 08:57:59 +000058 // The MS mangler uses the number of scopes that can hold declarations as
59 // part of an external name.
60 if (Flags & (ClassScope | FnScope)) {
David Majnemera7f8c462015-03-19 21:54:30 +000061 MSLastManglingNumber = getMSLastManglingNumber();
62 MSLastManglingParent = this;
63 MSCurManglingNumber = 1;
David Majnemer2206bf52014-03-05 08:57:59 +000064 }
John McCall8fb0d9d2011-05-01 22:35:37 +000065 if (flags & BreakScope) BreakParent = this;
66 if (flags & ContinueScope) ContinueParent = this;
John McCall8fb0d9d2011-05-01 22:35:37 +000067 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++;
Hans Wennborgfe781452014-06-17 00:00:18 +000072
David Majnemer2206bf52014-03-05 08:57:59 +000073 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.
Hans Wennborgfe781452014-06-17 00:00:18 +000080 else if ((flags & EnumScope))
81 ; // Don't increment for enum scopes.
David Majnemer2206bf52014-03-05 08:57:59 +000082 else
David Majnemera7f8c462015-03-19 21:54:30 +000083 incrementMSManglingNumber();
David Majnemer2206bf52014-03-05 08:57:59 +000084 }
Akira Hatanaka10aced82016-04-29 02:24:14 +000085}
86
87void Scope::Init(Scope *parent, unsigned flags) {
88 setFlags(parent, flags);
John McCall8fb0d9d2011-05-01 22:35:37 +000089
90 DeclsInScope.clear();
91 UsingDirectives.clear();
Craig Topperc3ec1492014-05-26 06:22:03 +000092 Entity = nullptr;
John McCall8fb0d9d2011-05-01 22:35:37 +000093 ErrorTrap.reset();
Taiju Tsuiki3be68e12018-06-19 05:35:30 +000094 NRVO.setPointerAndInt(nullptr, 0);
John McCall8fb0d9d2011-05-01 22:35:37 +000095}
James Molloy6f8780b2012-02-29 10:24:19 +000096
97bool 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}
Serge Pavlov09f99242014-01-23 15:05:00 +0000106
107void 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
Taiju Tsuiki3be68e12018-06-19 05:35:30 +0000121void Scope::mergeNRVOIntoParent() {
122 if (VarDecl *Candidate = NRVO.getPointer()) {
123 if (isDeclScope(Candidate))
124 Candidate->setNRVOVariable(true);
Nick Lewyckyd78f92f2014-05-03 00:41:18 +0000125 }
126
Taiju Tsuiki3be68e12018-06-19 05:35:30 +0000127 if (getEntity())
128 return;
129
130 if (NRVO.getInt())
131 getParent()->setNoNRVO();
132 else if (NRVO.getPointer())
133 getParent()->addNRVOCandidate(NRVO.getPointer());
Nick Lewyckyd78f92f2014-05-03 00:41:18 +0000134}
135
Yaron Kerencdae9412016-01-29 19:38:18 +0000136LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
David Majnemer2206bf52014-03-05 08:57:59 +0000137
138void Scope::dumpImpl(raw_ostream &OS) const {
139 unsigned Flags = getFlags();
140 bool HasFlags = Flags != 0;
141
142 if (HasFlags)
143 OS << "Flags: ";
144
Richard Trieudf5ec072018-01-18 04:28:56 +0000145 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"}};
David Majnemer2206bf52014-03-05 08:57:59 +0000170
Richard Trieudf5ec072018-01-18 04:28:56 +0000171 for (auto Info : FlagInfo) {
172 if (Flags & Info.first) {
173 OS << Info.second;
174 Flags &= ~Info.first;
175 if (Flags)
176 OS << " | ";
177 }
David Majnemer2206bf52014-03-05 08:57:59 +0000178 }
Richard Trieudf5ec072018-01-18 04:28:56 +0000179
180 assert(Flags == 0 && "Unknown scope flags");
181
David Majnemer2206bf52014-03-05 08:57:59 +0000182 if (HasFlags)
183 OS << '\n';
184
185 if (const Scope *Parent = getParent())
186 OS << "Parent: (clang::Scope*)" << Parent << '\n';
187
188 OS << "Depth: " << Depth << '\n';
David Majnemera7f8c462015-03-19 21:54:30 +0000189 OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
190 OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
David Majnemer2206bf52014-03-05 08:57:59 +0000191 if (const DeclContext *DC = getEntity())
192 OS << "Entity : (clang::DeclContext*)" << DC << '\n';
Taiju Tsuiki3be68e12018-06-19 05:35:30 +0000193
194 if (NRVO.getInt())
195 OS << "NRVO not allowed\n";
196 else if (NRVO.getPointer())
197 OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
David Majnemer2206bf52014-03-05 08:57:59 +0000198}