https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/106117
>From 65307bd2f5f8ca5c6aaa24335c77a63280d668e3 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Mon, 26 Aug 2024 20:45:31 +0300 Subject: [PATCH 1/3] [clang] Add tests for CWG issues about friend declaration matching --- clang/test/CXX/drs/cwg14xx.cpp | 19 +++++++++ clang/test/CXX/drs/cwg1xx.cpp | 74 ++++++++++++++++++++++++++++++++++ clang/test/CXX/drs/cwg3xx.cpp | 69 +++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp index a23ac744436331..1240c416451b8f 100644 --- a/clang/test/CXX/drs/cwg14xx.cpp +++ b/clang/test/CXX/drs/cwg14xx.cpp @@ -603,6 +603,25 @@ namespace cwg1467 { // cwg1467: 3.7 c++11 #endif } // cwg1467 +namespace cwg1477 { // cwg1477: 2.7 +namespace N { +struct A { + // Name "f" is not bound in N, + // so single searches of 'f' in N won't find it, + // but the targets scope of this declaration is N, + // making it nominable in N. + friend int f(); +}; +} +// Corresponds to the friend declaration, +// because it's nominable in N, +// and binds name 'f' in N. +int N::f() { return 0; } +// Name 'f' is bound in N, +// so the search performed by qualified lookup finds it. +int i = N::f(); +} // namespace cwg1477 + namespace cwg1479 { // cwg1479: 3.1 #if __cplusplus >= 201103L int operator"" _a(const char*, std::size_t = 0); diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp index e7dddd1ea9278f..d6ee0844458b1d 100644 --- a/clang/test/CXX/drs/cwg1xx.cpp +++ b/clang/test/CXX/drs/cwg1xx.cpp @@ -568,6 +568,80 @@ namespace cwg137 { // cwg137: yes const volatile int *cvqcv = static_cast<const volatile int*>(cvp); } +namespace cwg138 { // cwg138: partial +namespace example1 { +void foo(); // #cwg138-ex1-foo +namespace A { + using example1::foo; // #cwg138-ex1-using + class X { + static const int i = 10; + // This friend declaration is using neither qualified-id nor template-id, + // so name 'foo' is not looked up, which means the using-declaration has no effect. + // Target scope of this declaration is A, so this is grating friendship to + // (hypothetical) A::foo instead of 'example1::foo' using declaration refers to. + // A::foo corresponds to example1::foo named by the using declaration, + // and since A::foo is a different entity, they potentially conflict. + // FIXME: This is ill-formed, but not for the reason diagnostic says. + friend void foo(); + // expected-error@-1 {{cannot befriend target of using declaration}} + // expected-note@#cwg138-ex1-foo {{target of using declaration}} + // expected-note@#cwg138-ex1-using {{using declaration}} + }; +} +} // namespace example1 + +namespace example2 { +void f(); +void g(); +class B { + void g(); +}; +class A : public B { + static const int i = 10; + void f(); + // Both friend declaration are not using qualified-ids or template-ids, + // so 'f' and 'g' are not looked up, which means that presence of A::f + // and base B have no effect. + // Both target scope of namespace 'example2', and grant friendship to + // example2::f and example2::g respectively. + friend void f(); + friend void g(); +}; +void f() { + int i2 = A::i; +} +void g() { + int i3 = A::i; +} +} // namespace example2 + +namespace example3 { +struct Base { +private: + static const int i = 10; // #cwg138-ex3-Base-i + +public: + struct Data; + // Elaborated type specifier is not the sole constituent of declaration, + // so 'Data' undergoes unqualified type-only lookup, which finds Base::Data. + friend class Data; + + struct Data { + void f() { + int i2 = Base::i; + } + }; +}; +struct Data { + void f() { + int i2 = Base::i; + // expected-error@-1 {{'i' is a private member of 'cwg138::example3::Base'}} + // expected-note@#cwg138-ex3-Base-i {{declared private here}} + } +}; +} // namespace example3 +} // namespace cwg138 + namespace cwg139 { // cwg139: yes namespace example1 { typedef int f; // #cwg139-typedef-f diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp index a10ed95941ba4a..44bf974ef66649 100644 --- a/clang/test/CXX/drs/cwg3xx.cpp +++ b/clang/test/CXX/drs/cwg3xx.cpp @@ -1369,6 +1369,75 @@ namespace cwg385 { // cwg385: 2.8 // expected-note@#cwg385-n {{member is declared here}} } +namespace cwg386 { // cwg386: no +namespace example1 { +namespace N1 { +// Binds name 'f' in N1. Target scope is N1. +template<typename T> void f( T* x ) { + // ... other stuff ... + delete x; +} +} + +namespace N2 { +// Bind name 'f' in N2. When a single search find this declaration, +// it's replaced with N1::f declaration. +using N1::f; + +// `f<int>` is not a qualified-id, so its target scope is N2. +// `f<int>` is a template-id, so 'f' undergoes (unqualified) lookup. +// Search performed by unqualified lookup finds N1::f via using-declaration, +// but this result is not considered, because it's not nominable in N2, +// which is because its target scope is N1. +// So unqualified lookup doesn't find anything, making this declaration ill-formed. +template<> void f<int>( int* ); +// expected-error@-1 {{no function template matches function template specialization 'f'}} + +class Test { + ~Test() { } + // `f<>` is a template-id and not a template declaration, + // so its terminal name 'f' undergoes (unqualified) lookup. + // Search in N2 performed by unqualified lookup finds + // (single) N1::f declaration via using-declaration. + // N1::f is replaced with N1::f<> specialization after deduction, + // and this is the result of the unqualified lookup. + // This friend declaration correspond to the result of the lookup. + // All lookup results target the same scope, which is N1, + // so target scope of this friend declaration is also N1. + // FIXME: This is well-formed. + friend void f<>( Test* x ); + // expected-error@-1 {{no function template matches function template specialization 'f'}} +}; +} +} // namespace example1 + +namespace example2 { +namespace N1 { +// Binds name 'f' in N1. Target scope is N1. +void f(); // #cwg386-ex2-N1-f +} + +namespace N2 { +// Bind name 'f' in N2. When a single search finds this declaration, +// it's replaced with N1::f declaration. +using N1::f; // #cwg386-ex2-using +class A { + // `N2::f` is a qualified-id, so its terminal name 'f' undergoes (qualified) lookup. + // Search in N2 performed by qualified lookup finds N1::f via using-declaration, + // which is the (only) result of qualified lookup. + // This friend declaration corresponds to the result of the lookup. + // All lookup results target the same scope, which is N1, + // so target scope of this friend declaration is also N1. + // FIXME: This is well-formed. + friend void N2::f(); + // expected-error@-1 {{cannot befriend target of using declaration}} + // expected-note@#cwg386-ex2-N1-f {{target of using declaration}} + // expected-note@#cwg386-ex2-using {{using declaration}} +}; +} +} // namespace example2 +} // namespace cwg386 + namespace cwg387 { // cwg387: 2.8 namespace old { template<typename T> class number { >From affb324d70a8261e412514a7eb5d5351f56386c7 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Tue, 27 Aug 2024 00:20:30 +0300 Subject: [PATCH 2/3] Add test for CWG1900 --- clang/test/CXX/drs/cwg19xx.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clang/test/CXX/drs/cwg19xx.cpp b/clang/test/CXX/drs/cwg19xx.cpp index 762787a4368e62..b8fb6e1745a550 100644 --- a/clang/test/CXX/drs/cwg19xx.cpp +++ b/clang/test/CXX/drs/cwg19xx.cpp @@ -8,6 +8,17 @@ namespace std { struct type_info; } +namespace cwg1900 { // cwg1900: 2.7 +namespace N { +struct A { + friend int f(); +}; +} +int N::f() { return 0; } +int N::g() { return 0; } +// expected-error@-1 {{out-of-line definition of 'g' does not match any declaration in namespace 'cwg1900::N'}} +} // namespace cwg1900 + namespace cwg1902 { // cwg1902: 3.7 struct A {}; struct B { >From d97e4947dacc127eb030be7c1905be323b0ba8b8 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Tue, 27 Aug 2024 00:25:31 +0300 Subject: [PATCH 3/3] Update cxx_dr_status.html --- clang/www/cxx_dr_status.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 395b5d3bff49a6..dca8e617275c19 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -873,7 +873,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/138.html">138</a></td> <td>CD6</td> <td>Friend declaration name lookup</td> - <td class="unknown" align="center">Unknown</td> + <td class="partial" align="center">Partial</td> </tr> <tr id="139"> <td><a href="https://cplusplus.github.io/CWG/issues/139.html">139</a></td> @@ -2363,7 +2363,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/386.html">386</a></td> <td>CD6</td> <td>Friend declaration of name brought in by <I>using-declaration</I></td> - <td class="unknown" align="center">Unknown</td> + <td class="none" align="center">No</td> </tr> <tr id="387"> <td><a href="https://cplusplus.github.io/CWG/issues/387.html">387</a></td> @@ -8677,7 +8677,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/1477.html">1477</a></td> <td>CD3</td> <td>Definition of a <TT>friend</TT> outside its namespace</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 2.7</td> </tr> <tr id="1478"> <td><a href="https://cplusplus.github.io/CWG/issues/1478.html">1478</a></td> @@ -11215,7 +11215,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/1900.html">1900</a></td> <td>CD6</td> <td>Do <TT>friend</TT> declarations count as “previous declarations”?</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 2.7</td> </tr> <tr class="open" id="1901"> <td><a href="https://cplusplus.github.io/CWG/issues/1901.html">1901</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits