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
This commit is contained in:
Jason Merrill 2013-03-28 14:20:58 -04:00 committed by Jason Merrill
parent 374b283748
commit f5e44182eb
5 changed files with 62 additions and 24 deletions

View 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'.

View 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;

View File

@ -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;

View 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 ()

View 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 "" }
}
};