Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dcdd0add authored by Henri Chataing's avatar Henri Chataing
Browse files

system/log: Make log::fatal [[noreturn]]

[[noreturn]] cannot be attached to a class constructor,
instead implement log::fatal using template specialization of functions
with 0 up to 4 format parameters.

Test: m com.android.btservices
Test: atest libbluetooth_log_test
Bug: 305066880
Flag: EXEMPT, mechanical refactor
Change-Id: Ie095e56e7b50caabb4a0cd9cbfbf00879313f8d2
parent 0cac2866
Loading
Loading
Loading
Loading
+55 −8
Original line number Diff line number Diff line
@@ -102,8 +102,6 @@ namespace bluetooth::log {

#if (__cplusplus >= 202002L && defined(__GNUC__) && !defined(__clang__))

template <typename... T>
using fatal = log_internal::log<log_internal::kFatal, T...>;
template <typename... T>
using error = log_internal::log<log_internal::kError, T...>;
template <typename... T>
@@ -117,10 +115,6 @@ using verbose = log_internal::log<log_internal::kVerbose, T...>;

#else

template <typename... T>
struct fatal : log_internal::log<log_internal::kFatal, T...> {
  using log_internal::log<log_internal::kFatal, T...>::log;
};
template <typename... T>
struct error : log_internal::log<log_internal::kError, T...> {
  using log_internal::log<log_internal::kError, T...>::log;
@@ -142,8 +136,6 @@ struct verbose : log_internal::log<log_internal::kVerbose, T...> {
  using log_internal::log<log_internal::kVerbose, T...>::log;
};

template <typename... T>
fatal(fmt::format_string<T...>, T&&...) -> fatal<T...>;
template <typename... T>
error(fmt::format_string<T...>, T&&...) -> error<T...>;
template <typename... T>
@@ -157,6 +149,61 @@ verbose(fmt::format_string<T...>, T&&...) -> verbose<T...>;

#endif  // GCC / C++20

[[noreturn]] [[maybe_unused]] static void fatal(
    fmt::format_string<> fmt,
    log_internal::source_location location = log_internal::source_location()) {
  vlog(log_internal::kFatal, LOG_TAG, location,
       static_cast<fmt::string_view>(fmt), fmt::make_format_args());
  std::abort();  // Enforce [[noreturn]]
}

template <typename T0>
[[noreturn]] [[maybe_unused]] static void fatal(
    fmt::format_string<T0> fmt, T0&& arg0,
    log_internal::source_location location = log_internal::source_location()) {
  vlog(log_internal::kFatal, LOG_TAG, location,
       static_cast<fmt::string_view>(fmt),
       fmt::make_format_args(log_internal::format_replace(arg0)));
  std::abort();  // Enforce [[noreturn]]
}

template <typename T0, typename T1>
[[noreturn]] [[maybe_unused]] static void fatal(
    fmt::format_string<T0, T1> fmt, T0&& arg0, T1&& arg1,
    log_internal::source_location location = log_internal::source_location()) {
  vlog(log_internal::kFatal, LOG_TAG, location,
       static_cast<fmt::string_view>(fmt),
       fmt::make_format_args(log_internal::format_replace(arg0),
                             log_internal::format_replace(arg1)));
  std::abort();  // Enforce [[noreturn]]
}

template <typename T0, typename T1, typename T2>
[[noreturn]] [[maybe_unused]] static void fatal(
    fmt::format_string<T0, T1, T2> fmt, T0&& arg0, T1&& arg1, T2&& arg2,
    log_internal::source_location location = log_internal::source_location()) {
  vlog(log_internal::kFatal, LOG_TAG, location,
       static_cast<fmt::string_view>(fmt),
       fmt::make_format_args(log_internal::format_replace(arg0),
                             log_internal::format_replace(arg1),
                             log_internal::format_replace(arg2)));
  std::abort();  // Enforce [[noreturn]]
}

template <typename T0, typename T1, typename T2, typename T3>
[[noreturn]] [[maybe_unused]] static void fatal(
    fmt::format_string<T0, T1, T2, T3> fmt, T0&& arg0, T1&& arg1, T2&& arg2,
    T3&& arg3,
    log_internal::source_location location = log_internal::source_location()) {
  vlog(log_internal::kFatal, LOG_TAG, location,
       static_cast<fmt::string_view>(fmt),
       fmt::make_format_args(log_internal::format_replace(arg0),
                             log_internal::format_replace(arg1),
                             log_internal::format_replace(arg2),
                             log_internal::format_replace(arg3)));
  std::abort();  // Enforce [[noreturn]]
}

template <typename... T>
struct fatal_if {
  fatal_if(bool cond, fmt::format_string<T...> fmt, T&&... args,
+34 −3
Original line number Diff line number Diff line
@@ -118,6 +118,37 @@ TEST(BluetoothLoggerTest, error) {
               "TestBody: error test");
}

TEST(BluetoothLoggerTest, fatal) {
  androidLogMessage.reset();

  ASSERT_DEATH(
      {
        log::fatal("fatal test");
        // Validate that the compiler is correctly handling log::fatal as
        // [[noreturn]] by attempting to invoke an undefined function.
        // This test will fail linking if this check fails.
        void undefined_function();
        undefined_function();
      },
      "fatal test");

  ASSERT_DEATH(
      {
        log::fatal("fatal test {}", "2");
        void undefined_function();
        undefined_function();
      },
      "fatal test 2");

  ASSERT_DEATH(
      {
        log::fatal("fatal test {}, {}", 2, 3);
        void undefined_function();
        undefined_function();
      },
      "fatal test 2, 3");
}

TEST(BluetoothLoggerTest, fatal_if) {
  androidLogMessage.reset();

@@ -133,7 +164,7 @@ TEST(BluetoothLoggerTest, null_string_parameter) {
  char const* const_null_str = nullptr;
  log::info("input: {}", const_null_str);
  EXPECT_STREQ(androidLogMessage->message,
               "packages/modules/Bluetooth/system/log/src/vlog_test.cc:134 "
               "packages/modules/Bluetooth/system/log/src/vlog_test.cc:165 "
               "TestBody: input: (nullptr)");

  androidLogMessage.reset();
@@ -141,7 +172,7 @@ TEST(BluetoothLoggerTest, null_string_parameter) {
  char* null_str = nullptr;
  log::info("input: {}", null_str);
  EXPECT_STREQ(androidLogMessage->message,
               "packages/modules/Bluetooth/system/log/src/vlog_test.cc:142 "
               "packages/modules/Bluetooth/system/log/src/vlog_test.cc:173 "
               "TestBody: input: (nullptr)");

  androidLogMessage.reset();
@@ -149,6 +180,6 @@ TEST(BluetoothLoggerTest, null_string_parameter) {
  char const* nonnull_str = "hello world";
  log::info("input: {}", nonnull_str);
  EXPECT_STREQ(androidLogMessage->message,
               "packages/modules/Bluetooth/system/log/src/vlog_test.cc:150 "
               "packages/modules/Bluetooth/system/log/src/vlog_test.cc:181 "
               "TestBody: input: hello world");
}