From f9f3b77cf5290a8417cfc450b936039c78f6618b Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 11 Oct 2018 15:46:27 +0200 Subject: [PATCH] re PR c++/87582 (Returning a reference to a data member via structured bindings dangles) PR c++/87582 * typeck.c (maybe_warn_about_returning_address_of_local): If whats_returned is a structured binding identifier and the structured binding is a reference, recurse on its initializer. * g++.dg/cpp1z/decomp48.C: New test. From-SVN: r265041 --- gcc/cp/ChangeLog | 5 + gcc/cp/typeck.c | 16 +++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/cpp1z/decomp48.C | 134 ++++++++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp48.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0ac28f934d9..9ec7c8b861c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2018-10-11 Jakub Jelinek + PR c++/87582 + * typeck.c (maybe_warn_about_returning_address_of_local): If + whats_returned is a structured binding identifier and the structured + binding is a reference, recurse on its initializer. + PR c++/87547 * rtti.c (get_tinfo_decl_dynamic): Use unlowered_expr_type instead of TREE_TYPE. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e9932202b46..8f819592533 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -9096,6 +9096,22 @@ maybe_warn_about_returning_address_of_local (tree retval) && !(TREE_STATIC (whats_returned) || TREE_PUBLIC (whats_returned))) { + if (VAR_P (whats_returned) + && DECL_DECOMPOSITION_P (whats_returned) + && DECL_DECOMP_BASE (whats_returned) + && DECL_HAS_VALUE_EXPR_P (whats_returned)) + { + /* When returning address of a structured binding, if the structured + binding is not a reference, continue normally, if it is a + reference, recurse on the initializer of the structured + binding. */ + tree base = DECL_DECOMP_BASE (whats_returned); + if (TYPE_REF_P (TREE_TYPE (base))) + { + tree init = DECL_INITIAL (base); + return maybe_warn_about_returning_address_of_local (init); + } + } bool w = false; auto_diagnostic_group d; if (TYPE_REF_P (valtype)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3588376437b..333ec99bd67 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-10-11 Jakub Jelinek + + PR c++/87582 + * g++.dg/cpp1z/decomp48.C: New test. + 2018-10-11 David Malcolm * g++.dg/diagnostic/macro-arg-count.C: Move to... diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp48.C b/gcc/testsuite/g++.dg/cpp1z/decomp48.C new file mode 100644 index 00000000000..35413c79a9d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp48.C @@ -0,0 +1,134 @@ +// PR c++/87582 +// { dg-do run { target c++11 } } +// { dg-options "-Wreturn-local-addr" } + +struct S { int s, t; }; +S v {1, 2}; +int a[3] = {1, 2, 3}; + +int & +f1 () +{ + auto& [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-bogus "reference to local variable '.' returned" } +} + +int & +f2 () +{ + S v {1, 2}; + auto& [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-warning "reference to local variable 'v' returned" } +} + +int & +f3 () +{ + auto& [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-bogus "reference to local variable '.' returned" } +} + +int & +f4 () +{ + int a[3] = {1, 2, 3}; + auto& [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-warning "reference to local variable 'a' returned" } +} + +int & +f5 () +{ + auto [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-warning "reference to local variable 's' returned" } +} + +int & +f6 () +{ + S v {1, 2}; + auto [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-warning "reference to local variable 's' returned" } +} + +int & +f7 () +{ + auto [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-warning "reference to local variable 's' returned" } +} + +int & +f8 () +{ + int a[3] = {1, 2, 3}; + auto [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return s; // { dg-warning "reference to local variable 's' returned" } +} + +int * +f9 () +{ + auto& [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-bogus "address of local variable '.' returned" } +} + +int * +f10 () +{ + S v {1, 2}; + auto& [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-warning "address of local variable 'v' returned" } +} + +int * +f11 () +{ + auto& [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-bogus "address of local variable '.' returned" } +} + +int * +f12 () +{ + int a[3] = {1, 2, 3}; + auto& [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-warning "address of local variable 'a' returned" } +} + +int * +f13 () +{ + auto [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-warning "address of local variable 's' returned" } +} + +int * +f14 () +{ + S v {1, 2}; + auto [s, t] = v; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-warning "address of local variable 's' returned" } +} + +int * +f15 () +{ + auto [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-warning "address of local variable 's' returned" } +} + +int * +f16 () +{ + int a[3] = {1, 2, 3}; + auto [s, t, u] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + return &s; // { dg-warning "address of local variable 's' returned" } +} + +int +main () +{ + if (&f1 () != &v.s || &f3 () != &a[0] || f9 () != &v.s || f11 () != &a[0]) + __builtin_abort (); +} -- 2.30.2