Skip to content

Commit

Permalink
cite Herb Sutter quote re boundschecking if std::size is available + …
Browse files Browse the repository at this point in the history
…hyloish arr.unsafe[idx] bypass syntax
  • Loading branch information
ehren committed Sep 28, 2024
1 parent 3a2c4cc commit 8bc0652
Showing 1 changed file with 21 additions and 4 deletions.
25 changes: 21 additions & 4 deletions include/boundscheck.cth
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
include <iostream>

cpp'
#define CETO_UNSAFE_ARRAY_ACCESS(array, index) (array[index])
'

# Herb Sutter - ACCU 2024 - Keynote: Safety, Security, Safety and C / C++ - C++ Evolution
# https://youtu.be/EB7yR-1317k?t=3373
# "If you see an expression of the form a[b] and std::ssize is available,
# including for C-arrays and vector and span and all those things,
# just insert a 0 <= b < std::ssize(a) at the call site"

defmacro (array[index], array, index:
if (array.name() == "lambda":
# not actually an array access (general syntax ftl)
Expand All @@ -8,8 +18,15 @@ defmacro (array[index], array, index:
return quote(ceto.bounds_check(unquote(array), unquote(index)))
)

defmacro (array.unsafe[index], array, index:
return quote(CETO_UNSAFE_ARRAY_ACCESS(unquote(array), unquote(index)))
)

namespace (ceto)

# Herb Sutter - ACCU Keynote
# See slide at above URL:
# "Inserting call-site bounds checks for a[b] if std::size(a) is available"
if (defined(CETO_HAS_SOURCE_LOCATION):
def (bounds_check, arr: mut:auto:ref:ref, index: size_t, loc: const:std.source_location:ref = std.source_location.current():
if (index >= std.size(arr):
Expand All @@ -18,7 +35,7 @@ if (defined(CETO_HAS_SOURCE_LOCATION):
std.terminate()
)

return std.forward<decltype(arr)>(arr).unsafe_at(std.forward<decltype(index)>(index))
return std.forward<decltype(arr)>(arr).unsafe[std.forward<decltype(index)>(index)]
) : decltype(auto):requires:requires(std.size(arr))
else:
def (bounds_check, arr: mut:auto:ref:ref, index: size_t:
Expand All @@ -27,17 +44,17 @@ else:
std.terminate()
)

return std.forward<decltype(arr)>(arr).unsafe_at(std.forward<decltype(index)>(index))
return std.forward<decltype(arr)>(arr).unsafe[std.forward<decltype(index)>(index)]
) : decltype(auto):requires:requires(std.size(arr))
) : preprocessor

def (bounds_check, non_array: mut:auto:ref:ref, obj: mut:auto:ref:ref:
return std.forward<decltype(non_array)>(non_array).unsafe_at(std.forward<decltype(obj)>(obj))
return std.forward<decltype(non_array)>(non_array).unsafe[std.forward<decltype(obj)>(obj)]
) : decltype(auto):requires:not std.is_integral_v<std.remove_cvref_t<decltype(obj)>>

# from https://stackoverflow.com/questions/69785562/c-map-and-unordered-map-template-parameter-check-for-common-behavior-using-c/69869007#69869007
is_map_type: template<class:T>:concept = std.same_as<typename:T.value_type, std.pair<const:typename:T.key_type, typename:T.mapped_type>>

def (bounds_check, map_like: mut:auto:ref:ref, key: mut:auto:ref:ref:
return std.forward<decltype(map_like)>(map_like).unsafe_at(std.forward<decltype(key)>(key))
return std.forward<decltype(map_like)>(map_like).unsafe[std.forward<decltype(key)>(key)]
) : decltype(auto):requires:std.is_integral_v<std.remove_cvref_t<decltype(key)>> and is_map_type<std.remove_cvref_t<decltype(map_like)>>

0 comments on commit 8bc0652

Please sign in to comment.