This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/84978, ICE with NRVO
- From: Marek Polacek <polacek at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>
- Date: Tue, 20 Mar 2018 14:32:05 +0100
- Subject: C++ PATCH for c++/84978, ICE with NRVO
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 <polacek@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