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  <ja...@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

Reply via email to