diff mbox series

[C++] Fix error-recovery with constexpr dtor (PR c++/92414)

Message ID 20191108091451.GM4650@tucnak
State New
Headers show
Series [C++] Fix error-recovery with constexpr dtor (PR c++/92414) | expand

Commit Message

Jakub Jelinek Nov. 8, 2019, 9:14 a.m. UTC
Hi!

We ICE on the following testcase, because DECL_INITIAL (decl) is
error_mark_node due to previously reported error and
cxx_eval_outermost_constant_expr is unhappy if ctx.ctor is not
a CONSTRUCTOR, but error_mark_node.

If the initializer is invalid, it should have been diagnosed already and
there is no need to try to evaluate constexpr dtor on it.

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

2019-11-08  Jakub Jelinek  <jakub@redhat.com>

	PR c++/92414
	* constexpr.c (cxx_constant_dtor): Don't call
	cxx_eval_outermost_constant_expr if DECL_INITIAL is erroneous.

	* g++.dg/cpp2a/constexpr-dtor4.C: New test.


	Jakub

Comments

Jason Merrill Nov. 18, 2019, 7:38 p.m. UTC | #1
On 11/8/19 9:14 AM, Jakub Jelinek wrote:
> Hi!
> 
> We ICE on the following testcase, because DECL_INITIAL (decl) is
> error_mark_node due to previously reported error and
> cxx_eval_outermost_constant_expr is unhappy if ctx.ctor is not
> a CONSTRUCTOR, but error_mark_node.
> 
> If the initializer is invalid, it should have been diagnosed already and
> there is no need to try to evaluate constexpr dtor on it.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2019-11-08  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/92414
> 	* constexpr.c (cxx_constant_dtor): Don't call
> 	cxx_eval_outermost_constant_expr if DECL_INITIAL is erroneous.

Why add the error-checking here rather than in 
cxx_eval_outermost_constant_expr when we use DECL_INITIAL?

