https://gcc.gnu.org/g:08bfa32ae92e36a791ebdefd063b4f2616cd6f80

commit r14-11297-g08bfa32ae92e36a791ebdefd063b4f2616cd6f80
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Feb 7 17:08:39 2025 +0100

    c++: Fix up name independent decl in structured binding handling in range 
for [PR115586]
    
    cp_parser_range_for temporarily reverts IDENTIFIER_BINDING changes
    to hide the decls from the structured bindings from lookup during
    parsing of the expression after :
    If there are 2 or more name independent decls, we undo IDENTIFIER_BINDING
    for the same name multiple times, even when just one has been added
    (with a TREE_LIST inside of it as decl).
    
    The following patch fixes it by handling the _ name at most once, the
    later loop will DTRT then and just reinstall the temporarily hidden
    binding with the TREE_LIST in there.
    
    2025-02-07  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/115586
            * parser.cc (cp_parser_range_for): For name independent decls in
            structured bindings, only push the name/binding once per
            structured binding.
    
            * g++.dg/cpp26/name-independent-decl9.C: New test.
            * g++.dg/cpp26/name-independent-decl10.C: New test.
    
    (cherry picked from commit ca7c6d1212b8589deed18386427c67851af2b9ad)

Diff:
---
 gcc/cp/parser.cc                                   | 10 ++++
 .../g++.dg/cpp26/name-independent-decl10.C         | 63 ++++++++++++++++++++++
 .../g++.dg/cpp26/name-independent-decl9.C          | 49 +++++++++++++++++
 3 files changed, 122 insertions(+)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 5bfbdf85f152..aeb36d1e4831 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -14130,9 +14130,19 @@ cp_parser_range_for (cp_parser *parser, tree scope, 
tree init, tree range_decl,
              decomp = &decomp_d;
              decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
              decomp->decl = d;
+             bool seen_name_independent_decl = false;
              for (unsigned int i = 0; i < decomp->count;
                   i++, d = DECL_CHAIN (d))
                {
+                 if (name_independent_decl_p (d))
+                   {
+                     /* If there is more than one _ decl in
+                        the structured binding, just push and move it
+                        away once.  */
+                     if (seen_name_independent_decl)
+                       continue;
+                     seen_name_independent_decl = true;
+                   }
                  tree name = DECL_NAME (d);
                  names.safe_push (name);
                  bindings.safe_push (IDENTIFIER_BINDING (name));
diff --git a/gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C 
b/gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C
new file mode 100644
index 000000000000..792c2bd0c6b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/name-independent-decl10.C
@@ -0,0 +1,63 @@
+// PR c++/115586
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct S { int a, b, c; };
+
+void
+foo ()
+{
+  S s[4] = {};
+  for (auto [_, _, a] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    ++_;                       // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+                               // { dg-error "reference to '_' is ambiguous" 
"" { target *-*-* } .-1 }
+  for (auto _ : s)
+    ++_.b;
+  for (auto [a, _, b] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    ++_;
+  for (auto [_, _, a] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    {                          // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+      ++_;                     // { dg-error "reference to '_' is ambiguous" }
+    }
+  for (auto _ : s)
+    {
+      ++_.b;
+      int _ = 2;               // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+      ++_;                     // { dg-error "reference to '_' is ambiguous" }
+    }
+  for (auto [a, _, b] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    {
+      ++_;
+      int _ = ++b;             // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+      ++_;                     // { dg-error "reference to '_' is ambiguous" }
+    }
+}
+
+void
+bar ()
+{
+  S s[4] = {};
+  auto [_, c, _] = s[0];       // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+  ++_;                         // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+                               // { dg-error "reference to '_' is ambiguous" 
"" { target *-*-* } .-1 }
+  for (auto [a, _, _] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    ++_;                       // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+                               // { dg-error "reference to '_' is ambiguous" 
"" { target *-*-* } .-1 }
+  for (auto _ : s)
+    ++_.c;
+  for (auto [a, b, _] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    ++_;
+  for (auto [a, _, _] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    {                          // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+      ++_;                     // { dg-error "reference to '_' is ambiguous" }
+      ++a;
+    }
+  for (auto _ : s)
+    int _ = 5;                 // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+  for (auto [a, b, _] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    {
+      ++_;
+      int _ = a + b;           // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+      ++_;                     // { dg-error "reference to '_' is ambiguous" }
+    }
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C 
b/gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C
new file mode 100644
index 000000000000..0a8ef0405970
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/name-independent-decl9.C
@@ -0,0 +1,49 @@
+// PR c++/115586
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wunused-variable -Wunused-but-set-variable 
-Wunused-parameter -Wshadow" }
+
+struct S { int a, b, c; };
+
+void
+foo ()
+{
+  S s[4] = {};
+  for (auto [_, _, a] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    ++a;                       // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+  for (auto _ : s)
+    ++_.b;
+  for (auto [a, _, b] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    ++a;
+  for (auto [_, _, a] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    int _ = ++a;               // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+  for (auto _ : s)
+    {
+      int _ = 2;               // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    }
+  for (auto [a, _, b] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    int _ = ++b;               // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+}
+
+void
+bar ()
+{
+  S s[4] = {};
+  auto [_, c, _] = s[0];       // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+  ++c;                         // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+  for (auto [a, _, _] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    ++a;                       // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+  for (auto _ : s)
+    ++_.c;
+  for (auto [a, b, _] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    ++b;
+  for (auto [a, _, _] : s)     // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    {                          // { dg-warning "structured bindings only 
available with" "" { target c++14_down } .-1 }
+      int _ = ++a;
+    }
+  for (auto _ : s)
+    int _ = 5;                 // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+  for (auto [a, b, _] : s)     // { dg-warning "structured bindings only 
available with" "" { target c++14_down } }
+    {
+      int _ = a + b;           // { dg-warning "name-independent declarations 
only available with" "" { target c++23_down } }
+    }
+}

Reply via email to