This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [C++ PATCH] Reject self-recursive constexpr calls even in templates (PR c++/70449)


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
 {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]