aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pinski <apinski@marvell.com>2022-02-13 00:09:39 +0000
committerAndrew Pinski <apinski@marvell.com>2022-02-21 09:05:50 +0000
commite01530ec1e33f7df9c2acd0489d6d1f766cb1921 (patch)
treecbbef6e7711559b184bee3974a42b4361357f383
parentc42f1e7734412c64e45a0fb0e519d40e144d6f9d (diff)
downloadgcc-e01530ec1e33f7df9c2acd0489d6d1f766cb1921.zip
gcc-e01530ec1e33f7df9c2acd0489d6d1f766cb1921.tar.gz
gcc-e01530ec1e33f7df9c2acd0489d6d1f766cb1921.tar.bz2
c: [PR104506] Fix ICE after error due to change of type to error_mark_node
The problem here is we end up with an error_mark_node when calling useless_type_conversion_p and that ICEs. STRIP_NOPS/tree_nop_conversion has had a check for the inner type being an error_mark_node since g9a6bb3f78c96 (2000). This just adds the check also to tree_ssa_useless_type_conversion. STRIP_USELESS_TYPE_CONVERSION is mostly used inside the gimplifier and the places where it is used outside of the gimplifier would not be adding too much overhead. OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions. Thanks, Andrew Pinski PR c/104506 gcc/ChangeLog: * tree-ssa.cc (tree_ssa_useless_type_conversion): Check the inner type before calling useless_type_conversion_p. gcc/testsuite/ChangeLog: * gcc.dg/pr104506-1.c: New test. * gcc.dg/pr104506-2.c: New test. * gcc.dg/pr104506-3.c: New test.
-rw-r--r--gcc/testsuite/gcc.dg/pr104506-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr104506-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/pr104506-3.c11
-rw-r--r--gcc/tree-ssa.cc20
4 files changed, 47 insertions, 7 deletions
diff --git a/gcc/testsuite/gcc.dg/pr104506-1.c b/gcc/testsuite/gcc.dg/pr104506-1.c
new file mode 100644
index 0000000..5eb7191
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104506-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu11" } */
+/* PR c/104506: we used to ICE after the error of
+ changing the type. */
+
+void
+foo (double x)
+/* { dg-message "note: previous definition" "previous definition" { target *-*-* } .-1 } */
+{
+ (void)x;
+ int x; /* { dg-error "redeclared as different kind of symbol" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr104506-2.c b/gcc/testsuite/gcc.dg/pr104506-2.c
new file mode 100644
index 0000000..3c3aaaa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104506-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu11" } */
+/* PR c/104506: we used to ICE after the error of
+ changing the type. */
+void
+foo (double x)
+/* { dg-message "note: previous definition" "previous definition" { target *-*-* } .-1 } */
+{
+ x;
+ int x; /* { dg-error "redeclared as different kind of symbol" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr104506-3.c b/gcc/testsuite/gcc.dg/pr104506-3.c
new file mode 100644
index 0000000..b14deb5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr104506-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* PR c/104506: we used to ICE after the error of
+ changing the type. */
+double x;
+/* { dg-message "note: previous declaration" "previous declaration" { target *-*-* } .-1 } */
+void
+foo (void)
+{
+ x;
+}
+int x; /* { dg-error "conflicting types" } */
diff --git a/gcc/tree-ssa.cc b/gcc/tree-ssa.cc
index 430875a..423dd87 100644
--- a/gcc/tree-ssa.cc
+++ b/gcc/tree-ssa.cc
@@ -1256,18 +1256,24 @@ delete_tree_ssa (struct function *fn)
bool
tree_ssa_useless_type_conversion (tree expr)
{
+ tree outer_type, inner_type;
+
/* If we have an assignment that merely uses a NOP_EXPR to change
the top of the RHS to the type of the LHS and the type conversion
is "safe", then strip away the type conversion so that we can
enter LHS = RHS into the const_and_copies table. */
- if (CONVERT_EXPR_P (expr)
- || TREE_CODE (expr) == VIEW_CONVERT_EXPR
- || TREE_CODE (expr) == NON_LVALUE_EXPR)
- return useless_type_conversion_p
- (TREE_TYPE (expr),
- TREE_TYPE (TREE_OPERAND (expr, 0)));
+ if (!CONVERT_EXPR_P (expr)
+ && TREE_CODE (expr) != VIEW_CONVERT_EXPR
+ && TREE_CODE (expr) != NON_LVALUE_EXPR)
+ return false;
- return false;
+ outer_type = TREE_TYPE (expr);
+ inner_type = TREE_TYPE (TREE_OPERAND (expr, 0));
+
+ if (inner_type == error_mark_node)
+ return false;
+
+ return useless_type_conversion_p (outer_type, inner_type);
}
/* Strip conversions from EXP according to