Skip to content

Commit

Permalink
Polish handling of assertions and audits
Browse files Browse the repository at this point in the history
  • Loading branch information
Morwenn committed Dec 25, 2023
1 parent d27b515 commit b2916e5
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Expand Up @@ -13,6 +13,8 @@ include(GNUInstallDirs)
# Project options
option(CPPSORT_BUILD_TESTING "Build the cpp-sort test suite" ON)
option(CPPSORT_BUILD_EXAMPLES "Build the cpp-sort examples" OFF)
option(CPPSORT_ENABLE_AUDITS "Enable assertions in the library" OFF)
option(CPPSORT_ENABLE_ASSERTIONS "Enable assertions in the library" ${CPPSORT_ENABLE_AUDITS})
option(CPPSORT_USE_LIBASSERT "Use libassert for assertions (experimental)" OFF)

# Optionally use libassert for assertions
Expand Down Expand Up @@ -42,6 +44,14 @@ if (MSVC)
target_compile_options(cpp-sort INTERFACE /Zc:preprocessor)
endif()

# Handle diagnostic options
if (CPPSORT_ENABLE_ASSERTIONS)
target_compile_definitions(cpp-sort INTERFACE CPPSORT_ENABLE_ASSERTIONS)
endif()
if (CPPSORT_ENABLE_AUDITS)
target_compile_definitions(cpp-sort INTERFACE CPPSORT_ENABLE_AUDITS)
endif()

# Optionally link to libassert
if (CPPSORT_USE_LIBASSERT)
target_link_libraries(cpp-sort INTERFACE assert)
Expand Down
6 changes: 5 additions & 1 deletion docs/Home.md
Expand Up @@ -68,7 +68,9 @@ Some old components undergo deprecation before being removed in the following ma

Some algorithms have assertions to guard against accidental logic issues (mostly in algorithms adapted from other projects), but they are disabled by default. You can enable these assertions by defining the preprocessor macro `CPPSORT_ENABLE_ASSERTIONS`. This new macro still honours `NDEBUG`, so assertions won't be enabled anyway if `NDEBUG` is defined.

A similar `CPPSORT_ENABLE_AUDITS` macro can be defined to enable audits: those are expensive assertions which are not enabled by `CPPSORT_ENABLE_ASSERTIONS` because they are too expensive, to the point that they might even change the complexity of some algorithms. When turning on audits, internal calls to `__assume` or equivalent statements will also be turned into assertions to provided additional checks.
A similar `CPPSORT_ENABLE_AUDITS` macro can be defined to enable audits: those are expensive assertions which are not enabled by `CPPSORT_ENABLE_ASSERTIONS` because they are too expensive, to the point that they might even change the complexity of some algorithms. When turning on audits, assertions are automatically enabled too, and internal uses of [`[[assume(...)]]`][assume] and equivalent statements are turned into assertions. This macro also honours `NDEBUG`.

The macros `CPPSORT_ENABLE_ASSERTIONS` and `CPPSORT_ENABLE_AUDITS` can be configured directly from CMake by setting the eponymous options to `ON`. See [the Tooling page][tooling-cmake] for more information.

#### Rich assertions with libassert (experimental)

Expand All @@ -89,8 +91,10 @@ If you ever feel that this wiki is incomplete, that it needs more examples or mo
Hope you have fun!


