[clang] [clang] Add tests for CWG issues about friend declaration matching (PR #106117)
Vlad Serebrennikov via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 26 14:21:03 PDT 2024
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.vladislav at gmail.com>
Date: Mon, 26 Aug 2024 20:45:31 +0300
Subject: [PATCH 1/2] [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 at -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 at -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 at -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 at -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 at -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.vladislav at gmail.com>
Date: Tue, 27 Aug 2024 00:20:30 +0300
Subject: [PATCH 2/2] 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 at -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 {
More information about the cfe-commits
mailing list