diff options
| author | Fariborz Jahanian <fjahanian@apple.com> | 2014-03-06 00:34:05 +0000 |
|---|---|---|
| committer | Fariborz Jahanian <fjahanian@apple.com> | 2014-03-06 00:34:05 +0000 |
| commit | 15dde89357c4a62a263cee0dddd52c8770a22cad (patch) | |
| tree | 590d39d5c4a07132e03ff0944a769043388d975f | |
| parent | bb29e518c80d672ce9413b9dc0f086a5eb5b463b (diff) | |
| download | bcm5719-llvm-15dde89357c4a62a263cee0dddd52c8770a22cad.tar.gz bcm5719-llvm-15dde89357c4a62a263cee0dddd52c8770a22cad.zip | |
Objective-C properties. Fixes a crash in Sema where RHS of
the property assignment is an lvalue for an incomplete type.
// rdar://15118128. Reviewed offline by John McCall.
llvm-svn: 203043
| -rw-r--r-- | clang/lib/Sema/SemaPseudoObject.cpp | 11 | ||||
| -rw-r--r-- | clang/test/CodeGenObjCXX/property-lvalue-capture.mm | 53 |
2 files changed, 60 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index 81657e366e5..0f1df58e6d1 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -235,7 +235,10 @@ namespace { } /// Return true if assignments have a non-void result. - bool CanCaptureValueOfType(QualType ty) { + bool CanCaptureValue(Expr *exp) { + if (exp->isGLValue()) + return true; + QualType ty = exp->getType(); assert(!ty->isIncompleteType()); assert(!ty->isDependentType()); @@ -461,7 +464,7 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, // That's the postfix result. if (UnaryOperator::isPostfix(opcode) && - (result.get()->isTypeDependent() || CanCaptureValueOfType(resultType))) { + (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) { result = capture(result.take()); setResultToLastSemantic(); } @@ -762,7 +765,7 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, ObjCMessageExpr *msgExpr = cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); Expr *arg = msgExpr->getArg(0); - if (CanCaptureValueOfType(arg->getType())) + if (CanCaptureValue(arg)) msgExpr->setArg(0, captureValueAsResult(arg)); } @@ -1368,7 +1371,7 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, ObjCMessageExpr *msgExpr = cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); Expr *arg = msgExpr->getArg(0); - if (CanCaptureValueOfType(arg->getType())) + if (CanCaptureValue(arg)) msgExpr->setArg(0, captureValueAsResult(arg)); } diff --git a/clang/test/CodeGenObjCXX/property-lvalue-capture.mm b/clang/test/CodeGenObjCXX/property-lvalue-capture.mm new file mode 100644 index 00000000000..a4024fd29a3 --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-lvalue-capture.mm @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// rdar://15118128 + +template <typename T> struct Quad2 { + Quad2() {} +}; + +typedef Quad2<double> Quad2d; + +@interface Root @end + +@interface PAGeometryFrame +- (const Quad2d &)quad; +- (void)setQuad:(const Quad2d &)quad; +@end + +@interface PA2DScaleTransform : Root +@end + +@implementation PA2DScaleTransform +- (void)transformFrame:(PAGeometryFrame *)frame { + PAGeometryFrame *result; + result.quad = frame.quad; +} +@end + +// CHECK: [[TWO:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", !invariant.load !5 +// CHECK: [[THREE:%.*]] = bitcast [[ONET:%.*]]* [[ONE:%.*]] to i8* +// CHECK: [[CALL:%.*]] = call %struct.Quad2* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to %struct.Quad2* (i8*, i8*)*)(i8* [[THREE]], i8* [[TWO]]) +// CHECK: [[FOUR:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_2", !invariant.load !5 +// CHECK: [[FIVE:%.*]] = bitcast [[ONET]]* [[ZERO:%.*]] to i8* +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.Quad2*)*)(i8* [[FIVE]], i8* [[FOUR]], %struct.Quad2* [[CALL]]) + + +struct A { + void *ptr; + A(); + A(const A &); + ~A(); +}; + +@interface C +- (void) setProp: (const A&) value; +@end +void test(C *c, const A &a) { + const A &result = c.prop = a; +} + +// CHECK: [[ONE1:%.*]] = load %struct.A** [[AADDR:%.*]], align 8 +// CHECK: [[TWO1:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_5", !invariant.load !5 +// CHECK: [[THREE1:%.*]] = bitcast [[TWOT:%.*]]* [[ZERO1:%.*]] to i8* +// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.A*)*)(i8* [[THREE1]], i8* [[TWO1]], %struct.A* [[ONE1]]) +// CHECK: store %struct.A* [[ONE1]], %struct.A** [[RESULT:%.*]], align 8 |

