https://github.com/Endilll created https://github.com/llvm/llvm-project/pull/94288
This patch covers the following Core issues: [CWG1862](https://cplusplus.github.io/CWG/issues/1862.html) "Determining “corresponding members” for friendship" [CWG1918](https://cplusplus.github.io/CWG/issues/1918.html) "`friend` templates with dependent scopes" [CWG1945](https://cplusplus.github.io/CWG/issues/1945.html) "Friend declarations naming members of class templates in non-templates" All of them were resolved by CWG1862, where the current wording of [[temp.friend] p5](https://eel.is/c++draft/temp.friend#5) comes from: > A template friend declaration may declare a member of a dependent type to be > a friend[.](https://eel.is/c++draft/temp.friend#5.sentence-1) The friend > declaration shall declare a function or specify a type with an > [elaborated-type-specifier](https://eel.is/c++draft/dcl.type.elab#nt:elaborated-type-specifier), > in either case with a > [nested-name-specifier](https://eel.is/c++draft/expr.prim.id.qual#nt:nested-name-specifier) > ending with a > [simple-template-id](https://eel.is/c++draft/temp.names#nt:simple-template-id), > C, whose > [template-name](https://eel.is/c++draft/temp.names#nt:template-name) names a > class template[.](https://eel.is/c++draft/temp.friend#5.sentence-2) The > template parameters of the template friend declaration shall be deducible > from C > ([[temp.deduct.type]](https://eel.is/c++draft/temp.deduct.type))[.](https://eel.is/c++draft/temp.friend#5.sentence-3) > In this case, a member of a specialization S of the class template is a > friend of the class granting friendship if deduction of the template > parameters of C from S succeeds, and substituting the deduced template > arguments into the friend declaration produces a declaration that corresponds > to the member of the > specialization[.](https://eel.is/c++draft/temp.friend#5.sentence-4) A useful example is provided after the paragraph: https://eel.is/c++draft/temp.friend#example-4. Neither of Core issues is implemented, because we don't support dependent nested friend specifiers. >From a813e0afb4e0e3c6178b4dab86c9f48ff9c77261 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Tue, 4 Jun 2024 01:17:48 +0300 Subject: [PATCH] [clang] Add tests for Core issues about friend templates --- clang/test/CXX/drs/cwg18xx.cpp | 92 ++++++++++++++++++++++++++++++++++ clang/test/CXX/drs/cwg19xx.cpp | 39 ++++++++++++++ clang/www/cxx_dr_status.html | 6 +-- 3 files changed, 134 insertions(+), 3 deletions(-) diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index b71a81b62f814..054ce5a4f4b70 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -373,6 +373,98 @@ namespace cwg1837 { // cwg1837: 3.3 #endif } +namespace cwg1862 { // cwg1862: no +template<class T> +struct A { + struct B { + void e(); + }; + + void f(); + + struct D { + void g(); + }; + + T h(); + + template<T U> + T i(); +}; + +template<> +struct A<int> { + struct B { + void e(); + }; + + int f(); + + struct D { + void g(); + }; + + template<int U> + int i(); +}; + +template<> +struct A<float*> { + int* h(); +}; + +class C { + int private_int; + + template<class T> + friend struct A<T>::B; + // expected-warning@-1 {{dependent nested name specifier 'A<T>::' for friend class declaration is not supported; turning off access control for 'C'}} + + template<class T> + friend void A<T>::f(); + // expected-warning@-1 {{dependent nested name specifier 'A<T>::' for friend class declaration is not supported; turning off access control for 'C'}} + + // FIXME: this is ill-formed, because A<T>::D does not end with a simple-template-id + template<class T> + friend void A<T>::D::g(); + // expected-warning@-1 {{dependent nested name specifier 'A<T>::D::' for friend class declaration is not supported; turning off access control for 'C'}} + + template<class T> + friend int *A<T*>::h(); + // expected-warning@-1 {{dependent nested name specifier 'A<T *>::' for friend class declaration is not supported; turning off access control for 'C'}} + + template<class T> + template<T U> + friend T A<T>::i(); + // expected-warning@-1 {{dependent nested name specifier 'A<T>::' for friend class declaration is not supported; turning off access control for 'C'}} +}; + +C c; + +template<class T> +void A<T>::B::e() { (void)c.private_int; } +void A<int>::B::e() { (void)c.private_int; } + +template<class T> +void A<T>::f() { (void)c.private_int; } +int A<int>::f() { (void)c.private_int; return 0; } + +// FIXME: both definition of 'D::g' are not friends, so they don't have access to 'private_int' +template<class T> +void A<T>::D::g() { (void)c.private_int; } +void A<int>::D::g() { (void)c.private_int; } + +template<class T> +T A<T>::h() { (void)c.private_int; } +int* A<float*>::h() { (void)c.private_int; return 0; } + +template<class T> +template<T U> +T A<T>::i() { (void)c.private_int; } +template<int U> +int A<int>::i() { (void)c.private_int; } +} // namespace cwg1862 + namespace cwg1872 { // cwg1872: 9 #if __cplusplus >= 201103L template<typename T> struct A : T { diff --git a/clang/test/CXX/drs/cwg19xx.cpp b/clang/test/CXX/drs/cwg19xx.cpp index 3e4f82813f51b..6085a40b67afb 100644 --- a/clang/test/CXX/drs/cwg19xx.cpp +++ b/clang/test/CXX/drs/cwg19xx.cpp @@ -80,6 +80,30 @@ namespace cwg1909 { // cwg1909: 3.7 }; } +namespace cwg1918 { // cwg1918: no +template<typename T> struct A { + class B { + class C {}; + }; +}; +class X { + static int x; + // FIXME: this is ill-formed, because A<T>::B::C does not end with a simple-template-id + template <typename T> + friend class A<T>::B::C; + // expected-warning@-1 {{dependent nested name specifier 'A<T>::B::' for friend class declaration is not supported; turning off access control for 'X'}} +}; +template<> struct A<int> { + typedef struct Q B; +}; +struct Q { + class C { + // FIXME: 'f' is not a friend, so 'X::x' is not accessible + int f() { return X::x; } + }; +}; +} // namespace cwg1918 + namespace cwg1940 { // cwg1940: 3.5 #if __cplusplus >= 201103L static union { @@ -121,6 +145,21 @@ derived d2(42, 9); #endif } +namespace cwg1945 { // cwg1945: no +template<typename T> struct A { + class B { + class C {}; + }; +}; +class X { + static int x; + // FIXME: this is ill-formed, because A<T>::B::C does not end with a simple-template-id + template <typename T> + friend class A<T>::B::C; + // expected-warning@-1 {{dependent nested name specifier 'A<T>::B::' for friend class declaration is not supported; turning off access control for 'X'}} +}; +} // namespace cwg1918 + namespace cwg1947 { // cwg1947: 3.5 #if __cplusplus >= 201402L unsigned o = 0'01; // ok diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 4d94ac5a1ac1d..e5f79419a9975 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -10980,7 +10980,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/1862.html">1862</a></td> <td>CD5</td> <td>Determining “corresponding members” for friendship</td> - <td class="unknown" align="center">Unknown</td> + <td class="none" align="center">No</td> </tr> <tr id="1863"> <td><a href="https://cplusplus.github.io/CWG/issues/1863.html">1863</a></td> @@ -11316,7 +11316,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/1918.html">1918</a></td> <td>CD5</td> <td><TT>friend</TT> templates with dependent scopes</td> - <td class="unknown" align="center">Unknown</td> + <td class="none" align="center">No</td> </tr> <tr class="open" id="1919"> <td><a href="https://cplusplus.github.io/CWG/issues/1919.html">1919</a></td> @@ -11478,7 +11478,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/1945.html">1945</a></td> <td>CD5</td> <td>Friend declarations naming members of class templates in non-templates</td> - <td class="unknown" align="center">Unknown</td> + <td class="none" align="center">No</td> </tr> <tr id="1946"> <td><a href="https://cplusplus.github.io/CWG/issues/1946.html">1946</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits