From da7d921819a3e2ba17fd01d93fedf1cd4e2a5819 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 22 Jun 2011 00:18:02 -0400 Subject: [PATCH] re PR c++/49172 ([C++0x][constexpr] References should be declarable with constexpr) PR c++/49172 * decl.c (cp_finish_decl): Adjust init_const_expr_p for refs. (grokdeclarator): constexpr doesn't apply const for refs. * parser.c (cp_parser_initializer_clause): Don't call maybe_constant_value here. * call.c (initialize_reference): Handle constexpr. From-SVN: r175284 --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/call.c | 16 ++++++-- gcc/cp/decl.c | 12 +++++- gcc/cp/parser.c | 10 ----- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C | 2 +- gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C | 44 +++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C | 17 ++++++++ 8 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cf325fc7926..a329733f4e4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2011-06-21 Jason Merrill + PR c++/49172 + * decl.c (cp_finish_decl): Adjust init_const_expr_p for refs. + (grokdeclarator): constexpr doesn't apply const for refs. + * parser.c (cp_parser_initializer_clause): Don't call + maybe_constant_value here. + * call.c (initialize_reference): Handle constexpr. + PR c++/49482 * semantics.c (maybe_add_lambda_conv_op): Call mark_exp_read for static fn parameters. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 8123e3dd252..dd4dced8d72 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8629,6 +8629,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup, tree var; tree base_conv_type; + gcc_assert (complain == tf_warning_or_error); + /* Skip over the REF_BIND. */ conv = conv->u.next; /* If the next conversion is a BASE_CONV, skip that too -- but @@ -8646,7 +8648,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup, /*inner=*/-1, /*issue_conversion_warnings=*/true, /*c_cast_p=*/false, - tf_warning_or_error); + complain); if (error_operand_p (expr)) expr = error_mark_node; else @@ -8667,18 +8669,24 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup, } else /* Take the address of EXPR. */ - expr = cp_build_addr_expr (expr, tf_warning_or_error); + expr = cp_build_addr_expr (expr, complain); /* If a BASE_CONV was required, perform it now. */ if (base_conv_type) expr = (perform_implicit_conversion (build_pointer_type (base_conv_type), expr, - tf_warning_or_error)); + complain)); expr = build_nop (type, expr); + if (DECL_DECLARED_CONSTEXPR_P (decl)) + { + expr = cxx_constant_value (expr); + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) + = reduced_constant_expression_p (expr); + } } } else /* Perform the conversion. */ - expr = convert_like (conv, expr, tf_warning_or_error); + expr = convert_like (conv, expr, complain); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 263ab3fdafe..b8435a6ddaa 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5987,6 +5987,11 @@ 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; + /* If DECL is a reference, then we want to know whether init is a + reference constant; init_const_expr_p as passed tells us whether + it's an rvalue constant. */ + if (TREE_CODE (type) == REFERENCE_TYPE) + init_const_expr_p = potential_constant_expression (init); if (init_const_expr_p) { /* Set these flags now for templates. We'll update the flags in @@ -9333,8 +9338,11 @@ grokdeclarator (const cp_declarator *declarator, error ("both % and % cannot be used here"); if (type_quals & TYPE_QUAL_VOLATILE) error ("both % and % cannot be used here"); - type_quals |= TYPE_QUAL_CONST; - type = cp_build_qualified_type (type, type_quals); + if (TREE_CODE (type) != REFERENCE_TYPE) + { + type_quals |= TYPE_QUAL_CONST; + type = cp_build_qualified_type (type, type_quals); + } } if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 856a8a7b67c..f1b79761b8c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -16532,16 +16532,6 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/true, non_constant_p); - if (!*non_constant_p) - { - /* We only want to fold if this is really a constant - expression. FIXME Actually, we don't want to fold here, but in - cp_finish_decl. */ - tree folded = fold_non_dependent_expr (initializer); - folded = maybe_constant_value (folded); - if (TREE_CONSTANT (folded)) - initializer = folded; - } } else initializer = cp_parser_braced_list (parser, non_constant_p); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 59464fa2703..fae9f953566 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2011-06-21 Jason Merrill + PR c++/49172 + * g++.dg/cpp0x/constexpr-ref1.C: New. + * g++.dg/cpp0x/constexpr-ref2.C: New. + * g++.dg/cpp0x/constexpr-ice2.C: Remove dg-error tag. + PR c++/49482 * g++.dg/cpp0x/lambda/lambda-warn3.C: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C index 35643b990c1..856246fcc95 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C @@ -1,3 +1,3 @@ // { dg-options -std=c++0x } int x; -constexpr int& rx = x; // { dg-error "int&" } +constexpr int& rx = x; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C new file mode 100644 index 00000000000..482e1ba3691 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C @@ -0,0 +1,44 @@ +// PR c++/49172 +// { dg-options -std=c++0x } + +#define SA(X) static_assert((X),#X) + +constexpr int g() { return 42; }; +constexpr int(&rg)() = g; // #1 + +SA(rg() == 42); + +constexpr int i = 24; +constexpr int const& ri = i; // #2 + +SA(&ri == &i); +SA(ri == 24); + +void f() +{ + constexpr int(&rg)() = g; // #1 + + SA(rg() == 42); + + constexpr static int i = 24; + constexpr int const& ri = i; // #2 + + SA(&ri == &i); + SA(ri == 24); +} + +template +void f2() +{ + constexpr int(&rg)() = g; // #1 + + SA(rg() == 42); + + constexpr static int i = 24; + constexpr int const& ri = i; // #2 + + SA(&ri == &i); + SA(ri == 24); +} + +template void f2(); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C new file mode 100644 index 00000000000..2a86eb765cb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C @@ -0,0 +1,17 @@ +// Negative reference variable tests. +// { dg-options -std=c++0x } + +extern int *p; +constexpr int& ri = *p; // { dg-error "p" } + +extern constexpr int &er; // { dg-error "not a definition" } +constexpr int& ri2 = er; // { dg-error "er" } + +void f(int j) +{ + constexpr int i = 42; + constexpr int const& ri = i; // { dg-error "" } + + constexpr int& rj = j; // { dg-error "" } +} + -- 2.30.2