https://github.com/zygoloid created 
https://github.com/llvm/llvm-project/pull/215395

When determining whether a default argument is redefined, clang walks over the 
redeclaration chain of the function looking for a prior default argument that's 
visible. If it encounters a default argument that was inherited onto an 
instantiated friend declaration, the normal visibility check doesn't work 
because such friend declarations are visible anywhere they can be found. This 
led to false-positive "redefinition of default argument" errors.

Fix the check by simply skipping friend declarations when checking for 
redefinitions of default arguments. This is correct because a friend 
declaration that introduces a default argument is separately required to be the 
only declaration of that function, so it can never introduce a default argument 
that a later default argument conflicts with.

>From 0e14f81a6742eb31ac71f36e87215c85785cb436 Mon Sep 17 00:00:00 2001
From: Richard Smith <[email protected]>
Date: Mon, 10 Aug 2026 20:41:06 +0000
Subject: [PATCH] Fix visibility of default arguments in friends.

When determining whether a default argument is redefined, clang walks
over the redeclaration chain of the function looking for a prior default
argument that's visible. If it encounters a default argument that was
inherited onto an instantiated friend declaration, the normal visibility
check doesn't work because such friend declarations are visible anywhere
they can be found. This led to false-positive "redefinition of default
argument" errors.

Fix the check by simply skipping friend declarations when checking for
redefinitions of default arguments. This is correct because a friend
declaration that introduces a default argument is separately required
to be the only declaration of that function, so it can never introduce a
default argument that a later default argument conflicts with.
---
 clang/lib/Sema/SemaDeclCXX.cpp                |  8 +++++
 .../Modules/default-argument-in-friend.cpp    | 33 +++++++++++++++++++
 2 files changed, 41 insertions(+)
 create mode 100644 clang/test/Modules/default-argument-in-friend.cpp

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 47b01b913b428..6324a7f4b11bd 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -514,6 +514,14 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, 
FunctionDecl *Old,
       continue;
     }
 
+    if (PrevForDefaultArgs->getFriendObjectKind()) {
+      // Don't inherit default arguments from a friend declaration. It's 
invalid
+      // to redeclare such a function at all if it owns the default arguments;
+      // we check for that later. Otherwise, it's not the declaration that 
we're
+      // inheriting them from.
+      continue;
+    }
+
     // We found the right previous declaration.
     break;
   }
diff --git a/clang/test/Modules/default-argument-in-friend.cpp 
b/clang/test/Modules/default-argument-in-friend.cpp
new file mode 100644
index 0000000000000..b9f384d9b1bda
--- /dev/null
+++ b/clang/test/Modules/default-argument-in-friend.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fmodules -std=c++20 -verify -x c++-module-map 
-fmodule-name=A %s
+
+module A {
+  module Declare {}
+  module Friend {}
+  module Redeclare {}
+}
+
+#pragma clang module contents
+
+// First submodule: introduce a default argument.
+#pragma clang module begin A.Declare
+void f(int = 0);
+#pragma clang module end
+
+// Second submodule: extend redeclaration chain with an instantiated friend and
+// then a non-friend. Both inherit the default argument.
+#pragma clang module begin A.Friend
+#pragma clang module import A.Declare
+template<typename T> struct X {
+  friend void f(int);
+  using type = T;
+};
+using Y = X<int>::type;
+void f(int);
+#pragma clang module end
+
+// Third submodule: redefine the default argument. This should be valid; the
+// instantiated friend should not count as introducing a prior default 
argument.
+#pragma clang module begin A.Redeclare
+// expected-no-diagnostics
+void f(int = 0);
+#pragma clang module end

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to