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.
This commit is contained in:
parent
ec86e87439
commit
5ff9e21c1e
3 changed files with 38 additions and 1 deletions
|
@ -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;
|
||||
|
||||
|
|
19
gcc/testsuite/g++.dg/cpp2a/pr117317-1.C
Normal file
19
gcc/testsuite/g++.dg/cpp2a/pr117317-1.C
Normal file
|
@ -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, "");
|
15
gcc/testsuite/g++.dg/cpp2a/pr117317-2.C
Normal file
15
gcc/testsuite/g++.dg/cpp2a/pr117317-2.C
Normal file
|
@ -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 (), "");
|
Loading…
Add table
Reference in a new issue