Skip to content

friend function with default parameters causes "redefinition of default argument" error in templates #130917

Closed
@wingerZYM

Description

@wingerZYM

Summary:

Starting from commit 38b3d87bd384a469a6618ec6a971352cb4f813ba in LLVM, Clang 20 reports
error: redefinition of default argument when using friend functions
in template classes, even though the default argument is only defined once.

Steps to Reproduce:

Compile the following minimal example with Clang 20:

#include <iostream>
#include <memory>

namespace Work {

namespace detail {
    class Obj;
} // namespace detail

using Ptr = std::unique_ptr<detail::Obj>;

template <int>
Ptr Create(const void* key = nullptr);  // default argument only once.

namespace detail {

class Obj {
protected:
    Obj(const void* key) {
        std::cout << "Obj::Obj\n";
    }
};

template <int>
class ObjImpl : public Obj {
public:
    ObjImpl(const void* key)
        : Obj(key) {
        std::cout << "ObjImpl::ObjImpl\n";
    }
    template <int>
    friend Ptr Work::Create(const void*);
};

} // namespace detail

template <int i>
Ptr Create(const void* key) {  // error: redefinition of default argument
    return Ptr(new detail::ObjImpl<i>(key));
}

} // namespace Work

int main() {
    auto ptr = Work::Create<192>(nullptr);
    return 0;
}

Result:

clang++ reports:

./build/bin/clang++ -std=c++20 /mnt/e/test/error.cpp
/mnt/e/test/error.cpp:38:24: error: redefinition of default argument
   13 | Ptr Create(const void* key) {
      |                        ^
/mnt/e/test/error.cpp:39:20: note: in instantiation of template class 'Work::detail::ObjImpl<192>' requested here
   39 |     return Ptr(new detail::ObjImpl<i>(key));
      |                    ^
/mnt/e/test/error.cpp:45:22: note: in instantiation of function template specialization 'Work::Create<192>' requested here
   45 |     auto ptr = Work::Create<192>(nullptr);
      |                      ^
/mnt/e/test/error.cpp:32:40: note: previous definition is here
   32 |     friend Ptr Work::Create(const void*);
      |                                        ^
1 error generated.

Workaround:

If we remove the default parameter from Ptr Create(const void* key = nullptr);, then Clang++ compiles correctly.
If we remove the friend declaration, Clang++ also compiles correctly.

Regression:

git branch: release/20.x
First bad commit: 38b3d87
This issue does not occur in earlier versions of branch.

Metadata

Metadata

Assignees

Labels

clang:frontendLanguage frontend issues, e.g. anything involving "Sema"regression:20Regression in 20 release

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions