From fd338b13644908314b288c10dc2fb46b72aeb300 Mon Sep 17 00:00:00 2001
From: Jason Merrill <jason@redhat.com>
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 e9dd17c5d36a..e8de0c9c9914 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 e8c7702dede7..40d1e7be7825 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 9b9b51135aaf..5b5c0bef1184 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 4ebc7dca8d64..257d21133c15 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 fe1f75110b8e..7bf07c341622 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 1fad79cb247b..b4b6cdb0a4c6 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 000000000000..925ac4eb2e44
--- /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 000000000000..97f88fefc6e8
--- /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], "");
+}
-- 
GitLab