[cfe-commits] r147817 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/CodeGen/CGObjC.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaObjCProperty.cpp test/CodeGenObjCXX/property-object-reference-2.mm test/SemaObjCXX/property-reference.mm test/SemaObjCXX/property-synthesis-error.mm

Fariborz Jahanian fjahanian at apple.com
Mon Jan 9 16:37:02 PST 2012


Author: fjahanian
Date: Mon Jan  9 18:37:01 2012
New Revision: 147817

URL: http://llvm.org/viewvc/llvm-project?rev=147817&view=rev
Log:
objc++: patch for IRgen for atomic properties of
c++ objects with non-trivial assignment/copy functions.
Also, one additional sema check. // rdar://6137845

Added:
    cfe/trunk/test/CodeGenObjCXX/property-object-reference-2.mm
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/test/SemaObjCXX/property-reference.mm
    cfe/trunk/test/SemaObjCXX/property-synthesis-error.mm

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=147817&r1=147816&r2=147817&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan  9 18:37:01 2012
@@ -524,9 +524,9 @@
   InGroup<DiagGroup<"atomic-property-with-user-defined-accessor">>;
 def note_atomic_property_fixup_suggest : Note<"setter and getter must both be "
   "synthesized, or both be user defined,or the property must be nonatomic">;
-def warn_atomic_property_nontrivial_assign_op : Warning<
-  "atomic property of type %0 synthesizing setter using non-trivial assignment"
-  " operator">, InGroup<DiagGroup<"objc-property-atomic-setter-synthesis">>;
+def err_atomic_property_nontrivial_assign_op : Error<
+  "atomic property of reference type %0 cannot have non-trivial assignment"
+  " operator">;
 def warn_owning_getter_rule : Warning<
   "property's synthesized getter follows Cocoa naming"
   " convention for returning 'owned' objects">,

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=147817&r1=147816&r2=147817&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Jan  9 18:37:01 2012
@@ -565,7 +565,7 @@
 void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
                                          const ObjCPropertyImplDecl *PID) {
   llvm::Constant *AtomicHelperFn = 
-    GenerateObjCAtomicCopyHelperFunction(PID, false);
+    GenerateObjCAtomicGetterCopyHelperFunction(PID);
   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
   ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
   assert(OMD && "Invalid call to generate getter (empty method)");
@@ -599,15 +599,52 @@
   return false;
 }
 
+/// emitCPPObjectAtomicGetterCall - Call the runtime function to 
+/// copy the ivar into the resturn slot.
+static void emitCPPObjectAtomicGetterCall(CodeGenFunction &CGF, 
+                                          llvm::Value *returnAddr,
+                                          ObjCIvarDecl *ivar,
+                                          llvm::Constant *AtomicHelperFn) {
+  // objc_copyCppObjectAtomic (&returnSlot, &CppObjectIvar,
+  //                           AtomicHelperFn);
+  CallArgList args;
+  
+  // The 1st argument is the return Slot.
+  args.add(RValue::get(returnAddr), CGF.getContext().VoidPtrTy);
+  
+  // The 2nd argument is the address of the ivar.
+  llvm::Value *ivarAddr = 
+  CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), 
+                        CGF.LoadObjCSelf(), ivar, 0).getAddress();
+  ivarAddr = CGF.Builder.CreateBitCast(ivarAddr, CGF.Int8PtrTy);
+  args.add(RValue::get(ivarAddr), CGF.getContext().VoidPtrTy);
+  
+  // Third argument is the helper function.
+  args.add(RValue::get(AtomicHelperFn), CGF.getContext().VoidPtrTy);
+  
+  llvm::Value *copyCppAtomicObjectFn = 
+  CGF.CGM.getObjCRuntime().GetCppAtomicObjectFunction();
+  CGF.EmitCall(CGF.getTypes().getFunctionInfo(CGF.getContext().VoidTy, args,
+                                              FunctionType::ExtInfo()),
+               copyCppAtomicObjectFn, ReturnValueSlot(), args);
+}
+
 void
 CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
                                         const ObjCPropertyImplDecl *propImpl,
                                         llvm::Constant *AtomicHelperFn) {
   // If there's a non-trivial 'get' expression, we just have to emit that.
   if (!hasTrivialGetExpr(propImpl)) {
-    ReturnStmt ret(SourceLocation(), propImpl->getGetterCXXConstructor(),
-                   /*nrvo*/ 0);
-    EmitReturnStmt(ret);
+    if (!AtomicHelperFn) {
+      ReturnStmt ret(SourceLocation(), propImpl->getGetterCXXConstructor(),
+                     /*nrvo*/ 0);
+      EmitReturnStmt(ret);
+    }
+    else {
+      ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl();
+      emitCPPObjectAtomicGetterCall(*this, ReturnValue, 
+                                    ivar, AtomicHelperFn);
+    }
     return;
   }
 
@@ -817,6 +854,7 @@
 
 }
 
