7

Let's start with a minimal example:

#include <utility>

int main()
{
    auto [a, b] = std::pair(1, 'A');
    return a;
}

Compiling with GCC 7.3 passing -std=c++17 and -Wunused-variable, and running it:

<source>: In function 'int main()':
<source>:5:15: warning: unused variable 'b' [-Wunused-variable]
     auto [a, b] = std::pair(1, 'A');
               ^

GCC may be correctly reporting the absent use of b, but it wrongly calls it a variable. Quoting [dcl.struct.bind]/1:

A structured binding declaration introduces the identifiers v0, v1, v2, … of the identifier-list as names ([basic.scope.declarative]) of structured bindings.

So b clearly isn't a variable, but rather a name. Compiling the same code with Clang 6.0.0, and with the same flags, we get no warning whatsoever. Removing the return a; statement from the code:

#include <utility>

int main()
{
    auto [a, b] = std::pair(1, 'A');
    // return a;
}

and compiling it again with Clang, we get:

<source>:5:10: warning: unused variable '[a, b]' [-Wunused-variable]
    auto [a, b] = std::pair(1, 'A');
         ^

Which, from my interpretation, correctly treats [a, b] as a variable, and a and b separately as just names. My question then is why does GCC diagnose a warning for b being unused, considering that the variable is in fact being used in the return a; statement from the first code?

Mário Feroldi
  • 3,463
  • 2
  • 24
  • 49
  • 1
    What return statement? Only `a` is returned, not `b`. P.S. because this is a common idiom, with structured bindings, it's been reported that this warning message is no longer issued by gcc 8. – Sam Varshavchik Apr 15 '18 at 18:38
  • 1
    If they are not variables, how come you can take their addresses? For example `auto p = &a;` –  Apr 15 '18 at 18:38
  • 1
    In this particular case, `b` is a variable. But in general `b` might be anything, including a lambda or a pointer to a function. – Clearer Apr 15 '18 at 18:39
  • 2
    @NeilButterworth they are names for the underlying members of the struct. The actual variable doesn't get an identifier. – Mário Feroldi Apr 15 '18 at 18:39
  • 3
    That they are names doesn't conflict with that they are variables. Or simply put, what else can they be? – Passer By Apr 15 '18 at 18:40
  • @PasserBy the standard clearly says that they are names of lvalues, which is a different term from variable: http://eel.is/c++draft/dcl.struct.bind – Mário Feroldi Apr 15 '18 at 18:42
  • I'm surprised. Structured bindings are indeed considered something different. They are their own category. However I doubt the error message is meant to be taken that literally and precisely, to mean exactly a variable as defined in the standard. – Passer By Apr 15 '18 at 18:47
  • 1
    @PasserBy you'd be more surprised to know that [it was indeed meant to address a different term](https://stackoverflow.com/questions/46114214/lambda-implicit-capture-fails-with-variable-declared-from-structured-binding). – Mário Feroldi Apr 15 '18 at 18:53
  • 2
    "Why does GCC diagnose a unused variable for structured bindings while Clang doesn't?" - Because compilers are different and diagnose different things (and have different bugs) and also have different levels of standard conformance. – Jesper Juhl Apr 15 '18 at 18:59
  • 1
    @Mário Feroldi I don't believe I said the question was invalid. – Jesper Juhl Apr 15 '18 at 19:37

1 Answers1