-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang] Add tests for Core issues about friend templates #94288
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
Conversation
@llvm/pr-subscribers-clang Author: Vlad Serebrennikov (Endilll) ChangesThis patch covers the following Core issues: 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 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. Full diff: https://github.com/llvm/llvm-project/pull/94288.diff 3 Files Affected:
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>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after fixing minor comment
C c; | ||
|
||
template<class T> | ||
void A<T>::B::e() { (void)c.private_int; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess these work b/c as the diagnostic above said "we turn off access control"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, A<T>::B
is a friend. D::g
is the only function that doesn't have access in this example. Consult https://eel.is/c++draft/temp.friend#example-4 for details.
Co-authored-by: Shafik Yaghmour <shafik.yaghmour@intel.com>
This patch covers the following Core issues:
CWG1862 "Determining “corresponding members” for friendship"
CWG1918 "
friend
templates with dependent scopes"CWG1945 "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 comes from:
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.