+
 static bool hasTrivialSetExpr(const ObjCPropertyImplDecl *PID) {
   Expr *setter = PID->getSetterCXXAssignment();
   if (!setter) return true;
@@ -993,7 +1031,7 @@
 void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
                                          const ObjCPropertyImplDecl *PID) {
   llvm::Constant *AtomicHelperFn = 
-    GenerateObjCAtomicCopyHelperFunction(PID, true);
+    GenerateObjCAtomicSetterCopyHelperFunction(PID);
   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
   ObjCMethodDecl *OMD = PD->getSetterMethodDecl();
   assert(OMD && "Invalid call to generate setter (empty method)");
@@ -2531,14 +2569,13 @@
   Builder.CreateCall(extender, object)->setDoesNotThrow();
 }
 
-/// GenerateObjCAtomicCopyHelperFunction - Given a c++ object type with
+/// GenerateObjCAtomicSetterCopyHelperFunction - Given a c++ object type with
 /// non-trivial copy assignment function, produce following helper function.
 /// static void copyHelper(Ty *dest, const Ty *source) { *dest = *source; }
 ///
 llvm::Constant *
-CodeGenFunction::GenerateObjCAtomicCopyHelperFunction(
-                                        const ObjCPropertyImplDecl *PID,
-                                        bool forSetter) {
+CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
+                                        const ObjCPropertyImplDecl *PID) {
   // FIXME. This api is for NeXt runtime only for now.
   if (!getLangOptions().CPlusPlus || !getLangOptions().NeXTRuntime)
     return 0;
@@ -2546,29 +2583,18 @@
   if (!Ty->isRecordType())
     return 0;
   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
-  if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic))
-      || /* temporary */ true) 
+  if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic)))
     return 0;
   llvm::Constant * HelperFn = 0;
-  if (forSetter) {
-    if (hasTrivialSetExpr(PID))
-      return 0;
-    assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null");
-    if ((HelperFn = CGM.getAtomicSetterHelperFnMap(Ty)))
-      return HelperFn;
-  }
-  else  {
-    if (hasTrivialGetExpr(PID))
-      return 0;
-    assert(PID->getGetterCXXConstructor() && "getGetterCXXConstructor - null");
-    if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty)))
-      return HelperFn;
-  }
-    
+  if (hasTrivialSetExpr(PID))
+    return 0;
+  assert(PID->getSetterCXXAssignment() && "SetterCXXAssignment - null");
+  if ((HelperFn = CGM.getAtomicSetterHelperFnMap(Ty)))
+    return HelperFn;
   
   ASTContext &C = getContext();
   IdentifierInfo *II
-    = &CGM.getContext().Idents.get("__copy_helper_atomic_property_");
+    = &CGM.getContext().Idents.get("__assign_helper_atomic_property_");
   FunctionDecl *FD = FunctionDecl::Create(C,
                                           C.getTranslationUnitDecl(),
                                           SourceLocation(),
@@ -2596,7 +2622,7 @@
   
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
-                           "__copy_helper_atomic_property_", &CGM.getModule());
+                           "__assign_helper_atomic_property_", &CGM.getModule());
   
   if (CGM.getModuleDebugInfo())
     DebugInfo = CGM.getModuleDebugInfo();
@@ -2619,8 +2645,7 @@
                                     VK_LValue, OK_Ordinary, SourceLocation());
   
   Expr *Args[2] = { DST, SRC };
