1 //===--- ScopeInfo.cpp - Information about a semantic context -------------===// 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 FunctionScopeInfo and its subclasses, which contain 10 // information about a single function, block, lambda, or method body. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Sema/ScopeInfo.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/DeclObjC.h" 18 #include "clang/AST/Expr.h" 19 #include "clang/AST/ExprCXX.h" 20 #include "clang/AST/ExprObjC.h" 21 22 using namespace clang; 23 using namespace sema; 24 25 void FunctionScopeInfo::Clear() { 26 HasBranchProtectedScope = false; 27 HasBranchIntoScope = false; 28 HasIndirectGoto = false; 29 HasDroppedStmt = false; 30 HasOMPDeclareReductionCombiner = false; 31 HasFallthroughStmt = false; 32 UsesFPIntrin = false; 33 HasPotentialAvailabilityViolations = false; 34 ObjCShouldCallSuper = false; 35 ObjCIsDesignatedInit = false; 36 ObjCWarnForNoDesignatedInitChain = false; 37 ObjCIsSecondaryInit = false; 38 ObjCWarnForNoInitDelegation = false; 39 FirstReturnLoc = SourceLocation(); 40 FirstCXXOrObjCTryLoc = SourceLocation(); 41 FirstSEHTryLoc = SourceLocation(); 42 43 // Coroutine state 44 FirstCoroutineStmtLoc = SourceLocation(); 45 CoroutinePromise = nullptr; 46 CoroutineParameterMoves.clear(); 47 NeedsCoroutineSuspends = true; 48 CoroutineSuspends.first = nullptr; 49 CoroutineSuspends.second = nullptr; 50 51 SwitchStack.clear(); 52 Returns.clear(); 53 ErrorTrap.reset(); 54 PossiblyUnreachableDiags.clear(); 55 WeakObjectUses.clear(); 56 ModifiedNonNullParams.clear(); 57 Blocks.clear(); 58 ByrefBlockVars.clear(); 59 } 60 61 static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) { 62 if (PropE->isExplicitProperty()) 63 return PropE->getExplicitProperty(); 64 65 return PropE->getImplicitPropertyGetter(); 66 } 67 68 FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy 69 FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { 70 E = E->IgnoreParenCasts(); 71 72 const NamedDecl *D = nullptr; 73 bool IsExact = false; 74 75 switch (E->getStmtClass()) { 76 case Stmt::DeclRefExprClass: 77 D = cast<DeclRefExpr>(E)->getDecl(); 78 IsExact = isa<VarDecl>(D); 79 break; 80 case Stmt::MemberExprClass: { 81 const MemberExpr *ME = cast<MemberExpr>(E); 82 D = ME->getMemberDecl(); 83 IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()); 84 break; 85 } 86 case Stmt::ObjCIvarRefExprClass: { 87 const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E); 88 D = IE->getDecl(); 89 IsExact = IE->getBase()->isObjCSelfExpr(); 90 break; 91 } 92 case Stmt::PseudoObjectExprClass: { 93 const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E); 94 const ObjCPropertyRefExpr *BaseProp = 95 dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); 96 if (BaseProp) { 97 D = getBestPropertyDecl(BaseProp); 98 99 if (BaseProp->isObjectReceiver()) { 100 const Expr *DoubleBase = BaseProp->getBase(); 101 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase)) 102 DoubleBase = OVE->getSourceExpr(); 103 104 IsExact = DoubleBase->isObjCSelfExpr(); 105 } 106 } 107 break; 108 } 109 default: 110 break; 111 } 112 113 return BaseInfoTy(D, IsExact); 114 } 115 116 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( 117 const ObjCPropertyRefExpr *PropE) 118 : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) { 119 120 if (PropE->isObjectReceiver()) { 121 const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase()); 122 const Expr *E = OVE->getSourceExpr(); 123 Base = getBaseInfo(E); 124 } else if (PropE->isClassReceiver()) { 125 Base.setPointer(PropE->getClassReceiver()); 126 } else { 127 assert(PropE->isSuperReceiver()); 128 } 129 } 130 131 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE, 132 const ObjCPropertyDecl *Prop) 133 : Base(nullptr, true), Property(Prop) { 134 if (BaseE) 135 Base = getBaseInfo(BaseE); 136 // else, this is a message accessing a property on super. 137 } 138 139 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( 140 const DeclRefExpr *DRE) 141 : Base(nullptr, true), Property(DRE->getDecl()) { 142 assert(isa<VarDecl>(Property)); 143 } 144 145 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( 146 const ObjCIvarRefExpr *IvarE) 147 : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) { 148 } 149 150 void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg, 151 const ObjCPropertyDecl *Prop) { 152 assert(Msg && Prop); 153 WeakUseVector &Uses = 154 WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)]; 155 Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0)); 156 } 157 158 void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { 159 E = E->IgnoreParenCasts(); 160 161 if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { 162 markSafeWeakUse(POE->getSyntacticForm()); 163 return; 164 } 165 166 if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) { 167 markSafeWeakUse(Cond->getTrueExpr()); 168 markSafeWeakUse(Cond->getFalseExpr()); 169 return; 170 } 171 172 if (const BinaryConditionalOperator *Cond = 173 dyn_cast<BinaryConditionalOperator>(E)) { 174 markSafeWeakUse(Cond->getCommon()); 175 markSafeWeakUse(Cond->getFalseExpr()); 176 return; 177 } 178 179 // Has this weak object been seen before? 180 FunctionScopeInfo::WeakObjectUseMap::iterator Uses = WeakObjectUses.end(); 181 if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) { 182 if (!RefExpr->isObjectReceiver()) 183 return; 184 if (isa<OpaqueValueExpr>(RefExpr->getBase())) 185 Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr)); 186 else { 187 markSafeWeakUse(RefExpr->getBase()); 188 return; 189 } 190 } 191 else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E)) 192 Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE)); 193 else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 194 if (isa<VarDecl>(DRE->getDecl())) 195 Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE)); 196 } else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) { 197 if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) { 198 if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) { 199 Uses = 200 WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(), 201 Prop)); 202 } 203 } 204 } 205 else 206 return; 207 208 if (Uses == WeakObjectUses.end()) 209 return; 210 211 // Has there been a read from the object using this Expr? 212 FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse = 213 llvm::find(llvm::reverse(Uses->second), WeakUseTy(E, true)); 214 if (ThisUse == Uses->second.rend()) 215 return; 216 217 ThisUse->markSafe(); 218 } 219 220 bool Capture::isInitCapture() const { 221 // Note that a nested capture of an init-capture is not itself an 222 // init-capture. 223 return !isNested() && isVariableCapture() && getVariable()->isInitCapture(); 224 } 225 226 bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const { 227 for (auto &Cap : Captures) 228 if (Cap.isVLATypeCapture() && Cap.getCapturedVLAType() == VAT) 229 return true; 230 return false; 231 } 232 233 void LambdaScopeInfo::visitPotentialCaptures( 234 llvm::function_ref<void(VarDecl *, Expr *)> Callback) const { 235 for (Expr *E : PotentiallyCapturingExprs) { 236 if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { 237 Callback(cast<VarDecl>(DRE->getFoundDecl()), E); 238 } else if (auto *ME = dyn_cast<MemberExpr>(E)) { 239 Callback(cast<VarDecl>(ME->getMemberDecl()), E); 240 } else if (auto *FP = dyn_cast<FunctionParmPackExpr>(E)) { 241 for (VarDecl *VD : *FP) 242 Callback(VD, E); 243 } else { 244 llvm_unreachable("unexpected expression in potential captures list"); 245 } 246 } 247 } 248 249 FunctionScopeInfo::~FunctionScopeInfo() { } 250 BlockScopeInfo::~BlockScopeInfo() { } 251 CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { } 252