aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-11-08 13:36:05 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2024-11-08 13:36:05 +0100
commit5ff9e21c1ec81f8288e74679547e56051e051975 (patch)
tree2c4abc70506c6977066b1bacc55775be08cba646 /gcc
parentec86e87439b4a5cf73da6f318757f3561f9f278a (diff)
downloadgcc-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.cc5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/pr117317-1.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/pr117317-2.C15
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 (), "");