public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-2859] c++: most vexing parse and braced CTAD [PR89062]
@ 2021-08-11 19:59 Patrick Palka
0 siblings, 0 replies; only message in thread
From: Patrick Palka @ 2021-08-11 19:59 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:6186708312780bb2139da01946abdde39667e985
commit r12-2859-g6186708312780bb2139da01946abdde39667e985
Author: Patrick Palka <ppalka@redhat.com>
Date: Wed Aug 11 15:58:30 2021 -0400
c++: most vexing parse and braced CTAD [PR89062]
Here grokdeclarator is emitting the error
error: class template placeholder ‘Foo’ not permitted in this context
during the tentative (and ultimately futile) parse of 'x' as a function
declaration. This happens because when parsing 'Foo{1}',
cp_parser_parameter_declaration yields a parameter declaration with no
declarator and whose type is a CTAD placeholder, and stops short of
consuming the '{'. The caller cp_parser_parameter_declaration_list then
calls grokdeclarator on this declarator, hence the error, and soon
thereafter we abort this tentative parse since the next token '{'
doesn't make sense in the context of a parameter list.
Note that we don't have this issue with parenthesized CTAD
Foo<int> x(Foo(1));
because in this case cp_parser_direct_declarator (called indirectly from
c_p_p_d) consumes the '(' and returns cp_error_declarator instead of a
NULL declarator (and also simulates a parse error), and grokdeclarator
exits early for this declarator without emitting any error.
Since grokdeclarator doesn't take a 'complain' parameter, to fix this we
need to avoid calling grokdeclarator in this situation. To that end
this patch makes c_p_p_d simulate an error when a construct is a CTAD
expression and definitely not a parameter declaration, so that c_p_p_d_l
can avoid calling grokdeclarator by checking for this simulated error.
Alternatively we could keep all this logic inside c_p_p_d_l and not
touch c_p_p_d at all, but this approach seems slightly less adhoc.
PR c++/89062
gcc/cp/ChangeLog:
* parser.c (cp_parser_parameter_declaration_list): Don't call
grokdeclarator if cp_parser_error_occurred.
(cp_parser_parameter_declaration): Simulate an error if we see
the beginning of a CTAD form, i.e. if we see an opening brace
after the decl-specifier-seq and the type is a CTAD placeholder.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/class-deduction97.C: New test.
Diff:
---
gcc/cp/parser.c | 17 +++++++++++++----
gcc/testsuite/g++.dg/cpp1z/class-deduction97.C | 6 ++++++
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 1be42a1a776..87e8d37d473 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -24284,7 +24284,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags)
and warn in grokparms if appropriate. */
deprecated_state = DEPRECATED_SUPPRESS;
- if (parameter)
+ if (parameter && !cp_parser_error_occurred (parser))
{
decl = grokdeclarator (parameter->declarator,
¶meter->decl_specifiers,
@@ -24499,7 +24499,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
parser->default_arg_ok_p = false;
/* After seeing a decl-specifier-seq, if the next token is not a
- "(", there is no possibility that the code is a valid
+ "(" or "{", there is no possibility that the code is a valid
expression. Therefore, if parsing tentatively, we commit at
this point. */
if (!parser->in_template_argument_list_p
@@ -24512,9 +24512,18 @@ cp_parser_parameter_declaration (cp_parser *parser,
of some object of type "char" to "int". */
&& !parser->in_type_id_in_expr_p
&& cp_parser_uncommitted_to_tentative_parse_p (parser)
- && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
- cp_parser_commit_to_tentative_parse (parser);
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ if (decl_specifiers.type
+ && template_placeholder_p (decl_specifiers.type))
+ /* This is a CTAD expression, not a parameter declaration. */
+ cp_parser_simulate_error (parser);
+ }
+ else
+ cp_parser_commit_to_tentative_parse (parser);
+ }
/* Parse the declarator. */
declarator_token_start = token;
declarator = cp_parser_declarator (parser,
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction97.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction97.C
new file mode 100644
index 00000000000..32818681d8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction97.C
@@ -0,0 +1,6 @@
+// PR c++/89062
+// { dg-do compile { target c++17 } }
+
+template<class T> struct Foo { Foo(T); };
+
+Foo<int> x(Foo{1});
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-08-11 19:59 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-11 19:59 [gcc r12-2859] c++: most vexing parse and braced CTAD [PR89062] Patrick Palka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).