// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify #include "Inputs/system-header-simulator-cxx.h" void clang_analyzer_warnIfReached(); // Dereference - operator*() void deref_begin(const std::vector &V) { auto i = V.begin(); *i; // no-warning } void deref_begind_begin(const std::vector &V) { auto i = ++V.begin(); *i; // no-warning } template Iter return_any_iterator(const Iter &It); void deref_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); *i; // no-warning } void deref_ahead_of_end(const std::vector &V) { auto i = --V.end(); *i; // no-warning } void deref_end(const std::vector &V) { auto i = V.end(); *i; // expected-warning{{Past-the-end iterator dereferenced}} } // Prefix increment - operator++() void incr_begin(const std::vector &V) { auto i = V.begin(); ++i; // no-warning } void incr_behind_begin(const std::vector &V) { auto i = ++V.begin(); ++i; // no-warning } void incr_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); ++i; // no-warning } void incr_ahead_of_end(const std::vector &V) { auto i = --V.end(); ++i; // no-warning } void incr_end(const std::vector &V) { auto i = V.end(); ++i; // expected-warning{{Iterator incremented behind the past-the-end iterator}} } // Postfix increment - operator++(int) void begin_incr(const std::vector &V) { auto i = V.begin(); i++; // no-warning } void behind_begin_incr(const std::vector &V) { auto i = ++V.begin(); i++; // no-warning } void unknown_incr(const std::vector &V) { auto i = return_any_iterator(V.begin()); i++; // no-warning } void ahead_of_end_incr(const std::vector &V) { auto i = --V.end(); i++; // no-warning } void end_incr(const std::vector &V) { auto i = V.end(); i++; // expected-warning{{Iterator incremented behind the past-the-end iterator}} } // Prefix decrement - operator--() void decr_begin(const std::vector &V) { auto i = V.begin(); --i; // expected-warning{{Iterator decremented ahead of its valid range}} } void decr_behind_begin(const std::vector &V) { auto i = ++V.begin(); --i; // no-warning } void decr_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); --i; // no-warning } void decr_ahead_of_end(const std::vector &V) { auto i = --V.end(); --i; // no-warning } void decr_end(const std::vector &V) { auto i = V.end(); --i; // no-warning } // Postfix decrement - operator--(int) void begin_decr(const std::vector &V) { auto i = V.begin(); i--; // expected-warning{{Iterator decremented ahead of its valid range}} } void behind_begin_decr(const std::vector &V) { auto i = ++V.begin(); i--; // no-warning } void unknown_decr(const std::vector &V) { auto i = return_any_iterator(V.begin()); i--; // no-warning } void ahead_of_end_decr(const std::vector &V) { auto i = --V.end(); i--; // no-warning } void end_decr(const std::vector &V) { auto i = V.end(); i--; // no-warning } // Addition assignment - operator+=(int) void incr_by_2_begin(const std::vector &V) { auto i = V.begin(); i += 2; // no-warning } void incr_by_2_behind_begin(const std::vector &V) { auto i = ++V.begin(); i += 2; // no-warning } void incr_by_2_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); i += 2; // no-warning } void incr_by_2_ahead_by_2_of_end(const std::vector &V) { auto i = --V.end(); --i; i += 2; // no-warning } void incr_by_2_ahead_of_end(const std::vector &V) { auto i = --V.end(); i += 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}} } void incr_by_2_end(const std::vector &V) { auto i = V.end(); i += 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}} } // Addition - operator+(int) void incr_by_2_copy_begin(const std::vector &V) { auto i = V.begin(); auto j = i + 2; // no-warning } void incr_by_2_copy_behind_begin(const std::vector &V) { auto i = ++V.begin(); auto j = i + 2; // no-warning } void incr_by_2_copy_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); auto j = i + 2; // no-warning } void incr_by_2_copy_ahead_by_2_of_end(const std::vector &V) { auto i = --V.end(); --i; auto j = i + 2; // no-warning } void incr_by_2_copy_ahead_of_end(const std::vector &V) { auto i = --V.end(); auto j = i + 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}} } void incr_by_2_copy_end(const std::vector &V) { auto i = V.end(); auto j = i + 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}} } // Subtraction assignment - operator-=(int) void decr_by_2_begin(const std::vector &V) { auto i = V.begin(); i -= 2; // expected-warning{{Iterator decremented ahead of its valid range}} } void decr_by_2_behind_begin(const std::vector &V) { auto i = ++V.begin(); i -= 2; // expected-warning{{Iterator decremented ahead of its valid range}} } void decr_by_2_behind_begin_by_2(const std::vector &V) { auto i = ++V.begin(); ++i; i -= 2; // no-warning } void decr_by_2_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); i -= 2; // no-warning } void decr_by_2_ahead_of_end(const std::vector &V) { auto i = --V.end(); i -= 2; // no-warning } void decr_by_2_end(const std::vector &V) { auto i = V.end(); i -= 2; // no-warning } // Subtraction - operator-(int) void decr_by_2_copy_begin(const std::vector &V) { auto i = V.begin(); auto j = i - 2; // expected-warning{{Iterator decremented ahead of its valid range}} } void decr_by_2_copy_behind_begin(const std::vector &V) { auto i = ++V.begin(); auto j = i - 2; // expected-warning{{Iterator decremented ahead of its valid range}} } void decr_by_2_copy_behind_begin_by_2(const std::vector &V) { auto i = ++V.begin(); ++i; auto j = i - 2; // no-warning } void decr_by_2_copy_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); auto j = i - 2; // no-warning } void decr_by_2_copy_ahead_of_end(const std::vector &V) { auto i = --V.end(); auto j = i - 2; // no-warning } void decr_by_2_copy_end(const std::vector &V) { auto i = V.end(); auto j = i - 2; // no-warning } // // Subscript - operator[](int) // // By zero void subscript_zero_begin(const std::vector &V) { auto i = V.begin(); auto j = i[0]; // no-warning } void subscript_zero_behind_begin(const std::vector &V) { auto i = ++V.begin(); auto j = i[0]; // no-warning } void subscript_zero_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); auto j = i[0]; // no-warning } void subscript_zero_ahead_of_end(const std::vector &V) { auto i = --V.end(); auto j = i[0]; // no-warning } void subscript_zero_end(const std::vector &V) { auto i = V.end(); auto j = i[0]; // expected-warning{{Past-the-end iterator dereferenced}} } // By negative number void subscript_negative_begin(const std::vector &V) { auto i = V.begin(); auto j = i[-1]; // no-warning FIXME: expect warning Iterator decremented ahead of its valid range } void subscript_negative_behind_begin(const std::vector &V) { auto i = ++V.begin(); auto j = i[-1]; // no-warning } void subscript_negative_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); auto j = i[-1]; // no-warning } void subscript_negative_ahead_of_end(const std::vector &V) { auto i = --V.end(); auto j = i[-1]; // no-warning } void subscript_negative_end(const std::vector &V) { auto i = V.end(); auto j = i[-1]; // // expected-warning{{Past-the-end iterator dereferenced}} FIXME: expect no warning } // By positive number void subscript_positive_begin(const std::vector &V) { auto i = V.begin(); auto j = i[1]; // no-warning } void subscript_positive_behind_begin(const std::vector &V) { auto i = ++V.begin(); auto j = i[1]; // no-warning } void subscript_positive_unknown(const std::vector &V) { auto i = return_any_iterator(V.begin()); auto j = i[1]; // no-warning } void subscript_positive_ahead_of_end(const std::vector &V) { auto i = --V.end(); auto j = i[1]; // no-warning FIXME: expected warning Past-the-end iterator dereferenced } void subscript_positive_end(const std::vector &V) { auto i = V.end(); auto j = i[1]; // expected-warning{{Past-the-end iterator dereferenced}} FIXME: expect warning Iterator incremented behind the past-the-end iterator } // // Structure member dereference operators // struct S { int n; }; // Member dereference - operator->() void arrow_deref_begin(const std::vector &V) { auto i = V.begin(); int n = i->n; // no-warning } void arrow_deref_end(const std::vector &V) { auto i = V.end(); int n = i->n; // expected-warning{{Past-the-end iterator dereferenced}} }