aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2017-12-14 18:59:24 +0000
committerBernd Edlinger <edlinger@gcc.gnu.org>2017-12-14 18:59:24 +0000
commitc65e18d3331aa9995ddab8527132de706f6d9236 (patch)
treec07ca2eb9958d996e27a70559a3a4e136ba98e58 /gcc/cp
parent9d0e85af87d9e7fe3bd68d1647b7c47ad299f011 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/cp/typeck.c77
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)))
{