1221339Sdim//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
2221339Sdim//
3221339Sdim//                     The LLVM Compiler Infrastructure
4221339Sdim//
5221339Sdim// This file is distributed under the University of Illinois Open Source
6221339Sdim// License. See LICENSE.TXT for details.
7221339Sdim//
8221339Sdim//===----------------------------------------------------------------------===//
9221339Sdim//
10221339Sdim// This file implements the Scope class, which is used for recording
11221339Sdim// information about a lexical scope.
12221339Sdim//
13221339Sdim//===----------------------------------------------------------------------===//
14221339Sdim
15221339Sdim#include "clang/Sema/Scope.h"
16276479Sdim#include "clang/AST/Decl.h"
17276479Sdim#include "llvm/Support/raw_ostream.h"
18221339Sdim
19221339Sdimusing namespace clang;
20221339Sdim
21221339Sdimvoid Scope::Init(Scope *parent, unsigned flags) {
22221339Sdim  AnyParent = parent;
23221339Sdim  Flags = flags;
24234353Sdim
25234353Sdim  if (parent && !(flags & FnScope)) {
26234353Sdim    BreakParent    = parent->BreakParent;
27234353Sdim    ContinueParent = parent->ContinueParent;
28234353Sdim  } else {
29234353Sdim    // Control scopes do not contain the contents of nested function scopes for
30234353Sdim    // control flow purposes.
31276479Sdim    BreakParent = ContinueParent = nullptr;
32234353Sdim  }
33234353Sdim
34221339Sdim  if (parent) {
35221339Sdim    Depth = parent->Depth + 1;
36221339Sdim    PrototypeDepth = parent->PrototypeDepth;
37221339Sdim    PrototypeIndex = 0;
38221339Sdim    FnParent       = parent->FnParent;
39221339Sdim    BlockParent    = parent->BlockParent;
40221339Sdim    TemplateParamParent = parent->TemplateParamParent;
41288943Sdim    MSLastManglingParent = parent->MSLastManglingParent;
42288943Sdim    MSCurManglingNumber = getMSLastManglingNumber();
43276479Sdim    if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
44276479Sdim                  FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
45276479Sdim        0)
46276479Sdim      Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
47221339Sdim  } else {
48221339Sdim    Depth = 0;
49221339Sdim    PrototypeDepth = 0;
50221339Sdim    PrototypeIndex = 0;
51288943Sdim    MSLastManglingParent = FnParent = BlockParent = nullptr;
52276479Sdim    TemplateParamParent = nullptr;
53288943Sdim    MSLastManglingNumber = 1;
54288943Sdim    MSCurManglingNumber = 1;
55221339Sdim  }
56221339Sdim
57221339Sdim  // If this scope is a function or contains breaks/continues, remember it.
58221339Sdim  if (flags & FnScope)            FnParent = this;
59276479Sdim  // The MS mangler uses the number of scopes that can hold declarations as
60276479Sdim  // part of an external name.
61276479Sdim  if (Flags & (ClassScope | FnScope)) {
62288943Sdim    MSLastManglingNumber = getMSLastManglingNumber();
63288943Sdim    MSLastManglingParent = this;
64288943Sdim    MSCurManglingNumber = 1;
65276479Sdim  }
66221339Sdim  if (flags & BreakScope)         BreakParent = this;
67221339Sdim  if (flags & ContinueScope)      ContinueParent = this;
68221339Sdim  if (flags & BlockScope)         BlockParent = this;
69221339Sdim  if (flags & TemplateParamScope) TemplateParamParent = this;
70221339Sdim
71221339Sdim  // If this is a prototype scope, record that.
72221339Sdim  if (flags & FunctionPrototypeScope) PrototypeDepth++;
73221339Sdim
74276479Sdim  if (flags & DeclScope) {
75276479Sdim    if (flags & FunctionPrototypeScope)
76276479Sdim      ; // Prototype scopes are uninteresting.
77276479Sdim    else if ((flags & ClassScope) && getParent()->isClassScope())
78276479Sdim      ; // Nested class scopes aren't ambiguous.
79276479Sdim    else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
80276479Sdim      ; // Classes inside of namespaces aren't ambiguous.
81276479Sdim    else if ((flags & EnumScope))
82276479Sdim      ; // Don't increment for enum scopes.
83276479Sdim    else
84288943Sdim      incrementMSManglingNumber();
85276479Sdim  }
86276479Sdim
87221339Sdim  DeclsInScope.clear();
88221339Sdim  UsingDirectives.clear();
89276479Sdim  Entity = nullptr;
90221339Sdim  ErrorTrap.reset();
91276479Sdim  NRVO.setPointerAndInt(nullptr, 0);
92221339Sdim}
93234353Sdim
94234353Sdimbool Scope::containedInPrototypeScope() const {
95234353Sdim  const Scope *S = this;
96234353Sdim  while (S) {
97234353Sdim    if (S->isFunctionPrototypeScope())
98234353Sdim      return true;
99234353Sdim    S = S->getParent();
100234353Sdim  }
101234353Sdim  return false;
102234353Sdim}
103276479Sdim
104276479Sdimvoid Scope::AddFlags(unsigned FlagsToSet) {
105276479Sdim  assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
106276479Sdim         "Unsupported scope flags");
107276479Sdim  if (FlagsToSet & BreakScope) {
108276479Sdim    assert((Flags & BreakScope) == 0 && "Already set");
109276479Sdim    BreakParent = this;
110276479Sdim  }
111276479Sdim  if (FlagsToSet & ContinueScope) {
112276479Sdim    assert((Flags & ContinueScope) == 0 && "Already set");
113276479Sdim    ContinueParent = this;
114276479Sdim  }
115276479Sdim  Flags |= FlagsToSet;
116276479Sdim}
117276479Sdim
118276479Sdimvoid Scope::mergeNRVOIntoParent() {
119276479Sdim  if (VarDecl *Candidate = NRVO.getPointer()) {
120276479Sdim    if (isDeclScope(Candidate))
121276479Sdim      Candidate->setNRVOVariable(true);
122276479Sdim  }
123276479Sdim
124276479Sdim  if (getEntity())
125276479Sdim    return;
126276479Sdim
127276479Sdim  if (NRVO.getInt())
128276479Sdim    getParent()->setNoNRVO();
129276479Sdim  else if (NRVO.getPointer())
130276479Sdim    getParent()->addNRVOCandidate(NRVO.getPointer());
131276479Sdim}
132276479Sdim
133276479Sdimvoid Scope::dump() const { dumpImpl(llvm::errs()); }
134276479Sdim
135276479Sdimvoid Scope::dumpImpl(raw_ostream &OS) const {
136276479Sdim  unsigned Flags = getFlags();
137276479Sdim  bool HasFlags = Flags != 0;
138276479Sdim
139276479Sdim  if (HasFlags)
140276479Sdim    OS << "Flags: ";
141276479Sdim
142276479Sdim  while (Flags) {
143276479Sdim    if (Flags & FnScope) {
144276479Sdim      OS << "FnScope";
145276479Sdim      Flags &= ~FnScope;
146276479Sdim    } else if (Flags & BreakScope) {
147276479Sdim      OS << "BreakScope";
148276479Sdim      Flags &= ~BreakScope;
149276479Sdim    } else if (Flags & ContinueScope) {
150276479Sdim      OS << "ContinueScope";
151276479Sdim      Flags &= ~ContinueScope;
152276479Sdim    } else if (Flags & DeclScope) {
153276479Sdim      OS << "DeclScope";
154276479Sdim      Flags &= ~DeclScope;
155276479Sdim    } else if (Flags & ControlScope) {
156276479Sdim      OS << "ControlScope";
157276479Sdim      Flags &= ~ControlScope;
158276479Sdim    } else if (Flags & ClassScope) {
159276479Sdim      OS << "ClassScope";
160276479Sdim      Flags &= ~ClassScope;
161276479Sdim    } else if (Flags & BlockScope) {
162276479Sdim      OS << "BlockScope";
163276479Sdim      Flags &= ~BlockScope;
164276479Sdim    } else if (Flags & TemplateParamScope) {
165276479Sdim      OS << "TemplateParamScope";
166276479Sdim      Flags &= ~TemplateParamScope;
167276479Sdim    } else if (Flags & FunctionPrototypeScope) {
168276479Sdim      OS << "FunctionPrototypeScope";
169276479Sdim      Flags &= ~FunctionPrototypeScope;
170276479Sdim    } else if (Flags & FunctionDeclarationScope) {
171276479Sdim      OS << "FunctionDeclarationScope";
172276479Sdim      Flags &= ~FunctionDeclarationScope;
173276479Sdim    } else if (Flags & AtCatchScope) {
174276479Sdim      OS << "AtCatchScope";
175276479Sdim      Flags &= ~AtCatchScope;
176276479Sdim    } else if (Flags & ObjCMethodScope) {
177276479Sdim      OS << "ObjCMethodScope";
178276479Sdim      Flags &= ~ObjCMethodScope;
179276479Sdim    } else if (Flags & SwitchScope) {
180276479Sdim      OS << "SwitchScope";
181276479Sdim      Flags &= ~SwitchScope;
182276479Sdim    } else if (Flags & TryScope) {
183276479Sdim      OS << "TryScope";
184276479Sdim      Flags &= ~TryScope;
185276479Sdim    } else if (Flags & FnTryCatchScope) {
186276479Sdim      OS << "FnTryCatchScope";
187276479Sdim      Flags &= ~FnTryCatchScope;
188276479Sdim    } else if (Flags & SEHTryScope) {
189276479Sdim      OS << "SEHTryScope";
190276479Sdim      Flags &= ~SEHTryScope;
191288943Sdim    } else if (Flags & SEHExceptScope) {
192288943Sdim      OS << "SEHExceptScope";
193288943Sdim      Flags &= ~SEHExceptScope;
194276479Sdim    } else if (Flags & OpenMPDirectiveScope) {
195276479Sdim      OS << "OpenMPDirectiveScope";
196276479Sdim      Flags &= ~OpenMPDirectiveScope;
197276479Sdim    } else if (Flags & OpenMPLoopDirectiveScope) {
198276479Sdim      OS << "OpenMPLoopDirectiveScope";
199276479Sdim      Flags &= ~OpenMPLoopDirectiveScope;
200276479Sdim    } else if (Flags & OpenMPSimdDirectiveScope) {
201276479Sdim      OS << "OpenMPSimdDirectiveScope";
202276479Sdim      Flags &= ~OpenMPSimdDirectiveScope;
203276479Sdim    }
204276479Sdim
205276479Sdim    if (Flags)
206276479Sdim      OS << " | ";
207276479Sdim  }
208276479Sdim  if (HasFlags)
209276479Sdim    OS << '\n';
210276479Sdim
211276479Sdim  if (const Scope *Parent = getParent())
212276479Sdim    OS << "Parent: (clang::Scope*)" << Parent << '\n';
213276479Sdim
214276479Sdim  OS << "Depth: " << Depth << '\n';
215288943Sdim  OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
216288943Sdim  OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
217276479Sdim  if (const DeclContext *DC = getEntity())
218276479Sdim    OS << "Entity : (clang::DeclContext*)" << DC << '\n';
219276479Sdim
220276479Sdim  if (NRVO.getInt())
221288943Sdim    OS << "NRVO not allowed\n";
222276479Sdim  else if (NRVO.getPointer())
223276479Sdim    OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
224276479Sdim}
225