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
