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