]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Fix propagating noexcept for templates [PR124785]
authorNathaniel Shead <nathanieloshead@gmail.com>
Sun, 5 Apr 2026 14:34:33 +0000 (00:34 +1000)
committerNathaniel Shead <nathanieloshead@gmail.com>
Mon, 6 Apr 2026 21:50:31 +0000 (07:50 +1000)
We triggered a checking assertion because when propagating deduced
noexcept, we were updating the type of the existing TEMPLATE_DECL but
not the type of its DECL_TEMPLATE_RESULT, violating assumptions made
later on during modules streaming.

But actually there was nothing to propagate here anyway, these
declarations are identical, so this patch also fixes the condition for
checking whether we need to propagate anything.  And so now I don't
think there is ever a case we should have a noexcept-spec to propagate
for a TEMPLATE_DECL, so add an assertion to validate this.

PR c++/124785

gcc/cp/ChangeLog:

* module.cc (trees_in::is_matching_decl): Narrow condition for
when noexcept propagation occurs; assert that we don't propagate
noexcept-specs for TEMPLATE_DECLs.

gcc/testsuite/ChangeLog:

* g++.dg/modules/noexcept-5.h: New test.
* g++.dg/modules/noexcept-5_a.C: New test.
* g++.dg/modules/noexcept-5_b.C: New test.
* g++.dg/modules/noexcept-5_c.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/noexcept-5.h [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/noexcept-5_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/noexcept-5_b.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/noexcept-5_c.C [new file with mode: 0644]

index 5828748a3e697e50ba15da83b2411d921cba0ffb..1514711f8474288c25e89fa9d4e8eb210502c306 100644 (file)
@@ -12619,12 +12619,14 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
       tree d_spec = TYPE_RAISES_EXCEPTIONS (d_type);
       if (DECL_MAYBE_DELETED (e_inner) || DEFERRED_NOEXCEPT_SPEC_P (e_spec))
        {
-         if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
+         if (!(DECL_MAYBE_DELETED (d_inner)
+               || DEFERRED_NOEXCEPT_SPEC_P (d_spec))
              || (UNEVALUATED_NOEXCEPT_SPEC_P (e_spec)
                  && !UNEVALUATED_NOEXCEPT_SPEC_P (d_spec)))
            {
              dump (dumper::MERGE)
                && dump ("Propagating instantiated noexcept to %N", existing);
+             gcc_checking_assert (existing == e_inner);
              TREE_TYPE (existing) = d_type;
 
              /* Propagate to existing clones.  */
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-5.h b/gcc/testsuite/g++.dg/modules/noexcept-5.h
new file mode 100644 (file)
index 0000000..78d9132
--- /dev/null
@@ -0,0 +1,4 @@
+// PR c++/124785
+template <typename T> struct Iterator {
+  constexpr friend auto operator<=>(const Iterator&, const Iterator&) = default;
+};
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-5_a.C b/gcc/testsuite/g++.dg/modules/noexcept-5_a.C
new file mode 100644 (file)
index 0000000..7208571
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/124785
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M:A }
+
+export module M:A;
+#include "noexcept-5.h"
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-5_b.C b/gcc/testsuite/g++.dg/modules/noexcept-5_b.C
new file mode 100644 (file)
index 0000000..928980b
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/124785
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M:B }
+
+export module M:B;
+#include "noexcept-5.h"
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-5_c.C b/gcc/testsuite/g++.dg/modules/noexcept-5_c.C
new file mode 100644 (file)
index 0000000..d934914
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/124785
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodules -fdump-lang-module-alias" }
+// { dg-module-cmi M }
+
+export module M;
+export import :A;
+export import :B;
+
+// The noexcept-specifiers are equivalent, no need to merge.
+// { dg-final { scan-lang-dump-not {Propagating instantiated noexcept} module } }