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 18 using namespace clang; 19 20 void 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 // transmit the parent's 'order' flag, if exists 47 if (parent->getFlags() & OpenMPOrderClauseScope) 48 Flags |= OpenMPOrderClauseScope; 49 } else { 50 Depth = 0; 51 PrototypeDepth = 0; 52 PrototypeIndex = 0; 53 MSLastManglingParent = FnParent = BlockParent = nullptr; 54 TemplateParamParent = nullptr; 55 MSLastManglingNumber = 1; 56 MSCurManglingNumber = 1; 57 } 58 59 // If this scope is a function or contains breaks/continues, remember it. 60 if (flags & FnScope) FnParent = this; 61 // The MS mangler uses the number of scopes that can hold declarations as 62 // part of an external name. 63 if (Flags & (ClassScope | FnScope)) { 64 MSLastManglingNumber = getMSLastManglingNumber(); 65 MSLastManglingParent = this; 66 MSCurManglingNumber = 1; 67 } 68 if (flags & BreakScope) BreakParent = this; 69 if (flags & ContinueScope) ContinueParent = this; 70 if (flags & BlockScope) BlockParent = this; 71 if (flags & TemplateParamScope) TemplateParamParent = this; 72 73 // If this is a prototype scope, record that. 74 if (flags & FunctionPrototypeScope) PrototypeDepth++; 75 76 if (flags & DeclScope) { 77 if (flags & FunctionPrototypeScope) 78 ; // Prototype scopes are uninteresting. 79 else if ((flags & ClassScope) && getParent()->isClassScope()) 80 ; // Nested class scopes aren't ambiguous. 81 else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope) 82 ; // Classes inside of namespaces aren't ambiguous. 83 else if ((flags & EnumScope)) 84 ; // Don't increment for enum scopes. 85 else 86 incrementMSManglingNumber(); 87 } 88 } 89 90 void Scope::Init(Scope *parent, unsigned flags) { 91 setFlags(parent, flags); 92 93 DeclsInScope.clear(); 94 UsingDirectives.clear(); 95 Entity = nullptr; 96 ErrorTrap.reset(); 97 NRVO = std::nullopt; 98 } 99 100 bool Scope::containedInPrototypeScope() const { 101 const Scope *S = this; 102 while (S) { 103 if (S->isFunctionPrototypeScope()) 104 return true; 105 S = S->getParent(); 106 } 107 return false; 108 } 109 110 void Scope::AddFlags(unsigned FlagsToSet) { 111 assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 && 112 "Unsupported scope flags"); 113 if (FlagsToSet & BreakScope) { 114 assert((Flags & BreakScope) == 0 && "Already set"); 115 BreakParent = this; 116 } 117 if (FlagsToSet & ContinueScope) { 118 assert((Flags & ContinueScope) == 0 && "Already set"); 119 ContinueParent = this; 120 } 121 Flags |= FlagsToSet; 122 } 123 124 // The algorithm for updating NRVO candidate is as follows: 125 // 1. All previous candidates become invalid because a new NRVO candidate is 126 // obtained. Therefore, we need to clear return slots for other 127 // variables defined before the current return statement in the current 128 // scope and in outer scopes. 129 // 2. Store the new candidate if its return slot is available. Otherwise, 130 // there is no NRVO candidate so far. 131 void Scope::updateNRVOCandidate(VarDecl *VD) { 132 auto UpdateReturnSlotsInScopeForVD = [VD](Scope *S) -> bool { 133 bool IsReturnSlotFound = S->ReturnSlots.contains(VD); 134 135 // We found a candidate variable that can be put into a return slot. 136 // Clear the set, because other variables cannot occupy a return 137 // slot in the same scope. 138 S->ReturnSlots.clear(); 139 140 if (IsReturnSlotFound) 141 S->ReturnSlots.insert(VD); 142 143 return IsReturnSlotFound; 144 }; 145 146 bool CanBePutInReturnSlot = false; 147 148 for (auto *S = this; S; S = S->getParent()) { 149 CanBePutInReturnSlot |= UpdateReturnSlotsInScopeForVD(S); 150 151 if (S->getEntity()) 152 break; 153 } 154 155 // Consider the variable as NRVO candidate if the return slot is available 156 // for it in the current scope, or if it can be available in outer scopes. 157 NRVO = CanBePutInReturnSlot ? VD : nullptr; 158 } 159 160 void Scope::applyNRVO() { 161 // There is no NRVO candidate in the current scope. 162 if (!NRVO.has_value()) 163 return; 164 165 if (*NRVO && isDeclScope(*NRVO)) 166 (*NRVO)->setNRVOVariable(true); 167 168 // It's necessary to propagate NRVO candidate to the parent scope for cases 169 // when the parent scope doesn't contain a return statement. 170 // For example: 171 // X foo(bool b) { 172 // X x; 173 // if (b) 174 // return x; 175 // exit(0); 176 // } 177 // Also, we need to propagate nullptr value that means NRVO is not 178 // allowed in this scope. 179 // For example: 180 // X foo(bool b) { 181 // X x; 182 // if (b) 183 // return x; 184 // else 185 // return X(); // NRVO is not allowed 186 // } 187 if (!getEntity()) 188 getParent()->NRVO = *NRVO; 189 } 190 191 LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); } 192 193 void Scope::dumpImpl(raw_ostream &OS) const { 194 unsigned Flags = getFlags(); 195 bool HasFlags = Flags != 0; 196 197 if (HasFlags) 198 OS << "Flags: "; 199 200 std::pair<unsigned, const char *> FlagInfo[] = { 201 {FnScope, "FnScope"}, 202 {BreakScope, "BreakScope"}, 203 {ContinueScope, "ContinueScope"}, 204 {DeclScope, "DeclScope"}, 205 {ControlScope, "ControlScope"}, 206 {ClassScope, "ClassScope"}, 207 {BlockScope, "BlockScope"}, 208 {TemplateParamScope, "TemplateParamScope"}, 209 {FunctionPrototypeScope, "FunctionPrototypeScope"}, 210 {FunctionDeclarationScope, "FunctionDeclarationScope"}, 211 {AtCatchScope, "AtCatchScope"}, 212 {ObjCMethodScope, "ObjCMethodScope"}, 213 {SwitchScope, "SwitchScope"}, 214 {TryScope, "TryScope"}, 215 {FnTryCatchScope, "FnTryCatchScope"}, 216 {OpenMPDirectiveScope, "OpenMPDirectiveScope"}, 217 {OpenMPLoopDirectiveScope, "OpenMPLoopDirectiveScope"}, 218 {OpenMPSimdDirectiveScope, "OpenMPSimdDirectiveScope"}, 219 {EnumScope, "EnumScope"}, 220 {SEHTryScope, "SEHTryScope"}, 221 {SEHExceptScope, "SEHExceptScope"}, 222 {SEHFilterScope, "SEHFilterScope"}, 223 {CompoundStmtScope, "CompoundStmtScope"}, 224 {ClassInheritanceScope, "ClassInheritanceScope"}, 225 {CatchScope, "CatchScope"}, 226 }; 227 228 for (auto Info : FlagInfo) { 229 if (Flags & Info.first) { 230 OS << Info.second; 231 Flags &= ~Info.first; 232 if (Flags) 233 OS << " | "; 234 } 235 } 236 237 assert(Flags == 0 && "Unknown scope flags"); 238 239 if (HasFlags) 240 OS << '\n'; 241 242 if (const Scope *Parent = getParent()) 243 OS << "Parent: (clang::Scope*)" << Parent << '\n'; 244 245 OS << "Depth: " << Depth << '\n'; 246 OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n'; 247 OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n'; 248 if (const DeclContext *DC = getEntity()) 249 OS << "Entity : (clang::DeclContext*)" << DC << '\n'; 250 251 if (!NRVO) 252 OS << "there is no NRVO candidate\n"; 253 else if (*NRVO) 254 OS << "NRVO candidate : (clang::VarDecl*)" << *NRVO << '\n'; 255 else 256 OS << "NRVO is not allowed\n"; 257 } 258