c++: constexpr static data member instantiation [PR94523]
authorJason Merrill <jason@redhat.com>
Thu, 9 Apr 2020 03:59:30 +0000 (23:59 -0400)
committerJason Merrill <jason@redhat.com>
Thu, 9 Apr 2020 21:34:16 +0000 (17:34 -0400)
Here due to my recent change to store_init_value we were expanding the
initializer of aw knowing that we were initializing aw.  When
cxx_eval_call_expression finished the constructor, it wanted to look up the
value of aw to set TREE_READONLY on it, but we haven't set DECL_INITIAL yet,
so decl_constant_value tried to instantiate the initializer again.  And
infinite recursion.  Stopped by optimizing the case of asking for the value
of ctx->object, which is ctx->value.  It also would have worked to look in
the values hash table, so let's move that up before decl_constant_value as
well.

gcc/cp/ChangeLog
2020-04-09  Jason Merrill  <jason@redhat.com>

PR c++/94523
* constexpr.c (cxx_eval_constant_expression) [VAR_DECL]: Look at
ctx->object and ctx->global->values first.

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C [new file with mode: 0644]

index cdd9b52915a1b7e3bf4abcb117ef5964923883ac..49246e8fa2d8553e3b5fc9a270dd6797f45f2db3 100644 (file)
@@ -1,3 +1,9 @@
+2020-04-09  Jason Merrill  <jason@redhat.com>
+
+       PR c++/94523
+       * constexpr.c (cxx_eval_constant_expression) [VAR_DECL]: Look at
+       ctx->object and ctx->global->values first.
+
 2020-04-09  Marek Polacek  <polacek@redhat.com>
 
        PR c++/93790
index 96497ab85d782a5374d9682074f0c8e43c4ee327..5793430c88daea18f47625d7dee9dc68f67c9702 100644 (file)
@@ -5485,6 +5485,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
         CONST_DECL for aggregate constants.  */
       if (lval)
        return t;
+      else if (t == ctx->object)
+       return ctx->ctor;
+      if (VAR_P (t))
+       if (tree *p = ctx->global->values.get (t))
+         if (*p != NULL_TREE)
+           {
+             r = *p;
+             break;
+           }
       if (COMPLETE_TYPE_P (TREE_TYPE (t))
          && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
        {
@@ -5499,10 +5508,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       if (TREE_CODE (r) == TARGET_EXPR
          && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
        r = TARGET_EXPR_INITIAL (r);
-      if (VAR_P (r))
-       if (tree *p = ctx->global->values.get (r))
-         if (*p != NULL_TREE)
-           r = *p;
       if (DECL_P (r))
        {
          if (!ctx->quiet)
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-static1.C
new file mode 100644 (file)
index 0000000..f39ed21
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/94523
+// { dg-do compile { target c++14 } }
+
+template <bool, typename a> using b = a;
+struct d {
+  char ao;
+  template <typename ap> constexpr d(ap) : ao{} {}
+};
+template <int... au> struct e { static constexpr auto aw = d(au...); };
+template <int c> b<c, d> ax(e<1>::aw);