diff mbox

[C++/52595] template in NSDMI initializer

Message ID 55664D9C.2040801@acm.org
State New
Headers show

Commit Message

Nathan Sidwell May 27, 2015, 11:05 p.m. UTC
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

Comments

Nathan Sidwell June 4, 2015, 4:56 p.m. UTC | #1
ping?  or do you want to leave this dormant until 325 is resolved (which doesn't 
seem to be any time soon ...)

https://gcc.gnu.org/ml/gcc-patches/2015-05/msg02892.html

On 05/27/15 16:05, Nathan Sidwell wrote:
> 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
Jason Merrill June 4, 2015, 5:29 p.m. UTC | #2
OK.

Jason
diff mbox

Patch

2015-05-27  Nathan Sidwell  <nathan@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