11
11
#include " clang/ASTMatchers/ASTMatchers.h"
12
12
#include " clang/Testing/TestAST.h"
13
13
#include " llvm/ADT/StringMap.h"
14
+ #include " llvm/Testing/Support/Error.h"
14
15
#include " gmock/gmock.h"
15
16
#include " gtest/gtest.h"
16
17
#include < optional>
@@ -96,21 +97,18 @@ class LifetimeTestHelper {
96
97
return OID;
97
98
}
98
99
99
- std::optional <LoanID> getLoanForVar (llvm::StringRef VarName) {
100
+ std::vector <LoanID> getLoansForVar (llvm::StringRef VarName) {
100
101
auto *VD = findDecl<VarDecl>(VarName);
101
- if (!VD)
102
- return std::nullopt;
102
+ if (!VD) {
103
+ ADD_FAILURE () << " No VarDecl found for '" << VarName << " '" ;
104
+ return {};
105
+ }
103
106
std::vector<LoanID> LID = Analysis.getLoanIDForVar (VD);
104
107
if (LID.empty ()) {
105
108
ADD_FAILURE () << " Loan for '" << VarName << " ' not found." ;
106
- return std::nullopt;
107
- }
108
- // TODO: Support retrieving more than one loans to a var.
109
- if (LID.size () > 1 ) {
110
- ADD_FAILURE () << " More than 1 loans found for '" << VarName;
111
- return std::nullopt;
109
+ return {};
112
110
}
113
- return LID[ 0 ] ;
111
+ return LID;
114
112
}
115
113
116
114
std::optional<LoanSet> getLoansAtPoint (OriginID OID,
@@ -121,13 +119,12 @@ class LifetimeTestHelper {
121
119
return Analysis.getLoansAtPoint (OID, PP);
122
120
}
123
121
124
- std::optional<llvm::DenseSet <LoanID>>
122
+ std::optional<std::vector <LoanID>>
125
123
getExpiredLoansAtPoint (llvm::StringRef Annotation) {
126
124
ProgramPoint PP = Runner.getProgramPoint (Annotation);
127
125
if (!PP)
128
126
return std::nullopt;
129
- auto Expired = Analysis.getExpiredLoansAtPoint (PP);
130
- return llvm::DenseSet<LoanID>{Expired.begin (), Expired.end ()};
127
+ return Analysis.getExpiredLoansAtPoint (PP);
131
128
}
132
129
133
130
private:
@@ -197,12 +194,13 @@ MATCHER_P2(HasLoansToImpl, LoanVars, Annotation, "") {
197
194
198
195
std::vector<LoanID> ExpectedLoans;
199
196
for (const auto &LoanVar : LoanVars) {
200
- std::optional <LoanID> ExpectedLIDOpt = Info.Helper .getLoanForVar (LoanVar);
201
- if (!ExpectedLIDOpt ) {
197
+ std::vector <LoanID> ExpectedLIDs = Info.Helper .getLoansForVar (LoanVar);
198
+ if (ExpectedLIDs. empty () ) {
202
199
*result_listener << " could not find loan for var '" << LoanVar << " '" ;
203
200
return false ;
204
201
}
205
- ExpectedLoans.push_back (*ExpectedLIDOpt);
202
+ ExpectedLoans.insert (ExpectedLoans.end (), ExpectedLIDs.begin (),
203
+ ExpectedLIDs.end ());
206
204
}
207
205
208
206
return ExplainMatchResult (UnorderedElementsAreArray (ExpectedLoans),
@@ -221,17 +219,17 @@ MATCHER_P(AreExpiredAt, Annotation, "") {
221
219
<< Annotation << " '" ;
222
220
return false ;
223
221
}
224
- std::vector<LoanID> ActualExpiredLoans (ActualExpiredSetOpt->begin (),
225
- ActualExpiredSetOpt->end ());
222
+ std::vector<LoanID> ActualExpiredLoans = *ActualExpiredSetOpt;
226
223
std::vector<LoanID> ExpectedExpiredLoans;
227
224
for (const auto &VarName : Info.LoanVars ) {
228
- auto LoanIDOpt = Helper.getLoanForVar (VarName);
229
- if (!LoanIDOpt ) {
225
+ auto LoanIDs = Helper.getLoansForVar (VarName);
226
+ if (LoanIDs. empty () ) {
230
227
*result_listener << " could not find a loan for variable '" << VarName
231
228
<< " '" ;
232
229
return false ;
233
230
}
234
- ExpectedExpiredLoans.push_back (*LoanIDOpt);
231
+ ExpectedExpiredLoans.insert (ExpectedExpiredLoans.end (), LoanIDs.begin (),
232
+ LoanIDs.end ());
235
233
}
236
234
return ExplainMatchResult (UnorderedElementsAreArray (ExpectedExpiredLoans),
237
235
ActualExpiredLoans, result_listener);
@@ -730,5 +728,17 @@ TEST_F(LifetimeAnalysisTest, ReassignedPointerThenOriginalExpires) {
730
728
EXPECT_THAT (LoansTo ({" s1" , " s2" }), AreExpiredAt (" p_after_s1_expires" ));
731
729
}
732
730
731
+ TEST_F (LifetimeAnalysisTest, NoDuplicateLoansForImplicitCastToConst) {
732
+ SetupTest (R"(
733
+ void target() {
734
+ MyObj a;
735
+ const MyObj* p = &a;
736
+ const MyObj* q = p;
737
+ POINT(at_end);
738
+ }
739
+ )" );
740
+ EXPECT_THAT (Helper->getLoansForVar (" a" ), testing::SizeIs (1 ));
741
+ }
742
+
733
743
} // anonymous namespace
734
744
} // namespace clang::lifetimes::internal
0 commit comments