aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
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/c
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/c')
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-typeck.c63
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);