//===--- ScopeInfo.cpp - Information about a semantic context -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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;
ObjCShouldCallSuper = false;
ObjCIsDesignatedInit = false;
ObjCWarnForNoDesignatedInitChain = false;
ObjCIsSecondaryInit = false;
ObjCWarnForNoInitDelegation = false;
FirstReturnLoc = SourceLocation();
FirstCXXTryLoc = SourceLocation();
FirstSEHTryLoc = SourceLocation();
SwitchStack.clear();
Returns.clear();
CoroutinePromise = nullptr;
CoroutineStmts.clear();
ErrorTrap.reset();
PossiblyUnreachableDiags.clear();
WeakObjectUses.clear();
ModifiedNonNullParams.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);
}
bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
RecordDecl *RD = nullptr;
if (auto *LSI = dyn_cast<LambdaScopeInfo>(this))
RD = LSI->Lambda;
else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(this))
RD = CRSI->TheRecordDecl;
if (RD)
for (auto *FD : RD->fields()) {
if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT)
return true;
}
return false;
}
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;
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))
Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) {
Uses = WeakObjectUses.end();
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();
}
void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD,
Expr *&E) const {
assert(Idx < getNumPotentialVariableCaptures() &&
"Index of potential capture must be within 0 to less than the "
"number of captures!");
E = PotentiallyCapturingExprs[Idx];
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
VD = dyn_cast<VarDecl>(DRE->getFoundDecl());
else if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
VD = dyn_cast<VarDecl>(ME->getMemberDecl());
else
llvm_unreachable("Only DeclRefExprs or MemberExprs should be added for "
"potential captures");
assert(VD);
}
FunctionScopeInfo::~FunctionScopeInfo() { }
BlockScopeInfo::~BlockScopeInfo() { }
CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }