OK.
On Thu, Oct 11, 2018 at 8:52 AM Jakub Jelinek <ja...@redhat.com> wrote:
>
> Hi!
>
> Except for std::tuple* structured bindings, the VAR_DECLs we create for the
> identifiers aren't actually variables, but placeholders with
> DECL_VALUE_EXPR. If the structured binding is not a reference, it is still
> an automatic variable and so -Wreturn-local-addr should warn on those,
> but if it is a reference, then it depends if it references an automatic
> variable or something else.
>
> The following patch handles it by recursing for references on the
> initializer of the structured binding. Note we don't just emit incorrect
> warning without this patch, but the caller replaces return something;
> with return (something, 0); if maybe_warn_about_returning_address_of_local
> returns true, so it is also invalid at runtime.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and
> release branches?
>
> 2018-10-11 Jakub Jelinek <ja...@redhat.com>
>
> 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.
>
> --- gcc/cp/typeck.c.jj 2018-09-13 09:27:31.547765011 +0200
> +++ gcc/cp/typeck.c 2018-10-11 10:06:36.820295475 +0200
> @@ -9096,6 +9096,22 @@ maybe_warn_about_returning_address_of_lo
> && !(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))
> --- gcc/testsuite/g++.dg/cpp1z/decomp48.C.jj 2018-10-11 10:30:09.255651339
> +0200
> +++ gcc/testsuite/g++.dg/cpp1z/decomp48.C 2018-10-11 11:00:23.210283412
> +0200
> @@ -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 ();
> +}
>
> Jakub