[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / test / cctest / test-ast-expression-visitor.cc
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdlib.h>
6
7 #include "src/v8.h"
8
9 #include "src/ast.h"
10 #include "src/ast-expression-visitor.h"
11 #include "src/parser.h"
12 #include "src/rewriter.h"
13 #include "src/scopes.h"
14 #include "test/cctest/cctest.h"
15 #include "test/cctest/expression-type-collector.h"
16 #include "test/cctest/expression-type-collector-macros.h"
17
18 using namespace v8::internal;
19
20 namespace {
21
22 static void CollectTypes(HandleAndZoneScope* handles, const char* source,
23                          ZoneVector<ExpressionTypeEntry>* dst) {
24   i::Isolate* isolate = CcTest::i_isolate();
25   i::Factory* factory = isolate->factory();
26
27   i::Handle<i::String> source_code =
28       factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked();
29
30   i::Handle<i::Script> script = factory->NewScript(source_code);
31
32   i::ParseInfo info(handles->main_zone(), script);
33   i::Parser parser(&info);
34   parser.set_allow_harmony_arrow_functions(true);
35   parser.set_allow_harmony_sloppy(true);
36   info.set_global();
37   info.set_lazy(false);
38   info.set_allow_lazy_parsing(false);
39   info.set_toplevel(true);
40
41   CHECK(i::Compiler::ParseAndAnalyze(&info));
42
43   ExpressionTypeCollector(
44       isolate, handles->main_zone(),
45       info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(), dst)
46       .Run();
47 }
48
49 }  // namespace
50
51
52 TEST(VisitExpressions) {
53   v8::V8::Initialize();
54   HandleAndZoneScope handles;
55   ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
56   const char test_function[] =
57       "function GeometricMean(stdlib, foreign, buffer) {\n"
58       "  \"use asm\";\n"
59       "\n"
60       "  var exp = stdlib.Math.exp;\n"
61       "  var log = stdlib.Math.log;\n"
62       "  var values = new stdlib.Float64Array(buffer);\n"
63       "\n"
64       "  function logSum(start, end) {\n"
65       "    start = start|0;\n"
66       "    end = end|0;\n"
67       "\n"
68       "    var sum = 0.0, p = 0, q = 0;\n"
69       "\n"
70       "    // asm.js forces byte addressing of the heap by requiring shifting "
71       "by 3\n"
72       "    for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n"
73       "      sum = sum + +log(values[p>>3]);\n"
74       "    }\n"
75       "\n"
76       "    return +sum;\n"
77       "  }\n"
78       "\n"
79       " function geometricMean(start, end) {\n"
80       "    start = start|0;\n"
81       "    end = end|0;\n"
82       "\n"
83       "    return +exp(+logSum(start, end) / +((end - start)|0));\n"
84       "  }\n"
85       "\n"
86       "  return { geometricMean: geometricMean };\n"
87       "}\n";
88
89   CollectTypes(&handles, test_function, &types);
90   CHECK_TYPES_BEGIN {
91     // function logSum
92     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
93       CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
94         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
95           CHECK_VAR(start, Bounds::Unbounded());
96           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
97             CHECK_VAR(start, Bounds::Unbounded());
98             CHECK_EXPR(Literal, Bounds::Unbounded());
99           }
100         }
101         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
102           CHECK_VAR(end, Bounds::Unbounded());
103           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
104             CHECK_VAR(end, Bounds::Unbounded());
105             CHECK_EXPR(Literal, Bounds::Unbounded());
106           }
107         }
108         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
109           CHECK_VAR(sum, Bounds::Unbounded());
110           CHECK_EXPR(Literal, Bounds::Unbounded());
111         }
112         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
113           CHECK_VAR(p, Bounds::Unbounded());
114           CHECK_EXPR(Literal, Bounds::Unbounded());
115         }
116         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
117           CHECK_VAR(q, Bounds::Unbounded());
118           CHECK_EXPR(Literal, Bounds::Unbounded());
119         }
120         // for (p = start << 3, q = end << 3;
121         CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
122           CHECK_EXPR(Assignment, Bounds::Unbounded()) {
123             CHECK_VAR(p, Bounds::Unbounded());
124             CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
125               CHECK_VAR(start, Bounds::Unbounded());
126               CHECK_EXPR(Literal, Bounds::Unbounded());
127             }
128           }
129           CHECK_EXPR(Assignment, Bounds::Unbounded()) {
130             CHECK_VAR(q, Bounds::Unbounded());
131             CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
132               CHECK_VAR(end, Bounds::Unbounded());
133               CHECK_EXPR(Literal, Bounds::Unbounded());
134             }
135           }
136         }
137         // (p|0) < (q|0);
138         CHECK_EXPR(CompareOperation, Bounds::Unbounded()) {
139           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
140             CHECK_VAR(p, Bounds::Unbounded());
141             CHECK_EXPR(Literal, Bounds::Unbounded());
142           }
143           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
144             CHECK_VAR(q, Bounds::Unbounded());
145             CHECK_EXPR(Literal, Bounds::Unbounded());
146           }
147         }
148         // p = (p + 8)|0) {\n"
149         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
150           CHECK_VAR(p, Bounds::Unbounded());
151           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
152             CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
153               CHECK_VAR(p, Bounds::Unbounded());
154               CHECK_EXPR(Literal, Bounds::Unbounded());
155             }
156             CHECK_EXPR(Literal, Bounds::Unbounded());
157           }
158         }
159         // sum = sum + +log(values[p>>3]);
160         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
161           CHECK_VAR(sum, Bounds::Unbounded());
162           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
163             CHECK_VAR(sum, Bounds::Unbounded());
164             CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
165               CHECK_EXPR(Call, Bounds::Unbounded()) {
166                 CHECK_VAR(log, Bounds::Unbounded());
167                 CHECK_EXPR(Property, Bounds::Unbounded()) {
168                   CHECK_VAR(values, Bounds::Unbounded());
169                   CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
170                     CHECK_VAR(p, Bounds::Unbounded());
171                     CHECK_EXPR(Literal, Bounds::Unbounded());
172                   }
173                 }
174               }
175               CHECK_EXPR(Literal, Bounds::Unbounded());
176             }
177           }
178         }
179         // return +sum;
180         CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
181           CHECK_VAR(sum, Bounds::Unbounded());
182           CHECK_EXPR(Literal, Bounds::Unbounded());
183         }
184       }
185       // function geometricMean
186       CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
187         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
188           CHECK_VAR(start, Bounds::Unbounded());
189           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
190             CHECK_VAR(start, Bounds::Unbounded());
191             CHECK_EXPR(Literal, Bounds::Unbounded());
192           }
193         }
194         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
195           CHECK_VAR(end, Bounds::Unbounded());
196           CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
197             CHECK_VAR(end, Bounds::Unbounded());
198             CHECK_EXPR(Literal, Bounds::Unbounded());
199           }
200         }
201         // return +exp(+logSum(start, end) / +((end - start)|0));
202         CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
203           CHECK_EXPR(Call, Bounds::Unbounded()) {
204             CHECK_VAR(exp, Bounds::Unbounded());
205             CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
206               CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
207                 CHECK_EXPR(Call, Bounds::Unbounded()) {
208                   CHECK_VAR(logSum, Bounds::Unbounded());
209                   CHECK_VAR(start, Bounds::Unbounded());
210                   CHECK_VAR(end, Bounds::Unbounded());
211                 }
212                 CHECK_EXPR(Literal, Bounds::Unbounded());
213               }
214               CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
215                 CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
216                   CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
217                     CHECK_VAR(end, Bounds::Unbounded());
218                     CHECK_VAR(start, Bounds::Unbounded());
219                   }
220                   CHECK_EXPR(Literal, Bounds::Unbounded());
221                 }
222                 CHECK_EXPR(Literal, Bounds::Unbounded());
223               }
224             }
225           }
226           CHECK_EXPR(Literal, Bounds::Unbounded());
227         }
228       }
229       // "use asm";
230       CHECK_EXPR(Literal, Bounds::Unbounded());
231       // var exp = stdlib.Math.exp;
232       CHECK_EXPR(Assignment, Bounds::Unbounded()) {
233         CHECK_VAR(exp, Bounds::Unbounded());
234         CHECK_EXPR(Property, Bounds::Unbounded()) {
235           CHECK_EXPR(Property, Bounds::Unbounded()) {
236             CHECK_VAR(stdlib, Bounds::Unbounded());
237             CHECK_EXPR(Literal, Bounds::Unbounded());
238           }
239           CHECK_EXPR(Literal, Bounds::Unbounded());
240         }
241       }
242       // var log = stdlib.Math.log;
243       CHECK_EXPR(Assignment, Bounds::Unbounded()) {
244         CHECK_VAR(log, Bounds::Unbounded());
245         CHECK_EXPR(Property, Bounds::Unbounded()) {
246           CHECK_EXPR(Property, Bounds::Unbounded()) {
247             CHECK_VAR(stdlib, Bounds::Unbounded());
248             CHECK_EXPR(Literal, Bounds::Unbounded());
249           }
250           CHECK_EXPR(Literal, Bounds::Unbounded());
251         }
252       }
253       // var values = new stdlib.Float64Array(buffer);
254       CHECK_EXPR(Assignment, Bounds::Unbounded()) {
255         CHECK_VAR(values, Bounds::Unbounded());
256         CHECK_EXPR(CallNew, Bounds::Unbounded()) {
257           CHECK_EXPR(Property, Bounds::Unbounded()) {
258             CHECK_VAR(stdlib, Bounds::Unbounded());
259             CHECK_EXPR(Literal, Bounds::Unbounded());
260           }
261           CHECK_VAR(buffer, Bounds::Unbounded());
262         }
263       }
264       // return { geometricMean: geometricMean };
265       CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
266         CHECK_VAR(geometricMean, Bounds::Unbounded());
267       }
268     }
269   }
270   CHECK_TYPES_END
271 }
272
273
274 TEST(VisitEmptyForStatment) {
275   v8::V8::Initialize();
276   HandleAndZoneScope handles;
277   ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
278   // Check that traversing an empty for statement works.
279   const char test_function[] =
280       "function foo() {\n"
281       "  for (;;) {}\n"
282       "}\n";
283   CollectTypes(&handles, test_function, &types);
284   CHECK_TYPES_BEGIN {
285     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {}
286   }
287   CHECK_TYPES_END
288 }
289
290
291 TEST(VisitSwitchStatment) {
292   v8::V8::Initialize();
293   HandleAndZoneScope handles;
294   ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
295   // Check that traversing a switch with a default works.
296   const char test_function[] =
297       "function foo() {\n"
298       "  switch (0) { case 1: break; default: break; }\n"
299       "}\n";
300   CollectTypes(&handles, test_function, &types);
301   CHECK_TYPES_BEGIN {
302     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
303       CHECK_EXPR(Assignment, Bounds::Unbounded()) {
304         CHECK_VAR(.switch_tag, Bounds::Unbounded());
305         CHECK_EXPR(Literal, Bounds::Unbounded());
306       }
307       CHECK_EXPR(Literal, Bounds::Unbounded());
308       CHECK_VAR(.switch_tag, Bounds::Unbounded());
309       CHECK_EXPR(Literal, Bounds::Unbounded());
310     }
311   }
312   CHECK_TYPES_END
313 }
314
315
316 TEST(VisitThrow) {
317   v8::V8::Initialize();
318   HandleAndZoneScope handles;
319   ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
320   // Check that traversing an empty for statement works.
321   const char test_function[] =
322       "function foo() {\n"
323       "  throw 123;\n"
324       "}\n";
325   CollectTypes(&handles, test_function, &types);
326   CHECK_TYPES_BEGIN {
327     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
328       CHECK_EXPR(Throw, Bounds::Unbounded()) {
329         CHECK_EXPR(Literal, Bounds::Unbounded());
330       }
331     }
332   }
333   CHECK_TYPES_END
334 }
335
336
337 TEST(VisitYield) {
338   v8::V8::Initialize();
339   HandleAndZoneScope handles;
340   ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
341   // Check that traversing an empty for statement works.
342   const char test_function[] =
343       "function* foo() {\n"
344       "  yield 123;\n"
345       "}\n";
346   CollectTypes(&handles, test_function, &types);
347   CHECK_TYPES_BEGIN {
348     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
349       // Generator function yields generator on entry.
350       CHECK_EXPR(Yield, Bounds::Unbounded()) {
351         CHECK_VAR(.generator_object, Bounds::Unbounded());
352         CHECK_EXPR(Assignment, Bounds::Unbounded()) {
353           CHECK_VAR(.generator_object, Bounds::Unbounded());
354           CHECK_EXPR(CallRuntime, Bounds::Unbounded());
355         }
356       }
357       // Then yields undefined.
358       CHECK_EXPR(Yield, Bounds::Unbounded()) {
359         CHECK_VAR(.generator_object, Bounds::Unbounded());
360         CHECK_EXPR(Literal, Bounds::Unbounded());
361       }
362       // Then yields 123.
363       CHECK_EXPR(Yield, Bounds::Unbounded()) {
364         CHECK_VAR(.generator_object, Bounds::Unbounded());
365         CHECK_EXPR(Literal, Bounds::Unbounded());
366       }
367     }
368   }
369   CHECK_TYPES_END
370 }
371
372
373 TEST(VisitSkipping) {
374   v8::V8::Initialize();
375   HandleAndZoneScope handles;
376   ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
377   // Check that traversing an empty for statement works.
378   const char test_function[] =
379       "function foo(x) {\n"
380       "  return (x + x) + 1;\n"
381       "}\n";
382   CollectTypes(&handles, test_function, &types);
383   CHECK_TYPES_BEGIN {
384     CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
385       CHECK_EXPR(BinaryOperation, Bounds::Unbounded()) {
386         // Skip x + x
387         CHECK_SKIP();
388         CHECK_EXPR(Literal, Bounds::Unbounded());
389       }
390     }
391   }
392   CHECK_TYPES_END
393 }