OSDN Git Service

2007-03-31 Douglas Gregor <doug.gregor@gmail.com>
authordgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 31 Mar 2007 12:41:30 +0000 (12:41 +0000)
committerdgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 31 Mar 2007 12:41:30 +0000 (12:41 +0000)
PR c++/31138
PR c++/31140
PR c++/31141
* parser.c (declarator_can_be_parameter_pack): New.
(cp_parser_template_parameter): Only parse the `...' if the
declarator can be a parameter pack.
(cp_parser_parameter_declaration): Ditto. Also, handle when TYPE
is NULL.
* pt.c (find_parameter_packs_r): Look into the bounds on integer
types (they could be used as array bounds).
(check_for_bare_parameter_packs): Deal with TEMPLATE_PARM_INDEX.
(tsubst_pack_expansion): Handle failure to expand parameter
packs.

2007-03-31  Douglas Gregor  <doug.gregor@gmail.com>

* g++.dg/parser/pr31138.C: New.
* g++.dg/parser/pr31140.C: New.
* g++.dg/parser/pr31141.C: New.

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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog

index 4374e6b..c13dcee 100644 (file)
@@ -1,3 +1,19 @@
+2007-03-31  Douglas Gregor  <doug.gregor@gmail.com>
+
+       PR c++/31138
+       PR c++/31140
+       PR c++/31141
+       * parser.c (declarator_can_be_parameter_pack): New.
+       (cp_parser_template_parameter): Only parse the `...' if the
+       declarator can be a parameter pack.
+       (cp_parser_parameter_declaration): Ditto. Also, handle when TYPE
+       is NULL.
+       * pt.c (find_parameter_packs_r): Look into the bounds on integer
+       types (they could be used as array bounds). 
+       (check_for_bare_parameter_packs): Deal with TEMPLATE_PARM_INDEX.
+       (tsubst_pack_expansion): Handle failure to expand parameter
+       packs.
+       
 2007-03-30  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/26099
index 4fc1a62..63f7fec 100644 (file)
@@ -1055,6 +1055,36 @@ make_array_declarator (cp_declarator *element, tree bounds)
   return declarator;
 }
 
+/* Determine whether the declarator we've seen so far can be a
+   parameter pack, when followed by an ellipsis.  */
+static bool 
+declarator_can_be_parameter_pack (cp_declarator *declarator)
+{
+  /* Search for a declarator name, or any other declarator that goes
+     after the point where the ellipsis could appear in a parameter
+     pack. If we find any of these, then this declarator can not be
+     made into a parameter pack.  */
+  bool found = false;
+  while (declarator && !found)
+    {
+      switch ((int)declarator->kind)
+       {
+       case cdk_id:
+       case cdk_error:
+       case cdk_array:
+       case cdk_ptrmem:
+         found = true;
+         break;
+         
+       default:
+         declarator = declarator->declarator;
+         break;
+       }
+    }
+
+  return !found;
+}
+
 cp_parameter_declarator *no_parameters;
 
 /* Create a parameter declarator with the indicated DECL_SPECIFIERS,
@@ -9049,9 +9079,9 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
      marked as a parameter pack, then we have a parameter pack (that
      has no declarator); */
   if (!*is_parameter_pack
-      && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+      && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
+      && declarator_can_be_parameter_pack (parameter_declarator->declarator))
     {
-
       /* Consume the `...'. */
       cp_lexer_consume_token (parser->lexer);
       maybe_warn_variadic_templates ();
@@ -13095,32 +13125,35 @@ cp_parser_parameter_declaration (cp_parser *parser,
                   cp_parser_attributes_opt (parser));
     }
 
-  /* If the next token is an ellipsis, and the type of the declarator
-     contains parameter packs but it is not a TYPE_PACK_EXPANSION, then
-     we actually have a parameter pack expansion expression. Otherwise,
-     leave the ellipsis for a C-style variadic function. */
+  /* If the next token is an ellipsis, and we have not seen a
+     declarator name, and the type of the declarator contains parameter
+     packs but it is not a TYPE_PACK_EXPANSION, then we actually have
+     a parameter pack expansion expression. Otherwise, leave the
+     ellipsis for a C-style variadic function. */
   token = cp_lexer_peek_token (parser->lexer);
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
     {
       tree type = decl_specifiers.type;
 
-      if (DECL_P (type))
+      if (type && DECL_P (type))
         type = TREE_TYPE (type);
 
-      if (TREE_CODE (type) != TYPE_PACK_EXPANSION
+      if (type
+         && TREE_CODE (type) != TYPE_PACK_EXPANSION
+         && declarator_can_be_parameter_pack (declarator)
           && (!declarator || !declarator->parameter_pack_p)
           && uses_parameter_packs (type))
         {
-          /* Consume the `...'. */
-          cp_lexer_consume_token (parser->lexer);
-          maybe_warn_variadic_templates ();
-          
-          /* Build a pack expansion type */
-          if (declarator)
-            declarator->parameter_pack_p = true;
-          else
-            decl_specifiers.type = make_pack_expansion (type);
-        }
+         /* Consume the `...'. */
+         cp_lexer_consume_token (parser->lexer);
+         maybe_warn_variadic_templates ();
+         
+         /* Build a pack expansion type */
+         if (declarator)
+           declarator->parameter_pack_p = true;
+         else
+           decl_specifiers.type = make_pack_expansion (type);
+       }
     }
 
   /* The restriction on defining new types applies only to the type
index f1e6b18..906b8d5 100644 (file)
@@ -2441,6 +2441,12 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
       *walk_subtrees = 0;
       return NULL_TREE;
 
+    case INTEGER_TYPE:
+      walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r, 
+                ppd, ppd->visited);
+      *walk_subtrees = 0;
+      return NULL_TREE;
+
     default:
       return NULL_TREE;
     }
@@ -2621,6 +2627,8 @@ check_for_bare_parameter_packs (tree t)
         if (TREE_CODE (pack) == TEMPLATE_TYPE_PARM
             || TREE_CODE (pack) == TEMPLATE_TEMPLATE_PARM)
           name = TYPE_NAME (pack);
+       else if (TREE_CODE (pack) == TEMPLATE_PARM_INDEX)
+         name = DECL_NAME (TEMPLATE_PARM_DECL (pack));
         else
           name = DECL_NAME (pack);
         inform ("        %qD", name);
@@ -6860,6 +6868,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
       if (arg_pack && TREE_CODE (arg_pack) == ARGUMENT_PACK_SELECT)
        arg_pack = ARGUMENT_PACK_SELECT_FROM_PACK (arg_pack);
       
+      if (arg_pack && !ARGUMENT_PACK_P (arg_pack))
+       /* This can only happen if we forget to expand an argument
+          pack somewhere else. Just return an error, silently.  */
+       {
+         result = make_tree_vec (1);
+         TREE_VEC_ELT (result, 0) = error_mark_node;
+         return result;
+       }
+
       if (arg_pack)
         {
           int my_len = 
index a1af0d5..35e22c8 100644 (file)
@@ -1,3 +1,9 @@
+2007-03-31  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * g++.dg/parser/pr31138.C: New.
+       * g++.dg/parser/pr31140.C: New.
+       * g++.dg/parser/pr31141.C: New.
+
 2007-03-30  Paolo Carlini  <pcarlini@suse.de>
 
        PR c++/26099