// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <vector>
bool A();
bool B();
void SameConditionInvalidatesThenValidatesIterator() {
std::vector<int> container = {1, 2, 3};
auto it = container.begin() + 1;
if (it == container.end()) {
return;
}
const bool a = A();
if (a) {
container.clear();
}
if (a) {
container.push_back(1);
container.push_back(2);
it = container.begin() + 1;
if (it == std::end(container)) {
return;
}
}
// This is valid because although the container was invalidated in the first
// `if(a)` block, the second one reassigns the iterator and ensures that it
// is different than `end`. Since the same check is made at the very
// beginning of the function, the iterator is logically valid at this point
// of the execution.
*it = 10;
}
void SameConditionUncheckedIterator() {
std::vector<int> container = {1, 2, 3};
auto it = container.begin() + 1;
if (it == std::end(container)) {
return;
}
const bool a = A();
if (a) {
container.clear();
}
if (!a) {
container.push_back(1);
container.push_back(2);
it = container.begin() + 1;
}
// This is invalid because although the iterator is getting reassigned in the
// second `a` conditional block, it is not checked against the `end` iterator.
*it = 10; // Invalid.
}
void DifferentConditionsWithCheckedIterator() {
std::vector<int> container = {1, 2, 3};
auto it = container.begin() + 1;
if (it == std::end(container)) {
return;
}
const bool a = A();
const bool b = B();
if (a && b) {
container.clear();
}
if (a || b) {
container.push_back(1);
container.push_back(2);
it = container.begin() + 1;
if (it == std::end(container)) {
return;
}
}
// Valid since in all cases it is checked against the `end` iterator.
*it = 10;
}
void DifferentConditionsWithUncheckedIterator() {
std::vector<int> container = {1, 2, 3};
auto it = container.begin() + 1;
if (it == std::end(container)) {
return;
}
const bool a = A();
const bool b = B();
if (a && b) {
container.clear();
}
if (a || b) {
container.push_back(1);
container.push_back(2);
it = container.begin() + 1;
}
// Invalid. The difference with `DifferentConditionsWithCheckedIterator` is
// that we do not check the iterator in the last `if` block, hence we can't
// ensure that the iterator is valid.
*it = 10;
}