My recent patch to make sure that we've given an error for failed template argument conversion caught this latent bug: when we evaluate __builtin_constant_p within a constexpr function, we don't fold it until later, at constexpr evaluation time when we have values for the arguments. Which makes sense for the maybe_constant_value case. But here we require a constant value, but are silently calling it non-constant. So only do the deferral if we're being quiet about non-constant expressions.
Tested x86_64-pc-linux-gnu, applying to trunk and 7.
commit be9bfa78348d2f5aec7209e126cf77ec89d60fc3 Author: Jason Merrill <ja...@redhat.com> Date: Tue Apr 3 13:59:29 2018 -0400 PR c++/85113 - ICE with constexpr and __builtin_constant_p. * constexpr.c (cxx_eval_builtin_function_call): Only defer __builtin_constant_p if ctx->quiet. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index bebd9f5b5d0..201f27d8e66 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1171,7 +1171,10 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, /* Don't fold __builtin_constant_p within a constexpr function. */ bool bi_const_p = (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P); + /* If we aren't requiring a constant expression, defer __builtin_constant_p + in a constexpr function until we have values for the parameters. */ if (bi_const_p + && ctx->quiet && current_function_decl && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) { diff --git a/gcc/testsuite/g++.dg/ext/builtin12.C b/gcc/testsuite/g++.dg/ext/builtin12.C new file mode 100644 index 00000000000..1d6bb75cd77 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/builtin12.C @@ -0,0 +1,10 @@ +// PR c++/85113 +// { dg-do compile { target c++14 } } + +template<bool> struct A {}; + +constexpr int foo() +{ + A<__builtin_constant_p(0)> a{}; + return 0; +}