aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2003-12-20 08:12:39 +0100
committerEric Botcazou <ebotcazou@gcc.gnu.org>2003-12-20 07:12:39 +0000
commitc96f4f736a59db9dc34b776392576d4832914689 (patch)
tree58cb78943c2eb8f3ef4c073d23518b703972ec8d /gcc
parentbcd11e5e45f59f88d76cd56024e1d7c14a7c4665 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/c-typeck.c42
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/cast-function-1.c49
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;
+}