10b57cec5SDimitry Andric //===--- ScopeInfo.cpp - Information about a semantic context -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements FunctionScopeInfo and its subclasses, which contain 100b57cec5SDimitry Andric // information about a single function, block, lambda, or method body. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h" 150b57cec5SDimitry Andric #include "clang/AST/Decl.h" 160b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 180b57cec5SDimitry Andric #include "clang/AST/Expr.h" 190b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 200b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace clang; 230b57cec5SDimitry Andric using namespace sema; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric void FunctionScopeInfo::Clear() { 260b57cec5SDimitry Andric HasBranchProtectedScope = false; 270b57cec5SDimitry Andric HasBranchIntoScope = false; 280b57cec5SDimitry Andric HasIndirectGoto = false; 290b57cec5SDimitry Andric HasDroppedStmt = false; 300b57cec5SDimitry Andric HasOMPDeclareReductionCombiner = false; 310b57cec5SDimitry Andric HasFallthroughStmt = false; 32e8d8bef9SDimitry Andric UsesFPIntrin = false; 330b57cec5SDimitry Andric HasPotentialAvailabilityViolations = false; 340b57cec5SDimitry Andric ObjCShouldCallSuper = false; 350b57cec5SDimitry Andric ObjCIsDesignatedInit = false; 360b57cec5SDimitry Andric ObjCWarnForNoDesignatedInitChain = false; 370b57cec5SDimitry Andric ObjCIsSecondaryInit = false; 380b57cec5SDimitry Andric ObjCWarnForNoInitDelegation = false; 390b57cec5SDimitry Andric FirstReturnLoc = SourceLocation(); 40349cc55cSDimitry Andric FirstCXXOrObjCTryLoc = SourceLocation(); 410b57cec5SDimitry Andric FirstSEHTryLoc = SourceLocation(); 42*0fca6ea1SDimitry Andric FirstVLALoc = SourceLocation(); 4306c3fb27SDimitry Andric FoundImmediateEscalatingExpression = false; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // Coroutine state 460b57cec5SDimitry Andric FirstCoroutineStmtLoc = SourceLocation(); 470b57cec5SDimitry Andric CoroutinePromise = nullptr; 480b57cec5SDimitry Andric CoroutineParameterMoves.clear(); 490b57cec5SDimitry Andric NeedsCoroutineSuspends = true; 500b57cec5SDimitry Andric CoroutineSuspends.first = nullptr; 510b57cec5SDimitry Andric CoroutineSuspends.second = nullptr; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric SwitchStack.clear(); 540b57cec5SDimitry Andric Returns.clear(); 550b57cec5SDimitry Andric ErrorTrap.reset(); 560b57cec5SDimitry Andric PossiblyUnreachableDiags.clear(); 570b57cec5SDimitry Andric WeakObjectUses.clear(); 580b57cec5SDimitry Andric ModifiedNonNullParams.clear(); 590b57cec5SDimitry Andric Blocks.clear(); 600b57cec5SDimitry Andric ByrefBlockVars.clear(); 61bdd1243dSDimitry Andric AddrLabels.clear(); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) { 650b57cec5SDimitry Andric if (PropE->isExplicitProperty()) 660b57cec5SDimitry Andric return PropE->getExplicitProperty(); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric return PropE->getImplicitPropertyGetter(); 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy 720b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { 730b57cec5SDimitry Andric E = E->IgnoreParenCasts(); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric const NamedDecl *D = nullptr; 760b57cec5SDimitry Andric bool IsExact = false; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric switch (E->getStmtClass()) { 790b57cec5SDimitry Andric case Stmt::DeclRefExprClass: 800b57cec5SDimitry Andric D = cast<DeclRefExpr>(E)->getDecl(); 810b57cec5SDimitry Andric IsExact = isa<VarDecl>(D); 820b57cec5SDimitry Andric break; 830b57cec5SDimitry Andric case Stmt::MemberExprClass: { 840b57cec5SDimitry Andric const MemberExpr *ME = cast<MemberExpr>(E); 850b57cec5SDimitry Andric D = ME->getMemberDecl(); 860b57cec5SDimitry Andric IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()); 870b57cec5SDimitry Andric break; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric case Stmt::ObjCIvarRefExprClass: { 900b57cec5SDimitry Andric const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E); 910b57cec5SDimitry Andric D = IE->getDecl(); 920b57cec5SDimitry Andric IsExact = IE->getBase()->isObjCSelfExpr(); 930b57cec5SDimitry Andric break; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric case Stmt::PseudoObjectExprClass: { 960b57cec5SDimitry Andric const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E); 970b57cec5SDimitry Andric const ObjCPropertyRefExpr *BaseProp = 980b57cec5SDimitry Andric dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); 990b57cec5SDimitry Andric if (BaseProp) { 1000b57cec5SDimitry Andric D = getBestPropertyDecl(BaseProp); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric if (BaseProp->isObjectReceiver()) { 1030b57cec5SDimitry Andric const Expr *DoubleBase = BaseProp->getBase(); 1040b57cec5SDimitry Andric if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase)) 1050b57cec5SDimitry Andric DoubleBase = OVE->getSourceExpr(); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric IsExact = DoubleBase->isObjCSelfExpr(); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric break; 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric default: 1130b57cec5SDimitry Andric break; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric return BaseInfoTy(D, IsExact); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( 1200b57cec5SDimitry Andric const ObjCPropertyRefExpr *PropE) 1210b57cec5SDimitry Andric : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) { 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric if (PropE->isObjectReceiver()) { 1240b57cec5SDimitry Andric const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase()); 1250b57cec5SDimitry Andric const Expr *E = OVE->getSourceExpr(); 1260b57cec5SDimitry Andric Base = getBaseInfo(E); 1270b57cec5SDimitry Andric } else if (PropE->isClassReceiver()) { 1280b57cec5SDimitry Andric Base.setPointer(PropE->getClassReceiver()); 1290b57cec5SDimitry Andric } else { 1300b57cec5SDimitry Andric assert(PropE->isSuperReceiver()); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE, 1350b57cec5SDimitry Andric const ObjCPropertyDecl *Prop) 1360b57cec5SDimitry Andric : Base(nullptr, true), Property(Prop) { 1370b57cec5SDimitry Andric if (BaseE) 1380b57cec5SDimitry Andric Base = getBaseInfo(BaseE); 1390b57cec5SDimitry Andric // else, this is a message accessing a property on super. 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( 1430b57cec5SDimitry Andric const DeclRefExpr *DRE) 1440b57cec5SDimitry Andric : Base(nullptr, true), Property(DRE->getDecl()) { 1450b57cec5SDimitry Andric assert(isa<VarDecl>(Property)); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( 1490b57cec5SDimitry Andric const ObjCIvarRefExpr *IvarE) 1500b57cec5SDimitry Andric : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) { 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg, 1540b57cec5SDimitry Andric const ObjCPropertyDecl *Prop) { 1550b57cec5SDimitry Andric assert(Msg && Prop); 1560b57cec5SDimitry Andric WeakUseVector &Uses = 1570b57cec5SDimitry Andric WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)]; 1580b57cec5SDimitry Andric Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0)); 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { 1620b57cec5SDimitry Andric E = E->IgnoreParenCasts(); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { 1650b57cec5SDimitry Andric markSafeWeakUse(POE->getSyntacticForm()); 1660b57cec5SDimitry Andric return; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) { 1700b57cec5SDimitry Andric markSafeWeakUse(Cond->getTrueExpr()); 1710b57cec5SDimitry Andric markSafeWeakUse(Cond->getFalseExpr()); 1720b57cec5SDimitry Andric return; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric if (const BinaryConditionalOperator *Cond = 1760b57cec5SDimitry Andric dyn_cast<BinaryConditionalOperator>(E)) { 1770b57cec5SDimitry Andric markSafeWeakUse(Cond->getCommon()); 1780b57cec5SDimitry Andric markSafeWeakUse(Cond->getFalseExpr()); 1790b57cec5SDimitry Andric return; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric // Has this weak object been seen before? 1830b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectUseMap::iterator Uses = WeakObjectUses.end(); 1840b57cec5SDimitry Andric if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) { 1850b57cec5SDimitry Andric if (!RefExpr->isObjectReceiver()) 1860b57cec5SDimitry Andric return; 1870b57cec5SDimitry Andric if (isa<OpaqueValueExpr>(RefExpr->getBase())) 1880b57cec5SDimitry Andric Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr)); 1890b57cec5SDimitry Andric else { 1900b57cec5SDimitry Andric markSafeWeakUse(RefExpr->getBase()); 1910b57cec5SDimitry Andric return; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E)) 1950b57cec5SDimitry Andric Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE)); 1960b57cec5SDimitry Andric else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 1970b57cec5SDimitry Andric if (isa<VarDecl>(DRE->getDecl())) 1980b57cec5SDimitry Andric Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE)); 1990b57cec5SDimitry Andric } else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) { 2000b57cec5SDimitry Andric if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) { 2010b57cec5SDimitry Andric if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) { 2020b57cec5SDimitry Andric Uses = 2030b57cec5SDimitry Andric WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(), 2040b57cec5SDimitry Andric Prop)); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric else 2090b57cec5SDimitry Andric return; 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric if (Uses == WeakObjectUses.end()) 2120b57cec5SDimitry Andric return; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric // Has there been a read from the object using this Expr? 2150b57cec5SDimitry Andric FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse = 2160b57cec5SDimitry Andric llvm::find(llvm::reverse(Uses->second), WeakUseTy(E, true)); 2170b57cec5SDimitry Andric if (ThisUse == Uses->second.rend()) 2180b57cec5SDimitry Andric return; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric ThisUse->markSafe(); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric bool Capture::isInitCapture() const { 2240b57cec5SDimitry Andric // Note that a nested capture of an init-capture is not itself an 2250b57cec5SDimitry Andric // init-capture. 2260b57cec5SDimitry Andric return !isNested() && isVariableCapture() && getVariable()->isInitCapture(); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const { 2300b57cec5SDimitry Andric for (auto &Cap : Captures) 2310b57cec5SDimitry Andric if (Cap.isVLATypeCapture() && Cap.getCapturedVLAType() == VAT) 2320b57cec5SDimitry Andric return true; 2330b57cec5SDimitry Andric return false; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric void LambdaScopeInfo::visitPotentialCaptures( 237bdd1243dSDimitry Andric llvm::function_ref<void(ValueDecl *, Expr *)> Callback) const { 2380b57cec5SDimitry Andric for (Expr *E : PotentiallyCapturingExprs) { 2390b57cec5SDimitry Andric if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { 240bdd1243dSDimitry Andric Callback(cast<ValueDecl>(DRE->getFoundDecl()), E); 2410b57cec5SDimitry Andric } else if (auto *ME = dyn_cast<MemberExpr>(E)) { 242bdd1243dSDimitry Andric Callback(cast<ValueDecl>(ME->getMemberDecl()), E); 2430b57cec5SDimitry Andric } else if (auto *FP = dyn_cast<FunctionParmPackExpr>(E)) { 244bdd1243dSDimitry Andric for (ValueDecl *VD : *FP) 2450b57cec5SDimitry Andric Callback(VD, E); 2460b57cec5SDimitry Andric } else { 2470b57cec5SDimitry Andric llvm_unreachable("unexpected expression in potential captures list"); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2525f757f3fSDimitry Andric bool LambdaScopeInfo::lambdaCaptureShouldBeConst() const { 2535f757f3fSDimitry Andric if (ExplicitObjectParameter) 2545f757f3fSDimitry Andric return ExplicitObjectParameter->getType() 2555f757f3fSDimitry Andric .getNonReferenceType() 2565f757f3fSDimitry Andric .isConstQualified(); 2575f757f3fSDimitry Andric return !Mutable; 2585f757f3fSDimitry Andric } 2595f757f3fSDimitry Andric 2600b57cec5SDimitry Andric FunctionScopeInfo::~FunctionScopeInfo() { } 2610b57cec5SDimitry Andric BlockScopeInfo::~BlockScopeInfo() { } 2620b57cec5SDimitry Andric CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { } 263