commit:     ba1c1c9ab955b533393e343bdfd8a0e7d7650639
Author:     Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
AuthorDate: Sun Dec 22 00:04:55 2019 +0000
Commit:     Sergei Trofimovich <slyfox <AT> gentoo <DOT> org>
CommitDate: Sun Dec 22 00:04:55 2019 +0000
URL:        https://gitweb.gentoo.org/proj/gcc-patches.git/commit/?id=ba1c1c9a

9.2.0: backport PR92831 (':?' lifetime extension)

It's a backport of upstream commit 59693b226e245aeb99.

Bug: https://gcc.gnu.org/PR92831
Bug: https://bugs.gentoo.org/701866
Signed-off-by: Sergei Trofimovich <slyfox <AT> gentoo.org>

 9.2.0/gentoo/33_all_extend-lifetime.patch | 240 ++++++++++++++++++++++++++++++
 9.2.0/gentoo/README.history               |   1 +
 2 files changed, 241 insertions(+)

diff --git a/9.2.0/gentoo/33_all_extend-lifetime.patch 
b/9.2.0/gentoo/33_all_extend-lifetime.patch
new file mode 100644
index 0000000..520d491
--- /dev/null
+++ b/9.2.0/gentoo/33_all_extend-lifetime.patch
@@ -0,0 +1,240 @@
+https://github.com/gcc-mirror/gcc/commit/59693b226e245aeb991ab2275a9c37d35da1191b.patch
+https://bugs.gentoo.org/701866
+
+From 59693b226e245aeb991ab2275a9c37d35da1191b Mon Sep 17 00:00:00 2001
+From: jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Fri, 20 Dec 2019 17:37:45 +0000
+Subject: [PATCH]       Backported from mainline        2019-12-06  Jakub
+ Jelinek  <[email protected]>
+
+       PR c++/92831 - CWG 1299, not extending temporary lifetime for ?:
+       * cp-tree.h (extend_ref_init_temps): Add a new argument with NULL
+       default arg.
+       * call.c (set_up_extended_ref_temp): Add COND_GUARD argument, pass it
+       down to extend_ref_init_temps.  Before pushing cleanup, if COND_GUARD
+       is non-NULL, create a bool temporary if needed, initialize to false
+       and guard the cleanup with the temporary being true.
+       (extend_ref_init_temps_1): Add COND_GUARD argument, pass it down
+       to recursive calls and set_up_extended_ref_temp.  Handle COND_EXPR.
+       (extend_ref_init_temps): Add COND_GUARD argument, pass it down to
+       recursive calls and to extend_ref_init_temps_1.
+
+       * g++.dg/cpp0x/temp-extend2.C: New test.
+
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-9-branch@279669 
138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/cp/call.c                             | 83 +++++++++++++++++++----
+ gcc/cp/cp-tree.h                          |  4 +-
+ gcc/testsuite/g++.dg/cpp0x/temp-extend2.C | 36 ++++++++++
+ 5 files changed, 129 insertions(+), 13 deletions(-)
+ create mode 100644 gcc/testsuite/g++.dg/cpp0x/temp-extend2.C
+
+--- a/gcc/cp/call.c
++++ b/gcc/cp/call.c
+@@ -11449,7 +11449,7 @@ make_temporary_var_for_ref_to_temp (tree decl, tree 
type)
+ 
+ static tree
+ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
+-                        tree *initp)
++                        tree *initp, tree *cond_guard)
+ {
+   tree init;
+   tree type;
+@@ -11480,7 +11480,8 @@ set_up_extended_ref_temp (tree decl, tree expr, 
vec<tree, va_gc> **cleanups,
+ 
+   /* Recursively extend temps in this initializer.  */
+   TARGET_EXPR_INITIAL (expr)
+-    = extend_ref_init_temps (decl, TARGET_EXPR_INITIAL (expr), cleanups);
++    = extend_ref_init_temps (decl, TARGET_EXPR_INITIAL (expr), cleanups,
++                           cond_guard);
+ 
+   /* Any reference temp has a non-trivial initializer.  */
+   DECL_NONTRIVIALLY_INITIALIZED_P (var) = true;
+@@ -11521,7 +11522,29 @@ set_up_extended_ref_temp (tree decl, tree expr, 
vec<tree, va_gc> **cleanups,
+       {
+         tree cleanup = cxx_maybe_build_cleanup (var, tf_warning_or_error);
+         if (cleanup)
+-          vec_safe_push (*cleanups, cleanup);
++          {
++            if (cond_guard && cleanup != error_mark_node)
++              {
++                if (*cond_guard == NULL_TREE)
++                  {
++                    *cond_guard = build_decl (input_location, VAR_DECL,
++                                              NULL_TREE, boolean_type_node);
++                    DECL_ARTIFICIAL (*cond_guard) = 1;
++                    DECL_IGNORED_P (*cond_guard) = 1;
++                    DECL_CONTEXT (*cond_guard) = current_function_decl;
++                    layout_decl (*cond_guard, 0);
++                    add_decl_expr (*cond_guard);
++                    tree set = cp_build_modify_expr (UNKNOWN_LOCATION,
++                                                     *cond_guard, NOP_EXPR,
++                                                     boolean_false_node,
++                                                     tf_warning_or_error);
++                    finish_expr_stmt (set);
++                  }
++                cleanup = build3 (COND_EXPR, void_type_node,
++                                  *cond_guard, cleanup, NULL_TREE);
++              }
++            vec_safe_push (*cleanups, cleanup);
++          }
+       }
+ 
+       /* We must be careful to destroy the temporary only
+@@ -11626,7 +11649,8 @@ initialize_reference (tree type, tree expr,
+    which is bound either to a reference or a std::initializer_list.  */
+ 
+ static tree
+-extend_ref_init_temps_1 (tree decl, tree init, vec<tree, va_gc> **cleanups)
++extend_ref_init_temps_1 (tree decl, tree init, vec<tree, va_gc> **cleanups,
++                       tree *cond_guard)
+ {
+   tree sub = init;
+   tree *p;
+@@ -11634,20 +11658,52 @@ extend_ref_init_temps_1 (tree decl, tree init, 
vec<tree, va_gc> **cleanups)
+   if (TREE_CODE (sub) == COMPOUND_EXPR)
+     {
+       TREE_OPERAND (sub, 1)
+-        = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups);
++      = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups,
++                                 cond_guard);
++      return init;
++    }
++  if (TREE_CODE (sub) == COND_EXPR)
++    {
++      tree cur_cond_guard = NULL_TREE;
++      if (TREE_OPERAND (sub, 1))
++      TREE_OPERAND (sub, 1)
++        = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups,
++                                   &cur_cond_guard);
++      if (cur_cond_guard)
++      {
++        tree set = cp_build_modify_expr (UNKNOWN_LOCATION, cur_cond_guard,
++                                         NOP_EXPR, boolean_true_node,
++                                         tf_warning_or_error);
++        TREE_OPERAND (sub, 1)
++          = cp_build_compound_expr (set, TREE_OPERAND (sub, 1),
++                                    tf_warning_or_error);
++      }
++      cur_cond_guard = NULL_TREE;
++      if (TREE_OPERAND (sub, 2))
++      TREE_OPERAND (sub, 2)
++        = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 2), cleanups,
++                                   &cur_cond_guard);
++      if (cur_cond_guard)
++      {
++        tree set = cp_build_modify_expr (UNKNOWN_LOCATION, cur_cond_guard,
++                                         NOP_EXPR, boolean_true_node,
++                                         tf_warning_or_error);
++        TREE_OPERAND (sub, 2)
++          = cp_build_compound_expr (set, TREE_OPERAND (sub, 2),
++                                    tf_warning_or_error);
++      }
+       return init;
+     }
+   if (TREE_CODE (sub) != ADDR_EXPR)
+     return init;
+   /* Deal with binding to a subobject.  */
+   for (p = &TREE_OPERAND (sub, 0);
+-       (TREE_CODE (*p) == COMPONENT_REF
+-      || TREE_CODE (*p) == ARRAY_REF); )
++       TREE_CODE (*p) == COMPONENT_REF || TREE_CODE (*p) == ARRAY_REF; )
+     p = &TREE_OPERAND (*p, 0);
+   if (TREE_CODE (*p) == TARGET_EXPR)
+     {
+       tree subinit = NULL_TREE;
+-      *p = set_up_extended_ref_temp (decl, *p, cleanups, &subinit);
++      *p = set_up_extended_ref_temp (decl, *p, cleanups, &subinit, 
cond_guard);
+       recompute_tree_invariant_for_addr_expr (sub);
+       if (init != sub)
+       init = fold_convert (TREE_TYPE (init), sub);
+@@ -11662,13 +11718,14 @@ extend_ref_init_temps_1 (tree decl, tree init, 
vec<tree, va_gc> **cleanups)
+    lifetime to match that of DECL.  */
+ 
+ tree
+-extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups)
++extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups,
++                     tree *cond_guard)
+ {
+   tree type = TREE_TYPE (init);
+   if (processing_template_decl)
+     return init;
+   if (TYPE_REF_P (type))
+-    init = extend_ref_init_temps_1 (decl, init, cleanups);
++    init = extend_ref_init_temps_1 (decl, init, cleanups, cond_guard);
+   else
+     {
+       tree ctor = init;
+@@ -11681,7 +11738,8 @@ extend_ref_init_temps (tree decl, tree init, vec<tree, 
va_gc> **cleanups)
+             /* The temporary array underlying a std::initializer_list
+                is handled like a reference temporary.  */
+             tree array = CONSTRUCTOR_ELT (ctor, 0)->value;
+-            array = extend_ref_init_temps_1 (decl, array, cleanups);
++            array = extend_ref_init_temps_1 (decl, array, cleanups,
++                                             cond_guard);
+             CONSTRUCTOR_ELT (ctor, 0)->value = array;
+           }
+         else
+@@ -11690,7 +11748,8 @@ extend_ref_init_temps (tree decl, tree init, vec<tree, 
va_gc> **cleanups)
+             constructor_elt *p;
+             vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
+             FOR_EACH_VEC_SAFE_ELT (elts, i, p)
+-              p->value = extend_ref_init_temps (decl, p->value, cleanups);
++              p->value = extend_ref_init_temps (decl, p->value, cleanups,
++                                                cond_guard);
+           }
+         recompute_constructor_flags (ctor);
+         if (decl_maybe_constant_var_p (decl) && TREE_CONSTANT (ctor))
+--- a/gcc/cp/cp-tree.h
++++ b/gcc/cp/cp-tree.h
+@@ -6229,7 +6229,9 @@ extern tree convert_for_arg_passing              (tree, 
tree, tsubst_flags_t);
+ extern bool is_properly_derived_from          (tree, tree);
+ extern tree initialize_reference              (tree, tree, int,
+                                                tsubst_flags_t);
+-extern tree extend_ref_init_temps             (tree, tree, vec<tree, 
va_gc>**);
++extern tree extend_ref_init_temps             (tree, tree,
++                                               vec<tree, va_gc>**,
++                                               tree * = NULL);
+ extern tree make_temporary_var_for_ref_to_temp        (tree, tree);
+ extern bool type_has_extended_temps           (tree);
+ extern tree strip_top_quals                   (tree);
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/cpp0x/temp-extend2.C
+@@ -0,0 +1,36 @@
++// PR c++/92831
++// { dg-do run { target c++11 } }
++
++template<typename T> using id = T;
++struct S { S () { s++; } ~S () { s--; } S (int) { s++; } static int s; };
++int S::s = 0;
++
++void
++bar (bool cond, bool cond2)
++{
++  if (S::s != (cond ? cond2 ? 7 : 5 : cond2 ? 8 : 9))
++    __builtin_abort ();
++}
++
++void
++foo (bool cond, bool cond2)
++{
++  int i = 1;
++  // temporary array has same lifetime as a
++  S&& a = id<S[3]>{1, 2, 3}[i];
++  // temporary S has same lifetime as b
++  const S& b = static_cast<const S&>(0);
++  // exactly one of the four temporaries is lifetime-extended
++  S&& c = cond ? cond2 ? id<S[3]>{1, 2, 3}[i] : static_cast<S&&>(0)
++             : cond2 ? id<S[4]>{1, 2, 3, 4}[i] : id<S[5]>{1, 2, 3, 4, 5}[i];
++  bar (cond, cond2);
++}
++
++int
++main ()
++{
++  foo (true, true);
++  foo (true, false);
++  foo (false, true);
++  foo (false, false);
++}

diff --git a/9.2.0/gentoo/README.history b/9.2.0/gentoo/README.history
index 1569eac..3535536 100644
--- a/9.2.0/gentoo/README.history
+++ b/9.2.0/gentoo/README.history
@@ -2,6 +2,7 @@
        + 31_all_openmp-for-SEGV.patch
        + 27_all_sparc-PIC-constant-PR91472.patch
        + 32_all_sparc-PIC-constant-part2.patch
+       + 33_all_extend-lifetime.patch
 
 3              04 Nov 2019
        + 30_all_arm64-march-native.patch

Reply via email to