Bug 767563 - Add a clang static checker, part 1: add the plugin shell. r=glandium
authorJoshua Cranmer <Pidgeot18@gmail.com>
Sat, 23 Mar 2013 21:12:25 -0500
changeset 137257 cf75954e488fa602bf19de0b44a710066d0a5c5d
parent 137256 0ed97a9289b6f331be3658a30c2f315fe2d5f529
child 137258 9dfc8698edd08ea77c193b4ffe69ec8421983559
push id336
push userakeybl@mozilla.com
push dateMon, 17 Jun 2013 22:53:19 +0000
treeherdermozilla-release@574a39cdf657 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs767563
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 767563 - Add a clang static checker, part 1: add the plugin shell. r=glandium
build/clang-plugin/Makefile.in
build/clang-plugin/clang-plugin.cpp
build/clang-plugin/configure
config/static-checking-config.mk
configure.in
js/src/config/static-checking-config.mk
js/src/configure.in
moz.build
new file mode 100644
--- /dev/null
+++ b/build/clang-plugin/Makefile.in
@@ -0,0 +1,39 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CXX      := @CXX@
+CXXFLAGS := @CXXFLAGS@
+LDFLAGS  := @LDFLAGS@
+VPATH		 := @srcdir@
+
+# Helper for end
+NULL :=
+
+CPPSRCS := \
+	clang-plugin.cpp \
+	$(NULL)
+
+TESTSRCS := \
+	$(NULL)
+
+OBJS := $(patsubst %.cpp,%.o,$(CPPSRCS))
+TESTS := $(patsubst %.cpp,test-%,$(TESTSRCS))
+
+PLUGIN := libclang-plugin.so
+
+all: $(PLUGIN) $(TESTS)
+
+$(OBJS): %.o: %.cpp Makefile
+	$(CXX) -o $@ -c $(CXXFLAGS) $<
+
+$(PLUGIN): $(OBJS)
+	rm -f $@
+	$(CXX) -shared -o $@ $(CXXFLAGS) $(LDFLAGS) $(OBJS)
+
+TESTFLAGS := -fsyntax-only -Xclang -verify \
+	-Xclang -load -Xclang $(CURDIR)/$(PLUGIN) \
+	-Xclang -add-plugin -Xclang moz-check
+
+$(TESTS): test-%: tests/%.cpp $(PLUGIN)
+	$(CXX) $(TESTFLAGS) $<
new file mode 100644
--- /dev/null
+++ b/build/clang-plugin/clang-plugin.cpp
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Sema/Sema.h"
+
+#define CLANG_VERSION_FULL (CLANG_VERSION_MAJOR * 100 + CLANG_VERSION_MINOR)
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
+  DiagnosticsEngine &Diag;
+  const CompilerInstance &CI;
+public:
+  MozChecker(const CompilerInstance &CI) : Diag(CI.getDiagnostics()), CI(CI) {}
+  virtual void HandleTranslationUnit(ASTContext &ctx) {
+    TraverseDecl(ctx.getTranslationUnitDecl());
+  }
+};
+
+class MozCheckAction : public PluginASTAction {
+public:
+  ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef fileName) {
+    return new MozChecker(CI);
+  }
+
+  bool ParseArgs(const CompilerInstance &CI,
+                 const std::vector<std::string> &args) {
+    return true;
+  }
+};
+}
+
+static FrontendPluginRegistry::Add<MozCheckAction>
+X("moz-check", "check moz action");
new file mode 100755
--- /dev/null
+++ b/build/clang-plugin/configure
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+# Default srcdir to this directory
+srcdir=
+
+for option; do
+  case "$option" in
+  -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) optarg= ;;
+  esac
+
+  case "$option" in
+  --srcdir=*) srcdir="$optarg";;
+  esac
+done
+
+if test -z "$CXX"; then
+  CXX=`which clang++`
+fi
+
+echo -n "checking for llvm-config... "
+
+if test -z "$LLVMCONFIG"; then
+  LLVMCONFIG=`which llvm-config`
+fi
+
+if test -z "$LLVMCONFIG"; then
+  LLVMCONFIG=`dirname $CXX`/llvm-config
+fi
+
+if test ! -x "$LLVMCONFIG"; then
+  echo "configure: error: Cannot find an llvm-config binary for building a clang plugin" 1>&2
+  exit 1
+fi
+
+echo "$LLVMCONFIG"
+
+LLVMCXXFLAGS=`$LLVMCONFIG --cxxflags`
+LLVMLDFLAGS=`$LLVMCONFIG --ldflags`
+CXXFLAGS="$CXXFLAGS $LLVMCXXFLAGS -fno-rtti -fno-exceptions"
+LDFLAGS="$LDFLAGS $LLVMLDFLAGS"
+
+cat $srcdir/Makefile.in | sed \
+  -e "s%@CXX@%$CXX%" \
+  -e "s%@CXXFLAGS@%$CXXFLAGS%" \
+  -e "s%@LDFLAGS@%$LDFLAGS%" \
+  -e "s%@srcdir@%$srcdir%" \
+  > Makefile
--- a/config/static-checking-config.mk
+++ b/config/static-checking-config.mk
@@ -31,8 +31,14 @@ DEHYDRA_ARGS = \
   $(DEHYDRA_ARG_PREFIX)treehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(TREEHYDRA_MODULES))) \
   $(NULL)
 
 DEHYDRA_FLAGS = -fplugin=$(DEHYDRA_PATH) $(DEHYDRA_ARGS)
 
 ifdef DEHYDRA_PATH
 OS_CXXFLAGS += $(DEHYDRA_FLAGS)
 endif
