[PATCH] D31003: [Objective-C] C++ Classes with __weak Members non-POD Types when using -fobjc-weak
bkelley created this revision. When adding an Objective-C retainable type member to a C++ class, also check the LangOpts.ObjCWeak flag and the lifetime qualifier so __weak qualified Objective-C pointer members cause the class to be a non-POD type with non-trivial special members, so the compiler always emits the necessary runtime calls for copying, moving, and destroying the weak member. Otherwise, Objective-C++ classes with weak Objective-C pointer members compiled with -fobjc-weak exhibit undefined behavior if the C++ class is classified as a POD type. https://reviews.llvm.org/D31003 Files: lib/AST/DeclCXX.cpp lib/Sema/SemaDeclCXX.cpp test/CodeGenObjCXX/objc-weak.mm 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]]) + Index: lib/Sema/SemaDeclCXX.cpp === --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -4399,11 +4399,13 @@ } } - if (SemaRef.getLangOpts().ObjCAutoRefCount && - FieldBaseElementType->isObjCRetainableType() && - FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None && - FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) { -// ARC: + if (FieldBaseElementType->isObjCRetainableType() && + ((SemaRef.getLangOpts().ObjCAutoRefCount && +FieldBa
[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak
bkelley created this revision. Similar to ARC, in ObjCWeak Objective-C object pointers qualified with a weak lifetime are not POD or trivial types. Update the type trait code to reflect this. Copy and adapt the arc-type-traits.mm test case to verify correctness. https://reviews.llvm.org/D31004 Files: lib/AST/Type.cpp lib/Sema/SemaExprCXX.cpp test/SemaObjCXX/objc-weak-type-traits.mm Index: test/SemaObjCXX/objc-weak-type-traits.mm === --- /dev/null +++ test/SemaObjCXX/objc-weak-type-traits.mm @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-weak -fobjc-runtime-has-weak -verify -std=c++11 %s +// expected-no-diagnostics + +// Check the results of the various type-trait query functions on +// lifetime-qualified types in ObjC Weak. + +#define TRAIT_IS_TRUE(Trait, Type) static_assert(Trait(Type), "") +#define TRAIT_IS_FALSE(Trait, Type) static_assert(!Trait(Type), "") +#define TRAIT_IS_TRUE_2(Trait, Type1, Type2) static_assert(Trait(Type1, Type2), "") +#define TRAIT_IS_FALSE_2(Trait, Type1, Type2) static_assert(!Trait(Type1, Type2), "") + +struct HasStrong { id obj; }; +struct HasWeak { __weak id obj; }; +struct HasUnsafeUnretained { __unsafe_unretained id obj; }; + +// __has_nothrow_assign +TRAIT_IS_TRUE(__has_nothrow_assign, __strong id); +TRAIT_IS_TRUE(__has_nothrow_assign, __weak id); +TRAIT_IS_TRUE(__has_nothrow_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_assign, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_assign, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_assign, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_assign, HasUnsafeUnretained); + +// __has_nothrow_copy +TRAIT_IS_TRUE(__has_nothrow_copy, __strong id); +TRAIT_IS_TRUE(__has_nothrow_copy, __weak id); +TRAIT_IS_TRUE(__has_nothrow_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_copy, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_copy, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_copy, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_copy, HasUnsafeUnretained); + +// __has_nothrow_constructor +TRAIT_IS_TRUE(__has_nothrow_constructor, __strong id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __weak id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasUnsafeUnretained); + +// __has_trivial_assign +TRAIT_IS_TRUE(__has_trivial_assign, __strong id); +TRAIT_IS_FALSE(__has_trivial_assign, __weak id); +TRAIT_IS_TRUE(__has_trivial_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_assign, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_assign, HasStrong); +TRAIT_IS_FALSE(__has_trivial_assign, HasWeak); +TRAIT_IS_TRUE(__has_trivial_assign, HasUnsafeUnretained); + +// __has_trivial_copy +TRAIT_IS_TRUE(__has_trivial_copy, __strong id); +TRAIT_IS_FALSE(__has_trivial_copy, __weak id); +TRAIT_IS_TRUE(__has_trivial_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_copy, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_copy, HasStrong); +TRAIT_IS_FALSE(__has_trivial_copy, HasWeak); +TRAIT_IS_TRUE(__has_trivial_copy, HasUnsafeUnretained); + +// __has_trivial_constructor +TRAIT_IS_TRUE(__has_trivial_constructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_constructor, __weak id); +TRAIT_IS_TRUE(__has_trivial_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_constructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_constructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_constructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_constructor, HasUnsafeUnretained); + +// __has_trivial_destructor +TRAIT_IS_TRUE(__has_trivial_destructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_destructor, __weak id); +TRAIT_IS_TRUE(__has_trivial_destructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_destructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_destructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_destructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_destructor, HasUnsafeUnretained); + +// __is_literal +TRAIT_IS_TRUE(__is_literal, __strong id); +TRAIT_IS_TRUE(__is_literal, __weak id); +TRAIT_IS_TRUE(__is_literal, __autoreleasing id); +TRAIT_IS_TRUE(__is_literal, __unsafe_unretained id); + +// __is_literal_type +TRAIT_IS_TRUE(__is_literal_type, __strong id); +TRAIT_IS_TRUE(__is_literal_type, __weak id); +TRAIT_IS_TRUE(__is_literal_type, __autoreleasing id); +TRAIT_IS_TRUE(__is_literal_type, __unsafe_unretained id); + +// __is_pod +TRAIT_IS_TRUE(__is_pod, __strong id); +TRAIT_IS_FALSE(__is_pod, __weak id); +TRAIT_IS_TRUE(__is_pod, __autoreleasing id); +TRAIT_IS_TRUE(__is_pod, __unsafe_unretained id); +TRAIT_IS_TRUE(__is_pod, HasStrong); +TRAIT_IS_FALSE(__is_pod, HasWeak); +TRAIT_IS_TRUE(__is_pod, HasUnsafeUnretained); + +// __is_trivial +TRAIT_IS_TRUE(__is_trivial, __strong id); +TRAIT_IS_FALSE(__is_tr
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley created this revision. -Warc-repeated-use-of-weak should produce the same warnings with -fobjc-weak as it does with -objc-arc. Also check for ObjCWeak along with ObjCAutoRefCount when recording the use of an evaluated weak variable. Add a -fobjc-weak run to the existing arc-repeated-weak test case and adapt it slightly to work in both modes. https://reviews.llvm.org/D31005 Files: lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprMember.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaPseudoObject.cpp test/SemaObjC/arc-repeated-weak.mm Index: test/SemaObjC/arc-repeated-weak.mm === --- test/SemaObjC/arc-repeated-weak.mm +++ test/SemaObjC/arc-repeated-weak.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s @interface Test { @public @@ -445,8 +446,8 @@ @class NSString; @interface NSBundle +(NSBundle *)foo; -@property (class) NSBundle *foo2; -@property NSString *prop; +@property (class, strong) NSBundle *foo2; +@property (strong) NSString *prop; @property(weak) NSString *weakProp; @end @@ -463,6 +464,8 @@ use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}} } +// With -fobjc-weak, the cast below is allowed. +#if __has_feature(objc_arc) // This used to crash in the constructor of WeakObjectProfileTy when a // DeclRefExpr was passed that didn't reference a VarDecl. @@ -475,3 +478,4 @@ void foo1() { INTFPtrTy tmp = (INTFPtrTy)e1; // expected-error{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}} } +#endif Index: lib/Sema/SemaPseudoObject.cpp === --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -841,7 +841,7 @@ result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); } } -if (S.getLangOpts().ObjCAutoRefCount) { +if (S.getLangOpts().ObjCAutoRefCount || S.getLangOpts().ObjCWeak) { Qualifiers::ObjCLifetime LT = propType.getObjCLifetime(); if (LT == Qualifiers::OCL_Weak) if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation())) @@ -962,11 +962,12 @@ } ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { - if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty() && + if ((S.getLangOpts().ObjCAutoRefCount || S.getLangOpts().ObjCWeak) && + isWeakProperty() && !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, SyntacticForm->getLocStart())) - S.recordUseOfEvaluatedWeak(SyntacticRefExpr, - SyntacticRefExpr->isMessagingGetter()); +S.recordUseOfEvaluatedWeak(SyntacticRefExpr, + SyntacticRefExpr->isMessagingGetter()); return PseudoOpBuilder::complete(SyntacticForm); } Index: lib/Sema/SemaExprObjC.cpp === --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -3100,7 +3100,9 @@ // In ARC, check for message sends which are likely to introduce // retain cycles. checkRetainCycles(Result); + } + if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) { if (!isImplicit && Method) { if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) { bool IsWeak = Index: lib/Sema/SemaExprMember.cpp === --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -1475,7 +1475,7 @@ } } bool warn = true; -if (S.getLangOpts().ObjCAutoRefCount) { +if (S.getLangOpts().ObjCAutoRefCount || S.getLangOpts().ObjCWeak) { Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); if (UnaryOperator *UO = dyn_cast(BaseExp)) if (UO->getOpcode() == UO_Deref) @@ -1502,7 +1502,7 @@ IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(), IsArrow); -if (S.getLangOpts().ObjCAutoRefCount) { +if (S.getLangOpts().ObjCAutoRefCount || S.getLangOpts().ObjCWeak) { if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) S.recordUseOfEvaluatedWeak(Result); Index: lib/Sema/SemaExpr.cpp === --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -704,7 +704,7 @@ // Loading a __weak object implicitly retains the value, so we need a cleanup to // balance that. - if (getLangOpts().ObjCAutoRefCount && + if ((getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) && E->getType().getObjCLifetime()
[PATCH] D31006: [Objective-C] Fix "weak-unavailable" warning with -fobjc-weak
bkelley created this revision. clang should produce the same errors Objective-C classes that cannot be assigned to weak pointers under both -fobjc-arc and -fobjc-weak. Check for ObjCWeak along with ObjCAutoRefCount when analyzing pointer conversions. Add an -fobjc-weak pass to the existing arc-unavailable-for-weakref test cases to verify the behavior is the same. https://reviews.llvm.org/D31006 Files: include/clang/Sema/Sema.h lib/Sema/SemaCast.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaPseudoObject.cpp test/SemaObjC/arc-unavailable-for-weakref.m test/SemaObjCXX/arc-unavailable-for-weakref.mm Index: test/SemaObjCXX/arc-unavailable-for-weakref.mm === --- test/SemaObjCXX/arc-unavailable-for-weakref.mm +++ test/SemaObjCXX/arc-unavailable-for-weakref.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-weak -verify %s // rdar://9693477 __attribute__((objc_arc_weak_reference_unavailable)) Index: test/SemaObjC/arc-unavailable-for-weakref.m === --- test/SemaObjC/arc-unavailable-for-weakref.m +++ test/SemaObjC/arc-unavailable-for-weakref.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-weak -verify -Wno-objc-root-class %s // rdar://9693477 __attribute__((objc_arc_weak_reference_unavailable)) Index: lib/Sema/SemaPseudoObject.cpp === --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -1128,8 +1128,8 @@ if (!Getter) return; QualType T = Getter->parameters()[0]->getType(); - S.CheckObjCARCConversion(Key->getSourceRange(), - T, Key, Sema::CCK_ImplicitConversion); + S.CheckObjCConversion(Key->getSourceRange(), T, Key, +Sema::CCK_ImplicitConversion); } bool ObjCSubscriptOpBuilder::findAtIndexGetter() { Index: lib/Sema/SemaExprObjC.cpp === --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -4108,11 +4108,10 @@ } Sema::ARCConversionResult -Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, - Expr *&castExpr, CheckedConversionKind CCK, - bool Diagnose, - bool DiagnoseCFAudited, - BinaryOperatorKind Opc) { +Sema::CheckObjCConversion(SourceRange castRange, QualType castType, + Expr *&castExpr, CheckedConversionKind CCK, + bool Diagnose, bool DiagnoseCFAudited, + BinaryOperatorKind Opc) { QualType castExprType = castExpr->getType(); // For the purposes of the classification, we assume reference types @@ -4152,7 +4151,12 @@ } return ACR_okay; } - + + // The life-time qualifier cast check above is all we need for ObjCWeak. + // ObjCAutoRefCount has more restrictions on what is legal. + if (!getLangOpts().ObjCAutoRefCount) +return ACR_okay; + if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; // Allow all of these types to be cast to integer types (but not Index: lib/Sema/SemaExprCXX.cpp === --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -3744,10 +3744,9 @@ if (From->getType()->isObjCObjectPointerType() && ToType->isObjCObjectPointerType()) EmitRelatedResultTypeNote(From); -} -else if (getLangOpts().ObjCAutoRefCount && - !CheckObjCARCUnavailableWeakConversion(ToType, -From->getType())) { +} else if ((getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) && + !CheckObjCARCUnavailableWeakConversion(ToType, + From->getType())) { if (Action == AA_Initializing) Diag(From->getLocStart(), diag::err_arc_weak_unavailable_assign); @@ -3770,8 +3769,8 @@ (void) PrepareCastToObjCObjectPointer(E); From = E.get(); } -if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), ToType, From, CCK); +if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) + CheckObjCConversion(SourceRange(), ToType, From, CCK); From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) .get(); break; Index: lib/Sema/
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley created this revision. After examining the remaining uses of LangOptions.ObjCAutoRefCount, found a some additional places to also check for ObjCWeak not covered by previous test cases. Added a test file to verify all the code paths that were changed. https://reviews.llvm.org/D31007 Files: lib/Sema/SemaCast.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaInit.cpp test/SemaObjCXX/objc-weak.mm Index: test/SemaObjCXX/objc-weak.mm === --- /dev/null +++ test/SemaObjCXX/objc-weak.mm @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++98 -Wno-c++0x-extensions -verify %s + +@interface AnObject +@property(weak) id value; +@end + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NOWEAK : AnObject // expected-note 2 {{class is declared here}} +@end + +struct S { + __weak id a; // expected-note {{because type 'S' has a member with __weak ownership}} +}; + +union U { + __weak id a; // expected-error {{ARC forbids Objective-C objects in union}} + S b; // expected-error {{union member 'b' has a non-trivial copy constructor}} +}; + +void testCast(AnObject *o) { + __weak id a = reinterpret_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} + + __weak id b = static_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} +} Index: lib/Sema/SemaInit.cpp === --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6680,6 +6680,8 @@ // full-expression's cleanups. if ((S.getLangOpts().ObjCAutoRefCount && MTE->getType()->isObjCLifetimeType()) || + (S.getLangOpts().ObjCWeak && + MTE->getType().getObjCLifetime() == Qualifiers::OCL_Weak) || (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType())) S.Cleanup.setExprNeedsCleanups(true); Index: lib/Sema/SemaDeclCXX.cpp === --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -7150,8 +7150,10 @@ // [...] nontrivally ownership-qualified types are [...] not trivially // default constructible, copy constructible, move constructible, copy // assignable, move assignable, or destructible [...] -if (S.getLangOpts().ObjCAutoRefCount && -FieldType.hasNonTrivialObjCLifetime()) { +if ((S.getLangOpts().ObjCAutoRefCount && + FieldType.hasNonTrivialObjCLifetime()) || +(S.getLangOpts().ObjCWeak && + FieldType.getObjCLifetime() == Qualifiers::OCL_Weak)) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) << RD << FieldType.getObjCLifetime(); Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -14493,7 +14493,7 @@ // Verify that all the fields are okay. SmallVector RecFields; - bool ARCErrReported = false; + bool ObjCFieldLifetimeErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); @@ -14628,16 +14628,20 @@ << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); -} else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported && +} else if ((getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) && + Record && !ObjCFieldLifetimeErrReported && (!getLangOpts().CPlusPlus || Record->isUnion())) { - // It's an error in ARC if a field has lifetime. + // It's an error in ARC or Weak if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. // FIXME: that's really not sufficient; we need to make the type // itself invalid to, say, initialize or copy. QualType T = FD->getType(); Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); - if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { + if (lifetime && + ((getLangOpts().ObjCAutoRefCount && +lifetime != Qua
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley added inline comments. Comment at: lib/Sema/SemaDecl.cpp:10184 + (!getLangOpts().ObjCAutoRefCount && getLangOpts().ObjCWeak && + VDecl->getType().getObjCLifetime() != Qualifiers::OCL_Weak)) && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, jordan_rose wrote: > This condition's getting complicated, and it shows up in a few places. Would > it make sense to factor it out? What do you think about adding a member function like `hasMRCNonTrivialWeakObjCLifetime(const ASTContext &Context)` to QualType to factor out lines 10183-10184? We could use that in D31003, D31004, here, and D31007. Comment at: lib/Sema/SemaExpr.cpp:10340 - } else if (getLangOpts().ObjCAutoRefCount) { + } else if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) { checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get()); jordan_rose wrote: > Does ObjCAutoRefCount imply ObjCWeak? If so, you could just use the latter. I don't believe so. For Snow Leopard, ARC without weak references was supported so they can be independent. https://reviews.llvm.org/D31005 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31003: [Objective-C] C++ Classes with __weak Members non-POD Types when using -fobjc-weak
bkelley updated this revision to Diff 92216. bkelley marked an inline comment as done. bkelley added a comment. Integrated feedback from @rjmccall https://reviews.llvm.org/D31003 Files: lib/AST/DeclCXX.cpp lib/Sema/SemaDeclCXX.cpp test/CodeGenObjCXX/objc-weak.mm 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]]) + 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: 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
[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak
bkelley updated this revision to Diff 92217. bkelley added a comment. Updated with feedback from @rjmccall https://reviews.llvm.org/D31004 Files: lib/AST/Type.cpp lib/Sema/SemaExprCXX.cpp test/SemaObjCXX/objc-weak-type-traits.mm Index: test/SemaObjCXX/objc-weak-type-traits.mm === --- /dev/null +++ test/SemaObjCXX/objc-weak-type-traits.mm @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-weak -fobjc-runtime-has-weak -verify -std=c++11 %s +// expected-no-diagnostics + +// Check the results of the various type-trait query functions on +// lifetime-qualified types in ObjC Weak. + +#define TRAIT_IS_TRUE(Trait, Type) static_assert(Trait(Type), "") +#define TRAIT_IS_FALSE(Trait, Type) static_assert(!Trait(Type), "") +#define TRAIT_IS_TRUE_2(Trait, Type1, Type2) static_assert(Trait(Type1, Type2), "") +#define TRAIT_IS_FALSE_2(Trait, Type1, Type2) static_assert(!Trait(Type1, Type2), "") + +struct HasStrong { id obj; }; +struct HasWeak { __weak id obj; }; +struct HasUnsafeUnretained { __unsafe_unretained id obj; }; + +// __has_nothrow_assign +TRAIT_IS_TRUE(__has_nothrow_assign, __strong id); +TRAIT_IS_TRUE(__has_nothrow_assign, __weak id); +TRAIT_IS_TRUE(__has_nothrow_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_assign, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_assign, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_assign, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_assign, HasUnsafeUnretained); + +// __has_nothrow_copy +TRAIT_IS_TRUE(__has_nothrow_copy, __strong id); +TRAIT_IS_TRUE(__has_nothrow_copy, __weak id); +TRAIT_IS_TRUE(__has_nothrow_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_copy, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_copy, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_copy, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_copy, HasUnsafeUnretained); + +// __has_nothrow_constructor +TRAIT_IS_TRUE(__has_nothrow_constructor, __strong id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __weak id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasUnsafeUnretained); + +// __has_trivial_assign +TRAIT_IS_TRUE(__has_trivial_assign, __strong id); +TRAIT_IS_FALSE(__has_trivial_assign, __weak id); +TRAIT_IS_TRUE(__has_trivial_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_assign, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_assign, HasStrong); +TRAIT_IS_FALSE(__has_trivial_assign, HasWeak); +TRAIT_IS_TRUE(__has_trivial_assign, HasUnsafeUnretained); + +// __has_trivial_copy +TRAIT_IS_TRUE(__has_trivial_copy, __strong id); +TRAIT_IS_FALSE(__has_trivial_copy, __weak id); +TRAIT_IS_TRUE(__has_trivial_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_copy, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_copy, HasStrong); +TRAIT_IS_FALSE(__has_trivial_copy, HasWeak); +TRAIT_IS_TRUE(__has_trivial_copy, HasUnsafeUnretained); + +// __has_trivial_constructor +TRAIT_IS_TRUE(__has_trivial_constructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_constructor, __weak id); +TRAIT_IS_TRUE(__has_trivial_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_constructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_constructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_constructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_constructor, HasUnsafeUnretained); + +// __has_trivial_destructor +TRAIT_IS_TRUE(__has_trivial_destructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_destructor, __weak id); +TRAIT_IS_TRUE(__has_trivial_destructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_destructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_destructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_destructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_destructor, HasUnsafeUnretained); + +// __is_literal +TRAIT_IS_TRUE(__is_literal, __strong id); +TRAIT_IS_TRUE(__is_literal, __weak id); +TRAIT_IS_TRUE(__is_literal, __autoreleasing id); +TRAIT_IS_TRUE(__is_literal, __unsafe_unretained id); + +// __is_literal_type +TRAIT_IS_TRUE(__is_literal_type, __strong id); +TRAIT_IS_TRUE(__is_literal_type, __weak id); +TRAIT_IS_TRUE(__is_literal_type, __autoreleasing id); +TRAIT_IS_TRUE(__is_literal_type, __unsafe_unretained id); + +// __is_pod +TRAIT_IS_TRUE(__is_pod, __strong id); +TRAIT_IS_FALSE(__is_pod, __weak id); +TRAIT_IS_TRUE(__is_pod, __autoreleasing id); +TRAIT_IS_TRUE(__is_pod, __unsafe_unretained id); +TRAIT_IS_TRUE(__is_pod, HasStrong); +TRAIT_IS_FALSE(__is_pod, HasWeak); +TRAIT_IS_TRUE(__is_pod, HasUnsafeUnretained); + +// __is_trivial +TRAIT_IS_TRUE(__is_trivial, __strong id); +TRAIT_IS_FALSE(__is_trivial, __weak id); +TRAIT_IS_TRUE(__is_trivial, __autoreleasing id); +TRAIT_IS_TRUE(__is_trivial, __unsafe_unretained id); +TRAIT_IS_TRUE(__is_trivial, HasStr
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley marked 3 inline comments as done. bkelley added inline comments. Comment at: lib/Sema/SemaDecl.cpp:10184 + (!getLangOpts().ObjCAutoRefCount && getLangOpts().ObjCWeak && + VDecl->getType().getObjCLifetime() != Qualifiers::OCL_Weak)) && !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, arphaman wrote: > jordan_rose wrote: > > bkelley wrote: > > > jordan_rose wrote: > > > > This condition's getting complicated, and it shows up in a few places. > > > > Would it make sense to factor it out? > > > What do you think about adding a member function like > > > `hasMRCNonTrivialWeakObjCLifetime(const ASTContext &Context)` to QualType > > > to factor out lines 10183-10184? We could use that in D31003, D31004, > > > here, and D31007. > > I'm fine with it myself but I don't work on Clang very much anymore. Maybe > > someone else can say whether it's actually a good idea. > > > > (By the way, the conventional abbreviation for this mode is "MRR" for > > "Manual Retain/Release", even though it's "ARC" and "Automated Reference > > Counting".) > Do you want to extract the out the entire > > ``` > (!getLangOpts().ObjCAutoRefCount && getLangOpts().ObjCWeak && > VDecl->getType().getObjCLifetime() != Qualifiers::OCL_Weak) > ``` > ? > > It looks like the others patches use only `getLangOpts().ObjCWeak && > Type.getObjCLifetime() != Qualifiers::OCL_Weak` so the use of > `hasMRCNonTrivialWeakObjCLifetime` won't be equivalent to the original code > in the other patches if you extract all code from lines 10183-10184. Yeah, my suspicion was that the addition of `!getLangOpts().ObjCAutoRefCount()` would have been fine, but most of the other code was simplified by using `hasNonTrivialObjCLifetime()` or another means, so this new function seems to only be necessary in this patch. I misnamed the proposed function, which would imply the qualifier is `OCL_Weak`, but we need //not// that, so my new proposed name is the odd looking `isNonWeakInMRRWithObjCWeak()`. Comment at: lib/Sema/SemaExpr.cpp:10340 - } else if (getLangOpts().ObjCAutoRefCount) { + } else if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) { checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get()); jordan_rose wrote: > bkelley wrote: > > jordan_rose wrote: > > > Does ObjCAutoRefCount imply ObjCWeak? If so, you could just use the > > > latter. > > I don't believe so. For Snow Leopard, ARC without weak references was > > supported so they can be independent. > Sure, but in that case we don't need the warning, right? Oh, I see. Yeah, looks like I can update most of the checks to just use ObjCWeak. I think we need both conditions here, however, since `checkUnsafeExprAssigns()` emits the "assigning retained object to unsafe property" warning, which is only applicable in ARC. https://reviews.llvm.org/D31005 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31003: [Objective-C] C++ Classes with __weak Members non-POD Types when using -fobjc-weak
bkelley marked 2 inline comments as done. bkelley added inline comments. Comment at: lib/Sema/SemaDeclCXX.cpp:4407 + (SemaRef.getLangOpts().ObjCWeak && +FieldBaseElementType.getObjCLifetime() == Qualifiers::OCL_Weak))) { +// ARC and Weak: rjmccall wrote: > I think this entire check can just be: > > if (FieldBaseElementType.hasNonTrivialObjCLifetime()) > > The language-options checks are almost certainly slower than just checking > the qualifiers. I see. `handleObjCOwnershipTypeAttr()` in SemaType.cpp only adds `OCL_Weak` or `OCL_ExplicitNone` outside of ARC and it's a compile error to use `__weak` without -fobjc-arc or -fobjc-weak, so `hasNonTrivialObjCLifetime()` is indeed much more simple. Thanks! https://reviews.llvm.org/D31003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak
bkelley added a comment. Looks like we can simplify everything by using `hasNonTrivialObjCLifetime()`, like in https://reviews.llvm.org/D31003. https://reviews.llvm.org/D31004 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31006: [Objective-C] Fix "weak-unavailable" warning with -fobjc-weak
bkelley updated this revision to Diff 92219. bkelley marked an inline comment as done. bkelley added a comment. Updated with feedback from @rjmccall https://reviews.llvm.org/D31006 Files: include/clang/Basic/LangOptions.h include/clang/Sema/Sema.h lib/Sema/SemaCast.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaPseudoObject.cpp test/SemaObjC/arc-unavailable-for-weakref.m test/SemaObjCXX/arc-unavailable-for-weakref.mm Index: test/SemaObjCXX/arc-unavailable-for-weakref.mm === --- test/SemaObjCXX/arc-unavailable-for-weakref.mm +++ test/SemaObjCXX/arc-unavailable-for-weakref.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-weak -verify %s // rdar://9693477 __attribute__((objc_arc_weak_reference_unavailable)) Index: test/SemaObjC/arc-unavailable-for-weakref.m === --- test/SemaObjC/arc-unavailable-for-weakref.m +++ test/SemaObjC/arc-unavailable-for-weakref.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-weak -verify -Wno-objc-root-class %s // rdar://9693477 __attribute__((objc_arc_weak_reference_unavailable)) Index: lib/Sema/SemaPseudoObject.cpp === --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -1127,8 +1127,8 @@ if (!Getter) return; QualType T = Getter->parameters()[0]->getType(); - S.CheckObjCARCConversion(Key->getSourceRange(), - T, Key, Sema::CCK_ImplicitConversion); + S.CheckObjCConversion(Key->getSourceRange(), T, Key, +Sema::CCK_ImplicitConversion); } bool ObjCSubscriptOpBuilder::findAtIndexGetter() { Index: lib/Sema/SemaExprObjC.cpp === --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -4108,11 +4108,10 @@ } Sema::ARCConversionResult -Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, - Expr *&castExpr, CheckedConversionKind CCK, - bool Diagnose, - bool DiagnoseCFAudited, - BinaryOperatorKind Opc) { +Sema::CheckObjCConversion(SourceRange castRange, QualType castType, + Expr *&castExpr, CheckedConversionKind CCK, + bool Diagnose, bool DiagnoseCFAudited, + BinaryOperatorKind Opc) { QualType castExprType = castExpr->getType(); // For the purposes of the classification, we assume reference types @@ -4152,7 +4151,12 @@ } return ACR_okay; } - + + // The life-time qualifier cast check above is all we need for ObjCWeak. + // ObjCAutoRefCount has more restrictions on what is legal. + if (!getLangOpts().ObjCAutoRefCount) +return ACR_okay; + if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; // Allow all of these types to be cast to integer types (but not Index: lib/Sema/SemaExprCXX.cpp === --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -3744,10 +3744,9 @@ if (From->getType()->isObjCObjectPointerType() && ToType->isObjCObjectPointerType()) EmitRelatedResultTypeNote(From); -} -else if (getLangOpts().ObjCAutoRefCount && - !CheckObjCARCUnavailableWeakConversion(ToType, -From->getType())) { +} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + !CheckObjCARCUnavailableWeakConversion(ToType, + From->getType())) { if (Action == AA_Initializing) Diag(From->getLocStart(), diag::err_arc_weak_unavailable_assign); @@ -3770,8 +3769,8 @@ (void) PrepareCastToObjCObjectPointer(E); From = E.get(); } -if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), ToType, From, CCK); +if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) + CheckObjCConversion(SourceRange(), ToType, From, CCK); From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) .get(); break; Index: lib/Sema/SemaExpr.cpp === --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -7700,7 +7700,7 @@ Kind = CK_BitCast; Sem
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley added a comment. Thanks for all the feedback! I think things are looking a lot better now. https://reviews.llvm.org/D31007 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31006: [Objective-C] Fix "weak-unavailable" warning with -fobjc-weak
bkelley marked an inline comment as done. bkelley added inline comments. Comment at: lib/Sema/SemaCast.cpp:125 + assert(Self.getLangOpts().ObjCAutoRefCount || + Self.getLangOpts().ObjCWeak); rjmccall wrote: > Unlike the other patches, we do clearly need to be checking the language > options in places like this. Still, it's a shame to repeat the same > condition in a million places. > > I think the right thing to do here is to add a helper method to LangOpts: > > /// Returns true if any types in the program might have non-trivial > lifetime qualifiers. > bool allowsNonTrivialObjCLifetimeQualifiers() const { > return ObjCAutoRefCount || ObjCWeak; > } Thanks for the suggestion. I was hesitant to add a method to LangOpts since it has so few derived state functions, but it certainly makes everything else cleaner. https://reviews.llvm.org/D31006 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley updated this revision to Diff 92218. bkelley added a comment. Updated with feedback from @jordan_rose and @arphaman https://reviews.llvm.org/D31005 Files: include/clang/AST/Type.h lib/AST/Type.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprMember.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaPseudoObject.cpp test/SemaObjC/arc-repeated-weak.mm Index: test/SemaObjC/arc-repeated-weak.mm === --- test/SemaObjC/arc-repeated-weak.mm +++ test/SemaObjC/arc-repeated-weak.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s @interface Test { @public @@ -445,8 +446,8 @@ @class NSString; @interface NSBundle +(NSBundle *)foo; -@property (class) NSBundle *foo2; -@property NSString *prop; +@property (class, strong) NSBundle *foo2; +@property (strong) NSString *prop; @property(weak) NSString *weakProp; @end @@ -473,5 +474,8 @@ }; void foo1() { - INTFPtrTy tmp = (INTFPtrTy)e1; // expected-error{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}} + INTFPtrTy tmp = (INTFPtrTy)e1; +#if __has_feature(objc_arc) +// expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}} +#endif } Index: lib/Sema/SemaPseudoObject.cpp === --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -841,7 +841,7 @@ result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); } } -if (S.getLangOpts().ObjCAutoRefCount) { +if (S.getLangOpts().ObjCWeak) { Qualifiers::ObjCLifetime LT = propType.getObjCLifetime(); if (LT == Qualifiers::OCL_Weak) if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation())) @@ -962,11 +962,11 @@ } ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { - if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty() && + if (S.getLangOpts().ObjCWeak && isWeakProperty() && !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, SyntacticForm->getLocStart())) - S.recordUseOfEvaluatedWeak(SyntacticRefExpr, - SyntacticRefExpr->isMessagingGetter()); +S.recordUseOfEvaluatedWeak(SyntacticRefExpr, + SyntacticRefExpr->isMessagingGetter()); return PseudoOpBuilder::complete(SyntacticForm); } Index: lib/Sema/SemaExprObjC.cpp === --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -3100,7 +3100,9 @@ // In ARC, check for message sends which are likely to introduce // retain cycles. checkRetainCycles(Result); + } + if (getLangOpts().ObjCWeak) { if (!isImplicit && Method) { if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) { bool IsWeak = Index: lib/Sema/SemaExprMember.cpp === --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -1475,7 +1475,7 @@ } } bool warn = true; -if (S.getLangOpts().ObjCAutoRefCount) { +if (S.getLangOpts().ObjCWeak) { Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); if (UnaryOperator *UO = dyn_cast(BaseExp)) if (UO->getOpcode() == UO_Deref) @@ -1502,7 +1502,7 @@ IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(), IsArrow); -if (S.getLangOpts().ObjCAutoRefCount) { +if (S.getLangOpts().ObjCWeak) { if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) S.recordUseOfEvaluatedWeak(Result); Index: lib/Sema/SemaExpr.cpp === --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -704,7 +704,7 @@ // Loading a __weak object implicitly retains the value, so we need a cleanup to // balance that. - if (getLangOpts().ObjCAutoRefCount && + if (getLangOpts().ObjCWeak && E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) Cleanup.setExprNeedsCleanups(true); @@ -2509,11 +2509,13 @@ ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc, IV->getLocation(), SelfExpr.get(), true, true); - if (getLangOpts().ObjCAutoRefCount) { + if (getLangOpts().ObjCWeak) { if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc)) recordUseOfEvaluatedWeak(Result); } + } + if (g
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley updated this revision to Diff 92220. bkelley added a comment. Integrated feedback from @rjmccall https://reviews.llvm.org/D31007 Files: include/clang/AST/Type.h lib/AST/Type.cpp lib/Sema/SemaCast.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaInit.cpp test/SemaObjCXX/objc-weak.mm Index: test/SemaObjCXX/objc-weak.mm === --- /dev/null +++ test/SemaObjCXX/objc-weak.mm @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++98 -Wno-c++0x-extensions -verify %s + +@interface AnObject +@property(weak) id value; +@end + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NOWEAK : AnObject // expected-note 2 {{class is declared here}} +@end + +struct S { + __weak id a; // expected-note {{because type 'S' has a member with __weak ownership}} +}; + +union U { + __weak id a; // expected-error {{ARC forbids Objective-C objects in union}} + S b; // expected-error {{union member 'b' has a non-trivial copy constructor}} +}; + +void testCast(AnObject *o) { + __weak id a = reinterpret_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} + + __weak id b = static_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} +} Index: lib/Sema/SemaInit.cpp === --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6678,8 +6678,7 @@ // need cleanups. Likewise if we're extending this temporary to automatic // storage duration -- we need to register its cleanup during the // full-expression's cleanups. - if ((S.getLangOpts().ObjCAutoRefCount && - MTE->getType()->isObjCLifetimeType()) || + if (MTE->getType()->isNonTrivialObjCLifetimeType() || (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType())) S.Cleanup.setExprNeedsCleanups(true); Index: lib/Sema/SemaDeclCXX.cpp === --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -7145,8 +7145,7 @@ // [...] nontrivally ownership-qualified types are [...] not trivially // default constructible, copy constructible, move constructible, copy // assignable, move assignable, or destructible [...] -if (S.getLangOpts().ObjCAutoRefCount && -FieldType.hasNonTrivialObjCLifetime()) { +if (FieldType.hasNonTrivialObjCLifetime()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) << RD << FieldType.getObjCLifetime(); Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -14492,7 +14492,7 @@ // Verify that all the fields are okay. SmallVector RecFields; - bool ARCErrReported = false; + bool ObjCFieldLifetimeErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); @@ -14627,16 +14627,16 @@ << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); -} else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported && +} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + Record && !ObjCFieldLifetimeErrReported && (!getLangOpts().CPlusPlus || Record->isUnion())) { - // It's an error in ARC if a field has lifetime. + // It's an error in ARC or Weak if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. // FIXME: that's really not sufficient; we need to make the type // itself invalid to, say, initialize or copy. QualType T = FD->getType(); - Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); - if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { + if (T.hasNonTrivialObjCLifetime()) { SourceLocation loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(loc)) { if (!FD->hasAttr()) { @@ -14647,7 +14647,7 @@ Diag(FD->getLocation(), diag::err_arc_objc_ob
[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak
bkelley added a comment. Thanks for the feedback! Apologies for the slow turn around; I was out sick :( Comment at: lib/AST/Type.cpp:2026 - if (Context.getLangOpts().ObjCAutoRefCount) { -switch (getObjCLifetime()) { -case Qualifiers::OCL_ExplicitNone: - return true; - -case Qualifiers::OCL_Strong: -case Qualifiers::OCL_Weak: -case Qualifiers::OCL_Autoreleasing: - return false; - -case Qualifiers::OCL_None: - break; -} - } + if (getQualifiers().hasObjCLifetime() && hasNonTrivialObjCLifetime()) +return false; rjmccall wrote: > Is the first condition not implied by the second? It definitely is. Thanks! https://reviews.llvm.org/D31004 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak
bkelley updated this revision to Diff 92890. bkelley marked an inline comment as done. bkelley added a comment. Removed redundant conditions, per feedback from @rjmccall https://reviews.llvm.org/D31004 Files: lib/AST/Type.cpp lib/Sema/SemaExprCXX.cpp test/SemaObjCXX/objc-weak-type-traits.mm Index: test/SemaObjCXX/objc-weak-type-traits.mm === --- /dev/null +++ test/SemaObjCXX/objc-weak-type-traits.mm @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-weak -fobjc-runtime-has-weak -verify -std=c++11 %s +// expected-no-diagnostics + +// Check the results of the various type-trait query functions on +// lifetime-qualified types in ObjC Weak. + +#define TRAIT_IS_TRUE(Trait, Type) static_assert(Trait(Type), "") +#define TRAIT_IS_FALSE(Trait, Type) static_assert(!Trait(Type), "") +#define TRAIT_IS_TRUE_2(Trait, Type1, Type2) static_assert(Trait(Type1, Type2), "") +#define TRAIT_IS_FALSE_2(Trait, Type1, Type2) static_assert(!Trait(Type1, Type2), "") + +struct HasStrong { id obj; }; +struct HasWeak { __weak id obj; }; +struct HasUnsafeUnretained { __unsafe_unretained id obj; }; + +// __has_nothrow_assign +TRAIT_IS_TRUE(__has_nothrow_assign, __strong id); +TRAIT_IS_TRUE(__has_nothrow_assign, __weak id); +TRAIT_IS_TRUE(__has_nothrow_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_assign, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_assign, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_assign, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_assign, HasUnsafeUnretained); + +// __has_nothrow_copy +TRAIT_IS_TRUE(__has_nothrow_copy, __strong id); +TRAIT_IS_TRUE(__has_nothrow_copy, __weak id); +TRAIT_IS_TRUE(__has_nothrow_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_copy, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_copy, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_copy, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_copy, HasUnsafeUnretained); + +// __has_nothrow_constructor +TRAIT_IS_TRUE(__has_nothrow_constructor, __strong id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __weak id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_nothrow_constructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasStrong); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasWeak); +TRAIT_IS_TRUE(__has_nothrow_constructor, HasUnsafeUnretained); + +// __has_trivial_assign +TRAIT_IS_TRUE(__has_trivial_assign, __strong id); +TRAIT_IS_FALSE(__has_trivial_assign, __weak id); +TRAIT_IS_TRUE(__has_trivial_assign, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_assign, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_assign, HasStrong); +TRAIT_IS_FALSE(__has_trivial_assign, HasWeak); +TRAIT_IS_TRUE(__has_trivial_assign, HasUnsafeUnretained); + +// __has_trivial_copy +TRAIT_IS_TRUE(__has_trivial_copy, __strong id); +TRAIT_IS_FALSE(__has_trivial_copy, __weak id); +TRAIT_IS_TRUE(__has_trivial_copy, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_copy, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_copy, HasStrong); +TRAIT_IS_FALSE(__has_trivial_copy, HasWeak); +TRAIT_IS_TRUE(__has_trivial_copy, HasUnsafeUnretained); + +// __has_trivial_constructor +TRAIT_IS_TRUE(__has_trivial_constructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_constructor, __weak id); +TRAIT_IS_TRUE(__has_trivial_constructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_constructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_constructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_constructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_constructor, HasUnsafeUnretained); + +// __has_trivial_destructor +TRAIT_IS_TRUE(__has_trivial_destructor, __strong id); +TRAIT_IS_FALSE(__has_trivial_destructor, __weak id); +TRAIT_IS_TRUE(__has_trivial_destructor, __autoreleasing id); +TRAIT_IS_TRUE(__has_trivial_destructor, __unsafe_unretained id); +TRAIT_IS_TRUE(__has_trivial_destructor, HasStrong); +TRAIT_IS_FALSE(__has_trivial_destructor, HasWeak); +TRAIT_IS_TRUE(__has_trivial_destructor, HasUnsafeUnretained); + +// __is_literal +TRAIT_IS_TRUE(__is_literal, __strong id); +TRAIT_IS_TRUE(__is_literal, __weak id); +TRAIT_IS_TRUE(__is_literal, __autoreleasing id); +TRAIT_IS_TRUE(__is_literal, __unsafe_unretained id); + +// __is_literal_type +TRAIT_IS_TRUE(__is_literal_type, __strong id); +TRAIT_IS_TRUE(__is_literal_type, __weak id); +TRAIT_IS_TRUE(__is_literal_type, __autoreleasing id); +TRAIT_IS_TRUE(__is_literal_type, __unsafe_unretained id); + +// __is_pod +TRAIT_IS_TRUE(__is_pod, __strong id); +TRAIT_IS_FALSE(__is_pod, __weak id); +TRAIT_IS_TRUE(__is_pod, __autoreleasing id); +TRAIT_IS_TRUE(__is_pod, __unsafe_unretained id); +TRAIT_IS_TRUE(__is_pod, HasStrong); +TRAIT_IS_FALSE(__is_pod, HasWeak); +TRAIT_IS_TRUE(__is_pod, HasUnsafeUnretained); + +// __is_trivial +TRAIT_IS_TRUE(__is_trivial, __strong id); +TRAIT_IS_FALSE(__is_trivial, __weak id); +TRAIT_IS_TRUE(__is_trivial, __autoreleasing id); +TRAIT_IS_TRUE(__is_trivia
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley updated this revision to Diff 92892. https://reviews.llvm.org/D31007 Files: include/clang/AST/Type.h lib/AST/Type.cpp lib/Sema/SemaCast.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaInit.cpp test/SemaObjCXX/objc-weak.mm Index: test/SemaObjCXX/objc-weak.mm === --- /dev/null +++ test/SemaObjCXX/objc-weak.mm @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++98 -Wno-c++0x-extensions -verify %s + +@interface AnObject +@property(weak) id value; +@end + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NOWEAK : AnObject // expected-note 2 {{class is declared here}} +@end + +struct S { + __weak id a; // expected-note {{because type 'S' has a member with __weak ownership}} +}; + +union U { + __weak id a; // expected-error {{ARC forbids Objective-C objects in union}} + S b; // expected-error {{union member 'b' has a non-trivial copy constructor}} +}; + +void testCast(AnObject *o) { + __weak id a = reinterpret_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} + + __weak id b = static_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} +} Index: lib/Sema/SemaInit.cpp === --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6678,8 +6678,7 @@ // need cleanups. Likewise if we're extending this temporary to automatic // storage duration -- we need to register its cleanup during the // full-expression's cleanups. - if ((S.getLangOpts().ObjCAutoRefCount && - MTE->getType()->isObjCLifetimeType()) || + if (MTE->getType()->isNonTrivialObjCLifetimeType() || (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType())) S.Cleanup.setExprNeedsCleanups(true); Index: lib/Sema/SemaDeclCXX.cpp === --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -7145,8 +7145,7 @@ // [...] nontrivally ownership-qualified types are [...] not trivially // default constructible, copy constructible, move constructible, copy // assignable, move assignable, or destructible [...] -if (S.getLangOpts().ObjCAutoRefCount && -FieldType.hasNonTrivialObjCLifetime()) { +if (FieldType.hasNonTrivialObjCLifetime()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) << RD << FieldType.getObjCLifetime(); Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -14492,7 +14492,7 @@ // Verify that all the fields are okay. SmallVector RecFields; - bool ARCErrReported = false; + bool ObjCFieldLifetimeErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); @@ -14627,16 +14627,16 @@ << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); -} else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported && +} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + Record && !ObjCFieldLifetimeErrReported && (!getLangOpts().CPlusPlus || Record->isUnion())) { - // It's an error in ARC if a field has lifetime. + // It's an error in ARC or Weak if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. // FIXME: that's really not sufficient; we need to make the type // itself invalid to, say, initialize or copy. QualType T = FD->getType(); - Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); - if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { + if (T.hasNonTrivialObjCLifetime()) { SourceLocation loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(loc)) { if (!FD->hasAttr()) { @@ -14647,7 +14647,7 @@ Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) << T->isBlockPointerType() << Record
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley added inline comments. Comment at: lib/AST/Type.cpp:3773 +/// lifetime semantics. +bool Type::isNonTrivialObjCLifetimeType() const { + return CanonicalType.hasNonTrivialObjCLifetime(); rjmccall wrote: > Is this method not identical in behavior to hasNonTrivialObjCLifetime()? Yes, but I didn't see how to extract that information, which is on the internal QualType. But after examining the usage of this function in SemaInit.cpp:6681, I think we need something similar to the isObjCLifetimeType() implementation above. https://reviews.llvm.org/D31007 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley updated this revision to Diff 92966. bkelley marked an inline comment as done. bkelley added a comment. Updated with latest feedback from @rjmccall https://reviews.llvm.org/D31007 Files: lib/Sema/SemaCast.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaInit.cpp test/SemaObjCXX/objc-weak.mm Index: test/SemaObjCXX/objc-weak.mm === --- /dev/null +++ test/SemaObjCXX/objc-weak.mm @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++98 -Wno-c++0x-extensions -verify %s + +@interface AnObject +@property(weak) id value; +@end + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NOWEAK : AnObject // expected-note 2 {{class is declared here}} +@end + +struct S { + __weak id a; // expected-note {{because type 'S' has a member with __weak ownership}} +}; + +union U { + __weak id a; // expected-error {{ARC forbids Objective-C objects in union}} + S b; // expected-error {{union member 'b' has a non-trivial copy constructor}} +}; + +void testCast(AnObject *o) { + __weak id a = reinterpret_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} + + __weak id b = static_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} +} Index: lib/Sema/SemaInit.cpp === --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6674,14 +6674,10 @@ /*IsInitializerList=*/false, ExtendingEntity->getDecl()); - // If we're binding to an Objective-C object that has lifetime, we - // need cleanups. Likewise if we're extending this temporary to automatic - // storage duration -- we need to register its cleanup during the - // full-expression's cleanups. - if ((S.getLangOpts().ObjCAutoRefCount && - MTE->getType()->isObjCLifetimeType()) || - (MTE->getStorageDuration() == SD_Automatic && - MTE->getType().isDestructedType())) + // If we're extending this temporary to automatic storage duration -- we + // need to register its cleanup during the full-expression's cleanups. + if (MTE->getStorageDuration() == SD_Automatic && + MTE->getType().isDestructedType()) S.Cleanup.setExprNeedsCleanups(true); CurInit = MTE; Index: lib/Sema/SemaDeclCXX.cpp === --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -7145,8 +7145,7 @@ // [...] nontrivally ownership-qualified types are [...] not trivially // default constructible, copy constructible, move constructible, copy // assignable, move assignable, or destructible [...] -if (S.getLangOpts().ObjCAutoRefCount && -FieldType.hasNonTrivialObjCLifetime()) { +if (FieldType.hasNonTrivialObjCLifetime()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) << RD << FieldType.getObjCLifetime(); Index: lib/Sema/SemaDecl.cpp === --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -14492,7 +14492,7 @@ // Verify that all the fields are okay. SmallVector RecFields; - bool ARCErrReported = false; + bool ObjCFieldLifetimeErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); @@ -14627,16 +14627,16 @@ << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); -} else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported && +} else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + Record && !ObjCFieldLifetimeErrReported && (!getLangOpts().CPlusPlus || Record->isUnion())) { - // It's an error in ARC if a field has lifetime. + // It's an error in ARC or Weak if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. // FIXME: that's really not sufficient; we need to make the type // itself invalid to, say, initialize or c
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley added inline comments. Comment at: lib/Sema/SemaInit.cpp:6681 // full-expression's cleanups. - if ((S.getLangOpts().ObjCAutoRefCount && - MTE->getType()->isObjCLifetimeType()) || + if (MTE->getType()->isNonTrivialObjCLifetimeType() || (MTE->getStorageDuration() == SD_Automatic && rjmccall wrote: > Oh, I see what's happening here. The special case for ARC is actually wholly > unnecessary. The code's been written as if MTE->getType() for an ARC > temporary will just have type "id". In fact, it'll have a lifetime-qualified > type, dependent on the type of the reference which has been bound to it. So > we need to mark that there's a temporary cleanup if the type has non-trivial > lifetime, i.e. if MTE->getType().hasNonTrivialObjCLifetime(); but this is > already considered as part of MTE->getType().isDestructedType(), and the > storage-duration condition there is correct as well. So really we should > just delete this entire clause. > > That should eliminate the need for Type::isNonTrivialObjCLifetimeType(). In > general, we don't want methods like that to ever exist: lifetime is > determined by qualifiers, and querying a Type instead of a QualType has the > potential to implicitly remove qualifiers. Thanks for looking in to this and for the explanation. I've removed the check and the changes to Type. https://reviews.llvm.org/D31007 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley added a comment. Thanks again for the feedback. Is there anything further I should update in this diff or is it looking good? Thanks! Brian https://reviews.llvm.org/D31005 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley updated this revision to Diff 93023. bkelley marked 4 inline comments as done. bkelley added a comment. Updated with feedback from @rjmccall https://reviews.llvm.org/D31005 Files: include/clang/AST/Type.h lib/AST/Type.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprMember.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaPseudoObject.cpp test/SemaObjC/arc-repeated-weak.mm Index: test/SemaObjC/arc-repeated-weak.mm === --- test/SemaObjC/arc-repeated-weak.mm +++ test/SemaObjC/arc-repeated-weak.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s @interface Test { @public @@ -445,8 +446,8 @@ @class NSString; @interface NSBundle +(NSBundle *)foo; -@property (class) NSBundle *foo2; -@property NSString *prop; +@property (class, strong) NSBundle *foo2; +@property (strong) NSString *prop; @property(weak) NSString *weakProp; @end @@ -473,5 +474,8 @@ }; void foo1() { - INTFPtrTy tmp = (INTFPtrTy)e1; // expected-error{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}} + INTFPtrTy tmp = (INTFPtrTy)e1; +#if __has_feature(objc_arc) +// expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}} +#endif } Index: lib/Sema/SemaPseudoObject.cpp === --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -841,12 +841,10 @@ result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); } } -if (S.getLangOpts().ObjCAutoRefCount) { - Qualifiers::ObjCLifetime LT = propType.getObjCLifetime(); - if (LT == Qualifiers::OCL_Weak) -if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation())) - S.getCurFunction()->markSafeWeakUse(RefExpr); -} +if (propType.getObjCLifetime() == Qualifiers::OCL_Weak && +!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, + RefExpr->getLocation())) + S.getCurFunction()->markSafeWeakUse(RefExpr); } return result; @@ -962,11 +960,11 @@ } ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { - if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty() && + if (isWeakProperty() && !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, SyntacticForm->getLocStart())) - S.recordUseOfEvaluatedWeak(SyntacticRefExpr, - SyntacticRefExpr->isMessagingGetter()); +S.recordUseOfEvaluatedWeak(SyntacticRefExpr, + SyntacticRefExpr->isMessagingGetter()); return PseudoOpBuilder::complete(SyntacticForm); } Index: lib/Sema/SemaExprObjC.cpp === --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -3100,7 +3100,9 @@ // In ARC, check for message sends which are likely to introduce // retain cycles. checkRetainCycles(Result); + } + if (getLangOpts().ObjCWeak) { if (!isImplicit && Method) { if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) { bool IsWeak = Index: lib/Sema/SemaExprMember.cpp === --- lib/Sema/SemaExprMember.cpp +++ lib/Sema/SemaExprMember.cpp @@ -1475,7 +1475,7 @@ } } bool warn = true; -if (S.getLangOpts().ObjCAutoRefCount) { +if (S.getLangOpts().ObjCWeak) { Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); if (UnaryOperator *UO = dyn_cast(BaseExp)) if (UO->getOpcode() == UO_Deref) @@ -1502,11 +1502,9 @@ IV, IV->getUsageType(BaseType), MemberLoc, OpLoc, BaseExpr.get(), IsArrow); -if (S.getLangOpts().ObjCAutoRefCount) { - if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { -if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) - S.recordUseOfEvaluatedWeak(Result); - } +if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, MemberLoc)) +S.recordUseOfEvaluatedWeak(Result); } return Result; Index: lib/Sema/SemaExpr.cpp === --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -704,8 +704,7 @@ // Loading a __weak object implicitly retains the value, so we need a cleanup to // balance that. - if (getLangOpts().ObjCAutoRefCount && - E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) + if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) Cleanup.setExpr
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley added a comment. Sorry for missing the unnecessary LangOpts checks here. Thanks again for the feedback! https://reviews.llvm.org/D31005 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak
bkelley added a comment. Thank you @rjmccall for the approval. I don't have commit access; would someone be willing to commit this path for me please? Thanks! https://reviews.llvm.org/D31004 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak
bkelley added a comment. Thank you @rjmccall for the approval. I don't have commit access; would someone be willing to commit this path for me please? Thanks! https://reviews.llvm.org/D31005 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31003: [Objective-C] C++ Classes with __weak Members non-POD Types when using -fobjc-weak
bkelley added a comment. Thank you @rjmccall for the approval. I don't have commit access; would someone be willing to commit this path for me please? Thanks! https://reviews.llvm.org/D31003 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31006: [Objective-C] Fix "weak-unavailable" warning with -fobjc-weak
bkelley added a comment. Thank you @rjmccall for the approval. I don't have commit access; would someone be willing to commit this path for me please? Thanks! https://reviews.llvm.org/D31006 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes
bkelley added a comment. Thank you @rjmccall for the approval. I don't have commit access; would someone be willing to commit this path for me please? Thanks! https://reviews.llvm.org/D31007 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits