1//===- 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"
16#include "clang/AST/Decl.h"
17#include "llvm/Support/raw_ostream.h"
18
19using namespace clang;
20
21void Scope::Init(Scope *parent, unsigned flags) {
22  AnyParent = parent;
23  Flags = flags;
24
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 = nullptr;
32  }
33
34  if (parent) {
35    Depth = parent->Depth + 1;
36    PrototypeDepth = parent->PrototypeDepth;
37    PrototypeIndex = 0;
38    FnParent       = parent->FnParent;
39    BlockParent    = parent->BlockParent;
40    TemplateParamParent = parent->TemplateParamParent;
41    MSLocalManglingParent = parent->MSLocalManglingParent;
42    if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
43                  FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
44        0)
45      Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
46  } else {
47    Depth = 0;
48    PrototypeDepth = 0;
49    PrototypeIndex = 0;
50    MSLocalManglingParent = FnParent = BlockParent = nullptr;
51    TemplateParamParent = nullptr;
52    MSLocalManglingNumber = 1;
53  }
54
55  // If this scope is a function or contains breaks/continues, remember it.
56  if (flags & FnScope)            FnParent = this;
57  // The MS mangler uses the number of scopes that can hold declarations as
58  // part of an external name.
59  if (Flags & (ClassScope | FnScope)) {
60    MSLocalManglingNumber = getMSLocalManglingNumber();
61    MSLocalManglingParent = this;
62  }
63  if (flags & BreakScope)         BreakParent = this;
64  if (flags & ContinueScope)      ContinueParent = this;
65  if (flags & BlockScope)         BlockParent = this;
66  if (flags & TemplateParamScope) TemplateParamParent = this;
67
68  // If this is a prototype scope, record that.
69  if (flags & FunctionPrototypeScope) PrototypeDepth++;
70
71  if (flags & DeclScope) {
72    if (flags & FunctionPrototypeScope)
73      ; // Prototype scopes are uninteresting.
74    else if ((flags & ClassScope) && getParent()->isClassScope())
75      ; // Nested class scopes aren't ambiguous.
76    else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
77      ; // Classes inside of namespaces aren't ambiguous.
78    else if ((flags & EnumScope))
79      ; // Don't increment for enum scopes.
80    else
81      incrementMSLocalManglingNumber();
82  }
83
84  DeclsInScope.clear();
85  UsingDirectives.clear();
86  Entity = nullptr;
87  ErrorTrap.reset();
88  NRVO.setPointerAndInt(nullptr, 0);
89}
90
91bool Scope::containedInPrototypeScope() const {
92  const Scope *S = this;
93  while (S) {
94    if (S->isFunctionPrototypeScope())
95      return true;
96    S = S->getParent();
97  }
98  return false;
99}
100
101void Scope::AddFlags(unsigned FlagsToSet) {
102  assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
103         "Unsupported scope flags");
104  if (FlagsToSet & BreakScope) {
105    assert((Flags & BreakScope) == 0 && "Already set");
106    BreakParent = this;
107  }
108  if (FlagsToSet & ContinueScope) {
109    assert((Flags & ContinueScope) == 0 && "Already set");
110    ContinueParent = this;
111  }
112  Flags |= FlagsToSet;
113}
114
115void Scope::mergeNRVOIntoParent() {
116  if (VarDecl *Candidate = NRVO.getPointer()) {
117    if (isDeclScope(Candidate))
118      Candidate->setNRVOVariable(true);
119  }
120
121  if (getEntity())
122    return;
123
124  if (NRVO.getInt())
125    getParent()->setNoNRVO();
126  else if (NRVO.getPointer())
127    getParent()->addNRVOCandidate(NRVO.getPointer());
128}
129
130void Scope::dump() const { dumpImpl(llvm::errs()); }
131
132void Scope::dumpImpl(raw_ostream &OS) const {
133  unsigned Flags = getFlags();
134  bool HasFlags = Flags != 0;
135
136  if (HasFlags)
137    OS << "Flags: ";
138
139  while (Flags) {
140    if (Flags & FnScope) {
141      OS << "FnScope";
142      Flags &= ~FnScope;
143    } else if (Flags & BreakScope) {
144      OS << "BreakScope";
145      Flags &= ~BreakScope;
146    } else if (Flags & ContinueScope) {
147      OS << "ContinueScope";
148      Flags &= ~ContinueScope;
149    } else if (Flags & DeclScope) {
150      OS << "DeclScope";
151      Flags &= ~DeclScope;
152    } else if (Flags & ControlScope) {
153      OS << "ControlScope";
154      Flags &= ~ControlScope;
155    } else if (Flags & ClassScope) {
156      OS << "ClassScope";
157      Flags &= ~ClassScope;
158    } else if (Flags & BlockScope) {
159      OS << "BlockScope";
160      Flags &= ~BlockScope;
161    } else if (Flags & TemplateParamScope) {
162      OS << "TemplateParamScope";
163      Flags &= ~TemplateParamScope;
164    } else if (Flags & FunctionPrototypeScope) {
165      OS << "FunctionPrototypeScope";
166      Flags &= ~FunctionPrototypeScope;
167    } else if (Flags & FunctionDeclarationScope) {
168      OS << "FunctionDeclarationScope";
169      Flags &= ~FunctionDeclarationScope;
170    } else if (Flags & AtCatchScope) {
171      OS << "AtCatchScope";
172      Flags &= ~AtCatchScope;
173    } else if (Flags & ObjCMethodScope) {
174      OS << "ObjCMethodScope";
175      Flags &= ~ObjCMethodScope;
176    } else if (Flags & SwitchScope) {
177      OS << "SwitchScope";
178      Flags &= ~SwitchScope;
179    } else if (Flags & TryScope) {
180      OS << "TryScope";
181      Flags &= ~TryScope;
182    } else if (Flags & FnTryCatchScope) {
183      OS << "FnTryCatchScope";
184      Flags &= ~FnTryCatchScope;
185    } else if (Flags & SEHTryScope) {
186      OS << "SEHTryScope";
187      Flags &= ~SEHTryScope;
188    } else if (Flags & OpenMPDirectiveScope) {
189      OS << "OpenMPDirectiveScope";
190      Flags &= ~OpenMPDirectiveScope;
191    } else if (Flags & OpenMPLoopDirectiveScope) {
192      OS << "OpenMPLoopDirectiveScope";
193      Flags &= ~OpenMPLoopDirectiveScope;
194    } else if (Flags & OpenMPSimdDirectiveScope) {
195      OS << "OpenMPSimdDirectiveScope";
196      Flags &= ~OpenMPSimdDirectiveScope;
197    }
198
199    if (Flags)
200      OS << " | ";
201  }
202  if (HasFlags)
203    OS << '\n';
204
205  if (const Scope *Parent = getParent())
206    OS << "Parent: (clang::Scope*)" << Parent << '\n';
207
208  OS << "Depth: " << Depth << '\n';
209  OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
210  if (const DeclContext *DC = getEntity())
211    OS << "Entity : (clang::DeclContext*)" << DC << '\n';
212
213  if (NRVO.getInt())
214    OS << "NRVO not allowed";
215  else if (NRVO.getPointer())
216    OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
217}
218