[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