Add __analysis_assume support to CHECK macros to reduce warnings with /analyze.

Due to bugs and quirks in the analysis engine this is a very delicate dance.

The __analysis_assume invocation has to evaluate !!(condition) instead
of just condition because otherwise it fails on overloaded operators
such as with smart pointers. See this post for details:
http://randomascii.wordpress.com/2011/09/13/analyze-for-visual-studio-the-ugly-part-5/

The evaluation of condition in the 'regular' part of the macro has to
be removed during the /analyze phase in order to avoid confusing the
analysis engine which thinks that branching on the condition implies
uncertainty about the condition.

None of this is documented -- thinking like a compiler is required.

Wrapping this with #ifdef _PREFAST_ makes it easy to guarantee that this
will not affect regular builds.

To build add  win_debug_extra_cflags="/analyze"  to GYP_DEFINES, rebuild
the project files and then build.

Review URL: https://codereview.chromium.org/674643002

Cr-Commit-Position: refs/heads/master@{#300937}


CrOS-Libchrome-Original-Commit: 9d1602515adc3e797d71c3a0e29cc175432eb8fe
diff --git a/base/logging.h b/base/logging.h
index 88d5eff..54ff579 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -450,14 +450,36 @@
 
 #else
 
+#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
+// __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 PCHECK(condition)                \
+  __analysis_assume(!!(condition)),      \
+  LAZY_STREAM(PLOG_STREAM(FATAL), false) \
+  << "Check failed: " #condition ". "
+
+#else  // _PREFAST_
+
 #define CHECK(condition)                       \
   LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \
   << "Check failed: " #condition ". "
 
-#define PCHECK(condition) \
+#define PCHECK(condition)                       \
   LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
   << "Check failed: " #condition ". "
 
+#endif  // _PREFAST_
+
 // Helper macro for binary operators.
 // Don't use this macro directly in your code, use CHECK_EQ et al below.
 //
@@ -616,6 +638,21 @@
 // variable warnings if the only use of a variable is in a DCHECK.
 // This behavior is different from DLOG_IF et al.
 
+#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 DPCHECK(condition)                                              \
+  __analysis_assume(!!(condition)),                                     \
+  LAZY_STREAM(PLOG_STREAM(DCHECK), false)                               \
+  << "Check failed: " #condition ". "
+
+#else  // _PREFAST_
+
 #define DCHECK(condition)                                               \
   LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON ? !(condition) : false)  \
   << "Check failed: " #condition ". "
@@ -624,6 +661,8 @@
   LAZY_STREAM(PLOG_STREAM(DCHECK), DCHECK_IS_ON ? !(condition) : false) \
   << "Check failed: " #condition ". "
 
+#endif  // _PREFAST_
+
 // Helper macro for binary operators.
 // Don't use this macro directly in your code, use DCHECK_EQ et al below.
 #define DCHECK_OP(name, op, val1, val2)                         \