aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorflovent <flbven@protonmail.com>2025-06-25 22:15:01 +0800
committerGitHub <noreply@github.com>2025-06-25 16:15:01 +0200
commitb8bda9d446e756f1ec722a06d604a654b472e581 (patch)
tree2067929167fee0982e7aba0d97f089bf020aade9 /clang/lib/StaticAnalyzer
parent022e1e99f3b017ac1baf8b65f5a48212c5fca2ae (diff)
downloadllvm-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.cpp12
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)