Skip to content

Commit

Permalink
Add RIEGELI_EVAL_ASSERT* family of assertion macros.
Browse files Browse the repository at this point in the history
They are similar to the `RIEGELI_ASSERT*` family, but they always evaluate the
arguments.

They replace the `if (!condition) RIEGELI_ASSERT_UNREACHABLE()` idiom, being
consistent with other macros and printing compared values if the assumption
fails in debug mode. Also they do not allow the compiler to optimize under the
assumption that the condition holds, because this is not expected in most cases.
Use `RIEGELI_ASSUME*` instead if that is useful.

Add `RIEGELI_ASSUME*` family of assertion macros.

They are similar to the `RIEGELI_ASSERT*` family, but they allow the compiler
to optimize based on the assumption that the condition holds. In the current
implementation the condition is evaluated unconditionally, but this should not
be relied upon.

The name reminds of C++23 `[[assume(condition)]];`.

Rename `RIEGELI_ASSERT_NOTNULL` to `RIEGELI_EVAL_ASSUME_NOTNULL`, and
`RIEGELI_ASSERT_UNREACHABLE` to `RIEGELI_ASSUME_UNREACHABLE`. They already had
the semantics corresponding to new names.

Add `RIEGELI_{CHECK,ASSERT,EVAL_ASSERT,ASSUME}_OK` for checking `absl::Status`,
`absl::StatusOr<T>`, and the status of instances of classes deriving from
`Object`.

Use `ABSL_LOG()` in `RIEGELI_CHECK*` macros instead of writing to stderr. Rework
their implementation. This version tries harder to optimize for the code size,
by moving more code to out of line functions.

Use `if (type variable = init)` syntax. This is cleaner than `while` which
relied on process termination in the false case to avoid an infinite loop, and
this can be used also when the false case is not fatal.

PiperOrigin-RevId: 700231814
  • Loading branch information
QrczakMK committed Nov 26, 2024
1 parent 93c0208 commit 08074ce
Show file tree
Hide file tree
Showing 3 changed files with 367 additions and 103 deletions.
2 changes: 2 additions & 0 deletions riegeli/base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ cc_library(
deps = [
":debug",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/meta:type_traits",
],
)

Expand Down
37 changes: 28 additions & 9 deletions riegeli/base/assert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,42 @@

#include "riegeli/base/assert.h"

#include <exception>
#include <iostream>
#include <ostream>
#include <sstream>
#include <string>
#include <utility>

#include "absl/log/absl_log.h"

namespace riegeli {
namespace assert_internal {

CheckFailed::CheckFailed(const char* file, int line, const char* function,
const char* message) {
stream_ << "Check failed at " << file << ":" << line << " in " << function
<< ": " << message << " ";
CheckResult::CheckResult(const char* function, const char* prefix)
: header_(new std::ostringstream()) {
header() << "Check failed in " << function << ": " << prefix;
}

CheckFailed::CheckFailed(const char* file, int line, CheckResult check_result)
: file_(file),
line_(line),
check_result_(check_result),
details_(new std::ostringstream()) {}

CheckFailed::~CheckFailed() {
std::cerr << stream_.str() << std::endl;
std::terminate();
std::ostringstream& message = check_result_.header();
const std::string details = std::move(*details_).str();
if (!details.empty()) message << "; " << details;
ABSL_LOG(FATAL).AtLocation(file_, line_) << std::move(message).str();
}

void CheckNotNullFailed(const char* file, int line, const char* function,
const char* expression) {
CheckResult check_result(function, expression);
check_result.header() << " != nullptr";
CheckFailed check_failed(file, line, check_result);
}

CheckResult CheckImpossibleResult(const char* function) {
return CheckResult(function, "Impossible");
}

} // namespace assert_internal
Expand Down
Loading

0 comments on commit 08074ce

Please sign in to comment.