Skip to content

Commit 3a67c7c

Browse files
authored
[Clang] Check for uninitialized use in lambda within CXXOperatorCallExpr (#129198)
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; }();`. Fix #128058
1 parent 6cb2f6d commit 3a67c7c

File tree

3 files changed

+23
-0
lines changed

3 files changed

+23
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ Improvements to C++ diagnostics
299299
Bug Fixes to AST Handling
300300
^^^^^^^^^^^^^^^^^^^^^^^^^
301301
- Fixed type checking when a statement expression ends in an l-value of atomic type. (#GH106576)
302+
- Fixed uninitialized use check in a lambda within CXXOperatorCallExpr. (#GH129198)
302303

303304
Miscellaneous Bug Fixes
304305
^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDecl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "llvm/ADT/STLForwardCompat.h"
6262
#include "llvm/ADT/SmallString.h"
6363
#include "llvm/ADT/StringExtras.h"
64+
#include "llvm/Support/SaveAndRestore.h"
6465
#include "llvm/TargetParser/Triple.h"
6566
#include <algorithm>
6667
#include <cstring>
@@ -12611,6 +12612,7 @@ namespace {
1261112612
bool isRecordType;
1261212613
bool isPODType;
1261312614
bool isReferenceType;
12615+
bool isInCXXOperatorCall;
1261412616

1261512617
bool isInitList;
1261612618
llvm::SmallVector<unsigned, 4> InitFieldIndex;
@@ -12623,6 +12625,7 @@ namespace {
1262312625
isPODType = false;
1262412626
isRecordType = false;
1262512627
isReferenceType = false;
12628+
isInCXXOperatorCall = false;
1262612629
isInitList = false;
1262712630
if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) {
1262812631
isPODType = VD->getType().isPODType(S.Context);
@@ -12810,6 +12813,7 @@ namespace {
1281012813
}
1281112814

1281212815
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
12816+
llvm::SaveAndRestore CxxOpCallScope(isInCXXOperatorCall, true);
1281312817
Expr *Callee = E->getCallee();
1281412818

1281512819
if (isa<UnresolvedLookupExpr>(Callee))
@@ -12820,6 +12824,19 @@ namespace {
1282012824
HandleValue(Arg->IgnoreParenImpCasts());
1282112825
}
1282212826

12827+
void VisitLambdaExpr(LambdaExpr *E) {
12828+
if (!isInCXXOperatorCall) {
12829+
Inherited::VisitLambdaExpr(E);
12830+
return;
12831+
}
12832+
12833+
for (Expr *Init : E->capture_inits())
12834+
if (DeclRefExpr *DRE = dyn_cast_if_present<DeclRefExpr>(Init))
12835+
HandleDeclRefExpr(DRE);
12836+
else if (Init)
12837+
Visit(Init);
12838+
}
12839+
1282312840
void VisitUnaryOperator(UnaryOperator *E) {
1282412841
// For POD record types, addresses of its own members are well-defined.
1282512842
if (E->getOpcode() == UO_AddrOf && isRecordType &&

clang/test/SemaCXX/uninitialized.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,11 @@ namespace lambdas {
892892
return a1.x;
893893
});
894894
A a2([&] { return a2.x; }); // ok
895+
A a3([=] { return a3.x; }()); // expected-warning{{variable 'a3' is uninitialized when used within its own initialization}}
896+
A a4([&] { return a4.x; }()); // expected-warning{{variable 'a4' is uninitialized when used within its own initialization}}
897+
A a5([&] { return a5; }()); // expected-warning{{variable 'a5' is uninitialized when used within its own initialization}}
898+
A a6([&] { return a5.x; }()); // ok
899+
A a7 = [&a7] { return a7; }(); // expected-warning{{variable 'a7' is uninitialized when used within its own initialization}}
895900
}
896901
}
897902

0 commit comments

Comments
 (0)