give better diagnostics for converting between function pointer and void*.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45556 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 1ec60d9..68c301a 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -644,6 +644,11 @@
              LHSType.getAsString(), RHSType.getAsString(),
              Fn->getSourceRange(), Arg->getSourceRange());
         break;
+      case FunctionVoidPointer:
+        Diag(Loc, diag::ext_typecheck_passing_pointer_void_func, 
+             LHSType.getAsString(), RHSType.getAsString(),
+             Fn->getSourceRange(), Arg->getSourceRange());
+        break;
       case IncompatiblePointer:
         Diag(Loc, diag::ext_typecheck_passing_incompatible_pointer, 
              RHSType.getAsString(), LHSType.getAsString(),
@@ -1075,17 +1080,29 @@
   // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or 
   // incomplete type and the other is a pointer to a qualified or unqualified 
   // version of void...
-  if (lhptee.getUnqualifiedType()->isVoidType() &&
-      (rhptee->isObjectType() || rhptee->isIncompleteType()))
-    ;
-  else if (rhptee.getUnqualifiedType()->isVoidType() &&
-      (lhptee->isObjectType() || lhptee->isIncompleteType()))
-    ;
+  if (lhptee->isVoidType()) {
+    if (rhptee->isObjectType() || rhptee->isIncompleteType())
+      return r;
+    
+    // As an extension, we allow cast to/from void* to function pointer.
+    if (rhptee->isFunctionType())
+      return FunctionVoidPointer;
+  }
+  
+  if (rhptee->isVoidType()) {
+    if (lhptee->isObjectType() || lhptee->isIncompleteType())
+      return r;
+
+    // As an extension, we allow cast to/from void* to function pointer.
+    if (lhptee->isFunctionType())
+      return FunctionVoidPointer;
+  }
+  
   // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or 
   // unqualified versions of compatible types, ...
-  else if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), 
-                                       rhptee.getUnqualifiedType()))
-    r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
+  if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), 
+                                  rhptee.getUnqualifiedType()))
+    return IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
   return r;
 }
 
@@ -1543,6 +1560,11 @@
          lhsType.getAsString(), rhsType.getAsString(),
          lex->getSourceRange(), rex->getSourceRange());
     break;
+  case FunctionVoidPointer:
+    Diag(loc, diag::ext_typecheck_assign_pointer_void_func, 
+         lhsType.getAsString(), rhsType.getAsString(),
+         lex->getSourceRange(), rex->getSourceRange());
+    break;
   case IncompatiblePointer:
     Diag(loc, diag::ext_typecheck_assign_incompatible_pointer,
          lhsType.getAsString(), rhsType.getAsString(),
@@ -2226,6 +2248,11 @@
            rhsType.getAsString(), lhsType.getAsString(),
            argExpr->getSourceRange());
       break;
+    case FunctionVoidPointer:
+      Diag(l, diag::ext_typecheck_sending_pointer_void_func, 
+           rhsType.getAsString(), lhsType.getAsString(),
+           argExpr->getSourceRange());
+      break;
     case CompatiblePointerDiscardsQualifiers:
       Diag(l, diag::ext_typecheck_passing_discards_qualifiers,
            rhsType.getAsString(), lhsType.getAsString(),