Bug 112546 - -Wmaybe-uninitialized and -Wuninitialized does not detect usage of uninitilazed value in a lambda
Summary: -Wmaybe-uninitialized and -Wuninitialized does not detect usage of uninitilaz...
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 13.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2023-11-15 13:05 UTC by Federico Kircheis
Modified: 2023-11-15 17:00 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Federico Kircheis 2023-11-15 13:05:49 UTC
I noticed the issue when comparing this three equivalent bar functions:


----
struct data{
	int i;
};
data foo();
void bar(const data& d);

void bar1(){
    data d = [&]{bar(d); return foo();}();
}

void bar2(){
    data d = (bar(d), void(), foo());
}


void bar3(){
    data d;
    bar(d);
    d = foo();
}
----


example on godbolt: https://godbolt.org/z/Wxj6rbKb9
With "-Wmaybe-uninitialized", GCC detects in bar2 and bar3 that d is possible used inside bar without being initialized, but it fails to do so when using a lambda.

In fact, I noticed that it fails to report (with "-Wuninitialized") even when the value is used directly in the lambda:


----
void bar4(){
    data d = [&]{ ++d.i; bar(d); return foo();}();
}
----
Comment 1 Federico Kircheis 2023-11-15 17:00:28 UTC
I looked at some reports at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=24639

It seems that most related issues rely on global variables or parameters, but in fact I found some other examples with local variables

----
void foo(int);

void baz1(){
    int i;
    [&]{++i;}(); // no warning
    foo(i);
}

void baz2(){
    int i;
    ++i; // warning
    foo(i);
}

void baz3(){
    int i;
    int& r = i;
    ++r; // warning
    foo(i);
}

void baz4(){
    int i;
    int& r = i;
    int& rr = r;
    ++rr; // no warning
    foo(i);
}

void baz5(){
    int i;
    struct {int& j;}  r{i};
    ++r.j; // no warning
    foo(i);
}
----


only baz2 and baz3 trigger a warning, in all function a local uninitialized variable is unconditionally modified.
(the call to function foo is to ensure that the code is not marked as dead/unused and thus ignored)