> 	* g++.dg/cpp2a/constexpr-dtor4.C: New test.
> 
> --- gcc/cp/constexpr.c.jj	2019-11-06 08:58:37.000000000 +0100
> +++ gcc/cp/constexpr.c	2019-11-07 22:13:58.395840756 +0100
> @@ -6024,7 +6024,8 @@ cxx_constant_value (tree t, tree decl)
>   void
>   cxx_constant_dtor (tree t, tree decl)
>   {
> -  cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
> +  if (!error_operand_p (DECL_INITIAL (decl)))
> +    cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
>   }
>   
>   /* Helper routine for fold_simple function.  Either return simplified
> --- gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C.jj	2019-11-07 22:16:56.943181785 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C	2019-11-07 22:18:16.752993443 +0100
> @@ -0,0 +1,15 @@
> +// PR c++/92414
> +// { dg-do compile { target c++2a } }
> +
> +struct A { virtual void foo (); };
> +
> +struct B : A {
> +  constexpr B (int);	// { dg-warning "used but never defined" }
> +  constexpr ~B () { }
> +};
> +
> +struct D : B {
> +  constexpr D () : B (42) { }	// { dg-error "used before its definition" }
> +};
> +
> +constexpr D d;	// { dg-message "in 'constexpr' expansion of" }
> 
> 	Jakub
>
Jakub Jelinek Nov. 18, 2019, 11:22 p.m. UTC | #2
On Mon, Nov 18, 2019 at 02:38:51PM -0500, Jason Merrill wrote:
> On 11/8/19 9:14 AM, Jakub Jelinek wrote:
> > Hi!
> > 
> > We ICE on the following testcase, because DECL_INITIAL (decl) is
> > error_mark_node due to previously reported error and
> > cxx_eval_outermost_constant_expr is unhappy if ctx.ctor is not
> > a CONSTRUCTOR, but error_mark_node.
> > 
> > If the initializer is invalid, it should have been diagnosed already and
> > there is no need to try to evaluate constexpr dtor on it.
> > 
> > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> > 
> > 2019-11-08  Jakub Jelinek  <jakub@redhat.com>
> > 
> > 	PR c++/92414
> > 	* constexpr.c (cxx_constant_dtor): Don't call
> > 	cxx_eval_outermost_constant_expr if DECL_INITIAL is erroneous.
> 
> Why add the error-checking here rather than in
> cxx_eval_outermost_constant_expr when we use DECL_INITIAL?

So like this?
Also passed bootstrap/regtest on x86_64-linux and i686-linux:

2019-11-19  Jakub Jelinek  <jakub@redhat.com>

	PR c++/92414
	* constexpr.c (cxx_eval_outermost_constant_expr): If DECL_INITIAL
	on object is erroneous, return t without trying to evaluate
	a constexpr dtor.

	* g++.dg/cpp2a/constexpr-dtor4.C: New test.

--- gcc/cp/constexpr.c.jj	2019-11-18 21:50:49.539233013 +0100
+++ gcc/cp/constexpr.c	2019-11-18 21:52:47.217475549 +0100
@@ -5834,6 +5834,8 @@ cxx_eval_outermost_constant_expr (tree t
 	  gcc_assert (object && VAR_P (object));
 	  gcc_assert (DECL_DECLARED_CONSTEXPR_P (object));
 	  gcc_assert (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object));
+	  if (error_operand_p (DECL_INITIAL (object)))
+	    return t;
 	  ctx.ctor = unshare_expr (DECL_INITIAL (object));
 	  TREE_READONLY (ctx.ctor) = false;
 	  /* Temporarily force decl_really_constant_value to return false
--- gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C.jj	2019-11-18 21:50:56.152134256 +0100
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C	2019-11-18 21:50:56.152134256 +0100
@@ -0,0 +1,15 @@
+// PR c++/92414
+// { dg-do compile { target c++2a } }
+
+struct A { virtual void foo (); };
+
+struct B : A {
+  constexpr B (int);	// { dg-warning "used but never defined" }
+  constexpr ~B () { }
+};
+
+struct D : B {
+  constexpr D () : B (42) { }	// { dg-error "used before its definition" }
+};
+
+constexpr D d;	// { dg-message "in 'constexpr' expansion of" }


	Jakub
Jason Merrill Nov. 19, 2019, 9:13 p.m. UTC | #3
On 11/18/19 11:22 PM, Jakub Jelinek wrote:
> On Mon, Nov 18, 2019 at 02:38:51PM -0500, Jason Merrill wrote:
>> On 11/8/19 9:14 AM, Jakub Jelinek wrote:
>>> Hi!
>>>
>>> We ICE on the following testcase, because DECL_INITIAL (decl) is
>>> error_mark_node due to previously reported error and
>>> cxx_eval_outermost_constant_expr is unhappy if ctx.ctor is not
>>> a CONSTRUCTOR, but error_mark_node.
>>>
>>> If the initializer is invalid, it should have been diagnosed already and
>>> there is no need to try to evaluate constexpr dtor on it.
>>>
>>> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>>>
>>> 2019-11-08  Jakub Jelinek  <jakub@redhat.com>
>>>
>>> 	PR c++/92414
>>> 	* constexpr.c (cxx_constant_dtor): Don't call
>>> 	cxx_eval_outermost_constant_expr if DECL_INITIAL is erroneous.
>>
>> Why add the error-checking here rather than in
>> cxx_eval_outermost_constant_expr when we use DECL_INITIAL?
> 
> So like this?
> Also passed bootstrap/regtest on x86_64-linux and i686-linux:

OK, thanks.

> 2019-11-19  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/92414
> 	* constexpr.c (cxx_eval_outermost_constant_expr): If DECL_INITIAL
> 	on object is erroneous, return t without trying to evaluate
> 	a constexpr dtor.
> 
> 	* g++.dg/cpp2a/constexpr-dtor4.C: New test.
> 
> --- gcc/cp/constexpr.c.jj	2019-11-18 21:50:49.539233013 +0100
> +++ gcc/cp/constexpr.c	2019-11-18 21:52:47.217475549 +0100
> @@ -5834,6 +5834,8 @@ cxx_eval_outermost_constant_expr (tree t
>   	  gcc_assert (object && VAR_P (object));
>   	  gcc_assert (DECL_DECLARED_CONSTEXPR_P (object));
>   	  gcc_assert (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object));
> +	  if (error_operand_p (DECL_INITIAL (object)))
> +	    return t;
>   	  ctx.ctor = unshare_expr (DECL_INITIAL (object));
>   	  TREE_READONLY (ctx.ctor) = false;
>   	  /* Temporarily force decl_really_constant_value to return false
> --- gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C.jj	2019-11-18 21:50:56.152134256 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C	2019-11-18 21:50:56.152134256 +0100
> @@ -0,0 +1,15 @@
> +// PR c++/92414
> +// { dg-do compile { target c++2a } }
> +
> +struct A { virtual void foo (); };
> +
> +struct B : A {
> +  constexpr B (int);	// { dg-warning "used but never defined" }
> +  constexpr ~B () { }
> +};
> +
> +struct D : B {
> +  constexpr D () : B (42) { }	// { dg-error "used before its definition" }
> +};
> +
> +constexpr D d;	// { dg-message "in 'constexpr' expansion of" }
> 
> 
> 	Jakub
>
diff mbox series

Patch

--- gcc/cp/constexpr.c.jj	2019-11-06 08:58:37.000000000 +0100
+++ gcc/cp/constexpr.c	2019-11-07 22:13:58.395840756 +0100
@@ -6024,7 +6024,8 @@  cxx_constant_value (tree t, tree decl)
 void
 cxx_constant_dtor (tree t, tree decl)
 {
-  cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
+  if (!error_operand_p (DECL_INITIAL (decl)))
+    cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
 }
 
 /* Helper routine for fold_simple function.  Either return simplified
--- gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C.jj	2019-11-07 22:16:56.943181785 +0100
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-dtor4.C	2019-11-07 22:18:16.752993443 +0100
@@ -0,0 +1,15 @@ 
+// PR c++/92414
+// { dg-do compile { target c++2a } }
+
+struct A { virtual void foo (); };
+
+struct B : A {
+  constexpr B (int);	// { dg-warning "used but never defined" }
+  constexpr ~B () { }
+};
+
+struct D : B {
+  constexpr D () : B (42) { }	// { dg-error "used before its definition" }
+};
+
+constexpr D d;	// { dg-message "in 'constexpr' expansion of" }