Add "WITH_STATIC_ANALYZER=1 m/mm/mmm/mma/mmma ..."

The new option WITH_STATIC_ANALYZER=1 instructs build system to
run static analyzer via "clang --analyze" on a successful build.
If analyzer finds any issue, instruction to open report is displayed.
See http://clang-analyzer.llvm.org/scan-build.html for details.

WITH_STATIC_ANALYZER trumps WITH_SYNTAX_CHECK if both exist.

Project use lots of GCC extensions (eg. nested function) not supported
by clang may opt out by adding LOCAL_NO_STATIC_ANALYZER:=true

Change-Id: I9970560560bd52ce5f0fd7129c3488629627c735
diff --git a/core/binary.mk b/core/binary.mk
index 75f6ede..f40c444 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -174,6 +174,10 @@
   LOCAL_NO_SYNTAX_CHECK := true
 endif
 
+ifeq ($(strip $(WITH_STATIC_ANALYZER)),)
+  LOCAL_NO_STATIC_ANALYZER := true
+endif
+
 ifneq ($(strip $(LOCAL_IS_HOST_MODULE)),)
   my_syntax_arch := host
 else
@@ -187,9 +191,13 @@
     LOCAL_CC := $($(my_prefix)CC)
   endif
 endif
+ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
+  LOCAL_CC := $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer $(my_syntax_arch) "$(LOCAL_CC)"
+else
 ifneq ($(LOCAL_NO_SYNTAX_CHECK),true)
   LOCAL_CC := $(SYNTAX_TOOLS_PREFIX)/ccc-syntax $(my_syntax_arch) "$(LOCAL_CC)"
 endif
+endif
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CC := $(LOCAL_CC)
 
 ifeq ($(strip $(LOCAL_CXX)),)
@@ -199,9 +207,13 @@
     LOCAL_CXX := $($(my_prefix)CXX)
   endif
 endif
+ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
+  LOCAL_CXX := $(SYNTAX_TOOLS_PREFIX)/cxx-analyzer $(my_syntax_arch) "$(LOCAL_CXX)"
+else
 ifneq ($(LOCAL_NO_SYNTAX_CHECK),true)
   LOCAL_CXX := $(SYNTAX_TOOLS_PREFIX)/cxx-syntax $(my_syntax_arch) "$(LOCAL_CXX)"
 endif
+endif
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_CXX := $(LOCAL_CXX)
 
 # TODO: support a mix of standard extensions so that this isn't necessary
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 9b8bf40..7530ea8 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -138,6 +138,7 @@
 LOCAL_POST_INSTALL_CMD:=
 LOCAL_DIST_BUNDLED_BINARIES:=
 LOCAL_NO_SYNTAX_CHECK:=
+LOCAL_NO_STATIC_ANALYZER:=
 
 # Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to
 # iterate over thousands of entries every time.
diff --git a/core/config.mk b/core/config.mk
index 0153109..2a84b34 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -247,8 +247,22 @@
 TARGET_TOOLCHAIN_ROOT := $(wildcard $(TARGET_TOOLCHAIN_ROOT))
 endif
 
-# Disable WITH_SYNTAX_CHECK if tool can't be found
+# Normalize WITH_STATIC_ANALYZER and WITH_SYNTAX_CHECK
+ifeq ($(strip $(WITH_STATIC_ANALYZER)),0)
+  WITH_STATIC_ANALYZER :=
+endif
+ifeq ($(strip $(WITH_SYNTAX_CHECK)),0)
+  WITH_SYNTAX_CHECK :=
+endif
+
+# Disable WITH_STATIC_ANALYZER and WITH_SYNTAX_CHECK if tool can't be found
 SYNTAX_TOOLS_PREFIX := prebuilts/clang/$(HOST_PREBUILT_TAG)/host/3.3/bin
+ifneq ($(strip $(WITH_STATIC_ANALYZER)),)
+  ifeq ($(wildcard $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer),)
+    $(warning *** Disable WITH_STATIC_ANALYZER because $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer does not exist)
+    WITH_STATIC_ANALYZER :=
+  endif
+endif
 ifneq ($(strip $(WITH_SYNTAX_CHECK)),)
   ifeq ($(wildcard $(SYNTAX_TOOLS_PREFIX)/ccc-syntax),)
     $(warning *** Disable WITH_SYNTAX_CHECK because $(SYNTAX_TOOLS_PREFIX)/ccc-syntax does not exist)
@@ -256,6 +270,14 @@
   endif
 endif
 
+# WITH_STATIC_ANALYZER trumps WITH_SYNTAX_CHECK
+ifneq ($(strip $(WITH_STATIC_ANALYZER)),)
+  ifneq ($(strip $(WITH_SYNTAX_CHECK)),)
+    $(warning *** Disable WITH_SYNTAX_CHECK in the presence of static analyzer WITH_STATIC_ANALYZER)
+    WITH_SYNTAX_CHECK :=
+  endif
+endif
+
 # Pick a Java compiler.
 include $(BUILD_SYSTEM)/combo/javac.mk