blob: 9e59741ba11878bc5874fe218bca7a7a612c66fe [file] [log] [blame]
/* 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);