re PR c++/57 ([DR 325] GCC can't parse a non-parenthesized comma in a template-id...
authorJason Merrill <jason@redhat.com>
Mon, 28 Apr 2008 20:43:27 +0000 (16:43 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 28 Apr 2008 20:43:27 +0000 (16:43 -0400)
        PR c++/57
        * parser.c (cp_parser_parameter_declaration): Handle < ambiguity
        in default arguments.

Co-Authored-By: Liu Guanwei <liu_gw@163.com>
From-SVN: r134762

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.old-deja/g++.pt/defarg8.C

index 74b1b15a22395148288b7e04c006425589675547..368348a3d95ae8c98cacf72c0603b05d05eb13df 100644 (file)
@@ -1,3 +1,10 @@
+2008-04-28  Jason Merrill  <jason@redhat.com>
+           Liu Guanwei <liu_gw@163.com>
+
+       PR c++/57
+       * parser.c (cp_parser_parameter_declaration): Handle < ambiguity
+       in default arguments.
+
 2008-04-25  Jan Hubicka  <jh@suse.cz>
 
        * typeck.c (check_return_expr): Update.
index f2acddbb255f9a4baab5d346634a1e40830fc114..21a762dc59ef7ae5d6d63cfaa03e1b99c2624bfb 100644 (file)
@@ -13723,6 +13723,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
          && TYPE_BEING_DEFINED (current_class_type))
        {
          unsigned depth = 0;
+         int maybe_template_id = 0;
          cp_token *first_token;
          cp_token *token;
 
@@ -13741,6 +13742,33 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  /* In valid code, a default argument must be
                     immediately followed by a `,' `)', or `...'.  */
                case CPP_COMMA:
+                 if (depth == 0 && maybe_template_id)
+                   {
+                     /* If we've seen a '<', we might be in a
+                        template-argument-list.  Until Core issue 325 is
+                        resolved, we don't know how this situation ought
+                        to be handled, so try to DTRT.  We check whether
+                        what comes after the comma is a valid parameter
+                        declaration list.  If it is, then the comma ends
+                        the default argument; otherwise the default
+                        argument continues.  */
+                     bool error = false;
+
+                     /* Set ITALP so cp_parser_parameter_declaration_list
+                        doesn't decide to commit to this parse.  */
+                     bool saved_italp = parser->in_template_argument_list_p;
+                     parser->in_template_argument_list_p = true;
+
+                     cp_parser_parse_tentatively (parser);
+                     cp_lexer_consume_token (parser->lexer);
+                     cp_parser_parameter_declaration_list (parser, &error);
+                     if (!cp_parser_error_occurred (parser) && !error)
+                       done = true;
+                     cp_parser_abort_tentative_parse (parser);
+
+                     parser->in_template_argument_list_p = saved_italp;
+                     break;
+                   }
                case CPP_CLOSE_PAREN:
                case CPP_ELLIPSIS:
                  /* If we run into a non-nested `;', `}', or `]',
@@ -13764,6 +13792,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  ++depth;
                  break;
 
+               case CPP_LESS:
+                 if (depth == 0)
+                   /* This might be the comparison operator, or it might
+                      start a template argument list.  */
+                   ++maybe_template_id;
+                 break;
+
                 case CPP_RSHIFT:
                   if (cxx_dialect == cxx98)
                     break;
@@ -13772,11 +13807,16 @@ cp_parser_parameter_declaration (cp_parser *parser,
                      cases.  */
 
                case CPP_GREATER:
-                 /* If we see a non-nested `>', and `>' is not an
-                    operator, then it marks the end of the default
-                    argument.  */
-                 if (!depth && !greater_than_is_operator_p)
-                   done = true;
+                 if (depth == 0)
+                   {
+                     /* This might be an operator, or it might close a
+                        template argument list.  But if a previous '<'
+                        started a template argument list, this will have
+                        closed it, so we can't be in one anymore.  */
+                     maybe_template_id -= 1 + (token->type == CPP_RSHIFT);
+                     if (maybe_template_id < 0)
+                       maybe_template_id = 0;
+                   }
                  break;
 
                  /* If we run out of tokens, issue an error message.  */
index 239672dec433e60f8dc71a215e66a88798a05144..a72e85c4394dc236bd9372ab75a4b7c527f56691 100644 (file)
@@ -3,15 +3,15 @@
 // Default arguments containing more than one non-nested explicit
 // template argument leads to parse error
 
-// This might be ill formed. See DR 325 (which would like to make it
-// so)
+// This might be ill formed. See DR 325 (one proposed resolution is to make
+// it so)
 
 template <class T> class foo1;
-template <class T, class U> class foo2; // { dg-error "" }
+template <class T, class U> class foo2;
 
 struct bar {
   template <class T, class U>
   bar(int i = foo1<T>::baz, // { dg-bogus "" }  - 
       int j = int(foo2<T, U>::baz), // ok
-      int k = foo2<T, U>::baz) {} // { dg-error "" }
+      int k = foo2<T, U>::baz) {} // ok?
 };