Index: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -356,14 +356,12 @@ IteratorChecker::IteratorChecker() { OutOfRangeBugType.reset( - new BugType(this, "Iterator out of range", "Misuse of STL APIs", - /*SuppressOnSink=*/true)); + new BugType(this, "Iterator out of range", "Misuse of STL APIs")); MismatchedBugType.reset( new BugType(this, "Iterator(s) mismatched", "Misuse of STL APIs", /*SuppressOnSink=*/true)); InvalidatedBugType.reset( - new BugType(this, "Iterator invalidated", "Misuse of STL APIs", - /*SuppressOnSink=*/true)); + new BugType(this, "Iterator invalidated", "Misuse of STL APIs")); } void IteratorChecker::checkPreCall(const CallEvent &Call, @@ -928,7 +926,7 @@ auto State = C.getState(); const auto *Pos = getIteratorPosition(State, Val); if (Pos && isPastTheEnd(State, *Pos)) { - auto *N = C.generateNonFatalErrorNode(State); + auto *N = C.generateErrorNode(State); if (!N) return; reportOutOfRangeBug("Past-the-end iterator dereferenced.", Val, C, N); @@ -940,7 +938,7 @@ auto State = C.getState(); const auto *Pos = getIteratorPosition(State, Val); if (Pos && !Pos->isValid()) { - auto *N = C.generateNonFatalErrorNode(State); + auto *N = C.generateErrorNode(State); if (!N) { return; } @@ -1048,14 +1046,14 @@ // The result may be the past-end iterator of the container, but any other // out of range position is undefined behaviour if (isAheadOfRange(State, advancePosition(C, Op, *Pos, Value))) { - auto *N = C.generateNonFatalErrorNode(State); + auto *N = C.generateErrorNode(State); if (!N) return; reportOutOfRangeBug("Iterator decremented ahead of its valid range.", LHS, C, N); } if (isBehindPastTheEnd(State, advancePosition(C, Op, *Pos, Value))) { - auto *N = C.generateNonFatalErrorNode(State); + auto *N = C.generateErrorNode(State); if (!N) return; reportOutOfRangeBug("Iterator incremented behind the past-the-end " Index: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h =================================================================== --- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h +++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -150,7 +150,7 @@ typedef std::bidirectional_iterator_tag iterator_category; __list_iterator(T* it = 0) : item(it) {} - __list_iterator(const iterator &rhs): item(rhs.base()) {} + __list_iterator(const iterator &rhs): item(rhs.item) {} __list_iterator operator++() { item = item->next; return *this; } __list_iterator operator++(int) { auto tmp = *this; @@ -175,6 +175,9 @@ const T* &base() const { return item; } + template + friend struct __list_iterator; + private: T* item; }; @@ -190,7 +193,7 @@ typedef std::forward_iterator_tag iterator_category; __fwdl_iterator(T* it = 0) : item(it) {} - __fwdl_iterator(const iterator &rhs): item(rhs.base()) {} + __fwdl_iterator(const iterator &rhs): item(rhs.item) {} __fwdl_iterator operator++() { item = item->next; return *this; } __fwdl_iterator operator++(int) { auto tmp = *this; @@ -208,6 +211,9 @@ const T* &base() const { return item; } + template + friend struct __fwdl_iterator; + private: T* item; }; Index: cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp =================================================================== --- cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp +++ cfe/trunk/test/Analysis/diagnostics/explicit-suppression.cpp @@ -19,6 +19,6 @@ void testCopyNull(C *I, C *E) { std::copy(I, E, (C *)0); #ifndef SUPPRESSED - // expected-warning@../Inputs/system-header-simulator-cxx.h:680 {{Called C++ object pointer is null}} + // expected-warning@../Inputs/system-header-simulator-cxx.h:686 {{Called C++ object pointer is null}} #endif } Index: cfe/trunk/test/Analysis/invalidated-iterator.cpp =================================================================== --- cfe/trunk/test/Analysis/invalidated-iterator.cpp +++ cfe/trunk/test/Analysis/invalidated-iterator.cpp @@ -3,397 +3,762 @@ #include "Inputs/system-header-simulator-cxx.h" -void bad_copy_assign_operator_list1(std::list &L1, +void clang_analyzer_warnIfReached(); + +void bad_copy_assign_operator1_list(std::list &L1, const std::list &L2) { auto i0 = L1.cbegin(); L1 = L2; *i0; // expected-warning{{Invalidated iterator accessed}} + clang_analyzer_warnIfReached(); } -void bad_copy_assign_operator_vector1(std::vector &V1, +void bad_copy_assign_operator1_vector(std::vector &V1, const std::vector &V2) { auto i0 = V1.cbegin(); V1 = V2; *i0; // expected-warning{{Invalidated iterator accessed}} } -void bad_copy_assign_operator_deque1(std::deque &D1, +void bad_copy_assign_operator1_deque(std::deque &D1, const std::deque &D2) { auto i0 = D1.cbegin(); D1 = D2; *i0; // expected-warning{{Invalidated iterator accessed}} } -void bad_copy_assign_operator_forward_list1(std::forward_list &FL1, +void bad_copy_assign_operator1_forward_list(std::forward_list &FL1, const std::forward_list &FL2) { auto i0 = FL1.cbegin(); FL1 = FL2; *i0; // expected-warning{{Invalidated iterator accessed}} } -void bad_assign_list1(std::list &L, int n) { +void bad_assign1_list(std::list &L, int n) { auto i0 = L.cbegin(); L.assign(10, n); *i0; // expected-warning{{Invalidated iterator accessed}} } -void bad_assign_vector1(std::vector &V, int n) { +void bad_assign1_vector(std::vector &V, int n) { auto i0 = V.cbegin(); V.assign(10, n); *i0; // expected-warning{{Invalidated iterator accessed}} } -void bad_assign_deque1(std::deque &D, int n) { +void bad_assign1_deque(std::deque &D, int n) { auto i0 = D.cbegin(); D.assign(10, n); *i0; // expected-warning{{Invalidated iterator accessed}} } -void bad_assign_forward_list1(std::forward_list &FL, int n) { +void bad_assign1_forward_list(std::forward_list &FL, int n) { auto i0 = FL.cbegin(); FL.assign(10, n); *i0; // expected-warning{{Invalidated iterator accessed}} } -void good_clear_list1(std::list &L) { +void good_clear1_list(std::list &L) { auto i0 = L.cend(); L.clear(); --i0; // no-warning } -void bad_clear_list1(std::list &L) { +void bad_clear1_list(std::list &L) { auto i0 = L.cbegin(), i1 = L.cend(); L.clear(); *i0; // expected-warning{{Invalidated iterator accessed}} } -void bad_clear_vector1(std::vector &V) { +void bad_clear1_vector(std::vector &V) { auto i0 = V.cbegin(), i1 = V.cend(); V.clear(); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_clear1_vector_decr(std::vector &V) { + auto i0 = V.cbegin(), i1 = V.cend(); + V.clear(); --i1; // expected-warning{{Invalidated iterator accessed}} } -void bad_clear_deque1(std::deque &D) { +void bad_clear1_deque(std::deque &D) { auto i0 = D.cbegin(), i1 = D.cend(); D.clear(); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_clear1_deque_decr(std::deque &D) { + auto i0 = D.cbegin(), i1 = D.cend(); + D.clear(); --i1; // expected-warning{{Invalidated iterator accessed}} } -void good_push_back_list1(std::list &L, int n) { +void good_push_back1_list(std::list &L, int n) { auto i0 = L.cbegin(), i1 = L.cend(); L.push_back(n); *i0; // no-warning --i1; // no-warning } -void good_push_back_vector1(std::vector &V, int n) { +void good_push_back1_vector(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = V.cend(); V.push_back(n); *i0; // no-warning } -void bad_push_back_vector1(std::vector &V, int n) { +void bad_push_back1_vector(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = V.cend(); V.push_back(n); --i1; // expected-warning{{Invalidated iterator accessed}} } -void bad_push_back_deque1(std::deque &D, int n) { +void bad_push_back1_deque(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = D.cend(); D.push_back(n); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_push_back1_deque_decr(std::deque &D, int n) { + auto i0 = D.cbegin(), i1 = D.cend(); + D.push_back(n); --i1; // expected-warning{{Invalidated iterator accessed}} } -void good_emplace_back_list1(std::list &L, int n) { +void good_emplace_back1_list(std::list &L, int n) { auto i0 = L.cbegin(), i1 = L.cend(); L.emplace_back(n); *i0; // no-warning --i1; // no-warning } -void good_emplace_back_vector1(std::vector &V, int n) { +void good_emplace_back1_vector(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = V.cend(); V.emplace_back(n); *i0; // no-warning } -void bad_emplace_back_vector1(std::vector &V, int n) { +void bad_emplace_back1_vector(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = V.cend(); V.emplace_back(n); --i1; // expected-warning{{Invalidated iterator accessed}} } -void bad_emplace_back_deque1(std::deque &D, int n) { +void bad_emplace_back1_deque(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = D.cend(); D.emplace_back(n); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_emplace_back1_deque_decr(std::deque &D, int n) { + auto i0 = D.cbegin(), i1 = D.cend(); + D.emplace_back(n); --i1; // expected-warning{{Invalidated iterator accessed}} } -void good_pop_back_list1(std::list &L, int n) { +void good_pop_back1_list(std::list &L, int n) { auto i0 = L.cbegin(), i1 = L.cend(), i2 = i1--; L.pop_back(); *i0; // no-warning *i2; // no-warning } -void bad_pop_back_list1(std::list &L, int n) { +void bad_pop_back1_list(std::list &L, int n) { auto i0 = L.cbegin(), i1 = L.cend(), i2 = i1--; L.pop_back(); *i1; // expected-warning{{Invalidated iterator accessed}} } -void good_pop_back_vector1(std::vector &V, int n) { +void good_pop_back1_vector(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--; V.pop_back(); *i0; // no-warning } -void bad_pop_back_vector1(std::vector &V, int n) { +void bad_pop_back1_vector(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--; V.pop_back(); *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_pop_back1_vector_decr(std::vector &V, int n) { + auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--; + V.pop_back(); --i2; // expected-warning{{Invalidated iterator accessed}} } -void good_pop_back_deque1(std::deque &D, int n) { +void good_pop_back1_deque(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--; D.pop_back(); *i0; // no-warning } -void bad_pop_back_deque1(std::deque &D, int n) { +void bad_pop_back1_deque(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--; D.pop_back(); *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_pop_back1_deque_decr(std::deque &D, int n) { + auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--; + D.pop_back(); --i2; // expected-warning{{Invalidated iterator accessed}} } -void good_push_front_list1(std::list &L, int n) { +void good_push_front1_list(std::list &L, int n) { auto i0 = L.cbegin(), i1 = L.cend(); L.push_front(n); *i0; // no-warning --i1; // no-warning } -void bad_push_front_deque1(std::deque &D, int n) { +void bad_push_front1_deque(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = D.cend(); D.push_front(n); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_push_front1_deque_decr(std::deque &D, int n) { + auto i0 = D.cbegin(), i1 = D.cend(); + D.push_front(n); --i1; // expected-warning{{Invalidated iterator accessed}} } -void good_push_front_forward_list1(std::forward_list &FL, int n) { +void good_push_front1_forward_list(std::forward_list &FL, int n) { auto i0 = FL.cbegin(), i1 = FL.cend(); FL.push_front(n); *i0; // no-warning } -void good_emplace_front_list1(std::list &L, int n) { +void good_emplace_front1_list(std::list &L, int n) { auto i0 = L.cbegin(), i1 = L.cend(); L.emplace_front(n); *i0; // no-warning --i1; // no-warning } -void bad_emplace_front_deque1(std::deque &D, int n) { +void bad_emplace_front1_deque(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = D.cend(); D.emplace_front(n); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_emplace_front1_deque_decr(std::deque &D, int n) { + auto i0 = D.cbegin(), i1 = D.cend(); + D.emplace_front(n); --i1; // expected-warning{{Invalidated iterator accessed}} } -void good_emplace_front_forward_list1(std::forward_list &FL, int n) { +void good_emplace_front1_forward_list(std::forward_list &FL, int n) { auto i0 = FL.cbegin(), i1 = FL.cend(); FL.emplace_front(n); *i0; // no-warning } -void good_pop_front_list1(std::list &L, int n) { +void good_pop_front1_list(std::list &L, int n) { auto i1 = L.cbegin(), i0 = i1++; L.pop_front(); *i1; // no-warning } -void bad_pop_front_list1(std::list &L, int n) { +void bad_pop_front1_list(std::list &L, int n) { auto i1 = L.cbegin(), i0 = i1++; L.pop_front(); *i0; // expected-warning{{Invalidated iterator accessed}} } -void good_pop_front_deque1(std::deque &D, int n) { +void good_pop_front1_deque(std::deque &D, int n) { auto i1 = D.cbegin(), i0 = i1++; D.pop_front(); *i1; // no-warning } -void bad_pop_front_deque1(std::deque &D, int n) { +void bad_pop_front1_deque(std::deque &D, int n) { auto i1 = D.cbegin(), i0 = i1++; D.pop_front(); *i0; // expected-warning{{Invalidated iterator accessed}} } -void good_pop_front_forward_list1(std::forward_list &FL, int n) { +void good_pop_front1_forward_list(std::forward_list &FL, int n) { auto i1 = FL.cbegin(), i0 = i1++; FL.pop_front(); *i1; // no-warning } -void bad_pop_front_forward_list1(std::forward_list &FL, int n) { +void bad_pop_front1_forward_list(std::forward_list &FL, int n) { auto i1 = FL.cbegin(), i0 = i1++; FL.pop_front(); *i0; // expected-warning{{Invalidated iterator accessed}} } -void good_insert_list1(std::list &L, int n) { +void good_insert1_list1(std::list &L, int n) { auto i1 = L.cbegin(), i0 = i1++; L.insert(i1, n); *i0; // no-warning *i1; // no-warning } -void good_insert_vector1(std::vector &V, int n) { +void good_insert1_list2(std::list &L, int n) { + auto i1 = L.cbegin(), i0 = i1++; + i1 = L.insert(i1, n); + *i1; // no-warning +} + +void good_insert1_vector1(std::vector &V, int n) { auto i1 = V.cbegin(), i0 = i1++; V.insert(i1, n); *i0; // no-warning } -void bad_insert_vector1(std::vector &V, int n) { +void good_insert1_vector2(std::vector &V, int n) { + auto i1 = V.cbegin(), i0 = i1++; + i1 = V.insert(i1, n); + *i1; // no-warning +} + +void bad_insert1_vector(std::vector &V, int n) { auto i1 = V.cbegin(), i0 = i1++; V.insert(i1, n); *i1; // expected-warning{{Invalidated iterator accessed}} } -void bad_insert_deque1(std::deque &D, int n) { +void good_insert1_deque(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + i0 = D.insert(i1, n); + *i0; // no-warning +} + +void bad_insert1_deque1(std::deque &D, int n) { auto i1 = D.cbegin(), i0 = i1++; D.insert(i1, n); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_insert1_deque2(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + D.insert(i1, n); *i1; // expected-warning{{Invalidated iterator accessed}} } -void good_emplace_list1(std::list &L, int n) { +void good_insert2_list1(std::list &L, int n) { + auto i1 = L.cbegin(), i0 = i1++; + L.insert(i1, std::move(n)); + *i0; // no-warning + *i1; // no-warning +} + +void good_insert2_list2(std::list &L, int n) { + auto i1 = L.cbegin(), i0 = i1++; + i1 = L.insert(i1, std::move(n)); + *i1; // no-warning +} + +void good_insert2_vector1(std::vector &V, int n) { + auto i1 = V.cbegin(), i0 = i1++; + V.insert(i1, std::move(n)); + *i0; // no-warning +} + +void good_insert2_vector2(std::vector &V, int n) { + auto i1 = V.cbegin(), i0 = i1++; + i1 = V.insert(i1, std::move(n)); + *i1; // no-warning +} + +void bad_insert2_vector(std::vector &V, int n) { + auto i1 = V.cbegin(), i0 = i1++; + V.insert(i1, std::move(n)); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_insert2_deque(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + i1 = D.insert(i1, std::move(n)); + *i1; // no-warning +} + +void bad_insert2_deque1(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + D.insert(i1, std::move(n)); + *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_insert2_deque2(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + D.insert(i1, std::move(n)); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_insert3_list1(std::list &L, int n) { + auto i1 = L.cbegin(), i0 = i1++; + L.insert(i1, 10, n); + *i0; // no-warning + *i1; // no-warning +} + +void good_insert3_list2(std::list &L, int n) { + auto i1 = L.cbegin(), i0 = i1++; + i1 = L.insert(i1, 10, n); + *i1; // no-warning +} + +void good_insert3_vector1(std::vector &V, int n) { + auto i1 = V.cbegin(), i0 = i1++; + V.insert(i1, 10, n); + *i0; // no-warning +} + +void good_insert3_vector2(std::vector &V, int n) { + auto i1 = V.cbegin(), i0 = i1++; + i1 = V.insert(i1, 10, n); + *i1; // no-warning +} + +void bad_insert3_vector(std::vector &V, int n) { + auto i1 = V.cbegin(), i0 = i1++; + V.insert(i1, 10, n); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_insert3_deque(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + i1 = D.insert(i1, 10, std::move(n)); + *i1; // no-warning +} + +void bad_insert3_deque1(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + D.insert(i1, 10, std::move(n)); + *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_insert3_deque2(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + D.insert(i1, 10, std::move(n)); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_insert4_list1(std::list &L1, std::list &L2, int n) { + auto i1 = L1.cbegin(), i0 = i1++; + L1.insert(i1, L2.cbegin(), L2.cend()); + *i0; // no-warning + *i1; // no-warning +} + +void good_insert4_list2(std::list &L1, std::list &L2, int n) { + auto i1 = L1.cbegin(), i0 = i1++; + i1 = L1.insert(i1, L2.cbegin(), L2.cend()); + *i1; // no-warning +} + +void good_insert4_vector1(std::vector &V1, std::vector &V2, int n) { + auto i1 = V1.cbegin(), i0 = i1++; + V1.insert(i1, V2.cbegin(), V2.cend()); + *i0; // no-warning +} + +void good_insert4_vector2(std::vector &V1, std::vector &V2, int n) { + auto i1 = V1.cbegin(), i0 = i1++; + i1 = V1.insert(i1, V2.cbegin(), V2.cend()); + *i1; // no-warning +} + +void bad_insert4_vector(std::vector &V1, std::vector &V2, int n) { + auto i1 = V1.cbegin(), i0 = i1++; + V1.insert(i1, V2.cbegin(), V2.cend()); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_insert4_deque(std::deque &D1, std::deque &D2, int n) { + auto i1 = D1.cbegin(), i0 = i1++; + i1 = D1.insert(i1, D2.cbegin(), D2.cend()); + *i1; // no-warning +} + +void bad_insert4_deque1(std::deque &D1, std::deque &D2, int n) { + auto i1 = D1.cbegin(), i0 = i1++; + D1.insert(i1, D2.cbegin(), D2.cend()); + *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_insert4_deque2(std::deque &D1, std::deque &D2, int n) { + auto i1 = D1.cbegin(), i0 = i1++; + D1.insert(i1, D2.cbegin(), D2.cend()); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_insert5_list1(std::list &L) { + auto i1 = L.cbegin(), i0 = i1++; + L.insert(i1, {1, 2, 3, 4}); + *i0; // no-warning + *i1; // no-warning +} + +void good_insert5_list2(std::list &L) { + auto i1 = L.cbegin(), i0 = i1++; + i1 = L.insert(i1, {1, 2, 3, 4}); + *i1; // no-warning +} + +void good_insert5_vector1(std::vector &V) { + auto i1 = V.cbegin(), i0 = i1++; + V.insert(i1, {1, 2, 3, 4}); + *i0; // no-warning +} + +void good_insert5_vector2(std::vector &V) { + auto i1 = V.cbegin(), i0 = i1++; + i1 = V.insert(i1, {1, 2, 3, 4}); + *i1; // no-warning +} + +void bad_insert5_vector(std::vector &V) { + auto i1 = V.cbegin(), i0 = i1++; + V.insert(i1, {1, 2, 3, 4}); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_insert5_deque(std::deque &D) { + auto i1 = D.cbegin(), i0 = i1++; + i1 = D.insert(i1, {1, 2, 3, 4}); + *i1; // no-warning +} + +void bad_insert5_deque1(std::deque &D) { + auto i1 = D.cbegin(), i0 = i1++; + D.insert(i1, {1, 2, 3, 4}); + *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_insert5_deque2(std::deque &D) { + auto i1 = D.cbegin(), i0 = i1++; + D.insert(i1, {1, 2, 3, 4}); + *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void good_emplace1_list(std::list &L, int n) { auto i1 = L.cbegin(), i0 = i1++; L.emplace(i1, n); *i0; // no-warning *i1; // no-warning } -void good_emplace_vector1(std::vector &V, int n) { +void good_emplace1_vector(std::vector &V, int n) { auto i1 = V.cbegin(), i0 = i1++; V.emplace(i1, n); *i0; // no-warning } -void bad_emplace_vector1(std::vector &V, int n) { +void bad_emplace1_vector(std::vector &V, int n) { auto i1 = V.cbegin(), i0 = i1++; V.emplace(i1, n); *i1; // expected-warning{{Invalidated iterator accessed}} } -void bad_emplace_deque1(std::deque &D, int n) { +void bad_emplace1_deque1(std::deque &D, int n) { auto i1 = D.cbegin(), i0 = i1++; D.emplace(i1, n); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_emplace1_deque2(std::deque &D, int n) { + auto i1 = D.cbegin(), i0 = i1++; + D.emplace(i1, n); *i1; // expected-warning{{Invalidated iterator accessed}} } -void good_erase_list1(std::list &L) { +void good_erase1_list1(std::list &L) { auto i2 = L.cbegin(), i0 = i2++, i1 = i2++; L.erase(i1); *i0; // no-warning *i2; // no-warning } -void bad_erase_list1(std::list &L) { +void good_erase1_list2(std::list &L) { + auto i0 = L.cbegin(); + i0 = L.erase(i0); + *i0; // no-warning +} + +void bad_erase1_list(std::list &L) { auto i0 = L.cbegin(); L.erase(i0); *i0; // expected-warning{{Invalidated iterator accessed}} } -void good_erase_vector1(std::vector &V) { +void good_erase1_vector1(std::vector &V) { auto i2 = V.cbegin(), i0 = i2++, i1 = i2++; V.erase(i1); *i0; // no-warning } -void bad_erase_vector1(std::vector &V) { +void good_erase1_vector2(std::vector &V) { + auto i0 = V.cbegin(); + i0 = V.erase(i0); + *i0; // no-warning +} + +void bad_erase1_vector1(std::vector &V) { auto i1 = V.cbegin(), i0 = i1++; V.erase(i0); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase1_vector2(std::vector &V) { + auto i1 = V.cbegin(), i0 = i1++; + V.erase(i0); *i1; // expected-warning{{Invalidated iterator accessed}} } -void bad_erase_deque1(std::deque &D) { +void good_erase1_deque(std::deque &D) { + auto i0 = D.cbegin(); + i0 = D.erase(i0); + *i0; // no-warning +} + +void bad_erase1_deque1(std::deque &D) { auto i2 = D.cbegin(), i0 = i2++, i1 = i2++; D.erase(i1); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase1_deque2(std::deque &D) { + auto i2 = D.cbegin(), i0 = i2++, i1 = i2++; + D.erase(i1); *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase1_deque3(std::deque &D) { + auto i2 = D.cbegin(), i0 = i2++, i1 = i2++; + D.erase(i1); *i2; // expected-warning{{Invalidated iterator accessed}} } -void good_erase_list2(std::list &L) { +void good_erase2_list1(std::list &L) { auto i3 = L.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; L.erase(i1, i3); *i0; // no-warning *i3; // no-warning } -void bad_erase_list2(std::list &L) { +void good_erase2_list2(std::list &L) { + auto i2 = L.cbegin(), i0 = i2++, i1 = i2++; + i0 = L.erase(i0, i2); + *i0; // no-warning +} + +void bad_erase2_list1(std::list &L) { auto i2 = L.cbegin(), i0 = i2++, i1 = i2++; L.erase(i0, i2); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase2_list2(std::list &L) { + auto i2 = L.cbegin(), i0 = i2++, i1 = i2++; + L.erase(i0, i2); *i1; // expected-warning{{Invalidated iterator accessed}} } -void good_erase_vector2(std::vector &V) { +void good_erase2_vector1(std::vector &V) { auto i3 = V.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;; V.erase(i1, i3); *i0; // no-warning } -void bad_erase_vector2(std::vector &V) { +void good_erase2_vector2(std::vector &V) { + auto i2 = V.cbegin(), i0 = i2++, i1 = i2++; + i0 = V.erase(i0, i2); + *i0; // no-warning +} + +void bad_erase2_vector1(std::vector &V) { auto i2 = V.cbegin(), i0 = i2++, i1 = i2++; V.erase(i0, i2); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase2_vector2(std::vector &V) { + auto i2 = V.cbegin(), i0 = i2++, i1 = i2++; + V.erase(i0, i2); *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase2_vector3(std::vector &V) { + auto i2 = V.cbegin(), i0 = i2++, i1 = i2++; + V.erase(i0, i2); *i2; // expected-warning{{Invalidated iterator accessed}} } -void bad_erase_deque2(std::deque &D) { +void good_erase2_deque(std::deque &D) { + auto i2 = D.cbegin(), i0 = i2++, i1 = i2++; + i0 = D.erase(i0, i2); + *i0; // no-warning +} + +void bad_erase2_deque1(std::deque &D) { auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; D.erase(i1, i3); *i0; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase2_deque2(std::deque &D) { + auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; + D.erase(i1, i3); *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase2_deque3(std::deque &D) { + auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; + D.erase(i1, i3); *i2; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase2_deque4(std::deque &D) { + auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; + D.erase(i1, i3); *i3; // expected-warning{{Invalidated iterator accessed}} } -void good_erase_after_forward_list1(std::forward_list &FL) { +void good_erase_after1_forward_list1(std::forward_list &FL) { auto i2 = FL.cbegin(), i0 = i2++, i1 = i2++; FL.erase_after(i0); *i0; // no-warning *i2; // no-warning } -void bad_erase_after_forward_list1(std::forward_list &FL) { +void good_erase_after1_forward_lis2(std::forward_list &FL) { + auto i1 = FL.cbegin(), i0 = i1++; + i1 = FL.erase_after(i0); + *i1; // no-warning +} + +void bad_erase_after1_forward_list(std::forward_list &FL) { auto i1 = FL.cbegin(), i0 = i1++; FL.erase_after(i0); *i1; // expected-warning{{Invalidated iterator accessed}} } -void good_erase_after_forward_list2(std::forward_list &FL) { +void good_erase_after2_forward_list1(std::forward_list &FL) { auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; FL.erase_after(i0, i3); *i0; // no-warning *i3; // no-warning } -void bad_erase_after_forward_list2(std::forward_list &FL) { +void good_erase_after2_forward_list2(std::forward_list &FL) { + auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; + i2 = FL.erase_after(i0, i3); + *i2; // no-warning +} + +void bad_erase_after2_forward_list1(std::forward_list &FL) { auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; FL.erase_after(i0, i3); *i1; // expected-warning{{Invalidated iterator accessed}} +} + +void bad_erase_after2_forward_list2(std::forward_list &FL) { + auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++; + FL.erase_after(i0, i3); *i2; // expected-warning{{Invalidated iterator accessed}} } Index: cfe/trunk/test/Analysis/iterator-range.cpp =================================================================== --- cfe/trunk/test/Analysis/iterator-range.cpp +++ cfe/trunk/test/Analysis/iterator-range.cpp @@ -24,6 +24,7 @@ void simple_bad_end(const std::vector &v) { auto i = v.end(); *i; // expected-warning{{Past-the-end iterator dereferenced}} + clang_analyzer_warnIfReached(); } void copy(const std::vector &v) {