[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes

2017-03-27 Thread Brian T. Kelley via Phabricator via cfe-commits
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


[PATCH] D31006: [Objective-C] Fix "weak-unavailable" warning with -fobjc-weak

2017-03-27 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-27 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak

2017-03-27 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31003: [Objective-C] C++ Classes with __weak Members non-POD Types when using -fobjc-weak

2017-03-27 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-24 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-24 Thread Brian T. Kelley via Phabricator via cfe-commits
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)
 

[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-24 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes

2017-03-24 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes

2017-03-24 Thread Brian T. Kelley via Phabricator via cfe-commits
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, 

[PATCH] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes

2017-03-23 Thread Brian T. Kelley via Phabricator via cfe-commits
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

2017-03-23 Thread Brian T. Kelley via Phabricator via cfe-commits
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)
 << 

[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak

2017-03-23 Thread Brian T. Kelley via Phabricator via cfe-commits
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);

[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak

2017-03-23 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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(), 

[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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 

[PATCH] D31006: [Objective-C] Fix "weak-unavailable" warning with -fobjc-weak

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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 *, CheckedConversionKind CCK,
- bool Diagnose,
- bool DiagnoseCFAudited,
- BinaryOperatorKind Opc) {
+Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
+  Expr *, 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, , CCK)
  .get();
 break;
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -7700,7 +7700,7 @@
   Kind = CK_BitCast;
   Sema::AssignConvertType 

[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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, 

[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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 )` 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

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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] D31003: [Objective-C] C++ Classes with __weak Members non-POD Types when using -fobjc-weak

2017-03-17 Thread Brian T. Kelley via Phabricator via cfe-commits
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  = getASTContext();
 QualType T = Context.getBaseElementType(Field->getType());
 if (T->isObjCRetainableType() 

[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-15 Thread Brian T. Kelley via Phabricator via cfe-commits
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 )` 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] D31007: [Objective-C] Miscellaneous -fobjc-weak Fixes

2017-03-15 Thread Brian T. Kelley via Phabricator via cfe-commits
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 &&
+   

[PATCH] D31006: [Objective-C] Fix "weak-unavailable" warning with -fobjc-weak

2017-03-15 Thread Brian T. Kelley via Phabricator via cfe-commits
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 *, CheckedConversionKind CCK,
- bool Diagnose,
- bool DiagnoseCFAudited,
- BinaryOperatorKind Opc) {
+Sema::CheckObjCConversion(SourceRange castRange, QualType castType,
+  Expr *, 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, , CCK)
  .get();
 break;
Index: lib/Sema/SemaExpr.cpp

[PATCH] D31005: [Objective-C] Fix "repeated use of weak" warning with -fobjc-weak

2017-03-15 Thread Brian T. Kelley via Phabricator via cfe-commits
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) &&
   

[PATCH] D31004: [Objective-C] Fix __weak type traits with -fobjc-weak

2017-03-15 Thread Brian T. Kelley via Phabricator via cfe-commits
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);

[PATCH] D31003: [Objective-C] C++ Classes with __weak Members non-POD Types when using -fobjc-weak

2017-03-15 Thread Brian T. Kelley via Phabricator via cfe-commits
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 &&
+