Add hints for static analysis about when we intend to crash
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 23 Nov 2011 21:25:35 +0000 (21:25 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 23 Nov 2011 21:25:35 +0000 (21:25 +0000)
Review URL: http://codereview.appspot.com/5433062

git-svn-id: http://skia.googlecode.com/svn/trunk@2745 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkPostConfig.h
include/gpu/GrConfig.h

index 0135b85f9e3156f861ce9c06bbe320d5c9d528b3..51a629f2a64769f927457033a85c74f7e753cc89 100644 (file)
     #endif
 #endif
 
+#if !defined(SK_HAS_COMPILER_FEATURE)
+    #if defined(__has_feature)
+        #define SK_HAS_COMPILER_FEATURE(x) __has_feature(x)
+    #else
+        #define SK_HAS_COMPILER_FEATURE(x) 0
+    #endif
+#endif
+
+/**
+ * The clang static analyzer likes to know that when the program is not
+ * expected to continue (crash, assertion failure, etc). It will notice that
+ * some combination of parameters lead to a function call that does not return.
+ * It can then make appropriate assumptions about the parameters in code
+ * executed only if the non-returning function was *not* called.
+ */
+#if !defined(SkNO_RETURN_HINT)
+    #if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn)
+        namespace {
+            inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn));
+            void SkNO_RETURN_HINT() {}
+        }
+    #else
+        #define SkNO_RETURN_HINT() do {} while (false)
+    #endif
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifndef SkNEW
@@ -68,9 +94,9 @@
 
 #ifndef SK_CRASH
 #if 1   // set to 0 for infinite loop, which can help connecting gdb
-    #define SK_CRASH() *(int *)(uintptr_t)0xbbadbeef = 0
+    #define SK_CRASH() SkNO_RETURN_HINT(); *(int *)(uintptr_t)0xbbadbeef = 0
 #else
-    #define SK_CRASH()  do {} while (true)
+    #define SK_CRASH() SkNO_RETURN_HINT(); do {} while (true)
 #endif
 #endif
 
     #endif
 
     #ifndef SK_DEBUGBREAK
-        #define SK_DEBUGBREAK(cond)     do { if (!(cond)) __debugbreak(); } while (false)
+        #define SK_DEBUGBREAK(cond)     do { if (!(cond)) { SkNO_RETURN_HINT(); __debugbreak(); }} while (false)
     #endif
 
     #ifndef SK_A32_SHIFT
index d6037f4f9781e2194ea796205be3a66a3fada80a..72b9748a47745e43b30085bc8148bd8326a6058b 100644 (file)
@@ -220,12 +220,12 @@ extern GR_API void GrPrintf(const char format[], ...);
  */
 #if !defined(GR_ALWAYSBREAK)
     #if     GR_WIN32_BUILD
-        #define GR_ALWAYSBREAK __debugbreak()
+        #define GR_ALWAYSBREAK SkNO_RETURN_HINT(); __debugbreak()
     #else
         // TODO: do other platforms really not have continuable breakpoints?
         // sign extend for 64bit architectures to be sure this is
         // in the high address range
-        #define GR_ALWAYSBREAK *((int*)(int64_t)(int32_t)0xbeefcafe) = 0;
+        #define GR_ALWAYSBREAK SkNO_RETURN_HINT(); *((int*)(int64_t)(int32_t)0xbeefcafe) = 0;
     #endif
 #endif