[clang] [LifetimeSafety] Flow origins from lifetimebound args in `gsl::Pointer` construction (PR #189907)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 1 01:06:41 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-analysis
Author: NeKon69
<details>
<summary>Changes</summary>
This PR adds origin flow from `[[clang::lifetimebound]]` constructor arguments during `gsl::Pointer` construction.
Fixes #<!-- -->175898
---
Full diff: https://github.com/llvm/llvm-project/pull/189907.diff
2 Files Affected:
- (modified) clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp (+4-4)
- (modified) clang/test/Sema/warn-lifetime-analysis-nocfg.cpp (+5-7)
``````````diff
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 861e1f6fa8a33..b314ac45c5760 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -704,10 +704,10 @@ void FactsGenerator::handleFunctionCall(const Expr *Call,
assert(!Args[I]->isGLValue() || ArgList->getLength() >= 2);
ArgList = getRValueOrigins(Args[I], ArgList);
}
- if (isGslOwnerType(Args[I]->getType())) {
- // The constructed gsl::Pointer borrows from the Owner's storage, not
- // from what the Owner itself borrows, so only the outermost origin is
- // needed.
+ if (isGslOwnerType(Args[I]->getType()) || IsArgLifetimeBound(I)) {
+ // The constructed gsl::Pointer is dependent on the argument itself, not
+ // on anything the argument is dependent on, so only the outermost
+ // origin is needed.
CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
CallList->getOuterOriginID(), ArgList->getOuterOriginID(),
KillSrc));
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index d58f23e4b554c..0ed151b9db136 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -931,13 +931,11 @@ struct [[gsl::Pointer]] Pointer {
Pointer(const Bar & bar [[clang::lifetimebound]]);
};
Pointer test3(Bar bar) {
- // FIXME: Detect this using the CFG-based lifetime analysis (constructor of a pointer).
- // https://github.com/llvm/llvm-project/issues/175898
- Pointer p = Pointer(Bar()); // expected-warning {{temporary}}
- use(p);
- p = Pointer(Bar()); // expected-warning {{object backing}}
- use(p);
- return bar; // expected-warning {{address of stack}}
+ Pointer p = Pointer(Bar()); // expected-warning {{temporary}} cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}}
+ use(p); // cfg-note {{later used here}}
+ p = Pointer(Bar()); // expected-warning {{object backing}} cfg-warning {{object whose reference is captured does not live long enough}} cfg-note {{destroyed here}}
+ use(p); // cfg-note {{later used here}}
+ return bar; // expected-warning {{address of stack}} cfg-warning {{address of stack memory is returned later}} cfg-note {{returned here}}
}
template<typename T>
``````````
</details>
https://github.com/llvm/llvm-project/pull/189907
More information about the cfe-commits
mailing list