-  CallExpr *CalleeExp = forSetter ? cast<CallExpr>(PID->getSetterCXXAssignment())
-                                  : cast<CallExpr>(PID->getGetterCXXConstructor());
+  CallExpr *CalleeExp = cast<CallExpr>(PID->getSetterCXXAssignment());
   CXXOperatorCallExpr *TheCall =
     new (C) CXXOperatorCallExpr(C, OO_Equal, CalleeExp->getCallee(),
                                 Args, 2, DestTy->getPointeeType(), 
@@ -2630,12 +2655,113 @@
 
   FinishFunction();
   HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
-  if (forSetter)
-    CGM.setAtomicSetterHelperFnMap(Ty, HelperFn);
-  else
-    CGM.setAtomicGetterHelperFnMap(Ty, HelperFn);
+  CGM.setAtomicSetterHelperFnMap(Ty, HelperFn);
   return HelperFn;
+}
+
+llvm::Constant *
+CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
+                                            const ObjCPropertyImplDecl *PID) {
+  // FIXME. This api is for NeXt runtime only for now.
+  if (!getLangOptions().CPlusPlus || !getLangOptions().NeXTRuntime)
+    return 0;
+  const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  QualType Ty = PD->getType();
+  if (!Ty->isRecordType())
+    return 0;
+  if ((!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic)))
+    return 0;
+  llvm::Constant * HelperFn = 0;
+  
+  if (hasTrivialGetExpr(PID))
+    return 0;
+  assert(PID->getGetterCXXConstructor() && "getGetterCXXConstructor - null");
+  if ((HelperFn = CGM.getAtomicGetterHelperFnMap(Ty)))
+    return HelperFn;
+  
   
+  ASTContext &C = getContext();
+  IdentifierInfo *II
+  = &CGM.getContext().Idents.get("__copy_helper_atomic_property_");
+  FunctionDecl *FD = FunctionDecl::Create(C,
+                                          C.getTranslationUnitDecl(),
+                                          SourceLocation(),
+                                          SourceLocation(), II, C.VoidTy, 0,
+                                          SC_Static,
+                                          SC_None,
+                                          false,
+                                          true);
+  
+  QualType DestTy = C.getPointerType(Ty);
+  QualType SrcTy = Ty;
+  SrcTy.addConst();
+  SrcTy = C.getPointerType(SrcTy);
+  
+  FunctionArgList args;
+  ImplicitParamDecl dstDecl(FD, SourceLocation(), 0, DestTy);
+  args.push_back(&dstDecl);
+  ImplicitParamDecl srcDecl(FD, SourceLocation(), 0, SrcTy);
+  args.push_back(&srcDecl);
+  
+  const CGFunctionInfo &FI =
+  CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo());
+  
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false);
+  
+  llvm::Function *Fn =
+  llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+                         "__copy_helper_atomic_property_", &CGM.getModule());
+  
+  if (CGM.getModuleDebugInfo())
+    DebugInfo = CGM.getModuleDebugInfo();
+  
+  
+  StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation());
+  
+  DeclRefExpr *SrcExpr = 
+  new (C) DeclRefExpr(&srcDecl, SrcTy,
+                      VK_RValue, SourceLocation());
+  
+  Expr* SRC = new (C) UnaryOperator(SrcExpr, UO_Deref, SrcTy->getPointeeType(),
+                                    VK_LValue, OK_Ordinary, SourceLocation());
+  
+  CXXConstructExpr *CXXConstExpr = 
+    cast<CXXConstructExpr>(PID->getGetterCXXConstructor());
+  
+  SmallVector<Expr*, 4> ConstructorArgs;
+  ConstructorArgs.push_back(SRC);
+  CXXConstructExpr::arg_iterator A = CXXConstExpr->arg_begin();
+  ++A;
+  
+  for (CXXConstructExpr::arg_iterator AEnd = CXXConstExpr->arg_end();
+       A != AEnd; ++A)
+    ConstructorArgs.push_back(*A);
+  
+  CXXConstructExpr *TheCXXConstructExpr =
+    CXXConstructExpr::Create(C, Ty, SourceLocation(),
+                             CXXConstExpr->getConstructor(),
+                             CXXConstExpr->isElidable(),
+                             &ConstructorArgs[0], ConstructorArgs.size(),
+                             CXXConstExpr->hadMultipleCandidates(), 
+                             CXXConstExpr->requiresZeroInitialization(),
+                             CXXConstExpr->getConstructionKind(), SourceRange());
+  
+  DeclRefExpr *DstExpr = 
+    new (C) DeclRefExpr(&dstDecl, DestTy,
+                        VK_RValue, SourceLocation());
+  
+  RValue DV = EmitAnyExpr(DstExpr);
+  CharUnits Alignment = getContext().getTypeAlignInChars(TheCXXConstructExpr->getType());
+  EmitAggExpr(TheCXXConstructExpr, 
+              AggValueSlot::forAddr(DV.getScalarVal(), Alignment, Qualifiers(),
+                                    AggValueSlot::IsDestructed,
+                                    AggValueSlot::DoesNotNeedGCBarriers,
+                                    AggValueSlot::IsNotAliased));
+  
+  FinishFunction();
+  HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+  CGM.setAtomicGetterHelperFnMap(Ty, HelperFn);
+  return HelperFn;
 }
 
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=147817&r1=147816&r2=147817&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Jan  9 18:37:01 2012
@@ -1335,9 +1335,10 @@
 
   llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo);
   llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo);
