Merge block/function pointer types with objc's __weak
attribute properly and avoid bogus warning. This is
an objective-c fix only. objective-c++ follows different code
pass and requires separate fix (which will come at a later time).
Fixes radar 7214820.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95571 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 7e03f56..386a5f3 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4303,11 +4303,24 @@
   bool allRTypes = true;
 
   // Check return type
-  QualType retType = mergeTypes(lbase->getResultType(), rbase->getResultType());
+  QualType LRES = lbase->getResultType();
+  QualType RRES = rbase->getResultType();
+  Qualifiers::GC GC_L = LRES.getObjCGCAttr();
+  Qualifiers::GC GC_R = RRES.getObjCGCAttr();
+  // __weak/__strong attribute on one function/block return type but
+  // not the other is OK.
+  if (GC_L != GC_R) {
+    if (GC_R == Qualifiers::GCNone)
+      RRES = getObjCGCQualType(RRES, GC_L);
+    else if (GC_L == Qualifiers::GCNone)
+      LRES = getObjCGCQualType(LRES, GC_R);
+  }
+  
+  QualType retType = mergeTypes(LRES, RRES);
   if (retType.isNull()) return QualType();
-  if (getCanonicalType(retType) != getCanonicalType(lbase->getResultType()))
+  if (getCanonicalType(retType) != getCanonicalType(LRES))
     allLTypes = false;
-  if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
+  if (getCanonicalType(retType) != getCanonicalType(RRES))
     allRTypes = false;
   // FIXME: double check this
   bool NoReturn = lbase->getNoReturnAttr() || rbase->getNoReturnAttr();
diff --git a/test/SemaObjC/gc-attr-block-ivar.m b/test/SemaObjC/gc-attr-block-ivar.m
new file mode 100644
index 0000000..c3e0033
--- /dev/null
+++ b/test/SemaObjC/gc-attr-block-ivar.m
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -fblocks -fobjc-gc %s
+
+@interface Intf  {
+@public
+    void (^block) (id);
+    __weak void (^weak_block) (id);
+    void (*fptr) (id);
+    __weak void (*weak_fptr) (id);
+}
+@end
+
+int main() {
+    Intf *observer;
+    return (observer->block != observer->weak_block ||
+            observer->fptr != observer->weak_fptr);
+}
+
diff --git a/test/SemaObjC/objc2-merge-gc-attribue-decl.m b/test/SemaObjC/objc2-merge-gc-attribue-decl.m
index 673a741..f8d5f00 100644
--- a/test/SemaObjC/objc2-merge-gc-attribue-decl.m
+++ b/test/SemaObjC/objc2-merge-gc-attribue-decl.m
@@ -10,8 +10,8 @@
 extern id CFRunLoopGetMain();
 extern __strong id CFRunLoopGetMain();
 
-extern __weak id WLoopGetMain(); // expected-note {{previous declaration is here}}
-extern id WLoopGetMain();	// expected-error {{conflicting types for 'WLoopGetMain'}}
+extern __weak id WLoopGetMain(); 
+extern id WLoopGetMain();	
 
 extern id p3;	// expected-note {{previous definition is here}}
 extern __weak id p3;	// expected-error {{redefinition of 'p3' with a different type}}