re PR c++/14550 (trouble with pointers in templates)

PR c++/14550
	* parser.c (cp_parser_non_integral_constant_expression): Encode
	more of the idiom that surrounded calls to this function within
	the function itself
	(cp_parser_primary_expression): Adjust accordingly.
	(cp_parser_postfix_expression): Likewise.
	(cp_parser_unary_expression): Likewise.
	(cp_parser_cast_expression): Likewise.
	(cp_parser_assignment_expression): Likewise.
	(cp_parser_expression): Likewise.
	(cp_parser_new_expression): Note that new-expressions are not
	allowed in integral constant expressions.
	(cp_parser_delete_expression): Likewise.

	PR c++/14550
	* g++.dg/parse/template14.C: New test.

From-SVN: r79498
This commit is contained in:
Mark Mitchell 2004-03-15 16:16:18 +00:00 committed by Mark Mitchell
parent 983e64842f
commit 625cbf9318
4 changed files with 114 additions and 94 deletions

View File

@ -1,3 +1,19 @@
2004-03-13 Mark Mitchell <mark@codesourcery.com>
PR c++/14550
* parser.c (cp_parser_non_integral_constant_expression): Encode
more of the idiom that surrounded calls to this function within
the function itself
(cp_parser_primary_expression): Adjust accordingly.
(cp_parser_postfix_expression): Likewise.
(cp_parser_unary_expression): Likewise.
(cp_parser_cast_expression): Likewise.
(cp_parser_assignment_expression): Likewise.
(cp_parser_expression): Likewise.
(cp_parser_new_expression): Note that new-expressions are not
allowed in integral constant expressions.
(cp_parser_delete_expression): Likewise.
2004-03-12 Matt Austern <austern@apple.com>
* decl2.c (maybe_make_one_only): Look at

View File

