C++ PATCH to -Wunused with C++17 structured bindings

Jason Merrill jason@redhat.com
Wed May 24 02:23:00 GMT 2017


Someone on IRC complained that there was no way to suppress -Wunused
on structured bindings.  It seemed to me that the way the feature
works, we shouldn't warn about the bindings individually; users need
to give each of the subobjects a name even if they're only interested
in using one of them.

So this patch switches to tracking whether the underlying aggregate
object as a whole is used; using one of the bindings will avoid any
warning.

This doesn't apply to tuple structured bindings, since in that case
the bindings are actual variables rather than aliases to subobjects.

Tested x86_64-pc-linux-gnu, applying to trunk.
-------------- next part --------------
commit a10b737bee6f269c6d6cf2a668d03fb322e1c45e
Author: Jason Merrill <jason@redhat.com>
Date:   Thu May 11 13:30:24 2017 -0400

            -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.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5877f37..afd47bb 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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)
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index b65cee4..66a4b60 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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)
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 77af54e..75e99e5 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -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
index 0000000..daf07a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp29.C
@@ -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.
+}


More information about the Gcc-patches mailing list