blob: 494768d66a61ef1314ace86cbdb681e6e78ce9ad [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"
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
20void Scope::Init(Scope *parent, unsigned flags) {
21 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.
30 BreakParent = ContinueParent = 0;
31 }
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 Majnemer2206bf52014-03-05 08:57:59 +000040 MSLocalManglingParent = parent->MSLocalManglingParent;
John McCall8fb0d9d2011-05-01 22:35:37 +000041 } else {
42 Depth = 0;
43 PrototypeDepth = 0;
44 PrototypeIndex = 0;
David Majnemer2206bf52014-03-05 08:57:59 +000045 MSLocalManglingParent = FnParent = BlockParent = 0;
John McCall8fb0d9d2011-05-01 22:35:37 +000046 TemplateParamParent = 0;
David Majnemer2206bf52014-03-05 08:57:59 +000047 MSLocalManglingNumber = 1;
John McCall8fb0d9d2011-05-01 22:35:37 +000048 }
49
50 // If this scope is a function or contains breaks/continues, remember it.
51 if (flags & FnScope) FnParent = this;
David Majnemer2206bf52014-03-05 08:57:59 +000052 // The MS mangler uses the number of scopes that can hold declarations as
53 // part of an external name.
54 if (Flags & (ClassScope | FnScope)) {
55 MSLocalManglingNumber = getMSLocalManglingNumber();
56 MSLocalManglingParent = this;
57 }
John McCall8fb0d9d2011-05-01 22:35:37 +000058 if (flags & BreakScope) BreakParent = this;
59 if (flags & ContinueScope) ContinueParent = this;
John McCall8fb0d9d2011-05-01 22:35:37 +000060 if (flags & BlockScope) BlockParent = this;
61 if (flags & TemplateParamScope) TemplateParamParent = this;
62
63 // If this is a prototype scope, record that.
64 if (flags & FunctionPrototypeScope) PrototypeDepth++;
David Majnemer2206bf52014-03-05 08:57:59 +000065 if (flags & DeclScope) {
66 if (flags & FunctionPrototypeScope)
67 ; // Prototype scopes are uninteresting.
68 else if ((flags & ClassScope) && getParent()->isClassScope())
69 ; // Nested class scopes aren't ambiguous.
70 else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
71 ; // Classes inside of namespaces aren't ambiguous.
72 else
73 incrementMSLocalManglingNumber();
74 }
John McCall8fb0d9d2011-05-01 22:35:37 +000075
76 DeclsInScope.clear();
77 UsingDirectives.clear();
78 Entity = 0;
79 ErrorTrap.reset();
80}
James Molloy6f8780b2012-02-29 10:24:19 +000081
82bool Scope::containedInPrototypeScope() const {
83 const Scope *S = this;
84 while (S) {
85 if (S->isFunctionPrototypeScope())
86 return true;
87 S = S->getParent();
88 }
89 return false;
90}
Serge Pavlov09f99242014-01-23 15:05:00 +000091
92void Scope::AddFlags(unsigned FlagsToSet) {
93 assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
94 "Unsupported scope flags");
95 if (FlagsToSet & BreakScope) {
96 assert((Flags & BreakScope) == 0 && "Already set");
97 BreakParent = this;
98 }
99 if (FlagsToSet & ContinueScope) {
100 assert((Flags & ContinueScope) == 0 && "Already set");
101 ContinueParent = this;
102 }
103 Flags |= FlagsToSet;
104}
105
David Majnemer2206bf52014-03-05 08:57:59 +0000106void Scope::dump() const { dumpImpl(llvm::errs()); }
107
108void Scope::dumpImpl(raw_ostream &OS) const {
109 unsigned Flags = getFlags();
110 bool HasFlags = Flags != 0;
111
112 if (HasFlags)
113 OS << "Flags: ";
114
115 while (Flags) {
116 if (Flags & FnScope) {
117 OS << "FnScope";
118 Flags &= ~FnScope;
119 } else if (Flags & BreakScope) {
120 OS << "BreakScope";
121 Flags &= ~BreakScope;
122 } else if (Flags & ContinueScope) {
123 OS << "ContinueScope";
124 Flags &= ~ContinueScope;
125 } else if (Flags & DeclScope) {
126 OS << "DeclScope";
127 Flags &= ~DeclScope;
128 } else if (Flags & ControlScope) {
129 OS << "ControlScope";
130 Flags &= ~ControlScope;
131 } else if (Flags & ClassScope) {
132 OS << "ClassScope";
133 Flags &= ~ClassScope;
134 } else if (Flags & BlockScope) {
135 OS << "BlockScope";
136 Flags &= ~BlockScope;
137 } else if (Flags & TemplateParamScope) {
138 OS << "TemplateParamScope";
139 Flags &= ~TemplateParamScope;
140 } else if (Flags & FunctionPrototypeScope) {
141 OS << "FunctionPrototypeScope";
142 Flags &= ~FunctionPrototypeScope;
143 } else if (Flags & FunctionDeclarationScope) {
144 OS << "FunctionDeclarationScope";
145 Flags &= ~FunctionDeclarationScope;
146 } else if (Flags & AtCatchScope) {
147 OS << "AtCatchScope";
148 Flags &= ~AtCatchScope;
149 } else if (Flags & ObjCMethodScope) {
150 OS << "ObjCMethodScope";
151 Flags &= ~ObjCMethodScope;
152 } else if (Flags & SwitchScope) {
153 OS << "SwitchScope";
154 Flags &= ~SwitchScope;
155 } else if (Flags & TryScope) {
156 OS << "TryScope";
157 Flags &= ~TryScope;
158 } else if (Flags & FnTryCatchScope) {
159 OS << "FnTryCatchScope";
160 Flags &= ~FnTryCatchScope;
161 } else if (Flags & OpenMPDirectiveScope) {
162 OS << "OpenMPDirectiveScope";
163 Flags &= ~OpenMPDirectiveScope;
164 }
165
166 if (Flags)
167 OS << " | ";
168 }
169 if (HasFlags)
170 OS << '\n';
171
172 if (const Scope *Parent = getParent())
173 OS << "Parent: (clang::Scope*)" << Parent << '\n';
174
175 OS << "Depth: " << Depth << '\n';
176 OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
177 if (const DeclContext *DC = getEntity())
178 OS << "Entity : (clang::DeclContext*)" << DC << '\n';
179}