This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ Patch] [PR c++/88146] do not crash synthesizing inherited ctor(...)
On Dec 28, 2018, Alexandre Oliva <aoliva@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