Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,11 @@ def warn_empty_init_statement : Warning<
"has no effect">, InGroup<EmptyInitStatement>, DefaultIgnore;
def err_keyword_as_parameter : Error <
"invalid parameter name: '%0' is a keyword">;
def warn_pre_cxx26_ambiguous_pack_indexing_type : Warning<
"parameter packs without specifying a name would become a pack indexing "
"declaration in C++2c onwards">, InGroup<CXXPre26Compat>;
def note_add_a_name_to_pre_cxx26_parameter_packs : Note<
"add a name to disambiguate">;

// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
Expand Down
21 changes: 20 additions & 1 deletion clang/lib/Parse/ParseExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,30 @@ bool Parser::ParseOptionalCXXScopeSpecifier(

else if (!HasScopeSpecifier && Tok.is(tok::identifier) &&
GetLookAheadToken(1).is(tok::ellipsis) &&
GetLookAheadToken(2).is(tok::l_square)) {
GetLookAheadToken(2).is(tok::l_square) &&
!GetLookAheadToken(3).is(tok::r_square)) {
SourceLocation Start = Tok.getLocation();
DeclSpec DS(AttrFactory);
SourceLocation CCLoc;
TentativeParsingAction MaybePackIndexing(*this, /*Unannotated=*/true);
SourceLocation EndLoc = ParsePackIndexingType(DS);
// C++ [cpp23.dcl.dcl-2]:
// Previously, T...[n] would declare a pack of function parameters.
// T...[n] is now a pack-index-specifier. [...] Valid C++ 2023 code that
// declares a pack of parameters without specifying a declarator-id
// becomes ill-formed.
if (!Tok.is(tok::coloncolon) && !getLangOpts().CPlusPlus26 &&
getCurScope()->isFunctionDeclarationScope()) {
Diag(DS.getEllipsisLoc(),
diag::warn_pre_cxx26_ambiguous_pack_indexing_type);
Diag(DS.getEllipsisLoc(),
diag::note_add_a_name_to_pre_cxx26_parameter_packs);
MaybePackIndexing.Revert();
return false;
}

MaybePackIndexing.Commit();

if (DS.getTypeSpecType() == DeclSpec::TST_error)
return false;

Expand Down
8 changes: 5 additions & 3 deletions clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ template<typename T>
void b(T[] ...);

template<typename T>
void c(T ... []); // expected-error {{expected expression}} \
// expected-error {{'T' does not refer to the name of a parameter pack}} \
// expected-warning {{pack indexing is a C++2c extension}}
void c(T ... []); // expected-error {{type 'T[]' of function parameter pack does not contain any unexpanded parameter packs}}

// A function that takes pointers to each type T as arguments, after any decay.
template <typename ...T>
void g(T...[]);

template<typename T>
void d(T ... x[]); // expected-error{{type 'T[]' of function parameter pack does not contain any unexpanded parameter packs}}
Expand Down
8 changes: 2 additions & 6 deletions clang/test/Parser/cxx0x-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,8 @@ struct MemberComponentOrder : Base {
void NoMissingSemicolonHere(struct S
[3]);
template<int ...N> void NoMissingSemicolonHereEither(struct S... [N]);
// expected-error@-1 {{'S' does not refer to the name of a parameter pack}} \
// expected-error@-1 {{declaration of anonymous struct must be a definition}} \
// expected-error@-1 {{expected parameter declarator}} \
// expected-error@-1 {{pack indexing is a C++2c extension}} \


// expected-warning@-1 {{parameter packs without specifying a name would become a pack indexing declaration in C++2c onwards}} \
// expected-note@-1 {{add a name to disambiguate}}

// This must be at the end of the file; we used to look ahead past the EOF token here.
// expected-error@+1 {{expected unqualified-id}} expected-error@+1{{expected ';'}}
Expand Down
5 changes: 2 additions & 3 deletions clang/test/Parser/cxx2c-pack-indexing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ struct S {
// expected-note {{to match this '['}} \
// expected-warning{{declaration does not declare anything}}

T...[]; // expected-error{{expected expression}} \
// expected-warning{{declaration does not declare anything}}
T...[]; // expected-error{{expected member name or ';' after declaration specifiers}}

void f(auto... v) {
decltype(v...[1]) a = v...[1];
Expand Down Expand Up @@ -65,7 +64,7 @@ int main() {
}


namespace GH11460 {
namespace GH111460 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was a typo. The patch - 1ad5f31#diff-64f7b2e488768fb71e127d736dc81d9d817ec14b759a8ec23fab7416d70a31aeR68 - was actually fixing 111460

template <typename... T>
requires( ); // expected-error {{expected expression}}
struct SS {
Expand Down
24 changes: 24 additions & 0 deletions clang/test/SemaCXX/cxx2c-pack-indexing-ext-diags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,27 @@ void f(T... t) {
// cxx11-warning@+1 {{pack indexing is a C++2c extension}}
T...[0] c;
}

template <typename... T>
void g(T... [1]); // cxx11-warning {{parameter packs without specifying a name would become a pack indexing declaration in C++2c onwards}} \
// cxx11-note {{add a name to disambiguate}} \
// cxx26-warning {{pack indexing is incompatible with C++ standards before C++2c}} \
// cxx26-note {{candidate function template not viable}}

template <typename... T>
void h(T... param[1]);

template <class T>
struct S {
using type = T;
};

template <typename... T>
void h(typename T... [1]::type); // cxx11-warning {{pack indexing is a C++2c extension}} \
// cxx26-warning {{pack indexing is incompatible with C++ standards before C++2c}}

void call() {
g<int, double>(nullptr, nullptr); // cxx26-error {{no matching function for call to 'g'}}
h<int, double>(nullptr, nullptr);
h<S<int>, S<const char *>>("hello");
}
Loading