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]

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


Hi!

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.

The patch attempts to reject that.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-04-01  Jakub Jelinek  <jakub@redhat.com>

	PR c++/70449
	* constexpr.c (cxx_eval_call_expression): Before calling
	instantiate_decl check if not trying to instantiate current
	function template and handle that the same as if
	fun == current_function_decl.

	* g++.dg/cpp1y/pr70449.C: New test.

--- gcc/cp/constexpr.c.jj	2016-03-29 19:31:21.000000000 +0200
+++ gcc/cp/constexpr.c	2016-04-01 16:26:53.591088640 +0200
@@ -1293,6 +1293,27 @@ cxx_eval_call_expression (const constexp
   if (!DECL_INITIAL (fun)
       && DECL_TEMPLOID_INSTANTIATION (fun))
     {
+      tree d = fun;
+      if (DECL_CLONED_FUNCTION_P (d))
+	d = DECL_CLONED_FUNCTION (d);
+      d = template_for_substitution (d);
+      if (DECL_TEMPLATE_RESULT (d) == current_function_decl)
+	{
+	  /* A call to the current function template, i.e.
+	     template <typename T>
+	     constexpr int f (int i) {
+	       constexpr int j = f<T>(i-1);
+	       return j;
+	     }
+	     This would be OK without the constexpr on the declaration
+	     of j.  */
+	  if (!ctx->quiet)
+	    error_at (loc, "%qD called in a constant expression before its "
+			   "definition is complete", fun);
+	  *non_constant_p = true;
+	  return t;
+	}
+
       ++function_depth;
       instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
       --function_depth;
--- gcc/testsuite/g++.dg/cpp1y/pr70449.C.jj	2016-04-01 16:42:55.055190752 +0200
+++ gcc/testsuite/g++.dg/cpp1y/pr70449.C	2016-04-01 16:43:43.207545314 +0200
@@ -0,0 +1,26 @@
+// PR c++/70449
+// { dg-do compile { target c++14 } }
+// { dg-options "-Wall" }
+
+template <int N>
+constexpr int f1 ()
+{
+  enum E { a = f1<0> () }; // { dg-error "called in a constant expression before its definition is complete|is not an integer constant" }
+  return 0;
+}
+
+template <int N>
+constexpr int f2 ()
+{
+  enum E { a = f2<0> () };
+  return 0;
+}
+
+constexpr int f3 ()
+{
+  enum E { a = f3 () };	// { dg-error "called in a constant expression before its definition is complete|is not an integer constant" }
+  return 0; 
+}
+
+constexpr int c = f1<0> ();
+constexpr int d = f3 ();

	Jakub


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