Skip to content

Commit 618f9e1

Browse files
committed
🎨 Allow extra arguments to CIB_FATAL
Problem: - `CIB_FATAL` expects log arguments to be interpolated into the format string, but there is no way to pass extra arguments along to `stdx::panic`. Solution: - Use the `format_result` tuple as the first argument to `stdx::panic`, and allow any further arguments passed to `CIB_FATAL` to be forwarded through. Note: - Splitting a tuple may be worthwhile to move to stdx in due course. Surprisingly I don't think we've had cause for it yet. And since clang backports pack indexing, when that is available we can use it without pulling in `stdx::tuple`.
1 parent 10ba43b commit 618f9e1

File tree

3 files changed

+77
-17
lines changed

3 files changed

+77
-17
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ include(cmake/string_catalog.cmake)
2525
add_versioned_package("gh:boostorg/mp11#boost-1.83.0")
2626
fmt_recipe(11.1.3)
2727
add_versioned_package("gh:intel/cpp-baremetal-concurrency#7c5b26c")
28-
add_versioned_package("gh:intel/cpp-std-extensions#7725142")
28+
add_versioned_package("gh:intel/cpp-std-extensions#01be679")
2929
add_versioned_package("gh:intel/cpp-baremetal-senders-and-receivers#0525974")
3030

