]> granicus.if.org Git - clang/commitdiff
[Sema] Create a separate group for incompatible function pointer warning
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Mon, 18 Jul 2016 20:37:06 +0000 (20:37 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Mon, 18 Jul 2016 20:37:06 +0000 (20:37 +0000)
Give incompatible function pointer warning its own diagnostic group
but still leave it as a subgroup of incompatible-pointer-types. This is in
preparation to promote -Wincompatible-function-pointer-types to error on
darwin.

Differential Revision: https://reviews.llvm.org/D22248

rdar://problem/12907612

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@275907 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/Sema/incompatible-function-pointer-types.c [new file with mode: 0644]
test/Sema/initialize-noreturn.c
test/Sema/overloadable.c

index 72dfedbbaef0332a13ddf7169d6051eabd9181a9..7e40c44bc1c94c0b49c5ef114e4573c143e16cfd 100644 (file)
@@ -225,9 +225,12 @@ def GNUIncludeNext : DiagGroup<"gnu-include-next">;
 def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
 def IncompatiblePointerTypesDiscardsQualifiers 
   : DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
+def IncompatibleFunctionPointerTypes
+  : DiagGroup<"incompatible-function-pointer-types">;
 def IncompatiblePointerTypes
   : DiagGroup<"incompatible-pointer-types",
-    [IncompatiblePointerTypesDiscardsQualifiers]>;
+    [IncompatiblePointerTypesDiscardsQualifiers,
+     IncompatibleFunctionPointerTypes]>;
 def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
 def NonModularIncludeInFrameworkModule
   : DiagGroup<"non-modular-include-in-framework-module">;
index 1203fe765b52426ea0ad5bd958f1496a92819541..7987cf0511e43cab533590007b9bc02419909113 100644 (file)
@@ -6351,6 +6351,24 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn<
   "; remove *|"
   "; remove &}3">,
   InGroup<IncompatiblePointerTypes>;
+def ext_typecheck_convert_incompatible_function_pointer : ExtWarn<
+  "incompatible function pointer types "
+  "%select{%diff{assigning to $ from $|assigning to different types}0,1"
+  "|%diff{passing $ to parameter of type $|"
+  "passing to parameter of different type}0,1"
+  "|%diff{returning $ from a function with result type $|"
+  "returning from function with different return type}0,1"
+  "|%diff{converting $ to type $|converting between types}0,1"
+  "|%diff{initializing $ with an expression of type $|"
+  "initializing with expression of different type}0,1"
+  "|%diff{sending $ to parameter of type $|"
+  "sending to parameter of different type}0,1"
+  "|%diff{casting $ to type $|casting between types}0,1}2"
+  "%select{|; dereference with *|"
+  "; take the address with &|"
+  "; remove *|"
+  "; remove &}3">,
+  InGroup<IncompatibleFunctionPointerTypes>;
 def ext_typecheck_convert_discards_qualifiers : ExtWarn<
   "%select{%diff{assigning to $ from $|assigning to different types}0,1"
   "|%diff{passing $ to parameter of type $|"
index a5bd69f819f7bc684fcf79539de70dcb48f14daa..e882f2e28c51266529ca84dd2ba8257cd8055b13 100644 (file)
@@ -12423,10 +12423,14 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
     MayHaveConvFixit = true;
     break;
   case IncompatiblePointer:
-      DiagKind =
-        (Action == AA_Passing_CFAudited ?
-          diag::err_arc_typecheck_convert_incompatible_pointer :
-          diag::ext_typecheck_convert_incompatible_pointer);
+    if (Action == AA_Passing_CFAudited)
+      DiagKind = diag::err_arc_typecheck_convert_incompatible_pointer;
+    else if (SrcType->isFunctionPointerType() &&
+             DstType->isFunctionPointerType())
+      DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer;
+    else
+      DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
+
     CheckInferredResultType = DstType->isObjCObjectPointerType() &&
       SrcType->isObjCObjectPointerType();
     if (Hint.isNull() && !CheckInferredResultType) {
diff --git a/test/Sema/incompatible-function-pointer-types.c b/test/Sema/incompatible-function-pointer-types.c
new file mode 100644 (file)
index 0000000..f0f594f
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only %s -Wincompatible-pointer-types -verify
+// RUN: %clang_cc1 -fsyntax-only %s -Wincompatible-function-pointer-types -verify
+
+// This test ensures that the subgroup of -Wincompatible-pointer-types warnings
+// that concern function pointers can be promoted (or not promoted) to an error
+// *separately* from the other -Wincompatible-pointer-type warnings.
+typedef int (*MyFnTyA)(int *, char *);
+
+int bar(char *a, int *b) { return 0; }
+int foo(MyFnTyA x) { return 0; } // expected-note {{passing argument to parameter 'x' here}}
+
+void baz() {
+  foo(&bar); // expected-warning {{incompatible function pointer types passing 'int (*)(char *, int *)' to parameter of type 'MyFnTyA' (aka 'int (*)(int *, char *)')}}
+}
index 55578628716b17622e2bab955f3b5ee7938b2b27..b90d46d6beb04a8dfca8b8d263c05ac91a71c78f 100644 (file)
@@ -8,7 +8,7 @@ void foo(void);
 void foo_noret(void)  __attribute__((noreturn));
 
 void test() {
-  Fn_noret fn2 = &foo; // expected-warning {{incompatible pointer types initializing 'Fn_noret'}}
+  Fn_noret fn2 = &foo; // expected-warning {{incompatible function pointer types initializing 'Fn_noret'}}
   Fn_noret fn3 = &foo_noret; 
   Fn_ret fn4 = &foo_noret; 
   Fn_ret fn5 = &foo;
index 5d95a317fa38849f717fae01bfb4c893a4582f89..b518aa90a01b25bbf9d65b17b22041a69919d9b2 100644 (file)
@@ -109,7 +109,7 @@ void fn_type_conversions() {
   void (*ambiguous)(int *) = &foo; // expected-error{{initializing 'void (*)(int *)' with an expression of incompatible type '<overloaded function type>'}} expected-note@105{{candidate function}} expected-note@106{{candidate function}}
   void *vp_ambiguous = &foo; // expected-error{{initializing 'void *' with an expression of incompatible type '<overloaded function type>'}} expected-note@105{{candidate function}} expected-note@106{{candidate function}}
 
-  void (*specific1)(int *) = (void (*)(void *))&foo; // expected-warning{{incompatible pointer types initializing 'void (*)(int *)' with an expression of type 'void (*)(void *)'}}
+  void (*specific1)(int *) = (void (*)(void *))&foo; // expected-warning{{incompatible function pointer types initializing 'void (*)(int *)' with an expression of type 'void (*)(void *)'}}
   void *specific2 = (void (*)(void *))&foo;
 
   void disabled(void *c) __attribute__((overloadable, enable_if(0, "")));