Merge pull request #96 from reventlov/fix_iterator_bug
Fix array iterators when the array view is a temporary object.
diff --git a/compiler/back_end/cpp/testcode/auto_array_size_test.cc b/compiler/back_end/cpp/testcode/auto_array_size_test.cc
index 8e03d40..eaae8ec 100644
--- a/compiler/back_end/cpp/testcode/auto_array_size_test.cc
+++ b/compiler/back_end/cpp/testcode/auto_array_size_test.cc
@@ -122,6 +122,22 @@
});
}
+TEST(AutoSizeView, ForEachWithTemporaries) {
+ auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize);
+
+ int i = 0;
+ ::std::for_each(view.four_struct_array().begin(),
+ view.four_struct_array().end(), [&](ElementView element) {
+ ASSERT_TRUE(element.Equals(view.four_struct_array()[i++]));
+ });
+
+ i = view.four_struct_array().ElementCount() - 1;
+ ::std::for_each(view.four_struct_array().rbegin(),
+ view.four_struct_array().rend(), [&](ElementView element) {
+ ASSERT_TRUE(element.Equals(view.four_struct_array()[i--]));
+ });
+}
+
TEST(AutoSizeView, Find) {
auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize).four_struct_array();
diff --git a/runtime/cpp/emboss_array_view.h b/runtime/cpp/emboss_array_view.h
index 79c6268..7287fce 100644
--- a/runtime/cpp/emboss_array_view.h
+++ b/runtime/cpp/emboss_array_view.h
@@ -50,9 +50,9 @@
using pointer = typename ::std::add_pointer<value_type>::type;
using reference = typename ::std::add_lvalue_reference<value_type>::type;
- explicit ElementViewIterator(const GenericArrayView *array_view,
+ explicit ElementViewIterator(const GenericArrayView array_view,
::std::ptrdiff_t index)
- : array_view_(array_view), view_((*array_view)[index]), index_(index) {}
+ : array_view_(array_view), view_(array_view[index]), index_(index) {}
ElementViewIterator() = default;
@@ -62,7 +62,7 @@
ElementViewIterator &operator+=(difference_type d) {
index_ += (kDirection == ElementViewIteratorDirection::kForward ? d : -d);
- view_ = (*array_view_)[index_];
+ view_ = array_view_[index_];
return *this;
}
@@ -135,7 +135,7 @@
}
private:
- const GenericArrayView *array_view_;
+ const GenericArrayView array_view_;
typename GenericArrayView::ViewType view_;
::std::ptrdiff_t index_;
};
@@ -179,12 +179,12 @@
index);
}
- ForwardIterator begin() const { return ForwardIterator(this, 0); }
- ForwardIterator end() const { return ForwardIterator(this, ElementCount()); }
+ ForwardIterator begin() const { return ForwardIterator(*this, 0); }
+ ForwardIterator end() const { return ForwardIterator(*this, ElementCount()); }
ReverseIterator rbegin() const {
- return ReverseIterator(this, ElementCount() - 1);
+ return ReverseIterator(*this, ElementCount() - 1);
}
- ReverseIterator rend() const { return ReverseIterator(this, -1); }
+ ReverseIterator rend() const { return ReverseIterator(*this, -1); }
// In order to selectively enable SizeInBytes and SizeInBits, it is
// necessary to make them into templates. Further, it is necessary for
@@ -262,6 +262,10 @@
return BackingStorage().template ToString<String>();
}
+ bool operator==(const GenericArrayView &other) const {
+ return parameters_ == other.parameters_ && buffer_ == other.buffer_;
+ }
+
private:
// This uses the same technique to select the correct definition of
// SizeOfBuffer() as in the SizeInBits()/SizeInBytes() selection above.
diff --git a/runtime/cpp/emboss_memory_util.h b/runtime/cpp/emboss_memory_util.h
index 49f4287..4195e99 100644
--- a/runtime/cpp/emboss_memory_util.h
+++ b/runtime/cpp/emboss_memory_util.h
@@ -438,6 +438,35 @@
: bytes_{reinterpret_cast<Byte *>(other.data())},
size_{other.SizeInBytes()} {}
+ // Compare a ContiguousBuffers to another, compatible ContiguousBuffer.
+ template <typename OtherByte, ::std::size_t kOtherAlignment,
+ ::std::size_t kOtherOffset,
+ typename = typename ::std::enable_if<
+ kOtherAlignment % kAlignment == 0 &&
+ kOtherOffset % kAlignment ==
+ kOffset && ::std::is_same<
+ typename AddSourceCV<OtherByte, Byte>::Type,
+ Byte>::value>::type>
+ bool operator==(const ContiguousBuffer<OtherByte, kOtherAlignment,
+ kOtherOffset> &other) const {
+ return bytes_ == reinterpret_cast<Byte *>(other.data()) &&
+ size_ == other.SizeInBytes();
+ }
+
+ // Compare a ContiguousBuffers to another, compatible ContiguousBuffer.
+ template <typename OtherByte, ::std::size_t kOtherAlignment,
+ ::std::size_t kOtherOffset,
+ typename = typename ::std::enable_if<
+ kOtherAlignment % kAlignment == 0 &&
+ kOtherOffset % kAlignment ==
+ kOffset && ::std::is_same<
+ typename AddSourceCV<OtherByte, Byte>::Type,
+ Byte>::value>::type>
+ bool operator!=(const ContiguousBuffer<OtherByte, kOtherAlignment,
+ kOtherOffset> &other) const {
+ return !(*this == other);
+ }
+
// Assignment from a compatible ContiguousBuffer.
template <typename OtherByte, ::std::size_t kOtherAlignment,
::std::size_t kOtherOffset,
diff --git a/runtime/cpp/emboss_text_util.h b/runtime/cpp/emboss_text_util.h
index 500d828..ac2e1d9 100644
--- a/runtime/cpp/emboss_text_util.h
+++ b/runtime/cpp/emboss_text_util.h
@@ -19,6 +19,7 @@
#include <array>
#include <climits>
#include <cmath>
+#include <cstdint>
#include <cstdio>
#include <cstring>
#include <limits>