Skip to content

Commit d71253d

Browse files
authored
added bounds checking to CArray (#40)
* added bounds checking to CArray * add operator[] access and slicing * doxygen, cppcheck, and some clangTidy * add test of shivaAssertionFailed() for coverage
1 parent aa50bca commit d71253d

27 files changed

Lines changed: 629 additions & 170 deletions

cmake/CMakeBasics.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ endif()
99
set( SHIVA_BUILD_OBJ_LIBS OFF CACHE BOOL "" )
1010

1111

12+
option( SHIVA_ENABLE_BOUNDS_CHECK "Enable bounds checking in shiva::CArray" ON )
13+
1214
if( CMAKE_CXX_STANDARD IN_LIST "98; 11; 14" )
1315
MESSAGE(FATAL_ERROR "Shiva requires at least c++17")
1416
endif()
@@ -25,4 +27,5 @@ blt_append_custom_compiler_flag( FLAGS_VAR CMAKE_CXX_FLAGS_DEBUG
2527
CLANG "-fstandalone-debug"
2628
)
2729

30+
2831
set( CAMP_ENABLE_TESTS OFF CACHE BOOL "")

cmake/Config.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#
22
set( PREPROCESSOR_DEFINES CUDA
33
HIP
4+
BOUNDS_CHECK
45
)
56

67
set( USE_CONFIGFILE ON CACHE BOOL "" )
78
foreach( DEP in ${PREPROCESSOR_DEFINES})
8-
if( ${DEP}_FOUND OR ENABLE_${DEP} )
9+
if( ${DEP}_FOUND OR ENABLE_${DEP} OR SHIVA_ENABLE_${DEP} )
910
set( SHIVA_USE_${DEP} TRUE )
1011
endif()
1112
endforeach()

cmake/Macros.cmake

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,16 @@ macro(shiva_add_code_checks)
3434

3535
set( CPPCHECK_FLAGS --std=c++17
3636
--enable=all
37+
--quiet
3738
--suppress=missingIncludeSystem
3839
--suppress=unmatchedSuppression
3940
--suppress=missingInclude
4041
--suppress=noConstructor
4142
--suppress=noExplicitConstructor
4243
--suppress=unusedFunction
4344
--suppress=constStatement
44-
--suppress=unusedStructMember )
45+
--suppress=unusedStructMember
46+
--suppress=unknownMacro )
4547

