Hi!

Apparently we can end up trying to store into a pointer-to-member
that has a PTRMEM_CST as its current value.  Later code in
cxx_eval_store_expression is upset that it isn't a CONSTRUCTOR when
the type is actually aggregate.

The following patch fixes that, bootstrapped/regtested on x86_64-linux
and i686-linux, though I admit I'm not really sure if this is the best fix.

2017-02-21  Jakub Jelinek  <ja...@redhat.com>

        PR c++/79639
        * constexpr.c (cxx_eval_store_expression): If *valp is a PTRMEM_CST,
        call cplus_expand_constant on it first.

        * g++.dg/cpp1y/constexpr-79639.C: New test. 

--- gcc/cp/constexpr.c.jj       2017-02-21 13:49:06.000000000 +0100
+++ gcc/cp/constexpr.c  2017-02-21 14:57:30.290440638 +0100
@@ -3518,11 +3518,12 @@ cxx_eval_store_expression (const constex
         wants to modify it.  */
       if (*valp == NULL_TREE)
        {
-         *valp = new_ctx.ctor = build_constructor (type, NULL);
-         CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = no_zero_init;
+         *valp = build_constructor (type, NULL);
+         CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = no_zero_init;
        }
-      else
-       new_ctx.ctor = *valp;
+      else if (TREE_CODE (*valp) == PTRMEM_CST)
+       *valp = cplus_expand_constant (*valp);
+      new_ctx.ctor = *valp;
       new_ctx.object = target;
     }
 
--- gcc/testsuite/g++.dg/cpp1y/constexpr-79639.C.jj     2017-02-21 
15:06:42.625475572 +0100
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-79639.C        2017-02-21 
15:06:07.000000000 +0100
@@ -0,0 +1,27 @@
+// PR c++/79639
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+  void foo () {}
+  void bar () {}
+};
+typedef void (A::*T) ();
+
+constexpr T
+foo (T f)
+{
+  f = 0;
+  return f;
+}
+
+constexpr T
+bar (T f)
+{
+  f = &A::bar;
+  return f;
+}
+
+constexpr T a = foo (&A::foo);
+constexpr T b = foo (&A::foo);
+static_assert (a == nullptr, "");

        Jakub

Reply via email to