C++ PATCH: PR 13243 and PR 12573
Mark Mitchell
mark@codesourcery.com
Mon Dec 15 16:57:00 GMT 2003
These PRs both had examples of expressions that were not
constant-expressions being used as template-arguments. Some of us got
fooled into thinking we should fix value_dependent_expression_p, but
the real problem was that we were not correctly flagging these as
invalid template arguments.
The standard is not perfectly clear on what is permitted in an
integral constant-expression, and it has a partial listk of what is
forbidden, which confused me. However, things like "[...]" and "->"
clearly should not be permitted, and the EDG front end rejects these
cases as well.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-12-15 Mark Mitchell <mark@codesourcery.com>
PR c++/13243
PR c++/12573
* parser.c (cp_parser_postfix_expression): Tighten handling of
integral constant expressions.
(cp_parser_unary_expression): Likewise.
* pt.c (value_dependent_expression_p): Remove handling for
COMPONENT_REFs.
2003-12-15 Mark Mitchell <mark@codesourcery.com>
PR c++/13243
PR c++/12573
* g++.dg/template/crash14.C: New test.
* g++.dg/template/dependent-expr3.C: Add dg-error markers.
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.131
diff -c -5 -p -r1.131 parser.c
*** cp/parser.c 15 Dec 2003 06:28:15 -0000 1.131
--- cp/parser.c 15 Dec 2003 16:52:57 -0000
*************** cp_parser_postfix_expression (cp_parser
*** 3635,3644 ****
--- 3637,3655 ----
/* Build the ARRAY_REF. */
postfix_expression
= grok_array_decl (postfix_expression, index);
idk = CP_ID_KIND_NONE;
+ /* Array references are not permitted in
+ constant-expressions. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ postfix_expression
+ = cp_parser_non_constant_expression ("an array reference");
+ parser->non_constant_expression_p = true;
+ }
}
break;
case CPP_OPEN_PAREN:
/* postfix-expression ( expression-list [opt] ) */
*************** cp_parser_postfix_expression (cp_parser
*** 3656,3666 ****
/* Function calls are not permitted in
constant-expressions. */
if (parser->constant_expression_p)
{
if (!parser->allow_non_constant_expression_p)
! return cp_parser_non_constant_expression ("a function call");
parser->non_constant_expression_p = true;
}
koenig_p = false;
if (idk == CP_ID_KIND_UNQUALIFIED)
--- 3667,3681 ----
/* Function calls are not permitted in
constant-expressions. */
if (parser->constant_expression_p)
{
if (!parser->allow_non_constant_expression_p)
! {
! postfix_expression
! = cp_parser_non_constant_expression ("a function call");
! break;
! }
parser->non_constant_expression_p = true;
}
koenig_p = false;
if (idk == CP_ID_KIND_UNQUALIFIED)
*************** cp_parser_postfix_expression (cp_parser
*** 3735,3744 ****
--- 3750,3760 ----
{
tree name;
bool dependent_p;
bool template_p;
tree scope = NULL_TREE;
+ enum cpp_ttype token_type = token->type;
/* If this is a `->' operator, dereference the pointer. */
if (token->type == CPP_DEREF)
postfix_expression = build_x_arrow (postfix_expression);
/* Check to see whether or not the expression is
*************** cp_parser_postfix_expression (cp_parser
*** 3837,3882 ****
/* We no longer need to look up names in the scope of the
object on the left-hand side of the `.' or `->'
operator. */
parser->context->object_type = NULL_TREE;
}
break;
case CPP_PLUS_PLUS:
/* postfix-expression ++ */
/* Consume the `++' token. */
cp_lexer_consume_token (parser->lexer);
/* Increments may not appear in constant-expressions. */
if (parser->constant_expression_p)
{
if (!parser->allow_non_constant_expression_p)
! return cp_parser_non_constant_expression ("an increment");
parser->non_constant_expression_p = true;
}
- /* Generate a representation for the complete expression. */
- postfix_expression
- = finish_increment_expr (postfix_expression,
- POSTINCREMENT_EXPR);
idk = CP_ID_KIND_NONE;
break;
case CPP_MINUS_MINUS:
/* postfix-expression -- */
/* Consume the `--' token. */
cp_lexer_consume_token (parser->lexer);
/* Decrements may not appear in constant-expressions. */
if (parser->constant_expression_p)
{
if (!parser->allow_non_constant_expression_p)
! return cp_parser_non_constant_expression ("a decrement");
parser->non_constant_expression_p = true;
}
- /* Generate a representation for the complete expression. */
- postfix_expression
- = finish_increment_expr (postfix_expression,
- POSTDECREMENT_EXPR);
idk = CP_ID_KIND_NONE;
break;
default:
return postfix_expression;
--- 3853,3909 ----
/* We no longer need to look up names in the scope of the
object on the left-hand side of the `.' or `->'
operator. */
parser->context->object_type = NULL_TREE;
+ /* These operators may not appear in constant-expressions. */
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ postfix_expression
+ = (cp_parser_non_constant_expression
+ (token_type == CPP_DEREF ? "'->'" : "`.'"));
+ parser->non_constant_expression_p = true;
+ }
}
break;
case CPP_PLUS_PLUS:
/* postfix-expression ++ */
/* Consume the `++' token. */
cp_lexer_consume_token (parser->lexer);
+ /* Generate a representation for the complete expression. */
+ postfix_expression
+ = finish_increment_expr (postfix_expression,
+ POSTINCREMENT_EXPR);
/* Increments may not appear in constant-expressions. */
if (parser->constant_expression_p)
{
if (!parser->allow_non_constant_expression_p)
! postfix_expression
! = cp_parser_non_constant_expression ("an increment");
parser->non_constant_expression_p = true;
}
idk = CP_ID_KIND_NONE;
break;
case CPP_MINUS_MINUS:
/* postfix-expression -- */
/* Consume the `--' token. */
cp_lexer_consume_token (parser->lexer);
+ /* Generate a representation for the complete expression. */
+ postfix_expression
+ = finish_increment_expr (postfix_expression,
+ POSTDECREMENT_EXPR);
/* Decrements may not appear in constant-expressions. */
if (parser->constant_expression_p)
{
if (!parser->allow_non_constant_expression_p)
! postfix_expression
! = cp_parser_non_constant_expression ("a decrement");
parser->non_constant_expression_p = true;
}
idk = CP_ID_KIND_NONE;
break;
default:
return postfix_expression;
*************** cp_parser_unary_expression (cp_parser *p
*** 4215,4260 ****
}
}
if (unary_operator != ERROR_MARK)
{
tree cast_expression;
/* Consume the operator token. */
token = cp_lexer_consume_token (parser->lexer);
/* Parse the cast-expression. */
cast_expression
= cp_parser_cast_expression (parser, unary_operator == ADDR_EXPR);
/* Now, build an appropriate representation. */
switch (unary_operator)
{
case INDIRECT_REF:
! return build_x_indirect_ref (cast_expression, "unary *");
!
case ADDR_EXPR:
case BIT_NOT_EXPR:
! return build_x_unary_op (unary_operator, cast_expression);
!
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
! if (parser->constant_expression_p)
! {
! if (!parser->allow_non_constant_expression_p)
! return cp_parser_non_constant_expression (PREINCREMENT_EXPR
! ? "an increment"
! : "a decrement");
! parser->non_constant_expression_p = true;
! }
/* Fall through. */
case CONVERT_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
! return finish_unary_op_expr (unary_operator, cast_expression);
default:
abort ();
- return error_mark_node;
}
}
return cp_parser_postfix_expression (parser, address_p);
}
--- 4242,4297 ----
}
}
if (unary_operator != ERROR_MARK)
{
tree cast_expression;
+ tree expression = error_mark_node;
+ const char *non_constant_p = NULL;
/* Consume the operator token. */
token = cp_lexer_consume_token (parser->lexer);
/* Parse the cast-expression. */
cast_expression
= cp_parser_cast_expression (parser, unary_operator == ADDR_EXPR);
/* Now, build an appropriate representation. */
switch (unary_operator)
{
case INDIRECT_REF:
! non_constant_p = "`*'";
! expression = build_x_indirect_ref (cast_expression, "unary *");
! break;
!
case ADDR_EXPR:
+ non_constant_p = "`&'";
+ /* Fall through. */
case BIT_NOT_EXPR:
! expression = build_x_unary_op (unary_operator, cast_expression);
! break;
!
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
! non_constant_p = (unary_operator == PREINCREMENT_EXPR
! ? "`++'" : "`--'");
/* Fall through. */
case CONVERT_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
! expression = finish_unary_op_expr (unary_operator, cast_expression);
! break;
default:
abort ();
}
+
+ if (non_constant_p && parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression (non_constant_p);
+ parser->non_constant_expression_p = true;
+ }
+
+ return expression;
}
return cp_parser_postfix_expression (parser, address_p);
}
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.801
diff -c -5 -p -r1.801 pt.c
*** cp/pt.c 13 Dec 2003 04:28:50 -0000 1.801
--- cp/pt.c 15 Dec 2003 16:53:03 -0000
*************** value_dependent_expression_p (tree expre
*** 11712,11724 ****
return dependent_type_p (expression);
return type_dependent_expression_p (expression);
}
if (TREE_CODE (expression) == SCOPE_REF)
return dependent_scope_ref_p (expression, value_dependent_expression_p);
- if (TREE_CODE (expression) == COMPONENT_REF)
- return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
- || value_dependent_expression_p (TREE_OPERAND (expression, 1)));
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
{
switch (TREE_CODE_CLASS (TREE_CODE (expression)))
--- 11712,11721 ----
Index: testsuite/g++.dg/template/crash14.C
===================================================================
RCS file: testsuite/g++.dg/template/crash14.C
diff -N testsuite/g++.dg/template/crash14.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/crash14.C 15 Dec 2003 16:53:05 -0000
***************
*** 0 ****
--- 1,3 ----
+ template <int T> class foo { public: foo() { } class Z { };};
+ template <int I[2]> void dep7(foo<I[0]> *) { } // { dg-error "" }
+
Index: testsuite/g++.dg/template/dependent-expr3.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/template/dependent-expr3.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 dependent-expr3.C
*** testsuite/g++.dg/template/dependent-expr3.C 2 Dec 2003 12:10:32 -0000 1.1
--- testsuite/g++.dg/template/dependent-expr3.C 15 Dec 2003 16:53:05 -0000
*************** template <bool> struct S;
*** 7,14 ****
template <typename K> struct Y : K {
int x;
};
template <class T> struct Z {
! S< (bool)(&static_cast<Y<T> *>(0)->x == 0) >
! s;
};
--- 7,14 ----
template <typename K> struct Y : K {
int x;
};
template <class T> struct Z {
! S< (bool)(&static_cast<Y<T> *>(0)->x == 0) > // { dg-error "" }
! s; // { dg-error "" }
};
More information about the Gcc-patches
mailing list