diff -r 000000000000 -r 6474c204b198 config/static-checking.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/config/static-checking.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,147 @@ +/* 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/. */ + +/** + * 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'); +} + +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; +} + +// This is useful for detecting method overrides +function signaturesMatch(m1, m2) +{ + if (m1.shortName != m2.shortName) + return false; + + if ((!!m1.isVirtual) != (!!m2.isVirtual)) + return false; + + if (m1.isStatic != m2.isStatic) + return false; + + let p1 = m1.type.parameters; + let p2 = m2.type.parameters; + + if (p1.length != p2.length) + return false; + + for (let i = 0; i < p1.length; ++i) + if (!params_match(p1[i], p2[i])) + return false; + + return true; +} + +function params_match(p1, p2) +{ + [p1, p2] = unwrap_types(p1, p2); + + for (let i in p1) + if (i == "type" && !types_match(p1.type, p2.type)) + return false; + else if (i != "type" && p1[i] !== p2[i]) + return false; + + for (let i in p2) + if (!(i in p1)) + return false; + + return true; +} + +function types_match(t1, t2) +{ + if (!t1 || !t2) + return false; + + [t1, t2] = unwrap_types(t1, t2); + + return t1 === t2; +} + +function unwrap_types(t1, t2) +{ + while (t1.variantOf) + t1 = t1.variantOf; + + while (t2.variantOf) + t2 = t2.variantOf; + + return [t1, t2]; +} + +const forward_functions = [ + 'process_type', + 'process_tree_type', + 'process_decl', + 'process_tree_decl', + 'process_function', + 'process_tree', + 'process_cp_pre_genericize', + 'input_end' +]; + +function setup_forwarding(n) +{ + this[n] = function() { + for each (let module in modules) { + if (module.hasOwnProperty(n)) { + module[n].apply(this, arguments); + } + } + } +} + +for each (let n in forward_functions) + setup_forwarding(n);