Chromium Code Reviews| Index: base/logging.h |
| diff --git a/base/logging.h b/base/logging.h |
| index 5174e6d375540cd0f0bf355034c17812a66bf37b..c7e2f8e6388576b88038ef3a8d88c1d5bd6c7233 100644 |
| --- a/base/logging.h |
| +++ b/base/logging.h |
| @@ -289,6 +289,33 @@ typedef bool (*LogMessageHandlerFunction)(int severity, |
| BASE_EXPORT void SetLogMessageHandler(LogMessageHandlerFunction handler); |
| BASE_EXPORT LogMessageHandlerFunction GetLogMessageHandler(); |
| +// ANALYZER_ASSUME_TRUE(...) generates compiler-specific annotations which |
| +// prevent the static analyzer from analyzing the code using hypothetical |
| +// values that are asserted to be impossible. |
| +#if defined(__clang_analyzer__) |
| + |
| +inline void AnalyzerNoReturn() __attribute__((analyzer_noreturn)) {} |
| + |
| +template <typename TVal> |
| +inline constexpr TVal&& AnalysisAssumeTrue(TVal&& arg) { |
| + if (!arg) { |
| + AnalyzerNoReturn(); |
| + } |
| + return std::forward<TVal>(arg); |
| +} |
| + |
| +#define ANALYZER_ASSUME_TRUE(val) ::logging::AnalysisAssumeTrue(val) |
| + |
| +#elif defined(_PREFAST_) && defined(OS_WIN) |
| + |
| +#define ANALYZER_ASSUME_TRUE(val) __analysis_assume(!!(val)) |
| + |
| +#else // !_PREFAST_ & !__clang_analyzer__ |
| + |
| +#define ANALYZER_ASSUME_TRUE(val) (val) |
| + |
| +#endif // !_PREFAST_ & !__clang_analyzer__ |
| + |
| typedef int LogSeverity; |
| const LogSeverity LOG_VERBOSE = -1; // This is level 1 verbosity |
| // Note: the log severities are used to index into the array of names, |
| @@ -408,8 +435,9 @@ const LogSeverity LOG_0 = LOG_ERROR; |
| // TODO(akalin): Add more VLOG variants, e.g. VPLOG. |
| -#define LOG_ASSERT(condition) \ |
| - LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " |
| +#define LOG_ASSERT(condition) \ |
| + LOG_IF(FATAL, !ANALYZER_ASSUME_TRUE(condition)) \ |
| + << "Assert failed: " #condition ". " |
| #if defined(OS_WIN) |
| #define PLOG_STREAM(severity) \ |
| @@ -492,33 +520,29 @@ class CheckOpResult { |
| #else // !(OFFICIAL_BUILD && NDEBUG) |
| #if defined(_PREFAST_) && defined(OS_WIN) |
| -// Use __analysis_assume to tell the VC++ static analysis engine that |
| -// assert conditions are true, to suppress warnings. The LAZY_STREAM |
| -// parameter doesn't reference 'condition' in /analyze builds because |
| -// this evaluation confuses /analyze. The !! before condition is because |
| +// The LAZY_STREAM parameter doesn't reference 'condition' in /analyze builds |
| +// because this evaluation confuses /analyze. The !! before condition is because |
| // __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) \ |
| + ANALYZER_ASSUME_TRUE(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) \ |
| + ANALYZER_ASSUME_TRUE(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(), \ |
| - !(condition)) |
| + !ANALYZER_ASSUME_TRUE(condition)) |
| -#define PCHECK(condition) \ |
| - LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \ |
| - << "Check failed: " #condition ". " |
| +#define PCHECK(condition) \ |
| + LAZY_STREAM(PLOG_STREAM(FATAL), !ANALYZER_ASSUME_TRUE(condition)) \ |
| + << "Check failed: " #condition ". " |
| #endif // _PREFAST_ |
| @@ -720,51 +744,33 @@ const LogSeverity LOG_DCHECK = LOG_INFO; |
| #if defined(_PREFAST_) && defined(OS_WIN) |
| // See comments on the previous use of __analysis_assume. |
|
Wez
2017/02/06 21:04:39
See comment above; do we need this if we have a "s
Kevin M
2017/02/09 23:36:25
Done.
Wez
2017/02/10 00:40:45
Woohoo, that looks great. Hopefully it doesn't tri
|
| -#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 DCHECK(condition) \ |
| + ANALYZER_ASSUME_TRUE(condition) \ |
| + , LAZY_STREAM(LOG_STREAM(DCHECK), false) << "Check failed: " #condition ". " |
| -#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() ? (logging::AnalyzerNoReturn() || !(condition)) : false) \ |
| - << "Check failed: " #condition ". " |
| - |
| -#define DPCHECK(condition) \ |
| - LAZY_STREAM( \ |
| - PLOG_STREAM(DCHECK), \ |
| - DCHECK_IS_ON() ? (logging::AnalyzerNoReturn() || !(condition)) : false) \ |
| - << "Check failed: " #condition ". " |
| +#define DPCHECK(condition) \ |
| + ANALYZER_ASSUME_TRUE(condition) \ |
| + , LAZY_STREAM(PLOG_STREAM(DCHECK), false) << "Check failed: " #condition \ |
| + "." \ |
| + " " |
| #else |
| #if DCHECK_IS_ON() |
| -#define DCHECK(condition) \ |
| - LAZY_STREAM(LOG_STREAM(DCHECK), !(condition)) \ |
| +#define DCHECK(condition) \ |
| + LAZY_STREAM(LOG_STREAM(DCHECK), !ANALYZER_ASSUME_TRUE(condition)) \ |
| << "Check failed: " #condition ". " |
| -#define DPCHECK(condition) \ |
| - LAZY_STREAM(PLOG_STREAM(DCHECK), !(condition)) \ |
| +#define DPCHECK(condition) \ |
| + LAZY_STREAM(PLOG_STREAM(DCHECK), !ANALYZER_ASSUME_TRUE(condition)) \ |
| << "Check failed: " #condition ". " |
| #else // DCHECK_IS_ON() |
| -#define DCHECK(condition) EAT_STREAM_PARAMETERS << !(condition) |
| -#define DPCHECK(condition) EAT_STREAM_PARAMETERS << !(condition) |
| +#define DCHECK(condition) \ |
| + EAT_STREAM_PARAMETERS << !ANALYZER_ASSUME_TRUE(condition) |
| +#define DPCHECK(condition) \ |
| + EAT_STREAM_PARAMETERS << !ANALYZER_ASSUME_TRUE(condition) |
| #endif // DCHECK_IS_ON() |
| @@ -804,7 +810,7 @@ inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) { |
| ::logging::g_swallow_stream, val1), \ |
| ::logging::MakeCheckOpValueString( \ |
| ::logging::g_swallow_stream, val2), \ |
| - (val1)op(val2)) |
| + ANALYZER_ASSUME_TRUE((val1)op(val2))) |
| #endif // DCHECK_IS_ON() |
| @@ -993,7 +999,7 @@ BASE_EXPORT void RawLog(int level, const char* message); |
| #define RAW_CHECK(condition) \ |
| do { \ |
| - if (!(condition)) \ |
| + if (!ANALYZER_ASSUME_TRUE(condition)) \ |
| ::logging::RawLog(::logging::LOG_FATAL, \ |
| "Check failed: " #condition "\n"); \ |
| } while (0) |