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