summaryrefslogtreecommitdiff
path: root/base/logging.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/logging.h')
-rw-r--r--base/logging.h402
1 files changed, 270 insertions, 132 deletions
diff --git a/base/logging.h b/base/logging.h
index 2bfc972601..7ca018e227 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -15,6 +15,7 @@
#include <utility>
#include "base/base_export.h"
+#include "base/compiler_specific.h"
#include "base/debug/debugger.h"
#include "base/macros.h"
#include "base/template_util.h"
@@ -140,34 +141,6 @@
// There is the special severity of DFATAL, which logs FATAL in debug mode,
// ERROR in normal mode.
-// Note that "The behavior of a C++ program is undefined if it adds declarations
-// or definitions to namespace std or to a namespace within namespace std unless
-// otherwise specified." --C++11[namespace.std]
-//
-// We've checked that this particular definition has the intended behavior on
-// our implementations, but it's prone to breaking in the future, and please
-// don't imitate this in your own definitions without checking with some
-// standard library experts.
-namespace std {
-// These functions are provided as a convenience for logging, which is where we
-// use streams (it is against Google style to use streams in other places). It
-// is designed to allow you to emit non-ASCII Unicode strings to the log file,
-// which is normally ASCII. It is relatively slow, so try not to use it for
-// common cases. Non-ASCII characters will be converted to UTF-8 by these
-// operators.
-BASE_EXPORT std::ostream& operator<<(std::ostream& out, const wchar_t* wstr);
-inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
- return out << wstr.c_str();
-}
-
-template<typename T>
-typename std::enable_if<std::is_enum<T>::value, std::ostream&>::type operator<<(
- std::ostream& out, T value) {
- return out << static_cast<typename std::underlying_type<T>::type>(value);
-}
-
-} // namespace std
-
namespace logging {
// TODO(avi): do we want to do a unification of character types here?
@@ -337,15 +310,16 @@ const LogSeverity LOG_DFATAL = LOG_FATAL;
// by LOG() and LOG_IF, etc. Since these are used all over our code, it's
// better to have compact code for these operations.
#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__)
+ ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_INFO, ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
+ ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_WARNING, \
+ ##__VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__)
+ ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_ERROR, ##__VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__)
+ ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_FATAL, ##__VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
- logging::ClassName(__FILE__, __LINE__, logging::LOG_DFATAL , ##__VA_ARGS__)
+ ::logging::ClassName(__FILE__, __LINE__, ::logging::LOG_DFATAL, ##__VA_ARGS__)
#define COMPACT_GOOGLE_LOG_INFO \
COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
@@ -406,7 +380,7 @@ const LogSeverity LOG_0 = LOG_ERROR;
// The VLOG macros log with negative verbosities.
#define VLOG_STREAM(verbose_level) \
- logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream()
+ ::logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream()
#define VLOG(verbose_level) \
LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
@@ -417,11 +391,11 @@ const LogSeverity LOG_0 = LOG_ERROR;
#if defined (OS_WIN)
#define VPLOG_STREAM(verbose_level) \
- logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \
+ ::logging::Win32ErrorLogMessage(__FILE__, __LINE__, -verbose_level, \
::logging::GetLastSystemErrorCode()).stream()
#elif defined(OS_POSIX)
#define VPLOG_STREAM(verbose_level) \
- logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \
+ ::logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \
::logging::GetLastSystemErrorCode()).stream()
#endif
@@ -434,7 +408,7 @@ const LogSeverity LOG_0 = LOG_ERROR;
// TODO(akalin): Add more VLOG variants, e.g. VPLOG.
-#define LOG_ASSERT(condition) \
+#define LOG_ASSERT(condition) \
LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
#if defined(OS_WIN)
@@ -453,9 +427,23 @@ const LogSeverity LOG_0 = LOG_ERROR;
#define PLOG_IF(severity, condition) \
LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
-// The actual stream used isn't important.
-#define EAT_STREAM_PARAMETERS \
- true ? (void) 0 : ::logging::LogMessageVoidify() & LOG_STREAM(FATAL)
+BASE_EXPORT extern std::ostream* g_swallow_stream;
+
+// Note that g_swallow_stream is used instead of an arbitrary LOG() stream to
+// avoid the creation of an object with a non-trivial destructor (LogMessage).
+// On MSVC x86 (checked on 2015 Update 3), this causes a few additional
+// pointless instructions to be emitted even at full optimization level, even
+// though the : arm of the ternary operator is clearly never executed. Using a
+// simpler object to be &'d with Voidify() avoids these extra instructions.
+// Using a simpler POD object with a templated operator<< also works to avoid
+// these instructions. However, this causes warnings on statically defined
+// implementations of operator<<(std::ostream, ...) in some .cc files, because
+// they become defined-but-unreferenced functions. A reinterpret_cast of 0 to an
+// ostream* also is not suitable, because some compilers warn of undefined
+// behavior.
+#define EAT_STREAM_PARAMETERS \
+ true ? (void)0 \
+ : ::logging::LogMessageVoidify() & (*::logging::g_swallow_stream)
// Captures the result of a CHECK_EQ (for example) and facilitates testing as a
// boolean.
@@ -472,6 +460,84 @@ class CheckOpResult {
std::string* message_;
};
+// Crashes in the fastest possible way with no attempt at logging.
+// There are different constraints to satisfy here, see http://crbug.com/664209
+// for more context:
+// - The trap instructions, and hence the PC value at crash time, have to be
+// distinct and not get folded into the same opcode by the compiler.
+// On Linux/Android this is tricky because GCC still folds identical
+// asm volatile blocks. The workaround is generating distinct opcodes for
+// each CHECK using the __COUNTER__ macro.
+// - The debug info for the trap instruction has to be attributed to the source
+// line that has the CHECK(), to make crash reports actionable. This rules
+// out the ability of using a inline function, at least as long as clang
+// doesn't support attribute(artificial).
+// - Failed CHECKs should produce a signal that is distinguishable from an
+// invalid memory access, to improve the actionability of crash reports.
+// - The compiler should treat the CHECK as no-return instructions, so that the
+// trap code can be efficiently packed in the prologue of the function and
+// doesn't interfere with the main execution flow.
+// - When debugging, developers shouldn't be able to accidentally step over a
+// CHECK. This is achieved by putting opcodes that will cause a non
+// continuable exception after the actual trap instruction.
+// - Don't cause too much binary bloat.
+#if defined(COMPILER_GCC)
+
+#if defined(ARCH_CPU_X86_FAMILY) && !defined(OS_NACL)
+// int 3 will generate a SIGTRAP.
+#define TRAP_SEQUENCE() \
+ asm volatile( \
+ "int3; ud2; push %0;" ::"i"(static_cast<unsigned char>(__COUNTER__)))
+
+#elif defined(ARCH_CPU_ARMEL) && !defined(OS_NACL)
+// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running
+// as a 32 bit userspace app on arm64. There doesn't seem to be any way to
+// cause a SIGTRAP from userspace without using a syscall (which would be a
+// problem for sandboxing).
+#define TRAP_SEQUENCE() \
+ asm volatile("bkpt #0; udf %0;" ::"i"(__COUNTER__ % 256))
+
+#elif defined(ARCH_CPU_ARM64) && !defined(OS_NACL)
+// This will always generate a SIGTRAP on arm64.
+#define TRAP_SEQUENCE() \
+ asm volatile("brk #0; hlt %0;" ::"i"(__COUNTER__ % 65536))
+
+#else
+// Crash report accuracy will not be guaranteed on other architectures, but at
+// least this will crash as expected.
+#define TRAP_SEQUENCE() __builtin_trap()
+#endif // ARCH_CPU_*
+
+#define IMMEDIATE_CRASH() \
+ ({ \
+ TRAP_SEQUENCE(); \
+ __builtin_unreachable(); \
+ })
+
+#elif defined(COMPILER_MSVC)
+
+// Clang is cleverer about coalescing int3s, so we need to add a unique-ish
+// instruction following the __debugbreak() to have it emit distinct locations
+// for CHECKs rather than collapsing them all together. It would be nice to use
+// a short intrinsic to do this (and perhaps have only one implementation for
+// both clang and MSVC), however clang-cl currently does not support intrinsics.
+// On the flip side, MSVC x64 doesn't support inline asm. So, we have to have
+// two implementations. Normally clang-cl's version will be 5 bytes (1 for
+// `int3`, 2 for `ud2`, 2 for `push byte imm`, however, TODO(scottmg):
+// https://crbug.com/694670 clang-cl doesn't currently support %'ing
+// __COUNTER__, so eventually it will emit the dword form of push.
+// TODO(scottmg): Reinvestigate a short sequence that will work on both
+// compilers once clang supports more intrinsics. See https://crbug.com/693713.
+#if defined(__clang__)
+#define IMMEDIATE_CRASH() ({__asm int 3 __asm ud2 __asm push __COUNTER__})
+#else
+#define IMMEDIATE_CRASH() __debugbreak()
+#endif // __clang__
+
+#else
+#error Port
+#endif
+
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.
@@ -481,20 +547,14 @@ class CheckOpResult {
#if defined(OFFICIAL_BUILD) && defined(NDEBUG)
-// Make all CHECK functions discard their log strings to reduce code
-// bloat, and improve performance, for official release builds.
-
-#if defined(COMPILER_GCC) || __clang__
-#define LOGGING_CRASH() __builtin_trap()
-#else
-#define LOGGING_CRASH() ((void)(*(volatile char*)0 = 0))
-#endif
-
+// Make all CHECK functions discard their log strings to reduce code bloat, and
+// improve performance, for official release builds.
+//
// This is not calling BreakDebugger since this is called frequently, and
// calling an out-of-line function instead of a noreturn inline macro prevents
// compiler optimizations.
-#define CHECK(condition) \
- !(condition) ? LOGGING_CRASH() : EAT_STREAM_PARAMETERS
+#define CHECK(condition) \
+ UNLIKELY(!(condition)) ? IMMEDIATE_CRASH() : EAT_STREAM_PARAMETERS
#define PCHECK(condition) CHECK(condition)
@@ -510,26 +570,26 @@ class CheckOpResult {
// __analysis_assume gets confused on some conditions:
// http://randomascii.wordpress.com/2011/09/13/analyze-for-visual-studio-the-ugly-part-5/
-#define CHECK(condition) \
- __analysis_assume(!!(condition)), \
- LAZY_STREAM(LOG_STREAM(FATAL), false) \
- << "Check failed: " #condition ". "
+#define CHECK(condition) \
+ __analysis_assume(!!(condition)), \
+ LAZY_STREAM(LOG_STREAM(FATAL), false) \
+ << "Check failed: " #condition ". "
-#define PCHECK(condition) \
- __analysis_assume(!!(condition)), \
- LAZY_STREAM(PLOG_STREAM(FATAL), false) \
- << "Check failed: " #condition ". "
+#define PCHECK(condition) \
+ __analysis_assume(!!(condition)), \
+ LAZY_STREAM(PLOG_STREAM(FATAL), false) \
+ << "Check failed: " #condition ". "
#else // _PREFAST_
// Do as much work as possible out of line to reduce inline code size.
-#define CHECK(condition) \
- LAZY_STREAM(logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \
+#define CHECK(condition) \
+ LAZY_STREAM(::logging::LogMessage(__FILE__, __LINE__, #condition).stream(), \
!(condition))
#define PCHECK(condition) \
LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
- << "Check failed: " #condition ". "
+ << "Check failed: " #condition ". "
#endif // _PREFAST_
@@ -541,12 +601,12 @@ class CheckOpResult {
// CHECK_EQ(2, a);
#define CHECK_OP(name, op, val1, val2) \
switch (0) case 0: default: \
- if (logging::CheckOpResult true_if_passed = \
- logging::Check##name##Impl((val1), (val2), \
- #val1 " " #op " " #val2)) \
+ if (::logging::CheckOpResult true_if_passed = \
+ ::logging::Check##name##Impl((val1), (val2), \
+ #val1 " " #op " " #val2)) \
; \
else \
- logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream()
+ ::logging::LogMessage(__FILE__, __LINE__, true_if_passed.message()).stream()
#endif // !(OFFICIAL_BUILD && NDEBUG)
@@ -554,12 +614,26 @@ class CheckOpResult {
// it uses the definition for operator<<, with a few special cases below.
template <typename T>
inline typename std::enable_if<
- base::internal::SupportsOstreamOperator<const T&>::value,
+ base::internal::SupportsOstreamOperator<const T&>::value &&
+ !std::is_function<typename std::remove_pointer<T>::type>::value,
void>::type
MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
+// Provide an overload for functions and function pointers. Function pointers
+// don't implicitly convert to void* but do implicitly convert to bool, so
+// without this function pointers are always printed as 1 or 0. (MSVC isn't
+// standards-conforming here and converts function pointers to regular
+// pointers, so this is a no-op for MSVC.)
+template <typename T>
+inline typename std::enable_if<
+ std::is_function<typename std::remove_pointer<T>::type>::value,
+ void>::type
+MakeCheckOpValueString(std::ostream* os, const T& v) {
+ (*os) << reinterpret_cast<const void*>(v);
+}
+
// We need overloads for enums that don't support operator<<.
// (i.e. scoped enums where no operator<< overload was declared).
template <typename T>
@@ -611,16 +685,20 @@ std::string* MakeCheckOpString<std::string, std::string>(
// 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.
-#define DEFINE_CHECK_OP_IMPL(name, op) \
- template <class t1, class t2> \
- inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
- const char* names) { \
- if (v1 op v2) return NULL; \
- else return MakeCheckOpString(v1, v2, names); \
- } \
+#define DEFINE_CHECK_OP_IMPL(name, op) \
+ template <class t1, class t2> \
+ inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \
+ const char* names) { \
+ if (v1 op v2) \
+ return NULL; \
+ else \
+ return ::logging::MakeCheckOpString(v1, v2, names); \
+ } \
inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \
- if (v1 op v2) return NULL; \
- else return MakeCheckOpString(v1, v2, names); \
+ if (v1 op v2) \
+ return NULL; \
+ else \
+ return ::logging::MakeCheckOpString(v1, v2, names); \
}
DEFINE_CHECK_OP_IMPL(EQ, ==)
DEFINE_CHECK_OP_IMPL(NE, !=)
@@ -638,12 +716,6 @@ DEFINE_CHECK_OP_IMPL(GT, > )
#define CHECK_GT(val1, val2) CHECK_OP(GT, > , val1, val2)
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
-#define ENABLE_DLOG 0
-#else
-#define ENABLE_DLOG 1
-#endif
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
#define DCHECK_IS_ON() 0
#else
#define DCHECK_IS_ON() 1
@@ -651,7 +723,7 @@ DEFINE_CHECK_OP_IMPL(GT, > )
// Definitions for DLOG et al.
-#if ENABLE_DLOG
+#if DCHECK_IS_ON()
#define DLOG_IS_ON(severity) LOG_IS_ON(severity)
#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
@@ -660,12 +732,11 @@ DEFINE_CHECK_OP_IMPL(GT, > )
#define DVLOG_IF(verboselevel, condition) VLOG_IF(verboselevel, condition)
#define DVPLOG_IF(verboselevel, condition) VPLOG_IF(verboselevel, condition)
-#else // ENABLE_DLOG
+#else // DCHECK_IS_ON()
-// If ENABLE_DLOG is off, we want to avoid emitting any references to
-// |condition| (which may reference a variable defined only if NDEBUG
-// is not defined). Contrast this with DCHECK et al., which has
-// different behavior.
+// If !DCHECK_IS_ON(), we want to avoid emitting any references to |condition|
+// (which may reference a variable defined only if DCHECK_IS_ON()).
+// Contrast this with DCHECK et al., which has different behavior.
#define DLOG_IS_ON(severity) false
#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS
@@ -674,19 +745,7 @@ DEFINE_CHECK_OP_IMPL(GT, > )
#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
-#endif // ENABLE_DLOG
-
-// DEBUG_MODE is for uses like
-// if (DEBUG_MODE) foo.CheckThatFoo();
-// instead of
-// #ifndef NDEBUG
-// foo.CheckThatFoo();
-// #endif
-//
-// We tie its state to ENABLE_DLOG.
-enum { DEBUG_MODE = ENABLE_DLOG };
-
-#undef ENABLE_DLOG
+#endif // DCHECK_IS_ON()
#define DLOG(severity) \
LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity))
@@ -721,31 +780,63 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
// whether DCHECKs are enabled; this is so that we don't get unused
// variable warnings if the only use of a variable is in a DCHECK.
// This behavior is different from DLOG_IF et al.
+//
+// Note that the definition of the DCHECK macros depends on whether or not
+// DCHECK_IS_ON() is true. When DCHECK_IS_ON() is false, the macros use
+// EAT_STREAM_PARAMETERS to avoid expressions that would create temporaries.
#if defined(_PREFAST_) && defined(OS_WIN)
// See comments on the previous use of __analysis_assume.
-#define DCHECK(condition) \
- __analysis_assume(!!(condition)), \
- LAZY_STREAM(LOG_STREAM(DCHECK), false) \
- << "Check failed: " #condition ". "
+#define DCHECK(condition) \
+ __analysis_assume(!!(condition)), \
+ LAZY_STREAM(LOG_STREAM(DCHECK), false) \
+ << "Check failed: " #condition ". "
-#define DPCHECK(condition) \
- __analysis_assume(!!(condition)), \
- LAZY_STREAM(PLOG_STREAM(DCHECK), false) \
- << "Check failed: " #condition ". "
+#define DPCHECK(condition) \
+ __analysis_assume(!!(condition)), \
+ LAZY_STREAM(PLOG_STREAM(DCHECK), false) \
+ << "Check failed: " #condition ". "
-#else // _PREFAST_
+#elif defined(__clang_analyzer__)
+
+// Keeps the static analyzer from proceeding along the current codepath,
+// otherwise false positive errors may be generated by null pointer checks.
+inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) {
+ return false;
+}
-#define DCHECK(condition) \
- LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \
+#define DCHECK(condition) \
+ LAZY_STREAM( \
+ LOG_STREAM(DCHECK), \
+ DCHECK_IS_ON() ? (logging::AnalyzerNoReturn() || !(condition)) : false) \
<< "Check failed: " #condition ". "
-#define DPCHECK(condition) \
- LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON() ? !(condition) : false) \
+#define DPCHECK(condition) \
+ LAZY_STREAM( \
+ PLOG_STREAM(DCHECK), \
+ DCHECK_IS_ON() ? (logging::AnalyzerNoReturn() || !(condition)) : false) \
<< "Check failed: " #condition ". "
-#endif // _PREFAST_
+#else
+
+#if DCHECK_IS_ON()
+
+#define DCHECK(condition) \
+ LAZY_STREAM(LOG_STREAM(DCHECK), !(condition)) \
+ << "Check failed: " #condition ". "
+#define DPCHECK(condition) \
+ LAZY_STREAM(PLOG_STREAM(DCHECK), !(condition)) \
+ << "Check failed: " #condition ". "
+
+#else // DCHECK_IS_ON()
+
+#define DCHECK(condition) EAT_STREAM_PARAMETERS << !(condition)
+#define DPCHECK(condition) EAT_STREAM_PARAMETERS << !(condition)
+
+#endif // DCHECK_IS_ON()
+
+#endif
// Helper macro for binary operators.
// Don't use this macro directly in your code, use DCHECK_EQ et al below.
@@ -753,16 +844,37 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
// macro is used in an 'if' clause such as:
// if (a == 1)
// DCHECK_EQ(2, a);
-#define DCHECK_OP(name, op, val1, val2) \
- switch (0) case 0: default: \
- if (logging::CheckOpResult true_if_passed = \
- DCHECK_IS_ON() ? \
- logging::Check##name##Impl((val1), (val2), \
- #val1 " " #op " " #val2) : nullptr) \
- ; \
- else \
- logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \
- true_if_passed.message()).stream()
+#if DCHECK_IS_ON()
+
+#define DCHECK_OP(name, op, val1, val2) \
+ switch (0) case 0: default: \
+ if (::logging::CheckOpResult true_if_passed = \
+ DCHECK_IS_ON() ? \
+ ::logging::Check##name##Impl((val1), (val2), \
+ #val1 " " #op " " #val2) : nullptr) \
+ ; \
+ else \
+ ::logging::LogMessage(__FILE__, __LINE__, ::logging::LOG_DCHECK, \
+ true_if_passed.message()).stream()
+
+#else // DCHECK_IS_ON()
+
+// When DCHECKs aren't enabled, DCHECK_OP still needs to reference operator<<
+// overloads for |val1| and |val2| to avoid potential compiler warnings about
+// unused functions. For the same reason, it also compares |val1| and |val2|
+// using |op|.
+//
+// Note that the contract of DCHECK_EQ, etc is that arguments are only evaluated
+// once. Even though |val1| and |val2| appear twice in this version of the macro
+// expansion, this is OK, since the expression is never actually evaluated.
+#define DCHECK_OP(name, op, val1, val2) \
+ EAT_STREAM_PARAMETERS << (::logging::MakeCheckOpValueString( \
+ ::logging::g_swallow_stream, val1), \
+ ::logging::MakeCheckOpValueString( \
+ ::logging::g_swallow_stream, val2), \
+ (val1)op(val2))
+
+#endif // DCHECK_IS_ON()
// Equality/Inequality checks - compare two values, and log a
// LOG_DCHECK message including the two values when the result is not
@@ -770,7 +882,7 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
// defined.
//
// You may append to the error message like so:
-// DCHECK_NE(1, 2) << ": The world must be ending!";
+// DCHECK_NE(1, 2) << "The world must be ending!";
//
// We are very careful to ensure that each argument is evaluated exactly
// once, and that anything which is legal to pass as a function argument is
@@ -834,6 +946,9 @@ class BASE_EXPORT LogMessage {
std::ostream& stream() { return stream_; }
+ LogSeverity severity() { return severity_; }
+ std::string str() { return stream_.str(); }
+
private:
void Init(const char* file, int line);
@@ -941,12 +1056,14 @@ BASE_EXPORT void CloseLogFile();
// Async signal safe logging mechanism.
BASE_EXPORT void RawLog(int level, const char* message);
-#define RAW_LOG(level, message) logging::RawLog(logging::LOG_ ## level, message)
+#define RAW_LOG(level, message) \
+ ::logging::RawLog(::logging::LOG_##level, message)
-#define RAW_CHECK(condition) \
- do { \
- if (!(condition)) \
- logging::RawLog(logging::LOG_FATAL, "Check failed: " #condition "\n"); \
+#define RAW_CHECK(condition) \
+ do { \
+ if (!(condition)) \
+ ::logging::RawLog(::logging::LOG_FATAL, \
+ "Check failed: " #condition "\n"); \
} while (0)
#if defined(OS_WIN)
@@ -959,6 +1076,27 @@ BASE_EXPORT std::wstring GetLogFileFullPath();
} // namespace logging
+// Note that "The behavior of a C++ program is undefined if it adds declarations
+// or definitions to namespace std or to a namespace within namespace std unless
+// otherwise specified." --C++11[namespace.std]
+//
+// We've checked that this particular definition has the intended behavior on
+// our implementations, but it's prone to breaking in the future, and please
+// don't imitate this in your own definitions without checking with some
+// standard library experts.
+namespace std {
+// These functions are provided as a convenience for logging, which is where we
+// use streams (it is against Google style to use streams in other places). It
+// is designed to allow you to emit non-ASCII Unicode strings to the log file,
+// which is normally ASCII. It is relatively slow, so try not to use it for
+// common cases. Non-ASCII characters will be converted to UTF-8 by these
+// operators.
+BASE_EXPORT std::ostream& operator<<(std::ostream& out, const wchar_t* wstr);
+inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
+ return out << wstr.c_str();
+}
+} // namespace std
+
// The NOTIMPLEMENTED() macro annotates codepaths which have
// not been implemented yet.
//