Bug 437647 - Dispatch outparams and other analyses explicitly, so it's easier to add various analyses, r=dmandelin
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 06 Jun 2008 15:31:11 -0400
changeset 15276 5cd633865e6d26a18595e549993ccc629634ca08
parent 15275 851965dfe20d4872dd0fb91c6e097868bbf083c9
child 15277 d4910bfb3faba5aaa018b0641000446829436ee0
push idunknown
push userunknown
push dateunknown
reviewersdmandelin
bugs437647
milestone1.9.1a1pre
Bug 437647 - Dispatch outparams and other analyses explicitly, so it's easier to add various analyses, r=dmandelin
config/config.mk
xpcom/analysis/stack.js
xpcom/analysis/static-checking.js
--- a/config/config.mk
+++ b/config/config.mk
@@ -57,16 +57,18 @@ ifndef INCLUDED_AUTOCONF_MK
 include $(DEPTH)/config/autoconf.mk
 endif
 ifndef INCLUDED_INSURE_MK
 ifdef MOZ_INSURIFYING
 include $(topsrcdir)/config/insure.mk
 endif
 endif
 
+COMMA = ,
+
 # Sanity check some variables
 CHECK_VARS := \
  XPI_NAME \
  LIBRARY_NAME \
  MODULE \
  DEPTH \
  SHORT_LIBNAME \
  XPI_PKGNAME \
@@ -517,20 +519,36 @@ INCLUDES	= $(LOCAL_INCLUDES) $(REQ_INCLU
 
 ifndef MOZILLA_INTERNAL_API
 INCLUDES	+= -I$(LIBXUL_DIST)/sdk/include
 endif
 
 # The entire tree should be subject to static analysis using the XPCOM
 # script. Additional scripts may be added by specific subdirectories.
 
-DEHYDRA_SCRIPTS = $(topsrcdir)/xpcom/analysis/static-checking.js
+DEHYDRA_SCRIPT = $(topsrcdir)/xpcom/analysis/static-checking.js
+
+DEHYDRA_MODULES = \
+  $(topsrcdir)/xpcom/analysis/stack.js \
+  $(NULL)
+
+TREEHYDRA_MODULES = \
+  $(topsrcdir)/xpcom/analysis/outparams.js \
+  $(NULL)
+
+DEHYDRA_ARGS = \
+  --topsrcdir=$(topsrcdir) \
+  --objdir=$(DEPTH) \
+  --dehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(DEHYDRA_MODULES))) \
+  --treehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(TREEHYDRA_MODULES))) \
+  $(NULL)
+
+DEHYDRA_FLAGS = -fplugin=$(DEHYDRA_PATH) -fplugin-arg="$(DEHYDRA_SCRIPT) $(DEHYDRA_ARGS)"
 
 ifdef DEHYDRA_PATH
-DEHYDRA_FLAGS = -fplugin=$(DEHYDRA_PATH) $(foreach script,$(DEHYDRA_SCRIPTS),-fplugin-arg=$(script))
 OS_CXXFLAGS += $(DEHYDRA_FLAGS)
 endif
 
 CFLAGS		= $(OS_CFLAGS)
 CXXFLAGS	= $(OS_CXXFLAGS)
 LDFLAGS		= $(OS_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
 
 # Allow each module to override the *default* optimization settings
new file mode 100644
--- /dev/null
+++ b/xpcom/analysis/stack.js
@@ -0,0 +1,26 @@
+function process_function(f, stmts)
+{
+  var stmt;
+  function getLocation()
+  {
+    if (stmt.loc)
+      return stmt.loc;
+
+    return f.loc;
+  }
+
+  function processVar(v)
+  {
+    if (v.isConstructor &&
+        v.fieldOf &&
+        get_class(v.memberOf, false).stack &&
+        v.fieldOf.type.isPointer) {
+      error(getLocation() + ": constructed object of type '" +
+            v.memberOf.name + "' not on the stack.");
+    }
+  }
+
+  for each (stmt in stmts) {
+    iter(processVar, stmt.statements);
+  }
+}
--- a/xpcom/analysis/static-checking.js
+++ b/xpcom/analysis/static-checking.js
@@ -5,20 +5,42 @@
 /**
  * Activate Treehydra outparams analysis if running in Treehydra.
  */
 
 function treehydra_enabled() {
   return this.hasOwnProperty('TREE_CODE');
 }
 
-if (treehydra_enabled()) {
-  include('outparams.js');
+include('unstable/getopt.js');
+[options, args] = getopt();
+
+// XXXbugfix: when you pass arguments to -fplugin-arg, include_path[0] is bad
+sys.include_path[0] = options.topsrcdir + "/xpcom/analysis";
+sys.include_path.push(options.topsrcdir);
+
+let modules = [];
+
+function LoadModules(modulelist)
+{
+  if (modulelist == "")
+    return;
+
+  let modulenames = modulelist.split(',');
+  for each (let modulename in modulenames) {
+    let module = { __proto__: this };
+    include(modulename, module);
+    modules.push(module);
+  }
 }
 
+LoadModules(options['dehydra-modules']);
+if (treehydra_enabled())
+  LoadModules(options['treehydra-modules']);
+
 /**
  * gClassMap maps class names to an object with the following properties:
  *
  * .final = true   if the class has been annotated as final, and may not be
  *                 subclassed
  * .stack = true   if the class has been annotated as a class which may only
  *                 be instantiated on the stack
  */
@@ -33,16 +55,20 @@ ClassType.prototype = {
   final: false,
   stack: false,
 };
 
 function process_type(c)
 {
   if (c.kind == 'class' || c.kind == 'struct')
     get_class(c, true);
+
+  for each (let module in modules)
+    if (module.hasOwnProperty('process_type'))
+      module.process_type(c);
 }
 
 /**
  * Get the ClassType for a type 'c'
  *
  * If allowIncomplete is true and the type is incomplete, this function
  * will return null.
  *
@@ -195,32 +221,33 @@ function unwrapArray(t)
   while (t.isArray) {
     t = t.type;
   }
   return t;
 }
 
 function process_function(f, stmts)
 {
-  var stmt;
-  function getLocation()
-  {
-    if (stmt.loc)
-      return stmt.loc;
+  for each (let module in modules)
+    if (module.hasOwnProperty('process_function'))
+      module.process_function(f, stmts);
+}
 
-    return f.loc;
-  }
+function process_tree(fndecl)
+{
+  for each (let module in modules)
+    if (module.hasOwnProperty('process_tree'))
+      module.process_tree(fndecl);
+}
 
-  function processVar(v)
-  {
-    if (v.isConstructor &&
-        v.fieldOf &&
-        get_class(v.methodOf, false).stack &&
-        v.fieldOf.type.isPointer) {
-      error(getLocation() + ": constructed object of type '" +
-            v.methodOf.name + "' not on the stack.");
-    }
-  }
+function process_var(decl)
+{
+  for each (let module in modules)
+    if (module.hasOwnProperty('process_var'))
+      module.process_var(decl);
+}
 
-  for each (stmt in stmts) {
-    iter(processVar, stmt.statements);
-  }
+function input_end()
+{
+  for each (let module in modules)
+    if (module.hasOwnProperty('input_end'))
+      module.input_end();
 }