-Wunused and C++17 structured bindings
authorJason Merrill <jason@redhat.com>
Wed, 24 May 2017 01:46:16 +0000 (21:46 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 24 May 2017 01:46:16 +0000 (21:46 -0400)
* decl.c (poplevel): Don't warn about unused structured bindings,
only real variables.
* error.c (dump_simple_decl): Handle structured bindings.
* expr.c (mark_exp_read): Look through DECL_VALUE_EXPR.

From-SVN: r248399

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/expr.c
gcc/testsuite/g++.dg/cpp1z/decomp29.C [new file with mode: 0644]

index 4a72b655318f4335ef99eb5e78c7f7815a6b9c99..785dfc56fc073a8c6002cbc45fdd056cd1b84e45 100644 (file)
@@ -1,3 +1,11 @@
+2017-05-23  Jason Merrill  <jason@redhat.com>
+
+       -Wunused and C++17 structured bindings
+       * decl.c (poplevel): Don't warn about unused structured bindings,
+       only real variables.
+       * error.c (dump_simple_decl): Handle structured bindings.
+       * expr.c (mark_exp_read): Look through DECL_VALUE_EXPR.
+
 2017-05-23  Nathan Sidwell  <nathan@acm.org>
 
        * cp-tree.h (PUSH_GLOBAL, PUSH_LOCAL, PUSH_USING): Delete.
index 5877f37998e80a6ea7467a9bf3c2f630bafd297f..afd47bbc509c9966941294560b911dd6c6fff0da 100644 (file)
@@ -656,7 +656,10 @@ poplevel (int keep, int reverse, int functionbody)
        if (VAR_P (decl)
            && (! TREE_USED (decl) || !DECL_READ_P (decl))
            && ! DECL_IN_SYSTEM_HEADER (decl)
-           && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)
+           /* For structured bindings, consider only real variables, not
+              subobjects.  */
+           && (DECL_DECOMPOSITION_P (decl) ? !DECL_VALUE_EXPR (decl)
+               : (DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)))
            && type != error_mark_node
            && (!CLASS_TYPE_P (type)
                || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
index 1ae25bb486ce7c86aefd4d9c9d901afb5c1e7dc1..624a0e95d7f6a2d106c345a8694dde9ae7a1f92f 100644 (file)
@@ -992,6 +992,8 @@ dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags)
       else
        dump_decl (pp, DECL_NAME (t), flags);
     }
+  else if (DECL_DECOMPOSITION_P (t))
+    pp_string (pp, M_("<structured bindings>"));
   else
     pp_string (pp, M_("<anonymous>"));
   if (flags & TFF_DECL_SPECIFIERS)
index 77af54e82a1b0993ccbd5899cf01913033101cf3..75e99e598af26d88f90668fdec6c8522d2b2b474 100644 (file)
@@ -133,6 +133,9 @@ mark_exp_read (tree exp)
   switch (TREE_CODE (exp))
     {
     case VAR_DECL:
+      if (DECL_VALUE_EXPR (exp))
+       mark_exp_read (DECL_VALUE_EXPR (exp));
+      gcc_fallthrough ();
     case PARM_DECL:
       DECL_READ_P (exp) = 1;
       break;
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp29.C b/gcc/testsuite/g++.dg/cpp1z/decomp29.C
new file mode 100644 (file)
index 0000000..daf07a0
--- /dev/null
@@ -0,0 +1,26 @@
+// { dg-options "-std=c++17 -Wunused" }
+
+#include <tuple>
+
+struct A { int i,j,k; };
+
+A f();
+
+int z;
+
+int main()
+{
+  {
+    auto [i,j,k] = f();                // { dg-warning "unused" }
+  }
+  {
+    auto [i,j,k] = f();
+    z = i;
+  }
+  {
+    auto [i,j] = std::tuple{1,2}; // { dg-warning "unused" }
+  }
+  // No parallel second test, because in this case i and j are variables rather
+  // than mere bindings, so there isn't a link between them and using i will
+  // not prevent a warning about unused j.
+}