@ -1719,8 +1719,8 @@ static void cp_parser_check_for_definition_in_return_type
(tree, int);
static void cp_parser_check_for_invalid_template_id
(cp_parser *, tree);
static tree cp_parser_non_integral_constant_expression
(const char *);
static bool cp_parser_non_integral_constant_expression
(cp_parser *, const char *);
static void cp_parser_diagnose_invalid_type_name
(cp_parser *, tree, tree);
static bool cp_parser_parse_and_diagnose_invalid_type_name
@ -1922,14 +1922,24 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
}
}
/* Issue an error message about the fact that THING appeared in a
constant-expression. Returns ERROR_MARK_NODE. */
/* If parsing an integral constant-expression, issue an error message
about the fact that THING appeared and return true. Otherwise,
return false, marking the current expression as non-constant. */
static tree
cp_parser_non_integral_constant_expression (const char *thing)
static bool
cp_parser_non_integral_constant_expression (cp_parser *parser,
const char *thing)
{
error ("%s cannot appear in a constant-expression", thing);
return error_mark_node;
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
{
error ("%s cannot appear in a constant-expression", thing);
return true;
}
parser->non_integral_constant_expression_p = true;
}
return false;
}
/* Emit a diagnostic for an invalid type name. Consider also if it is
@ -2542,12 +2552,9 @@ cp_parser_primary_expression (cp_parser *parser,
return error_mark_node;
}
/* Pointers cannot appear in constant-expressions. */
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
return cp_parser_non_integral_constant_expression ("`this'");
parser->non_integral_constant_expression_p = true;
}
if (cp_parser_non_integral_constant_expression (parser,
"`this'"))
return error_mark_node;
return finish_this_expr ();
/* The `operator' keyword can be the beginning of an
@ -2589,12 +2596,9 @@ cp_parser_primary_expression (cp_parser *parser,
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
/* Using `va_arg' in a constant-expression is not
allowed. */
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
return cp_parser_non_integral_constant_expression ("`va_arg'");
parser->non_integral_constant_expression_p = true;
}
if (cp_parser_non_integral_constant_expression (parser,
"`va_arg'"))
return error_mark_node;
return build_x_va_arg (expression, type);
}
@ -3518,14 +3522,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
&& !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
/* A cast to pointer or reference type is allowed in the
implementation of "offsetof". */
&& !(parser->in_offsetof_p && POINTER_TYPE_P (type)))
{
if (!parser->allow_non_integral_constant_expression_p)
return (cp_parser_non_integral_constant_expression
("a cast to a type other than an integral or "
"enumeration type"));
parser->non_integral_constant_expression_p = true;
}
&& !(parser->in_offsetof_p && POINTER_TYPE_P (type))
&& (cp_parser_non_integral_constant_expression
(parser,
"a cast to a type other than an integral or "
"enumeration type")))
return error_mark_node;
switch (keyword)
{
@ -3771,13 +3773,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
idk = CP_ID_KIND_NONE;
/* Array references are not permitted in
constant-expressions. */
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
postfix_expression
= cp_parser_non_integral_constant_expression ("an array reference");
parser->non_integral_constant_expression_p = true;
}
if (cp_parser_non_integral_constant_expression
(parser, "an array reference"))
postfix_expression = error_mark_node;
}
break;
@ -3796,15 +3794,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* Function calls are not permitted in
constant-expressions. */
if (parser->integral_constant_expression_p)
if (cp_parser_non_integral_constant_expression (parser,
"a function call"))
{
if (!parser->allow_non_integral_constant_expression_p)
{
postfix_expression
= cp_parser_non_integral_constant_expression ("a function call");
break;
}
parser->non_integral_constant_expression_p = true;
postfix_expression = error_mark_node;
break;
}
koenig_p = false;
@ -3999,18 +3993,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
operator. */
parser->context->object_type = NULL_TREE;
/* These operators may not appear in constant-expressions. */
if (parser->integral_constant_expression_p
/* The "->" operator is allowed in the implementation
if (/* The "->" operator is allowed in the implementation
of "offsetof". The "." operator may appear in the
name of the member. */
&& !parser->in_offsetof_p)
{
if (!parser->allow_non_integral_constant_expression_p)
postfix_expression
= (cp_parser_non_integral_constant_expression
(token_type == CPP_DEREF ? "'->'" : "`.'"));
parser->non_integral_constant_expression_p = true;
}
!parser->in_offsetof_p
&& (cp_parser_non_integral_constant_expression
(parser,
token_type == CPP_DEREF ? "'->'" : "`.'")))
postfix_expression = error_mark_node;
}
break;
@ -4023,13 +4013,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
= finish_increment_expr (postfix_expression,
POSTINCREMENT_EXPR);
/* Increments may not appear in constant-expressions. */
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
postfix_expression
= cp_parser_non_integral_constant_expression ("an increment");
parser->non_integral_constant_expression_p = true;
}
if (cp_parser_non_integral_constant_expression (parser,
"an increment"))
postfix_expression = error_mark_node;
idk = CP_ID_KIND_NONE;
break;
@ -4042,13 +4028,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
= finish_increment_expr (postfix_expression,
POSTDECREMENT_EXPR);
/* Decrements may not appear in constant-expressions. */
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
postfix_expression
= cp_parser_non_integral_constant_expression ("a decrement");
parser->non_integral_constant_expression_p = true;
}
if (cp_parser_non_integral_constant_expression (parser,
"a decrement"))
postfix_expression = error_mark_node;
idk = CP_ID_KIND_NONE;
break;
@ -4447,12 +4429,10 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
abort ();
}
if (non_constant_p && parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
return cp_parser_non_integral_constant_expression (non_constant_p);
parser->non_integral_constant_expression_p = true;
}
if (non_constant_p
&& cp_parser_non_integral_constant_expression (parser,
non_constant_p))
expression = error_mark_node;
return expression;
}
@ -4553,6 +4533,11 @@ cp_parser_new_expression (cp_parser* parser)
else
initializer = NULL_TREE;
/* A new-expression may not appear in an integral constant
expression. */
if (cp_parser_non_integral_constant_expression (parser, "`new'"))
return error_mark_node;
/* Create a representation of the new-expression. */
return build_new (placement, type, initializer, global_scope_p);
}
@ -4781,6 +4766,11 @@ cp_parser_delete_expression (cp_parser* parser)
/* Parse the cast-expression. */
expression = cp_parser_simple_cast_expression (parser);
/* A delete-expression may not appear in an integral constant
expression. */
if (cp_parser_non_integral_constant_expression (parser, "`delete'"))
return error_mark_node;
return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
}
@ -4878,14 +4868,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
can be used in constant-expressions. */
if (parser->integral_constant_expression_p
&& !dependent_type_p (type)
&& !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
if (!parser->allow_non_integral_constant_expression_p)
return (cp_parser_non_integral_constant_expression
("a casts to a type other than an integral or "
"enumeration type"));
parser->non_integral_constant_expression_p = true;
}
&& !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
&& (cp_parser_non_integral_constant_expression
(parser,
"a cast to a type other than an integral or "
"enumeration type")))
return error_mark_node;
/* Perform the cast. */
expr = build_c_cast (type, expr);
return expr;
@ -5238,12 +5227,9 @@ cp_parser_assignment_expression (cp_parser* parser)
rhs = cp_parser_assignment_expression (parser);
/* An assignment may not appear in a
constant-expression. */
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
return cp_parser_non_integral_constant_expression ("an assignment");
parser->non_integral_constant_expression_p = true;
}
if (cp_parser_non_integral_constant_expression (parser,
"an assignment"))
return error_mark_node;
/* Build the assignment expression. */
expr = build_x_modify_expr (expr,
assignment_operator,
@ -5381,13 +5367,9 @@ cp_parser_expression (cp_parser* parser)
/* Consume the `,'. */
cp_lexer_consume_token (parser->lexer);
/* A comma operator cannot appear in a constant-expression. */
if (parser->integral_constant_expression_p)
{
if (!parser->allow_non_integral_constant_expression_p)
expression
= cp_parser_non_integral_constant_expression ("a comma operator");
parser->non_integral_constant_expression_p = true;
}
if (cp_parser_non_integral_constant_expression (parser,
"a comma operator"))
expression = error_mark_node;
}
return expression;

View File

@ -1,3 +1,8 @@
2004-03-13 Mark Mitchell <mark@codesourcery.com>
PR c++/14550
* g++.dg/parse/template14.C: New test.
2004-03-13 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.c-torture/execute/20040313-1.c: New test.

View File

@ -0,0 +1,17 @@
// PR c++/14550
struct A {
A();
};
template <int> void foo()
{
A *p = new A;
}
void bar()
{
foo<0>();
}