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

Unified Diff: base/logging.h

Issue 2729503004: Add Clang static analysis control to all assert functions in logging.h (Closed)
Patch Set: Move ANALYSIS_ASSUME_TRUE into body of CheckXYZImpl Created 3 years, 9 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 | no next file » | 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 c67b937e5b08607736e860dd349f1de6204c6a5b..f76cfdf8ed0223125f01d8f56469de57c1fd900b 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -289,6 +289,39 @@ typedef bool (*LogMessageHandlerFunction)(int severity,
BASE_EXPORT void SetLogMessageHandler(LogMessageHandlerFunction handler);
BASE_EXPORT LogMessageHandlerFunction GetLogMessageHandler();
+// ANALYZER_ASSUME_TRUE(bool arg) generates compiler-specific annotations which
+// prevent the static analyzer from analyzing the code using hypothetical
+// values that are asserted to be impossible. It returns the truth value of
+// |arg| as a bool.
+//
+// If |arg| is true, ANALYZER_ASSUME_TRUE has no effect and static analysis
+// may proceed with analysis along the current path.
+//
+// If |arg| is false, static analysis is terminated and no further analysis
+// errors will be generated for the current path.
brucedawson 2017/03/16 20:15:40 This doesn't fit my mental model for how /analyze
Kevin M 2017/03/16 23:08:13 Interesting. In the Clang case, noreturn is used f
+#if defined(__clang_analyzer__)
+
+inline void AnalyzerNoReturn() __attribute__((analyzer_noreturn)) {}
+
+inline constexpr bool AnalyzerAssumeTrue(bool arg) {
+ if (!arg) {
+ AnalyzerNoReturn();
+ }
+ return arg;
+}
+
+#define ANALYZER_ASSUME_TRUE(arg) ::logging::AnalyzerAssumeTrue(!!(arg))
+
+#elif defined(_PREFAST_) && defined(OS_WIN)
+
+#define ANALYZER_ASSUME_TRUE(arg) (__analysis_assume(!!(arg)), !!(arg))
brucedawson 2017/03/16 20:15:40 The second !! is not needed.
Kevin M 2017/03/16 23:08:13 It makes the expression value consistent with the
+
+#else // _PREFAST_ & OS_WIN
+
+#define ANALYZER_ASSUME_TRUE(arg) !!(arg)
brucedawson 2017/03/16 20:15:40 The !! should not be needed, should it? It is need
Kevin M 2017/03/16 23:08:13 See above..
+
+#endif // !__clang_analyzer && !_PREFAST_
+
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,
@@ -562,37 +595,15 @@ 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
-// __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_
-
// 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)) \
+#define PCHECK(condition) \
+ LAZY_STREAM(PLOG_STREAM(FATAL), !ANALYZER_ASSUME_TRUE(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.
// The 'switch' is used to prevent the 'else' from being ambiguous when the
@@ -685,17 +696,21 @@ 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.
+//
+// The checked condition is wrapped with ANALYZER_ASSUME_TRUE, which under
+// static analysis builds, blocks analysis of the current path if the
+// condition is false.
#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) \
+ if (ANALYZER_ASSUME_TRUE(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) \
+ if (ANALYZER_ASSUME_TRUE(v1 op v2)) \
return NULL; \
else \
return ::logging::MakeCheckOpString(v1, v2, names); \
@@ -792,48 +807,13 @@ const LogSeverity LOG_DCHECK = LOG_INFO;
// 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 DPCHECK(condition) \
- __analysis_assume(!!(condition)), \
- LAZY_STREAM(PLOG_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 ". "
-
-#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()
@@ -843,8 +823,6 @@ inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) {
#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.
// The 'switch' is used to prevent the 'else' from being ambiguous when the
@@ -879,7 +857,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()
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698