https://gcc.gnu.org/g:1784de4b60651b257c818001ace1755eafd28b6f

commit r13-9570-g1784de4b60651b257c818001ace1755eafd28b6f
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Nov 8 13:36:05 2024 +0100

    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  <ja...@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.
    
    (cherry picked from commit 5ff9e21c1ec81f8288e74679547e56051e051975)

Diff:
---
 gcc/cp/semantics.cc                     |  5 ++++-
 gcc/testsuite/g++.dg/cpp2a/pr117317-1.C | 19 +++++++++++++++++++
 gcc/testsuite/g++.dg/cpp2a/pr117317-2.C | 15 +++++++++++++++
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 886186403691..1400023258eb 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4766,7 +4766,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 000000000000..f3ef3849d033
--- /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 000000000000..44f2ec601bbf
--- /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 (), "");

Reply via email to