https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114450

            Bug ID: 114450
           Summary: -Wunused-but-set-variable false positive in lambda
                    using another static auto lambda
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: olof.gullnas at gmail dot com
  Target Milestone: ---

Created attachment 57798
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57798&action=edit
Code to produce warning

Using g++ where "g++-13 -v" print a last line with:
 gcc version 13.2.1 20230912 [revision b96e66fd4ef3e36983969fb8cdd1956f551a074b 
 (SUSE Linux)

I compiling with g++-13 -Wall -Wextra.

This program gets a warning
   variable ‘lambda_2’ set but not used [-Wunused-but-set-variable]

The variable IS used, so I think this is a "false positive"
The code is stripped down from a MUCH larger example so this code
does not do anything useful...

//#include <algorithm> // required if std::for_each or std::ranges::for_each is
used
#include <iostream> // for "trace printouts", not needed if printouts are
removed
#include <vector>

// a MUCH simplified version of std::for_each
template <typename I, typename F>
void foreach(I b, I e, F f)
{
    for (auto ii= b; ii != e; ++ii)
    {
        f(*ii);
    }
};

int main (int, char**)
{
    std::vector<int> v{ 2 };

    // constexpr is not needed for warning to appear. static probably is
    // If not static and "lambda_2" captured by lambda_1 then no
    // warning. Likely that static variable being available
    // to lambda_1 without explicit capture is required for warning to
    // appear.
    // A lambda that returns another lambda. A -Wunused-but-set-variable
    // warning is generated. It IS used in lambda_1. 
    static /*constexpr*/ auto lambda_2 = [](auto id) {
        std::cout << "lambda_2" << "\n";
        return [id]( auto f) {
            std::cout<< "lambda gen by lambda_2\n";
            return f == id;
        };
    };

    auto lambda_1 = []( auto& id)
    {
        auto f = lambda_2(id); // lambda_2 used here
        // to avoid warning about unused f... If pgm executed without
        // following line, lambda_2 is still called/used.
        std::cout << f(2) << "\n";
    };
#if 1
    // using a local simplistic foreach template gives the warning
    foreach(v.begin(), v.end(), lambda_1);

    // as does using lambda_1 in std::for_each(...)
    //std::for_each( v.begin(), v.end(), lambda_1); // requires #include
<algorithm>
#else
    // if std::for_each algorithm is replaced by a simple loop or
    // a direct call to lambda_1 the warning disappears
    //for ( auto it = v.begin(); it != v.end();++it) // no warning
    //    lambda_1(*it);
    // or
    //lambda_1(v[0]); // no warning
    //
    // A bit more surprising is that using
    // std::ranges::for_each also avoids the warning!
    std::ranges::for_each(v, lambda_1); // no warning, requires #include
<algorithm>
#endif
}

Reply via email to