OSDN Git Service

2008-01-15 Douglas Gregor <doug.gregor@gmail.com>
authordgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Jan 2008 18:49:47 +0000 (18:49 +0000)
committerdgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Jan 2008 18:49:47 +0000 (18:49 +0000)
PR c++/34751
* pt.c (coerce_template_parameter_pack): When substituting into
the type of a non-type template parameter pack. use the
deduced/substituted arguments.
* parser.c (declarator_can_be_parameter_pack): A pointer-to-member
can be a parameter pack with the ellipsis following it.  When we
have an erroneous declaration, allow it to be a parameter pack.
(cp_parser_template_parameter): Complain about default
arguments on non-type template parameter packs, and parse them
using the new cp_parser_default_argument.
(cp_parser_parameter_declaration): Complain about parameter packs
with default arguments. Move parsing of default arguments into a
new function, cp_parser_default_argument.
(cp_parser_default_argument): New; extracted from
cp_parser_parameter_declaration.

2008-01-15  Douglas Gregor  <doug.gregor@gmail.com>

PR c++/34751
* g++.dg/cpp0x/vt-34751.C: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131548 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/vt-34751.C [new file with mode: 0644]

index 5325bcd..6fec22f 100644 (file)
@@ -1,5 +1,23 @@
 2008-01-15  Douglas Gregor  <doug.gregor@gmail.com>
 
+       PR c++/34751
+       * pt.c (coerce_template_parameter_pack): When substituting into
+       the type of a non-type template parameter pack. use the
+       deduced/substituted arguments.
+       * parser.c (declarator_can_be_parameter_pack): A pointer-to-member
+       can be a parameter pack with the ellipsis following it.  When we
+       have an erroneous declaration, allow it to be a parameter pack.
+       (cp_parser_template_parameter): Complain about default
+       arguments on non-type template parameter packs, and parse them
+       using the new cp_parser_default_argument.
+       (cp_parser_parameter_declaration): Complain about parameter packs
+       with default arguments. Move parsing of default arguments into a
+       new function, cp_parser_default_argument.
+       (cp_parser_default_argument): New; extracted from
+       cp_parser_parameter_declaration.
+
+2008-01-15  Douglas Gregor  <doug.gregor@gmail.com>
+
        PR c++/34051
        PR c++/34055
        PR c++/34102
index 1400424..6462f35 100644 (file)
@@ -1071,12 +1071,13 @@ declarator_can_be_parameter_pack (cp_declarator *declarator)
       switch ((int)declarator->kind)
        {
        case cdk_id:
-       case cdk_error:
        case cdk_array:
-       case cdk_ptrmem:
          found = true;
          break;
-         
+
+       case cdk_error:
+         return true;
+
        default:
          declarator = declarator->declarator;
          break;
@@ -1734,6 +1735,8 @@ static cp_parameter_declarator *cp_parser_parameter_declaration_list
   (cp_parser *, bool *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
   (cp_parser *, bool, bool *);
+static tree cp_parser_default_argument 
+  (cp_parser *, bool);
 static void cp_parser_function_body
   (cp_parser *);
 static tree cp_parser_initializer
@@ -9385,16 +9388,39 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 
   /* If the next token is an ellipsis, and we don't already have it
      marked as a parameter pack, then we have a parameter pack (that
-     has no declarator); */
+     has no declarator) */
   if (!*is_parameter_pack
       && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
       && declarator_can_be_parameter_pack (parameter_declarator->declarator))
     {
-      /* Consume the `...'. */
+      /* Consume the `...'.  */
       cp_lexer_consume_token (parser->lexer);
       maybe_warn_variadic_templates ();
       
       *is_parameter_pack = true;
+
+      /* Parameter packs cannot have default arguments.  However, a
+        user may try to do so, so we'll parse them and give an
+        appropriate diagnostic here.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+       {
+         /* Consume the `='.  */
+         cp_lexer_consume_token (parser->lexer);
+
+         /* Find the name of the parameter pack.  */     
+         cp_declarator *id_declarator = parameter_declarator->declarator;
+         while (id_declarator && id_declarator->kind != cdk_id)
+           id_declarator = id_declarator->declarator;
+         
+         if (id_declarator && id_declarator->kind == cdk_id)
+           error ("template parameter pack %qD cannot have a default argument",
+                  id_declarator->u.id.unqualified_name);
+         else
+           error ("template parameter pack cannot have a default argument");
+
+          /* Parse the default argument, but throw away the result.  */
+          cp_parser_default_argument (parser, /*template_parm_p=*/true);
+       }
     }
 
   parm = grokdeclarator (parameter_declarator->declarator,
@@ -13540,7 +13566,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
   /* If the next token is `=', then process a default argument.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
     {
-      bool saved_greater_than_is_operator_p;
       /* Consume the `='.  */
       cp_lexer_consume_token (parser->lexer);
 
@@ -13646,39 +13671,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
       /* Outside of a class definition, we can just parse the
         assignment-expression.  */
       else
-       {
-         bool saved_local_variables_forbidden_p;
-
-         /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
-            set correctly.  */
-         saved_greater_than_is_operator_p
-           = parser->greater_than_is_operator_p;
-         parser->greater_than_is_operator_p = greater_than_is_operator_p;
-         /* Local variable names (and the `this' keyword) may not
-            appear in a default argument.  */
-         saved_local_variables_forbidden_p
-           = parser->local_variables_forbidden_p;
-         parser->local_variables_forbidden_p = true;
-         /* The default argument expression may cause implicitly
-            defined member functions to be synthesized, which will
-            result in garbage collection.  We must treat this
-            situation as if we were within the body of function so as
-            to avoid collecting live data on the stack.  */
-         ++function_depth;
-         /* Parse the assignment-expression.  */
-         if (template_parm_p)
-           push_deferring_access_checks (dk_no_deferred);
-         default_argument
-           = cp_parser_assignment_expression (parser, /*cast_p=*/false);
-         if (template_parm_p)
-           pop_deferring_access_checks ();
-         /* Restore saved state.  */
-         --function_depth;
-         parser->greater_than_is_operator_p
-           = saved_greater_than_is_operator_p;
-         parser->local_variables_forbidden_p
-           = saved_local_variables_forbidden_p;
-       }
+        default_argument 
+          = cp_parser_default_argument (parser, template_parm_p);
+
       if (!parser->default_arg_ok_p)
        {
          if (!flag_pedantic_errors)
@@ -13689,6 +13684,26 @@ cp_parser_parameter_declaration (cp_parser *parser,
              default_argument = NULL_TREE;
            }
        }
+      else if ((declarator && declarator->parameter_pack_p)
+              || (decl_specifiers.type
+                  && PACK_EXPANSION_P (decl_specifiers.type)))
+       {
+         const char* kind = template_parm_p? "template " : "";
+         
+         /* Find the name of the parameter pack.  */     
+         cp_declarator *id_declarator = declarator;
+         while (id_declarator && id_declarator->kind != cdk_id)
+           id_declarator = id_declarator->declarator;
+         
+         if (id_declarator && id_declarator->kind == cdk_id)
+           error ("%sparameter pack %qD cannot have a default argument",
+                  kind, id_declarator->u.id.unqualified_name);
+         else
+           error ("%sparameter pack cannot have a default argument",
+                  kind);
+         
+         default_argument = NULL_TREE;
+       }
     }
   else
     default_argument = NULL_TREE;
