From fd338b13644908314b288c10dc2fb46b72aeb300 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 15 Nov 2016 09:55:52 -0500 Subject: [PATCH] Allow references in constant-expressions. * decl2.c (decl_maybe_constant_var_p): References qualify. * constexpr.c (non_const_var_error): Handle references. * init.c (constant_value_1): Always check decl_constant_var_p. * cp-gimplify.c (cp_fold_maybe_rvalue): Don't fold references. * error.c (dump_decl_name): Split out from dump_decl. From-SVN: r242422 --- gcc/cp/ChangeLog | 8 ++++ gcc/cp/constexpr.c | 4 ++ gcc/cp/cp-gimplify.c | 3 +- gcc/cp/decl2.c | 3 ++ gcc/cp/error.c | 46 ++++++++++++++------ gcc/cp/init.c | 7 ++- gcc/testsuite/g++.dg/cpp0x/constexpr-ref10.C | 5 +++ gcc/testsuite/g++.dg/cpp0x/constexpr-ref9.C | 9 ++++ 8 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ref10.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ref9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e9dd17c5d36..e8de0c9c991 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2016-11-15 Jason Merrill + + * decl2.c (decl_maybe_constant_var_p): References qualify. + * constexpr.c (non_const_var_error): Handle references. + * init.c (constant_value_1): Always check decl_constant_var_p. + * cp-gimplify.c (cp_fold_maybe_rvalue): Don't fold references. + * error.c (dump_decl_name): Split out from dump_decl. + 2016-11-14 Jason Merrill * tree.c (bitfield_p): New. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index e8c7702dede..40d1e7be782 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3153,6 +3153,10 @@ non_const_var_error (tree r) else gcc_unreachable (); } + else if (TREE_CODE (type) == REFERENCE_TYPE) + inform (DECL_SOURCE_LOCATION (r), + "%qD was not initialized with a constant " + "expression", r); else { if (cxx_dialect >= cxx11 && !DECL_DECLARED_CONSTEXPR_P (r)) diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 9b9b51135aa..5b5c0bef118 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1977,7 +1977,8 @@ cp_fold_maybe_rvalue (tree x, bool rval) while (true) { x = cp_fold (x); - if (rval && DECL_P (x)) + if (rval && DECL_P (x) + && TREE_CODE (TREE_TYPE (x)) != REFERENCE_TYPE) { tree v = decl_constant_value (x); if (v != x && v != error_mark_node) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 4ebc7dca8d6..257d21133c1 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4144,6 +4144,9 @@ decl_maybe_constant_var_p (tree decl) if (DECL_HAS_VALUE_EXPR_P (decl)) /* A proxy isn't constant. */ return false; + if (TREE_CODE (type) == REFERENCE_TYPE) + /* References can be constant. */ + return true; return (CP_TYPE_CONST_NON_VOLATILE_P (type) && INTEGRAL_OR_ENUMERATION_TYPE_P (type)); } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index fe1f75110b8..7bf07c34162 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1000,6 +1000,37 @@ dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags) dump_type_suffix (pp, type, flags); } +/* Print an IDENTIFIER_NODE that is the name of a declaration. */ + +static void +dump_decl_name (cxx_pretty_printer *pp, tree t, int flags) +{ + /* These special cases are duplicated here so that other functions + can feed identifiers to error and get them demangled properly. */ + if (IDENTIFIER_TYPENAME_P (t)) + { + pp_cxx_ws_string (pp, "operator"); + /* Not exactly IDENTIFIER_TYPE_VALUE. */ + dump_type (pp, TREE_TYPE (t), flags); + return; + } + if (dguide_name_p (t)) + { + dump_decl (pp, CLASSTYPE_TI_TEMPLATE (TREE_TYPE (t)), + TFF_PLAIN_IDENTIFIER); + return; + } + + const char *str = IDENTIFIER_POINTER (t); + if (!strncmp (str, "_ZGR", 3)) + { + pp_cxx_ws_string (pp, ""); + return; + } + + pp_cxx_tree_identifier (pp, t); +} + /* Dump a human readable string for the decl T under control of FLAGS. */ static void @@ -1155,21 +1186,8 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags) gcc_unreachable (); break; - /* These special cases are duplicated here so that other functions - can feed identifiers to error and get them demangled properly. */ case IDENTIFIER_NODE: - if (IDENTIFIER_TYPENAME_P (t)) - { - pp_cxx_ws_string (pp, "operator"); - /* Not exactly IDENTIFIER_TYPE_VALUE. */ - dump_type (pp, TREE_TYPE (t), flags); - break; - } - else if (dguide_name_p (t)) - dump_decl (pp, CLASSTYPE_TI_TEMPLATE (TREE_TYPE (t)), - TFF_PLAIN_IDENTIFIER); - else - pp_cxx_tree_identifier (pp, t); + dump_decl_name (pp, t, flags); break; case OVERLOAD: diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 1fad79cb247..b4b6cdb0a4c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2078,10 +2078,9 @@ static tree constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p) { while (TREE_CODE (decl) == CONST_DECL - || (strict_p - ? decl_constant_var_p (decl) - : (VAR_P (decl) - && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))))) + || decl_constant_var_p (decl) + || (!strict_p && VAR_P (decl) + && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))) { tree init; /* If DECL is a static data member in a template diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref10.C new file mode 100644 index 00000000000..925ac4eb2e4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref10.C @@ -0,0 +1,5 @@ +// { dg-do compile { target c++11 } } + +int &&r = 42; +static_assert (r, ""); // { dg-error "temporary" } +// { dg-prune-output "assert" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref9.C new file mode 100644 index 00000000000..97f88fefc6e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref9.C @@ -0,0 +1,9 @@ +// { dg-do compile { target c++11 } } + +int a[2] = { 1, 2 }; + +int main() +{ + auto &r = a; + static_assert (&r[0] == &a[0], ""); +} -- 2.30.2