| /* 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); |