Allow comparison of 'void *' with function pointer 
as a g++ extension (fixes radar 7481987).


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91827 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 791948f..f67a7a6 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -5170,7 +5170,18 @@
     if (getLangOptions().CPlusPlus) {
       if (LCanPointeeTy == RCanPointeeTy)
         return ResultTy;
-
+      if (!isRelational &&
+          (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
+        // Valid unless comparison between non-null pointer and function pointer
+        // This is a gcc extension compatibility comparison.
+        if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
+            && !LHSIsNull && !RHSIsNull) {
+          Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void)
+            << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+          ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+          return ResultTy;
+        }
+      }
       // C++ [expr.rel]p2:
       //   [...] Pointer conversions (4.10) and qualification
       //   conversions (4.4) are performed on pointer operands (or on
diff --git a/test/SemaObjCXX/function-pointer-void-star.mm b/test/SemaObjCXX/function-pointer-void-star.mm
new file mode 100644
index 0000000..8d3d625
--- /dev/null
+++ b/test/SemaObjCXX/function-pointer-void-star.mm
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+extern "C" id (*_dealloc)(id) ;
+
+void foo() {
+        extern void *_original_dealloc;
+        if (_dealloc == _original_dealloc) { }
+        if (_dealloc != _original_dealloc) { }
+}