| //===--- ScopeInfo.cpp - Information about a semantic context -------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements FunctionScopeInfo and its subclasses, which contain |
| // information about a single function, block, lambda, or method body. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Sema/ScopeInfo.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/ExprObjC.h" |
| |
| using namespace clang; |
| using namespace sema; |
| |
| void FunctionScopeInfo::Clear() { |
| HasBranchProtectedScope = false; |
| HasBranchIntoScope = false; |
| HasIndirectGoto = false; |
| HasDroppedStmt = false; |
| HasOMPDeclareReductionCombiner = false; |
| HasFallthroughStmt = false; |
| UsesFPIntrin = false; |
| HasPotentialAvailabilityViolations = false; |
| ObjCShouldCallSuper = false; |
| ObjCIsDesignatedInit = false; |
| ObjCWarnForNoDesignatedInitChain = false; |
| ObjCIsSecondaryInit = false; |
| ObjCWarnForNoInitDelegation = false; |
| FirstReturnLoc = SourceLocation(); |
| FirstCXXOrObjCTryLoc = SourceLocation(); |
| FirstSEHTryLoc = SourceLocation(); |
| |
| // Coroutine state |
| FirstCoroutineStmtLoc = SourceLocation(); |
| CoroutinePromise = nullptr; |
| CoroutineParameterMoves.clear(); |
| NeedsCoroutineSuspends = true; |
| CoroutineSuspends.first = nullptr; |
| CoroutineSuspends.second = nullptr; |
| |
| SwitchStack.clear(); |
| Returns.clear(); |
| ErrorTrap.reset(); |
| PossiblyUnreachableDiags.clear(); |
| WeakObjectUses.clear(); |
| ModifiedNonNullParams.clear(); |
| Blocks.clear(); |
| ByrefBlockVars.clear(); |
| } |
| |
| static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) { |
| if (PropE->isExplicitProperty()) |
| return PropE->getExplicitProperty(); |
| |
| return PropE->getImplicitPropertyGetter(); |
| } |
| |
| FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy |
| FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { |
| E = E->IgnoreParenCasts(); |
| |
| const NamedDecl *D = nullptr; |
| bool IsExact = false; |
| |
| switch (E->getStmtClass()) { |
| case Stmt::DeclRefExprClass: |
| D = cast<DeclRefExpr>(E)->getDecl(); |
| IsExact = isa<VarDecl>(D); |
| break; |
| case Stmt::MemberExprClass: { |
| const MemberExpr *ME = cast<MemberExpr>(E); |
| D = ME->getMemberDecl(); |
| IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()); |
| break; |
| } |
| case Stmt::ObjCIvarRefExprClass: { |
| const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E); |
| D = IE->getDecl(); |
| IsExact = IE->getBase()->isObjCSelfExpr(); |
| break; |
| } |
| case Stmt::PseudoObjectExprClass: { |
| const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E); |
| const ObjCPropertyRefExpr *BaseProp = |
| dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); |
| if (BaseProp) { |
| D = getBestPropertyDecl(BaseProp); |
| |
| if (BaseProp->isObjectReceiver()) { |
| const Expr *DoubleBase = BaseProp->getBase(); |
| if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase)) |
| DoubleBase = OVE->getSourceExpr(); |
| |
| IsExact = DoubleBase->isObjCSelfExpr(); |
| } |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| |
| return BaseInfoTy(D, IsExact); |
| } |
| |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( |
| const ObjCPropertyRefExpr *PropE) |
| : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) { |
| |
| if (PropE->isObjectReceiver()) { |
| const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase()); |
| const Expr *E = OVE->getSourceExpr(); |
| Base = getBaseInfo(E); |
| } else if (PropE->isClassReceiver()) { |
| Base.setPointer(PropE->getClassReceiver()); |
| } else { |
| assert(PropE->isSuperReceiver()); |
| } |
| } |
| |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE, |
| const ObjCPropertyDecl *Prop) |
| : Base(nullptr, true), Property(Prop) { |
| if (BaseE) |
| Base = getBaseInfo(BaseE); |
| // else, this is a message accessing a property on super. |
| } |
| |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( |
| const DeclRefExpr *DRE) |
| : Base(nullptr, true), Property(DRE->getDecl()) { |
| assert(isa<VarDecl>(Property)); |
| } |
| |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( |
| const ObjCIvarRefExpr *IvarE) |
| : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) { |
| } |
| |
| void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg, |
| const ObjCPropertyDecl *Prop) { |
| assert(Msg && Prop); |
| WeakUseVector &Uses = |
| WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)]; |
| Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0)); |
| } |
| |
| void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { |
| E = E->IgnoreParenCasts(); |
| |
| if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { |
| markSafeWeakUse(POE->getSyntacticForm()); |
| return; |
| } |
| |
| if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) { |
| markSafeWeakUse(Cond->getTrueExpr()); |
| markSafeWeakUse(Cond->getFalseExpr()); |
| return; |
| } |
| |
| if (const BinaryConditionalOperator *Cond = |
| dyn_cast<BinaryConditionalOperator>(E)) { |
| markSafeWeakUse(Cond->getCommon()); |
| markSafeWeakUse(Cond->getFalseExpr()); |
| return; |
| } |
| |
| // Has this weak object been seen before? |
| FunctionScopeInfo::WeakObjectUseMap::iterator Uses = WeakObjectUses.end(); |
| if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) { |
| if (!RefExpr->isObjectReceiver()) |
| return; |
| if (isa<OpaqueValueExpr>(RefExpr->getBase())) |
| Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr)); |
| else { |
| markSafeWeakUse(RefExpr->getBase()); |
| return; |
| } |
| } |
| else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E)) |
| Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE)); |
| else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { |
| if (isa<VarDecl>(DRE->getDecl())) |
| Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE)); |
| } else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) { |
| if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) { |
| if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) { |
| Uses = |
| WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(), |
| Prop)); |
| } |
| } |
| } |
| else |
| return; |
| |
| if (Uses == WeakObjectUses.end()) |
| return; |
| |
| // Has there been a read from the object using this Expr? |
| FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse = |
| llvm::find(llvm::reverse(Uses->second), WeakUseTy(E, true)); |
| if (ThisUse == Uses->second.rend()) |
| return; |
| |
| ThisUse->markSafe(); |
| } |
| |
| bool Capture::isInitCapture() const { |
| // Note that a nested capture of an init-capture is not itself an |
| // init-capture. |
| return !isNested() && isVariableCapture() && getVariable()->isInitCapture(); |
| } |
| |
| bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const { |
| for (auto &Cap : Captures) |
| if (Cap.isVLATypeCapture() && Cap.getCapturedVLAType() == VAT) |
| return true; |
| return false; |
| } |
| |
| void LambdaScopeInfo::visitPotentialCaptures( |
| llvm::function_ref<void(VarDecl *, Expr *)> Callback) const { |
| for (Expr *E : PotentiallyCapturingExprs) { |
| if (auto *DRE = dyn_cast<DeclRefExpr>(E)) { |
| Callback(cast<VarDecl>(DRE->getFoundDecl()), E); |
| } else if (auto *ME = dyn_cast<MemberExpr>(E)) { |
| Callback(cast<VarDecl>(ME->getMemberDecl()), E); |
| } else if (auto *FP = dyn_cast<FunctionParmPackExpr>(E)) { |
| for (VarDecl *VD : *FP) |
| Callback(VD, E); |
| } else { |
| llvm_unreachable("unexpected expression in potential captures list"); |
| } |
| } |
| } |
| |
| FunctionScopeInfo::~FunctionScopeInfo() { } |
| BlockScopeInfo::~BlockScopeInfo() { } |
| CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { } |