Skip to content

Commit

Permalink
[Sema] Create a separate group for incompatible function pointer warning
Browse files Browse the repository at this point in the history
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

llvm-svn: 275907
  • Loading branch information
bcardosolopes committed Jul 18, 2016
1 parent 320a5a6 commit d9b7dfe
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 7 deletions.
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Expand Up @@ -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">;
Expand Down
18 changes: 18 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -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 $|"
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/Sema/SemaExpr.cpp
Expand Up @@ -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) {
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Sema/incompatible-function-pointer-types.c
@@ -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 *)')}}
}
2 changes: 1 addition & 1 deletion clang/test/Sema/initialize-noreturn.c
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/overloadable.c
Expand Up @@ -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, "")));
Expand Down

0 comments on commit d9b7dfe

Please sign in to comment.