[ox] Change panic and assert to use std::source_location

This commit is contained in:
2026-01-25 21:11:22 -06:00
parent bc05bd12e5
commit cdd574d873
12 changed files with 108 additions and 77 deletions

View File

@@ -135,7 +135,7 @@ class ModelHandlerInterface {
return m_handler->field(name, &v->template get<ModelValueArray>());
}
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
oxPanic(ox::Error(1), "invalid type");
ox::panic(ox::Error(1), "invalid type");
return ox::Error(1, "invalid type");
}

View File

@@ -168,7 +168,7 @@ class ModelValue {
constexpr const auto &get() const noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
oxPanic(ox::Error(1), "invalid cast");
ox::panic(ox::Error(1), "invalid cast");
}
return getValue<type>(*this);
}
@@ -178,7 +178,7 @@ class ModelValue {
constexpr auto &get() noexcept {
constexpr auto type = getType<T>();
if (m_type != type) [[unlikely]] {
oxPanic(ox::Error(1), "invalid cast");
ox::panic(ox::Error(1), "invalid cast");
}
return getValue<type>(*this);
}

View File

@@ -181,13 +181,13 @@ constexpr Array<T, ArraySize> &Array<T, ArraySize>::operator=(Array &&other) noe
template<typename T, std::size_t ArraySize>
constexpr T &Array<T, ArraySize>::operator[](std::size_t i) noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
boundsCheck(i, size(), "Array access overflow");
return m_items[i];
}
template<typename T, std::size_t ArraySize>
constexpr const T &Array<T, ArraySize>::operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Array access overflow");
boundsCheck(i, size(), "Array access overflow");
return m_items[i];
}

View File

@@ -15,8 +15,8 @@
namespace ox {
void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const&err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
void panic(Error const&err, StringViewCR panicMsg, std::source_location const &src) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", src.file_name(), src.line(), panicMsg);
if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg);
}
@@ -26,7 +26,7 @@ void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const
}
#ifdef OX_USE_STDLIB
printStackTrace(2);
oxTrace("panic").del("") << "Panic: " << panicMsg << " (" << file << ":" << line << ")";
oxTrace("panic").del("") << "Panic: " << panicMsg << " (" << src.file_name() << ":" << src.line() << ")";
std::abort();
#else
while (1);
@@ -36,34 +36,51 @@ void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const
#if __GNUC__ && !_WIN32
__attribute__((weak))
#endif
void panic(const char *file, int const line, char const*panicMsg, Error const&err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err);
void panic(Error const&err, char const*panicMsg, std::source_location const &src) noexcept {
panic(err, StringView{panicMsg}, src);
}
void assertFailFuncRuntime(
StringViewCR file,
int const line,
StringViewCR assertTxt,
StringViewCR msg) noexcept {
StringViewCR msg,
std::source_location const &src) noexcept {
#ifdef OX_USE_STDLIB
auto const st = genStackTrace(2);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]:\n{}", msg, assertTxt, file, line, st);
oxTracef(
"assert", "Failed assert: {} ({}) [{}:{}]:\n{}",
msg,
assertTxt,
src.file_name(),
src.line(),
st);
abort();
#else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
constexprPanic(file, line, msg);
oxErrf(
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
src.file_name(),
src.line(),
msg);
oxTracef(
"assert", "Failed assert: {} ({}) [{}:{}]",
msg,
assertTxt,
src.file_name(),
src.line());
constexprPanic(msg, {}, src);
#endif
}
void assertFailFuncRuntime(
StringViewCR file,
int const line,
[[maybe_unused]] Error const&err,
[[maybe_unused]] Error const &err,
StringViewCR,
StringViewCR assertMsg) noexcept {
StringViewCR assertMsg,
std::source_location const &src) noexcept {
#if defined(OX_USE_STDLIB)
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
auto msg = sfmt(
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
src.file_name(),
src.line(),
assertMsg);
if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg);
}
@@ -73,10 +90,10 @@ void assertFailFuncRuntime(
}
msg += genStackTrace(2);
oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, src.file_name(), src.line());
abort();
#else
constexprPanic(file, line, assertMsg);
constexprPanic(assertMsg, {}, src);
#endif
}

View File

