Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang-static-analyzer] False positive core.NullDefererence when capturing a structured binding in a lambda #91835

Open
captaincrutches opened this issue May 11, 2024 · 2 comments
Labels
clang:static analyzer false-positive Warning fires when it should not

Comments

@captaincrutches
Copy link

captaincrutches commented May 11, 2024

Reproducible example:

struct S { int x; };

void f(int x) { (void)x; }

int main()
{
    S s{42};
    auto& [x] = s;
    auto g = [x](){ f(x); };
    g();
}

This is perfectly valid C++20 code AFAIK, and compiles with both GCC (13) and Clang (18.1).

The static analyzer, however, gets upset:

$ clang++ --version
clang version 18.1.5
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm/18/bin
Configuration file: /etc/clang/x86_64-pc-linux-gnu-clang++.cfg
$ clang++ --analyze --analyzer-output text bindings.cpp 
bindings.cpp:9:23: warning: Dereference of undefined pointer value [core.NullDereference]
    9 |     auto g = [x](){ f(x); };
      |                       ^
bindings.cpp:10:5: note: Calling 'operator()'
   10 |     g();
      |     ^~~
bindings.cpp:9:23: note: Dereference of undefined pointer value
    9 |     auto g = [x](){ f(x); };
      |                       ^
1 warning generated.

But x in that context is neither a pointer nor undefined, as it's being captured by value into the lambda.

Godbolt to reproduce: https://godbolt.org/z/3zha6nv5f

Perhaps noteworthy:

  • The same warning is emitted if x is captured by reference, i.e. [&x]
  • The same warning is emitted if default by-value [=] or by-reference [&] capture is used
  • However, if x is captured explicitly using an initializer ([x = x] or [&x = x]) the warning is not emitted
@EugeneZelenko EugeneZelenko added clang:static analyzer false-positive Warning fires when it should not and removed new issue labels May 11, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented May 11, 2024

@llvm/issue-subscribers-clang-static-analyzer

Author: Captain Crutches (captaincrutches)

Reproducible example: ```cpp struct S { int x; };

void f(int x) { (void)x; }

int main()
{
S s{42};
auto& [x] = s;
auto g = x{ f(x); };
g();
}

This is perfectly valid C++20 code AFAIK, and compiles with both gcc (13) and clang (18.1).

The static analyzer, however, gets upset:

$ clang++ --version
clang version 18.1.5
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm/18/bin
Configuration file: /etc/clang/x86_64-pc-linux-gnu-clang++.cfg
$ clang++ --analyze --analyzer-output text bindings.cpp
bindings.cpp:9:23: warning: Dereference of undefined pointer value [core.NullDereference]
9 | auto g = x{ f(x); };
| ^
bindings.cpp:10:5: note: Calling 'operator()'
10 | g();
| ^~~
bindings.cpp:9:23: note: Dereference of undefined pointer value
9 | auto g = x{ f(x); };
| ^
1 warning generated.

But `x` in that context is neither a pointer nor undefined, as it's being captured by value into the lambda.

Godbolt to reproduce: https://godbolt.org/z/3zha6nv5f

Perhaps noteworthy:
- The same warning is emitted if `x` is captured by reference, i.e. `[&x]`
- The same warning is emitted if default by-value `[=]` or by-reference `[&]` capture is used
- However, if `x` is captured explicitly using an initializer (`[x = x]` or `[&x = x]`) the warning is not emitted
</details>

@steakhal
Copy link
Contributor

Thanks for reporting it. Your report is extensive and minimal, thanks for that!

The issue is that from the lambda body, we try to load form variable x from ExprEngine::VisitCommonDeclRefExpr, where D is a BindingDecl, which refers to a DecompositionDecl with reference type. Then the Base = state->getSVal(R) will associate undefinedVal with Base.

Instead, Base should refer to the address of the lambda itself, so that the binding in the store (temp_object{class (lambda at code.cpp:9:12), S1144}: 42 S32b) would be loaded instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:static analyzer false-positive Warning fires when it should not
Projects
None yet
Development

No branches or pull requests

4 participants