mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
c++: Parse splice-type-specifier in cp_parser_mem_initializer_id [PR124944]
The grammar has:
mem-initializer-id:
class-or-decltype
identifier
class-or-decltype:
nested-name-specifier[opt] type-name
nested-name-specifier template simple-template-id
computed-type-specifier
computed-type-specifier:
decltype-specifier
pack-index-specifier
splice-type-specifier
but we weren't parsing splice-type-specifier in there, just in
cp_parser_base_specifier. So, the following patch defers
similarly to cp_parser_base_specifier the typename diagnostics
because we don't know whether typename [: will be valid or not
- it could be splice-scope-specifier and in that case typename
is not valid, or splice-type-specifier, in which case it is valid
but not required. And calls cp_parser_splice_type_specifier too
when nested-name-specifier nor :: don't appear.
2026-04-21 Jakub Jelinek <jakub@redhat.com>
PR c++/124944
* parser.cc (cp_parser_mem_initializer_id): Parse
splice-type-specifier.
* g++.dg/reflect/splice13.C: New test.
* g++.dg/reflect/splice14.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
committed by
Jakub Jelinek
parent
c5b8140b27
commit
80958ebae3
@@ -19980,14 +19980,17 @@ cp_parser_mem_initializer_id (cp_parser* parser)
|
||||
bool template_p = false;
|
||||
tree id;
|
||||
|
||||
cp_token *token = cp_lexer_peek_token (parser->lexer);
|
||||
cp_token *typename_token = nullptr, *splice_token = nullptr;
|
||||
|
||||
/* `typename' is not allowed in this context ([temp.res]). */
|
||||
/* `typename' is not allowed in this context ([temp.res]), unless
|
||||
it is part of splice-type-specifier. Defer diagnostics for now
|
||||
because it needs to be diagnosed if followed by splice-scope-specifier
|
||||
but not when followed by splice-type-specifier. */
|
||||
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
|
||||
{
|
||||
error_at (token->location,
|
||||
"keyword %<typename%> not allowed in this context (a qualified "
|
||||
"member initializer is implicitly a type)");
|
||||
typename_token = cp_lexer_peek_token (parser->lexer);
|
||||
if (cp_parser_next_tokens_start_splice_type_spec_p (parser, true))
|
||||
splice_token = cp_lexer_peek_nth_token (parser->lexer, 2);
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
/* Look for the optional `::' operator. */
|
||||
@@ -20014,6 +20017,12 @@ cp_parser_mem_initializer_id (cp_parser* parser)
|
||||
/*type_p=*/true,
|
||||
/*is_declaration=*/true)
|
||||
!= NULL_TREE);
|
||||
if (typename_token && cp_lexer_peek_token (parser->lexer) != splice_token)
|
||||
/* Emit deferred diagnostics for invalid typename keyword if
|
||||
cp_parser_nested_name_specifier_opt parsed splice-scope-specifier. */
|
||||
error_at (typename_token->location,
|
||||
"keyword %<typename%> not allowed in this context (a qualified "
|
||||
"member initializer is implicitly a type)");
|
||||
if (nested_name_specifier_p)
|
||||
template_p = cp_parser_optional_template_keyword (parser);
|
||||
/* If there is a `::' operator or a nested-name-specifier, then we
|
||||
@@ -20026,6 +20035,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
|
||||
/*check_dependency_p=*/true,
|
||||
/*class_head_p=*/false,
|
||||
/*is_declaration=*/true);
|
||||
else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SPLICE))
|
||||
{
|
||||
/* Parse C++26 splice-type-specifier. */
|
||||
id = cp_parser_splice_type_specifier (parser);
|
||||
if (id == NULL_TREE)
|
||||
return error_mark_node;
|
||||
return id;
|
||||
}
|
||||
/* Otherwise, we could also be looking for an ordinary identifier. */
|
||||
cp_parser_parse_tentatively (parser);
|
||||
if (cp_lexer_next_token_is_decltype (parser->lexer))
|
||||
|
||||
23
gcc/testsuite/g++.dg/reflect/splice13.C
Normal file
23
gcc/testsuite/g++.dg/reflect/splice13.C
Normal file
@@ -0,0 +1,23 @@
|
||||
// PR c++/124944
|
||||
// { dg-do compile { target c++26 } }
|
||||
// { dg-additional-options "-freflection" }
|
||||
|
||||
struct A {};
|
||||
constexpr auto x = ^^A;
|
||||
|
||||
struct B : [: x :] {
|
||||
B () : typename [: x :] () {}
|
||||
};
|
||||
|
||||
struct C : [: x :] {
|
||||
C () : [: x :] () {}
|
||||
};
|
||||
|
||||
namespace D {
|
||||
struct E {};
|
||||
}
|
||||
constexpr auto y = ^^D;
|
||||
|
||||
struct F : [: y :]::E {
|
||||
F () : [: y :]::E () {}
|
||||
};
|
||||
12
gcc/testsuite/g++.dg/reflect/splice14.C
Normal file
12
gcc/testsuite/g++.dg/reflect/splice14.C
Normal file
@@ -0,0 +1,12 @@
|
||||
// PR c++/124944
|
||||
// { dg-do compile { target c++26 } }
|
||||
// { dg-additional-options "-freflection" }
|
||||
|
||||
namespace D {
|
||||
struct E {};
|
||||
}
|
||||
constexpr auto y = ^^D;
|
||||
|
||||
struct F : [: y :]::E {
|
||||
F () : typename [: y :]::E () {} // { dg-error "keyword 'typename' not allowed in this context \\\(a qualified member initializer is implicitly a type\\\)" }
|
||||
};
|
||||
Reference in New Issue
Block a user