aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp18
-rw-r--r--clang/test/Analysis/Inputs/system-header-simulator-cxx.h4
-rw-r--r--clang/test/Analysis/mismatched-iterator.cpp10
3 files changed, 26 insertions, 6 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
index 82a6228..1c101b9 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp
@@ -91,12 +91,18 @@ void MismatchedIteratorChecker::checkPreCall(const CallEvent &Call,
InstCall->getCXXThisVal().getAsRegion());
}
} else if (isInsertCall(Func)) {
- verifyMatch(C, Call.getArgSVal(0),
- InstCall->getCXXThisVal().getAsRegion());
- if (Call.getNumArgs() == 3 &&
- isIteratorType(Call.getArgExpr(1)->getType()) &&
- isIteratorType(Call.getArgExpr(2)->getType())) {
- verifyMatch(C, Call.getArgSVal(1), Call.getArgSVal(2));
+ if (Call.getNumArgs() == 2 &&
+ isIteratorType(Call.getArgExpr(0)->getType()) &&
+ isIteratorType(Call.getArgExpr(1)->getType())) {
+ verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+ } else {
+ verifyMatch(C, Call.getArgSVal(0),
+ InstCall->getCXXThisVal().getAsRegion());
+ if (Call.getNumArgs() == 3 &&
+ isIteratorType(Call.getArgExpr(1)->getType()) &&
+ isIteratorType(Call.getArgExpr(2)->getType())) {
+ verifyMatch(C, Call.getArgSVal(1), Call.getArgSVal(2));
+ }
}
} else if (isEmplaceCall(Func)) {
verifyMatch(C, Call.getArgSVal(0),
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h
index a379a47..c5aeb0af 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -1244,6 +1244,7 @@ template<
class Alloc = std::allocator<Key>
> class unordered_set {
public:
+ unordered_set() {}
unordered_set(initializer_list<Key> __list) {}
class iterator {
@@ -1260,6 +1261,9 @@ template<
Key *val;
iterator begin() const { return iterator(val); }
iterator end() const { return iterator(val + 1); }
+
+ template< class InputIt >
+ void insert( InputIt first, InputIt last );
};
template <typename T>
diff --git a/clang/test/Analysis/mismatched-iterator.cpp b/clang/test/Analysis/mismatched-iterator.cpp
index 570e742..325e776 100644
--- a/clang/test/Analysis/mismatched-iterator.cpp
+++ b/clang/test/Analysis/mismatched-iterator.cpp
@@ -19,6 +19,11 @@ void good_insert4(std::vector<int> &V, int len, int n) {
V.insert(V.cbegin(), {n-1, n, n+1}); // no-warning
}
+void good_insert5(std::vector<int> &V, int len, int n) {
+ std::unordered_set<int> us;
+ us.insert(V.cbegin(), V.cend()); // no-warning
+}
+
void good_insert_find(std::vector<int> &V, int n, int m) {
auto i = std::find(V.cbegin(), V.cend(), n);
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) {
V2.insert(V1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container accessed using foreign iterator argument}}
}
+void bad_insert5(std::vector<int> &V1, std::vector<int> &V2, int len, int n) {
+ std::unordered_set<int> us;
+ us.insert(V1.cbegin(), V2.cend()); // expected-warning{{Iterators of different containers used where the same container is expected}}
+}
+
void bad_erase1(std::vector<int> &V1, std::vector<int> &V2) {
V2.erase(V1.cbegin()); // expected-warning{{Container accessed using foreign iterator argument}}
}