On Dec 28, 2018, Alexandre Oliva <aol...@redhat.com> wrote: > I guess I still need to > fill in other gaps to in my knowledge to try and make sense of it.
Done. > diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c Here's a patch based on your suggestion. [PR88146] do not instantiate constexpr if not manifestly const This is another approach at fixing the g++.dg/cpp0x/inh-ctor32.C test failures on targets that have non-void return values for cdtors: only instantiate constexpr functions for expressions that are potentially constant evaluated. Alas, this exposed a latent problem elsewhere: braced initializer lists underwent check_narrowing when simplified to non-lists, but that did not signal maybe_constant_value the potentially constant evaluated constant that all direct members of braced initializer lists have, so after the change above we'd no longer initialize constexpr functions that per P0859 we ought to. cpp2a/constexpr-init1.C, taken directly from P0859, flagged the regression. While looking into it, I realized it was fragile: it could have passed even if we flagged the error we should flag for the construct that we are supposed to accept. So, I split it out, to catch too-aggressive constexpr instantiation as much as the too-lax instantiation the original testcase flagged after the first part of the change. Regstrapped on x86_64- and i686-linux-gnu. Ok to install? for gcc/cp/ChangeLog PR c++/88146 * constexpr.c (cxx_eval_outermost_constant_expr): Only instantiate constexpr fns for manifestly const eval. * typeck2.c (check_narrowing): Test for maybe constant value with manifestly const eval. for gcc/testsuite/ChangeLog PR c++/88146 * g++.dg/cpp2a/constexpr-inst1a.C: Split out of... * g++.dg/cpp2a/constexpr-inst1.C: ... this. --- gcc/cp/constexpr.c | 3 ++- gcc/cp/typeck2.c | 6 +++++- gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C | 3 --- gcc/testsuite/g++.dg/cpp2a/constexpr-inst1a.C | 9 +++++++++ 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-inst1a.C diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index cea414d33def..88bee7aa1fed 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5076,7 +5076,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, r = TARGET_EXPR_INITIAL (r); } - instantiate_constexpr_fns (r); + if (ctx.manifestly_const_eval) + instantiate_constexpr_fns (r); r = cxx_eval_constant_expression (&ctx, r, false, &non_constant_p, &overflow_p); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index cc9bf02439b6..ae194d519395 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -918,7 +918,11 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain, bool const_only) return ok; } - init = maybe_constant_value (init); + /* Immediate subexpressions in BRACED_ENCLOSED_INITIALIZERs are + potentially constant evaluated. Without manifestly_const_eval, + we won't instantiate constexpr functions that we must + instantiate. */ + init = maybe_constant_value (init, NULL_TREE, /*manifestly_const_eval=*/true); /* If we were asked to only check constants, return early. */ if (const_only && !TREE_CONSTANT (init)) diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C index 1016bec9d3e1..34863de3cf84 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1.C @@ -2,12 +2,9 @@ // { dg-do compile { target c++14 } } template<typename T> constexpr int f() { return T::value; } // { dg-error "int" } -template<bool B, typename T> void g(decltype(B ? f<T>() : 0)); -template<bool B, typename T> void g(...); template<bool B, typename T> void h(decltype(int{B ? f<T>() : 0})); template<bool B, typename T> void h(...); void x() { - g<false, int>(0); // OK, B ? f<T>() : 0 is not potentially constant evaluated h<false, int>(0); // error, instantiates f<int> even though B evaluates to false and // list-initialization of int from int cannot be narrowing } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1a.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1a.C new file mode 100644 index 000000000000..1c068595e374 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-inst1a.C @@ -0,0 +1,9 @@ +// Testcase from P0859 +// { dg-do compile { target c++14 } } + +template<typename T> constexpr int f() { return T::value; } +template<bool B, typename T> void g(decltype(B ? f<T>() : 0)); +template<bool B, typename T> void g(...); +void x() { + g<false, int>(0); // OK, B ? f<T>() : 0 is not potentially constant evaluated +} -- Alexandre Oliva, freedom fighter https://FSFLA.org/blogs/lxo Be the change, be Free! FSF Latin America board member GNU Toolchain Engineer Free Software Evangelist Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe