re PR c++/56679 ([C++11] Cannot take sizeof... a template template parameter pack)
authorJason Merrill <jason@redhat.com>
Thu, 28 Mar 2013 18:20:58 +0000 (14:20 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 28 Mar 2013 18:20:58 +0000 (14:20 -0400)
PR c++/56679
* parser.c (cp_parser_sizeof_pack): Split out from...
(cp_parser_sizeof_operand): ...here.  Require (id).

From-SVN: r197213

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp0x/variadic-sizeof1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic76.C
gcc/testsuite/g++.dg/cpp0x/variadic77.C

index b0a952a741cf787d4298993ca9177c51eb8d50d5..0709b66966f4bb628f0795f1ea664d981318675f 100644 (file)
@@ -1,5 +1,9 @@
 2013-03-28  Jason Merrill  <jason@redhat.com>
 
+       PR c++/56679
+       * parser.c (cp_parser_sizeof_pack): Split out from...
+       (cp_parser_sizeof_operand): ...here.  Require (id).
+
        PR c++/56701
        * semantics.c (finish_this_expr): 'this' is an rvalue.
        * typeck.c (cp_build_indirect_ref): Handle NOP_EXPR of 'this'.
index 5e2a4e095253ffce6355355b43a4c929640559f2..ec6eb085289b7ca55f3662bd67f7055a9c7ecfe8 100644 (file)
@@ -22618,6 +22618,44 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
   pop_unparsed_function_queues (parser);
 }
 
+/* Subroutine of cp_parser_sizeof_operand, for handling C++11
+
+     sizeof ... ( identifier )
+
+   where the 'sizeof' token has already been consumed.  */
+
+static tree
+cp_parser_sizeof_pack (cp_parser *parser)
+{
+  /* Consume the `...'.  */
+  cp_lexer_consume_token (parser->lexer);
+  maybe_warn_variadic_templates ();
+
+  bool paren = cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN);
+  if (paren)
+    cp_lexer_consume_token (parser->lexer);
+  else
+    permerror (cp_lexer_peek_token (parser->lexer)->location,
+              "%<sizeof...%> argument must be surrounded by parentheses");
+
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  tree name = cp_parser_identifier (parser);
+  tree expr = cp_parser_lookup_name_simple (parser, name, token->location);
+  if (expr == error_mark_node)
+    cp_parser_name_lookup_error (parser, name, expr, NLE_NULL,
+                                token->location);
+  if (TREE_CODE (expr) == TYPE_DECL)
+    expr = TREE_TYPE (expr);
+  else if (TREE_CODE (expr) == CONST_DECL)
+    expr = DECL_INITIAL (expr);
+  expr = make_pack_expansion (expr);
+
+  if (paren)
+    cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+  return expr;
+}
+
 /* Parse the operand of `sizeof' (or a similar operator).  Returns
    either a TYPE or an expression, depending on the form of the
    input.  The KEYWORD indicates which kind of expression we have
@@ -22631,7 +22669,12 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   char *tmp;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
-  bool pack_expansion_p = false;
+
+  /* If it's a `...', then we are computing the length of a parameter
+     pack.  */
+  if (keyword == RID_SIZEOF
+      && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+    return cp_parser_sizeof_pack (parser);
 
   /* Types cannot be defined in a `sizeof' expression.  Save away the
      old message.  */
@@ -22650,19 +22693,6 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
     = parser->non_integral_constant_expression_p;
   parser->integral_constant_expression_p = false;
 
-  /* If it's a `...', then we are computing the length of a parameter
-     pack.  */
-  if (keyword == RID_SIZEOF
-      && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
-    {
-      /* Consume the `...'.  */
-      cp_lexer_consume_token (parser->lexer);
-      maybe_warn_variadic_templates ();
-
-      /* Note that this is an expansion.  */
-      pack_expansion_p = true;
-    }
-
   /* Do not actually evaluate the expression.  */
   ++cp_unevaluated_operand;
   ++c_inhibit_evaluation_warnings;
@@ -22702,9 +22732,6 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
                                 /*attrlist=*/NULL);
        }
     }
-  else if (pack_expansion_p)
-    permerror (cp_lexer_peek_token (parser->lexer)->location,
-              "%<sizeof...%> argument must be surrounded by parentheses");
 
   /* If the type-id production did not work out, then we must be
      looking at the unary-expression production.  */
@@ -22712,10 +22739,6 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
     expr = cp_parser_unary_expression (parser, /*address_p=*/false,
                                       /*cast_p=*/false, NULL);
 
-  if (pack_expansion_p)
-    /* Build a pack expansion. */
-    expr = make_pack_expansion (expr);
-
   /* Go back to evaluating expressions.  */
   --cp_unevaluated_operand;
   --c_inhibit_evaluation_warnings;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof1.C
new file mode 100644 (file)
index 0000000..2837c85
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/56679
+// { dg-require-effective-target c++11 }
+
+template <template <typename> class... Args>
+struct Foo {
+  static const int value = sizeof...(Args);
+};
+
+template <typename> struct Bar { };
+
+const int test = Foo<Bar>::value;
index fb80244d658e86af7a8bf40e5fec1915b836b855..ff0211ded150461d1bb8e0026c3025271bc8843a 100644 (file)
@@ -4,8 +4,8 @@
 
 template<int... N> int foo ()
 {
-  return sizeof... (N ());     // { dg-error "cannot be used as a function" }
-  return sizeof... (N) ();     // { dg-error "cannot be used as a function" }
+  return sizeof... (N ());     // { dg-error "" }
+  return sizeof... (N) ();     // { dg-error "" }
 }
 
 int bar ()
index 43f2d1e43d8c57ffc281d91116588e9c7027f924..8c6119ff160affedecff060dca3aca2fef9a38a6 100644 (file)
@@ -12,7 +12,7 @@ template<int... M> struct S
 {
   template<int... N> static int foo ()
   {
-    return sizeof... (pair<M, N>);     // { dg-error "mismatched argument pack lengths" }
+    return sizeof... (pair<M, N>);     // { dg-error "" }
   }
 };