Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Unified Diff: base/logging.h

Issue 2656053002: NullStream
Patch Set: . Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/time/time.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/logging.h
diff --git a/base/logging.h b/base/logging.h
index 6eb796fa4a4163541f4d194ada062da131876ef0..621e94daafaa3b1a188ecafece0f5702f89c5195 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -427,23 +427,21 @@ const LogSeverity LOG_0 = LOG_ERROR;
#define PLOG_IF(severity, condition) \
LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
-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)
+class NullStream {
+ public:
+ NullStream& stream() { return *this; }
+};
+
+template <typename T>
+inline NullStream& operator<<(NullStream& null_stream, const T&) {
+ return null_stream;
+}
+
+// std::endl compatibility
+inline NullStream& operator<<(NullStream& null_stream,
+ std::ostream& (*)(std::ostream&)) {
+ return null_stream;
+}
// Captures the result of a CHECK_EQ (for example) and facilitates testing as a
// boolean.
@@ -483,7 +481,9 @@ class CheckOpResult {
// calling an out-of-line function instead of a noreturn inline macro prevents
// compiler optimizations.
#define CHECK(condition) \
- UNLIKELY(!(condition)) ? IMMEDIATE_CRASH() : EAT_STREAM_PARAMETERS
+ UNLIKELY(!(condition)) \
+ ? IMMEDIATE_CRASH() \
+ : ::logging::LogMessageVoidify() & ::logging::NullStream().stream()
#define PCHECK(condition) CHECK(condition)
@@ -664,11 +664,11 @@ DEFINE_CHECK_OP_IMPL(GT, > )
// Contrast this with DCHECK et al., which has different behavior.
#define DLOG_IS_ON(severity) false
-#define DLOG_IF(severity, condition) EAT_STREAM_PARAMETERS
-#define DLOG_ASSERT(condition) EAT_STREAM_PARAMETERS
-#define DPLOG_IF(severity, condition) EAT_STREAM_PARAMETERS
-#define DVLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
-#define DVPLOG_IF(verboselevel, condition) EAT_STREAM_PARAMETERS
+#define DLOG_IF(severity, condition) ::logging::NullStream().stream()
+#define DLOG_ASSERT(condition) ::logging::NullStream().stream()
+#define DPLOG_IF(severity, condition) ::logging::NullStream().stream()
+#define DVLOG_IF(verboselevel, condition) ::logging::NullStream().stream()
+#define DVPLOG_IF(verboselevel, condition) ::logging::NullStream().stream()
#endif // DCHECK_IS_ON()
@@ -679,6 +679,8 @@ DEFINE_CHECK_OP_IMPL(GT, > )
// For compile-time checks, #if DCHECK_IS_ON() can be used.
enum { DEBUG_MODE = DCHECK_IS_ON() };
+#if DCHECK_IS_ON()
+
#define DLOG(severity) \
LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity))
@@ -689,24 +691,16 @@ enum { DEBUG_MODE = DCHECK_IS_ON() };
#define DVPLOG(verboselevel) DVPLOG_IF(verboselevel, VLOG_IS_ON(verboselevel))
-// Definitions for DCHECK et al.
-
-#if DCHECK_IS_ON()
-
-#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
- COMPACT_GOOGLE_LOG_EX_FATAL(ClassName , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_FATAL
-const LogSeverity LOG_DCHECK = LOG_FATAL;
-
#else // DCHECK_IS_ON()
-// These are just dummy values.
-#define COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
- COMPACT_GOOGLE_LOG_EX_INFO(ClassName , ##__VA_ARGS__)
-#define COMPACT_GOOGLE_LOG_DCHECK COMPACT_GOOGLE_LOG_INFO
-const LogSeverity LOG_DCHECK = LOG_INFO;
+#define DLOG(severity) ::logging::NullStream().stream()
+#define DPLOG(severity) ::logging::NullStream().stream()
+#define DVLOG(verboselevel) ::logging::NullStream().stream()
+#define DVPLOG(verboselevel) ::logging::NullStream().stream()
-#endif // DCHECK_IS_ON()
+#endif
+
+// Definitions for DCHECK et al.
// DCHECK et al. make sure to reference |condition| regardless of
// whether DCHECKs are enabled; this is so that we don't get unused
@@ -715,7 +709,9 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
//
// 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.
+// NullStream() to reduce the number of expressions that create temporaries,
+// since the MSVC optimizer has trouble optimizing those temporaries away
+// completely.
#if defined(_PREFAST_) && defined(OS_WIN)
// See comments on the previous use of __analysis_assume.
@@ -743,8 +739,10 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
#else // DCHECK_IS_ON()
-#define DCHECK(condition) EAT_STREAM_PARAMETERS << !(condition)
-#define DPCHECK(condition) EAT_STREAM_PARAMETERS << !(condition)
+#define DCHECK(condition) \
+ LAZY_STREAM(::logging::NullStream().stream(), !(condition))
+#define DPCHECK(condition) \
+ LAZY_STREAM(::logging::NullStream().stream(), !(condition))
#endif // DCHECK_IS_ON()
@@ -771,20 +769,8 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
#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))
+#define DCHECK_OP(name, op, val1, val2) \
+ LAZY_STREAM(::logging::NullStream().stream(), !((val1)op(val2)))
#endif // DCHECK_IS_ON()
@@ -821,7 +807,7 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
void LogErrorNotReached(const char* file, int line);
#define NOTREACHED() \
true ? ::logging::LogErrorNotReached(__FILE__, __LINE__) \
- : EAT_STREAM_PARAMETERS
+ : ::logging::LogMessageVoidify() & ::logging::NullStream()
#else
#define NOTREACHED() DCHECK(false)
#endif
@@ -900,10 +886,10 @@ class BASE_EXPORT LogMessage {
// is not used" and "statement has no effect".
class LogMessageVoidify {
public:
- LogMessageVoidify() { }
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(std::ostream&) { }
+ void operator&(NullStream&) {}
};
#if defined(OS_WIN)
@@ -1038,7 +1024,7 @@ inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
#endif
#if NOTIMPLEMENTED_POLICY == 0
-#define NOTIMPLEMENTED() EAT_STREAM_PARAMETERS
+#define NOTIMPLEMENTED() ::logging::NullStream().stream()
#elif NOTIMPLEMENTED_POLICY == 1
// TODO, figure out how to generate a warning
#define NOTIMPLEMENTED() static_assert(false, "NOT_IMPLEMENTED")
@@ -1049,12 +1035,13 @@ inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) {
#elif NOTIMPLEMENTED_POLICY == 4
#define NOTIMPLEMENTED() LOG(ERROR) << NOTIMPLEMENTED_MSG
#elif NOTIMPLEMENTED_POLICY == 5
-#define NOTIMPLEMENTED() do {\
- static bool logged_once = false;\
- LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG;\
- logged_once = true;\
-} while(0);\
-EAT_STREAM_PARAMETERS
+#define NOTIMPLEMENTED() \
+ do { \
+ static bool logged_once = false; \
+ LOG_IF(ERROR, !logged_once) << NOTIMPLEMENTED_MSG; \
+ logged_once = true; \
+ } while (0); \
+ ::logging::NullStream().stream()
#endif
#endif // BASE_LOGGING_H_
« no previous file with comments | « no previous file | base/time/time.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698