Skip to content

Commit 600a576

Browse files
committed
address comments and make expired loans hermetic
1 parent 894fa21 commit 600a576

File tree

2 files changed

+51
-32
lines changed

2 files changed

+51
-32
lines changed

clang/lib/Analysis/LifetimeSafety.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -901,8 +901,8 @@ struct ExpiredLattice {
901901
OS << "ExpiredLattice State:\n";
902902
if (Expired.isEmpty())
903903
OS << " <empty>\n";
904-
for (const auto &ID_ : Expired)
905-
OS << " Loan " << ID_.first << " is expired\n";
904+
for (const auto &[ID, _] : Expired)
905+
OS << " Loan " << ID << " is expired\n";
906906
}
907907
};
908908

@@ -928,8 +928,10 @@ class ExpiredLoansAnalysis
928928
Lattice join(Lattice L1, Lattice L2) {
929929
return Lattice(
930930
utils::join(L1.Expired, L2.Expired, Factory,
931-
// Take any ExpireFact to join the values.
932-
[](const ExpireFact *F, const ExpireFact *) { return F; }));
931+
// Take the last expiry fact to make this hermetic.
932+
[](const ExpireFact *F1, const ExpireFact *F2) {
933+
return F1->getExpiryLoc() > F2->getExpiryLoc() ? F1 : F2;
934+
}));
933935
}
934936

935937
Lattice transfer(Lattice In, const ExpireFact &F) {
@@ -975,10 +977,9 @@ class ExpiredLoansAnalysis
975977

976978
/// Struct to store the complete context for a potential lifetime violation.
977979
struct PendingWarning {
978-
const Expr *IssueExpr; // Where the loan was originally issued.
979980
SourceLocation ExpiryLoc; // Where the loan expired.
980981
const Expr *UseExpr; // Where the origin holding this loan was used.
981-
Confidence Level;
982+
Confidence ConfidenceLevel;
982983
};
983984

984985
class LifetimeChecker {
@@ -1052,28 +1053,26 @@ class LifetimeChecker {
10521053
// If we already have a warning for this loan with a higher or equal
10531054
// confidence, skip this one.
10541055
if (FinalWarningsMap.count(DefaultedLoan) &&
1055-
CurrentConfidence <= FinalWarningsMap[DefaultedLoan].Level)
1056+
CurrentConfidence <= FinalWarningsMap[DefaultedLoan].ConfidenceLevel)
10561057
continue;
10571058

1058-
const Loan &L = FactMgr.getLoanMgr().getLoan(DefaultedLoan);
10591059
auto *EF = AllExpiredLoans.lookup(DefaultedLoan);
10601060
assert(EF && "Could not find ExpireFact for an expired loan.");
10611061

1062-
const Expr *IssueExpr = L.IssueExpr;
1063-
SourceLocation ExpiryLoc = dyn_cast<ExpireFact>(*EF)->getExpiryLoc();
1064-
1065-
FinalWarningsMap[DefaultedLoan] = {IssueExpr, ExpiryLoc, UF->getUseExpr(),
1066-
CurrentConfidence};
1062+
FinalWarningsMap[DefaultedLoan] = {/*ExpiryLoc=*/(*EF)->getExpiryLoc(),
1063+
/*UseExpr=*/UF->getUseExpr(),
1064+
/*ConfidenceLevel=*/CurrentConfidence};
10671065
}
10681066
}
10691067

10701068
void issuePendingWarnings() {
10711069
if (!Reporter)
10721070
return;
1073-
for (const auto &pair : FinalWarningsMap) {
1074-
const PendingWarning &PW = pair.second;
1075-
Reporter->reportUseAfterFree(PW.IssueExpr, PW.UseExpr, PW.ExpiryLoc,
1076-
PW.Level);
1071+
for (const auto &[LID, Warning] : FinalWarningsMap) {
1072+
const Loan &L = FactMgr.getLoanMgr().getLoan(LID);
1073+
const Expr *IssueExpr = L.IssueExpr;
1074+
Reporter->reportUseAfterFree(IssueExpr, Warning.UseExpr,
1075+
Warning.ExpiryLoc, Warning.ConfidenceLevel);
10771076
}
10781077
}
10791078
};

clang/test/Sema/warn-lifetime-safety.cpp

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,41 @@ void potential_loop_with_break(bool cond) {
182182
(void)*p; // expected-note {{later used here}}
183183
}
184184

185+
void potential_multiple_expiry_of_same_loan(bool cond) {
186+
// Choose the last expiry location for the loan.
187+
MyObj safe;
188+
MyObj* p = &safe;
189+
for (int i = 0; i < 10; ++i) {
190+
MyObj unsafe;
191+
if (cond) {
192+
p = &unsafe; // expected-warning {{may not live long enough}}
193+
break;
194+
}
195+
} // expected-note {{destroyed here}}
196+
(void)*p; // expected-note {{later used here}}
197+
198+
p = &safe;
199+
for (int i = 0; i < 10; ++i) {
200+
MyObj unsafe;
201+
if (cond) {
202+
p = &unsafe; // expected-warning {{may not live long enough}}
203+
if (cond)
204+
break;
205+
}
206+
} // expected-note {{destroyed here}}
207+
(void)*p; // expected-note {{later used here}}
208+
209+
p = &safe;
210+
for (int i = 0; i < 10; ++i) {
211+
if (cond) {
212+
MyObj unsafe2;
213+
p = &unsafe2; // expected-warning {{may not live long enough}}
214+
break; // expected-note {{destroyed here}}
215+
}
216+
}
217+
(void)*p; // expected-note {{later used here}}
218+
}
219+
185220
void potential_switch(int mode) {
186221
MyObj safe;
187222
MyObj* p = &safe;
@@ -236,18 +271,3 @@ void no_error_if_dangle_then_rescue() {
236271
p = &safe; // p is "rescued" before use.
237272
(void)*p; // This is safe.
238273
}
239-
240-
// MyObj some_name(bool condition, MyObj x) {
241-
// MyObj* p = &x;
242-
// MyObj* q = &x;
243-
// if (condition)
244-
// {
245-
// MyObj y{20};
246-
// MyObj * abcd = &y;
247-
// p = abcd;
248-
// q = abcd;
249-
// }
250-
// MyObj a = *p;
251-
// MyObj b = *q;
252-
// return a + b;
253-
// }

0 commit comments

Comments
 (0)