https://github.com/Endilll created https://github.com/llvm/llvm-project/pull/237113
This PR adds tests for Core issues against [namespace.def], [namespace.memdef], [namespace.unnamed], [namespace.udir], [namespace.qual], and [namespace.alias] that didn't have tests (some of them were covered by my previous efforts towards P1787R6). I bundled them together, because in general all of them are covered by the same subset of the wording. As a preface, I think it's worth reminding that in addition to regular name lookup described in [basic.lookup], there is a "name lookup"-lite for cases when name is not looked up in the Standard sense, but declaration matching needs to happen, such as terminal names of declarations whose declarator-id is a qualified name. This lookup-lite searches for declarations [nominable](https://eel.is/c++draft/basic.scope.scope#def:nominable) in a given scope that [correspond](https://eel.is/c++draft/basic.scope.scope#def:correspond) to a given declaration ([[dcl.meaning]/3.4](https://eel.is/c++draft/dcl.meaning#general-3.4)). ### [CWG165](https://cplusplus.github.io/CWG/issues/165.html) "Definitions of friends and block-scope externs" This was a pre-existing test with a bunch of FIXMEs from 2013 that were no longer accurate, so I decided to update them. The difference between the two cases there is caused by the fact that the definition of nominable excludes declarations that are lexically placed inside a block scope. ### [CWG812](https://cplusplus.github.io/CWG/issues/812.html) "Duplicate names in inline namespaces" Despite the impression that [[namespace.def]/6](https://eel.is/c++draft/namespace.def#general-6) might leave, inline namespaces introduce a namespace scope like any other namespace ([[basic.scope.namespace]/1](https://eel.is/c++draft/basic.scope.namespace#1)), which means that the declarations they contain have different target (i.e. semantic) scope compared to declarations in the enclosing non-inline namespace, hence they declare different entities ([[basic.link]/8](https://eel.is/c++draft/basic.link#8)). Contrary to what you might expect if you already saw description for CWG986 below, [[namespace.qual]/1](https://eel.is/c++draft/basic.lookup#namespace.qual-1) gives inline namespaces special treatment during qualified name lookup: a search in a namespace N also contains results from searches in the inline namespace set. [[basic.lookup.general]/1](https://eel.is/c++draft/basic.lookup#general-1) still applies, requiring all the results to denote the same entity, making both cases ill-formed. ### [CWG861](https://cplusplus.github.io/CWG/issues/861.html) "Unintended ambiguity in inline namespace lookup" ### [CWG861](https://cplusplus.github.io/CWG/issues/861.html) "Unintended ambiguity in inline namespace lookup" >From 22a0fa3b24570012022d4e5c4dac0853be006ec0 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <[email protected]> Date: Fri, 30 Oct 2026 08:39:19 +0300 Subject: [PATCH] [clang] Add tests for CWG issues about namespaces --- clang/test/CXX/drs/cwg10xx.cpp | 30 ++++++++++++++++ clang/test/CXX/drs/cwg14xx.cpp | 36 +++++++++++++++++++ clang/test/CXX/drs/cwg16xx.cpp | 30 ++++++++++++++++ clang/test/CXX/drs/cwg17xx.cpp | 11 ++++++ clang/test/CXX/drs/cwg1xx.cpp | 3 +- clang/test/CXX/drs/cwg8xx.cpp | 40 +++++++++++++++++++++ clang/test/CXX/drs/cwg9xx.cpp | 64 ++++++++++++++++++++++++++++++++++ 7 files changed, 212 insertions(+), 2 deletions(-) diff --git a/clang/test/CXX/drs/cwg10xx.cpp b/clang/test/CXX/drs/cwg10xx.cpp index 28c5e2e40129af..cdca0ff35a82d4 100644 --- a/clang/test/CXX/drs/cwg10xx.cpp +++ b/clang/test/CXX/drs/cwg10xx.cpp @@ -47,6 +47,10 @@ namespace cwg1004 { // cwg1004: 5 Third<A<int> > t; // #cwg1004-t } // namespace cwg1004 +namespace cwg1012 { // cwg1012: 2.7 +static void f() {} +} // namespace cwg1012 + namespace cwg1042 { // cwg1042: 3.5 #if __cplusplus >= 201402L // C++14 added an attribute that we can test the semantics of. @@ -112,6 +116,32 @@ namespace cwg1070 { // cwg1070: 3.5 #endif } // namespace cwg1070 +namespace cwg1077 { // cwg1077: 2.7 +namespace N { + template <typename> + void f(); // #cwg1077-f + + template <typename, typename> + struct S; // #cwg1077-S +} +namespace M { + template <> + void N::f<int>(); + // expected-error@-1 {{function template specialization of 'f' not in a namespace enclosing 'N'}} + // expected-note@#cwg1077-f {{explicitly specialized declaration is here}} + + template <> + struct N::S<int, int>; + // expected-error@-1 {{class template specialization of 'S' not in a namespace enclosing 'N'}} + // expected-note@#cwg1077-S {{explicitly specialized declaration is here}} + + template <typename T> + struct N::S<int, T>; + // expected-error@-1 {{class template partial specialization of 'S' not in a namespace enclosing 'N'}} + // expected-note@#cwg1077-S {{explicitly specialized declaration is here}} +} +} // namespace cwg1077 + namespace cwg1094 { // cwg1094: 24 #if __cplusplus >= 201103L enum class E : bool { Zero, One }; diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp index f3b2bab8e7f3ac..c082cc62c827aa 100644 --- a/clang/test/CXX/drs/cwg14xx.cpp +++ b/clang/test/CXX/drs/cwg14xx.cpp @@ -110,6 +110,42 @@ namespace cwg1432 { // cwg1432: 16 open 2022-11-11 #endif } // namespace cwg1432 +namespace cwg1439 { // cwg1439: 2.7 +class A { + template <typename> + friend void f(); + + template <typename> + friend struct B; +}; + +void (*p1)() = &f<int>; +// expected-error@-1 {{use of undeclared identifier 'f'}} + +// FIXME: only the first error is relevant, others are noise +void (*p2)() = &cwg1439::f<int>; +// expected-error@-1 {{no member named 'f' in namespace 'cwg1439'}} +// expected-error@-2 {{expected '(' for function-style cast or type construction}} +// expected-error@-3 {{expected expression}} + +B<int>* p3; +// expected-error@-1 {{no template named 'B'}} + +cwg1439::B<int>* p4; +// expected-error@-1 {{no template named 'B' in namespace 'cwg1439'}} + +template <typename> +void f(); + +template <typename> +struct B; + +void (*p5)() = &f<int>; +void (*p6)() = &cwg1439::f<int>; +B<int>* p7; +cwg1439::B<int>* p8; +} // namespace cwg1439 + namespace cwg1443 { // cwg1443: 2.7 struct A { int i; diff --git a/clang/test/CXX/drs/cwg16xx.cpp b/clang/test/CXX/drs/cwg16xx.cpp index 91cc8261eb6bef..eedb50ca954f9a 100644 --- a/clang/test/CXX/drs/cwg16xx.cpp +++ b/clang/test/CXX/drs/cwg16xx.cpp @@ -175,6 +175,36 @@ namespace cwg1653 { // cwg1653: 4 c++17 } } // namespace cwg1653 +namespace cwg1657 { // cwg1657: 3.6 +#if __cplusplus >= 201103L +enum { + one [[]] + // cxx11-14-error@-1 {{attributes on an enumerator declaration are a C++17 extension}} +}; +enum E { + two [[]] + // cxx11-14-error@-1 {{attributes on an enumerator declaration are a C++17 extension}} +}; +enum struct E2 { + three [[]] + // cxx11-14-error@-1 {{attributes on an enumerator declaration are a C++17 extension}} +}; + +inline namespace [[]] {} // #cwg1657-unnamed +// cxx11-14-error@-1 {{attributes on a namespace declaration are a C++17 extension}} +namespace [[]] {} +// cxx11-14-error@-1 {{attributes on a namespace declaration are a C++17 extension}} +// since-cxx11-warning@-2 {{inline namespace reopened as a non-inline namespace}} +// since-cxx11-note@#cwg1657-unnamed {{previous definition is here}} + +inline namespace [[]] N {} +// cxx11-14-error@-1 {{attributes on a namespace declaration are a C++17 extension}} + +namespace [[]] M {} +// cxx11-14-error@-1 {{attributes on a namespace declaration are a C++17 extension}} +#endif +} // namespace cwg1657 + namespace cwg1658 { // cwg1658: 5 namespace DefCtor { class A { A(); }; // #cwg1658-A1 diff --git a/clang/test/CXX/drs/cwg17xx.cpp b/clang/test/CXX/drs/cwg17xx.cpp index 62ea94c4c21733..96280e0ee08a81 100644 --- a/clang/test/CXX/drs/cwg17xx.cpp +++ b/clang/test/CXX/drs/cwg17xx.cpp @@ -264,3 +264,14 @@ template auto GLL::operator()<int>(int a) const -> int; #endif } // namespace cwg1780 + +namespace cwg1795 { // cwg1975: 2.7 +namespace N { + struct S{}; // #cwg1795-S +} +namespace N { + struct S{}; + // expected-error@-1 {{redefinition of 'S'}} + // expected-note@#cwg1795-S {{previous definition is here}} +} +} // namespace cwg1795 diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp index e85adff7bb7fba..3bd8cd4c2f5265 100644 --- a/clang/test/CXX/drs/cwg1xx.cpp +++ b/clang/test/CXX/drs/cwg1xx.cpp @@ -1005,10 +1005,9 @@ namespace cwg165 { // cwg165: no struct A { friend struct B; }; void f() { void g(); } } - // FIXME: cwg1477 says this is ok, cwg165 says it's ill-formed struct N::B {}; - // FIXME: cwg165 says this is ill-formed, but the argument in cwg1477 says it's ok void N::g() {} + // FIXME-error@-1 {{'g' is not nominable in 'N'}} } // namespace cwg165 namespace cwg166 { // cwg166: 2.9 diff --git a/clang/test/CXX/drs/cwg8xx.cpp b/clang/test/CXX/drs/cwg8xx.cpp index b512411bdf27b7..688cd0ee27264c 100644 --- a/clang/test/CXX/drs/cwg8xx.cpp +++ b/clang/test/CXX/drs/cwg8xx.cpp @@ -6,6 +6,30 @@ // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx11 // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx20,since-cxx11 +namespace cwg812 { // cwg812: 2.8 +#if __cplusplus >= 201103L +namespace Q { + inline namespace V1 { + int i = 1; // #cwg812-v1-i + int j = 1; // #cwg812-v1-j + } + inline namespace V2 { + int j = 2; // #cwg812-v2-j + } + int i = 0; // #cwg812-Q-i +} + +static_assert(Q::i, ""); +// since-cxx11-error@-1 {{reference to 'i' is ambiguous}} +// since-cxx11-note@#cwg812-v1-i {{candidate found by name lookup is 'cwg812::Q::V1::i'}} +// since-cxx11-note@#cwg812-Q-i {{candidate found by name lookup is 'cwg812::Q::i'}} +static_assert(Q::j, ""); +// since-cxx11-error@-1 {{reference to 'j' is ambiguous}} +// since-cxx11-note@#cwg812-v1-j {{candidate found by name lookup is 'cwg812::Q::V1::j'}} +// since-cxx11-note@#cwg812-v2-j {{candidate found by name lookup is 'cwg812::Q::V2::j'}} +#endif +} // namespace cwg812 + namespace cwg820 { // cwg820: 2.7 export template <class T> struct B {}; // cxx98-17-warning@-1 {{exported templates are unsupported}} @@ -15,6 +39,22 @@ export template<typename T> void f() {} // since-cxx20-error@-2 {{export declaration can only be used within a module interface}} } // namespace cwg820 +namespace cwg861 { // cwg861: 2.7 +#if __cplusplus >= 201103L +namespace A { + inline namespace B { + namespace C { + constexpr int i = 0; + } + using namespace C; + } + constexpr int i = 1; +} + +static_assert(A::i == 1, ""); +#endif +} // namespace cwg861 + namespace cwg873 { // cwg873: 3.0 #if __cplusplus >= 201103L template <typename T> void f(T &&); diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp index f218ecddb9686d..2826a69cebcd74 100644 --- a/clang/test/CXX/drs/cwg9xx.cpp +++ b/clang/test/CXX/drs/cwg9xx.cpp @@ -15,6 +15,52 @@ namespace std { }; } // namespace std +namespace cwg919 { // cwg919: 2.7 +#if __cplusplus >= 201103L +namespace N { + inline namespace M { + template <typename, typename> + struct S; + + template <typename> + void f(); + } +} + +template <> +struct N::S<int, int> {}; + +template <typename T> +struct N::S<float, T> {}; + +template <> +void N::f<int>() {} +#endif +} // namespace cwg919 + +namespace cwg921 { // cwg921: 3.1 +#if __cplusplus >= 201103L +namespace N { + struct S {}; + inline namespace M { + int f(S); + } +} +int i = f(N::S{}); +#endif +} // namespace cwg921 + +namespace cwg926 { // cwg926: 2.8 +#if __cplusplus >= 201103L +namespace N { + inline namespace { + struct S {}; + } +} +N::S s; +#endif +} // namespace cwg926 + namespace cwg930 { // cwg930: 2.7 #if __cplusplus >= 201103L static_assert(alignof(int[]) == alignof(int), ""); @@ -207,6 +253,24 @@ enum struct E4 : int { e = static_cast<int>(E4()) }; #endif } // namespace cwg977 +namespace cwg986 { // cwg986: 2.7 +namespace A { + int f(); // #cwg986-A-f +} +namespace B { + using namespace A; + int f(); // #cwg986-B-f +} +namespace C { + using namespace B; + int i = C::f(); + int j = f(); + // expected-error@-1 {{call to 'f' is ambiguous}} + // expected-note@#cwg986-A-f {{candidate function}} + // expected-note@#cwg986-B-f {{candidate function}} +} +} // namespace cwg986 + namespace cwg988 { // cwg988: 2.7 #if __cplusplus >= 201103L void f(int& lvalue_ref, int&& rvalue_ref) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
