mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
ARC writeback isn't supposed to apply to local indirect pointers,
only to pointers to locals. But it should work inside blocks, too. llvm-svn: 133969
This commit is contained in:
@@ -3195,24 +3195,24 @@ static void TryUserDefinedConversion(Sema &S,
|
||||
enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar };
|
||||
|
||||
/// Determines whether this expression is an acceptable ICR source.
|
||||
static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e) {
|
||||
static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e,
|
||||
bool isAddressOf) {
|
||||
// Skip parens.
|
||||
e = e->IgnoreParens();
|
||||
|
||||
// Skip address-of nodes.
|
||||
if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) {
|
||||
if (op->getOpcode() == UO_AddrOf)
|
||||
return isInvalidICRSource(C, op->getSubExpr());
|
||||
return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true);
|
||||
|
||||
// Skip certain casts.
|
||||
} else if (CastExpr *cast = dyn_cast<CastExpr>(e)) {
|
||||
switch (cast->getCastKind()) {
|
||||
} else if (CastExpr *ce = dyn_cast<CastExpr>(e)) {
|
||||
switch (ce->getCastKind()) {
|
||||
case CK_Dependent:
|
||||
case CK_BitCast:
|
||||
case CK_LValueBitCast:
|
||||
case CK_LValueToRValue:
|
||||
case CK_NoOp:
|
||||
return isInvalidICRSource(C, cast->getSubExpr());
|
||||
return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf);
|
||||
|
||||
case CK_ArrayToPointerDecay:
|
||||
return IIK_nonscalar;
|
||||
@@ -3225,16 +3225,25 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e) {
|
||||
}
|
||||
|
||||
// If we have a declaration reference, it had better be a local variable.
|
||||
} else if (DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(e)) {
|
||||
if (VarDecl *var = dyn_cast<VarDecl>(declRef->getDecl()))
|
||||
return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal);
|
||||
} else if (isa<DeclRefExpr>(e) || isa<BlockDeclRefExpr>(e)) {
|
||||
if (!isAddressOf) return IIK_nonlocal;
|
||||
|
||||
VarDecl *var;
|
||||
if (isa<DeclRefExpr>(e)) {
|
||||
var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl());
|
||||
if (!var) return IIK_nonlocal;
|
||||
} else {
|
||||
var = cast<BlockDeclRefExpr>(e)->getDecl();
|
||||
}
|
||||
|
||||
return (var->hasLocalStorage() ? IIK_okay : IIK_nonlocal);
|
||||
|
||||
// If we have a conditional operator, check both sides.
|
||||
} else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) {
|
||||
if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS()))
|
||||
if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf))
|
||||
return iik;
|
||||
|
||||
return isInvalidICRSource(C, cond->getRHS());
|
||||
return isInvalidICRSource(C, cond->getRHS(), isAddressOf);
|
||||
|
||||
// These are never scalar.
|
||||
} else if (isa<ArraySubscriptExpr>(e)) {
|
||||
@@ -3254,7 +3263,7 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e) {
|
||||
static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) {
|
||||
assert(src->isRValue());
|
||||
|
||||
InvalidICRKind iik = isInvalidICRSource(S.Context, src);
|
||||
InvalidICRKind iik = isInvalidICRSource(S.Context, src, false);
|
||||
if (iik == IIK_okay) return;
|
||||
|
||||
S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback)
|
||||
|
||||
@@ -592,3 +592,16 @@ int Test33(id someid) {
|
||||
@synthesize newName2;
|
||||
@end
|
||||
|
||||
void test35(void) {
|
||||
extern void test36_helper(id*);
|
||||
id x;
|
||||
__strong id *xp = 0;
|
||||
|
||||
test36_helper(&x);
|
||||
test36_helper(xp); // expected-error {{passing address of non-local object to __autoreleasing parameter for write-back}}
|
||||
|
||||
// rdar://problem/9665710
|
||||
__block id y;
|
||||
test36_helper(&y);
|
||||
^{ test36_helper(&y); }();
|
||||
}
|
||||
|
||||
@@ -58,15 +58,15 @@ void test_f2() {
|
||||
int &f3(id __autoreleasing *); // expected-note{{candidate function not viable: 1st argument ('__unsafe_unretained id *') has __unsafe_unretained ownership, but parameter has __autoreleasing ownership}}
|
||||
|
||||
void test_f3() {
|
||||
id __strong *sip;
|
||||
id __weak *wip;
|
||||
id __autoreleasing *aip;
|
||||
id __unsafe_unretained *uip;
|
||||
id __strong sip;
|
||||
id __weak wip;
|
||||
id __autoreleasing aip;
|
||||
id __unsafe_unretained uip;
|
||||
|
||||
int &ir1 = f3(sip);
|
||||
int &ir2 = f3(wip);
|
||||
int &ir3 = f3(aip);
|
||||
f3(uip); // expected-error{{no matching function for call to 'f3'}}
|
||||
int &ir1 = f3(&sip);
|
||||
int &ir2 = f3(&wip);
|
||||
int &ir3 = f3(&aip);
|
||||
f3(&uip); // expected-error{{no matching function for call to 'f3'}}
|
||||
}
|
||||
|
||||
// Writeback conversion vs. no conversion
|
||||
@@ -74,15 +74,15 @@ int &f4(id __autoreleasing *);
|
||||
float &f4(id __strong *);
|
||||
|
||||
void test_f4() {
|
||||
id __strong *sip;
|
||||
id __weak *wip;
|
||||
id __autoreleasing *aip;
|
||||
extern __weak id *weak_global_ptr;
|
||||
id __strong sip;
|
||||
id __weak wip;
|
||||
id __autoreleasing aip;
|
||||
extern __weak id weak_global_ptr;
|
||||
|
||||
float &fr1 = f4(sip);
|
||||
int &ir1 = f4(wip);
|
||||
int &ir2 = f4(aip);
|
||||
int &ir3 = f4(weak_global_ptr); // expected-error{{passing address of non-local object to __autoreleasing parameter for write-back}}
|
||||
float &fr1 = f4(&sip);
|
||||
int &ir1 = f4(&wip);
|
||||
int &ir2 = f4(&aip);
|
||||
int &ir3 = f4(&weak_global_ptr); // expected-error{{passing address of non-local object to __autoreleasing parameter for write-back}}
|
||||
}
|
||||
|
||||
// Writeback conversion vs. other conversion.
|
||||
@@ -90,13 +90,13 @@ int &f5(id __autoreleasing *);
|
||||
float &f5(id const __unsafe_unretained *);
|
||||
|
||||
void test_f5() {
|
||||
id __strong *sip;
|
||||
id __weak *wip;
|
||||
id __autoreleasing *aip;
|
||||
id __strong sip;
|
||||
id __weak wip;
|
||||
id __autoreleasing aip;
|
||||
|
||||
int &ir1 = f5(wip);
|
||||
float &fr1 = f5(sip);
|
||||
int &ir2 = f5(aip);
|
||||
int &ir1 = f5(&wip);
|
||||
float &fr1 = f5(&sip);
|
||||
int &ir2 = f5(&aip);
|
||||
}
|
||||
|
||||
@interface A
|
||||
@@ -106,13 +106,13 @@ int &f6(id __autoreleasing *);
|
||||
float &f6(id const __unsafe_unretained *);
|
||||
|
||||
void test_f6() {
|
||||
A* __strong *sip;
|
||||
A* __weak *wip;
|
||||
A* __autoreleasing *aip;
|
||||
A* __strong sip;
|
||||
A* __weak wip;
|
||||
A* __autoreleasing aip;
|
||||
|
||||
int &ir1 = f6(wip);
|
||||
float &fr1 = f6(sip);
|
||||
int &ir2 = f6(aip);
|
||||
int &ir1 = f6(&wip);
|
||||
float &fr1 = f6(&sip);
|
||||
int &ir2 = f6(&aip);
|
||||
}
|
||||
|
||||
// Reference binding
|
||||
|
||||
Reference in New Issue
Block a user