From d263fd1451299b1e5f5f1acb2bb13b0a4119aee8 Mon Sep 17 00:00:00 2001
From: Fariborz Jahanian <fjahanian@apple.com>
Date: Fri, 11 Feb 2011 18:46:17 +0000
Subject: [PATCH] Fix a block sema bug where result type of initializer is
 unqualified but its initialized is qualified. This is for c only and fixes
 the imm. problem. c++ is more involved and is wip. // rdar://8979379

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125386 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/AST/ASTContext.cpp       | 11 ++++++++---
 test/Sema/block-call.c       |  2 +-
 test/Sema/block-return.c     |  2 +-
 test/SemaObjC/block-return.m | 13 +++++++++++++
 4 files changed, 23 insertions(+), 5 deletions(-)
 create mode 100644 test/SemaObjC/block-return.m

diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 03c0abd3c62..dcbfd9deec5 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -5076,9 +5076,14 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
 
   // Check return type
   QualType retType;
-  if (OfBlockPointer)
-    retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true,
-                         Unqualified);
+  if (OfBlockPointer) {
+    QualType RHS = rbase->getResultType();
+    QualType LHS = lbase->getResultType();
+    bool UnqualifiedResult = Unqualified;
+    if (!UnqualifiedResult)
+      UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers());
+    retType = mergeTypes(RHS, LHS, true, UnqualifiedResult);
+  }
   else
     retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), false,
                          Unqualified);
diff --git a/test/Sema/block-call.c b/test/Sema/block-call.c
index fbf0da4eb8b..2aa1422dd91 100644
--- a/test/Sema/block-call.c
+++ b/test/Sema/block-call.c
@@ -13,7 +13,7 @@ int main() {
   int (^IFP) () = PFR; // OK
 
 
-  const int (^CIC) () = IFP; // expected-error {{incompatible block pointer types initializing 'const int (^)()' with an expression of type 'int (^)()'}}
+  const int (^CIC) () = IFP; // OK -  initializing 'const int (^)()' with an expression of type 'int (^)()'}}
 
   const int (^CICC) () = CIC;
 
diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c
index 23dbbc2ce66..c6e1e9dc542 100644
--- a/test/Sema/block-return.c
+++ b/test/Sema/block-return.c
@@ -110,7 +110,7 @@ void foo6() {
 
 void foo7()
 {
- const int (^BB) (void) = ^{ const int i = 1; return i; }; // expected-error{{incompatible block pointer types initializing 'const int (^)(void)' with an expression of type 'int (^)(void)'}}
+ const int (^BB) (void) = ^{ const int i = 1; return i; }; // OK - initializing 'const int (^)(void)' with an expression of type 'int (^)(void)'
 
  const int (^CC) (void)  = ^const int{ const int i = 1; return i; };
 
diff --git a/test/SemaObjC/block-return.m b/test/SemaObjC/block-return.m
new file mode 100644
index 00000000000..15c3fb64d77
--- /dev/null
+++ b/test/SemaObjC/block-return.m
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -fblocks -fobjc-gc-only %s
+// rdar://8979379
+
+@interface NSString
+- (__attribute__((objc_gc(strong))) const char *)UTF8String;
+@end
+
+int main() {
+__attribute__((objc_gc(strong))) char const *(^libraryNameForIndex)() = ^() {
+        NSString *moduleName;
+        return [moduleName UTF8String];
+    };
+}
-- 
GitLab