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:
Bernd Edlinger 2017-12-14 18:59:24 +00:00 committed by Bernd Edlinger
parent 9d0e85af87
commit c65e18d333
19 changed files with 258 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)))
{

View File

@ -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

View File

@ -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); }

View File

@ -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

View 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" } */
}

View 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" } */
}

View File

@ -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);

View File

@ -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>. */

View File

@ -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

View File

@ -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 *,