[cfe-commits] r167884 - in /cfe/trunk: lib/Sema/SemaPseudoObject.cpp test/CodeGenObjCXX/property-objects.mm test/SemaObjCXX/properties.mm
Eli Friedman
eli.friedman at gmail.com
Tue Nov 13 15:16:33 PST 2012
Author: efriedma
Date: Tue Nov 13 17:16:33 2012
New Revision: 167884
URL: http://llvm.org/viewvc/llvm-project?rev=167884&view=rev
Log:
Don't try to save the assigned value in a Objective-C property assignment
if the type of the value is a non-trivial class type. Fixes PR14318.
(There's a minor ObjC++ language change here: given that we can't save the
value, the type of the assignment expression is void in such cases.)
Modified:
cfe/trunk/lib/Sema/SemaPseudoObject.cpp
cfe/trunk/test/CodeGenObjCXX/property-objects.mm
cfe/trunk/test/SemaObjCXX/properties.mm
Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=167884&r1=167883&r2=167884&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Tue Nov 13 17:16:33 2012
@@ -198,7 +198,14 @@
}
/// Return true if assignments have a non-void result.
- virtual bool assignmentsHaveResult() { return true; }
+ bool CanCaptureValueOfType(QualType ty) {
+ assert(!ty->isIncompleteType());
+ assert(!ty->isDependentType());
+
+ if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl())
+ return ClassDecl->isTriviallyCopyable();
+ return true;
+ }
virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
virtual ExprResult buildGet() = 0;
@@ -380,7 +387,7 @@
// The result of the assignment, if not void, is the value set into
// the l-value.
- result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
+ result = buildSet(result.take(), opcLoc, /*captureSetValueAsResult*/ true);
if (result.isInvalid()) return ExprError();
addSemanticExpr(result.take());
@@ -404,7 +411,7 @@
QualType resultType = result.get()->getType();
// That's the postfix result.
- if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
+ if (UnaryOperator::isPostfix(opcode) && CanCaptureValueOfType(resultType)) {
result = capture(result.take());
setResultToLastSemantic();
}
@@ -423,8 +430,7 @@
// Store that back into the result. The value stored is the result
// of a prefix operation.
- result = buildSet(result.take(), opcLoc,
- UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
+ result = buildSet(result.take(), opcLoc, UnaryOperator::isPrefix(opcode));
if (result.isInvalid()) return ExprError();
addSemanticExpr(result.take());
@@ -696,7 +702,8 @@
ObjCMessageExpr *msgExpr =
cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
Expr *arg = msgExpr->getArg(0);
- msgExpr->setArg(0, captureValueAsResult(arg));
+ if (CanCaptureValueOfType(arg->getType()))
+ msgExpr->setArg(0, captureValueAsResult(arg));
}
return msg;
@@ -1312,7 +1319,8 @@
ObjCMessageExpr *msgExpr =
cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
Expr *arg = msgExpr->getArg(0);
- msgExpr->setArg(0, captureValueAsResult(arg));
+ if (CanCaptureValueOfType(arg->getType()))
+ msgExpr->setArg(0, captureValueAsResult(arg));
}
return msg;
Modified: cfe/trunk/test/CodeGenObjCXX/property-objects.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/property-objects.mm?rev=167884&r1=167883&r2=167884&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/property-objects.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/property-objects.mm Tue Nov 13 17:16:33 2012
@@ -1,8 +1,4 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
-// CHECK-NOT: callq _objc_msgSend_stret
-// CHECK: call void @_ZN1SC1ERKS_
-// CHECK: call %class.S* @_ZN1SaSERKS_
-// CHECK: call %struct.CGRect* @_ZN6CGRectaSERKS_
class S {
public:
@@ -19,13 +15,14 @@
S position;
CGRect bounds;
}
+
@property(assign, nonatomic) S position;
@property CGRect bounds;
@property CGRect frame;
- (void)setFrame:(CGRect)frameRect;
- (CGRect)frame;
- (void) initWithOwner;
-- (struct CGRect)extent;
+- (CGRect)extent;
- (void)dealloc;
@end
@@ -33,6 +30,11 @@
@synthesize position;
@synthesize bounds;
@synthesize frame;
+
+// CHECK: define internal void @"\01-[I setPosition:]"
+// CHECK: call %class.S* @_ZN1SaSERKS_
+// CHECK-NEXT: ret void
+
- (void)setFrame:(CGRect)frameRect {}
- (CGRect)frame {return bounds;}
@@ -42,14 +44,20 @@
labelLayerFrame = self.bounds;
_labelLayer.frame = labelLayerFrame;
}
+
// rdar://8366604
- (void)dealloc
{
CGRect cgrect = self.extent;
}
- (struct CGRect)extent {return bounds;}
+
@end
+// CHECK: define i32 @main
+// CHECK: call void @_ZN1SC1ERKS_(%class.S* [[AGGTMP:%[a-zA-Z0-9\.]+]], %class.S* {{%[a-zA-Z0-9\.]+}})
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %class.S*)*)(i8* {{%[a-zA-Z0-9\.]+}}, i8* {{%[a-zA-Z0-9\.]+}}, %class.S* [[AGGTMP]])
+// CHECK-NEXT: ret i32 0
int main() {
I *i;
S s1;
@@ -59,7 +67,9 @@
// rdar://8379892
// CHECK: define void @_Z1fP1A
-// CHECK: @objc_msgSend to void
+// CHECK: call void @_ZN1XC1Ev(%struct.X* [[LVTEMP:%[a-zA-Z0-9\.]+]])
+// CHECK: call void @_ZN1XC1ERKS_(%struct.X* [[AGGTMP:%[a-zA-Z0-9\.]+]], %struct.X* [[LVTEMP]])
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.X*)*)({{.*}} %struct.X* [[AGGTMP]])
struct X {
X();
X(const X&);
Modified: cfe/trunk/test/SemaObjCXX/properties.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/properties.mm?rev=167884&r1=167883&r2=167884&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/properties.mm (original)
+++ cfe/trunk/test/SemaObjCXX/properties.mm Tue Nov 13 17:16:33 2012
@@ -106,3 +106,26 @@
delete ptr.implicit_struct_property;
delete ptr.explicit_struct_property;
}
+
+// Make sure the returned value from property assignment is void,
+// because there isn't any other viable way to handle it for
+// non-trivial classes.
+class NonTrivial1 {
+public:
+ ~NonTrivial1();
+};
+class NonTrivial2 {
+public:
+ NonTrivial2();
+ NonTrivial2(const NonTrivial2&);
+};
+ at interface TestNonTrivial
+ at property(assign, nonatomic) NonTrivial1 p1;
+ at property(assign, nonatomic) NonTrivial2 p2;
+ at end
+TestNonTrivial *TestNonTrivialObj;
+
+extern void* VoidType;
+extern decltype(TestNonTrivialObj.p1 = NonTrivial1())* VoidType;
+extern decltype(TestNonTrivialObj.p2 = NonTrivial2())* VoidType;
+
More information about the cfe-commits
mailing list