We started crashing on this test with r258592 which added cp_get_callee_fndecl
in <case AGGR_INIT_EXPR> in cp_genericize_r.

This ICE apparently depends on whether we perform NRVO or not.  If the size of
S is <=16B we pass it in registers and it compiles fine.  But if the size of S
is >16B, then we pass in memory, and we NRV-optimize.  That means that
s.fn ();
is turned by finalize_nrv into
<retval>.fn ();

Then the newly added call to cp_get_callee_fndecl calls maybe_constant_init,
which ends up evaluating <retval>, but it's not in the hash map, so we crash
here:
4111       /* We ask for an rvalue for the RESULT_DECL when indirecting
4112          through an invisible reference, or in named return value
4113          optimization.  */
4114       return (*ctx->values->get (t));

I thought we could be more careful and not blindly dereference the result
of get().  After all, it's not a problem here if the <retval> cannot be
evaluated to a constant.

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

2018-03-20  Marek Polacek  <pola...@redhat.com>

        PR c++/84978
        * constexpr.c (cxx_eval_constant_expression): Handle the case when
        a RESULT_DECL isn't in the hash map.

        * g++.dg/opt/nrv19.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 894bcd0bb3e..1f8ece89730 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -4111,7 +4111,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
       /* We ask for an rvalue for the RESULT_DECL when indirecting
         through an invisible reference, or in named return value
         optimization.  */
-      return (*ctx->values->get (t));
+      if (tree *p = ctx->values->get (t))
+       return *p;
+      else
+       {
+         if (!ctx->quiet)
+           error ("%qE is not a constant expression", t);
+         *non_constant_p = true;
+       }
+      break;
 
     case VAR_DECL:
       if (DECL_HAS_VALUE_EXPR_P (t))
diff --git gcc/testsuite/g++.dg/opt/nrv19.C gcc/testsuite/g++.dg/opt/nrv19.C
index e69de29bb2d..385593cc90c 100644
--- gcc/testsuite/g++.dg/opt/nrv19.C
+++ gcc/testsuite/g++.dg/opt/nrv19.C
@@ -0,0 +1,15 @@
+// PR c++/84978
+// { dg-do compile }
+
+struct S {
+  void (*fn)();
+  int a[10];
+};
+
+S
+foo ()
+{
+  S s;
+  s.fn ();
+  return s;
+}

        Marek

Reply via email to