Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -722,9 +722,7 @@
ASTContext &Context = getASTContext();
QualType T = Context.getBaseElementType(Field->getType());
if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
- if (!Context.getLangOpts().ObjCAutoRefCount) {
- setHasObjectMember(true);
- } else if (T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
+ if (T.hasNonTrivialObjCLifetime()) {
// Objective-C Automatic Reference Counting:
// If a class has a non-static data member of Objective-C pointer
// type (or array thereof), it is a non-POD type and its
@@ -736,6 +734,8 @@
Data.PlainOldData = false;
Data.HasTrivialSpecialMembers = 0;
Data.HasIrrelevantDestructor = false;
+ } else if (!Context.getLangOpts().ObjCAutoRefCount) {
+ setHasObjectMember(true);
}
} else if (!T.isCXX98PODType(Context))
data().PlainOldData = false;
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -4399,11 +4399,8 @@
}
}
- if (SemaRef.getLangOpts().ObjCAutoRefCount &&
- FieldBaseElementType->isObjCRetainableType() &&
- FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None &&
- FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
- // ARC:
+ if (FieldBaseElementType.hasNonTrivialObjCLifetime()) {
+ // ARC and Weak:
// Default-initialize Objective-C pointers to NULL.
CXXMemberInit
= new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
Index: test/CodeGenObjCXX/objc-weak.mm
===================================================================
--- /dev/null
+++ test/CodeGenObjCXX/objc-weak.mm
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-weak -fobjc-runtime-has-weak -std=c++11 -o - %s | FileCheck %s
+
+struct A { __weak id x; };
+
+id test0() {
+ A a;
+ A b = a;
+ A c(static_cast(b));
+ a = c;
+ c = static_cast(a);
+ return c.x;
+}
+
+// Copy Assignment Operator
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.A* @_ZN1AaSERKS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
+
+// Move Assignment Operator
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.A* @_ZN1AaSEOS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
+
+// Default Constructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AC2Ev(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: store i8* null, i8** [[T0]]
+
+// Copy Constructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AC2ERKS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: call void @objc_copyWeak(i8** [[T0]], i8** [[T1]])
+
+// Move Constructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AC2EOS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
+
+// Destructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AD2Ev(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
+