Hi! I have implemented a warning -Wcast-function-type that analyzes type casts which change the function signatures.
I would consider function pointers with different result type invalid, also if both function types have a non-null TYPE_ARG_TYPES I would say this deserves a warning. As an exception I have used for instance in recog.h, the warning allows casting a function with the type typedef rtx (*stored_funcptr) (...); to any function with the same result type. I would think a warning like that should be enabled with -Wextra. Attached is a first version of the patch and as you can see the warning found already lots of suspicious type casts. The worst is the splay-tree which always calls functions with uintptr_t instead of the correct parameter type. I was unable to find a solution for this, and just silenced the warning with a second type-cast. Note that I also changed one line in libgo, but that is only a quick hack which I only did to make the boot-strap with all languages succeed. I'm not sure if this warning may be a bit too strict, but I think so far it just triggered on rather questionable code. Thoughts? Bernd.
gcc: 2017-10-03 Bernd Edlinger <bernd.edlin...@hotmail.de> * doc/invoke.texi: Document -Wcast-function-type. * gengtype.c (write_root): Remove cast. * ggc.h (gt_pch_n_S_nonconst, gt_ggc_m_S_nonconst): Declare. * ggc-page.c (gt_ggc_m_S_nonconst): New function. * stringpool.c (gt_pch_n_S_nonconst): New function. * tree-pass.h (do_per_function_toporder): Adjust header. * passes.c (do_per_function_toporder): Change signature. (execute_ipa_pass_list): Remove cast. * recog.h (f0..f15): Fix return types. (stored_funcptr): Use variadic parameter list. * tree-dump.c (dump_node): Avoid warning. * typed-splay-tree.h (typed_splay_tree): Avoid warning. libcpp: 2017-10-03 Bernd Edlinger <bernd.edlin...@hotmail.de> * include/symtab.h (ht_forall_internal): Declare. * symtab.c (ht_forall_internal): New function. * internal.h (maybe_print_line): Change signature. c-family: 2017-10-03 Bernd Edlinger <bernd.edlin...@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-10-03 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-typeck.c (build_c_cast): Implement -Wcast_function_type. cp: 2017-10-03 Bernd Edlinger <bernd.edlin...@hotmail.de> * cxx-pretty-print.c (pp_c_type_specifier_seq, pp_c_parameter_declaration_clause): New wrapper functions. (cxx_pretty_printer::cxx_pretty_printer): Remove cast. * decl2.c (start_static_storage_duration_function): Aboid warning. * typeck.c (build_reinterpret_cast_1): Implement -Wcast_function_type. testsuite: 2017-10-03 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-c++-common/Wcast-function-type.c: New test.
Index: gcc/c/c-typeck.c =================================================================== --- gcc/c/c-typeck.c (revision 253328) +++ gcc/c/c-typeck.c (working copy) @@ -5667,6 +5667,20 @@ 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 + && (TYPE_ARG_TYPES (TREE_TYPE (type)) + && TYPE_ARG_TYPES (TREE_TYPE (otype)) + ? !comptypes (TREE_TYPE (type), + TREE_TYPE (otype)) + : !comptypes (TREE_TYPE (TREE_TYPE (type)), + TREE_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); Index: gcc/c-family/c-lex.c =================================================================== --- gcc/c-family/c-lex.c (revision 253328) +++ gcc/c-family/c-lex.c (working copy) @@ -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) + (uintptr_t) strcmp, 0, - (splay_tree_delete_value_fn) free); + (splay_tree_delete_value_fn) + (uintptr_t) free); n = splay_tree_lookup (file_info_tree, (splay_tree_key) name); if (n) Index: gcc/c-family/c-ppoutput.c =================================================================== --- gcc/c-family/c-ppoutput.c (revision 253328) +++ gcc/c-family/c-ppoutput.c (working copy) @@ -299,7 +299,7 @@ scan_translation_unit_directives_only (cpp_reader 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); } Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 253328) +++ gcc/c-family/c.opt (working copy) @@ -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. Index: gcc/cp/cxx-pretty-print.c =================================================================== --- gcc/cp/cxx-pretty-print.c (revision 253328) +++ gcc/cp/cxx-pretty-print.c (working copy) @@ -2935,8 +2935,16 @@ pp_cxx_constraint (cxx_pretty_printer *pp, tree t) -typedef c_pretty_print_fn pp_fun; +static void pp_c_type_specifier_seq (c_pretty_printer *pp, tree t) +{ + pp_cxx_type_specifier_seq ((cxx_pretty_printer *)pp, t); +} +static void pp_c_parameter_declaration_clause (c_pretty_printer *pp, tree t) +{ + pp_cxx_parameter_declaration_clause ((cxx_pretty_printer *)pp, t); +} + /* Initialization of a C++ pretty-printer object. */ cxx_pretty_printer::cxx_pretty_printer () @@ -2943,6 +2951,6 @@ cxx_pretty_printer::cxx_pretty_printer () : c_pretty_printer (), enclosing_scope (global_namespace) { - type_specifier_seq = (pp_fun) pp_cxx_type_specifier_seq; - parameter_list = (pp_fun) pp_cxx_parameter_declaration_clause; + type_specifier_seq = pp_c_type_specifier_seq; + parameter_list = pp_c_parameter_declaration_clause; } Index: gcc/cp/decl2.c =================================================================== --- gcc/cp/decl2.c (revision 253328) +++ gcc/cp/decl2.c (working copy) @@ -3480,7 +3480,8 @@ start_static_storage_duration_function (unsigned c 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) + (uintptr_t) free); /* We always need to generate functions for the DEFAULT_INIT_PRIORITY so enter it now. That way when we walk Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 253328) +++ gcc/cp/typeck.c (working copy) @@ -7261,8 +7261,21 @@ build_reinterpret_cast_1 (tree type, tree expr, bo && 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))) + else if (TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype)) + { + if ((complain & tf_warning) + && (TYPE_ARG_TYPES (TREE_TYPE (type)) + && TYPE_ARG_TYPES (TREE_TYPE (intype)) + ? !same_type_p (TREE_TYPE (type), + TREE_TYPE (intype)) + : !same_type_p (TREE_TYPE (TREE_TYPE (type)), + TREE_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)) return build_nop (type, expr); else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 253328) +++ gcc/doc/invoke.texi (working copy) @@ -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 @@ -3899,6 +3899,7 @@ This enables some extra warning flags that are not 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 @@ -5948,6 +5949,15 @@ Warn whenever a pointer is cast such that the requ 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. +When one of the function types uses variable arguments like this +@code{int f(...);}, then only the return value is checked, otherwise +the return value and the parameter types are checked. +This warning is enabled by @option{-Wextra}. + @item -Wwrite-strings @opindex Wwrite-strings @opindex Wno-write-strings Index: gcc/gengtype.c =================================================================== --- gcc/gengtype.c (revision 253328) +++ gcc/gengtype.c (working copy) @@ -4406,8 +4406,8 @@ write_root (outf_p f, pair_p v, type_p type, const if (!start_root_entry (f, v, name, line)) return; - oprintf (f, " (gt_pointer_walker) >_ggc_m_S,\n"); - oprintf (f, " (gt_pointer_walker) >_pch_n_S\n"); + oprintf (f, " >_ggc_m_S_nonconst,\n"); + oprintf (f, " >_pch_n_S_nonconst\n"); oprintf (f, " },\n"); } break; Index: gcc/ggc-page.c =================================================================== --- gcc/ggc-page.c (revision 253328) +++ gcc/ggc-page.c (working copy) @@ -1500,6 +1500,11 @@ gt_ggc_m_S (const void *p) return; } +void +gt_ggc_m_S_nonconst (void *p) +{ + gt_ggc_m_S (CONST_CAST(const void *, p)); +} /* User-callable entry points for marking string X. */ Index: gcc/ggc.h =================================================================== --- gcc/ggc.h (revision 253328) +++ gcc/ggc.h (working copy) @@ -98,6 +98,8 @@ extern int ggc_marked_p (const void *); /* PCH and GGC handling for strings, mostly trivial. */ extern void gt_pch_n_S (const void *); extern void gt_ggc_m_S (const void *); +extern void gt_pch_n_S_nonconst (void *); +extern void gt_ggc_m_S_nonconst (void *); /* End of GTY machinery API. */ Index: gcc/passes.c =================================================================== --- gcc/passes.c (revision 253328) +++ gcc/passes.c (working copy) @@ -1694,7 +1694,8 @@ remove_cgraph_node_from_order (cgraph_node *node, call CALLBACK on the current function. This function is global so that plugins can use it. */ void -do_per_function_toporder (void (*callback) (function *, void *data), void *data) +do_per_function_toporder (void (*callback) (function *, opt_pass *data), + opt_pass *data) { int i; @@ -2932,9 +2933,7 @@ execute_ipa_pass_list (opt_pass *pass) if (pass->sub->type == GIMPLE_PASS) { invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL); - do_per_function_toporder ((void (*)(function *, void *)) - execute_pass_list, - pass->sub); + do_per_function_toporder (execute_pass_list, pass->sub); invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL); } else if (pass->sub->type == SIMPLE_IPA_PASS Index: gcc/recog.h =================================================================== --- gcc/recog.h (revision 253328) +++ gcc/recog.h (working copy) @@ -276,43 +276,60 @@ typedef const char * (*insn_output_fn) (rtx *, rtx struct insn_gen_fn { - typedef rtx_insn * (*f0) (void); - typedef rtx_insn * (*f1) (rtx); - typedef rtx_insn * (*f2) (rtx, rtx); - typedef rtx_insn * (*f3) (rtx, rtx, rtx); - typedef rtx_insn * (*f4) (rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f5) (rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f6) (rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef rtx_insn * (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - 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 rtx (*f0) (void); + typedef rtx (*f1) (rtx); + typedef rtx (*f2) (rtx, rtx); + typedef rtx (*f3) (rtx, rtx, rtx); + typedef rtx (*f4) (rtx, rtx, rtx, rtx); + typedef rtx (*f5) (rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f6) (rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + typedef rtx (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); - typedef f0 stored_funcptr; + typedef rtx (*stored_funcptr) (...); - rtx_insn * operator () (void) const { return ((f0)func) (); } - rtx_insn * operator () (rtx a0) const { return ((f1)func) (a0); } - rtx_insn * operator () (rtx a0, rtx a1) const { return ((f2)func) (a0, a1); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2) const { return ((f3)func) (a0, a1, a2); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3) const { return ((f4)func) (a0, a1, a2, a3); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const { return ((f5)func) (a0, a1, a2, a3, a4); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const { return ((f6)func) (a0, a1, a2, a3, a4, a5); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const { return ((f7)func) (a0, a1, a2, a3, a4, a5, a6); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const { return ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const { return ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const { return ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const { return ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const { return ((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const { return ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const { return ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const { return ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } - rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const { return ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } + rtx_insn * operator () (void) const + { return (rtx_insn *) ((f0)func) (); } + rtx_insn * operator () (rtx a0) const + { return (rtx_insn *) ((f1)func) (a0); } + rtx_insn * operator () (rtx a0, rtx a1) const + { return (rtx_insn *) ((f2)func) (a0, a1); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2) const + { return (rtx_insn *) ((f3)func) (a0, a1, a2); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3) const + { return (rtx_insn *) ((f4)func) (a0, a1, a2, a3); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const + { return (rtx_insn *) ((f5)func) (a0, a1, a2, a3, a4); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const + { return (rtx_insn *) ((f6)func) (a0, a1, a2, a3, a4, a5); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const + { return (rtx_insn *) ((f7)func) (a0, a1, a2, a3, a4, a5, a6); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const + { return (rtx_insn *) ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const + { return (rtx_insn *) ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const + { return (rtx_insn *) ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const + { return (rtx_insn *) ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const + { return (rtx_insn *)((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const + { return (rtx_insn *) ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const + { return (rtx_insn *) ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const + { return (rtx_insn *) ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } + rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const + { return (rtx_insn *) ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } // This is for compatibility of code that invokes functions like // (*funcptr) (arg) Index: gcc/stringpool.c =================================================================== --- gcc/stringpool.c (revision 253328) +++ gcc/stringpool.c (working copy) @@ -196,6 +196,11 @@ gt_pch_n_S (const void *x) >_pch_p_S); } +void +gt_pch_n_S_nonconst (void *x) +{ + gt_pch_n_S (CONST_CAST (const void *, x)); +} /* User-callable entry point for marking string X. */ Index: gcc/testsuite/c-c++-common/Wcast-function-type.c =================================================================== --- gcc/testsuite/c-c++-common/Wcast-function-type.c (revision 0) +++ gcc/testsuite/c-c++-common/Wcast-function-type.c (working copy) @@ -0,0 +1,28 @@ +/* { 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 + +f1 *a; +f2 *b; +f3 *c; +f4 *d; + +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" } */ +} Index: gcc/tree-dump.c =================================================================== --- gcc/tree-dump.c (revision 253328) +++ gcc/tree-dump.c (working copy) @@ -735,7 +735,8 @@ dump_node (const_tree t, dump_flags_t flags, FILE 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) + (uintptr_t) free); /* Queue up the first node. */ queue (&di, t, DUMP_NONE); Index: gcc/tree-pass.h =================================================================== --- gcc/tree-pass.h (revision 253328) +++ gcc/tree-pass.h (working copy) @@ -646,7 +646,8 @@ extern void register_one_dump_file (opt_pass *); extern bool function_called_by_processed_nodes_p (void); /* Declare for plugins. */ -extern void do_per_function_toporder (void (*) (function *, void *), void *); +extern void do_per_function_toporder (void (*) (function *, opt_pass *), + opt_pass *); extern void disable_pass (const char *); extern void enable_pass (const char *); Index: gcc/typed-splay-tree.h =================================================================== --- gcc/typed-splay-tree.h (revision 253328) +++ gcc/typed-splay-tree.h (working copy) @@ -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) + (uintptr_t) compare_fn, + (splay_tree_delete_key_fn) + (uintptr_t) delete_key_fn, + (splay_tree_delete_value_fn) + (uintptr_t) delete_value_fn); } /* Destructor for typed_splay_tree <K, V>. */ Index: libcpp/identifiers.c =================================================================== --- libcpp/identifiers.c (revision 253328) +++ libcpp/identifiers.c (working copy) @@ -116,5 +116,5 @@ extern char proxy_assertion_broken[offsetof (struc void cpp_forall_identifiers (cpp_reader *pfile, cpp_cb cb, void *v) { - ht_forall (pfile->hash_table, (ht_cb) cb, v); + ht_forall_internal (pfile->hash_table, cb, v); } Index: libcpp/include/symtab.h =================================================================== --- libcpp/include/symtab.h (revision 253328) +++ libcpp/include/symtab.h (working copy) @@ -88,6 +88,11 @@ extern hashnode ht_lookup_with_hash (cpp_hash_tabl if the callback returns zero. */ typedef int (*ht_cb) (struct cpp_reader *, hashnode, const void *); extern void ht_forall (cpp_hash_table *, ht_cb, const void *); +struct cpp_hashnode; +extern void ht_forall_internal (cpp_hash_table *, + int (*)(struct cpp_reader *, + cpp_hashnode *, void *), + void *); /* For all nodes in TABLE, call the callback. If the callback returns a nonzero value, the node is removed from the table. */ Index: libcpp/internal.h =================================================================== --- libcpp/internal.h (revision 253328) +++ libcpp/internal.h (working copy) @@ -708,7 +708,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 *, Index: libcpp/symtab.c =================================================================== --- libcpp/symtab.c (revision 253328) +++ libcpp/symtab.c (working copy) @@ -236,6 +236,26 @@ ht_forall (cpp_hash_table *table, ht_cb cb, const while (++p < limit); } +/* Like ht_forall, but with different parameter types in the callback. */ +void +ht_forall_internal (cpp_hash_table *table, + int (*cb)(struct cpp_reader *, + cpp_hashnode *, void *), + void *v) +{ + hashnode *p, *limit; + + p = table->entries; + limit = p + table->nslots; + do + if (*p && *p != DELETED) + { + if ((*cb) (table->pfile, (cpp_hashnode *)*p, v) == 0) + break; + } + while (++p < limit); +} + /* Like ht_forall, but a nonzero return from the callback means that the entry should be removed from the table. */ void Index: libgo/runtime/runtime.h =================================================================== --- libgo/runtime/runtime.h (revision 253328) +++ libgo/runtime/runtime.h (working copy) @@ -94,7 +94,7 @@ struct String struct FuncVal { - void (*fn)(void); + void (*fn)(); // variable-size, fn-specific data here };