4648
blt_add_code_checks( PREFIX ${arg_PREFIX}
4749
SOURCES ${_sources}

cmake/blt

Submodule blt updated 354 files

docs/doxygen/ShivaConfig.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@
1313
/* #undef SHIVA_USE_HIP */
1414

1515
/* #undef SHIVA_USE_CALIPER */
16+
17+
#define SHIVA_USE_BOUNDS_CHECK

hostconfigs/apple/macOS_base.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ set( DOXYGEN_EXECUTABLE "${HOMEBREW_DIR}/bin/doxygen" CACHE PATH "" FORCE)
2626
set( CPPCHECK_EXECUTABLE "${HOMEBREW_DIR}/bin/cppcheck" CACHE PATH "" FORCE)
2727
set( CLANGTIDY_EXECUTABLE "${HOMEBREW_DIR}/opt/llvm/bin/clang-tidy" CACHE PATH "" FORCE)
2828

29-
set( ENABLE_COVERAGE ON CACHE BOOL "" FORCE)
29+
set( ENABLE_COVERAGE OFF CACHE BOOL "" FORCE)
3030
set( GCOV_EXECUTABLE "/usr/bin/gcov" CACHE PATH "" FORCE)
3131
set( LCOV_EXECUTABLE "${HOMEBREW_DIR}/bin/lcov" CACHE PATH "" FORCE)
3232

src/ShivaConfig.hpp.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@
1212

1313
#cmakedefine SHIVA_USE_HIP
1414

15-
#cmakedefine SHIVA_USE_CALIPER
15+
#cmakedefine SHIVA_USE_CALIPER
16+
17+
#cmakedefine SHIVA_USE_BOUNDS_CHECK

src/common/CArray.hpp

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include "CArrayHelper.hpp"
2525

2626
#include <utility>
27-
27+
#include <cmath>
2828

2929

3030
namespace shiva
@@ -94,12 +94,14 @@ struct CArray
9494
* @brief accessor for m_data
9595
* @return reference to m_data
9696
*/
97+
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
9798
DATA_BUFFER & data() { return m_data; }
9899

99100
/**
100101
* @brief const accessor for m_data
101102
* @return reference to const m_data
102103
*/
104+
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
103105
DATA_BUFFER const & data() const { return m_data; }
104106

105107
/**
@@ -156,11 +158,98 @@ struct CArray
156158
return m_data[ CArrayHelper::linearIndexHelper< DIMS... >::eval( indices ... ) ];
157159
}
158160

161+
private:
162+
/**
163+
* @struct SubArrayHelper
164+
* @brief This struct is used to help with the creation of subarrays.
165+
*/
166+
struct SubArrayHelper
167+
{
168+
/// This alias is used to create a const subarray type.
169+
170+
template< int ... SUB_DIMS >
171+
using const_type = CArray< T const, T const * const, SUB_DIMS... >;
172+
173+
/// This alias is used to create a subarray type.
174+
template< int ... SUB_DIMS >
175+
using type = CArray< T, T * const, SUB_DIMS... >;
176+
};
177+
178+
/**
179+
* @brief Helper function to enable operator[].
180+
* @tparam CARRAY_TYPE The type of the array to create. Either const_type or type.
181+
* @param index The index to access.
182+
* @return A reference to the data at the specified index or the subarray.
183+
*/
184+
template< template< int ... > typename CARRAY_TYPE >
185+
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
186+
decltype(auto) squareBracketOperatorHelper( index_type index ) const;
187+
188+
public:
189+
/**
190+
* @brief operator[] to access the data in the array or to slice a multidimensional array.
191+
* @param index The index to access.
192+
* @return A reference to the data at the specified index or the subarray.
193+
*/
194+
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
195+
decltype(auto) operator[]( index_type index ) const
196+
{
197+
return squareBracketOperatorHelper< SubArrayHelper::template const_type >( index );
198+
}
199+
200+
/**
201+
* @brief operator[] to access the data in the array or to slice a mutlidimensional array.
202+
* @param index The index to access.
203+
* @return A reference to the data at the specified index or the subarray.
204+
*/
205+
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
206+
decltype(auto) operator[]( index_type index )
207+
{
208+
if constexpr ( std::is_reference_v< decltype(squareBracketOperatorHelper< SubArrayHelper::template type >( index )) > )
209+
{
210+
return const_cast< T & >(squareBracketOperatorHelper< SubArrayHelper::template type >( index ));
211+
}
212+
else
213+
{
214+
return squareBracketOperatorHelper< SubArrayHelper::template type >( index );
215+
}
216+
}
217+
218+
159219
private:
160220
/// The data in the array.
161221
DATA_BUFFER m_data;
162222
};
163223

