Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / config / static-checking.js
1 /**
2  * A script for GCC-dehydra to analyze the Mozilla codebase and catch
3  * patterns that are incorrect, but which cannot be detected by a compiler. */
4
5 /**
6  * Activate Treehydra outparams analysis if running in Treehydra.
7  */
8
9 function treehydra_enabled() {
10   return this.hasOwnProperty('TREE_CODE');
11 }
12
13 sys.include_path.push(options.topsrcdir);
14
15 include('string-format.js');
16
17 let modules = [];
18
19 function LoadModules(modulelist)
20 {
21   if (modulelist == "")
22     return;
23
24   let modulenames = modulelist.split(',');
25   for each (let modulename in modulenames) {
26     let module = { __proto__: this };
27     include(modulename, module);
28     modules.push(module);
29   }
30 }
31
32 LoadModules(options['dehydra-modules']);
33 if (treehydra_enabled())
34   LoadModules(options['treehydra-modules']);
35
36 function process_type(c)
37 {
38   for each (let module in modules)
39     if (module.hasOwnProperty('process_type'))
40       module.process_type(c);
41 }
42
43 function hasAttribute(c, attrname)
44 {
45   var attr;
46
47   if (c.attributes === undefined)
48     return false;
49
50   for each (attr in c.attributes)
51     if (attr.name == 'user' && attr.value[0] == attrname)
52       return true;
53
54   return false;
55 }
56
57 // This is useful for detecting method overrides
58 function signaturesMatch(m1, m2)
59 {
60   if (m1.shortName != m2.shortName)
61     return false;
62
63   if ((!!m1.isVirtual) != (!!m2.isVirtual))
64     return false;
65   
66   if (m1.isStatic != m2.isStatic)
67     return false;
68   
69   let p1 = m1.type.parameters;
70   let p2 = m2.type.parameters;
71
72   if (p1.length != p2.length)
73     return false;
74   
75   for (let i = 0; i < p1.length; ++i)
76     if (!params_match(p1[i], p2[i]))
77       return false;
78
79   return true;
80 }
81
82 function params_match(p1, p2)
83 {
84   [p1, p2] = unwrap_types(p1, p2);
85
86   for (let i in p1)
87     if (i == "type" && !types_match(p1.type, p2.type))
88       return false;
89     else if (i != "type" && p1[i] !== p2[i])
90       return false;
91
92   for (let i in p2)
93     if (!(i in p1))
94       return false;
95
96   return true;
97 }
98
99 function types_match(t1, t2)
100 {
101   if (!t1 || !t2)
102     return false;
103
104   [t1, t2] = unwrap_types(t1, t2);
105
106   return t1 === t2;
107 }
108
109 function unwrap_types(t1, t2)
110 {
111   while (t1.variantOf)
112     t1 = t1.variantOf;
113
114   while (t2.variantOf)
115     t2 = t2.variantOf;
116
117   return [t1, t2];
118 }
119
120 const forward_functions = [
121   'process_type',
122   'process_tree_type',
123   'process_decl',
124   'process_tree_decl',
125   'process_function',
126   'process_tree',
127   'process_cp_pre_genericize',
128   'input_end'
129 ];
130
131 function setup_forwarding(n)
132 {
133   this[n] = function() {
134     for each (let module in modules) {
135       if (module.hasOwnProperty(n)) {
136         module[n].apply(this, arguments);
137       }
138     }
139   }
140 }
141
142 for each (let n in forward_functions)
143   setup_forwarding(n);