On Wed, 29 Jan 2014, Richard Biener wrote: > > This removes the code that tries to avoid ICEs in the middle-end when > facing calls through an incompatible type. The middle-end can now > happily deal with those mismatches (and we rely on that). Also the > code only detects the most primitive cases like > > ((bar_get_x_func*) foo_get_x) (x) > > but does not touch > > bar_get_x_func* fn = foo_get_x; > fn (x); > > I preserved the warning (so I didn't have to remove the cast-function-1.c > testcase) and fixed the testcase to be not optimized to nothing by the > very first DCE pass and thus get non-empty assembler output with > some calls and some inlines (yes, we _can_ inline some mismatches, > esp. those refered to in the PR which is about void * vs some > struct * type). > > Bootstrap / regtest running on x86_64-unknown-linux-gnu - ok for trunk?
testing reveals diagnostic regressions FAIL: gcc.dg/call-diag-2.c abort (test for warnings, line 12) FAIL: gcc.dg/call-diag-2.c abort (test for warnings, line 15) FAIL: gcc.dg/invalid-call-1.c (test for warnings, line 16) which may be hard to preserve (didn't investigate thoroughly yet), one is probably emitted via the call to require_complete_type I remove. Is it ok to adjust the testcases expectation for what is produced now? Otherwise I'll dump this patch for now. Thanks, Richard. > Thanks, > Richard. > > 2014-01-29 Richard Biener <rguent...@suse.de> > > PR c/59905 > * c-typeck.c (build_function_call_vec): Do not replace calls > to a function via an incompatible type with a runtime abort. > > * gcc.dg/cast-function-1.c: Adjust to survive DCE. > > Index: gcc/c/c-typeck.c > =================================================================== > *** gcc/c/c-typeck.c (revision 207194) > --- gcc/c/c-typeck.c (working copy) > *************** build_function_call_vec (location_t loc, > *** 2907,2962 **** > return error_mark_node; > > /* Check that the function is called through a compatible prototype. > ! If it is not, replace the call by a trap, wrapped up in a compound > ! expression if necessary. This has the nice side-effect to prevent > ! the tree-inliner from generating invalid assignment trees which may > ! blow up in the RTL expander later. */ > if (CONVERT_EXPR_P (function) > && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR > && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL > && !comptypes (fntype, TREE_TYPE (tem))) > { > tree return_type = TREE_TYPE (fntype); > - tree trap = build_function_call (loc, > - builtin_decl_explicit (BUILT_IN_TRAP), > - NULL_TREE); > - int i; > > /* This situation leads to run-time undefined behavior. We can't, > therefore, simply error unless we can prove that all possible > executions of the program must execute the code. */ > ! if (warning_at (loc, 0, "function called through a non-compatible > type")) > ! /* We can, however, treat "undefined" any way we please. > ! Call abort to encourage the user to fix the program. */ > ! inform (loc, "if this code is reached, the program will abort"); > ! /* Before the abort, allow the function arguments to exit or > ! call longjmp. */ > ! for (i = 0; i < nargs; i++) > ! trap = build2 (COMPOUND_EXPR, void_type_node, (*params)[i], trap); > > ! if (VOID_TYPE_P (return_type)) > ! { > ! if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED) > ! pedwarn (loc, 0, > ! "function with qualified void return type called"); > ! return trap; > ! } > ! else > ! { > ! tree rhs; > ! > ! if (AGGREGATE_TYPE_P (return_type)) > ! rhs = build_compound_literal (loc, return_type, > ! build_constructor (return_type, > ! NULL), > ! false); > ! else > ! rhs = build_zero_cst (return_type); > ! > ! return require_complete_type (build2 (COMPOUND_EXPR, return_type, > ! trap, rhs)); > ! } > ! } > > argarray = vec_safe_address (params); > > --- 2907,2930 ---- > return error_mark_node; > > /* Check that the function is called through a compatible prototype. > ! If it is not, warn. */ > if (CONVERT_EXPR_P (function) > && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR > && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL > && !comptypes (fntype, TREE_TYPE (tem))) > { > tree return_type = TREE_TYPE (fntype); > > /* This situation leads to run-time undefined behavior. We can't, > therefore, simply error unless we can prove that all possible > executions of the program must execute the code. */ > ! warning_at (loc, 0, "function called through a non-compatible type"); > > ! if (VOID_TYPE_P (return_type) > ! && TYPE_QUALS (return_type) != TYPE_UNQUALIFIED) > ! pedwarn (loc, 0, > ! "function with qualified void return type called"); > ! } > > argarray = vec_safe_address (params); > > Index: gcc/testsuite/gcc.dg/cast-function-1.c > =================================================================== > *** gcc/testsuite/gcc.dg/cast-function-1.c (revision 207194) > --- gcc/testsuite/gcc.dg/cast-function-1.c (working copy) > *************** typedef struct { > *** 16,27 **** > int a; > } str_t; > > ! void bar(void) > { > - double d; > - int i; > - str_t s; > - > d = ((double (*) (int)) foo1) (i); /* { dg-warning > "33:non-compatible|abort" } */ > i = ((int (*) (double)) foo1) (d); /* { dg-warning > "33:non-compatible|abort" } */ > s = ((str_t (*) (int)) foo1) (i); /* { dg-warning > "32:non-compatible|abort" } */ > --- 16,23 ---- > int a; > } str_t; > > ! void bar(double d, int i, str_t s) > { > d = ((double (*) (int)) foo1) (i); /* { dg-warning > "33:non-compatible|abort" } */ > i = ((int (*) (double)) foo1) (d); /* { dg-warning > "33:non-compatible|abort" } */ > s = ((str_t (*) (int)) foo1) (i); /* { dg-warning > "32:non-compatible|abort" } */ > *************** void bar(void) > *** 39,49 **** > --- 35,49 ---- > > int foo1(int arg) > { > + /* Prevent the function from becoming const and thus DCEd. */ > + __asm volatile ("" : "+r" (arg)); > return arg; > } > > int foo2(arg) > int arg; > { > + /* Prevent the function from becoming const and thus DCEd. */ > + __asm volatile ("" : "+r" (arg)); > return arg; > } > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer