1//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the Scope class, which is used for recording
10// information about a lexical scope.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Sema/Scope.h"
15#include "clang/AST/Decl.h"
16#include "llvm/Support/raw_ostream.h"
17
18using namespace clang;
19
20void Scope::setFlags(Scope *parent, unsigned flags) {
21  AnyParent = parent;
22  Flags = flags;
23
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 = nullptr;
31  }
32
33  if (parent) {
34    Depth = parent->Depth + 1;
35    PrototypeDepth = parent->PrototypeDepth;
36    PrototypeIndex = 0;
37    FnParent       = parent->FnParent;
38    BlockParent    = parent->BlockParent;
39    TemplateParamParent = parent->TemplateParamParent;
40    MSLastManglingParent = parent->MSLastManglingParent;
41    MSCurManglingNumber = getMSLastManglingNumber();
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    MSLastManglingParent = FnParent = BlockParent = nullptr;
51    TemplateParamParent = nullptr;
52    MSLastManglingNumber = 1;
53    MSCurManglingNumber = 1;
54  }
55
56  // If this scope is a function or contains breaks/continues, remember it.
57  if (flags & FnScope)            FnParent = this;
58  // The MS mangler uses the number of scopes that can hold declarations as
59  // part of an external name.
60  if (Flags & (ClassScope | FnScope)) {
61    MSLastManglingNumber = getMSLastManglingNumber();
62    MSLastManglingParent = this;
63    MSCurManglingNumber = 1;
64  }
65  if (flags & BreakScope)         BreakParent = this;
66  if (flags & ContinueScope)      ContinueParent = this;
67  if (flags & BlockScope)         BlockParent = this;
68  if (flags & TemplateParamScope) TemplateParamParent = this;
69
70  // If this is a prototype scope, record that.
71  if (flags & FunctionPrototypeScope) PrototypeDepth++;
72
73  if (flags & DeclScope) {
74    if (flags & FunctionPrototypeScope)
75      ; // Prototype scopes are uninteresting.
76    else if ((flags & ClassScope) && getParent()->isClassScope())
77      ; // Nested class scopes aren't ambiguous.
78    else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
79      ; // Classes inside of namespaces aren't ambiguous.
80    else if ((flags & EnumScope))
81      ; // Don't increment for enum scopes.
82    else
83      incrementMSManglingNumber();
84  }
85}
86
87void Scope::Init(Scope *parent, unsigned flags) {
88  setFlags(parent, flags);
89
90  DeclsInScope.clear();
91  UsingDirectives.clear();
92  Entity = nullptr;
93  ErrorTrap.reset();
94  NRVO.setPointerAndInt(nullptr, 0);
95}
96
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}
106
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
121void Scope::mergeNRVOIntoParent() {
122  if (VarDecl *Candidate = NRVO.getPointer()) {
123    if (isDeclScope(Candidate))
124      Candidate->setNRVOVariable(true);
125  }
126
127  if (getEntity())
128    return;
129
130  if (NRVO.getInt())
131    getParent()->setNoNRVO();
132  else if (NRVO.getPointer())
133    getParent()->addNRVOCandidate(NRVO.getPointer());
134}
135
136LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
137
138void Scope::dumpImpl(raw_ostream &OS) const {
139  unsigned Flags = getFlags();
140  bool HasFlags = Flags != 0;
141
142  if (HasFlags)
143    OS << "Flags: ";
144
145  std::pair<unsigned, const char *> FlagInfo[] = {
146      {FnScope, "FnScope"},
147      {BreakScope, "BreakScope"},
148      {ContinueScope, "ContinueScope"},
149      {DeclScope, "DeclScope"},
150      {ControlScope, "ControlScope"},
151      {ClassScope, "ClassScope"},
152      {BlockScope, "BlockScope"},
153      {TemplateParamScope, "TemplateParamScope"},
154      {FunctionPrototypeScope, "FunctionPrototypeScope"},
155      {FunctionDeclarationScope, "FunctionDeclarationScope"},
156      {AtCatchScope, "AtCatchScope"},
157      {ObjCMethodScope, "ObjCMethodScope"},
158      {SwitchScope, "SwitchScope"},
159      {TryScope, "TryScope"},
160      {FnTryCatchScope, "FnTryCatchScope"},
161      {OpenMPDirectiveScope, "OpenMPDirectiveScope"},
162      {OpenMPLoopDirectiveScope, "OpenMPLoopDirectiveScope"},
163      {OpenMPSimdDirectiveScope, "OpenMPSimdDirectiveScope"},
164      {EnumScope, "EnumScope"},
165      {SEHTryScope, "SEHTryScope"},
166      {SEHExceptScope, "SEHExceptScope"},
167      {SEHFilterScope, "SEHFilterScope"},
168      {CompoundStmtScope, "CompoundStmtScope"},
169      {ClassInheritanceScope, "ClassInheritanceScope"},
170      {CatchScope, "CatchScope"},
171  };
172
173  for (auto Info : FlagInfo) {
174    if (Flags & Info.first) {
175      OS << Info.second;
176      Flags &= ~Info.first;
177      if (Flags)
178        OS << " | ";
179    }
180  }
181
182  assert(Flags == 0 && "Unknown scope flags");
183
184  if (HasFlags)
185    OS << '\n';
186
187  if (const Scope *Parent = getParent())
188    OS << "Parent: (clang::Scope*)" << Parent << '\n';
189
190  OS << "Depth: " << Depth << '\n';
191  OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
192  OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
193  if (const DeclContext *DC = getEntity())
194    OS << "Entity : (clang::DeclContext*)" << DC << '\n';
195
196  if (NRVO.getInt())
197    OS << "NRVO not allowed\n";
198  else if (NRVO.getPointer())
199    OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
200}
201