Skip to content

Commit 2fe7585

Browse files
authored
[clang][analyzer] Improve the modeling of insert in MismatchedIteratorChecker (#132596)
Fixes #132010 Associative containers in STL has an unique `insert` overload member function comparing to un-associative containers(https://en.cppreference.com/w/cpp/container/unordered_set/insert): ``` template< class InputIt > void insert( InputIt first, InputIt last ); ``` Add support for this `insert` overload in `MismatchedIteratorChecker`, verify if `first` and `last` belongs to the same container in this case.
1 parent 4a76434 commit 2fe7585

File tree

3 files changed

+26
-6
lines changed

3 files changed

+26
-6
lines changed

clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,18 @@ void MismatchedIteratorChecker::checkPreCall(const CallEvent &Call,
9191
InstCall->getCXXThisVal().getAsRegion());
9292
}
9393
} else if (isInsertCall(Func)) {
94-
verifyMatch(C, Call.getArgSVal(0),
95-
InstCall->getCXXThisVal().getAsRegion());
96-
if (Call.getNumArgs() == 3 &&
97-
isIteratorType(Call.getArgExpr(1)->getType()) &&
98-
isIteratorType(Call.getArgExpr(2)->getType())) {
99-
verifyMatch(C, Call.getArgSVal(1), Call.getArgSVal(2));
94+
if (Call.getNumArgs() == 2 &&
95+
isIteratorType(Call.getArgExpr(0)->getType()) &&
96+
isIteratorType(Call.getArgExpr(1)->getType())) {
97+
verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
98+
} else {
99+
verifyMatch(C, Call.getArgSVal(0),
100+
InstCall->getCXXThisVal().getAsRegion());
101+
if (Call.getNumArgs() == 3 &&
102+
isIteratorType(Call.getArgExpr(1)->getType()) &&
103+
isIteratorType(Call.getArgExpr(2)->getType())) {
104+
verifyMatch(C, Call.getArgSVal(1), Call.getArgSVal(2));
105+
}
100106
}
101107
} else if (isEmplaceCall(Func)) {
102108
verifyMatch(C, Call.getArgSVal(0),

clang/test/Analysis/Inputs/system-header-simulator-cxx.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,7 @@ template<
12441244
class Alloc = std::allocator<Key>
12451245
> class unordered_set {
12461246
public:
1247+
unordered_set() {}
12471248
unordered_set(initializer_list<Key> __list) {}
12481249

12491250
class iterator {
@@ -1260,6 +1261,9 @@ template<
12601261
Key *val;
12611262
iterator begin() const { return iterator(val); }
12621263
iterator end() const { return iterator(val + 1); }
1264+
1265+
template< class InputIt >
1266+
void insert( InputIt first, InputIt last );
12631267
};
12641268

12651269
template <typename T>

clang/test/Analysis/mismatched-iterator.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ void good_insert4(std::vector<int> &V, int len, int n) {
1919
V.insert(V.cbegin(), {n-1, n, n+1}); // no-warning
2020
}
2121

22+
void good_insert5(std::vector<int> &V, int len, int n) {
23+
std::unordered_set<int> us;
24+
us.insert(V.cbegin(), V.cend()); // no-warning
25+
}
26+
2227
void good_insert_find(std::vector<int> &V, int n, int m) {
2328
auto i = std::find(V.cbegin(), V.cend(), n);
2429
V.insert(i, m); // no-warning
@@ -70,6 +75,11 @@ void bad_insert4(std::vector<int> &V1, std::vector<int> &V2, int len, int n) {
7075
V2.insert(V1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container accessed using foreign iterator argument}}
7176
}
7277

78+
void bad_insert5(std::vector<int> &V1, std::vector<int> &V2, int len, int n) {
79+
std::unordered_set<int> us;
80+
us.insert(V1.cbegin(), V2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}}
81+
}
82+
7383
void bad_erase1(std::vector<int> &V1, std::vector<int> &V2) {
7484
V2.erase(V1.cbegin()); // expected-warning{{Container accessed using foreign iterator argument}}
7585
}

0 commit comments

Comments
 (0)