From d7cb6ac2b1b309095820738f5fca3e84a3868b21 Mon Sep 17 00:00:00 2001 From: Gabriel Busnot Date: Fri, 20 Jan 2023 13:01:46 +0000 Subject: [PATCH] base: Turn all logging.hh macros into expression kind In the previous version, the body of several macros was a statement (do{...} while(0);) and not an expression. In the new version, all macros are expressions. Expressions can be used everywhere a statement is expected and in other locations as well. For instance, expressions can be used with the comma operator. When doing generic programming, the comma operator helps manipulating parameter packs. With a statement-based implementation, (gem5_assert(args > 0), ...) could not be written while perfectly sound. Also, (c1 ? a : c2 ? b : (gem5_assert(c3), c)) is a usefull expression to assert completeness of cascaded conditions that cannot be easily and efficiently achieved without an expression kind of assertion. Change-Id: Ia0efeb15e6deda6b90529a6f0e00ebe2e9b5d2a0 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/67336 Maintainer: Bobby Bruce Tested-by: kokoro Reviewed-by: Bobby Bruce --- src/base/logging.hh | 125 +++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 55 deletions(-) diff --git a/src/base/logging.hh b/src/base/logging.hh index 22fd2a84d2..f66423f652 100644 --- a/src/base/logging.hh +++ b/src/base/logging.hh @@ -138,9 +138,10 @@ class Logger const char *prefix; }; - -#define base_message(logger, ...) \ - logger.print(::gem5::Logger::Loc(__FILE__, __LINE__), __VA_ARGS__) +#define base_message(logger, ...) \ + [&log = logger](const auto&... args) { \ + log.print(::gem5::Logger::Loc(__FILE__, __LINE__), args...); \ + }(__VA_ARGS__) /* * Only print the message the first time this expression is @@ -150,19 +151,29 @@ class Logger * would have resulted in a different message thoes messages would be * supressed. */ -#define base_message_once(...) do { \ - static bool once = false; \ - if (!once) { \ - base_message(__VA_ARGS__); \ - once = true; \ - } \ - } while (0) +#define base_message_once(logger, ...) \ + [&log = logger](const auto&... args) { \ + static bool once{false}; \ + if (GEM5_UNLIKELY(!once)) { \ + once = true; \ + base_message(log, args...); \ + } \ + }(__VA_ARGS__) -#define exit_message(logger, ...) \ - do { \ - base_message(logger, __VA_ARGS__); \ - logger.exit_helper(); \ - } while (0) +/* + * logger.exit_helper() can't be called inside the lambda for now as the + * lambda's operator() can't be [[noreturn]]. As a result, exit_message and it' + * s derivative cannot be used in functions without also specifying a return + * value, which is inconvenient if not impossible. + */ + +#define exit_message(logger, ...) \ + ( \ + [&log = logger](const auto&... args) { \ + base_message(log, args...); \ + }(__VA_ARGS__), \ + logger.exit_helper() \ + ) /** * This implements a cprintf based panic() function. panic() should @@ -200,13 +211,13 @@ class Logger * * @ingroup api_logger */ -#define panic_if(cond, ...) \ - do { \ - if (GEM5_UNLIKELY(cond)) { \ - panic("panic condition " # cond " occurred: %s", \ - ::gem5::csprintf(__VA_ARGS__)); \ - } \ - } while (0) +#define panic_if(cond, ...) \ + ( \ + GEM5_UNLIKELY(static_cast(cond)) ? \ + panic("panic condition " # cond " occurred: %s", \ + ::gem5::csprintf(__VA_ARGS__)) : \ + void(0) \ + ) /** @@ -222,13 +233,13 @@ class Logger * * @ingroup api_logger */ -#define fatal_if(cond, ...) \ - do { \ - if (GEM5_UNLIKELY(cond)) { \ - fatal("fatal condition " # cond " occurred: %s", \ - ::gem5::csprintf(__VA_ARGS__)); \ - } \ - } while (0) +#define fatal_if(cond, ...) \ + ( \ + GEM5_UNLIKELY(static_cast(cond)) ? \ + fatal("fatal condition " # cond " occurred: %s", \ + ::gem5::csprintf(__VA_ARGS__)) : \ + void(0) \ + ) /** @@ -269,17 +280,20 @@ class Logger * @ingroup api_logger * @{ */ -#define warn_if(cond, ...) \ - do { \ - if (GEM5_UNLIKELY(cond)) \ - warn(__VA_ARGS__); \ - } while (0) +#define warn_if(cond, ...) \ + ( \ + static_cast(cond) ? \ + warn(__VA_ARGS__) : \ + void(0) \ + ) #define warn_if_once(cond, ...) \ - do { \ - if (GEM5_UNLIKELY(cond)) \ - warn_once(__VA_ARGS__); \ - } while (0) + ( \ + static_cast(cond) ? \ + warn_once(__VA_ARGS__) : \ + void(0) \ + ) + /** @} */ // end of api_logger #ifdef NDEBUG @@ -300,25 +314,26 @@ class Logger * * @ingroup api_logger */ -#define gem5_assert(cond, ...) \ - do { \ - GEM5_UNLIKELY(NDEBUG_DEFINED || static_cast(cond)) ? \ - void(0) : \ - [](const auto&... args) { \ - auto msg = [&]{ \ - if constexpr (sizeof...(args) == 0) return ""; \ - else return std::string(": ") + csprintf(args...); \ - }; \ - panic("assert(" #cond ") failed%s", msg()); \ - }(__VA_ARGS__); \ - } while (0) +#define gem5_assert(cond, ...) \ + ( \ + GEM5_UNLIKELY(NDEBUG_DEFINED || static_cast(cond)) ? \ + void(0) : \ + [](const auto&... args) { \ + auto msg = [&]{ \ + if constexpr (sizeof...(args) == 0) return ""; \ + else return std::string(": ") + csprintf(args...); \ + }; \ + panic("assert(" #cond ") failed%s", msg()); \ + }(__VA_ARGS__) \ + ) + /** @} */ // end of api_logger -#define chatty_assert(...) \ - do { \ - gem5_assert(__VA_ARGS__); \ - GEM5_DEPRECATED_MACRO(chatty_assert, {}, "Please use gem5_assert()"); \ - } while(0) +#define chatty_assert(...) \ + ( \ + gem5_assert(args...), \ + GEM5_DEPRECATED_MACRO(chatty_assert, {}, "Please use gem5_assert()") \ + ) } // namespace gem5 #endif // __BASE_LOGGING_HH__