-  llvm::Constant *GenerateObjCAtomicCopyHelperFunction(
-                                             const ObjCPropertyImplDecl *PID,
-                                             bool forSetter);
+  llvm::Constant *GenerateObjCAtomicSetterCopyHelperFunction(
+                                             const ObjCPropertyImplDecl *PID);
+  llvm::Constant *GenerateObjCAtomicGetterCopyHelperFunction(
+                                             const ObjCPropertyImplDecl *PID);
 
   void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags);
 

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=147817&r1=147816&r2=147817&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Jan  9 18:37:01 2012
@@ -830,9 +830,13 @@
               dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
           if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
             if (!FuncDecl->isTrivial())
-              Diag(PropertyLoc, 
-                   diag::warn_atomic_property_nontrivial_assign_op) 
+              if (property->getType()->isReferenceType()) {
+                Diag(PropertyLoc, 
+                     diag::err_atomic_property_nontrivial_assign_op)
                     << property->getType();
+                Diag(FuncDecl->getLocStart(), 
+                     diag::note_callee_decl) << FuncDecl;
+              }
       }
       PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
     }

Added: cfe/trunk/test/CodeGenObjCXX/property-object-reference-2.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/property-object-reference-2.mm?rev=147817&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/property-object-reference-2.mm (added)
+++ cfe/trunk/test/CodeGenObjCXX/property-object-reference-2.mm Mon Jan  9 18:37:01 2012
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// rdar://6137845
+
+extern int DEFAULT();
+
+struct TCPPObject
+{
+ TCPPObject();
+ ~TCPPObject();
+ TCPPObject(const TCPPObject& inObj, int i = DEFAULT());
+ TCPPObject& operator=(const TCPPObject& inObj);
+ int filler[64];
+};
+
+
+ at interface MyDocument 
+{
+ at private
+ TCPPObject _cppObject;
+ TCPPObject _cppObject1;
+}
+ at property (assign, readwrite, atomic) const TCPPObject MyProperty;
+ at property (assign, readwrite, atomic) const TCPPObject MyProperty1;
+ at end
+
+ at implementation MyDocument
+  @synthesize MyProperty = _cppObject;
+  @synthesize MyProperty1 = _cppObject1;
+ at end
+
+// CHECK: define internal void @__copy_helper_atomic_property_(
+// CHECK: [[TWO:%.*]] = load %struct.TCPPObject** [[ADDR:%.*]], align 8
+// CHECK: [[THREE:%.*]] = load %struct.TCPPObject** [[ADDR1:%.*]], align 8
+// CHECK: [[CALL:%.*]] = call i32 @_Z7DEFAULTv()
+// CHECK:  call void @_ZN10TCPPObjectC1ERKS_i(%struct.TCPPObject* [[TWO]], %struct.TCPPObject* [[THREE]], i32 [[CALL]])
+// CHECK:  ret void
+
+// CHECK: define internal void @"\01-[MyDocument MyProperty]"(
+// CHECK: [[ONE:%.*]] = bitcast i8* [[ADDPTR:%.*]] to %struct.TCPPObject*
+// CHECK: [[TWO:%.*]] = bitcast %struct.TCPPObject* [[ONE]] to i8*
+// CHECK: [[THREE:%.*]] = bitcast %struct.TCPPObject* [[AGGRESULT:%.*]] to i8*
+// CHECK: call void @objc_copyCppObjectAtomic(i8* [[THREE]], i8* [[TWO]], i8* bitcast (void (%struct.TCPPObject*, %struct.TCPPObject*)* @__copy_helper_atomic_property_ to i8*))
+// CHECK: ret void
+
+// CHECK: define internal void @__assign_helper_atomic_property_(
+// CHECK: [[TWO:%.*]] = load %struct.TCPPObject** [[ADDR:%.*]], align 8
+// CHECK: [[THREE:%.*]] = load %struct.TCPPObject** [[ADDR1:%.*]], align 8
+// CHECK: [[CALL:%.*]] = call %struct.TCPPObject* @_ZN10TCPPObjectaSERKS_(%struct.TCPPObject* [[TWO]], %struct.TCPPObject* [[THREE]])
+// CHECK:  ret void
+
+// CHECK: define internal void @"\01-[MyDocument setMyProperty:]"(
+// CHECK: [[ONE:%.*]] = bitcast i8* [[ADDRPTR:%.*]] to %struct.TCPPObject*
+// CHECK: [[TWO:%.*]] = bitcast %struct.TCPPObject* [[ONE]] to i8*
+// CHECK: [[THREE:%.*]] = bitcast %struct.TCPPObject* [[MYPROPERTY:%.*]] to i8*
+// CHECK: call void @objc_copyCppObjectAtomic(i8* [[TWO]], i8* [[THREE]], i8* bitcast (void (%struct.TCPPObject*, %struct.TCPPObject*)* @__assign_helper_atomic_property_ to i8*))
+// CHECK: ret void

