Skip to content

Commit 1995e86

Browse files
Anna Gringauzeneilmacintosh
authored andcommitted
span constructor no address (#723)
* Changed &arr[0] to std::array<T, N>::data and std::address_of to protect against overloaded operator&. * Removed the usage of `std::addressof` because it is a C++ 17 feature. Using decay for C arrays instead. * Add unit tests for #662. * Added c++17 test configurations for clang5.0 and clang6.0 * fixed CppCoreCheck pointer decay warning
1 parent 585f48c commit 1995e86

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

include/gsl/span

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <stdexcept>
3030
#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
3131
#include <utility>
32+
#include <memory> // for std::addressof
3233

3334
#ifdef _MSC_VER
3435
#pragma warning(push)
@@ -390,19 +391,19 @@ public:
390391

391392
template <std::size_t N>
392393
constexpr span(element_type (&arr)[N]) noexcept
393-
: storage_(KnownNotNull{&arr[0]}, details::extent_type<N>())
394+
: storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type<N>())
394395
{}
395396

396397
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
397398
// GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug
398399
constexpr span(std::array<ArrayElementType, N>& arr) noexcept
399-
: storage_(&arr[0], details::extent_type<N>())
400+
: storage_(arr.data(), details::extent_type<N>())
400401
{}
401402

402403
template <std::size_t N>
403404
// GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug
404405
constexpr span(const std::array<std::remove_const_t<element_type>, N>& arr) noexcept
405-
: storage_(&arr[0], details::extent_type<N>())
406+
: storage_(arr.data(), details::extent_type<N>())
406407
{}
407408

408409
// NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement

tests/span_tests.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ struct BaseClass
5252
struct DerivedClass : BaseClass
5353
{
5454
};
55+
struct AddressOverloaded
56+
{
57+
AddressOverloaded operator&() const { return {}; }
58+
};
5559
}
5660

5761
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
@@ -306,19 +310,17 @@ TEST_CASE("from_pointer_pointer_constructor")
306310
}
307311
}
308312

309-
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
310-
GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute // TODO: false positive?
311313
TEST_CASE("from_array_constructor")
312314
{
313315
int arr[5] = {1, 2, 3, 4, 5};
314316

315317
{
316-
span<int> s{arr};
318+
const span<int> s{arr};
317319
CHECK((s.size() == 5 && s.data() == &arr[0]));
318320
}
319321

320322
{
321-
span<int, 5> s{arr};
323+
const span<int, 5> s{arr};
322324
CHECK((s.size() == 5 && s.data() == &arr[0]));
323325
}
324326

@@ -350,8 +352,8 @@ TEST_CASE("from_array_constructor")
350352
}
351353
#endif
352354
{
353-
span<int[3]> s{&arr2d[0], 1};
354-
CHECK((s.size() == 1 && s.data() == &arr2d[0]));
355+
const span<int[3]> s{std::addressof(arr2d[0]), 1};
356+
CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0])));
355357
}
356358

357359
int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
@@ -379,24 +381,32 @@ TEST_CASE("from_array_constructor")
379381
}
380382
#endif
381383
{
382-
span<int[3][2]> s{&arr3d[0], 1};
383-
CHECK((s.size() == 1 && s.data() == &arr3d[0]));
384+
const span<int[3][2]> s{std::addressof(arr3d[0]), 1};
385+
CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0])));
384386
}
385387

386388
{
387-
auto s = make_span(arr);
388-
CHECK((s.size() == 5 && s.data() == &arr[0]));
389+
const auto s = make_span(arr);
390+
CHECK((s.size() == 5 && s.data() == std::addressof(arr[0])));
391+
}
392+
393+
{
394+
const auto s = make_span(std::addressof(arr2d[0]), 1);
395+
CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0])));
389396
}
390397

391398
{
392-
auto s = make_span(&(arr2d[0]), 1);
393-
CHECK((s.size() == 1 && s.data() == &arr2d[0]));
399+
const auto s = make_span(std::addressof(arr3d[0]), 1);
400+
CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0])));
394401
}
395402

403+
AddressOverloaded ao_arr[5] = {};
404+
396405
{
397-
auto s = make_span(&arr3d[0], 1);
398-
CHECK((s.size() == 1 && s.data() == &arr3d[0]));
406+
const span<AddressOverloaded, 5> s{ao_arr};
407+
CHECK((s.size() == 5 && s.data() == std::addressof(ao_arr[0])));
399408
}
409+
400410
}
401411

402412
GSL_SUPPRESS(con.4) // NO-FORMAT: attribute
@@ -442,6 +452,13 @@ TEST_CASE("from_std_array_constructor")
442452
CHECK((cs.size() == narrow_cast<ptrdiff_t>(arr.size()) && cs.data() == arr.data()));
443453
}
444454

455+
std::array<AddressOverloaded, 4> ao_arr{};
456+
457+
{
458+
span<AddressOverloaded, 4> fs{ao_arr};
459+
CHECK((fs.size() == narrow_cast<ptrdiff_t>(ao_arr.size()) && ao_arr.data() == fs.data()));
460+
}
461+
445462
#ifdef CONFIRM_COMPILATION_ERRORS
446463
{
447464
span<int, 2> s{arr};
@@ -516,6 +533,13 @@ TEST_CASE("from_const_std_array_constructor")
516533
CHECK((s.size() == narrow_cast<ptrdiff_t>(arr.size()) && s.data() == arr.data()));
517534
}
518535

536+
const std::array<AddressOverloaded, 4> ao_arr{};
537+
538+
{
539+
span<const AddressOverloaded, 4> s{ao_arr};
540+
CHECK((s.size() == narrow_cast<ptrdiff_t>(ao_arr.size()) && s.data() == ao_arr.data()));
541+
}
542+
519543
#ifdef CONFIRM_COMPILATION_ERRORS
520544
{
521545
span<const int, 2> s{arr};

0 commit comments

Comments
 (0)