objc-arc: when 'assign' attribute is unspecified,
rely on property's type for its life-time to avoid
bogus warning with -Warc-unsafe-retained-assign.
// rdar://10694932


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148355 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index f653849..06525a4 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -4652,7 +4652,19 @@
 
 void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
                               Expr *LHS, Expr *RHS) {
-  QualType LHSType = LHS->getType();
+  QualType LHSType;
+  // PropertyRef on LHS type need be directly obtained from
+  // its declaration as it has a PsuedoType.
+  ObjCPropertyRefExpr *PRE
+    = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
+  if (PRE && !PRE->isImplicitProperty()) {
+    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
+    if (PD)
+      LHSType = PD->getType();
+  }
+  
+  if (LHSType.isNull())
+    LHSType = LHS->getType();
   if (checkUnsafeAssigns(Loc, LHSType, RHS))
     return;
   Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
@@ -4660,8 +4672,7 @@
   if (LT != Qualifiers::OCL_None)
     return;
   
-  if (ObjCPropertyRefExpr *PRE
-        = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens())) {
+  if (PRE) {
     if (PRE->isImplicitProperty())
       return;
     const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
@@ -4669,7 +4680,15 @@
       return;
     
     unsigned Attributes = PD->getPropertyAttributes();
-    if (Attributes & ObjCPropertyDecl::OBJC_PR_assign)
+    if (Attributes & ObjCPropertyDecl::OBJC_PR_assign) {
+      // when 'assign' attribute was not explicitly specified
+      // by user, ignore it and rely on property type itself
+      // for lifetime info.
+      unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten();
+      if (!(AsWrittenAttr & ObjCPropertyDecl::OBJC_PR_assign) &&
+          LHSType->isObjCRetainableType())
+        return;
+        
       while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
         if (cast->getCastKind() == CK_ARCConsumeObject) {
           Diag(Loc, diag::warn_arc_retained_property_assign)
@@ -4678,5 +4697,6 @@
         }
         RHS = cast->getSubExpr();
       }
+    }
   }
 }
diff --git a/test/SemaObjC/arc-property-lifetime.m b/test/SemaObjC/arc-property-lifetime.m
index 2c27a51..3fd845b 100644
--- a/test/SemaObjC/arc-property-lifetime.m
+++ b/test/SemaObjC/arc-property-lifetime.m
@@ -149,3 +149,22 @@
 }
 @end
 
+// rdar://10694932
+@interface Baz 
+@property  id prop;
+@property  __strong id strong_prop;
+@property  (strong) id strong_attr_prop;
+@property  (strong) __strong id realy_strong_attr_prop;
++ (id) alloc;
+- (id) init;
+- (id) implicit;
+- (void) setImplicit : (id) arg; 
+@end
+
+void foo(Baz *f) {
+        f.prop = [[Baz alloc] init];
+        f.strong_prop = [[Baz alloc] init];
+        f.strong_attr_prop = [[Baz alloc] init];
+        f.realy_strong_attr_prop = [[Baz alloc] init];
+        f.implicit = [[Baz alloc] init];
+}