Modified: cfe/trunk/test/SemaObjCXX/property-reference.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/property-reference.mm?rev=147817&r1=147816&r2=147817&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/property-reference.mm (original)
+++ cfe/trunk/test/SemaObjCXX/property-reference.mm Mon Jan  9 18:37:01 2012
@@ -8,7 +8,7 @@
 	TCPPObject();
 	~TCPPObject();
 	
-	TCPPObject& operator=(const TCPPObject& inObj)const ;
+	TCPPObject& operator=(const TCPPObject& inObj)const ; // expected-note {{'operator=' declared here}}
 
 	void* Data();
 	
@@ -29,7 +29,7 @@
 @implementation TNSObject
 
 @synthesize cppObjectNonAtomic;
- at synthesize cppObjectAtomic; // expected-warning{{atomic property of type 'CREF_TCPPObject' (aka 'const TCPPObject &') synthesizing setter using non-trivial assignment operator}}
+ at synthesize cppObjectAtomic; // expected-error{{atomic property of reference type 'CREF_TCPPObject' (aka 'const TCPPObject &') cannot have non-trivial assignment operator}}
 @dynamic cppObjectDynamic;
 
 - (const TCPPObject&) cppObjectNonAtomic

Modified: cfe/trunk/test/SemaObjCXX/property-synthesis-error.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/property-synthesis-error.mm?rev=147817&r1=147816&r2=147817&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/property-synthesis-error.mm (original)
+++ cfe/trunk/test/SemaObjCXX/property-synthesis-error.mm Mon Jan  9 18:37:01 2012
@@ -38,7 +38,7 @@
  TCPPObject(const TCPPObject& inObj);
  TCPPObject();
  ~TCPPObject();
- TCPPObject& operator=(const TCPPObject& inObj);
+ TCPPObject& operator=(const TCPPObject& inObj); // expected-note {{'operator=' declared here}}
 private:
  void* fData;
 };
@@ -67,7 +67,7 @@
 
 @implementation MyDocument
 
- at synthesize cppObject = _cppObject; // expected-warning {{atomic property of type 'const TCPPObject &' synthesizing setter using non-trivial assignment operator}}
+ at synthesize cppObject = _cppObject; // expected-error {{atomic property of reference type 'const TCPPObject &' cannot have non-trivial assignment operator}}
 @synthesize ncppObject = _ncppObject;
 
 @synthesize tcppObject = _tcppObject;





More information about the cfe-commits mailing list