diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2017-12-14 18:59:24 +0000 |
---|---|---|
committer | Bernd Edlinger <edlinger@gcc.gnu.org> | 2017-12-14 18:59:24 +0000 |
commit | c65e18d3331aa9995ddab8527132de706f6d9236 (patch) | |
tree | c07ca2eb9958d996e27a70559a3a4e136ba98e58 /gcc/c | |
parent | 9d0e85af87d9e7fe3bd68d1647b7c47ad299f011 (diff) | |
download | gcc-c65e18d3331aa9995ddab8527132de706f6d9236.zip gcc-c65e18d3331aa9995ddab8527132de706f6d9236.tar.gz gcc-c65e18d3331aa9995ddab8527132de706f6d9236.tar.bz2 |
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
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 63 |
2 files changed, 69 insertions, 0 deletions
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 <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 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); |