The standard says that references that refer to a constant address can
be used in a constant-expression, but we haven't allowed that.  This
patch implements it, but without the parser.c hunk it broke
libgomp.c++/target-14.C.

Apparently the target mapping wants to use 't' in a way that doesn't
actually refer to x?  This seems like a strange use of references.
But if this is the desired behavior, does the parser.c patch seem like
a good way to prevent the compiler from replacing 't' with 'x' within
the openmp block?

Tested x86_64-pc-linux-gnu.
commit 93b5c38cb70b9c1e52a143415da76218583242d2
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Nov 14 14:15:57 2016 -0500

            * decl2.c (decl_maybe_constant_var_p): References qualify.
            * init.c (constant_value_1): Always check decl_constant_var_p.
            * parser.c (cp_parser_omp_var_list_no_open): Clear
            DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P on variables in OpenMP
            clauses.

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 4ebc7dc..3952600 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4127,7 +4127,7 @@ decl_constant_var_p (tree decl)
      constant until its initializer is complete in case it's used in
      its own initializer.  */
   maybe_instantiate_decl (decl);
-  return DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
+  return TREE_CONSTANT (decl);
 }
 
 /* Returns true if DECL could be a symbolic constant variable, depending on
@@ -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/cp/parser.c b/gcc/cp/parser.c
index 9360ab0..8869c46 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -30743,6 +30743,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum 
omp_clause_code kind,
            goto skip_comma;
 
          decl = cp_parser_lookup_name_simple (parser, name, token->location);
+         if (VAR_P (decl))
+           /* Make decl_constant_var_p false for OpenMP variables.  */
+           TREE_CONSTANT (decl) = false;
          if (decl == error_mark_node)
            cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
                                         token->location);
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], "");
+}

Reply via email to