diff --git a/config/static-checking-config.mk b/config/static-checking-config.mk index cf1901e71b02..1c834f884208 100644 --- a/config/static-checking-config.mk +++ b/config/static-checking-config.mk @@ -1,7 +1,7 @@ # The entire tree should be subject to static analysis using the XPCOM # script. Additional scripts may be added by specific subdirectories. -DEHYDRA_SCRIPT = $(topsrcdir)/xpcom/analysis/static-checking.js +DEHYDRA_SCRIPT = $(topsrcdir)/config/static-checking.js DEHYDRA_MODULES = \ $(topsrcdir)/xpcom/analysis/final.js \ @@ -11,7 +11,7 @@ TREEHYDRA_MODULES = \ $(topsrcdir)/xpcom/analysis/outparams.js \ $(topsrcdir)/xpcom/analysis/stack.js \ $(topsrcdir)/xpcom/analysis/flow.js \ - $(topsrcdir)/xpcom/analysis/jsstack.js \ + $(topsrcdir)/js/src/jsstack.js \ $(NULL) DEHYDRA_ARGS = \ diff --git a/xpcom/analysis/static-checking.js b/config/static-checking.js similarity index 93% rename from xpcom/analysis/static-checking.js rename to config/static-checking.js index d8256710c30f..68103cf7a027 100644 --- a/xpcom/analysis/static-checking.js +++ b/config/static-checking.js @@ -13,8 +13,6 @@ function treehydra_enabled() { 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); include('string-format.js'); diff --git a/xpcom/analysis/string-format.js b/config/string-format.js similarity index 100% rename from xpcom/analysis/string-format.js rename to config/string-format.js diff --git a/js/src/config/static-checking-config.mk b/js/src/config/static-checking-config.mk index 7c1140b56a69..27ca255e49a7 100644 --- a/js/src/config/static-checking-config.mk +++ b/js/src/config/static-checking-config.mk @@ -1,13 +1,10 @@ -# Currently spidermonkey has no static checking infrastructure, but it will... -# This is all dummy values now: see the Mozilla version of this file for -# an example with real data. - -DEHYDRA_SCRIPT = $(error No Spidermonkey static-checking.js yet!) +DEHYDRA_SCRIPT = $(topsrcdir)/config/static-checking.js DEHYDRA_MODULES = \ $(NULL) TREEHYDRA_MODULES = \ + $(topsrcdir)/jsstack.js \ $(NULL) DEHYDRA_ARGS = \ @@ -19,6 +16,6 @@ DEHYDRA_ARGS = \ DEHYDRA_FLAGS = -fplugin=$(DEHYDRA_PATH) -fplugin-arg='$(DEHYDRA_SCRIPT) $(DEHYDRA_ARGS)' -# ifdef DEHYDRA_PATH -# OS_CXXFLAGS += $(DEHYDRA_FLAGS) -# endif +ifdef DEHYDRA_PATH +OS_CXXFLAGS += $(DEHYDRA_FLAGS) +endif diff --git a/js/src/config/static-checking.js b/js/src/config/static-checking.js new file mode 100644 index 000000000000..68103cf7a027 --- /dev/null +++ b/js/src/config/static-checking.js @@ -0,0 +1,92 @@ +/** + * A script for GCC-dehydra to analyze the Mozilla codebase and catch + * patterns that are incorrect, but which cannot be detected by a compiler. */ + +/** + * Activate Treehydra outparams analysis if running in Treehydra. + */ + +function treehydra_enabled() { + return this.hasOwnProperty('TREE_CODE'); +} + +include('unstable/getopt.js'); +[options, args] = getopt(); + +sys.include_path.push(options.topsrcdir); + +include('string-format.js'); + +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']); + +function process_type(c) +{ + for each (let module in modules) + if (module.hasOwnProperty('process_type')) + module.process_type(c); +} + +function hasAttribute(c, attrname) +{ + var attr; + + if (c.attributes === undefined) + return false; + + for each (attr in c.attributes) + if (attr.name == 'user' && attr.value[0] == attrname) + return true; + + return false; +} +function process_function(f, stmts) +{ + for each (let module in modules) + if (module.hasOwnProperty('process_function')) + module.process_function(f, stmts); +} + +function process_tree(fndecl) +{ + for each (let module in modules) + if (module.hasOwnProperty('process_tree')) + module.process_tree(fndecl); +} + +function process_decl(decl) +{ + for each (let module in modules) + if (module.hasOwnProperty('process_var')) + module.process_decl(decl); +} + +function process_cp_pre_genericize(fndecl) +{ + for each (let module in modules) + if (module.hasOwnProperty('process_cp_pre_genericize')) + module.process_cp_pre_genericize(fndecl); +} + +function input_end() +{ + for each (let module in modules) + if (module.hasOwnProperty('input_end')) + module.input_end(); +} diff --git a/js/src/config/string-format.js b/js/src/config/string-format.js new file mode 100644 index 000000000000..352a5f33c589 --- /dev/null +++ b/js/src/config/string-format.js @@ -0,0 +1,61 @@ +String.prototype.format = function string_format() { + // there are two modes of operation... unnamed indices are read in order; + // named indices using %(name)s. The two styles cannot be mixed. + // Unnamed indices can be passed as either a single argument to this function, + // multiple arguments to this function, or as a single array argument + let curindex = 0; + let d; + + if (arguments.length > 1) { + d = arguments; + } + else + d = arguments[0]; + + function r(s, key, type) { + if (type == '%') + return '%'; + + let v; + if (key == "") { + if (curindex == -1) + throw Error("Cannot mix named and positional indices in string formatting."); + + if (curindex == 0 && (!(d instanceof Object) || !(0 in d))) { + v = d; + } + else if (!(curindex in d)) + throw Error("Insufficient number of items in format, requesting item %i".format(curindex)); + else { + v = d[curindex]; + } + + ++curindex; + } + else { + key = key.slice(1, -1); + if (curindex > 0) + throw Error("Cannot mix named and positional indices in string formatting."); + curindex = -1; + + if (!(key in d)) + throw Error("Key '%s' not present during string substitution.".format(key)); + v = d[key]; + } + switch (type) { + case "s": + if (v === undefined) + return ""; + return v.toString(); + case "r": + return uneval(v); + case "i": + return parseInt(v); + case "f": + return Number(v); + default: + throw Error("Unexpected format character '%s'.".format(type)); + } + } + return this.replace(/%(\([^)]+\))?(.)/g, r); +}; diff --git a/xpcom/analysis/jsstack.js b/js/src/jsstack.js similarity index 100% rename from xpcom/analysis/jsstack.js rename to js/src/jsstack.js diff --git a/xpcom/analysis/outparams.js b/xpcom/analysis/outparams.js index c452f0b6514a..690b29914b64 100644 --- a/xpcom/analysis/outparams.js +++ b/xpcom/analysis/outparams.js @@ -12,7 +12,7 @@ include('unstable/esp.js'); let Zero_NonZero = {}; include('unstable/zero_nonzero.js', Zero_NonZero); -include('mayreturn.js'); +include('xpcom/analysis/mayreturn.js'); function safe_location_of(t) { if (t === undefined)