aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2010-09-14 23:02:38 +0000
committerFariborz Jahanian <fjahanian@apple.com>2010-09-14 23:02:38 +0000
commitc4e1a6815235ade1a4affe3511ca5ce2dcc64467 (patch)
treef64a09c45be4cc8d3f1f853b637c9843f8efb62f
parent5833b0b831d6afae2885e6af420e2bda639652e6 (diff)
RHS of property expression assignment requires
copy initialization before passing it to a setter. Fixes radar 8427922. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113885 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/AST/ExprClassification.cpp3
-rw-r--r--lib/Sema/SemaExpr.cpp45
-rw-r--r--test/CodeGenObjCXX/property-dot-copy.mm34
4 files changed, 71 insertions, 14 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 081ae60040..cd3aa7dce6 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4107,6 +4107,9 @@ public:
// For compound assignment, pass both expressions and the converted type.
QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType);
+
+ void ConvertPropertyAssignment(Expr *LHS, Expr *&RHS, QualType& LHSTy);
+
QualType CheckCommaOperands( // C99 6.5.17
Expr *lex, Expr *&rex, SourceLocation OpLoc);
QualType CheckConditionalOperands( // C99 6.5.15
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 6ca18a21dd..b62a00f98e 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -478,7 +478,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
// Records with any const fields (recursively) are not modifiable.
if (const RecordType *R = CT->getAs<RecordType>()) {
- assert((isa<ObjCImplicitSetterGetterRefExpr>(E) ||
+ assert((isa<ObjCImplicitSetterGetterRefExpr>(E) ||
+ isa<ObjCPropertyRefExpr>(E) ||
!Ctx.getLangOptions().CPlusPlus) &&
"C++ struct assignment should be resolved by the "
"copy assignment operator.");
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 533d04f7ec..a99d118d2b 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -6016,17 +6016,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
if (CompoundType.isNull()) {
QualType LHSTy(LHSType);
// Simple assignment "x = y".
- if (const ObjCImplicitSetterGetterRefExpr *OISGE =
- dyn_cast<ObjCImplicitSetterGetterRefExpr>(LHS)) {
- // If using property-dot syntax notation for assignment, and there is a
- // setter, RHS expression is being passed to the setter argument. So,
- // type conversion (and comparison) is RHS to setter's argument type.
- if (const ObjCMethodDecl *SetterMD = OISGE->getSetterMethod()) {
- ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
- LHSTy = (*P)->getType();
- }
- }
-
+ ConvertPropertyAssignment(LHS, RHS, LHSTy);
ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
// Special case of NSObject attributes on c-style pointer types.
if (ConvTy == IncompatiblePointer &&
@@ -6181,6 +6171,34 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
? ResType : ResType.getUnqualifiedType();
}
+void Sema::ConvertPropertyAssignment(Expr *LHS, Expr *&RHS, QualType& LHSTy) {
+ bool copyInit = false;
+ if (const ObjCImplicitSetterGetterRefExpr *OISGE =
+ dyn_cast<ObjCImplicitSetterGetterRefExpr>(LHS)) {
+ // If using property-dot syntax notation for assignment, and there is a
+ // setter, RHS expression is being passed to the setter argument. So,
+ // type conversion (and comparison) is RHS to setter's argument type.
+ if (const ObjCMethodDecl *SetterMD = OISGE->getSetterMethod()) {
+ ObjCMethodDecl::param_iterator P = SetterMD->param_begin();
+ LHSTy = (*P)->getType();
+ }
+ copyInit = (getLangOptions().CPlusPlus && LHSTy->isRecordType());
+ }
+ else
+ copyInit = (getLangOptions().CPlusPlus && isa<ObjCPropertyRefExpr>(LHS) &&
+ LHSTy->isRecordType());
+ if (copyInit) {
+ InitializedEntity Entity =
+ InitializedEntity::InitializeParameter(LHSTy);
+ Expr *Arg = RHS;
+ ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(),
+ Owned(Arg));
+ if (!ArgE.isInvalid())
+ RHS = ArgE.takeAs<Expr>();
+ }
+}
+
+
/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
/// This routine allows us to typecheck complex/recursive expressions
/// where the declaration is needed for type checking. We only need to
@@ -6698,8 +6716,9 @@ ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *lhs, Expr *rhs) {
if (getLangOptions().CPlusPlus &&
- (!isa<ObjCImplicitSetterGetterRefExpr>(lhs) ||
- rhs->isTypeDependent()) &&
+ ((!isa<ObjCImplicitSetterGetterRefExpr>(lhs) &&
+ !isa<ObjCPropertyRefExpr>(lhs))
+ || rhs->isTypeDependent()) &&
(lhs->getType()->isOverloadableType() ||
rhs->getType()->isOverloadableType())) {
// Find all of the overloaded operators visible from this
diff --git a/test/CodeGenObjCXX/property-dot-copy.mm b/test/CodeGenObjCXX/property-dot-copy.mm
new file mode 100644
index 0000000000..35321ad5eb
--- /dev/null
+++ b/test/CodeGenObjCXX/property-dot-copy.mm
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -o - %s | FileCheck %s
+// rdar://8427922
+
+struct Vector3D
+{
+ float x, y, z;
+ Vector3D();
+ Vector3D(const Vector3D &inVector);
+ Vector3D(float initX, float initY, float initZ);
+ Vector3D &operator=(const Vector3D & rhs);
+};
+
+@interface Object3D
+{
+ Vector3D position;
+ Vector3D length;
+}
+@property (assign) Vector3D position;
+- (Vector3D) length;
+- (void) setLength: (Vector3D)arg;
+@end
+
+int main ()
+{
+ Object3D *myObject;
+ Vector3D V3D(1.0f, 1.0f, 1.0f);
+// CHECK: call void @_ZN8Vector3DC1ERKS_
+ myObject.position = V3D;
+
+// CHECK: call void @_ZN8Vector3DC1ERKS_
+ myObject.length = V3D;
+
+ return 0;
+}