This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH] Reject self-recursive constexpr calls even in templates (PR c++/70449)
- From: Jason Merrill <jason at redhat dot com>
- To: Jakub Jelinek <jakub at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 23 May 2016 23:33:35 -0400
- Subject: Re: [C++ PATCH] Reject self-recursive constexpr calls even in templates (PR c++/70449)
- Authentication-results: sourceware.org; auth=none
- References: <20160401191941 dot GG3017 at tucnak dot redhat dot com> <56FF21B2 dot 7060107 at redhat dot com> <56FF21C9 dot 4050003 at redhat dot com>
On 04/01/2016 09:35 PM, Jason Merrill wrote:
On 04/01/2016 09:34 PM, Jason Merrill wrote:
On 04/01/2016 03:19 PM, Jakub Jelinek wrote:
As the testcase shows, when not in a template, cxx_eval_call_expression
already complains about self-recursive calls in constexpr contexts,
but if we are in a function template, we ICE on the testcase,
because we try to instantiate the function template we are in the
middle of
parsing, e.g. function_end_locus is UNKNOWN_LOCATION, and only the
statements that have been already parsed are in there.
That's odd, we should have failed to instantiate the template.
Investigating further, it seems that we can check for DECL_INITIAL ==
error_mark_node to tell that a function is still being defined. So this
patch does that, and also replaces my earlier fix for 70344.
This doesn't quite work for the 70344 testcase when optimizing, because
we call cp_fold_function between when we set DECL_INITIAL to a BLOCK and
when we lower invisiref parameters, which leads to confusion when we try
to evaluate a recursive call. So let's put back the check against
current_function_decl.
Tested x86_64-pc-linux-gnu, applying to trunk and 6.
commit a65d5bc7e718824989e02233e6edf990afb15358
Author: Jason Merrill <jason@redhat.com>
Date: Fri May 20 12:35:30 2016 -0400
PR c++/70344 - ICE with recursive constexpr
* constexpr.c (cxx_eval_call_expression): Check for
fun == current_function_decl again.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7b56260..bb723f4 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1371,11 +1371,17 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
else
{
new_call.fundef = retrieve_constexpr_fundef (fun);
- if (new_call.fundef == NULL || new_call.fundef->body == NULL)
+ if (new_call.fundef == NULL || new_call.fundef->body == NULL
+ || fun == current_function_decl)
{
if (!ctx->quiet)
{
- if (DECL_INITIAL (fun) == error_mark_node)
+ /* We need to check for current_function_decl here in case we're
+ being called during cp_fold_function, because at that point
+ DECL_INITIAL is set properly and we have a fundef but we
+ haven't lowered invisirefs yet (c++/70344). */
+ if (DECL_INITIAL (fun) == error_mark_node
+ || fun == current_function_decl)
error_at (loc, "%qD called in a constant expression before its "
"definition is complete", fun);
else if (DECL_INITIAL (fun))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion2.C
index 978b998..ce2280c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion2.C
@@ -1,5 +1,6 @@
// PR c++/70344
// { dg-do compile { target c++11 } }
+// { dg-options -O }
struct Z
{