michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * A script for GCC-dehydra to analyze the Mozilla codebase and catch michael@0: * patterns that are incorrect, but which cannot be detected by a compiler. */ michael@0: michael@0: /** michael@0: * Activate Treehydra outparams analysis if running in Treehydra. michael@0: */ michael@0: michael@0: function treehydra_enabled() { michael@0: return this.hasOwnProperty('TREE_CODE'); michael@0: } michael@0: michael@0: sys.include_path.push(options.topsrcdir); michael@0: michael@0: include('string-format.js'); michael@0: michael@0: let modules = []; michael@0: michael@0: function LoadModules(modulelist) michael@0: { michael@0: if (modulelist == "") michael@0: return; michael@0: michael@0: let modulenames = modulelist.split(','); michael@0: for each (let modulename in modulenames) { michael@0: let module = { __proto__: this }; michael@0: include(modulename, module); michael@0: modules.push(module); michael@0: } michael@0: } michael@0: michael@0: LoadModules(options['dehydra-modules']); michael@0: if (treehydra_enabled()) michael@0: LoadModules(options['treehydra-modules']); michael@0: michael@0: function process_type(c) michael@0: { michael@0: for each (let module in modules) michael@0: if (module.hasOwnProperty('process_type')) michael@0: module.process_type(c); michael@0: } michael@0: michael@0: function hasAttribute(c, attrname) michael@0: { michael@0: var attr; michael@0: michael@0: if (c.attributes === undefined) michael@0: return false; michael@0: michael@0: for each (attr in c.attributes) michael@0: if (attr.name == 'user' && attr.value[0] == attrname) michael@0: return true; michael@0: michael@0: return false; michael@0: } michael@0: michael@0: // This is useful for detecting method overrides michael@0: function signaturesMatch(m1, m2) michael@0: { michael@0: if (m1.shortName != m2.shortName) michael@0: return false; michael@0: michael@0: if ((!!m1.isVirtual) != (!!m2.isVirtual)) michael@0: return false; michael@0: michael@0: if (m1.isStatic != m2.isStatic) michael@0: return false; michael@0: michael@0: let p1 = m1.type.parameters; michael@0: let p2 = m2.type.parameters; michael@0: michael@0: if (p1.length != p2.length) michael@0: return false; michael@0: michael@0: for (let i = 0; i < p1.length; ++i) michael@0: if (!params_match(p1[i], p2[i])) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: function params_match(p1, p2) michael@0: { michael@0: [p1, p2] = unwrap_types(p1, p2); michael@0: michael@0: for (let i in p1) michael@0: if (i == "type" && !types_match(p1.type, p2.type)) michael@0: return false; michael@0: else if (i != "type" && p1[i] !== p2[i]) michael@0: return false; michael@0: michael@0: for (let i in p2) michael@0: if (!(i in p1)) michael@0: return false; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: function types_match(t1, t2) michael@0: { michael@0: if (!t1 || !t2) michael@0: return false; michael@0: michael@0: [t1, t2] = unwrap_types(t1, t2); michael@0: michael@0: return t1 === t2; michael@0: } michael@0: michael@0: function unwrap_types(t1, t2) michael@0: { michael@0: while (t1.variantOf) michael@0: t1 = t1.variantOf; michael@0: michael@0: while (t2.variantOf) michael@0: t2 = t2.variantOf; michael@0: michael@0: return [t1, t2]; michael@0: } michael@0: michael@0: const forward_functions = [ michael@0: 'process_type', michael@0: 'process_tree_type', michael@0: 'process_decl', michael@0: 'process_tree_decl', michael@0: 'process_function', michael@0: 'process_tree', michael@0: 'process_cp_pre_genericize', michael@0: 'input_end' michael@0: ]; michael@0: michael@0: function setup_forwarding(n) michael@0: { michael@0: this[n] = function() { michael@0: for each (let module in modules) { michael@0: if (module.hasOwnProperty(n)) { michael@0: module[n].apply(this, arguments); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: for each (let n in forward_functions) michael@0: setup_forwarding(n);