[clang] [LifetimeSafety] Fix crash on ternary operator when one of the expressions is `throw` (PR #190345)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 3 06:47:47 PDT 2026
https://github.com/NeKon69 created https://github.com/llvm/llvm-project/pull/190345
`throw` is a special case: it produces void, but it can still appear in the ternary operator. Ignore it when flowing origins.
Closes #183895
>From 813689c7f7392ec5c44d90ec8a030a9ba102985d Mon Sep 17 00:00:00 2001
From: NeKon69 <nobodqwe at gmail.com>
Date: Fri, 3 Apr 2026 16:32:34 +0300
Subject: [PATCH 1/3] [LifetimeSafety] Apply the fix
---
.../Analysis/LifetimeSafety/FactsGenerator.cpp | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 75f2978d848b7..6108d34275092 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -94,6 +94,10 @@ static const Loan *createLoan(FactManager &FactMgr,
return FactMgr.getLoanMgr().createLoan(Path, MTE);
}
+static bool producesConditionalResult(const Expr *E) {
+ return isa<CXXThrowExpr>(E->IgnoreParenImpCasts());
+}
+
void FactsGenerator::run() {
llvm::TimeTraceScope TimeProfile("FactGenerator");
const CFG &Cfg = *AC.getCFG();
@@ -404,8 +408,18 @@ void FactsGenerator::VisitConditionalOperator(const ConditionalOperator *CO) {
if (hasOrigins(CO)) {
// Merge origins from both branches of the conditional operator.
// We kill to clear the initial state and merge both origins into it.
- killAndFlowOrigin(*CO, *CO->getTrueExpr());
- flowOrigin(*CO, *CO->getFalseExpr());
+ const Expr *TrueExpr = CO->getTrueExpr();
+ const Expr *FalseExpr = CO->getFalseExpr();
+ bool Initialized = false;
+ for (const Expr *Branch : {TrueExpr, FalseExpr}) {
+ if (producesConditionalResult(Branch))
+ continue;
+ if (!Initialized) {
+ killAndFlowOrigin(*CO, *Branch);
+ Initialized = true;
+ } else
+ flowOrigin(*CO, *Branch);
+ }
}
}
>From c43162e8d4de5a033ddc84a275f6fe3a44db78f7 Mon Sep 17 00:00:00 2001
From: NeKon69 <nobodqwe at gmail.com>
Date: Fri, 3 Apr 2026 16:41:36 +0300
Subject: [PATCH 2/3] add a test file
---
.../test/Sema/warn-lifetime-safety-conditional-throw.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 clang/test/Sema/warn-lifetime-safety-conditional-throw.cpp
diff --git a/clang/test/Sema/warn-lifetime-safety-conditional-throw.cpp b/clang/test/Sema/warn-lifetime-safety-conditional-throw.cpp
new file mode 100644
index 0000000000000..2437618d131cd
--- /dev/null
+++ b/clang/test/Sema/warn-lifetime-safety-conditional-throw.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -Wlifetime-safety -Wno-dangling -verify %s
+
+// expected-no-diagnostics
+
+void conditional_throw_branches(bool cond, int *value) {
+ (void)(cond ? throw 1 : value);
+ (void)(cond ? value : throw 1);
+ (void)(cond ? throw 1 : throw 2);
+}
>From ac67df326082b1a1ed7237742789b85bafaff45e Mon Sep 17 00:00:00 2001
From: NeKon69 <nobodqwe at gmail.com>
Date: Fri, 3 Apr 2026 16:43:14 +0300
Subject: [PATCH 3/3] update functions body to represent what it actually does
---
clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 6108d34275092..5eb2fcd150576 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -95,7 +95,7 @@ static const Loan *createLoan(FactManager &FactMgr,
}
static bool producesConditionalResult(const Expr *E) {
- return isa<CXXThrowExpr>(E->IgnoreParenImpCasts());
+ return !isa<CXXThrowExpr>(E->IgnoreParenImpCasts());
}
void FactsGenerator::run() {
@@ -412,7 +412,7 @@ void FactsGenerator::VisitConditionalOperator(const ConditionalOperator *CO) {
const Expr *FalseExpr = CO->getFalseExpr();
bool Initialized = false;
for (const Expr *Branch : {TrueExpr, FalseExpr}) {
- if (producesConditionalResult(Branch))
+ if (!producesConditionalResult(Branch))
continue;
if (!Initialized) {
killAndFlowOrigin(*CO, *Branch);
More information about the cfe-commits
mailing list