@@ -23,42 +23,42 @@
namespace ox {
[[noreturn]]
void panic(StringViewCR file, int line, StringViewCR panicMsg, Error const&err = {}) noexcept;
void panic(
Error const&err,
StringViewCR panicMsg,
std::source_location const &src = std::source_location::current()) noexcept;
[[noreturn]]
constexpr void constexprPanic(
StringViewCR file,
int const line,
StringViewCR panicMsg,
Error const&err = {}) noexcept {
Error const&err = {},
std::source_location const &src = std::source_location::current()) noexcept {
if (!std::is_constant_evaluated()) {
panic(file, line, panicMsg, err);
panic(err, panicMsg, src);
} else {
while (true);
}
}
void assertFailFuncRuntime(
StringViewCR file,
int line,
StringViewCR assertTxt,
StringViewCR msg) noexcept;
StringViewCR msg,
std::source_location const &src = std::source_location::current()) noexcept;
void assertFailFuncRuntime(
StringViewCR file,
int line,
Error const&err,
Error const &err,
StringViewCR,
StringViewCR assertMsg) noexcept;
StringViewCR assertMsg,
std::source_location const &src = std::source_location::current()) noexcept;
constexpr void assertFunc(
StringViewCR file,
int const line,
bool const pass,
[[maybe_unused]]StringViewCR assertTxt,
[[maybe_unused]]StringViewCR msg) noexcept {
[[maybe_unused]]StringViewCR msg,
std::source_location const &src = std::source_location::current()) noexcept {
if (!pass) {
if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, assertTxt, msg);
assertFailFuncRuntime(assertTxt, msg, src);
} else {
while (true);
}
@@ -66,14 +66,13 @@ constexpr void assertFunc(
}
constexpr void assertFunc(
StringViewCR file,
int const line,
Error const&err,
StringViewCR,
StringViewCR assertMsg) noexcept {
StringViewCR assertMsg,
std::source_location const &src = std::source_location::current()) noexcept {
if (err) {
if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, err, {}, assertMsg);
assertFailFuncRuntime(err, {}, assertMsg, src);
} else {
while (true);
}
@@ -81,20 +80,31 @@ constexpr void assertFunc(
}
constexpr void expect(
StringViewCR file,
int const line,
auto const&actual,
auto const&expected) noexcept {
auto const &actual,
auto const &expected,
std::source_location const &src = std::source_location::current()) noexcept {
if (actual != expected) {
if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB)
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, "Value incorrect");
oxErrf("expected: {}\nactual: {}\n", detail::toStringView<true>(expected), detail::toStringView<true>(actual));
oxErrf(
"\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n",
src.file_name(),
src.line(),
"Value incorrect");
oxErrf(
"expected: {}\nactual: {}\n",
detail::toStringView<true>(expected),
detail::toStringView<true>(actual));
printStackTrace(2);
oxTracef("assert.expect", "Failed assert: {} == {} [{}:{}]", detail::toStringView<true>(actual), detail::toStringView<true>(expected), file, line);
oxTracef(
"assert.expect", "Failed assert: {} == {} [{}:{}]",
detail::toStringView<true>(actual),
detail::toStringView<true>(expected),
src.file_name(),
src.line());
std::abort();
#else
constexprPanic(file, line, "Comparison failed");
constexprPanic("Comparison failed", {}, src);
#endif
} else {
while (true);

View File

@@ -48,9 +48,8 @@
// Asserts
#define oxPanic(errCode, msg) ox::panic(__FILE__, __LINE__, msg, errCode)
#ifndef NDEBUG
#define oxAssert(pass, msg) ox::assertFunc(__FILE__, __LINE__, pass, #pass, msg)
#define oxAssert(pass, msg) ox::assertFunc(pass, #pass, msg)
#else
namespace ox {
struct [[nodiscard]] Error;
@@ -59,7 +58,7 @@ constexpr void oxAssert(bool, const char*) noexcept {}
constexpr void oxAssert(const ox::Error&, const char*) noexcept {}
#endif
#define oxExpect(actual, expected) ox::expect(__FILE__, __LINE__, actual, expected)
#define oxExpect(actual, expected) ox::expect(actual, expected)
// Alloca

View File

@@ -110,7 +110,10 @@ struct Exception: public std::exception {
};
[[noreturn]]
void panic(char const*file, int line, char const*panicMsg, Error const&err) noexcept;
void panic(
Error const&err,
char const*panicMsg,
std::source_location const&src = std::source_location::current()) noexcept;
template<typename T>
struct [[nodiscard]] Result {
@@ -182,7 +185,7 @@ struct [[nodiscard]] Result {
[[nodiscard]]
constexpr T &unwrap() & noexcept {
if (error) {
oxPanic(error, "Failed unwrap");
ox::panic(error, "Failed unwrap");
}
return value;
}
@@ -190,7 +193,7 @@ struct [[nodiscard]] Result {
[[nodiscard]]
constexpr T &&unwrap() && noexcept {
if (error) {
oxPanic(error, "Failed unwrap");
ox::panic(error, "Failed unwrap");
}
return std::move(value);
}
@@ -198,7 +201,7 @@ struct [[nodiscard]] Result {
[[nodiscard]]
constexpr T const&unwrap() const & noexcept {
if (error) [[unlikely]] {
oxPanic(error, "Failed unwrap");
ox::panic(error, "Failed unwrap");
}
return value;
}
@@ -329,23 +332,25 @@ constexpr Error toError(Result<T> const&r) noexcept {
}
constexpr void primitiveAssert(char const*file, int line, bool pass, char const*msg) noexcept {
constexpr void primitiveAssert(
bool const pass,
char const *msg,
std::source_location const &src = std::source_location::current()) noexcept {
if constexpr(ox::defines::Debug) {
if (!pass) [[unlikely]] {
panic(file, line, msg, ox::Error(1));
panic(ox::Error{1}, msg, src);
}
}
}
constexpr void boundsCheck(
char const*file,
int const line,
size_t const i,
size_t const sz,
char const*msg) noexcept {
char const*msg,
std::source_location const &src = std::source_location::current()) noexcept {
if constexpr(defines::CheckBounds) {
if (i >= sz) [[unlikely]] {
panic(file, line, msg, ox::Error{1});
panic(ox::Error{1}, msg, src);
}
}
}

View File

@@ -77,7 +77,7 @@ static HeapSegment *findSegmentFor(std::size_t sz) noexcept {
return s;
}
}
oxPanic(ox::Error(1), "malloc: could not find segment");
ox::panic(ox::Error(1), "malloc: could not find segment");
return nullptr;
}
@@ -102,7 +102,7 @@ void free(void *ptr) noexcept {
} else if (p.segment) {
p.segment->inUse = false;
} else {
oxPanic(ox::Error(1), "Bad heap free");
ox::panic(ox::Error(1), "Bad heap free");
}
}

View File

@@ -133,17 +133,17 @@ struct SpanIterator {
}
constexpr PtrType operator->() const noexcept {
boundsCheck(__FILE__, __LINE__, m_offset, m_max, "SpanIterator access overflow");
boundsCheck(m_offset, m_max, "SpanIterator access overflow");
return &m_t[m_offset];
}
constexpr RefType operator*() const noexcept {
boundsCheck(__FILE__, __LINE__, m_offset, m_max, "SpanIterator access overflow");
boundsCheck(m_offset, m_max, "SpanIterator access overflow");
return m_t[m_offset];
}
constexpr RefType operator[](std::size_t s) const noexcept {
boundsCheck(__FILE__, __LINE__, s, m_max, "SpanIterator access overflow");
boundsCheck(s, m_max, "SpanIterator access overflow");
return m_t[s];
}

View File

@@ -80,10 +80,10 @@ constexpr U *make(Args &&...args) noexcept {
try {
return new T(ox::forward<Args>(args)...);
} catch (std::exception const&ex) {
oxPanic(ox::Error(1, ex.what()), ex.what());
ox::panic(ox::Error(1, ex.what()), ex.what());
return nullptr;
} catch (...) {
oxPanic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
ox::panic(ox::Error(2, "Allocation or constructor failed"), "Allocation or constructor failed");
return nullptr;
}
#else

View File

@@ -147,17 +147,17 @@ class Span {
}
constexpr T &operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
boundsCheck(i, size(), "Span access overflow");
return m_items[i];
}
constexpr Span operator+(size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
boundsCheck(i, size(), "Span access overflow");
return {m_items + i, m_size - i};
}
constexpr Span operator+=(size_t i) noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
boundsCheck(i, size(), "Span access overflow");
m_items += i;
m_size -= i;
return *this;

View File

@@ -419,13 +419,13 @@ constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allo
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr T &Vector<T, SmallVectorSize, Allocator>::operator[](std::size_t i) noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Vector access overflow");
boundsCheck(i, size(), "Vector access overflow");
return m_items[i];
}
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr const T &Vector<T, SmallVectorSize, Allocator>::operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Vector access overflow");
boundsCheck(i, size(), "Vector access overflow");
return m_items[i];
}