llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-modules Author: Richard Smith (zygoloid) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/215395.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+8) - (added) clang/test/Modules/default-argument-in-friend.cpp (+33) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/215395 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
