Skip to content

Commit 198ffb8

Browse files
authored
[Clang][Sema] Implement approved resolution for CWG2858 (#88042)
The approved resolution for CWG2858 changes [expr.prim.id.qual] p2 sentence 2 to read: > A declarative _nested-name-specifier_ shall not have a _computed-type-specifier_. This patch implements the approved resolution. Since we don't consider _nested-name-specifiers_ in friend declarations to be declarative (yet), it currently isn't possible to write a test that would produce this diagnostic (`diagnoseQualifiedDeclaration` is never called if the `DeclContext` can't be computed). Nevertheless, tests were added which will produce the diagnostic once we start calling `diagnoseQualifiedDeclaration` for friend declarations.
1 parent 4471831 commit 198ffb8

File tree

6 files changed

+40
-16
lines changed

6 files changed

+40
-16
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ Resolutions to C++ Defect Reports
147147
compatibility of two types.
148148
(`CWG2759: [[no_unique_address] and common initial sequence <https://cplusplus.github.io/CWG/issues/2759.html>`_).
149149

150+
- Clang now diagnoses declarative nested-name-specifiers with pack-index-specifiers.
151+
(`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers <https://cplusplus.github.io/CWG/issues/2858.html>`_).
152+
150153
C Language Changes
151154
------------------
152155

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,10 +2402,6 @@ def err_selected_explicit_constructor : Error<
24022402
def note_explicit_ctor_deduction_guide_here : Note<
24032403
"explicit %select{constructor|deduction guide}0 declared here">;
24042404

2405-
// C++11 decltype
2406-
def err_decltype_in_declarator : Error<
2407-
"'decltype' cannot be used to name a declaration">;
2408-
24092405
// C++11 auto
24102406
def warn_cxx98_compat_auto_type_specifier : Warning<
24112407
"'auto' type specifier is incompatible with C++98">,
@@ -8313,6 +8309,9 @@ def ext_template_after_declarative_nns : ExtWarn<
83138309
def ext_alias_template_in_declarative_nns : ExtWarn<
83148310
"a declarative nested name specifier cannot name an alias template">,
83158311
InGroup<DiagGroup<"alias-template-in-declaration-name">>;
8312+
def err_computed_type_in_declarative_nns : Error<
8313+
"a %select{pack indexing|'decltype'}0 specifier cannot be used in "
8314+
"a declarative nested name specifier">;
83168315

83178316
def err_no_typeid_with_fno_rtti : Error<
83188317
"use of typeid requires -frtti">;

clang/lib/Sema/SemaDecl.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6335,16 +6335,15 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
63356335
if (TST->isDependentType() && TST->isTypeAlias())
63366336
Diag(Loc, diag::ext_alias_template_in_declarative_nns)
63376337
<< SpecLoc.getLocalSourceRange();
6338-
} else if (T->isDecltypeType()) {
6338+
} else if (T->isDecltypeType() || T->getAsAdjusted<PackIndexingType>()) {
63396339
// C++23 [expr.prim.id.qual]p2:
63406340
// [...] A declarative nested-name-specifier shall not have a
6341-
// decltype-specifier.
6341+
// computed-type-specifier.
63426342
//
6343-
// FIXME: This wording appears to be defective as it does not forbid
6344-
// declarative nested-name-specifiers with pack-index-specifiers.
6345-
// See https://github.com/cplusplus/CWG/issues/499.
6346-
Diag(Loc, diag::err_decltype_in_declarator)
6347-
<< SpecLoc.getTypeLoc().getSourceRange();
6343+
// CWG2858 changed this from 'decltype-specifier' to
6344+
// 'computed-type-specifier'.
6345+
Diag(Loc, diag::err_computed_type_in_declarative_nns)
6346+
<< T->isDecltypeType() << SpecLoc.getTypeLoc().getSourceRange();
63486347
}
63496348
}
63506349
} while ((SpecLoc = SpecLoc.getPrefix()));

clang/test/CXX/dcl.decl/dcl.meaning/p1-0x.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ class foo {
66
void func();
77
};
88

9-
int decltype(foo())::i; // expected-error{{'decltype' cannot be used to name a declaration}}
10-
void decltype(foo())::func() { // expected-error{{'decltype' cannot be used to name a declaration}}
9+
int decltype(foo())::i; // expected-error{{a 'decltype' specifier cannot be used in a declarative nested name specifier}}
10+
void decltype(foo())::func() { // expected-error{{a 'decltype' specifier cannot be used in a declarative nested name specifier}}
1111
}
1212

1313

clang/test/CXX/drs/dr28xx.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,26 @@ void B<int>::g() requires true;
5858
#endif
5959

6060
} // namespace dr2847
61+
62+
namespace dr2858 { // dr2858: 19
63+
64+
#if __cplusplus > 202302L
65+
66+
template<typename... Ts>
67+
struct A {
68+
// FIXME: The nested-name-specifier in the following friend declarations are declarative,
69+
// but we don't treat them as such (yet).
70+
friend void Ts...[0]::f();
71+
template<typename U>
72+
friend void Ts...[0]::g();
73+
74+
friend struct Ts...[0]::B;
75+
// FIXME: The index of the pack-index-specifier is printed as a memory address in the diagnostic.
76+
template<typename U>
77+
friend struct Ts...[0]::C;
78+
// expected-warning-re@-1 {{dependent nested name specifier 'Ts...[{{.*}}]::' for friend template declaration is not supported; ignoring this friend declaration}}
79+
};
80+
81+
#endif
82+
83+
} // namespace dr2858

clang/test/Parser/cxx-class.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ typedef union {
5959
} y;
6060
} bug3177;
6161

62-
// check that we don't consume the token after the access specifier
62+
// check that we don't consume the token after the access specifier
6363
// when it's not a colon
6464
class D {
6565
public // expected-error{{expected ':'}}
6666
int i;
6767
};
6868

69-
// consume the token after the access specifier if it's a semicolon
69+
// consume the token after the access specifier if it's a semicolon
7070
// that was meant to be a colon
7171
class E {
7272
public; // expected-error{{expected ':'}}
@@ -281,7 +281,7 @@ struct A {} ::PR41192::a; // ok, no missing ';' here expected-warning {{extra q
281281
#if __cplusplus >= 201103L
282282
struct C;
283283
struct D { static C c; };
284-
struct C {} decltype(D())::c; // expected-error {{'decltype' cannot be used to name a declaration}}
284+
struct C {} decltype(D())::c; // expected-error {{a 'decltype' specifier cannot be used in a declarative nested name specifier}}
285285
#endif
286286
}
287287

0 commit comments

Comments
 (0)