invoke.texi: Document -Wcast-function-type.
gcc: 2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de> * doc/invoke.texi: Document -Wcast-function-type. * recog.h (stored_funcptr): Change signature. * tree-dump.c (dump_node): Avoid warning. * typed-splay-tree.h (typed_splay_tree): Avoid warning. libcpp: 2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de> * internal.h (maybe_print_line): Change signature. c-family: 2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de> * c.opt (Wcast-function-type): New warning option. * c-lex.c (get_fileinfo): Avoid warning. * c-ppoutput.c (scan_translation_unit_directives_only): Remove cast. c: 2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de> * c-typeck.c (c_safe_arg_type_equiv_p, c_safe_function_type_cast_p): New function. (build_c_cast): Implement -Wcast-function-type. cp: 2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de> * decl2.c (start_static_storage_duration_function): Avoid warning. * typeck.c (cxx_safe_arg_type_equiv_p, cxx_safe_function_type_cast_p): New function. (build_reinterpret_cast_1): Implement -Wcast-function-type. testsuite: 2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de> * c-c++-common/Wcast-function-type.c: New test. * g++.dg/Wcast-function-type.C: New test. From-SVN: r255661
This commit is contained in:
parent
9d0e85af87
commit
c65e18d333
@ -1,3 +1,10 @@
|
||||
2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* doc/invoke.texi: Document -Wcast-function-type.
|
||||
* recog.h (stored_funcptr): Change signature.
|
||||
* tree-dump.c (dump_node): Avoid warning.
|
||||
* typed-splay-tree.h (typed_splay_tree): Avoid warning.
|
||||
|
||||
2017-12-14 Qing Zhao <qing.zhao@oracle.com>
|
||||
|
||||
PR middle_end/79538
|
||||
|
@ -1,3 +1,9 @@
|
||||
2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* c.opt (Wcast-function-type): New warning option.
|
||||
* c-lex.c (get_fileinfo): Avoid warning.
|
||||
* c-ppoutput.c (scan_translation_unit_directives_only): Remove cast.
|
||||
|
||||
2017-12-14 Qing Zhao <qing.zhao@oracle.com>
|
||||
|
||||
PR middle_end/79538
|
||||
|
@ -101,9 +101,11 @@ get_fileinfo (const char *name)
|
||||
struct c_fileinfo *fi;
|
||||
|
||||
if (!file_info_tree)
|
||||
file_info_tree = splay_tree_new ((splay_tree_compare_fn) strcmp,
|
||||
file_info_tree = splay_tree_new ((splay_tree_compare_fn)
|
||||
(void (*) (void)) strcmp,
|
||||
0,
|
||||
(splay_tree_delete_value_fn) free);
|
||||
(splay_tree_delete_value_fn)
|
||||
(void (*) (void)) free);
|
||||
|
||||
n = splay_tree_lookup (file_info_tree, (splay_tree_key) name);
|
||||
if (n)
|
||||
|
@ -299,7 +299,7 @@ scan_translation_unit_directives_only (cpp_reader *pfile)
|
||||
struct _cpp_dir_only_callbacks cb;
|
||||
|
||||
cb.print_lines = print_lines_directives_only;
|
||||
cb.maybe_print_line = (void (*) (source_location)) maybe_print_line;
|
||||
cb.maybe_print_line = maybe_print_line;
|
||||
|
||||
_cpp_preprocess_dir_only (pfile, &cb);
|
||||
}
|
||||
|
@ -384,6 +384,10 @@ Wc++17-compat
|
||||
C++ ObjC++ Var(warn_cxx17_compat) Warning LangEnabledBy(C++ ObjC++,Wall)
|
||||
Warn about C++ constructs whose meaning differs between ISO C++ 2014 and ISO C++ 2017.
|
||||
|
||||
Wcast-function-type
|
||||
C ObjC C++ ObjC++ Var(warn_cast_function_type) Warning EnabledBy(Wextra)
|
||||
Warn about casts between incompatible function types.
|
||||
|
||||
Wcast-qual
|
||||
C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
|
||||
Warn about casts which discard qualifiers.
|
||||
|
@ -1,3 +1,9 @@
|
||||
2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* c-typeck.c (c_safe_arg_type_equiv_p,
|
||||
c_safe_function_type_cast_p): New function.
|
||||
(build_c_cast): Implement -Wcast-function-type.
|
||||
|
||||
2017-12-14 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR c/83415
|
||||
|
@ -5472,6 +5472,59 @@ handle_warn_cast_qual (location_t loc, tree type, tree otype)
|
||||
while (TREE_CODE (in_type) == POINTER_TYPE);
|
||||
}
|
||||
|
||||
/* Heuristic check if two parameter types can be considered ABI-equivalent. */
|
||||
|
||||
static bool
|
||||
c_safe_arg_type_equiv_p (tree t1, tree t2)
|
||||
{
|
||||
t1 = TYPE_MAIN_VARIANT (t1);
|
||||
t2 = TYPE_MAIN_VARIANT (t2);
|
||||
|
||||
if (TREE_CODE (t1) == POINTER_TYPE
|
||||
&& TREE_CODE (t2) == POINTER_TYPE)
|
||||
return true;
|
||||
|
||||
/* The signedness of the parameter matters only when an integral
|
||||
type smaller than int is promoted to int, otherwise only the
|
||||
precision of the parameter matters.
|
||||
This check should make sure that the callee does not see
|
||||
undefined values in argument registers. */
|
||||
if (INTEGRAL_TYPE_P (t1)
|
||||
&& INTEGRAL_TYPE_P (t2)
|
||||
&& TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
|
||||
&& (TYPE_UNSIGNED (t1) == TYPE_UNSIGNED (t2)
|
||||
|| !targetm.calls.promote_prototypes (NULL_TREE)
|
||||
|| TYPE_PRECISION (t1) >= TYPE_PRECISION (integer_type_node)))
|
||||
return true;
|
||||
|
||||
return comptypes (t1, t2);
|
||||
}
|
||||
|
||||
/* Check if a type cast between two function types can be considered safe. */
|
||||
|
||||
static bool
|
||||
c_safe_function_type_cast_p (tree t1, tree t2)
|
||||
{
|
||||
if (TREE_TYPE (t1) == void_type_node &&
|
||||
TYPE_ARG_TYPES (t1) == void_list_node)
|
||||
return true;
|
||||
|
||||
if (TREE_TYPE (t2) == void_type_node &&
|
||||
TYPE_ARG_TYPES (t2) == void_list_node)
|
||||
return true;
|
||||
|
||||
if (!c_safe_arg_type_equiv_p (TREE_TYPE (t1), TREE_TYPE (t2)))
|
||||
return false;
|
||||
|
||||
for (t1 = TYPE_ARG_TYPES (t1), t2 = TYPE_ARG_TYPES (t2);
|
||||
t1 && t2;
|
||||
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
|
||||
if (!c_safe_arg_type_equiv_p (TREE_VALUE (t1), TREE_VALUE (t2)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Build an expression representing a cast to type TYPE of expression EXPR.
|
||||
LOC is the location of the cast-- typically the open paren of the cast. */
|
||||
|
||||
@ -5665,6 +5718,16 @@ build_c_cast (location_t loc, tree type, tree expr)
|
||||
pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
|
||||
"conversion of object pointer to function pointer type");
|
||||
|
||||
if (TREE_CODE (type) == POINTER_TYPE
|
||||
&& TREE_CODE (otype) == POINTER_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
|
||||
&& !c_safe_function_type_cast_p (TREE_TYPE (type),
|
||||
TREE_TYPE (otype)))
|
||||
warning_at (loc, OPT_Wcast_function_type,
|
||||
"cast between incompatible function types"
|
||||
" from %qT to %qT", otype, type);
|
||||
|
||||
ovalue = value;
|
||||
value = convert (type, value);
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* decl2.c (start_static_storage_duration_function): Avoid warning.
|
||||
* typeck.c (cxx_safe_arg_type_equiv_p,
|
||||
cxx_safe_function_type_cast_p): New function.
|
||||
(build_reinterpret_cast_1): Implement -Wcast-function-type.
|
||||
|
||||
2017-12-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/79650
|
||||
|
@ -3558,7 +3558,8 @@ start_static_storage_duration_function (unsigned count)
|
||||
priority_info_map = splay_tree_new (splay_tree_compare_ints,
|
||||
/*delete_key_fn=*/0,
|
||||
/*delete_value_fn=*/
|
||||
(splay_tree_delete_value_fn) &free);
|
||||
(splay_tree_delete_value_fn)
|
||||
(void (*) (void)) free);
|
||||
|
||||
/* We always need to generate functions for the
|
||||
DEFAULT_INIT_PRIORITY so enter it now. That way when we walk
|
||||
|
@ -1173,6 +1173,59 @@ comp_template_parms_position (tree t1, tree t2)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Heuristic check if two parameter types can be considered ABI-equivalent. */
|
||||
|
||||
static bool
|
||||
cxx_safe_arg_type_equiv_p (tree t1, tree t2)
|
||||
{
|
||||
t1 = TYPE_MAIN_VARIANT (t1);
|
||||
t2 = TYPE_MAIN_VARIANT (t2);
|
||||
|
||||
if (TREE_CODE (t1) == POINTER_TYPE
|
||||
&& TREE_CODE (t2) == POINTER_TYPE)
|
||||
return true;
|
||||
|
||||
/* The signedness of the parameter matters only when an integral
|
||||
type smaller than int is promoted to int, otherwise only the
|
||||
precision of the parameter matters.
|
||||
This check should make sure that the callee does not see
|
||||
undefined values in argument registers. */
|
||||
if (INTEGRAL_TYPE_P (t1)
|
||||
&& INTEGRAL_TYPE_P (t2)
|
||||
&& TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
|
||||
&& (TYPE_UNSIGNED (t1) == TYPE_UNSIGNED (t2)
|
||||
|| !targetm.calls.promote_prototypes (NULL_TREE)
|
||||
|| TYPE_PRECISION (t1) >= TYPE_PRECISION (integer_type_node)))
|
||||
return true;
|
||||
|
||||
return same_type_p (t1, t2);
|
||||
}
|
||||
|
||||
/* Check if a type cast between two function types can be considered safe. */
|
||||
|
||||
static bool
|
||||
cxx_safe_function_type_cast_p (tree t1, tree t2)
|
||||
{
|
||||
if (TREE_TYPE (t1) == void_type_node &&
|
||||
TYPE_ARG_TYPES (t1) == void_list_node)
|
||||
return true;
|
||||
|
||||
if (TREE_TYPE (t2) == void_type_node &&
|
||||
TYPE_ARG_TYPES (t2) == void_list_node)
|
||||
return true;
|
||||
|
||||
if (!cxx_safe_arg_type_equiv_p (TREE_TYPE (t1), TREE_TYPE (t2)))
|
||||
return false;
|
||||
|
||||
for (t1 = TYPE_ARG_TYPES (t1), t2 = TYPE_ARG_TYPES (t2);
|
||||
t1 && t2;
|
||||
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
|
||||
if (!cxx_safe_arg_type_equiv_p (TREE_VALUE (t1), TREE_VALUE (t2)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Subroutine in comptypes. */
|
||||
|
||||
static bool
|
||||
@ -7326,9 +7379,27 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
|
||||
&& same_type_p (type, intype))
|
||||
/* DR 799 */
|
||||
return rvalue (expr);
|
||||
else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
|
||||
|| (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
|
||||
return build_nop (type, expr);
|
||||
else if (TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
|
||||
{
|
||||
if ((complain & tf_warning)
|
||||
&& !cxx_safe_function_type_cast_p (TREE_TYPE (type),
|
||||
TREE_TYPE (intype)))
|
||||
warning (OPT_Wcast_function_type,
|
||||
"cast between incompatible function types"
|
||||
" from %qH to %qI", intype, type);
|
||||
return build_nop (type, expr);
|
||||
}
|
||||
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
|
||||
{
|
||||
if ((complain & tf_warning)
|
||||
&& !cxx_safe_function_type_cast_p
|
||||
(TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (type)),
|
||||
TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (intype))))
|
||||
warning (OPT_Wcast_function_type,
|
||||
"cast between incompatible pointer to member types"
|
||||
" from %qH to %qI", intype, type);
|
||||
return build_nop (type, expr);
|
||||
}
|
||||
else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype))
|
||||
|| (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
|
||||
{
|
||||
|
@ -267,7 +267,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-Wno-builtin-declaration-mismatch @gol
|
||||
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol
|
||||
-Wc++-compat -Wc++11-compat -Wc++14-compat @gol
|
||||
-Wcast-align -Wcast-align=strict -Wcast-qual @gol
|
||||
-Wcast-align -Wcast-align=strict -Wcast-function-type -Wcast-qual @gol
|
||||
-Wchar-subscripts -Wchkp -Wcatch-value -Wcatch-value=@var{n} @gol
|
||||
-Wclobbered -Wcomment -Wconditionally-supported @gol
|
||||
-Wconversion -Wcoverage-mismatch -Wno-cpp -Wdangling-else -Wdate-time @gol
|
||||
@ -3904,6 +3904,7 @@ This enables some extra warning flags that are not enabled by
|
||||
name is still supported, but the newer name is more descriptive.)
|
||||
|
||||
@gccoptlist{-Wclobbered @gol
|
||||
-Wcast-function-type @gol
|
||||
-Wempty-body @gol
|
||||
-Wignored-qualifiers @gol
|
||||
-Wimplicit-fallthrough=3 @gol
|
||||
@ -6041,6 +6042,21 @@ Warn whenever a pointer is cast such that the required alignment of the
|
||||
target is increased. For example, warn if a @code{char *} is cast to
|
||||
an @code{int *} regardless of the target machine.
|
||||
|
||||
@item -Wcast-function-type
|
||||
@opindex Wcast-function-type
|
||||
@opindex Wno-cast-function-type
|
||||
Warn when a function pointer is cast to an incompatible function pointer.
|
||||
In a cast involving function types with a variable argument list only
|
||||
the types of initial arguments that are provided are considered.
|
||||
Any parameter of pointer-type matches any other pointer-type. Any benign
|
||||
differences in integral types are ignored, like @code{int} vs. @code{long}
|
||||
on ILP32 targets. Likewise type qualifiers are ignored. The function
|
||||
type @code{void (*) (void)} is special and matches everything, which can
|
||||
be used to suppress this warning.
|
||||
In a cast involving pointer to member types this warning warns whenever
|
||||
the type cast is changing the pointer to member type.
|
||||
This warning is enabled by @option{-Wextra}.
|
||||
|
||||
@item -Wwrite-strings
|
||||
@opindex Wwrite-strings
|
||||
@opindex Wno-write-strings
|
||||
|
@ -294,7 +294,7 @@ struct insn_gen_fn
|
||||
typedef rtx_insn * (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
|
||||
typedef rtx_insn * (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
|
||||
|
||||
typedef f0 stored_funcptr;
|
||||
typedef void (*stored_funcptr) (void);
|
||||
|
||||
rtx_insn * operator () (void) const { return ((f0)func) (); }
|
||||
rtx_insn * operator () (rtx a0) const { return ((f1)func) (a0); }
|
||||
|
@ -1,3 +1,8 @@
|
||||
2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* c-c++-common/Wcast-function-type.c: New test.
|
||||
* g++.dg/Wcast-function-type.C: New test.
|
||||
|
||||
2017-12-14 Qing Zhao <qing.zhao@oracle.com>
|
||||
|
||||
PR middle_end/79538
|
||||
|
31
gcc/testsuite/c-c++-common/Wcast-function-type.c
Normal file
31
gcc/testsuite/c-c++-common/Wcast-function-type.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wcast-function-type" } */
|
||||
|
||||
int f(long);
|
||||
|
||||
typedef int (f1)(long);
|
||||
typedef int (f2)(void*);
|
||||
#ifdef __cplusplus
|
||||
typedef int (f3)(...);
|
||||
typedef void (f4)(...);
|
||||
#else
|
||||
typedef int (f3)();
|
||||
typedef void (f4)();
|
||||
#endif
|
||||
typedef void (f5)(void);
|
||||
|
||||
f1 *a;
|
||||
f2 *b;
|
||||
f3 *c;
|
||||
f4 *d;
|
||||
f5 *e;
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
a = (f1 *) f; /* { dg-bogus "incompatible function types" } */
|
||||
b = (f2 *) f; /* { dg-warning "incompatible function types" } */
|
||||
c = (f3 *) f; /* { dg-bogus "incompatible function types" } */
|
||||
d = (f4 *) f; /* { dg-warning "incompatible function types" } */
|
||||
e = (f5 *) f; /* { dg-bogus "incompatible function types" } */
|
||||
}
|
17
gcc/testsuite/g++.dg/Wcast-function-type.C
Normal file
17
gcc/testsuite/g++.dg/Wcast-function-type.C
Normal file
@ -0,0 +1,17 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Wcast-function-type" } */
|
||||
|
||||
struct S
|
||||
{
|
||||
void foo (int*);
|
||||
void bar (int);
|
||||
};
|
||||
|
||||
typedef void (S::*MF)(int);
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
MF p1 = (MF)&S::foo; /* { dg-warning "pointer to member" } */
|
||||
MF p2 = (MF)&S::bar; /* { dg-bogus "pointer to member" } */
|
||||
}
|
@ -736,7 +736,8 @@ dump_node (const_tree t, dump_flags_t flags, FILE *stream)
|
||||
di.flags = flags;
|
||||
di.node = t;
|
||||
di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
|
||||
(splay_tree_delete_value_fn) &free);
|
||||
(splay_tree_delete_value_fn)
|
||||
(void (*) (void)) free);
|
||||
|
||||
/* Queue up the first node. */
|
||||
queue (&di, t, DUMP_NONE);
|
||||
|
@ -75,9 +75,12 @@ inline typed_splay_tree<KEY_TYPE, VALUE_TYPE>::
|
||||
delete_key_fn delete_key_fn,
|
||||
delete_value_fn delete_value_fn)
|
||||
{
|
||||
m_inner = splay_tree_new ((splay_tree_compare_fn)compare_fn,
|
||||
(splay_tree_delete_key_fn)delete_key_fn,
|
||||
(splay_tree_delete_value_fn)delete_value_fn);
|
||||
m_inner = splay_tree_new ((splay_tree_compare_fn)
|
||||
(void (*) (void)) compare_fn,
|
||||
(splay_tree_delete_key_fn)
|
||||
(void (*) (void)) delete_key_fn,
|
||||
(splay_tree_delete_value_fn)
|
||||
(void (*) (void)) delete_value_fn);
|
||||
}
|
||||
|
||||
/* Destructor for typed_splay_tree <K, V>. */
|
||||
|
@ -1,3 +1,7 @@
|
||||
2017-12-14 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* internal.h (maybe_print_line): Change signature.
|
||||
|
||||
2017-12-05 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/79228
|
||||
|
@ -709,7 +709,7 @@ struct _cpp_dir_only_callbacks
|
||||
{
|
||||
/* Called to print a block of lines. */
|
||||
void (*print_lines) (int, const void *, size_t);
|
||||
void (*maybe_print_line) (source_location);
|
||||
bool (*maybe_print_line) (source_location);
|
||||
};
|
||||
|
||||
extern void _cpp_preprocess_dir_only (cpp_reader *,
|
||||
|
Loading…
Reference in New Issue
Block a user