3131
set(GEN_STR_CATALOG

include/log/log.hpp

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
#include <stdx/ct_format.hpp>
1010
#include <stdx/ct_string.hpp>
1111
#include <stdx/panic.hpp>
12+
#if __cpp_pack_indexing < 202311L
13+
#include <stdx/tuple.hpp>
14+
#endif
1215
#include <stdx/type_traits.hpp>
1316
#include <stdx/utility.hpp>
1417

@@ -74,14 +77,57 @@ static auto log(TArgs &&...args) -> void {
7477
#define CIB_ERROR(...) \
7578
CIB_LOG_WITH_LEVEL(logging::level::ERROR __VA_OPT__(, ) __VA_ARGS__)
7679

80+
namespace logging::detail {
81+
template <stdx::ct_string Fmt, typename Env, typename F, typename L>
82+
[[nodiscard]] constexpr auto panic(F file, L line, auto &&...args) {
83+
STDX_PRAGMA(diagnostic push)
84+
#ifdef __clang__
85+
STDX_PRAGMA(diagnostic ignored "-Wunknown-warning-option")
86+
STDX_PRAGMA(diagnostic ignored "-Wc++26-extensions")
87+
#endif
88+
89+
constexpr auto N = stdx::num_fmt_specifiers<Fmt>;
90+
constexpr auto sz = sizeof...(args);
91+
using env_t =
92+
stdx::extend_env_t<Env, logging::get_level, logging::level::FATAL>;
93+
94+
#if __cpp_pack_indexing >= 202311L
95+
auto s = [&]<std::size_t... Is>(std::index_sequence<Is...>) {
96+
return stdx::ct_format<Fmt>(FWD(args...[Is])...);
97+
}(std::make_index_sequence<N>{});
98+
logging::log<env_t>(file, line, s);
99+
100+
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
101+
stdx::panic<decltype(s.str)::value>(std::move(s).args,
102+
FWD(args...[N + Is])...);
103+
}(std::make_index_sequence<sz - N>{});
104+
#else
105+
auto tup = stdx::make_tuple(FWD(args)...);
106+
auto t = [&]<std::size_t... Is, std::size_t... Js>(
107+
std::index_sequence<Is...>, std::index_sequence<Js...>) {
108+
return stdx::make_tuple(
109+
stdx::make_tuple(stdx::get<Is>(std::move(tup))...),
110+
stdx::make_tuple(stdx::get<sizeof...(Is) + Js>(std::move(tup))...));
111+
}(std::make_index_sequence<N>{}, std::make_index_sequence<sz - N>{});
112+
113+
auto s = stdx::get<0>(std::move(t)).apply([](auto &&...fmt_args) {
114+
return stdx::ct_format<Fmt>(FWD(fmt_args)...);
115+
});
116+
logging::log<env_t>(file, line, s);
117+
118+
stdx::get<1>(std::move(t)).apply([&](auto &&...extra_args) {
119+
stdx::panic<decltype(s.str)::value>(std::move(s).args,
120+
FWD(extra_args)...);
121+
});
122+
#endif
123+
124+
STDX_PRAGMA(diagnostic pop)
125+
}
126+
} // namespace logging::detail
127+
77128
#define CIB_FATAL(MSG, ...) \
78-
[](auto &&s) { \
79-
CIB_LOG_ENV(logging::get_level, logging::level::FATAL); \
80-
logging::log<cib_log_env_t>(__FILE__, __LINE__, s); \
81-
FWD(s).args.apply([](auto &&...args) { \
82-
stdx::panic<decltype(s.str)::value>(FWD(args)...); \
83-
}); \
84-
}(stdx::ct_format<MSG>(__VA_ARGS__))
129+
logging::detail::panic<MSG, cib_log_env_t>( \
130+
__FILE__, __LINE__ __VA_OPT__(, ) __VA_ARGS__)
85131

86132
#define CIB_ASSERT(expr) \
87133
((expr) ? void(0) : CIB_FATAL("Assertion failure: " #expr))

test/log/log.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,21 @@
33

44
#include <stdx/ct_string.hpp>
55
#include <stdx/panic.hpp>
6+
#include <stdx/tuple.hpp>
67
#include <stdx/utility.hpp>
78

89
#include <catch2/catch_test_macros.hpp>
910

11+
#include <any>
1012
#include <iterator>
11-
#include <optional>
1213
#include <string>
1314
#include <string_view>
15+
#include <tuple>
1416

1517
namespace {
1618
bool panicked{};
1719
std::string_view expected_why{};
18-
std::optional<int> expected_arg{};
20+
std::any expected_args{};
1921

2022
struct injected_handler {
2123
template <stdx::ct_string Why, typename... Args>
@@ -24,11 +26,11 @@ struct injected_handler {
2426
CAPTURE(s);
2527
CHECK(s.ends_with(expected_why));
2628
panicked = true;
27-
if (expected_arg) {
28-
CHECK(sizeof...(Args) == 1);
29-
if constexpr (sizeof...(Args) == 1) {
30-
CHECK(*expected_arg == (args, ...));
31-
}
29+
30+
if (expected_args.has_value()) {
31+
using expected_t = std::tuple<std::decay_t<Args>...>;
32+
CHECK(std::any_cast<expected_t>(expected_args) ==
33+
std::make_tuple(args...));
3234
}
3335
}
3436
};
@@ -38,7 +40,7 @@ std::string buffer{};
3840
auto reset_test_state() {
3941
panicked = false;
4042
expected_why = {};
41-
expected_arg.reset();
43+
expected_args.reset();
4244
buffer.clear();
4345
}
4446
} // namespace
@@ -88,11 +90,23 @@ TEST_CASE("CIB_FATAL pre-formats arguments passed to panic", "[log]") {
8890
TEST_CASE("CIB_FATAL can format stack arguments", "[log]") {
8991
reset_test_state();
9092
expected_why = "Hello {}";
91-
expected_arg = 42;
93+
expected_args = std::make_tuple(stdx::make_tuple(42));
9294

9395
auto x = 42;
9496
CIB_FATAL("Hello {}", x);
9597
CAPTURE(buffer);
9698
CHECK(buffer.find("Hello 42") != std::string::npos);
9799
CHECK(panicked);
98100
}
101+
102+
TEST_CASE("CIB_FATAL passes extra arguments to panic", "[log]") {
103+
reset_test_state();
104+
expected_why = "Hello {}";
105+
expected_args = std::make_tuple(stdx::make_tuple(42), 17);
106+
107+
auto x = 42;
108+
CIB_FATAL("Hello {}", x, 17);
109+
CAPTURE(buffer);
110+
CHECK(buffer.find("Hello 42") != std::string::npos);
111+
CHECK(panicked);
112+
}

0 commit comments

Comments
 (0)