]> granicus.if.org Git - clang/commitdiff
RHS of property expression assignment requires
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 14 Sep 2010 23:02:38 +0000 (23:02 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 14 Sep 2010 23:02:38 +0000 (23:02 +0000)
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

include/clang/Sema/Sema.h
lib/AST/ExprClassification.cpp
lib/Sema/SemaExpr.cpp
test/CodeGenObjCXX/property-dot-copy.mm [new file with mode: 0644]

index 081ae60040adca0a6732d5193de8869a993f17f4..cd3aa7dce64b4a0706e6e9479ca7a24340e440ec 100644 (file)
@@ -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
index 6ca18a21ddc6163d7fd1bb1a2d4279fc0f005a53..b62a00f98e763f8fd3773c5fe4bba79767997f7e 100644 (file)
@@ -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.");
index 533d04f7ec9e04bc82c7a78f746008486008bbba..a99d118d2bc585e67a98aeeb4c67369a82ba8110 100644 (file)
@@ -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 (file)
index 0000000..35321ad
--- /dev/null
@@ -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;
+}