https://gcc.gnu.org/g:ab169d27ea39bf828378d2bf08ebd27712842caf

commit r16-8487-gab169d27ea39bf828378d2bf08ebd27712842caf
Author: Nathaniel Shead <[email protected]>
Date:   Sat Apr 4 23:55:16 2026 +1100

    c++/modules: Handle importing an undeduced auto over a deduced auto 
[PR124735]
    
    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 <[email protected]>
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/module.cc                        |  6 +++++-
 gcc/testsuite/g++.dg/modules/auto-8_a.H |  7 +++++++
 gcc/testsuite/g++.dg/modules/auto-8_b.C | 15 +++++++++++++++
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index e7f810693d9a..1757bd58f772 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -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
index 000000000000..a0a5cacd9955
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-8_a.H
@@ -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
index 000000000000..bd749228a040
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-8_b.C
@@ -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;
+}

Reply via email to