blob: 5a46ba26d29e5f9a6b6f24ac80d5d678c2294854 [file] [log] [blame]
John McCall8fb0d9d2011-05-01 22:35:37 +00001//===- 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"
Nick Lewyckyd78f92f2014-05-03 00:41:18 +000016#include "clang/AST/Decl.h"
David Majnemer2206bf52014-03-05 08:57:59 +000017#include "llvm/Support/raw_ostream.h"
John McCall8fb0d9d2011-05-01 22:35:37 +000018
19using namespace clang;
20
Akira Hatanaka10aced82016-04-29 02:24:14 +000021void Scope::setFlags(Scope *parent, unsigned flags) {
John McCall8fb0d9d2011-05-01 22:35:37 +000022 AnyParent = parent;
23 Flags = flags;
Richard Smith1002d102012-02-17 01:35:32 +000024
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.
Craig Topperc3ec1492014-05-26 06:22:03 +000031 BreakParent = ContinueParent = nullptr;
Richard Smith1002d102012-02-17 01:35:32 +000032 }
33
John McCall8fb0d9d2011-05-01 22:35:37 +000034 if (parent) {
35 Depth = parent->Depth + 1;
36 PrototypeDepth = parent->PrototypeDepth;
37 PrototypeIndex = 0;
38 FnParent = parent->FnParent;
John McCall8fb0d9d2011-05-01 22:35:37 +000039 BlockParent = parent->BlockParent;
40 TemplateParamParent = parent->TemplateParamParent;
David Majnemera7f8c462015-03-19 21:54:30 +000041 MSLastManglingParent = parent->MSLastManglingParent;
42 MSCurManglingNumber = getMSLastManglingNumber();
Alexander Musmana8e9d2e2014-06-03 10:16:47 +000043 if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
44 FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
45 0)
46 Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
John McCall8fb0d9d2011-05-01 22:35:37 +000047 } else {
48 Depth = 0;
49 PrototypeDepth = 0;
50 PrototypeIndex = 0;
David Majnemera7f8c462015-03-19 21:54:30 +000051 MSLastManglingParent = FnParent = BlockParent = nullptr;
Craig Topperc3ec1492014-05-26 06:22:03 +000052 TemplateParamParent = nullptr;
David Majnemera7f8c462015-03-19 21:54:30 +000053 MSLastManglingNumber = 1;
54 MSCurManglingNumber = 1;
John McCall8fb0d9d2011-05-01 22:35:37 +000055 }
56
57 // If this scope is a function or contains breaks/continues, remember it.
58 if (flags & FnScope) FnParent = this;
David Majnemer2206bf52014-03-05 08:57:59 +000059 // The MS mangler uses the number of scopes that can hold declarations as
60 // part of an external name.
61 if (Flags & (ClassScope | FnScope)) {
David Majnemera7f8c462015-03-19 21:54:30 +000062 MSLastManglingNumber = getMSLastManglingNumber();
63 MSLastManglingParent = this;
64 MSCurManglingNumber = 1;
David Majnemer2206bf52014-03-05 08:57:59 +000065 }
John McCall8fb0d9d2011-05-01 22:35:37 +000066 if (flags & BreakScope) BreakParent = this;
67 if (flags & ContinueScope) ContinueParent = this;
John McCall8fb0d9d2011-05-01 22:35:37 +000068 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++;
Hans Wennborgfe781452014-06-17 00:00:18 +000073
David Majnemer2206bf52014-03-05 08:57:59 +000074 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.
Hans Wennborgfe781452014-06-17 00:00:18 +000081 else if ((flags & EnumScope))
82 ; // Don't increment for enum scopes.
David Majnemer2206bf52014-03-05 08:57:59 +000083 else
David Majnemera7f8c462015-03-19 21:54:30 +000084 incrementMSManglingNumber();
David Majnemer2206bf52014-03-05 08:57:59 +000085 }
Akira Hatanaka10aced82016-04-29 02:24:14 +000086}
87
88void Scope::Init(Scope *parent, unsigned flags) {
89 setFlags(parent, flags);
John McCall8fb0d9d2011-05-01 22:35:37 +000090
91 DeclsInScope.clear();
92 UsingDirectives.clear();
Craig Topperc3ec1492014-05-26 06:22:03 +000093 Entity = nullptr;
John McCall8fb0d9d2011-05-01 22:35:37 +000094 ErrorTrap.reset();
95}
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 Tsuikib000a882018-06-19 04:39:07 +0000121void Scope::setNRVOCandidate(VarDecl *Candidate) {
122 for (Decl *D : DeclsInScope) {
123 VarDecl *VD = dyn_cast<VarDecl>(D);
124 if (VD && VD != Candidate && VD->isNRVOCandidate())
125 VD->setNRVOVariable(false);
Nick Lewyckyd78f92f2014-05-03 00:41:18 +0000126 }
127
Taiju Tsuikib000a882018-06-19 04:39:07 +0000128 if (Scope *parent = getParent())
129 parent->setNRVOCandidate(Candidate);
Nick Lewyckyd78f92f2014-05-03 00:41:18 +0000130}
131
Yaron Kerencdae9412016-01-29 19:38:18 +0000132LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
David Majnemer2206bf52014-03-05 08:57:59 +0000133
134void Scope::dumpImpl(raw_ostream &OS) const {
135 unsigned Flags = getFlags();
136 bool HasFlags = Flags != 0;
137
138 if (HasFlags)
139 OS << "Flags: ";
140
Richard Trieudf5ec072018-01-18 04:28:56 +0000141 std::pair<unsigned, const char *> FlagInfo[] = {
142 {FnScope, "FnScope"},
143 {BreakScope, "BreakScope"},
144 {ContinueScope, "ContinueScope"},
145 {DeclScope, "DeclScope"},
146 {ControlScope, "ControlScope"},
147 {ClassScope, "ClassScope"},
148 {BlockScope, "BlockScope"},
149 {TemplateParamScope, "TemplateParamScope"},
150 {FunctionPrototypeScope, "FunctionPrototypeScope"},
151 {FunctionDeclarationScope, "FunctionDeclarationScope"},
152 {AtCatchScope, "AtCatchScope"},
153 {ObjCMethodScope, "ObjCMethodScope"},
154 {SwitchScope, "SwitchScope"},
155 {TryScope, "TryScope"},
156 {FnTryCatchScope, "FnTryCatchScope"},
157 {OpenMPDirectiveScope, "OpenMPDirectiveScope"},
158 {OpenMPLoopDirectiveScope, "OpenMPLoopDirectiveScope"},
159 {OpenMPSimdDirectiveScope, "OpenMPSimdDirectiveScope"},
160 {EnumScope, "EnumScope"},
161 {SEHTryScope, "SEHTryScope"},
162 {SEHExceptScope, "SEHExceptScope"},
163 {SEHFilterScope, "SEHFilterScope"},
164 {CompoundStmtScope, "CompoundStmtScope"},
165 {ClassInheritanceScope, "ClassInheritanceScope"}};
David Majnemer2206bf52014-03-05 08:57:59 +0000166
Richard Trieudf5ec072018-01-18 04:28:56 +0000167 for (auto Info : FlagInfo) {
168 if (Flags & Info.first) {
169 OS << Info.second;
170 Flags &= ~Info.first;
171 if (Flags)
172 OS << " | ";
173 }
David Majnemer2206bf52014-03-05 08:57:59 +0000174 }
Richard Trieudf5ec072018-01-18 04:28:56 +0000175
176 assert(Flags == 0 && "Unknown scope flags");
177
David Majnemer2206bf52014-03-05 08:57:59 +0000178 if (HasFlags)
179 OS << '\n';
180
181 if (const Scope *Parent = getParent())
182 OS << "Parent: (clang::Scope*)" << Parent << '\n';
183
184 OS << "Depth: " << Depth << '\n';
David Majnemera7f8c462015-03-19 21:54:30 +0000185 OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
186 OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
David Majnemer2206bf52014-03-05 08:57:59 +0000187 if (const DeclContext *DC = getEntity())
188 OS << "Entity : (clang::DeclContext*)" << DC << '\n';
189}