this patch fixes 52595, which I'd not noticed was actually suspended. anyway,
when parsing an NSDMI initializer of the form:
int var = A<T,N>::foo();
we have to figure whether the ',' is ending the initializer or not. We've
noticed the '<' as a potential template arg list opener. Currently we
tentatively parse a declarator after the ',', and if successful presume the ','
ends the initializer.
That's not good enough, because, as in this case, 'N' is a perfectly fine
declarator. This patch extends the tentative parsing to check the token after
the declarator.
If it is a ',' then we repeat, looking for another declarator.
If it is a ';' or '=' we treat the original ',' as ending the initializer. I
don't think there are other valid alternatives for post-declarator token.
Otherwise we presume the ',' is part of a template-id.
booted and tested on x86_64-linux, ok?
nathan
2015-05-27 Nathan Sidwell <nat...@acm.org>
cp/
PR c++.52595
* parser.c (cp_parser_cache_defarg): Continue looking for
declarators when scanning a potential template argument list of an
NSDMI.
testsuite/
PR c++/52595
* g++,dg/cpp0x/nsdmi-defer5.C: Add template case.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 223636)
+++ cp/parser.c (working copy)
@@ -25386,6 +25386,7 @@ cp_parser_cache_defarg (cp_parser *parse
the default argument; otherwise the default
argument continues. */
bool error = false;
+ cp_token *peek;
/* Set ITALP so cp_parser_parameter_declaration_list
doesn't decide to commit to this parse. */
@@ -25393,19 +25394,39 @@ cp_parser_cache_defarg (cp_parser *parse
parser->in_template_argument_list_p = true;
cp_parser_parse_tentatively (parser);
- cp_lexer_consume_token (parser->lexer);
if (nsdmi)
{
- int ctor_dtor_or_conv_p;
- cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
- &ctor_dtor_or_conv_p,
- /*parenthesized_p=*/NULL,
- /*member_p=*/true,
- /*friend_p=*/false);
+ /* Parse declarators until we reach a non-comma or
+ somthing that cannot be an initializer.
+ Just checking whether we're looking at a single
+ declarator is insufficient. Consider:
+ int var = tuple<T,U>::x;
+ The template parameter 'U' looks exactly like a
+ declarator. */
+ do
+ {
+ int ctor_dtor_or_conv_p;
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ &ctor_dtor_or_conv_p,
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/true,
+ /*friend_p=*/false);
+ peek = cp_lexer_peek_token (parser->lexer);
+ if (cp_parser_error_occurred (parser))
+ break;
+ }
+ while (peek->type == CPP_COMMA);
+ /* If we met an '=' or ';' then the original comma
+ was the end of the NSDMI. Otherwise assume
+ we're still in the NSDMI. */
+ error = (peek->type != CPP_EQ
+ && peek->type != CPP_SEMICOLON);
}
else
{
+ cp_lexer_consume_token (parser->lexer);
begin_scope (sk_function_parms, NULL_TREE);
cp_parser_parameter_declaration_list (parser, &error);
pop_bindings_and_leave_scope ();
Index: testsuite/g++.dg/cpp0x/nsdmi-defer5.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-defer5.C (revision 223636)
+++ testsuite/g++.dg/cpp0x/nsdmi-defer5.C (working copy)
@@ -5,6 +5,9 @@ template<typename T, typename U>
struct tuple
{
tuple(T, U) { }
+
+ static const int x = 3;
+ int var = tuple<T,U>::x;
};
struct Y