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/cp | |
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/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 3 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 77 |
3 files changed, 83 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ac6a8e1..d7a1dde 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 5d30369..89a940a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 8f3302f..390aa15 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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))) { |