[assume]: https://en.cppreference.com/w/cpp/language/attributes/assume
[benchmarks]: Benchmarks.md
[libassert]: https://github.com/jeremy-rifkin/libassert
[original-research]: Original-research.md
[quickstart]: Quickstart.md
[swappable]: https://en.cppreference.com/w/cpp/concepts/swappable
[tooling-cmake]: Tooling.md#cmake
5 changes: 5 additions & 0 deletions docs/Tooling.md
Expand Up @@ -29,10 +29,14 @@ The project's CMake files offers some options, though they are mainly used to co
* `CPPSORT_USE_VALGRIND`: whether to run the test suite through Valgrind, defaults to `OFF`.
* `CPPSORT_SANITIZE`: values to pass to the `-fsanitize` flags of compilers that supports them, default to empty string.
* `CPPSORT_STATIC_TESTS`: when `ON`, some tests are executed at compile time instead of runtime, defaults to `OFF`.
* `CPPSORT_ENABLE_ASSERTIONS`: when `ON`, defines the eponymous macro which enables debug assertions from the library's internals, defaults to the value of `CPPSORT_ENABLE_AUDITS`.
* `CPPSORT_ENABLE_AUDITS`: when `ON`, defines the eponymous macro which enables expensive debug assertions from the library's internals, defaults to `OFF`.
* `CPPSORT_USE_LIBASSERT` (experimental): when `ON`, internal assertions use [libassert][libassert] instead of the standard `assert` macro, providing additional information about the errors. Defaults to `OFF`.

Some of those options also exist without the `CPPSORT_` prefix, but they are deprecated. For compatibility reasons, the options with the `CPPSORT_` prefix default to the values of the equivalent unprefixed options.

Note: when `CPPSORT_ENABLE_AUDITS` is `ON`, assertions in the library are enabled even if `CPPSORT_ENABLE_ASSERTIONS` is `OFF`. See [the relevant page][assertions-and-audits] for more information.

[Catch2][catch2] 3.0.0-preview4 or greater is required to build the tests: if a suitable version has been installed on the system it will be used, otherwise the latest suitable Catch2 release will be downloaded.

## Conan
Expand Down Expand Up @@ -64,6 +68,7 @@ This can notably used to browse old versions of the documentation. It seems howe
Due to slight markup differences, some pages might not fully render correctly but it should nonetheless be a better experience than navigaitng the Markdown files by hand.


[assertions-and-audits]: Home.md#assertions--audits
[catch2]: https://github.com/catchorg/Catch2
[cmake]: https://cmake.org/
[conan]: https://conan.io/
Expand Down
17 changes: 11 additions & 6 deletions include/cpp-sort/detail/config.h
Expand Up @@ -8,6 +8,11 @@
////////////////////////////////////////////////////////////
// General: assertions

// Ensure that enabling audits always enables assertions
#if defined(CPPSORT_ENABLE_AUDITS)
# define CPPSORT_ENABLE_ASSERTIONS
#endif

#if defined(CPPSORT_ENABLE_ASSERTIONS) || defined(CPPSORT_ENABLE_AUDITS)
# include <cassert>
# if defined(CPPSORT_USE_LIBASSERT)
Expand Down Expand Up @@ -47,12 +52,12 @@
// scenarios, but still of great help when debugging tough
// problems, hence this audit feature

#ifndef CPPSORT_AUDIT
# ifdef CPPSORT_ENABLE_AUDITS
# define CPPSORT_AUDIT(...) assert((__VA_ARGS__))
# else
# define CPPSORT_AUDIT(...) ((void)0)
#if !defined(NDEBUG) && defined(CPPSORT_ENABLE_AUDITS)
# ifndef CPPSORT_AUDIT
# define CPPSORT_AUDIT(...) CPPSORT_ASSERT(__VA_ARGS__)
# endif
#else
# define CPPSORT_AUDIT(...) ((void)0)
#endif

////////////////////////////////////////////////////////////
Expand All @@ -65,7 +70,7 @@
// actually correct.

#if defined(CPPSORT_ENABLE_AUDITS)
# define CPPSORT_ASSUME(...) assert((__VA_ARGS__))
# define CPPSORT_ASSUME(...) CPPSORT_ASSERT(__VA_ARGS__)
#elif defined(__GNUC__)
# define CPPSORT_ASSUME(expression) do { if (!(expression)) __builtin_unreachable(); } while(0)
#elif defined(__clang__)
Expand Down

0 comments on commit b2916e5

Please sign in to comment.