[clang] 3a67c7c - [Clang] Check for uninitialized use in lambda within CXXOperatorCallExpr (#129198)

via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 7 00:01:26 PST 2025


Author: zhaohui
Date: 2025-03-07T16:01:23+08:00
New Revision: 3a67c7c6f7f6d41adf4487d099c1225c31caf8c3

URL: https://github.com/llvm/llvm-project/commit/3a67c7c6f7f6d41adf4487d099c1225c31caf8c3
DIFF: https://github.com/llvm/llvm-project/commit/3a67c7c6f7f6d41adf4487d099c1225c31caf8c3.diff

LOG: [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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaDecl.cpp
    clang/test/SemaCXX/uninitialized.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e42541818a0e9..28856c27317f3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -299,6 +299,7 @@ Improvements to C++ diagnostics
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 - Fixed type checking when a statement expression ends in an l-value of atomic type. (#GH106576)
+- Fixed uninitialized use check in a lambda within CXXOperatorCallExpr. (#GH129198)
 
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 8c5125b8eb6d9..714210c3856d7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -61,6 +61,7 @@
 #include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/SaveAndRestore.h"
 #include "llvm/TargetParser/Triple.h"
 #include <algorithm>
 #include <cstring>
@@ -12611,6 +12612,7 @@ namespace {
     bool isRecordType;
     bool isPODType;
     bool isReferenceType;
+    bool isInCXXOperatorCall;
 
     bool isInitList;
     llvm::SmallVector<unsigned, 4> InitFieldIndex;
@@ -12623,6 +12625,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);
@@ -12810,6 +12813,7 @@ namespace {
     }
 
     void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+      llvm::SaveAndRestore CxxOpCallScope(isInCXXOperatorCall, true);
       Expr *Callee = E->getCallee();
 
       if (isa<UnresolvedLookupExpr>(Callee))
@@ -12820,6 +12824,19 @@ namespace {
         HandleValue(Arg->IgnoreParenImpCasts());
     }
 
+    void VisitLambdaExpr(LambdaExpr *E) {
+      if (!isInCXXOperatorCall) {
+        Inherited::VisitLambdaExpr(E);
+        return;
+      }
+
+      for (Expr *Init : E->capture_inits())
+        if (DeclRefExpr *DRE = dyn_cast_if_present<DeclRefExpr>(Init))
+          HandleDeclRefExpr(DRE);
+        else if (Init)
+          Visit(Init);
+    }
+
     void VisitUnaryOperator(UnaryOperator *E) {
       // For POD record types, addresses of its own members are well-defined.
       if (E->getOpcode() == UO_AddrOf && isRecordType &&

diff  --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp
index 4af2c998f082e..c7b987e2172e6 100644
--- a/clang/test/SemaCXX/uninitialized.cpp
+++ b/clang/test/SemaCXX/uninitialized.cpp
@@ -892,6 +892,11 @@ 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
+    A a7 = [&a7] { return a7; }(); // expected-warning{{variable 'a7' is uninitialized when used within its own initialization}}
   }
 }
 


        


More information about the cfe-commits mailing list