Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clang doesn't recognise friendship in default parameters in C++20+ #83608

Open
cjdb opened this issue Mar 1, 2024 · 7 comments
Open

Clang doesn't recognise friendship in default parameters in C++20+ #83608

cjdb opened this issue Mar 1, 2024 · 7 comments
Labels
c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party rejects-valid

Comments

@cjdb
Copy link
Contributor

cjdb commented Mar 1, 2024

This code doesn't compile on Compiler Explorer. Moving the defaulted parameter to the constructor body seems to be okay.

template<class T>
class single;

template<class T, class U>
class check_constructible {
    check_constructible() = default;

    static_assert(is_constructible_v<T, U>);

    template<class X>
    friend class single;
};

template<class T>
struct single {
    template<class U>
    single(U u, check_constructible<T, U> = {})
    : x(u)
    {}

    T x;
};

int main() {
    single<int> x(0);
}

Diagnostic:

<source>:25:45: error: calling a private constructor of class 'check_constructible<int, int>'
   25 |     single(U u, check_constructible<T, U> = {})
      |                                             ^
<source>:14:5: note: implicitly declared private here
   14 |     check_constructible() = default;
      |     ^

Compiler info:

clang version 19.0.0git (https://github.com/llvm/llvm-project.git 5b058709536dd883980722ee000bb7b8c7b2cd8b)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/compiler-explorer/clang-trunk-20240301/bin
Compiler returned: 0

Both GCC and MSVC accept this code. If it's not conforming, should we accept it as an extension?

@cjdb cjdb added c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 1, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 1, 2024

@llvm/issue-subscribers-clang-frontend

Author: Christopher Di Bella (cjdb)

This code doesn't compile on Compiler Explorer. Moving the defaulted parameter to the constructor body seems to be okay.
template&lt;class T&gt;
class single;

template&lt;class T, class U&gt;
class check_constructible {
    check_constructible() = default;

    static_assert(is_constructible_v&lt;T, U&gt;);

    template&lt;class X&gt;
    friend class single;
};

template&lt;class T&gt;
struct single {
    template&lt;class U&gt;
    single(U u, check_constructible&lt;T, U&gt; = {})
    : x(u)
    {}

    T x;
};

int main() {
    single&lt;int&gt; x(0);
}

Diagnostic:

&lt;source&gt;:25:45: error: calling a private constructor of class 'check_constructible&lt;int, int&gt;'
   25 |     single(U u, check_constructible&lt;T, U&gt; = {})
      |                                             ^
&lt;source&gt;:14:5: note: implicitly declared private here
   14 |     check_constructible() = default;
      |     ^

Compiler info:

clang version 19.0.0git (https://github.com/llvm/llvm-project.git 5b058709536dd883980722ee000bb7b8c7b2cd8b)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/compiler-explorer/clang-trunk-20240301/bin
Compiler returned: 0

Both GCC and MSVC accept this code. If it's not conforming, should we accept it as an extension?

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 1, 2024

@llvm/issue-subscribers-c-1

Author: Christopher Di Bella (cjdb)

This code doesn't compile on Compiler Explorer. Moving the defaulted parameter to the constructor body seems to be okay.
template&lt;class T&gt;
class single;

template&lt;class T, class U&gt;
class check_constructible {
    check_constructible() = default;

    static_assert(is_constructible_v&lt;T, U&gt;);

    template&lt;class X&gt;
    friend class single;
};

template&lt;class T&gt;
struct single {
    template&lt;class U&gt;
    single(U u, check_constructible&lt;T, U&gt; = {})
    : x(u)
    {}

    T x;
};

int main() {
    single&lt;int&gt; x(0);
}

Diagnostic:

&lt;source&gt;:25:45: error: calling a private constructor of class 'check_constructible&lt;int, int&gt;'
   25 |     single(U u, check_constructible&lt;T, U&gt; = {})
      |                                             ^
&lt;source&gt;:14:5: note: implicitly declared private here
   14 |     check_constructible() = default;
      |     ^

Compiler info:

clang version 19.0.0git (https://github.com/llvm/llvm-project.git 5b058709536dd883980722ee000bb7b8c7b2cd8b)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/compiler-explorer/clang-trunk-20240301/bin
Compiler returned: 0

Both GCC and MSVC accept this code. If it's not conforming, should we accept it as an extension?

@shafik
Copy link
Collaborator

shafik commented Mar 5, 2024

If I am reading class.access.general p8:

Access is checked for a default argument ([dcl.fct.default]) at the point of declaration, rather than at any points of use of the default argument. Access checking for default arguments in function templates and in member functions of class templates is performed as described in [temp.inst].

and temp.inst p12:

If a templated function f is called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument is done as if the default argument had been an initializer used in a function template specialization with the same scope, the same template parameters and the same access as that of the function template f used at that point ...

correctly then clang is not correct.

CC @zygoloid @Endilll

@Endilll
Copy link
Contributor

Endilll commented Mar 5, 2024

I agree with Shafik's analysis.

@Endilll Endilll added rejects-valid confirmed Verified by a second party labels Mar 5, 2024
@jcsxky
Copy link
Contributor

jcsxky commented Mar 9, 2024

@cjdb I have checked the code with clang-trunk and it runs ok. Could you have a double check?

@cor3ntin
Copy link
Contributor

@jcsxky it reproduces https://godbolt.org/z/dWf54MYq8

@jcsxky
Copy link
Contributor

jcsxky commented Aug 23, 2024

@jcsxky it reproduces https://godbolt.org/z/dWf54MYq8

Hmm, compliant with -std=c++17

@cor3ntin cor3ntin changed the title Clang doesn't recognise friendship in default parameters Clang doesn't recognise friendship in default parameters in C++20+ Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party rejects-valid
Projects
None yet
Development

No branches or pull requests

6 participants