aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-11-15 09:55:52 -0500
committerJason Merrill <jason@gcc.gnu.org>2016-11-15 09:55:52 -0500
commitfd338b13644908314b288c10dc2fb46b72aeb300 (patch)
tree4eeb16c9eebc8c51f8f4cf99cc607d14a9907fe6
parentf05a874c256b90e0c45815b657ef0b9682e26189 (diff)
downloadgcc-fd338b13644908314b288c10dc2fb46b72aeb300.zip
gcc-fd338b13644908314b288c10dc2fb46b72aeb300.tar.gz
gcc-fd338b13644908314b288c10dc2fb46b72aeb300.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/constexpr.c4
-rw-r--r--gcc/cp/cp-gimplify.c3
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/cp/error.c46
-rw-r--r--gcc/cp/init.c7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref10.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ref9.C9
8 files changed, 66 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e9dd17c..e8de0c9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2016-11-15 Jason Merrill <jason@redhat.com>
+
+ * 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 <jason@redhat.com>
* tree.c (bitfield_p): New.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index e8c7702..40d1e7b 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 9b9b511..5b5c0be 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 4ebc7dc..257d211 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 fe1f751..7bf07c3 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, "<temporary>");
+ 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 1fad79c..b4b6cdb 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 0000000..925ac4e
--- /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 0000000..97f88fe
--- /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], "");
+}