| // 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 <cstdint> |
| #include <cstring> |
| #include <iterator> |
| #include <tuple> |
| |
| // No rewrite expected. |
| extern const int kPropertyVisitedIDs[]; |
| |
| namespace ns1 { |
| |
| struct Type1 { |
| int value; |
| }; |
| |
| } // namespace ns1 |
| |
| int UnsafeIndex(); // This function might return an out-of-bound index. |
| |
| struct Component { |
| // Expected rewrite: |
| // std::array<int, 10> values; |
| int values[10]; |
| }; |
| |
| void fct() { |
| // Expected rewrite: |
| // auto buf = std::to_array<int>({1, 2, 3, 4}); |
| int buf[] = {1, 2, 3, 4}; |
| buf[UnsafeIndex()] = 11; |
| |
| Component component; |
| // Triggers the rewrite of Component::values |
| component.values[UnsafeIndex()]++; |
| |
| // Expected rewrite: |
| // std::array<int, 5> buf2 = {1, 1, 1, 1, 1}; |
| int buf2[5] = {1, 1, 1, 1, 1}; |
| buf2[UnsafeIndex()] = 11; |
| |
| constexpr int size = 5; |
| // Expected rewrite: |
| // constexpr std::array<int, size> buf3 = {1, 1, 1, 1, 1}; |
| constexpr int buf3[size] = {1, 1, 1, 1, 1}; |
| (void)buf3[UnsafeIndex()]; |
| |
| // Expected rewrite: |
| // std::array<int, buf3[0]> buf4; |
| int buf4[buf3[0]]; |
| buf4[UnsafeIndex()] = 11; |
| |
| // Expected rewrite: |
| // auto buf5 = std::to_array<ns1::Type1>({{1}, {1}, {1}, {1}, {1}}); |
| ns1::Type1 buf5[] = {{1}, {1}, {1}, {1}, {1}}; |
| buf5[UnsafeIndex()].value = 11; |
| |
| // Expected rewrite: |
| // auto buf6 = std::to_array<uint16_t>({1, 1, 1}); |
| uint16_t buf6[] = {1, 1, 1}; |
| buf6[UnsafeIndex()] = 1; |
| |
| // Expected rewrite: |
| // std::array<int (*)(int), 16> buf7 = {}; |
| int (*buf7[16])(int) = {}; |
| buf7[UnsafeIndex()] = nullptr; |
| |
| // Expected rewrite: |
| // std::array<int (**)[], 16> buf8 = {}; |
| int (**buf8[16])[] = {}; |
| buf8[UnsafeIndex()] = nullptr; |
| |
| using Arr = int (**)[]; |
| // Expected rewrite: |
| // std::array<Arr, buf3[0]> buf9 = {}; |
| Arr buf9[buf3[0]] = {}; |
| buf9[UnsafeIndex()] = nullptr; |
| |
| // Expected rewrite: |
| // static auto buf10 = std::to_array<const volatile char*>({"1", "2", "3"}); |
| volatile static const char* buf10[] = {"1", "2", "3"}; |
| buf10[UnsafeIndex()] = nullptr; |
| |
| int buf11[] = {1, 2, 3}; |
| int* ptr11_type; |
| // Expected rewrite: |
| // base::span<int> ptr11 = buf11; |
| decltype(ptr11_type) ptr11 = buf11; |
| ptr11[UnsafeIndex()] = 11; |
| |
| std::ignore = kPropertyVisitedIDs[UnsafeIndex()]; |
| } |
| |
| void sizeof_array_expr() { |
| // Expected rewrite: |
| // auto buf = std::to_array<int>({1}); |
| int buf[]{1}; |
| std::ignore = buf[UnsafeIndex()]; |
| |
| // Expected rewrite: |
| // std::ignore = base::SpanificationSizeofForStdArray(buf); |
| std::ignore = sizeof buf; |
| // Expected rewrite: |
| // std::ignore = base::SpanificationSizeofForStdArray(buf); |
| std::ignore = sizeof(buf); |
| // Expected rewrite: |
| // std::ignore = sizeof buf[0]; |
| std::ignore = sizeof *buf; |
| std::ignore = sizeof buf[0]; |
| } |
| |
| // Test for crbug.com/383424943. |
| void crbug_383424943() { |
| // No rewrite expected. |
| int buf[]{1}; |
| // Using sizeof was causing buf to be rewritten. |
| memset(buf, 'x', sizeof(buf)); |
| } |
| |
| // Expected rewrite: |
| // void c_ptr_param(base::span<int> ptr) |
| void c_ptr_param(int* ptr) { |
| std::ignore = ptr[UnsafeIndex()]; |
| } |
| |
| // Expected rewrite: |
| // void c_array_param(base::span<int, 1 + 2> arr) |
| void c_array_param(int arr[1 + 2]) { |
| std::ignore = arr[UnsafeIndex()]; |
| } |
| |
| // Expected rewrite: |
| // void c_array_nosize_param(base::span<int> arr) |
| void c_array_nosize_param(int arr[]) { |
| std::ignore = arr[UnsafeIndex()]; |
| } |
| |
| void test_func_params() { |
| // Expected rewrite: |
| // auto arr = std::to_array<int>({1, 2, 3}); |
| int arr[] = {1, 2, 3}; |
| std::ignore = arr[UnsafeIndex()]; |
| |
| c_ptr_param(arr); |
| c_array_param(arr); |
| c_array_nosize_param(arr); |
| } |
| |
| struct ProgramInfo { |
| // Expected rewrite: |
| // mutable std::array<int, 10> filename_offsets; |
| mutable int filename_offsets[10]; |
| }; |
| |
| void test_with_mutable() { |
| const ProgramInfo info; |
| info.filename_offsets[UnsafeIndex()] = 0xdead; |
| } |
| |
| void test_for_loop_with_c_array() { |
| int arr[] = {1, 2, 3}; |
| |
| // Expected rewrite: |
| // for (base::span<int> it = base::SpanificationArrayBegin(arr); |
| // it != base::SpanificationArrayEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (int* it = std::begin(arr); it != std::end(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<const int> it = base::SpanificationArrayCBegin(arr); |
| // it != base::SpanificationArrayCEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (int const* it = std::cbegin(arr); it != std::cend(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<int> it = base::SpanificationArrayBegin(arr); |
| // it != base::SpanificationArrayEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto it = std::begin(arr); it != std::end(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<int> it = base::SpanificationArrayBegin(arr); |
| // it != base::SpanificationArrayEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto* it = std::begin(arr); it != std::end(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<const int> it = base::SpanificationArrayCBegin(arr); |
| // it != base::SpanificationArrayCEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto it = std::cbegin(arr); it != std::cend(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<const int> it = base::SpanificationArrayCBegin(arr); |
| // it != base::SpanificationArrayCEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto* it = std::cbegin(arr); it != std::cend(arr); ++it) { |
| } |
| // Note that reverse_iterator (rbegin, rend, crbegin, crend) won't be |
| // supported because reverse_iterator never be of a pointer type (`it++` |
| // cannot move backward if `it` is a raw pointer), hence they're out of |
| // scope of the spanification. |
| } |
| |
| void test_for_loop_with_std_array() { |
| // Except for the arrayfication of `arr` below, the expected rewrites are |
| // completely the same with the C array cases. |
| // |
| // Expected rewrite: |
| // auto arr = std::to_array<int>({1, 2, 3}); |
| int arr[] = {1, 2, 3}; |
| std::ignore = arr[UnsafeIndex()]; |
| |
| // Expected rewrite: |
| // for (base::span<int> it = base::SpanificationArrayBegin(arr); |
| // it != base::SpanificationArrayEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (int* it = std::begin(arr); it != std::end(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<const int> it = base::SpanificationArrayCBegin(arr); |
| // it != base::SpanificationArrayCEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (int const* it = std::cbegin(arr); it != std::cend(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<int> it = base::SpanificationArrayBegin(arr); |
| // it != base::SpanificationArrayEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto it = std::begin(arr); it != std::end(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<int> it = base::SpanificationArrayBegin(arr); |
| // it != base::SpanificationArrayEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto* it = std::begin(arr); it != std::end(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<const int> it = base::SpanificationArrayCBegin(arr); |
| // it != base::SpanificationArrayCEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto it = std::cbegin(arr); it != std::cend(arr); ++it) { |
| } |
| // Expected rewrite: |
| // for (base::span<const int> it = base::SpanificationArrayCBegin(arr); |
| // it != base::SpanificationArrayCEnd(arr); |
| // base::PreIncrementSpan(it)) { |
| // } |
| for (auto* it = std::cbegin(arr); it != std::cend(arr); ++it) { |
| } |
| // Note that reverse_iterator (rbegin, rend, crbegin, crend) won't be |
| // supported because reverse_iterator never be of a pointer type (`it++` |
| // cannot move backward if `it` is a raw pointer), hence they're out of |
| // scope of the spanification. |
| } |