This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH] [PR/13243] Detect more non constant expressions (regression in mainline)
Jason Merrill <jason@redhat.com> wrote:
> No. There are address constant-expressions, too, as described in 5.19p4.
Ok, but that kind of contant-expressions are valid only for non-local static
object initialization, for which we don't set constant_expression_p as far as I
can tell. I should have specified this in the mail, sorry.
Another thing that might not be crystal clear which I forgot about is that this
patch doesn't affect other entries in the 14.3.2/1 list (like pointer to
members or addresses to an object/function with external linkage, or even a
single non-type template parameter of non-integral/enumaration type -as checked
by dep5 in my testcase-) because those conditions are directly checked within
cp_parser_template_argument, before trying to parse the more generic constant
expression.
> and so your new test is appropriate. The name should be fixed accordingly,
> as should the error message in your patch and the comment in your testcase.
The generic error message emitted by "cp_parser_non_constant_expression" uses
the term "constant-expression". Anyway, I changed my error message.
> Also, we don't capitalize the first letter in an error message.
Done. I didn't retest the patch because it's only ChangLog, comment, and
literal changes. OK for mainline?
Giovanni Bajo
2003-12-07 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/13243
* parser.c (cp_parser_unary_expression): Emit an error when
INDIRECT_REF and ADDR_EXPR are used in an integral
constant-expression.
* pt.c (value_dependent_expression_p): Handle recursively
INDIRECT_REF and ARRAY_REF trees.
* semantics.c (finish_id_expression): Refactor the code to handle
template parameters, and emit a more informative error message
when they are used within non integral constant expressions.
2003-12-07 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/13243
* g++.dg/template/dependent-expr3.C: Adjust to test for the new error.
* g++.dg/template/nontype3.C: New test.
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.129
diff -c -3 -p -r1.129 parser.c
*** parser.c 6 Dec 2003 06:53:01 -0000 1.129
--- parser.c 7 Dec 2003 23:25:40 -0000
*************** cp_parser_unary_expression (cp_parser *p
*** 4196,4204 ****
--- 4196,4217 ----
switch (unary_operator)
{
case INDIRECT_REF:
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("unary `*'");
+ parser->non_constant_expression_p = true;
+ }
return build_x_indirect_ref (cast_expression, "unary *");
case ADDR_EXPR:
+ if (parser->constant_expression_p)
+ {
+ if (!parser->allow_non_constant_expression_p)
+ return cp_parser_non_constant_expression ("unary `&'");
+ parser->non_constant_expression_p = true;
+ }
+ /* Fall through. */
case BIT_NOT_EXPR:
return build_x_unary_op (unary_operator, cast_expression);
Index: pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.799
diff -c -3 -p -r1.799 pt.c
*** pt.c 2 Dec 2003 15:46:51 -0000 1.799
--- pt.c 7 Dec 2003 23:25:46 -0000
*************** value_dependent_expression_p (tree expre
*** 11717,11722 ****
--- 11717,11727 ----
if (TREE_CODE (expression) == COMPONENT_REF)
return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
|| value_dependent_expression_p (TREE_OPERAND (expression, 1)));
+ if (TREE_CODE (expression) == ARRAY_REF)
+ return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
+ || value_dependent_expression_p (TREE_OPERAND (expression, 1)));
+ if (TREE_CODE (expression) == INDIRECT_REF)
+ return (value_dependent_expression_p (TREE_OPERAND (expression, 0)));
/* A constant expression is value-dependent if any subexpression is
value-dependent. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
Index: semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.374
diff -c -3 -p -r1.374 semantics.c
*** semantics.c 4 Dec 2003 05:02:18 -0000 1.374
--- semantics.c 7 Dec 2003 23:25:48 -0000
*************** finish_id_expression (tree id_expression
*** 2392,2405 ****
}
/* If the name resolved to a template parameter, there is no
! need to look it up again later. Similarly, we resolve
! enumeration constants to their underlying values. */
! if (TREE_CODE (decl) == CONST_DECL)
{
*idk = CP_ID_KIND_NONE;
! if (DECL_TEMPLATE_PARM_P (decl) || !processing_template_decl)
return DECL_INITIAL (decl);
! return decl;
}
else
{
--- 2392,2423 ----
}
/* If the name resolved to a template parameter, there is no
! need to look it up again later. */
! if ((TREE_CODE (decl) == CONST_DECL && DECL_TEMPLATE_PARM_P (decl))
! || TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
{
*idk = CP_ID_KIND_NONE;
! if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
! decl = TEMPLATE_PARM_DECL (decl);
! if (constant_expression_p
! && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
! {
! if (!allow_non_constant_expression_p)
! error ("template parameter `%D' of type `%T' is not allowed in "
! "an integral constant expression because it is not of integral "
! "or enumeration type", decl, TREE_TYPE (decl));
! *non_constant_expression_p = true;
! }
! return DECL_INITIAL (decl);
! }
! /* Similarly, we resolve enumeration constants to their
! underlying values. */
! else if (TREE_CODE (decl) == CONST_DECL)
! {
! *idk = CP_ID_KIND_NONE;
! if (!processing_template_decl)
return DECL_INITIAL (decl);
! return decl;
}
else
{
*************** finish_id_expression (tree id_expression
*** 2516,2536 ****
}
/* Only certain kinds of names are allowed in constant
! expression. Enumerators have already been handled above. */
if (constant_expression_p)
{
- /* Non-type template parameters of integral or enumeration
- type are OK. */
- if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
- && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
- ;
/* Const variables or static data members of integral or
enumeration types initialized with constant expressions
are OK. */
! else if (TREE_CODE (decl) == VAR_DECL
! && CP_TYPE_CONST_P (TREE_TYPE (decl))
! && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
! && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
;
else
{
--- 2534,2550 ----
}
/* Only certain kinds of names are allowed in constant
! expression. Enumerators and template parameters
! have already been handled above. */
if (constant_expression_p)
{
/* Const variables or static data members of integral or
enumeration types initialized with constant expressions
are OK. */
! if (TREE_CODE (decl) == VAR_DECL
! && CP_TYPE_CONST_P (TREE_TYPE (decl))
! && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
! && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
;
else
{
Index: 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 -p -r1.1 dependent-expr3.C
*** g++.dg/template/dependent-expr3.C 2 Dec 2003 12:10:32 -0000 1.1
--- g++.dg/template/dependent-expr3.C 8 Dec 2003 02:55:33 -0000
*************** template <typename K> struct Y : K {
*** 9,14 ****
};
template <class T> struct Z {
! S< (bool)(&static_cast<Y<T> *>(0)->x == 0) >
! s;
};
--- 9,13 ----
};
template <class T> struct Z {
! S< (bool)(&static_cast<Y<T> *>(0)->x == 0) > s; // { dg-error "" "" }
};
// { dg-do compile }
// Origin: <drow at gcc dot gnu dot org>,
// <giovannibajo at gcc dot gnu dot org>
// c++/13243: Template parameters of non integral or enumeration type can't be
// used for integral constant expressions. ADDR_EXPR and INDIRECT_REF are
// invalid too.
template <int T> class foo {};
template <int *T> class bar {};
template <int *PI>
void dep5(bar<PI> *);
template <int *PI>
void dep6(bar<PI+1> *); // { dg-error "" "integral or enumeration" }
template <int I>
void dep7(bar<I+1> *);
template <int *PI>
void dep8(foo< *PI > *); // { dg-error "" "integral or enumeration" }
template <int PI[1]>
void dep9(foo< *PI > *); // { dg-error "" "integral or enumeration" }
template <int PI[1]>
void dep9a(foo< sizeof(*PI) > *);
template <int PI[1]>
void dep10(foo< PI[0] > *); // { dg-error "" "integral or enumeration" }
template <int I>
void dep11(foo< *&I > *); // { dg-error "" "constant-expression" }
template <int I>
void dep12(foo< (&I)[4] > *); // { dg-error "" "constant-expression" }