[clang] [LifetimeSafety] Detect use of a reference type as a use of underlying origin (PR #184295)
Zhijie Wang via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 8 08:22:35 PDT 2026
https://github.com/aeft updated https://github.com/llvm/llvm-project/pull/184295
>From fe7ea93422db01f15d310941cc2e859f1748562f Mon Sep 17 00:00:00 2001
From: Zhijie Wang <yesterda9 at gmail.com>
Date: Mon, 30 Mar 2026 09:54:06 -0700
Subject: [PATCH 1/4] [LifetimeSafety] Detect use of a reference type as a use
of underlying origin
---
.../Analysis/Analyses/LifetimeSafety/Facts.h | 24 ++++++++++++++++---
clang/lib/Analysis/LifetimeSafety/Facts.cpp | 14 +++++------
.../LifetimeSafety/FactsGenerator.cpp | 23 ++++++++++++++++--
.../Analysis/LifetimeSafety/LiveOrigins.cpp | 6 ++---
.../LifetimeSafety/LoanPropagation.cpp | 5 ++--
.../warn-lifetime-safety-invalidations.cpp | 15 ++++++++----
clang/test/Sema/warn-lifetime-safety.cpp | 12 ++++++++++
7 files changed, 75 insertions(+), 24 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index 0f848abd913d3..a986f37e67c05 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -234,7 +234,7 @@ class GlobalEscapeFact : public OriginEscapesFact {
class UseFact : public Fact {
const Expr *UseExpr;
- const OriginList *OList;
+ std::variant<const OriginList *, OriginID> Origins;
// True if this use is a write operation (e.g., left-hand side of assignment).
// Write operations are exempted from use-after-free checks.
bool IsWritten = false;
@@ -243,13 +243,31 @@ class UseFact : public Fact {
static bool classof(const Fact *F) { return F->getKind() == Kind::Use; }
UseFact(const Expr *UseExpr, const OriginList *OList)
- : Fact(Kind::Use), UseExpr(UseExpr), OList(OList) {}
+ : Fact(Kind::Use), UseExpr(UseExpr), Origins(OList) {}
+ UseFact(const Expr *UseExpr, OriginID OID)
+ : Fact(Kind::Use), UseExpr(UseExpr), Origins(OID) {}
- const OriginList *getUsedOrigins() const { return OList; }
const Expr *getUseExpr() const { return UseExpr; }
void markAsWritten() { IsWritten = true; }
bool isWritten() const { return IsWritten; }
+ void setOrigins(OriginID OID) { Origins = OID; }
+
+ const OriginList *getOriginList() const {
+ if (auto *OList = std::get_if<const OriginList *>(&Origins))
+ return *OList;
+ return nullptr;
+ }
+
+ template <typename Fn> void forEachOrigin(Fn &&F) const {
+ if (const OriginList *OList = getOriginList()) {
+ for (auto *Cur = OList; Cur; Cur = Cur->peelOuterOrigin())
+ F(Cur->getOuterOriginID());
+ } else {
+ F(std::get<OriginID>(Origins));
+ }
+ }
+
void dump(llvm::raw_ostream &OS, const LoanManager &,
const OriginManager &OM) const override;
};
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index 1bc0521a72359..d1dd396bdbe10 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -80,14 +80,14 @@ void GlobalEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
void UseFact::dump(llvm::raw_ostream &OS, const LoanManager &,
const OriginManager &OM) const {
OS << "Use (";
- size_t NumUsedOrigins = getUsedOrigins()->getLength();
- size_t I = 0;
- for (const OriginList *Cur = getUsedOrigins(); Cur;
- Cur = Cur->peelOuterOrigin(), ++I) {
- OM.dump(Cur->getOuterOriginID(), OS);
- if (I < NumUsedOrigins - 1)
+ bool First = true;
+ forEachOrigin([&](OriginID OID) {
+ if (!First)
OS << ", ";
- }
+ else
+ First = false;
+ OM.dump(OID, OS);
+ });
OS << ", " << (isWritten() ? "Write" : "Read") << ")\n";
}
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 80a73a2bf687e..bf3589314d7f7 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -366,8 +366,27 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr,
// assigned.
RHSList = getRValueOrigins(RHSExpr, RHSList);
- if (const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr))
- markUseAsWrite(DRE_LHS);
+ if (const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr)) {
+ QualType QT = DRE_LHS->getDecl()->getType();
+ if (QT->isReferenceType() && hasOrigins(QT->getPointeeType())) {
+ // Writing through a reference uses the binding but overwrites the
+ // pointee. Model this as a Read of the outer origin (keeping the binding
+ // live) and a Write of the inner origins (killing the pointee's
+ // liveness).
+ if (UseFact *UF = UseFacts.lookup(DRE_LHS)) {
+ const OriginList *FullList = UF->getOriginList();
+ assert(FullList);
+ UF->setOrigins(FullList->getOuterOriginID());
+ if (const OriginList *InnerList = FullList->peelOuterOrigin()) {
+ UseFact *WriteUF = FactMgr.createFact<UseFact>(DRE_LHS, InnerList);
+ WriteUF->markAsWritten();
+ CurrentBlockFacts.push_back(WriteUF);
+ }
+ }
+ } else if (!QT->isReferenceType()) {
+ markUseAsWrite(DRE_LHS);
+ }
+ }
// Kill the old loans of the destination origin and flow the new loans
// from the source origin.
flow(LHSList->peelOuterOrigin(), RHSList, /*Kill=*/true);
diff --git a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
index bc7494360624e..de4d7fa833ddf 100644
--- a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
@@ -129,9 +129,7 @@ class AnalysisImpl
/// the origin since it overwrites the value.
Lattice transfer(Lattice In, const UseFact &UF) {
Lattice Out = In;
- for (const OriginList *Cur = UF.getUsedOrigins(); Cur;
- Cur = Cur->peelOuterOrigin()) {
- OriginID OID = Cur->getOuterOriginID();
+ UF.forEachOrigin([&](OriginID OID) {
// Write kills liveness.
if (UF.isWritten()) {
Out = Lattice(Factory.remove(Out.LiveOrigins, OID));
@@ -141,7 +139,7 @@ class AnalysisImpl
Out = Lattice(Factory.add(Out.LiveOrigins, OID,
LivenessInfo(&UF, LivenessKind::Must)));
}
- }
+ });
return Out;
}
diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
index e437fb7d41268..8960479edb17b 100644
--- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
@@ -59,9 +59,8 @@ static llvm::BitVector computePersistentOrigins(const FactManager &FactMgr,
break;
}
case Fact::Kind::Use:
- for (const OriginList *Cur = F->getAs<UseFact>()->getUsedOrigins(); Cur;
- Cur = Cur->peelOuterOrigin())
- CheckOrigin(Cur->getOuterOriginID());
+ F->getAs<UseFact>()->forEachOrigin(
+ [&](OriginID OID) { CheckOrigin(OID); });
break;
case Fact::Kind::MovedOrigin:
case Fact::Kind::OriginEscapes:
diff --git a/clang/test/Sema/warn-lifetime-safety-invalidations.cpp b/clang/test/Sema/warn-lifetime-safety-invalidations.cpp
index 486edd7a1a023..c7f920c03736a 100644
--- a/clang/test/Sema/warn-lifetime-safety-invalidations.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-invalidations.cpp
@@ -259,14 +259,19 @@ namespace ElementReferences {
void ReferenceToVectorElement() {
std::vector<int> v = {1, 2, 3};
- int& ref = v[0];
- v.push_back(4);
- // FIXME: Detect this as a use of 'ref'.
- // https://github.com/llvm/llvm-project/issues/180187
- ref = 10;
+ int& ref = v[0]; // expected-warning {{object whose reference is captured is later invalidated}}
+ v.push_back(4); // expected-note {{invalidated here}}
+ ref = 10; // expected-note {{later used here}}
(void)ref;
}
+void PointerRefToVectorElement() {
+ std::vector<int*> v = {nullptr, nullptr};
+ int*& ref = v[0]; // expected-warning {{object whose reference is captured is later invalidated}}
+ v.push_back(nullptr); // expected-note {{invalidated here}}
+ ref = nullptr; // expected-note {{later used here}}
+}
+
void PointerToVectorElement() {
std::vector<int> v = {1, 2, 3};
int* ptr = &v[0]; // expected-warning {{object whose reference is captured is later invalidated}}
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp
index 76d43445f8636..866542303414a 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -752,6 +752,18 @@ void no_error_if_dangle_then_rescue_gsl() {
v.use(); // This is safe.
}
+void no_error_if_dangle_then_rescue_via_ref() {
+ MyObj safe;
+ MyObj* p;
+ MyObj*& ref = p;
+ {
+ MyObj temp;
+ ref = &temp; // p temporarily points to temp via ref.
+ }
+ ref = &safe; // p is "rescued" via ref before use.
+ (void)*ref; // This is safe.
+}
+
void no_error_loan_from_current_iteration(bool cond) {
// See https://github.com/llvm/llvm-project/issues/156959.
MyObj b;
>From 0da29b4d25907a3c6af60f8d0a78f9c598f14d8b Mon Sep 17 00:00:00 2001
From: Zhijie Wang <yesterda9 at gmail.com>
Date: Mon, 30 Mar 2026 14:05:56 -0700
Subject: [PATCH 2/4] add comment
---
clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index a986f37e67c05..f4ff96786070a 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -234,6 +234,9 @@ class GlobalEscapeFact : public OriginEscapesFact {
class UseFact : public Fact {
const Expr *UseExpr;
+ // For reference writes, handleAssignment narrows this to a single OriginID
+ // for the outer origin (a Read of the reference binding) and creates a
+ // separate Write UseFact for the inner origins.
std::variant<const OriginList *, OriginID> Origins;
// True if this use is a write operation (e.g., left-hand side of assignment).
// Write operations are exempted from use-after-free checks.
>From fbcf7d4f058437b107f6285f26fd562cfbdce05a Mon Sep 17 00:00:00 2001
From: Zhijie Wang <yesterda9 at gmail.com>
Date: Tue, 7 Apr 2026 23:31:02 -0700
Subject: [PATCH 3/4] create an OriginList with a single origin
---
.../Analysis/Analyses/LifetimeSafety/Facts.h | 28 +++----------------
.../Analyses/LifetimeSafety/Origins.h | 4 +++
clang/lib/Analysis/LifetimeSafety/Facts.cpp | 14 +++++-----
.../LifetimeSafety/FactsGenerator.cpp | 5 ++--
.../Analysis/LifetimeSafety/LiveOrigins.cpp | 6 ++--
.../LifetimeSafety/LoanPropagation.cpp | 5 ++--
clang/lib/Analysis/LifetimeSafety/Origins.cpp | 4 +++
7 files changed, 29 insertions(+), 37 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
index f4ff96786070a..0107c4d04e073 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Facts.h
@@ -234,10 +234,7 @@ class GlobalEscapeFact : public OriginEscapesFact {
class UseFact : public Fact {
const Expr *UseExpr;
- // For reference writes, handleAssignment narrows this to a single OriginID
- // for the outer origin (a Read of the reference binding) and creates a
- // separate Write UseFact for the inner origins.
- std::variant<const OriginList *, OriginID> Origins;
+ const OriginList *OList;
// True if this use is a write operation (e.g., left-hand side of assignment).
// Write operations are exempted from use-after-free checks.
bool IsWritten = false;
@@ -246,31 +243,14 @@ class UseFact : public Fact {
static bool classof(const Fact *F) { return F->getKind() == Kind::Use; }
UseFact(const Expr *UseExpr, const OriginList *OList)
- : Fact(Kind::Use), UseExpr(UseExpr), Origins(OList) {}
- UseFact(const Expr *UseExpr, OriginID OID)
- : Fact(Kind::Use), UseExpr(UseExpr), Origins(OID) {}
+ : Fact(Kind::Use), UseExpr(UseExpr), OList(OList) {}
+ const OriginList *getUsedOrigins() const { return OList; }
+ void setUsedOrigins(const OriginList *NewList) { OList = NewList; }
const Expr *getUseExpr() const { return UseExpr; }
void markAsWritten() { IsWritten = true; }
bool isWritten() const { return IsWritten; }
- void setOrigins(OriginID OID) { Origins = OID; }
-
- const OriginList *getOriginList() const {
- if (auto *OList = std::get_if<const OriginList *>(&Origins))
- return *OList;
- return nullptr;
- }
-
- template <typename Fn> void forEachOrigin(Fn &&F) const {
- if (const OriginList *OList = getOriginList()) {
- for (auto *Cur = OList; Cur; Cur = Cur->peelOuterOrigin())
- F(Cur->getOuterOriginID());
- } else {
- F(std::get<OriginID>(Origins));
- }
- }
-
void dump(llvm::raw_ostream &OS, const LoanManager &,
const OriginManager &OM) const override;
};
diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
index 8c638bdcace3f..a752f9939d482 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
@@ -145,6 +145,10 @@ class OriginManager {
/// \returns The OriginList, or nullptr for non-pointer rvalues.
OriginList *getOrCreateList(const Expr *E);
+ /// Wraps an existing OriginID in a new single-element OriginList, so a fact
+ /// can refer to a single level of an existing OriginList.
+ OriginList *createSingleOriginList(OriginID OID);
+
/// Returns the OriginList for the implicit 'this' parameter if the current
/// declaration is an instance method.
std::optional<OriginList *> getThisOrigins() const { return ThisOrigins; }
diff --git a/clang/lib/Analysis/LifetimeSafety/Facts.cpp b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
index d1dd396bdbe10..1bc0521a72359 100644
--- a/clang/lib/Analysis/LifetimeSafety/Facts.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Facts.cpp
@@ -80,14 +80,14 @@ void GlobalEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
void UseFact::dump(llvm::raw_ostream &OS, const LoanManager &,
const OriginManager &OM) const {
OS << "Use (";
- bool First = true;
- forEachOrigin([&](OriginID OID) {
- if (!First)
+ size_t NumUsedOrigins = getUsedOrigins()->getLength();
+ size_t I = 0;
+ for (const OriginList *Cur = getUsedOrigins(); Cur;
+ Cur = Cur->peelOuterOrigin(), ++I) {
+ OM.dump(Cur->getOuterOriginID(), OS);
+ if (I < NumUsedOrigins - 1)
OS << ", ";
- else
- First = false;
- OM.dump(OID, OS);
- });
+ }
OS << ", " << (isWritten() ? "Write" : "Read") << ")\n";
}
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index bf3589314d7f7..0719915144eea 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -374,9 +374,10 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr,
// live) and a Write of the inner origins (killing the pointee's
// liveness).
if (UseFact *UF = UseFacts.lookup(DRE_LHS)) {
- const OriginList *FullList = UF->getOriginList();
+ const OriginList *FullList = UF->getUsedOrigins();
assert(FullList);
- UF->setOrigins(FullList->getOuterOriginID());
+ UF->setUsedOrigins(FactMgr.getOriginMgr().createSingleOriginList(
+ FullList->getOuterOriginID()));
if (const OriginList *InnerList = FullList->peelOuterOrigin()) {
UseFact *WriteUF = FactMgr.createFact<UseFact>(DRE_LHS, InnerList);
WriteUF->markAsWritten();
diff --git a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
index de4d7fa833ddf..bc7494360624e 100644
--- a/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LiveOrigins.cpp
@@ -129,7 +129,9 @@ class AnalysisImpl
/// the origin since it overwrites the value.
Lattice transfer(Lattice In, const UseFact &UF) {
Lattice Out = In;
- UF.forEachOrigin([&](OriginID OID) {
+ for (const OriginList *Cur = UF.getUsedOrigins(); Cur;
+ Cur = Cur->peelOuterOrigin()) {
+ OriginID OID = Cur->getOuterOriginID();
// Write kills liveness.
if (UF.isWritten()) {
Out = Lattice(Factory.remove(Out.LiveOrigins, OID));
@@ -139,7 +141,7 @@ class AnalysisImpl
Out = Lattice(Factory.add(Out.LiveOrigins, OID,
LivenessInfo(&UF, LivenessKind::Must)));
}
- });
+ }
return Out;
}
diff --git a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
index 8960479edb17b..e437fb7d41268 100644
--- a/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
@@ -59,8 +59,9 @@ static llvm::BitVector computePersistentOrigins(const FactManager &FactMgr,
break;
}
case Fact::Kind::Use:
- F->getAs<UseFact>()->forEachOrigin(
- [&](OriginID OID) { CheckOrigin(OID); });
+ for (const OriginList *Cur = F->getAs<UseFact>()->getUsedOrigins(); Cur;
+ Cur = Cur->peelOuterOrigin())
+ CheckOrigin(Cur->getOuterOriginID());
break;
case Fact::Kind::MovedOrigin:
case Fact::Kind::OriginEscapes:
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index 0122f7a734541..df99a346c68e1 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -123,6 +123,10 @@ OriginList *OriginManager::createNode(const Expr *E, QualType QT) {
return new (ListAllocator.Allocate<OriginList>()) OriginList(NewID);
}
+OriginList *OriginManager::createSingleOriginList(OriginID OID) {
+ return new (ListAllocator.Allocate<OriginList>()) OriginList(OID);
+}
+
template <typename T>
OriginList *OriginManager::buildListForType(QualType QT, const T *Node) {
assert(hasOrigins(QT) && "buildListForType called for non-pointer type");
>From f2d2af9df3e1a765c0d11b33ed0b2446759d41d9 Mon Sep 17 00:00:00 2001
From: Zhijie Wang <yesterda9 at gmail.com>
Date: Wed, 8 Apr 2026 08:22:17 -0700
Subject: [PATCH 4/4] address review comments
---
.../LifetimeSafety/FactsGenerator.cpp | 33 ++++++++++---------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 0719915144eea..0b76428c86731 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -368,25 +368,26 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr,
if (const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr)) {
QualType QT = DRE_LHS->getDecl()->getType();
- if (QT->isReferenceType() && hasOrigins(QT->getPointeeType())) {
- // Writing through a reference uses the binding but overwrites the
- // pointee. Model this as a Read of the outer origin (keeping the binding
- // live) and a Write of the inner origins (killing the pointee's
- // liveness).
- if (UseFact *UF = UseFacts.lookup(DRE_LHS)) {
- const OriginList *FullList = UF->getUsedOrigins();
- assert(FullList);
- UF->setUsedOrigins(FactMgr.getOriginMgr().createSingleOriginList(
- FullList->getOuterOriginID()));
- if (const OriginList *InnerList = FullList->peelOuterOrigin()) {
- UseFact *WriteUF = FactMgr.createFact<UseFact>(DRE_LHS, InnerList);
- WriteUF->markAsWritten();
- CurrentBlockFacts.push_back(WriteUF);
+ if (QT->isReferenceType()) {
+ if (hasOrigins(QT->getPointeeType())) {
+ // Writing through a reference uses the binding but overwrites the
+ // pointee. Model this as a Read of the outer origin (keeping the
+ // binding live) and a Write of the inner origins (killing the pointee's
+ // liveness).
+ if (UseFact *UF = UseFacts.lookup(DRE_LHS)) {
+ const OriginList *FullList = UF->getUsedOrigins();
+ assert(FullList);
+ UF->setUsedOrigins(FactMgr.getOriginMgr().createSingleOriginList(
+ FullList->getOuterOriginID()));
+ if (const OriginList *InnerList = FullList->peelOuterOrigin()) {
+ UseFact *WriteUF = FactMgr.createFact<UseFact>(DRE_LHS, InnerList);
+ WriteUF->markAsWritten();
+ CurrentBlockFacts.push_back(WriteUF);
+ }
}
}
- } else if (!QT->isReferenceType()) {
+ } else
markUseAsWrite(DRE_LHS);
- }
}
// Kill the old loans of the destination origin and flow the new loans
// from the source origin.
More information about the cfe-commits
mailing list