aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cfgbuild.c5
-rw-r--r--gcc/sched-deps.c8
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/invalid-call-1.c17
5 files changed, 40 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2e2fad3..4444365 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2007-04-19 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR rtl-optimization/29841
+ * cfgbuild.c (control_flow_insn_p): Return TRUE for unconditional
+ trap instructions.
+ * sched-deps.c (sched_analyze_insn): Prevent all non-jump instructions
+ that may cause control flow transfer from being moved.
+
2007-04-18 Jan Hubicka <jh@suse.cz>
* fold-const.c (div_if_zero_remainder): Do signed divide for pointer
diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c
index 3d05ebc..642efc3 100644
--- a/gcc/cfgbuild.c
+++ b/gcc/cfgbuild.c
@@ -120,6 +120,11 @@ control_flow_insn_p (rtx insn)
|| can_throw_internal (insn));
case INSN:
+ /* Treat trap instructions like noreturn calls (same provision). */
+ if (GET_CODE (PATTERN (insn)) == TRAP_IF
+ && XEXP (PATTERN (insn), 0) == const1_rtx)
+ return true;
+
return (flag_non_call_exceptions && can_throw_internal (insn));
case BARRIER:
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index c3dc579..5a6a30a 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -1598,8 +1598,12 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
/* If this instruction can throw an exception, then moving it changes
where block boundaries fall. This is mighty confusing elsewhere.
- Therefore, prevent such an instruction from being moved. */
- if (can_throw_internal (insn))
+ Therefore, prevent such an instruction from being moved. Same for
+ non-jump instructions that define block boundaries.
+ ??? Unclear whether this is still necessary in EBB mode. If not,
+ add_branch_dependences should be adjusted for RGN mode instead. */
+ if (((CALL_P (insn) || JUMP_P (insn)) && can_throw_internal (insn))
+ || (NONJUMP_INSN_P (insn) && control_flow_insn_p (insn)))
reg_pending_barrier = MOVE_BARRIER;
/* Add dependencies if a scheduling barrier was found. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 06c53cf..501825d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2007-04-19 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * gcc.dg/invalid-call-1.c: New test.
+
2007-04-18 Dirk Mueller <dmueller@suse.de>
PR diagnostic/31227
diff --git a/gcc/testsuite/gcc.dg/invalid-call-1.c b/gcc/testsuite/gcc.dg/invalid-call-1.c
new file mode 100644
index 0000000..7474227
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/invalid-call-1.c
@@ -0,0 +1,17 @@
+/* PR rtl-optimization/29841 */
+/* Testcase by Khem Raj <raj.khem@gmail.com> */
+
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -mtune=i586" { target i?86-*-* } } */
+
+typedef void (*fp)(void);
+extern char* bar(void* a1, int a2);
+extern char* mar(int n);
+char* cptr;
+
+void foo()
+{
+ cptr = mar(6);
+ ((char *(*)(void *,int (*)(void *,unsigned char **),char**))((fp)bar))(0,0,(void*)(0)); /* { dg-warning "" "non-compatible type" } */
+}