diff mbox

[C++] Fix wrong-code on var construction in static init (PR c++/77907)

Message ID 20161123145946.GP3541@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 23, 2016, 2:59 p.m. UTC
Hi!

During cp_fold, we see a call to constructor and because the ctor
is DECL_DECLARED_CONSTEXPR_P, when optimizing we call maybe_constant_value
on it.  But as when evaluating that we don't have an object, it returns
the initializer of the var, rather than an assignment of the initializer to
the var, so it is optimized away.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2016-11-23  Jakub Jelinek  <jakub@redhat.com>

	PR c++/77907
	* cp-gimplify.c (cp_fold) <case CALL_EXPR>: When calling constructor
	and maybe_constant_value returns non-CALL_EXPR, create INIT_EXPR
	with the object on lhs and maybe_constant_value returned expr on rhs.

	* g++.dg/cpp0x/pr77907.C: New test.


	Jakub

Comments

Jason Merrill Nov. 23, 2016, 3:42 p.m. UTC | #1
OK, but I wonder why we don't do constant initialization of that variable...

On Wed, Nov 23, 2016 at 9:59 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> During cp_fold, we see a call to constructor and because the ctor
> is DECL_DECLARED_CONSTEXPR_P, when optimizing we call maybe_constant_value
> on it.  But as when evaluating that we don't have an object, it returns
> the initializer of the var, rather than an assignment of the initializer to
> the var, so it is optimized away.
>
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
> trunk?
>
> 2016-11-23  Jakub Jelinek  <jakub@redhat.com>
>
>         PR c++/77907
>         * cp-gimplify.c (cp_fold) <case CALL_EXPR>: When calling constructor
>         and maybe_constant_value returns non-CALL_EXPR, create INIT_EXPR
>         with the object on lhs and maybe_constant_value returned expr on rhs.
>
>         * g++.dg/cpp0x/pr77907.C: New test.
>
> --- gcc/cp/cp-gimplify.c.jj     2016-11-22 21:31:41.000000000 +0100
> +++ gcc/cp/cp-gimplify.c        2016-11-23 12:42:07.803518968 +0100
> @@ -2338,11 +2338,18 @@ cp_fold (tree x)
>            constant, but the call followed by an INDIRECT_REF is.  */
>         if (callee && DECL_DECLARED_CONSTEXPR_P (callee)
>             && !flag_no_inline)
> -          r = maybe_constant_value (x);
> +         r = maybe_constant_value (x);
>         optimize = sv;
>
>          if (TREE_CODE (r) != CALL_EXPR)
>           {
> +           if (DECL_CONSTRUCTOR_P (callee))
> +             {
> +               loc = EXPR_LOCATION (x);
> +               tree s = build_fold_indirect_ref_loc (loc,
> +                                                     CALL_EXPR_ARG (x, 0));
> +               r = build2_loc (loc, INIT_EXPR, TREE_TYPE (s), s, r);
> +             }
>             x = r;
>             break;
>           }
> --- gcc/testsuite/g++.dg/cpp0x/pr77907.C.jj     2016-11-23 12:42:46.660031305 +0100
> +++ gcc/testsuite/g++.dg/cpp0x/pr77907.C        2016-11-23 12:40:12.000000000 +0100
> @@ -0,0 +1,22 @@
> +// PR c++/77907
> +// { dg-do run { target c++11 } }
> +// { dg-options "-O2" }
> +
> +struct A {
> +  int foo () { return 1; }
> +};
> +
> +struct B {
> +  using C = int (A::*) ();
> +  constexpr explicit B (const C x) : b{x} {}
> +  C b;
> +};
> +
> +B b{&A::foo};
> +
> +int
> +main ()
> +{
> +  if (!b.b)
> +    __builtin_abort ();
> +}
>
>         Jakub
diff mbox

Patch

--- gcc/cp/cp-gimplify.c.jj	2016-11-22 21:31:41.000000000 +0100
+++ gcc/cp/cp-gimplify.c	2016-11-23 12:42:07.803518968 +0100
@@ -2338,11 +2338,18 @@  cp_fold (tree x)
 	   constant, but the call followed by an INDIRECT_REF is.  */
 	if (callee && DECL_DECLARED_CONSTEXPR_P (callee)
 	    && !flag_no_inline)
-          r = maybe_constant_value (x);
+	  r = maybe_constant_value (x);
 	optimize = sv;
 
         if (TREE_CODE (r) != CALL_EXPR)
 	  {
+	    if (DECL_CONSTRUCTOR_P (callee))
+	      {
+		loc = EXPR_LOCATION (x);
+		tree s = build_fold_indirect_ref_loc (loc,
+						      CALL_EXPR_ARG (x, 0));
+		r = build2_loc (loc, INIT_EXPR, TREE_TYPE (s), s, r);
+	      }
 	    x = r;
 	    break;
 	  }
--- gcc/testsuite/g++.dg/cpp0x/pr77907.C.jj	2016-11-23 12:42:46.660031305 +0100
+++ gcc/testsuite/g++.dg/cpp0x/pr77907.C	2016-11-23 12:40:12.000000000 +0100
@@ -0,0 +1,22 @@ 
+// PR c++/77907
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+
+struct A {
+  int foo () { return 1; }
+};
+
+struct B {
+  using C = int (A::*) ();
+  constexpr explicit B (const C x) : b{x} {}
+  C b;
+};
+
+B b{&A::foo};
+
+int
+main ()
+{
+  if (!b.b)
+    __builtin_abort ();
+}