diff --git a/src/base/logging.cc b/src/base/logging.cc index cadcb6f1de..c94fe9d693 100644 --- a/src/base/logging.cc +++ b/src/base/logging.cc @@ -14,9 +14,8 @@ namespace v8 { namespace base { // Explicit instantiations for commonly used comparisons. -#define DEFINE_MAKE_CHECK_OP_STRING(type) \ - template std::string* MakeCheckOpString( \ - type const&, type const&, char const*); +#define DEFINE_MAKE_CHECK_OP_STRING(type) \ + template std::string* MakeCheckOpString(type, type, char const*); DEFINE_MAKE_CHECK_OP_STRING(int) DEFINE_MAKE_CHECK_OP_STRING(long) // NOLINT(runtime/int) DEFINE_MAKE_CHECK_OP_STRING(long long) // NOLINT(runtime/int) @@ -29,11 +28,11 @@ DEFINE_MAKE_CHECK_OP_STRING(void const*) // Explicit instantiations for floating point checks. -#define DEFINE_CHECK_OP_IMPL(NAME) \ - template std::string* Check##NAME##Impl( \ - float const& lhs, float const& rhs, char const* msg); \ - template std::string* Check##NAME##Impl( \ - double const& lhs, double const& rhs, char const* msg); +#define DEFINE_CHECK_OP_IMPL(NAME) \ + template std::string* Check##NAME##Impl(float lhs, float rhs, \ + char const* msg); \ + template std::string* Check##NAME##Impl( \ + double lhs, double rhs, char const* msg); DEFINE_CHECK_OP_IMPL(EQ) DEFINE_CHECK_OP_IMPL(NE) DEFINE_CHECK_OP_IMPL(LE) diff --git a/src/base/logging.h b/src/base/logging.h index 4de8b537cb..eae8a7fdb6 100644 --- a/src/base/logging.h +++ b/src/base/logging.h @@ -55,13 +55,14 @@ namespace base { // Helper macro for binary operators. // Don't use this macro directly in your code, use CHECK_EQ et al below. -#define CHECK_OP(name, op, lhs, rhs) \ - do { \ - if (std::string* _msg = ::v8::base::Check##name##Impl( \ - (lhs), (rhs), #lhs " " #op " " #rhs)) { \ - V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", _msg->c_str()); \ - delete _msg; \ - } \ +#define CHECK_OP(name, op, lhs, rhs) \ + do { \ + if (std::string* _msg = \ + ::v8::base::Check##name##Impl( \ + (lhs), (rhs), #lhs " " #op " " #rhs)) { \ + V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", _msg->c_str()); \ + delete _msg; \ + } \ } while (0) #else @@ -73,13 +74,26 @@ namespace base { #endif +// Helpers to determine how to pass values: Pass scalars by value, others by +// const reference. +template +struct PassByValue { + enum : bool { + value = (std::is_scalar::value || std::is_array::value) && + (std::is_scalar::value || std::is_array::value) + }; +}; +template +struct PassType + : public std::conditional::value, T, T const&> {}; // Build the error message string. This is separate from the "Impl" // function template because it is not performance critical and so can // be out of line, while the "Impl" code should be inline. Caller // takes ownership of the returned string. template -std::string* MakeCheckOpString(Lhs const& lhs, Rhs const& rhs, +std::string* MakeCheckOpString(typename PassType::type lhs, + typename PassType::type rhs, char const* msg) { std::ostringstream ss; ss << msg << " (" << lhs << " vs. " << rhs << ")"; @@ -90,7 +104,7 @@ std::string* MakeCheckOpString(Lhs const& lhs, Rhs const& rhs, // in logging.cc. #define DEFINE_MAKE_CHECK_OP_STRING(type) \ extern template V8_BASE_EXPORT std::string* MakeCheckOpString( \ - type const&, type const&, char const*); + type, type, char const*); DEFINE_MAKE_CHECK_OP_STRING(int) DEFINE_MAKE_CHECK_OP_STRING(long) // NOLINT(runtime/int) DEFINE_MAKE_CHECK_OP_STRING(long long) // NOLINT(runtime/int) @@ -101,27 +115,21 @@ DEFINE_MAKE_CHECK_OP_STRING(char const*) DEFINE_MAKE_CHECK_OP_STRING(void const*) #undef DEFINE_MAKE_CHECK_OP_STRING - // Helper functions for CHECK_OP macro. -// The (int, int) specialization works around the issue that the compiler -// will not instantiate the template version of the function on values of -// unnamed enum type - see comment below. // The (float, float) and (double, double) instantiations are explicitly // externialized to ensure proper 32/64-bit comparisons on x86. #define DEFINE_CHECK_OP_IMPL(NAME, op) \ template \ - V8_INLINE std::string* Check##NAME##Impl(Lhs const& lhs, Rhs const& rhs, \ + V8_INLINE std::string* Check##NAME##Impl(typename PassType::type lhs, \ + typename PassType::type rhs, \ char const* msg) { \ - return V8_LIKELY(lhs op rhs) ? nullptr : MakeCheckOpString(lhs, rhs, msg); \ - } \ - V8_INLINE std::string* Check##NAME##Impl(int lhs, int rhs, \ - char const* msg) { \ - return V8_LIKELY(lhs op rhs) ? nullptr : MakeCheckOpString(lhs, rhs, msg); \ + return V8_LIKELY(lhs op rhs) ? nullptr \ + : MakeCheckOpString(lhs, rhs, msg); \ } \ extern template V8_BASE_EXPORT std::string* Check##NAME##Impl( \ - float const& lhs, float const& rhs, char const* msg); \ + const float lhs, const float rhs, char const* msg); \ extern template V8_BASE_EXPORT std::string* \ - Check##NAME##Impl(double const& lhs, double const& rhs, \ + Check##NAME##Impl(const double lhs, const double rhs, \ char const* msg); DEFINE_CHECK_OP_IMPL(EQ, ==) DEFINE_CHECK_OP_IMPL(NE, !=) diff --git a/test/unittests/base/logging-unittest.cc b/test/unittests/base/logging-unittest.cc index 918feb114b..d79e59ee06 100644 --- a/test/unittests/base/logging-unittest.cc +++ b/test/unittests/base/logging-unittest.cc @@ -8,11 +8,18 @@ namespace v8 { namespace base { +namespace { +template +std::string *CallCheckEQ(Lhs lhs, Rhs rhs, const char *msg) { + return CheckEQImpl(lhs, rhs, msg); +} +} // namespace + TEST(LoggingTest, CheckEQImpl) { - EXPECT_EQ(nullptr, CheckEQImpl(0.0, 0.0, "")); - EXPECT_EQ(nullptr, CheckEQImpl(0.0, -0.0, "")); - EXPECT_EQ(nullptr, CheckEQImpl(-0.0, 0.0, "")); - EXPECT_EQ(nullptr, CheckEQImpl(-0.0, -0.0, "")); + EXPECT_EQ(nullptr, CallCheckEQ(0.0, 0.0, "")); + EXPECT_EQ(nullptr, CallCheckEQ(0.0, -0.0, "")); + EXPECT_EQ(nullptr, CallCheckEQ(-0.0, 0.0, "")); + EXPECT_EQ(nullptr, CallCheckEQ(-0.0, -0.0, "")); } } // namespace base