3

Consider the following program:

template <unsigned int I>
int f(int x)
{
    auto task = [&]() { ++x; };
    if constexpr (I == 0) {
        task();
    }
    return x;
}

int main()
{
    f<1>(3);
}

Compiling on gcc 9.3 with -std=c++17 -Wall -pedantic, it issues a warning

warning: variable 'task' set but not used [-Wunused-but-set-variable]
    4 |     auto task = [&]() { ++x; };

But with a newer gcc version, no such warning appears. Notice that according to the manual, -Wunused-but-set-variable is enabled by -Wall.

Also with clang, no such a warning appears.

Test it on godbolt.

Is that a compiler shortcoming, or is this behavior (the lack of warning) wanted/expected?

francesco
  • 7,189
  • 7
  • 22
  • 49
  • For a function parameter that cannot be declared inside the `if`, the warning was bogus. For local variables, I guess I’d want it iff the variable was used in only one arm of a constexpr if? – Davis Herring May 07 '21 at 21:06
  • 1
    I wouldn't say _shortcoming_, but it _can_ be seen as a regression. The compiler is not obligated to "catch" this - and if newer language inventions have forced the compiler developers to dump certain cases to not flood newer, perfectly sane cases, with ill-adviced warnings, that could be a reason. Pure speculation. It could also be, a mistake. – Ted Lyngmo May 07 '21 at 21:07
  • I think that's on purpose. You didn't typo the name or anything, it just happens to be only used for some parameters and not others. Why do you want a warning? – Marc Glisse May 07 '21 at 21:09
  • 1
    Whether this is a "shortcoming" or "wanted/expected" is, I'm afraid, a matter of opinion. One can form an argument either way. I do not see a factual possible answer here. – Sam Varshavchik May 07 '21 at 21:29
  • I would not want such warning, and I would believe it was removed on purpose. A template can be invoked from different code paths, and unless compiler can guarantee **at the function site** that it is never called with a value of `I` which triggers `task` invocation (which it usually can not do) the warning would not be approriate. – SergeyA May 07 '21 at 21:29
  • 1
    @SamVarshavchik I am pretty sure it is a not a shortcoming, and I presume, it was removed as a fix. – SergeyA May 07 '21 at 21:30

1 Answers1

1

Consider this slightly modifed code:

template <unsigned int I>
int f(int x)
{
    auto task = [&]() { ++x; };
    if constexpr (I == 0) {
        task();
    }
    return x;
}

int main()
{
    f<0>(3);
    f<1>(3);
}

With gcc 9.3 -std=c++2a -Wall -Werror you get an error (warning treated as error):

<source>: In instantiation of 'int f(int) [with unsigned int I = 1]':
<source>:14:11:   required from here
<source>:4:10: error: variable 'task' set but not used [-Werror=unused-but-set-variable]
    4 |     auto task = [&]() { ++x; };
      |          ^~~~
cc1plus: all warnings being treated as errors

This is bad, because the code is completely fine and it can be considered a bug that it triggers a warning. Apparently this has been fixed in gcc >= 10.1.

One could argue that one could/should move declaration of task into the if constexpr branch, but then consider that this made gcc issue a warning as well:

template <unsigned int I>
int f(int x)
{
    auto task = [&]() { ++x; };
    if constexpr (I == 0) {
        task();
    } else if constexpr (I == 1) {
        task();
    } 
    return x;
}

int main()
{
    f<0>(3);
    f<1>(3);
    f<2>(3);
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185