blob: 8e339d705fb7f2ac937df6428e1088774a1ed7f5 [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
21void Scope::Init(Scope *parent, unsigned flags) {
22 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.
31 BreakParent = ContinueParent = 0;
32 }
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 Majnemer2206bf52014-03-05 08:57:59 +000041 MSLocalManglingParent = parent->MSLocalManglingParent;
John McCall8fb0d9d2011-05-01 22:35:37 +000042 } else {
43 Depth = 0;
44 PrototypeDepth = 0;
45 PrototypeIndex = 0;
David Majnemer2206bf52014-03-05 08:57:59 +000046 MSLocalManglingParent = FnParent = BlockParent = 0;
John McCall8fb0d9d2011-05-01 22:35:37 +000047 TemplateParamParent = 0;
David Majnemer2206bf52014-03-05 08:57:59 +000048 MSLocalManglingNumber = 1;
John McCall8fb0d9d2011-05-01 22:35:37 +000049 }
50
51 // If this scope is a function or contains breaks/continues, remember it.
52 if (flags & FnScope) FnParent = this;
David Majnemer2206bf52014-03-05 08:57:59 +000053 // The MS mangler uses the number of scopes that can hold declarations as
54 // part of an external name.
55 if (Flags & (ClassScope | FnScope)) {
56 MSLocalManglingNumber = getMSLocalManglingNumber();
57 MSLocalManglingParent = this;
58 }
John McCall8fb0d9d2011-05-01 22:35:37 +000059 if (flags & BreakScope) BreakParent = this;
60 if (flags & ContinueScope) ContinueParent = this;
John McCall8fb0d9d2011-05-01 22:35:37 +000061 if (flags & BlockScope) BlockParent = this;
62 if (flags & TemplateParamScope) TemplateParamParent = this;
63
64 // If this is a prototype scope, record that.
65 if (flags & FunctionPrototypeScope) PrototypeDepth++;
David Majnemer2206bf52014-03-05 08:57:59 +000066 if (flags & DeclScope) {
67 if (flags & FunctionPrototypeScope)
68 ; // Prototype scopes are uninteresting.
69 else if ((flags & ClassScope) && getParent()->isClassScope())
70 ; // Nested class scopes aren't ambiguous.
71 else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
72 ; // Classes inside of namespaces aren't ambiguous.
73 else
74 incrementMSLocalManglingNumber();
75 }
John McCall8fb0d9d2011-05-01 22:35:37 +000076
77 DeclsInScope.clear();
78 UsingDirectives.clear();
79 Entity = 0;
80 ErrorTrap.reset();
Nick Lewyckyd78f92f2014-05-03 00:41:18 +000081 NRVO.setPointerAndInt(nullptr, 0);
John McCall8fb0d9d2011-05-01 22:35:37 +000082}
James Molloy6f8780b2012-02-29 10:24:19 +000083
84bool Scope::containedInPrototypeScope() const {
85 const Scope *S = this;
86 while (S) {
87 if (S->isFunctionPrototypeScope())
88 return true;
89 S = S->getParent();
90 }
91 return false;
92}
Serge Pavlov09f99242014-01-23 15:05:00 +000093
94void Scope::AddFlags(unsigned FlagsToSet) {
95 assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
96 "Unsupported scope flags");
97 if (FlagsToSet & BreakScope) {
98 assert((Flags & BreakScope) == 0 && "Already set");
99 BreakParent = this;
100 }
101 if (FlagsToSet & ContinueScope) {
102 assert((Flags & ContinueScope) == 0 && "Already set");
103 ContinueParent = this;
104 }
105 Flags |= FlagsToSet;
106}
107
Nick Lewyckyd78f92f2014-05-03 00:41:18 +0000108void Scope::mergeNRVOIntoParent() {
109 if (VarDecl *Candidate = NRVO.getPointer()) {
110 if (isDeclScope(Candidate))
111 Candidate->setNRVOVariable(true);
112 }
113
114 if (getEntity())
115 return;
116
117 if (NRVO.getInt())
118 getParent()->setNoNRVO();
119 else if (NRVO.getPointer())
120 getParent()->addNRVOCandidate(NRVO.getPointer());
121}
122
David Majnemer2206bf52014-03-05 08:57:59 +0000123void Scope::dump() const { dumpImpl(llvm::errs()); }
124
125void Scope::dumpImpl(raw_ostream &OS) const {
126 unsigned Flags = getFlags();
127 bool HasFlags = Flags != 0;
128
129 if (HasFlags)
130 OS << "Flags: ";
131
132 while (Flags) {
133 if (Flags & FnScope) {
134 OS << "FnScope";
135 Flags &= ~FnScope;
136 } else if (Flags & BreakScope) {
137 OS << "BreakScope";
138 Flags &= ~BreakScope;
139 } else if (Flags & ContinueScope) {
140 OS << "ContinueScope";
141 Flags &= ~ContinueScope;
142 } else if (Flags & DeclScope) {
143 OS << "DeclScope";
144 Flags &= ~DeclScope;
145 } else if (Flags & ControlScope) {
146 OS << "ControlScope";
147 Flags &= ~ControlScope;
148 } else if (Flags & ClassScope) {
149 OS << "ClassScope";
150 Flags &= ~ClassScope;
151 } else if (Flags & BlockScope) {
152 OS << "BlockScope";
153 Flags &= ~BlockScope;
154 } else if (Flags & TemplateParamScope) {
155 OS << "TemplateParamScope";
156 Flags &= ~TemplateParamScope;
157 } else if (Flags & FunctionPrototypeScope) {
158 OS << "FunctionPrototypeScope";
159 Flags &= ~FunctionPrototypeScope;
160 } else if (Flags & FunctionDeclarationScope) {
161 OS << "FunctionDeclarationScope";
162 Flags &= ~FunctionDeclarationScope;
163 } else if (Flags & AtCatchScope) {
164 OS << "AtCatchScope";
165 Flags &= ~AtCatchScope;
166 } else if (Flags & ObjCMethodScope) {
167 OS << "ObjCMethodScope";
168 Flags &= ~ObjCMethodScope;
169 } else if (Flags & SwitchScope) {
170 OS << "SwitchScope";
171 Flags &= ~SwitchScope;
172 } else if (Flags & TryScope) {
173 OS << "TryScope";
174 Flags &= ~TryScope;
175 } else if (Flags & FnTryCatchScope) {
176 OS << "FnTryCatchScope";
177 Flags &= ~FnTryCatchScope;
178 } else if (Flags & OpenMPDirectiveScope) {
179 OS << "OpenMPDirectiveScope";
180 Flags &= ~OpenMPDirectiveScope;
181 }
182
183 if (Flags)
184 OS << " | ";
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 << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
194 if (const DeclContext *DC = getEntity())
195 OS << "Entity : (clang::DeclContext*)" << DC << '\n';
Nick Lewyckyd78f92f2014-05-03 00:41:18 +0000196
197 if (NRVO.getInt())
198 OS << "NRVO not allowed";
199 else if (NRVO.getPointer())
200 OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
David Majnemer2206bf52014-03-05 08:57:59 +0000201}