224+
/// @copydoc CArray::squareBracketOperatorHelper
225+
template< typename T, typename DATA_BUFFER, int ... DIMS >
226+
template< template< int ... > typename CARRAY_TYPE >
227+
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
228+
decltype(auto)
229+
CArray< T, DATA_BUFFER, DIMS ... >::squareBracketOperatorHelper( index_type index ) const
230+
{
231+
static_assert( sizeof...(DIMS) >= 1, "operator[] is only valid for sizeof...(DIMS) >= 1" );
232+
233+
#if defined( SHIVA_USE_BOUNDS_CHECK )
234+
constexpr int DIM = CArrayHelper::IntPeeler< DIMS... >::first;
235+
SHIVA_ASSERT_MSG( index >= 0 && index < DIM,
236+
"Index out of bounds: 0 < index(%jd) < dim(%jd)",
237+
static_cast< intmax_t >( index ),
238+
static_cast< intmax_t >( DIM ) );
239+
#endif
240+
241+
if constexpr ( sizeof...(DIMS) > 1 )
242+
{
243+
using SubArrayDims = typename CArrayHelper::IntPeeler< DIMS... >::rest;
244+
using SubArrayType = typename CArrayHelper::ApplyDims< SubArrayDims, CARRAY_TYPE >::type;
245+
return SubArrayType( const_cast< T * >( &m_data[ index * CArrayHelper::stride< DIMS..., 1 >() ] ) );
246+
}
247+
else
248+
{
249+
return operator()( index );
250+
}
251+
}
252+
164253
/**
165254
* @brief Alias for a scalar.
166255
* @tparam T Type held in the scalar

src/common/CArrayHelper.hpp

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
#pragma once
2020

2121

22-
#include "common/ShivaMacros.hpp"
22+
#include "common/ShivaErrorHandling.hpp"
23+
#include "common/types.hpp"
2324
#include <utility>
24-
25-
25+
#include <cstdint>
26+
#include <cinttypes>
2627

2728
namespace shiva
2829
{
@@ -93,6 +94,7 @@ struct linearIndexHelper
9394
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
9495
level()
9596
{
97+
static_assert( INDEX >= 0 && INDEX < DIM );
9698
constexpr int thisStride = strideHelper< DIMS ..., 1 >();
9799
if constexpr ( sizeof ... ( DIMS ) == 0 )
98100
{
@@ -108,17 +110,23 @@ struct linearIndexHelper
108110
* @copydoc level()
109111
*/
110112
template< typename INDEX_TYPE, typename ... INDICES_TYPE >
111-
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
113+
static constexpr SHIVA_HOST_DEVICE SHIVA_FORCE_INLINE int
112114
level( INDEX_TYPE const index, INDICES_TYPE const ... indices )
113115
{
116+
#if defined( SHIVA_USE_BOUNDS_CHECK )
117+
SHIVA_ASSERT_MSG( index >= 0 && index < DIM,
118+
"Index out of bounds: 0 < index(%jd) < dim(%jd)",
119+
static_cast< intmax_t >( index ),
120+
static_cast< intmax_t >( DIM ) );
121+
#endif
114122
constexpr int thisStride = strideHelper< DIMS ..., 1 >();
115123
if constexpr ( sizeof ... ( DIMS ) == 0 )
116124
{
117125
return index * thisStride;
118126
}
119127
else
120128
{
121-
return index * thisStride + linearIndexHelper< DIMS ... >::template level( std::forward< INDICES_TYPE const >( indices )... );
129+
return index * thisStride + linearIndexHelper< DIMS ... >::template level< INDICES_TYPE ... >( std::forward< INDICES_TYPE const >( indices )... );
122130
}
123131
}
124132

@@ -191,6 +199,44 @@ struct Peeler
191199
{
192200
/// The type of the first value in the pack.
193201
using type = T;
202+
203+
/// The type of the remaining values in the pack.
204+
using types = tuple< Ts ... >;
205+
};
206+
207+
/**
208+
* @brief function to peel an integer from a parameter pack.
209+
* @tparam INT The first value in the pack.
210+
* @tparam INTS The remaining values in the pack.
211+
*/
212+
template< int INT, int ... INTS >
213+
struct IntPeeler
214+
{
215+
/// The type of the first value in the pack.
216+
static constexpr int first = INT;
217+
218+
/// The type of the remaining values in the pack.
219+
using rest = std::integer_sequence< int, INTS... >;
220+
};
221+
222+
/**
223+
* @brief function to apply a parameter pack to a templated type.
224+
* @tparam Ints The integer sequence to apply.
225+
* @tparam Target The target type to apply the integer sequence to.
226+
*/
227+
template< typename Seq, template< int... > class Target >
228+
struct ApplyDims;
229+
230+
/**
231+
* @brief function to apply a parameter pack to a templated type.
232+
* @tparam Ints The integer sequence to apply.
233+
* @tparam Target The target type to apply the integer sequence to.
234+
*/
235+
template< int... Ints, template< int... > class Target >
236+
struct ApplyDims< std::integer_sequence< int, Ints... >, Target >
237+
{
238+
/// The type of the target that has the pack applied its varaidic pack.
239+
using type = Target< Ints... >;
194240
};
195241

196242
} // namespace CArrayHelper

src/common/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set( common_headers
99
pmpl.hpp
1010
SequenceUtilities.hpp
1111
NestedSequenceUtilities.hpp
12+
ShivaErrorHandling.hpp
1213
ShivaMacros.hpp
1314
types.hpp
1415
)

0 commit comments

Comments
 (0)