On Tue, Oct 15, 2019 at 01:17:17PM -0400, Marek Polacek wrote:
> 2019-10-15  Marek Polacek  <pola...@redhat.com>
> 
>       PR c++/92106 - ICE with structured bindings and -Wreturn-local-addr.
>       * typeck.c (maybe_warn_about_returning_address_of_local): Avoid
>       recursing on null initializer.
> 
>       * g++.dg/cpp1z/decomp50.C: New test.
> 
> diff --git gcc/cp/typeck.c gcc/cp/typeck.c
> index 141d86f50c9..1825540016f 100644
> --- gcc/cp/typeck.c
> +++ gcc/cp/typeck.c
> @@ -9354,10 +9354,8 @@ maybe_warn_about_returning_address_of_local (tree 
> retval)
>            binding.  */
>         tree base = DECL_DECOMP_BASE (whats_returned);
>         if (TYPE_REF_P (TREE_TYPE (base)))
> -         {
> -           tree init = DECL_INITIAL (base);
> +         if (tree init = DECL_INITIAL (base))
>             return maybe_warn_about_returning_address_of_local (init);
> -         }

Actually, seeing the dg-warning in the testcase, I think we shouldn't warn,
for range-for it is just too hard to find out if it will be returning
address of a local or not. &value in itself is not address of a local
variable when the structured binding is a reference.
Well, in the testcase as is it actually is (perhaps just in the reduced
one and not original):
    const struct J & D.2293;
    const int name [value-expr: D.2293->name];
    const int value [value-expr: D.2293->value];
...
          struct reference D.2352;

          try
            {
              D.2352 = D<A::J*, int>::operator* (&__for_begin);
              D.2293 = &D.2352;
but a small change to the testcase:
 template <typename _Iterator, typename> class D {
 public:
-  typename B<_Iterator>::reference operator*();
+  typename B<_Iterator>::reference &operator*();
   void operator++();
 };
results in D.2293 = D<A::J*, int>::operator* (&__for_begin);
and then it might very well not be address of a local variable.

This isn't just about a false positive warning, when
maybe_warn_about_returning_address_of_local returns true, then
we actually return NULL pointer instead of the value user wanted.

So, I think you want to add and do else return false;
if init is NULL.

> +    for (const auto &[name, value] : members)
> +      return &value; // { dg-warning "address of local variable" }
> +    return nullptr;
> +  }
> +};
> +int main() {
> +  A a;
> +  a.find("");
> +}

        Jakub

Reply via email to