diff options
author | flovent <flbven@protonmail.com> | 2025-06-25 22:15:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-25 16:15:01 +0200 |
commit | b8bda9d446e756f1ec722a06d604a654b472e581 (patch) | |
tree | 2067929167fee0982e7aba0d97f089bf020aade9 /clang/lib/StaticAnalyzer | |
parent | 022e1e99f3b017ac1baf8b65f5a48212c5fca2ae (diff) | |
download | llvm-b8bda9d446e756f1ec722a06d604a654b472e581.zip llvm-b8bda9d446e756f1ec722a06d604a654b472e581.tar.gz llvm-b8bda9d446e756f1ec722a06d604a654b472e581.tar.bz2 |
[clang][analyzer] Correctly handle lambda-converted function pointers (#144906)
For lambdas that are converted to C function pointers,
```
int (*ret_zero)() = []() { return 0; };
```
clang will generate conversion method like:
```
CXXConversionDecl implicit used constexpr operator int (*)() 'int (*() const noexcept)()' inline
-CompoundStmt
-ReturnStmt
-ImplicitCastExpr 'int (*)()' <FunctionToPointerDecay>
-DeclRefExpr 'int ()' lvalue CXXMethod 0x5ddb6fe35b18 '__invoke' 'int ()'
-CXXMethodDecl implicit used __invoke 'int ()' static inline
-CompoundStmt (empty)
```
Based on comment in Sema, `__invoke`'s function body is left empty
because it's will be filled in CodeGen, so in AST analysis phase we
should get lambda's `operator()` directly instead of calling `__invoke`
itself.
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index f78b1b8..34fcb9b 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -688,6 +688,18 @@ const FunctionDecl *SimpleFunctionCall::getDecl() const { return getSVal(getOriginExpr()->getCallee()).getAsFunctionDecl(); } +RuntimeDefinition SimpleFunctionCall::getRuntimeDefinition() const { + // Clang converts lambdas to function pointers using an implicit conversion + // operator, which returns the lambda's '__invoke' method. However, Sema + // leaves the body of '__invoke' empty (it is generated later in CodeGen), so + // we need to skip '__invoke' and access the lambda's operator() directly. + if (const auto *CMD = dyn_cast_if_present<CXXMethodDecl>(getDecl()); + CMD && CMD->isLambdaStaticInvoker()) + return RuntimeDefinition{CMD->getParent()->getLambdaCallOperator()}; + + return AnyFunctionCall::getRuntimeDefinition(); +} + const FunctionDecl *CXXInstanceCall::getDecl() const { const auto *CE = cast_or_null<CallExpr>(getOriginExpr()); if (!CE) |