From 4be5e5b12d501cb3aae673e673c30363b32480df Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 25 Feb 2011 01:22:51 -0500 Subject: [PATCH] parser.c (cp_parser_constant_expression): Set non_integral_constant_expression correctly for C++0x too. * parser.c (cp_parser_constant_expression): Set non_integral_constant_expression correctly for C++0x too. (cp_parser_static_assert): Allow non-constant expression. (cp_parser_direct_declarator): Expect non_constant_p to be set properly for C++0x. * pt.c (value_dependent_expression_p): Handle TYPEID_EXPR. * semantics.c (maybe_constant_value): Check type_unknown_p too. (potential_rvalue_constant_expression): New. (require_potential_rvalue_constant_expression): New. From-SVN: r170488 --- gcc/cp/ChangeLog | 12 ++++++++++ gcc/cp/cp-tree.h | 2 ++ gcc/cp/decl.c | 6 ++--- gcc/cp/parser.c | 23 ++++++++++++++----- gcc/cp/pt.c | 1 + gcc/cp/semantics.c | 17 ++++++++++++++ gcc/testsuite/ChangeLog | 8 +++++++ .../g++.dg/cpp0x/constexpr-array-tparm.C | 5 ++++ .../g++.dg/cpp0x/regress/debug-debug7.C | 19 +++++++++++++++ .../g++.dg/cpp0x/regress/parse-ambig5.C | 8 +++++++ .../g++.dg/cpp0x/regress/template-function1.C | 8 +++---- gcc/testsuite/g++.dg/cpp0x/variadic20.C | 4 ++-- 12 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/regress/parse-ambig5.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8637ee0b369..3dba66e335b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2011-02-24 Jason Merrill + + * parser.c (cp_parser_constant_expression): Set + non_integral_constant_expression correctly for C++0x too. + (cp_parser_static_assert): Allow non-constant expression. + (cp_parser_direct_declarator): Expect non_constant_p to be set + properly for C++0x. + * pt.c (value_dependent_expression_p): Handle TYPEID_EXPR. + * semantics.c (maybe_constant_value): Check type_unknown_p too. + (potential_rvalue_constant_expression): New. + (require_potential_rvalue_constant_expression): New. + 2011-02-23 Jason Merrill * cp-tree.h (DECL_PARM_LEVEL): New. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ee72322a354..d5a6d5c0763 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5256,7 +5256,9 @@ extern tree register_constexpr_fundef (tree, tree); extern bool check_constexpr_ctor_body (tree, tree); extern tree ensure_literal_type_for_constexpr_object (tree); extern bool potential_constant_expression (tree); +extern bool potential_rvalue_constant_expression (tree); extern bool require_potential_constant_expression (tree); +extern bool require_potential_rvalue_constant_expression (tree); extern tree cxx_constant_value (tree); extern tree maybe_constant_value (tree); extern tree maybe_constant_init (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 14d530ac988..93c184845f9 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5824,12 +5824,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (init && TREE_CODE (decl) == VAR_DECL) { DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1; - /* FIXME we rely on TREE_CONSTANT below; basing that on - init_const_expr_p is probably wrong for C++0x. */ if (init_const_expr_p) { - /* Set these flags now for C++98 templates. We'll update the - flags in store_init_value for instantiations and C++0x. */ + /* Set these flags now for templates. We'll update the flags in + store_init_value for instantiations. */ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1; if (decl_maybe_constant_var_p (decl)) TREE_CONSTANT (decl) = 1; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1e8f03bddca..314a2ff2c49 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7266,10 +7266,19 @@ cp_parser_constant_expression (cp_parser* parser, = saved_integral_constant_expression_p; parser->allow_non_integral_constant_expression_p = saved_allow_non_integral_constant_expression_p; + if (cxx_dialect >= cxx0x) + { + /* Require an rvalue constant expression here; that's what our + callers expect. Reference constant expressions are handled + separately in e.g. cp_parser_template_argument. */ + bool is_const = potential_rvalue_constant_expression (expression); + parser->non_integral_constant_expression_p = !is_const; + if (!is_const && !allow_non_constant_p) + require_potential_rvalue_constant_expression (expression); + } if (allow_non_constant_p) *non_constant_p = parser->non_integral_constant_expression_p; - else if (parser->non_integral_constant_expression_p - && cxx_dialect < cxx0x) + else if (parser->non_integral_constant_expression_p) expression = error_mark_node; parser->non_integral_constant_expression_p = saved_non_integral_constant_expression_p; @@ -10212,6 +10221,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) tree message; cp_token *token; location_t saved_loc; + bool dummy; /* Peek at the `static_assert' token so we can keep track of exactly where the static assertion started. */ @@ -10231,11 +10241,12 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /* Parse the `(' starting the static assertion condition. */ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); - /* Parse the constant-expression. */ + /* Parse the constant-expression. Allow a non-constant expression + here in order to give better diagnostics in finish_static_assert. */ condition = cp_parser_constant_expression (parser, - /*allow_non_constant_p=*/false, - /*non_constant_p=*/NULL); + /*allow_non_constant_p=*/true, + /*non_constant_p=*/&dummy); /* Parse the separating `,'. */ cp_parser_require (parser, CPP_COMMA, RT_COMMA); @@ -15115,7 +15126,7 @@ cp_parser_direct_declarator (cp_parser* parser, = cp_parser_constant_expression (parser, /*allow_non_constant=*/true, &non_constant_p); - if (!non_constant_p || cxx_dialect >= cxx0x) + if (!non_constant_p) /* OK */; /* Normally, the array bound must be an integral constant expression. However, as an extension, we allow VLAs diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8d28219fc88..ed9d28b0b2f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18091,6 +18091,7 @@ value_dependent_expression_p (tree expression) case SIZEOF_EXPR: case ALIGNOF_EXPR: + case TYPEID_EXPR: /* A `sizeof' expression is value-dependent if the operand is type-dependent or is a pack expansion. */ expression = TREE_OPERAND (expression, 0); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8a7dd7d5e62..199084a6008 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7138,6 +7138,7 @@ maybe_constant_value (tree t) tree r; if (type_dependent_expression_p (t) + || type_unknown_p (t) || !potential_constant_expression (t) || value_dependent_expression_p (t)) return t; @@ -7727,6 +7728,14 @@ potential_constant_expression (tree t) return potential_constant_expression_1 (t, false, tf_none); } +/* As above, but require a constant rvalue. */ + +bool +potential_rvalue_constant_expression (tree t) +{ + return potential_constant_expression_1 (t, true, tf_none); +} + /* Like above, but complain about non-constant expressions. */ bool @@ -7734,6 +7743,14 @@ require_potential_constant_expression (tree t) { return potential_constant_expression_1 (t, false, tf_warning_or_error); } + +/* Cross product of the above. */ + +bool +require_potential_rvalue_constant_expression (tree t) +{ + return potential_constant_expression_1 (t, true, tf_warning_or_error); +} /* Constructor for a lambda expression. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5f8cd96b9bc..5acd9f25057 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2011-02-24 Jason Merrill + + * g++.dg/cpp0x/constexpr-array-tparm.C: New. + * g++.dg/cpp0x/regress/parse-ambig5.C: Copy from parse/ambig5.C. + * g++.dg/cpp0x/regress/debug-debug7.C: Copy from debug/debug7.C. + * g++.dg/cpp0x/variadic20.C: Adjust expected errors. + * g++.dg/cpp0x/regress/template-function1.C: Likewise. + 2011-02-24 Jakub Jelinek PR fortran/47878 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C new file mode 100644 index 00000000000..c17090cc3b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C @@ -0,0 +1,5 @@ +// { dg-options -std=c++0x } + +template struct A { int ir[I[0]]; }; +extern constexpr int ar[2] = { 1, 2 }; +A a; diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C b/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C new file mode 100644 index 00000000000..8ee8824719d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/debug-debug7.C @@ -0,0 +1,19 @@ +// { dg-do compile } +// { dg-options -std=c++0x } + +void f (int); + +int +main() { + + int a = 4; + int b = 5; + int (*x)[b] = new int[a][b]; // { dg-error "" } + + x[2][1] = 7; + + for (int i = 0; i < a; ++i) + for (int j = 0; j < b; ++j) + f (x[i][j]); + delete [] x; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/parse-ambig5.C b/gcc/testsuite/g++.dg/cpp0x/regress/parse-ambig5.C new file mode 100644 index 00000000000..9be2f9258fa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/parse-ambig5.C @@ -0,0 +1,8 @@ +// PR c++/41786 +// { dg-options -std=c++0x } + +struct A { A(int, char const*); }; +int main() { + int i = 0, *b = &i; + A a(int(b[i]), "hello"); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C b/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C index ec686eec456..028669e511e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C +++ b/gcc/testsuite/g++.dg/cpp0x/regress/template-function1.C @@ -4,25 +4,25 @@ template struct A {}; const char func[] = "abc"; -template struct A {}; // { dg-error "cannot appear|is invalid|not a valid" } +template struct A {}; // { dg-error "cannot appear|is invalid|not a valid|not declared constexpr" } char a1[1]; A a; template struct B {}; -template struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } +template struct B<__FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|not declared constexpr" } char b1[1]; B b; template struct C {}; -template struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid" } +template struct C<__PRETTY_FUNCTION__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|not declared constexpr" } char c1[1]; C c; template struct D {}; -template struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|function scope" } +template struct D<__func__, N> {}; // { dg-error "cannot appear|is invalid|is not a valid|function scope|not declared constexpr" } char d1[1]; D d; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic20.C b/gcc/testsuite/g++.dg/cpp0x/variadic20.C index 06204c75dd5..7f2446e5585 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic20.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic20.C @@ -37,9 +37,9 @@ struct metatuple { // { dg-error "struct" } int a0[metatuple<>::value == 0? 1 : -1]; int a1[metatuple::value == 1? 1 : -1]; -int a2a[metatuple::value == 2? 1 : -1]; // { dg-error "ambiguous" } +int a2a[metatuple::value == 2? 1 : -1]; // { dg-error "ambiguous|array bound" } int a2b[metatuple::value == 2? 1 : -1]; -int a3[metatuple::value == 3? 1 : -1]; // { dg-error "ambiguous" } +int a3[metatuple::value == 3? 1 : -1]; // { dg-error "ambiguous|array bound" } int a4[metatuple::value == 4? 1 : -1]; int a5[metatuple::value == 5? 1 : -1]; -- 2.30.2