diff options
author | Eric Botcazou <ebotcazou@libertysurf.fr> | 2003-12-20 08:12:39 +0100 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2003-12-20 07:12:39 +0000 |
commit | c96f4f736a59db9dc34b776392576d4832914689 (patch) | |
tree | 58cb78943c2eb8f3ef4c073d23518b703972ec8d /gcc | |
parent | bcd11e5e45f59f88d76cd56024e1d7c14a7c4665 (diff) | |
download | gcc-c96f4f736a59db9dc34b776392576d4832914689.zip gcc-c96f4f736a59db9dc34b776392576d4832914689.tar.gz gcc-c96f4f736a59db9dc34b776392576d4832914689.tar.bz2 |
re PR c/12085 (Internal compiler error in convert_move, at expr.c:504 with -O3 flag)
PR c/12085
* c-typeck.c (build_function_call): Issue a warning if a
function is called through an incompatible prototype and
replace the call by a trap in this case.
From-SVN: r74874
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/c-typeck.c | 42 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/cast-function-1.c | 49 |
4 files changed, 102 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af9d6d4..a61b493 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2003-12-20 Eric Botcazou <ebotcazou@libertysurf.fr> + + PR c/12085 + * c-typeck.c (build_function_call): Issue a warning if a + function is called through an incompatible prototype and + replace the call by a trap in this case. + 2003-12-19 James E Wilson <wilson@specifixinc.com> * install.texi (ia64-*-linux): Document minimum libunwind version diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 9747a8c..eee6d55 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1645,6 +1645,7 @@ build_function_call (tree function, tree params) tree fntype, fundecl = 0; tree coerced_params; tree name = NULL_TREE, result; + tree tem; /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ STRIP_TYPE_NOPS (function); @@ -1684,6 +1685,47 @@ build_function_call (tree function, tree params) /* fntype now gets the type of function pointed to. */ fntype = TREE_TYPE (fntype); + /* 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. + + ??? This doesn't work for Objective-C because objc_comptypes + refuses to compare function prototypes, yet the compiler appears + to build calls that are flagged as invalid by C's comptypes. */ + if (! c_dialect_objc () + && TREE_CODE (function) == NOP_EXPR + && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR + && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL + && ! comptypes (fntype, TREE_TYPE (tem), COMPARE_STRICT)) + { + tree return_type = TREE_TYPE (fntype); + tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP], + NULL_TREE); + + /* 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 ("function called through a non-compatible type"); + + if (VOID_TYPE_P (return_type)) + return trap; + else + { + tree rhs; + + if (AGGREGATE_TYPE_P (return_type)) + rhs = build_compound_literal (return_type, + build_constructor (return_type, + NULL_TREE)); + else + rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node)); + + return build (COMPOUND_EXPR, return_type, trap, rhs); + } + } + /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bb7bce6..c62be7e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-12-20 Eric Botcazou <ebotcazou@libertysurf.fr> + + * gcc.dg/cast-function-1.c: New test. + 2003-12-19 Joseph S. Myers <jsm@polyomino.org.uk> * gcc.dg/format/ext-1.c: Allow 'I' flag on floating point decimal diff --git a/gcc/testsuite/gcc.dg/cast-function-1.c b/gcc/testsuite/gcc.dg/cast-function-1.c new file mode 100644 index 0000000..44cb183 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cast-function-1.c @@ -0,0 +1,49 @@ +/* PR c/12085 */ +/* Origin: David Hollenberg <dhollen@mosis.org> */ + +/* Verify that the compiler doesn't inline a function at + a calling point where it is viewed with a different + prototype than the actual one. */ + +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +int foo1(int); +int foo2(); + +typedef struct { + double d; + int a; +} str_t; + +void bar(void) +{ + double d; + int i; + str_t s; + + d = ((double (*) (int)) foo1) (i); /* { dg-warning "non-compatible" } */ + i = ((int (*) (double)) foo1) (d); /* { dg-warning "non-compatible" } */ + s = ((str_t (*) (int)) foo1) (i); /* { dg-warning "non-compatible" } */ + ((void (*) (int)) foo1) (d); /* { dg-warning "non-compatible" } */ + i = ((int (*) (int)) foo1) (i); /* { dg-bogus "non-compatible" } */ + (void) foo1 (i); /* { dg-bogus "non-compatible" } */ + + d = ((double (*) (int)) foo2) (i); /* { dg-warning "non-compatible" } */ + i = ((int (*) (double)) foo2) (d); /* { dg-bogus "non-compatible" } */ + s = ((str_t (*) (int)) foo2) (i); /* { dg-warning "non-compatible" } */ + ((void (*) (int)) foo2) (d); /* { dg-warning "non-compatible" } */ + i = ((int (*) (int)) foo2) (i); /* { dg-bogus "non-compatible" } */ + (void) foo2 (i); /* { dg-bogus "non-compatible" } */ +} + +int foo1(int arg) +{ + return arg; +} + +int foo2(arg) + int arg; +{ + return arg; +} |