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