Commit 959c569f authored by Wiktor Garbacz's avatar Wiktor Garbacz Committed by Commit Bot

[base] Better printing for char in CHECK_*

Non-printable characters will are printed as escapes.
NUL won't terminate error message prematurely now.

Change-Id: Ie24b34e377221e9b99d2268f8dfb5ce26d064cc2
Reviewed-on: https://chromium-review.googlesource.com/509490Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Commit-Queue: Wiktor Garbacz <wiktorg@google.com>
Cr-Commit-Position: refs/heads/master@{#45586}
parent 6674aed0
......@@ -4,6 +4,7 @@
#include "src/base/logging.h"
#include <cctype>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
......@@ -24,9 +25,51 @@ void SetPrintStackTrace(void (*print_stack_trace)()) {
g_print_stack_trace = print_stack_trace;
}
void PrettyPrintChar(std::ostream& os, int ch) {
switch (ch) {
#define CHAR_PRINT_CASE(ch) \
case ch: \
os << #ch; \
break;
CHAR_PRINT_CASE('\0')
CHAR_PRINT_CASE('\'')
CHAR_PRINT_CASE('\\')
CHAR_PRINT_CASE('\a')
CHAR_PRINT_CASE('\b')
CHAR_PRINT_CASE('\f')
CHAR_PRINT_CASE('\n')
CHAR_PRINT_CASE('\r')
CHAR_PRINT_CASE('\t')
CHAR_PRINT_CASE('\v')
#undef CHAR_PRINT_CASE
default:
if (std::isprint(ch)) {
os << '\'' << ch << '\'';
} else {
auto flags = os.flags(std::ios_base::hex);
os << "\\x" << static_cast<unsigned int>(ch);
os.flags(flags);
}
}
}
#define DEFINE_PRINT_CHECK_OPERAND_CHAR(type) \
template <> \
void PrintCheckOperand<type>(std::ostream & os, type ch) { \
PrettyPrintChar(os, ch); \
}
DEFINE_PRINT_CHECK_OPERAND_CHAR(char)
DEFINE_PRINT_CHECK_OPERAND_CHAR(signed char)
DEFINE_PRINT_CHECK_OPERAND_CHAR(unsigned char)
#undef DEFINE_PRINT_CHECK_OPERAND_CHAR
// Explicit instantiations for commonly used comparisons.
#define DEFINE_MAKE_CHECK_OP_STRING(type) \
template std::string* MakeCheckOpString<type, type>(type, type, char const*);
#define DEFINE_MAKE_CHECK_OP_STRING(type) \
template std::string* MakeCheckOpString<type, type>(type, type, \
char const*); \
template void PrintCheckOperand<type>(std::ostream&, type);
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)
......
......@@ -91,6 +91,22 @@ struct PassType : public std::conditional<
std::is_scalar<typename std::decay<T>::type>::value,
typename std::decay<T>::type, T const&> {};
template <typename Op>
void PrintCheckOperand(std::ostream& os, Op op) {
os << op;
}
void PrettyPrintChar(std::ostream& os, int ch);
#define DEFINE_PRINT_CHECK_OPERAND_CHAR(type) \
template <> \
V8_BASE_EXPORT void PrintCheckOperand<type>(std::ostream & os, type ch);
DEFINE_PRINT_CHECK_OPERAND_CHAR(char)
DEFINE_PRINT_CHECK_OPERAND_CHAR(signed char)
DEFINE_PRINT_CHECK_OPERAND_CHAR(unsigned char)
#undef DEFINE_PRINT_CHECK_OPERAND_CHAR
// 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
......@@ -100,7 +116,11 @@ std::string* MakeCheckOpString(typename PassType<Lhs>::type lhs,
typename PassType<Rhs>::type rhs,
char const* msg) {
std::ostringstream ss;
ss << msg << " (" << lhs << " vs. " << rhs << ")";
ss << msg << " (";
PrintCheckOperand(ss, lhs);
ss << " vs. ";
PrintCheckOperand(ss, rhs);
ss << ")";
return new std::string(ss.str());
}
......@@ -108,7 +128,9 @@ std::string* MakeCheckOpString(typename PassType<Lhs>::type lhs,
// in logging.cc.
#define DEFINE_MAKE_CHECK_OP_STRING(type) \
extern template V8_BASE_EXPORT std::string* MakeCheckOpString<type, type>( \
type, type, char const*);
type, type, char const*); \
extern template V8_BASE_EXPORT void PrintCheckOperand<type>(std::ostream&, \
type);
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)
......@@ -144,7 +166,7 @@ struct is_unsigned_vs_signed : public is_signed_vs_unsigned<Rhs, Lhs> {};
#define DEFINE_SIGNED_MISMATCH_COMP(CHECK, NAME, IMPL) \
template <typename Lhs, typename Rhs> \
V8_INLINE typename std::enable_if<CHECK<Lhs, Rhs>::value, bool>::type \
Cmp##NAME##Impl(Lhs const& lhs, Rhs const& rhs) { \
Cmp##NAME##Impl(Lhs lhs, Rhs rhs) { \
return IMPL; \
}
DEFINE_SIGNED_MISMATCH_COMP(is_signed_vs_unsigned, EQ,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment