PR c++/85873 - constant initializer_list array not in .rodata.
authorJason Merrill <jason@redhat.com>
Wed, 30 May 2018 17:33:06 +0000 (13:33 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 30 May 2018 17:33:06 +0000 (13:33 -0400)
* tree.c (build_target_expr): Set TREE_READONLY.
* call.c (set_up_extended_ref_temp): Set TREE_READONLY.

From-SVN: r260969

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/tree-ssa/array-temp1.C [new file with mode: 0644]

index 07fbafa..2999fc3 100644 (file)
@@ -1,5 +1,9 @@
 2018-05-30  Jason Merrill  <jason@redhat.com>
 
+       PR c++/85873 - constant initializer_list array not in .rodata.
+       * tree.c (build_target_expr): Set TREE_READONLY.
+       * call.c (set_up_extended_ref_temp): Set TREE_READONLY.
+
        * parser.c (cp_parser_check_condition_declarator): Handle
        cp_error_declarator.
 
index 2bbf983..67e404d 100644 (file)
@@ -10923,13 +10923,11 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
             lvalue-rvalue conversion applied to "a glvalue of literal type
             that refers to a non-volatile temporary object initialized
             with a constant expression".  Rather than try to communicate
-            that this VAR_DECL is a temporary, just mark it constexpr.
-
-            Currently this is only useful for initializer_list temporaries,
-            since reference vars can't appear in constant expressions.  */
+            that this VAR_DECL is a temporary, just mark it constexpr.  */
          DECL_DECLARED_CONSTEXPR_P (var) = true;
          DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (var) = true;
          TREE_CONSTANT (var) = true;
+         TREE_READONLY (var) = true;
        }
       DECL_INITIAL (var) = init;
       init = NULL_TREE;
index f21daac..53bc9c7 100644 (file)
@@ -461,6 +461,14 @@ build_target_expr (tree decl, tree value, tsubst_flags_t complain)
                       || useless_type_conversion_p (TREE_TYPE (decl),
                                                     TREE_TYPE (value)));
 
+  /* Set TREE_READONLY for optimization, such as gimplify_init_constructor
+     moving a constant aggregate into .rodata.  */
+  if (CP_TYPE_CONST_NON_VOLATILE_P (type)
+      && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+      && !VOID_TYPE_P (TREE_TYPE (value))
+      && reduced_constant_expression_p (value))
+    TREE_READONLY (decl) = true;
+
   if (complain & tf_no_cleanup)
     /* The caller is building a new-expr and does not need a cleanup.  */
     t = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/tree-ssa/array-temp1.C b/gcc/testsuite/g++.dg/tree-ssa/array-temp1.C
new file mode 100644 (file)
index 0000000..97c2e05
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/85873
+// Test that these array temporaries are promoted to static variables as an
+// optimization.
+
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump-not "= 42" "gimple" } }
+
+#include <initializer_list>
+
+int f()
+{
+  using AR = const int[];
+  return AR{ 1,42,3,4,5,6,7,8,9,0 }[5];
+}
+
+int g()
+{
+  std::initializer_list<int> a = {1,42,3};
+  return a.begin()[0];
+}