From c65e18d3331aa9995ddab8527132de706f6d9236 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Thu, 14 Dec 2017 18:59:24 +0000 Subject: invoke.texi: Document -Wcast-function-type. gcc: 2017-12-14 Bernd Edlinger * 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 * internal.h (maybe_print_line): Change signature. c-family: 2017-12-14 Bernd Edlinger * 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 * 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 * 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 * c-c++-common/Wcast-function-type.c: New test. * g++.dg/Wcast-function-type.C: New test. From-SVN: r255661 --- gcc/c/ChangeLog | 6 ++++++ gcc/c/c-typeck.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) (limited to 'gcc/c') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 3f5414b..d486018 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2017-12-14 Bernd Edlinger + + * 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 PR c/83415 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 13b2684..541fb61 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -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); -- cgit v1.1