2012-09-29 06:21:39 +08:00
|
|
|
//===--- 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"
|
2014-08-28 12:28:19 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2012-09-29 06:21:39 +08:00
|
|
|
#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;
|
2013-12-04 05:11:36 +08:00
|
|
|
HasDroppedStmt = false;
|
|
|
|
ObjCShouldCallSuper = false;
|
|
|
|
ObjCIsDesignatedInit = false;
|
|
|
|
ObjCWarnForNoDesignatedInitChain = false;
|
2013-12-04 05:11:49 +08:00
|
|
|
ObjCIsSecondaryInit = false;
|
|
|
|
ObjCWarnForNoInitDelegation = false;
|
2012-09-29 06:21:39 +08:00
|
|
|
|
|
|
|
SwitchStack.clear();
|
|
|
|
Returns.clear();
|
|
|
|
ErrorTrap.reset();
|
|
|
|
PossiblyUnreachableDiags.clear();
|
|
|
|
WeakObjectUses.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();
|
|
|
|
|
2014-05-26 14:22:03 +08:00
|
|
|
const NamedDecl *D = nullptr;
|
2012-09-29 06:21:39 +08:00
|
|
|
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();
|
2012-10-02 04:34:04 +08:00
|
|
|
IsExact = IE->getBase()->isObjCSelfExpr();
|
2012-09-29 06:21:39 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Stmt::PseudoObjectExprClass: {
|
|
|
|
const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
|
|
|
|
const ObjCPropertyRefExpr *BaseProp =
|
|
|
|
dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
|
|
|
|
if (BaseProp) {
|
|
|
|
D = getBestPropertyDecl(BaseProp);
|
|
|
|
|
|
|
|
const Expr *DoubleBase = BaseProp->getBase();
|
|
|
|
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
|
|
|
|
DoubleBase = OVE->getSourceExpr();
|
|
|
|
|
2012-10-02 04:34:04 +08:00
|
|
|
IsExact = DoubleBase->isObjCSelfExpr();
|
2012-09-29 06:21:39 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BaseInfoTy(D, IsExact);
|
|
|
|
}
|
|
|
|
|
2014-08-28 12:28:19 +08:00
|
|
|
bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
|
|
|
|
if (auto *LSI = dyn_cast<LambdaScopeInfo>(this))
|
|
|
|
for (auto *FD : LSI->Lambda->fields()) {
|
|
|
|
if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-09-29 06:21:39 +08:00
|
|
|
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
|
|
|
|
const ObjCPropertyRefExpr *PropE)
|
2014-05-26 14:22:03 +08:00
|
|
|
: Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
|
2012-09-29 06:21:39 +08:00
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.
This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.
<rdar://problem/12407765>
llvm-svn: 165718
2012-10-12 00:06:21 +08:00
|
|
|
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
|
|
|
|
const ObjCPropertyDecl *Prop)
|
2014-05-26 14:22:03 +08:00
|
|
|
: Base(nullptr, true), Property(Prop) {
|
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.
This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.
<rdar://problem/12407765>
llvm-svn: 165718
2012-10-12 00:06:21 +08:00
|
|
|
if (BaseE)
|
|
|
|
Base = getBaseInfo(BaseE);
|
|
|
|
// else, this is a message accessing a property on super.
|
|
|
|
}
|
|
|
|
|
2012-09-29 06:21:39 +08:00
|
|
|
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
|
|
|
|
const DeclRefExpr *DRE)
|
2014-05-26 14:22:03 +08:00
|
|
|
: Base(nullptr, true), Property(DRE->getDecl()) {
|
2012-09-29 06:21:39 +08:00
|
|
|
assert(isa<VarDecl>(Property));
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
|
|
|
|
const ObjCIvarRefExpr *IvarE)
|
|
|
|
: Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
|
|
|
|
}
|
|
|
|
|
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.
This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.
<rdar://problem/12407765>
llvm-svn: 165718
2012-10-12 00:06:21 +08:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2012-09-29 06:21:39 +08:00
|
|
|
void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
|
2012-10-11 00:43:06 +08:00
|
|
|
E = E->IgnoreParenCasts();
|
2012-09-29 06:21:39 +08:00
|
|
|
|
|
|
|
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;
|
2014-06-18 07:35:13 +08:00
|
|
|
if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
|
|
|
|
if (isa<OpaqueValueExpr>(RefExpr->getBase()))
|
|
|
|
Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
|
|
|
|
else {
|
|
|
|
markSafeWeakUse(RefExpr->getBase());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2012-09-29 06:21:39 +08:00
|
|
|
else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
|
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.
This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.
<rdar://problem/12407765>
llvm-svn: 165718
2012-10-12 00:06:21 +08:00
|
|
|
Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
|
2012-09-29 06:21:39 +08:00
|
|
|
else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
|
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.
This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.
<rdar://problem/12407765>
llvm-svn: 165718
2012-10-12 00:06:21 +08:00
|
|
|
Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
|
2012-10-12 01:02:00 +08:00
|
|
|
else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) {
|
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp.
Now, for every explicit message send, we check if it's a property access,
and if so, if the property is weak. Then for every assignment of a
message, we have to do the same thing again.
This is a potentially expensive increase because determining whether a
method is a property accessor requires searching through the methods it
overrides. However, without it -Warc-repeated-use-of-weak will miss cases
from people who prefer not to use dot syntax. If this turns out to be
too expensive, we can try caching the result somewhere, or even lose
precision by not checking superclass methods. The warning is off-by-default,
though.
<rdar://problem/12407765>
llvm-svn: 165718
2012-10-12 00:06:21 +08:00
|
|
|
Uses = WeakObjectUses.end();
|
|
|
|
if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) {
|
|
|
|
if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) {
|
|
|
|
Uses =
|
|
|
|
WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
|
|
|
|
Prop));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-09-29 06:21:39 +08:00
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Uses == WeakObjectUses.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Has there been a read from the object using this Expr?
|
|
|
|
FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
|
|
|
|
std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true));
|
|
|
|
if (ThisUse == Uses->second.rend())
|
|
|
|
return;
|
|
|
|
|
|
|
|
ThisUse->markSafe();
|
|
|
|
}
|
|
|
|
|
2013-12-08 04:22:44 +08:00
|
|
|
void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD,
|
|
|
|
Expr *&E) const {
|
2013-11-08 00:57:56 +08:00
|
|
|
assert(Idx < getNumPotentialVariableCaptures() &&
|
2013-12-08 04:22:44 +08:00
|
|
|
"Index of potential capture must be within 0 to less than the "
|
|
|
|
"number of captures!");
|
This patch implements capturing of variables within generic lambdas.
Both Richard and I felt that the current wording in the working paper needed some tweaking - Please see http://llvm-reviews.chandlerc.com/D2035 for additional context and references to core-reflector messages that discuss wording tweaks.
What is implemented is what we had intended to specify in Bristol; but, recently felt that the specification might benefit from some tweaking and fleshing.
As a rough attempt to explain the semantics: If a nested lambda with a default-capture names a variable within its body, and if the enclosing full expression that contains the name of that variable is instantiation-dependent - then an enclosing lambda that is capture-ready (i.e. within a non-dependent context) must capture that variable, if all intervening nested lambdas can potentially capture that variable if they need to, and all intervening parent lambdas of the capture-ready lambda can and do capture the variable.
Of note, 'this' capturing is also currently underspecified in the working paper for generic lambdas. What is implemented here is if the set of candidate functions in a nested generic lambda includes both static and non-static member functions (regardless of viability checking - i.e. num and type of parameters/arguments) - and if all intervening nested-inner lambdas between the capture-ready lambda and the function-call containing nested lambda can capture 'this' and if all enclosing lambdas of the capture-ready lambda can capture 'this', then 'this' is speculatively captured by that capture-ready lambda.
Hopefully a paper for the C++ committee (that Richard and I had started some preliminary work on) is forthcoming.
This essentially makes generic lambdas feature complete, except for known bugs. The more prominent ones (and the ones I am currently aware of) being:
- generic lambdas and init-captures are broken - but a patch that fixes this is already in the works ...
- nested variadic expansions such as:
auto K = [](auto ... OuterArgs) {
vp([=](auto ... Is) {
decltype(OuterArgs) OA = OuterArgs;
return 0;
}(5)...);
return 0;
};
auto M = K('a', ' ', 1, " -- ", 3.14);
currently cause crashes. I think I know how to fix this (since I had done so in my initial implementation) - but it will probably take some work and back & forth with Doug and Richard.
A warm thanks to all who provided feedback - and especially to Doug Gregor and Richard Smith for their pivotal guidance: their insight and prestidigitation in such matters is boundless!
Now let's hope this commit doesn't upset the buildbot gods ;)
Thanks!
llvm-svn: 194188
2013-11-07 13:17:06 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-09-29 06:21:39 +08:00
|
|
|
FunctionScopeInfo::~FunctionScopeInfo() { }
|
|
|
|
BlockScopeInfo::~BlockScopeInfo() { }
|
|
|
|
LambdaScopeInfo::~LambdaScopeInfo() { }
|
2013-04-17 03:37:38 +08:00
|
|
|
CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
|