diff options
Diffstat (limited to 'base/logging.h')
-rw-r--r-- | base/logging.h | 402 |
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. // |