[clang] [Clang] Check for uninitialized use in lambda within CXXOperatorCallExpr (PR #129198)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 27 22:19:53 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: zhaohui (zhaohuiw42)
<details>
<summary>Changes</summary>
Fix #<!-- -->128058.
Track whether a LambdaExpr is an immediate operand of a CXXOperatorCallExpr using a new flag, isInCXXOperatorCall. This enables special handling of capture initializations to detect uninitialized variable uses, such as in `S s = [&]() { return s; }();`.
---
Full diff: https://github.com/llvm/llvm-project/pull/129198.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaDecl.cpp (+22)
- (modified) clang/test/SemaCXX/uninitialized.cpp (+4)
``````````diff
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 285bd27a35a76..ad93b4a858543 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12597,6 +12597,12 @@ namespace {
bool isRecordType;
bool isPODType;
bool isReferenceType;
+ // Tracks whether the current expression is being visited within a
+ // CXXOperatorCallExpr. This flag is set to true when entering a
+ // CXXOperatorCallExpr and reset to false upon exit. It is used to detect
+ // when a LambdaExpr is an operand of an operator call, enabling special
+ // handling of its capture initializations.
+ bool isInCXXOperatorCall;
bool isInitList;
llvm::SmallVector<unsigned, 4> InitFieldIndex;
@@ -12609,6 +12615,7 @@ namespace {
isPODType = false;
isRecordType = false;
isReferenceType = false;
+ isInCXXOperatorCall = false;
isInitList = false;
if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) {
isPODType = VD->getType().isPODType(S.Context);
@@ -12796,6 +12803,7 @@ namespace {
}
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ isInCXXOperatorCall = true;
Expr *Callee = E->getCallee();
if (isa<UnresolvedLookupExpr>(Callee))
@@ -12804,6 +12812,20 @@ namespace {
Visit(Callee);
for (auto Arg: E->arguments())
HandleValue(Arg->IgnoreParenImpCasts());
+ isInCXXOperatorCall = false;
+ }
+
+ void VisitLambdaExpr(LambdaExpr *E) {
+ if (isInCXXOperatorCall) {
+ for (const auto &init : E->capture_inits()) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(init))
+ HandleDeclRefExpr(DRE);
+ else
+ Visit(init);
+ }
+ return;
+ }
+ Inherited::VisitLambdaExpr(E);
}
void VisitUnaryOperator(UnaryOperator *E) {
diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp
index 4af2c998f082e..654d955b3cc72 100644
--- a/clang/test/SemaCXX/uninitialized.cpp
+++ b/clang/test/SemaCXX/uninitialized.cpp
@@ -892,6 +892,10 @@ namespace lambdas {
return a1.x;
});
A a2([&] { return a2.x; }); // ok
+ A a3([=]{ return a3.x; }()); // expected-warning{{variable 'a3' is uninitialized when used within its own initialization}}
+ A a4([&]{ return a4.x; }()); // expected-warning{{variable 'a4' is uninitialized when used within its own initialization}}
+ A a5([&]{ return a5; }()); // expected-warning{{variable 'a5' is uninitialized when used within its own initialization}}
+ A a6([&]{ return a5.x; }()); // ok
}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/129198
More information about the cfe-commits
mailing list