From f5e44182eb3a89ef9cf0a51d2898d8f4111252d2 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 28 Mar 2013 14:20:58 -0400 Subject: [PATCH] re PR c++/56679 ([C++11] Cannot take sizeof... a template template parameter pack) 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 | 4 ++ gcc/cp/parser.c | 65 +++++++++++++------ gcc/testsuite/g++.dg/cpp0x/variadic-sizeof1.C | 11 ++++ gcc/testsuite/g++.dg/cpp0x/variadic76.C | 4 +- gcc/testsuite/g++.dg/cpp0x/variadic77.C | 2 +- 5 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-sizeof1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b0a952a741c..0709b66966f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2013-03-28 Jason Merrill + 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'. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 5e2a4e09525..ec6eb085289 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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, + "% 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, - "% 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 index 00000000000..2837c856b10 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof1.C @@ -0,0 +1,11 @@ +// PR c++/56679 +// { dg-require-effective-target c++11 } + +template