+
+ifdef ENABLE_CLANG_PLUGIN
+CLANG_PLUGIN := $(DEPTH)/build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
+OS_CXXFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
+OS_CFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
+endif
--- a/configure.in
+++ b/configure.in
@@ -7460,16 +7460,33 @@ if test -n "$DEHYDRA_PATH"; then
     if test ! -f "$DEHYDRA_PATH"; then
         AC_MSG_ERROR([The dehydra plugin is not at the specified path.])
     fi
     AC_DEFINE(NS_STATIC_CHECKING)
 fi
 AC_SUBST(DEHYDRA_PATH)
 
 dnl ========================================================
+dnl = Enable using the clang plugin to build
+dnl ========================================================
+
+MOZ_ARG_ENABLE_BOOL(clang-plugin,
+[  --enable-clang-plugin   Enable building with the mozilla clang plugin ],
+   ENABLE_CLANG_PLUGIN=1,
+   ENABLE_CLANG_PLUGIN= )
+if test -n "$ENABLE_CLANG_PLUGIN"; then
+    if test -z "$CLANG_CC"; then
+        AC_MSG_ERROR([Can't use clang plugin without clang.])
+    fi
+    AC_DEFINE(MOZ_CLANG_PLUGIN)
+fi
+
+AC_SUBST(ENABLE_CLANG_PLUGIN)
+
+dnl ========================================================
 dnl = Enable stripping of libs & executables
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(strip,
 [  --enable-strip          Enable stripping of libs & executables ],
     ENABLE_STRIP=1,
     ENABLE_STRIP= )
 
 dnl ========================================================
@@ -9383,16 +9400,22 @@ CFLAGS="$_SUBDIR_CFLAGS"
 CPPFLAGS="$_SUBDIR_CPPFLAGS"
 CXXFLAGS="$_SUBDIR_CXXFLAGS"
 LDFLAGS="$_SUBDIR_LDFLAGS"
 HOST_CC="$_SUBDIR_HOST_CC"
 HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS"
 HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS"
 RC=
 
+if test -n "$ENABLE_CLANG_PLUGIN"; then
+    ac_configure_args="$_SUBDIR_CONFIG_ARGS"
+    AC_OUTPUT_SUBDIRS(build/clang-plugin)
+fi
+
+
 # Run the SpiderMonkey 'configure' script.
 dist=$MOZ_BUILD_ROOT/dist
 ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 ac_configure_args="$ac_configure_args --enable-threadsafe"
 if test "$BUILD_CTYPES"; then
     # Build js-ctypes on the platforms we can.
     ac_configure_args="$ac_configure_args --enable-ctypes"
 fi
--- a/js/src/config/static-checking-config.mk
+++ b/js/src/config/static-checking-config.mk
@@ -21,8 +21,16 @@ DEHYDRA_ARGS = \
   $(DEHYDRA_ARG_PREFIX)treehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(TREEHYDRA_MODULES))) \
   $(NULL)
 
 DEHYDRA_FLAGS = -fplugin=$(DEHYDRA_PATH) $(DEHYDRA_ARGS)
 
 ifdef DEHYDRA_PATH
 OS_CXXFLAGS += $(DEHYDRA_FLAGS)
 endif
+
+ifdef ENABLE_CLANG_PLUGIN
+# Load the clang plugin from the mozilla topsrcdir. This implies that the clang
+# plugin is only usable if we're building js/src under mozilla/, though.
+CLANG_PLUGIN := $(DEPTH)/../../build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
+OS_CXXFLAGS += -fplugin=$(CLANG_PLUGIN)
+OS_CFLAGS += -fplugin=$(CLANG_PLUGIN)
+endif
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -3747,16 +3747,33 @@ if test -n "$DEHYDRA_PATH"; then
     if test ! -f "$DEHYDRA_PATH"; then
         AC_MSG_ERROR([The dehydra plugin is not at the specified path.])
     fi
     AC_DEFINE(NS_STATIC_CHECKING)
 fi
 AC_SUBST(DEHYDRA_PATH)
 
 dnl ========================================================
+dnl = Enable using the clang plugin to build
+dnl ========================================================
+
+MOZ_ARG_ENABLE_BOOL(clang-plugin,
+[  --enable-clang-plugin   Enable building with the mozilla clang plugin ],
+   ENABLE_CLANG_PLUGIN=1,
+   ENABLE_CLANG_PLUGIN= )
+if test -n "$ENABLE_CLANG_PLUGIN"; then
+    if test -z "$CLANG_CC"; then
+        AC_MSG_ERROR([Can't use clang plugin without clang.])
+    fi
+    AC_DEFINE(MOZ_CLANG_PLUGIN)
+fi
+
+AC_SUBST(ENABLE_CLANG_PLUGIN)
+
+dnl ========================================================
 dnl = Enable static checking using sixgill
 dnl ========================================================
 
 MOZ_ARG_WITH_STRING(sixgill,
 [  --with-sixgill=path/to/sixgill
                           Enable static checking of code using sixgill],
     SIXGILL_PATH=$withval,
     SIXGILL_PATH= )
--- a/moz.build
+++ b/moz.build
@@ -1,15 +1,18 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 CONFIGURE_SUBST_FILES += ['tools/update-packaging/Makefile']
 
+if CONFIG['ENABLE_CLANG_PLUGIN']:
+  add_tier_dir('base', 'build/clang-plugin', static=True)
+
 add_tier_dir('base', ['config', 'build', 'probes', 'mfbt', 'python'])
 
 if not CONFIG['LIBXUL_SDK']:
     if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
         add_tier_dir('base', ['other-licenses/android'])
 
     if CONFIG['MOZ_MEMORY']:
         add_tier_dir('base', ['memory'])