diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-11-08 13:36:05 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2024-11-08 13:36:05 +0100 |
commit | 5ff9e21c1ec81f8288e74679547e56051e051975 (patch) | |
tree | 2c4abc70506c6977066b1bacc55775be08cba646 /gcc | |
parent | ec86e87439b4a5cf73da6f318757f3561f9f278a (diff) | |
download | gcc-5ff9e21c1ec81f8288e74679547e56051e051975.zip gcc-5ff9e21c1ec81f8288e74679547e56051e051975.tar.gz gcc-5ff9e21c1ec81f8288e74679547e56051e051975.tar.bz2 |
c++: Fix ICE on constexpr virtual function [PR117317]
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.
2024-11-08 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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/semantics.cc | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/pr117317-1.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/pr117317-2.C | 15 |
3 files changed, 38 insertions, 1 deletions
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index ab8614e..cb2b154 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -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; diff --git a/gcc/testsuite/g++.dg/cpp2a/pr117317-1.C b/gcc/testsuite/g++.dg/cpp2a/pr117317-1.C new file mode 100644 index 0000000..f3ef384 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/pr117317-1.C @@ -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, ""); diff --git a/gcc/testsuite/g++.dg/cpp2a/pr117317-2.C b/gcc/testsuite/g++.dg/cpp2a/pr117317-2.C new file mode 100644 index 0000000..44f2ec6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/pr117317-2.C @@ -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 (), ""); |