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