Author: Gábor Horváth Date: 2026-06-17T20:56:39+01:00 New Revision: c11a0993281f0e14ef0ce87e391f66bf7b335488
URL: https://github.com/llvm/llvm-project/commit/c11a0993281f0e14ef0ce87e391f66bf7b335488 DIFF: https://github.com/llvm/llvm-project/commit/c11a0993281f0e14ef0ce87e391f66bf7b335488.diff LOG: [LifetimeSafety] Propagate loans through the comma operator (#204379) VisitBinaryOperator had no comma case, so a comma expression carried none of its right operand's loans and a borrow used via a comma result (e.g. `g = (f(), p)`) was silently dropped. Flow the RHS's origin into the result. Assisted-by: Claude Opus 4.8 Added: Modified: clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp clang/test/Sema/LifetimeSafety/dangling-global.cpp clang/test/Sema/LifetimeSafety/safety.cpp Removed: ################################################################################ diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index b45987cbc097c..d56703a4b29c4 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -468,6 +468,10 @@ void FactsGenerator::handlePointerArithmetic(const BinaryOperator *BO) { } void FactsGenerator::VisitBinaryOperator(const BinaryOperator *BO) { + if (BO->getOpcode() == BO_Comma) { + killAndFlowOrigin(*BO, *BO->getRHS()); + return; + } if (BO->isCompoundAssignmentOp()) return; if (BO->getType()->isPointerType() && BO->isAdditiveOp()) diff --git a/clang/test/Sema/LifetimeSafety/dangling-global.cpp b/clang/test/Sema/LifetimeSafety/dangling-global.cpp index 98f8905d0e2da..f419ff4416023 100644 --- a/clang/test/Sema/LifetimeSafety/dangling-global.cpp +++ b/clang/test/Sema/LifetimeSafety/dangling-global.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety -Wno-dangling -verify %s -int *global; // expected-note {{this global dangles}} +int *global; // expected-note 2 {{this global dangles}} int *global_backup; // expected-note {{this global dangles}} struct ObjWithStaticField { @@ -32,6 +32,12 @@ void store_local_in_global() { global = &local; // expected-warning {{stack memory associated with local variable 'local' escapes to the global variable 'global' which will dangle}} } +int side(); +void store_local_in_global_via_comma() { + int local; + global = (side(), &local); // expected-warning {{stack memory associated with local variable 'local' escapes to the global variable 'global' which will dangle}} +} + void store_then_clear() { int local; global = &local; diff --git a/clang/test/Sema/LifetimeSafety/safety.cpp b/clang/test/Sema/LifetimeSafety/safety.cpp index 3c954cebda820..6fc275b51a9d0 100644 --- a/clang/test/Sema/LifetimeSafety/safety.cpp +++ b/clang/test/Sema/LifetimeSafety/safety.cpp @@ -1250,6 +1250,43 @@ void conditional_operator_lifetimebound_nested_deep(bool cond) { (void)*p; // expected-note 4 {{later used here}} } +// Comma operator. +int side(); +void comma_use_after_scope() { + MyObj* p; + { + MyObj temp; + p = (side(), &temp); // expected-warning {{local variable 'temp' does not live long enough}} + } // expected-note {{destroyed here}} + (void)*p; // expected-note {{later used here}} +} + +void comma_nested() { + MyObj* p; + { + MyObj temp; + p = (side(), (side(), &temp)); // expected-warning {{local variable 'temp' does not live long enough}} + } // expected-note {{destroyed here}} + (void)*p; // expected-note {{later used here}} +} + +void comma_masked_by_conditional(bool cond) { + MyObj safe; + MyObj* keep = &safe; + MyObj* p; + { + MyObj temp; + p = cond ? keep : (side(), &temp); // expected-warning {{local variable 'temp' does not live long enough}} + } // expected-note {{destroyed here}} + (void)*p; // expected-note {{later used here}} +} + +void comma_safe() { + MyObj safe; + MyObj* p = (side(), &safe); + (void)*p; // no-warning +} + // FIXME: Diagnostic output does not handle ParenExpr correctly, causing alias // information to be missed (local variable 'p' aliases the storage of local variable 'b'). void simpleparen() { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
