c++: Fix ICE on constexpr virtual function [PR117317]
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
Hi!
Since C++20 virtual methods can be constexpr, and if they are
constexpr evaluated, we choose tentative_decl_linkage for those
defer their output and decide at_eof again.
On the following testcases we ICE though, because if
expand_or_defer_fn_1 decides to use tentative_decl_linkage, it
returns true and the caller in that case cals emit_associated_thunks,
where use_thunk which it calls asserts DECL_INTERFACE_KNOWN on the
thunk destination, which isn't the case for tentative_decl_linkage.
The following patch fixes the ICE by not emitting the thunks
for the DECL_DEFER_OUTPUT fns just yet but waiting until at_eof
time when we return to those.
Note, the second testcase ICEs already since r0-110035 with -std=c++0x
before it gets a chance to diagnose constexpr virtual method.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
and eventually for backports?
2024-10-30 Jakub Jelinek <jakub@redhat.com>
PR c++/117317
* semantics.cc (emit_associated_thunks): Do nothing for
!DECL_INTERFACE_KNOWN && DECL_DEFER_OUTPUT fns.
* g++.dg/cpp2a/pr117317-1.C: New test.
* g++.dg/cpp2a/pr117317-2.C: New test.
Jakub
Comments
On 10/30/24 3:17 AM, Jakub Jelinek wrote:
> Hi!
>
> Since C++20 virtual methods can be constexpr, and if they are
> constexpr evaluated, we choose tentative_decl_linkage for those
> defer their output and decide at_eof again.
> On the following testcases we ICE though, because if
> expand_or_defer_fn_1 decides to use tentative_decl_linkage, it
> returns true and the caller in that case cals emit_associated_thunks,
> where use_thunk which it calls asserts DECL_INTERFACE_KNOWN on the
> thunk destination, which isn't the case for tentative_decl_linkage.
>
> The following patch fixes the ICE by not emitting the thunks
> for the DECL_DEFER_OUTPUT fns just yet but waiting until at_eof
> time when we return to those.
> Note, the second testcase ICEs already since r0-110035 with -std=c++0x
> before it gets a chance to diagnose constexpr virtual method.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
> and eventually for backports?
OK.
> 2024-10-30 Jakub Jelinek <jakub@redhat.com>
>
> PR c++/117317
> * semantics.cc (emit_associated_thunks): Do nothing for
> !DECL_INTERFACE_KNOWN && DECL_DEFER_OUTPUT fns.
>
> * g++.dg/cpp2a/pr117317-1.C: New test.
> * g++.dg/cpp2a/pr117317-2.C: New test.
>
> --- gcc/cp/semantics.cc.jj 2024-10-25 10:00:29.433768358 +0200
> +++ gcc/cp/semantics.cc 2024-10-29 13:10:32.234068524 +0100
> @@ -5150,7 +5150,10 @@ emit_associated_thunks (tree fn)
> enabling you to output all the thunks with the function itself. */
> if (DECL_VIRTUAL_P (fn)
> /* Do not emit thunks for extern template instantiations. */
> - && ! DECL_REALLY_EXTERN (fn))
> + && ! DECL_REALLY_EXTERN (fn)
> + /* Do not emit thunks for tentative decls, those will be processed
> + again at_eof if really needed. */
> + && (DECL_INTERFACE_KNOWN (fn) || !DECL_DEFER_OUTPUT (fn)))
> {
> tree thunk;
>
> --- gcc/testsuite/g++.dg/cpp2a/pr117317-1.C.jj 2024-10-29 13:12:23.373519669 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/pr117317-1.C 2024-10-29 13:12:18.223591437 +0100
> @@ -0,0 +1,19 @@
> +// PR c++/117317
> +// { dg-do compile { target c++20 } }
> +
> +struct C {
> + constexpr bool operator== (const C &b) const { return foo (); }
> + constexpr virtual bool foo () const = 0;
> +};
> +class A : public C {};
> +class B : public C {};
> +template <int>
> +struct D : A, B
> +{
> + constexpr bool operator== (const D &) const = default;
> + constexpr bool foo () const override { return true; }
> +};
> +struct E : D<1> {};
> +constexpr E e;
> +constexpr E f;
> +static_assert (e == f, "");
> --- gcc/testsuite/g++.dg/cpp2a/pr117317-2.C.jj 2024-10-29 13:16:10.101359947 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/pr117317-2.C 2024-10-29 13:16:15.981278003 +0100
> @@ -0,0 +1,15 @@
> +// PR c++/117317
> +// { dg-do compile { target c++20 } }
> +
> +struct C {
> + constexpr virtual bool foo () const = 0;
> +};
> +struct A : public C {};
> +struct B : public C {};
> +template <int>
> +struct D : A, B
> +{
> + constexpr bool foo () const override { return true; }
> +};
> +constexpr D<0> d;
> +static_assert (d.foo (), "");
>
> Jakub
>
@@ -5150,7 +5150,10 @@ emit_associated_thunks (tree fn)
enabling you to output all the thunks with the function itself. */
if (DECL_VIRTUAL_P (fn)
/* Do not emit thunks for extern template instantiations. */
- && ! DECL_REALLY_EXTERN (fn))
+ && ! DECL_REALLY_EXTERN (fn)
+ /* Do not emit thunks for tentative decls, those will be processed
+ again at_eof if really needed. */
+ && (DECL_INTERFACE_KNOWN (fn) || !DECL_DEFER_OUTPUT (fn)))
{
tree thunk;
@@ -0,0 +1,19 @@
+// PR c++/117317
+// { dg-do compile { target c++20 } }
+
+struct C {
+ constexpr bool operator== (const C &b) const { return foo (); }
+ constexpr virtual bool foo () const = 0;
+};
+class A : public C {};
+class B : public C {};
+template <int>
+struct D : A, B
+{
+ constexpr bool operator== (const D &) const = default;
+ constexpr bool foo () const override { return true; }
+};
+struct E : D<1> {};
+constexpr E e;
+constexpr E f;
+static_assert (e == f, "");
@@ -0,0 +1,15 @@
+// PR c++/117317
+// { dg-do compile { target c++20 } }
+
+struct C {
+ constexpr virtual bool foo () const = 0;
+};
+struct A : public C {};
+struct B : public C {};
+template <int>
+struct D : A, B
+{
+ constexpr bool foo () const override { return true; }
+};
+constexpr D<0> d;
+static_assert (d.foo (), "");