]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Handle importing an undeduced auto over a deduced auto [PR124735]
authorNathaniel Shead <nathanieloshead@gmail.com>
Sat, 4 Apr 2026 12:55:16 +0000 (23:55 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Mon, 6 Apr 2026 21:50:32 +0000 (07:50 +1000)
Like with implicit constexpr, we need to handle cases where we import an
function declaration with undeduced auto, but we already have a
definition available with deduced auto.  In this case we can just keep
the existing declaration's type.

PR c++/124735

gcc/cp/ChangeLog:

* module.cc (trees_in::is_matching_decl): Handle importing
undeduced auto when existing is already deduced.

gcc/testsuite/ChangeLog:

* g++.dg/modules/auto-8_a.H: New test.
* g++.dg/modules/auto-8_b.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/auto-8_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/auto-8_b.C [new file with mode: 0644]

index e7f810693d9ad9c00fde25a581dafb5c717d12d5..1757bd58f772fb416a67173e98c80e41efc3f77b 100644 (file)
@@ -12652,7 +12652,9 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
 
       /* Similarly if EXISTING has an undeduced return type, but DECL's
         is already deduced.  */
-      if (undeduced_auto_decl (existing) && !undeduced_auto_decl (decl))
+      bool e_undeduced = undeduced_auto_decl (existing);
+      bool d_undeduced = undeduced_auto_decl (decl);
+      if (e_undeduced && !d_undeduced)
        {
          dump (dumper::MERGE)
            && dump ("Propagating deduced return type to %N", existing);
@@ -12661,6 +12663,8 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
          DECL_SAVED_AUTO_RETURN_TYPE (existing) = TREE_TYPE (e_type);
          TREE_TYPE (existing) = change_return_type (TREE_TYPE (d_type), e_type);
        }
+      else if (d_undeduced && !e_undeduced)
+       /* EXISTING was deduced, leave it alone.  */;
       else if (type_uses_auto (d_ret)
               && !same_type_p (TREE_TYPE (d_type), TREE_TYPE (e_type)))
        {
diff --git a/gcc/testsuite/g++.dg/modules/auto-8_a.H b/gcc/testsuite/g++.dg/modules/auto-8_a.H
new file mode 100644 (file)
index 0000000..a0a5cac
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/124735
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+struct S {
+  auto foo();
+};
diff --git a/gcc/testsuite/g++.dg/modules/auto-8_b.C b/gcc/testsuite/g++.dg/modules/auto-8_b.C
new file mode 100644 (file)
index 0000000..bd74922
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/124735
+// { dg-additional-options "-fmodules" }
+
+struct S {
+  auto foo();
+};
+
+auto S::foo() { return 123; }
+auto pfn = &S::foo;
+
+import "auto-8_a.H";
+
+int main() {
+  return S{}.foo() != 123;
+}