@@ -13698,6 +13713,46 @@ cp_parser_parameter_declaration (cp_parser *parser,
                                    default_argument);
 }
 
+/* Parse a default argument and return it.
+
+   TEMPLATE_PARM_P is true if this is a default argument for a
+   non-type template parameter.  */
+static tree
+cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
+{
+  tree default_argument = NULL_TREE;
+  bool saved_greater_than_is_operator_p;
+  bool saved_local_variables_forbidden_p;
+
+  /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
+     set correctly.  */
+  saved_greater_than_is_operator_p = parser->greater_than_is_operator_p;
+  parser->greater_than_is_operator_p = !template_parm_p;
+  /* Local variable names (and the `this' keyword) may not
+     appear in a default argument.  */
+  saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
+  parser->local_variables_forbidden_p = true;
+  /* The default argument expression may cause implicitly
+     defined member functions to be synthesized, which will
+     result in garbage collection.  We must treat this
+     situation as if we were within the body of function so as
+     to avoid collecting live data on the stack.  */
+  ++function_depth;
+  /* Parse the assignment-expression.  */
+  if (template_parm_p)
+    push_deferring_access_checks (dk_no_deferred);
+  default_argument
+    = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+  if (template_parm_p)
+    pop_deferring_access_checks ();
+  /* Restore saved state.  */
+  --function_depth;
+  parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
+  parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
+
+  return default_argument;
+}
+
 /* Parse a function-body.
 
    function-body:
index 57dc8f8..87c4bf5 100644 (file)
@@ -5138,7 +5138,7 @@ coerce_template_parameter_pack (tree parms,
     {
       argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
       TREE_TYPE (argument_pack) 
-        = tsubst (TREE_TYPE (TREE_VALUE (parm)), args, complain, in_decl);
+        = tsubst (TREE_TYPE (TREE_VALUE (parm)), new_args, complain, in_decl);
       TREE_CONSTANT (argument_pack) = 1;
     }
 
index 10cc27d..c6184f9 100644 (file)
@@ -1,5 +1,10 @@
 2008-01-15  Douglas Gregor  <doug.gregor@gmail.com>
 
+       PR c++/34751
+       * g++.dg/cpp0x/vt-34751.C: New.
+
+2008-01-15  Douglas Gregor  <doug.gregor@gmail.com>
+
        PR c++/34051
        PR c++/34055
        PR c++/34102
diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34751.C b/gcc/testsuite/g++.dg/cpp0x/vt-34751.C
new file mode 100644 (file)
index 0000000..e3ca39e
--- /dev/null
@@ -0,0 +1,19 @@
+// { dg-options "-std=c++0x" }
+// PR c++/34751
+struct A {};
+
+template<typename... Args = int>  // { dg-error "cannot have a default" }
+void f(Args... args = 0); // { dg-error "cannot have a default argument" }
+
+template<typename... Args> 
+void g(Args... = 0); // { dg-error "cannot have a default argument" }
+
+
+template<int, typename T = A, int T::*...p = 0 > struct B {}; // { dg-error "cannot have a default argument|no default argument" }
+
+B<0> b;
+
+template<int, typename T = A, int T::*... = 0 > struct C {}; // { dg-error "cannot have a default argument|no default argument" }
+
+C<0> c;
+