[C++] Fix ICE in bot_manip (PR c++/84449)

Message ID 20180219190403.GP5867@tucnak
State New
Headers show
Series
  • [C++] Fix ICE in bot_manip (PR c++/84449)
Related show

Commit Message

Jakub Jelinek Feb. 19, 2018, 7:04 p.m.
Hi!

build_cplus_new can return error_mark_node e.g. when calling a deleted
ctor or dtor, but bot_manip was assuming it will always return
AGGR_INIT_EXPR.  As it is generally unsafe to set subexpressions to
error_mark_node, e.g. cp_fold ICEs if binary expression has one of its
operand error_mark_node, the patch instead arranges for the whole
break_out_target_exprs to return error_mark_node in that case.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-02-19  Jakub Jelinek  <jakub@redhat.com>

	PR c++/84449
	* tree.c (bot_manip): If build_cplus_new or break_out_target_exprs
	returns error_mark_node, return it immediately.
	(break_out_target_exprs): If cp_walk_tree with bot_manip returns
	error_mark_node, return error_mark_node.

	* g++.dg/cpp0x/constexpr-84449.C: New test.


	Jakub

Comments

Jason Merrill Feb. 20, 2018, 3:12 a.m. | #1
OK.

On Mon, Feb 19, 2018 at 2:04 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!

>

> build_cplus_new can return error_mark_node e.g. when calling a deleted

> ctor or dtor, but bot_manip was assuming it will always return

> AGGR_INIT_EXPR.  As it is generally unsafe to set subexpressions to

> error_mark_node, e.g. cp_fold ICEs if binary expression has one of its

> operand error_mark_node, the patch instead arranges for the whole

> break_out_target_exprs to return error_mark_node in that case.

>

> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

>

> 2018-02-19  Jakub Jelinek  <jakub@redhat.com>

>

>         PR c++/84449

>         * tree.c (bot_manip): If build_cplus_new or break_out_target_exprs

>         returns error_mark_node, return it immediately.

>         (break_out_target_exprs): If cp_walk_tree with bot_manip returns

>         error_mark_node, return error_mark_node.

>

>         * g++.dg/cpp0x/constexpr-84449.C: New test.

>

> --- gcc/cp/tree.c.jj    2018-02-10 00:22:01.000000000 +0100

> +++ gcc/cp/tree.c       2018-02-19 11:54:55.815478346 +0100

> @@ -2896,6 +2896,8 @@ bot_manip (tree* tp, int* walk_subtrees,

>         {

>           u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),

>                                tf_warning_or_error);

> +         if (u == error_mark_node)

> +           return u;

>           if (AGGR_INIT_ZERO_FIRST (TREE_OPERAND (t, 1)))

>             AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true;

>         }

> @@ -2913,6 +2915,8 @@ bot_manip (tree* tp, int* walk_subtrees,

>                          (splay_tree_value) TREE_OPERAND (u, 0));

>

>        TREE_OPERAND (u, 1) = break_out_target_exprs (TREE_OPERAND (u, 1));

> +      if (TREE_OPERAND (u, 1) == error_mark_node)

> +       return error_mark_node;

>

>        /* Replace the old expression with the new version.  */

>        *tp = u;

> @@ -3025,7 +3029,8 @@ break_out_target_exprs (tree t)

>      target_remap = splay_tree_new (splay_tree_compare_pointers,

>                                    /*splay_tree_delete_key_fn=*/NULL,

>                                    /*splay_tree_delete_value_fn=*/NULL);

> -  cp_walk_tree (&t, bot_manip, target_remap, NULL);

> +  if (cp_walk_tree (&t, bot_manip, target_remap, NULL) == error_mark_node)

> +    t = error_mark_node;

>    cp_walk_tree (&t, bot_replace, target_remap, NULL);

>

>    if (!--target_remap_count)

> --- gcc/testsuite/g++.dg/cpp0x/constexpr-84449.C.jj     2018-02-19 12:04:51.518530240 +0100

> +++ gcc/testsuite/g++.dg/cpp0x/constexpr-84449.C        2018-02-19 12:04:26.643528069 +0100

> @@ -0,0 +1,14 @@

> +// PR c++/84449

> +// { dg-do compile { target c++11 } }

> +

> +struct A

> +{

> +  constexpr A (int) {}

> +  ~A () = delete;

> +};

> +

> +struct B

> +{

> +  A a;

> +  constexpr B () : a (0) {}    // { dg-error "use of deleted function" }

> +};

>

>         Jakub

Patch

--- gcc/cp/tree.c.jj	2018-02-10 00:22:01.000000000 +0100
+++ gcc/cp/tree.c	2018-02-19 11:54:55.815478346 +0100
@@ -2896,6 +2896,8 @@  bot_manip (tree* tp, int* walk_subtrees,
 	{
 	  u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
 			       tf_warning_or_error);
+	  if (u == error_mark_node)
+	    return u;
 	  if (AGGR_INIT_ZERO_FIRST (TREE_OPERAND (t, 1)))
 	    AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true;
 	}
@@ -2913,6 +2915,8 @@  bot_manip (tree* tp, int* walk_subtrees,
 			 (splay_tree_value) TREE_OPERAND (u, 0));
 
       TREE_OPERAND (u, 1) = break_out_target_exprs (TREE_OPERAND (u, 1));
+      if (TREE_OPERAND (u, 1) == error_mark_node)
+	return error_mark_node;
 
       /* Replace the old expression with the new version.  */
       *tp = u;
@@ -3025,7 +3029,8 @@  break_out_target_exprs (tree t)
     target_remap = splay_tree_new (splay_tree_compare_pointers,
 				   /*splay_tree_delete_key_fn=*/NULL,
 				   /*splay_tree_delete_value_fn=*/NULL);
-  cp_walk_tree (&t, bot_manip, target_remap, NULL);
+  if (cp_walk_tree (&t, bot_manip, target_remap, NULL) == error_mark_node)
+    t = error_mark_node;
   cp_walk_tree (&t, bot_replace, target_remap, NULL);
 
   if (!--target_remap_count)
--- gcc/testsuite/g++.dg/cpp0x/constexpr-84449.C.jj	2018-02-19 12:04:51.518530240 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-84449.C	2018-02-19 12:04:26.643528069 +0100
@@ -0,0 +1,14 @@ 
+// PR c++/84449
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  constexpr A (int) {}
+  ~A () = delete;
+};
+
+struct B
+{
+  A a;
+  constexpr B () : a (0) {}	// { dg-error "use of deleted function" }
+};