re PR c++/49165 (ICE on for-loop/throw combination)
authorJakub Jelinek <jakub@redhat.com>
Fri, 27 May 2011 19:19:36 +0000 (21:19 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 27 May 2011 19:19:36 +0000 (21:19 +0200)
PR c++/49165
* c-common.c (c_common_truthvalue_conversion) <case COND_EXPR>: For
C++ don't call c_common_truthvalue_conversion on void type arms.

* g++.dg/eh/cond6.C: New test.

From-SVN: r174350

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/cond6.C [new file with mode: 0644]

index 557f89634e9b8dd84b1b3d71fcfea5363bc3ab03..3bdfbab007c66eb38e02258657e22fd28dae0843 100644 (file)
@@ -1,3 +1,9 @@
+2011-05-27  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/49165
+       * c-common.c (c_common_truthvalue_conversion) <case COND_EXPR>: For
+       C++ don't call c_common_truthvalue_conversion on void type arms.
+
 2011-05-27  Nathan Froyd  <froydnj@codesourcery.com>
 
        * c-common.h (struct stmt_tree_s) [x_cur_stmt_list]: Change to a VEC.
index fa7ebc5d30d7ba2e5aca15d1829284bc1ae086fc..dbef4b314eab6045fd700dd631edc98bd0b0d5f1 100644 (file)
@@ -3945,14 +3945,15 @@ c_common_truthvalue_conversion (location_t location, tree expr)
       /* Distribute the conversion into the arms of a COND_EXPR.  */
       if (c_dialect_cxx ())
        {
+         tree op1 = TREE_OPERAND (expr, 1);
+         tree op2 = TREE_OPERAND (expr, 2);
+         /* In C++ one of the arms might have void type if it is throw.  */
+         if (!VOID_TYPE_P (TREE_TYPE (op1)))
+           op1 = c_common_truthvalue_conversion (location, op1);
+         if (!VOID_TYPE_P (TREE_TYPE (op2)))
+           op2 = c_common_truthvalue_conversion (location, op2);
          expr = fold_build3_loc (location, COND_EXPR, truthvalue_type_node,
-                             TREE_OPERAND (expr, 0),
-                             c_common_truthvalue_conversion (location,
-                                                             TREE_OPERAND (expr,
-                                                                           1)),
-                             c_common_truthvalue_conversion (location,
-                                                             TREE_OPERAND (expr,
-                                                                           2)));
+                                 TREE_OPERAND (expr, 0), op1, op2);
          goto ret;
        }
       else
index bb23b71195f60a4a0dc066c5b3afd33755ee2934..141714250d80ae04f7689739631a671bee2aabc0 100644 (file)
@@ -1,3 +1,8 @@
+2011-05-27  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/49165
+       * g++.dg/eh/cond6.C: New test.
+
 2011-05-27  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/48820
diff --git a/gcc/testsuite/g++.dg/eh/cond6.C b/gcc/testsuite/g++.dg/eh/cond6.C
new file mode 100644 (file)
index 0000000..1eed63e
--- /dev/null
@@ -0,0 +1,43 @@
+// PR c++/49165
+// { dg-do run }
+
+extern "C" void abort ();
+
+int
+foo (bool x, int y)
+{
+  if (y < 10 && (x ? 1 : throw 1))
+    y++;
+  if (y > 20 || (x ? 1 : throw 2))
+    y++;
+  return y;
+}
+
+int
+main ()
+{
+  if (foo (true, 0) != 2
+      || foo (true, 10) != 11
+      || foo (false, 30) != 31)
+    abort ();
+  try
+    {
+      foo (false, 0);
+      abort ();
+    }
+  catch (int i)
+    {
+      if (i != 1)
+       abort ();
+    }
+  try
+    {
+      foo (false, 10);
+      abort ();
+    }
+  catch (int i)
+    {
+      if (i != 2)
+       abort ();
+    }
+}