Bug Summary

File:platform/mac/avmshell/../../../eval/eval-parse-stmt.cpp
Location:line 616, column 39
Description:Access to field 'hd' results in a dereference of a null pointer (loaded from variable 'arguments')

Annotated Source Code

1/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3/* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is [Open Source Virtual Machine.].
17 *
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2008
21 * the Initial Developer. All Rights Reserved.
22 *
23 * Contributor(s):
24 * Adobe AS3 Team
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40#include "avmplus.h"
41
42#ifdef VMCFG_EVAL
43
44#include "eval.h"
45
46namespace avmplus
47{
48 namespace RTC
49 {
50 Stmt* Parser::statement(boolbool config)
51 {
52 AvmAssert(config == true || hd() == T_LeftBrace)do { } while (0);
53 switch (hd()) {
54 case T_Semicolon: {
55 Stmt* stmt = ALLOC(EmptyStmt, ())::new (allocator->alloc(sizeof(EmptyStmt))) EmptyStmt ();
56 next();
57 return stmt;
58 }
59
60 case T_LeftBrace:
61 return ALLOC(BlockStmt, (statementBlock(config)))::new (allocator->alloc(sizeof(BlockStmt))) BlockStmt (statementBlock
(config))
;
62
63 case T_Break: {
64 Stmt* stmt = breakStatement();
65 semicolon();
66 return stmt;
67 }
68
69 case T_Continue: {
70 Stmt* stmt = continueStatement();
71 semicolon();
72 return stmt;
73 }
74
75 case T_Default: {
76 next();
77 if (hd() == T_Identifier && identValue() == compiler->SYM_xml) {
78 Stmt* stmt = defaultXmlNamespaceStatement();
79 semicolon();
80 return stmt;
81 }
82 else {
83 compiler->syntaxError(position(), SYNTAXERR_DEFAULT_NOT_EXPECTED);
84 /*NOTREACHED*/
85 return NULL__null;
86 }
87 }
88
89 case T_Do: {
90 Stmt* stmt = doStatement();
91 semicolon();
92 return stmt;
93 }
94
95 case T_For:
96 return forStatement();
97
98 case T_If:
99 return ifStatement();
100
101 case T_Import:
102 return importStatement();
103
104 case T_Return: {
105 Stmt* stmt = returnStatement();
106 semicolon();
107 return stmt;
108 }
109
110 case T_Switch:
111 return switchStatement();
112
113 case T_Throw: {
114 Stmt* stmt = throwStatement();
115 semicolon();
116 return stmt;
117 }
118
119 case T_Try:
120 return tryStatement();
121
122 case T_Use: {
123 Stmt* stmt = useStatement();
124 semicolon();
125 return stmt;
126 }
127
128 case T_Var:
129 case T_Const: {
130 Stmt* stmt = varStatement(hd() == T_Const);
131 semicolon();
132 return stmt;
133 }
134
135 case T_While:
136 return whileStatement();
137
138 case T_With:
139 return withStatement ();
140
141 case T_Function:
142 if (compiler->local_functions) {
143 // FIXME: should block-internal function definition be initialized on block entry?
144 uint32_t pos = position();
145 Qualifier qual;
146 FunctionDefn* fn = functionGuts(&qual, truetrue, falsefalse, truetrue);
147 Str* name = fn->name;
148 fn->name = NULL__null;
149 addVarBinding(name, NULL__null);
150 return ALLOC(ExprStmt, (pos,::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, ::
new (allocator->alloc(sizeof(AssignExpr))) AssignExpr (OPR_assign
, ::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName
(__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName
(name), false, pos), ::new (allocator->alloc(sizeof(LiteralFunction
))) LiteralFunction (fn)))
151 ALLOC(AssignExpr,::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, ::
new (allocator->alloc(sizeof(AssignExpr))) AssignExpr (OPR_assign
, ::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName
(__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName
(name), false, pos), ::new (allocator->alloc(sizeof(LiteralFunction
))) LiteralFunction (fn)))
152 (OPR_assign,::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, ::
new (allocator->alloc(sizeof(AssignExpr))) AssignExpr (OPR_assign
, ::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName
(__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName
(name), false, pos), ::new (allocator->alloc(sizeof(LiteralFunction
))) LiteralFunction (fn)))
153 ALLOC(QualifiedName, (NULL, ALLOC(SimpleName, (name)), false, pos)),::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, ::
new (allocator->alloc(sizeof(AssignExpr))) AssignExpr (OPR_assign
, ::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName
(__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName
(name), false, pos), ::new (allocator->alloc(sizeof(LiteralFunction
))) LiteralFunction (fn)))
154 ALLOC(LiteralFunction, (fn))))))::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, ::
new (allocator->alloc(sizeof(AssignExpr))) AssignExpr (OPR_assign
, ::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName
(__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName
(name), false, pos), ::new (allocator->alloc(sizeof(LiteralFunction
))) LiteralFunction (fn)))
;
155 }
156 else {
157 compiler->syntaxError(position(), SYNTAXERR_NO_FUNCTIONS_IN_BLOCKS);
158 /*NOTREACHED*/
159 return NULL__null;
160 }
161
162 case T_Super:
163 return superStatement();
164
165 default: {
166 if (hd() == T_Identifier && hd2() == T_Colon)
167 return labeledStatement();
168 uint32_t pos = position();
169 Stmt* stmt = ALLOC(ExprStmt, (pos, commaExpression(0)))::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, commaExpression
(0))
;
170 semicolon();
171 return stmt;
172 }
173 }
174 }
175
176 void Parser::semicolon()
177 {
178 switch (hd ()) {
179 case T_Semicolon:
180 next();
181 return;
182 case T_EOS:
183 case T_RightBrace:
184 // Inserting it
185 return;
186 default:
187 if (!newline ())
188 compiler->syntaxError(position(), SYNTAXERR_SEMICOLON_OR_NEWLINE);
189 // Inserting it
190 return;
191 }
192 }
193
194 boolbool Parser::noNewline()
195 {
196 switch (hd ()) {
197 case T_EOS:
198 case T_Semicolon:
199 case T_RightBrace:
200 return falsefalse;
201 default:
202 if (newline())
203 return falsefalse;
204 return truetrue;
205 }
206 }
207
208 Seq<Stmt*>* Parser::statementBlock(boolbool config)
209 {
210 SeqBuilder<Stmt*> stmts(allocator);
211 eat (T_LeftBrace);
212 while (hd() != T_RightBrace)
213 stmts.addAtEnd(statement(config));
214 eat (T_RightBrace);
215 return stmts.get();
216 }
217
218 // updates bindings by side effect, returns a single expression
219 // statement for the initialization.
220
221 Stmt* Parser::varStatement(boolbool is_const)
222 {
223 uint32_t pos = 0;
224 Expr* inits = varBindings(&pos, is_const);
225 return ALLOC(ExprStmt, (pos, inits))::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, inits
)
;
226 }
227
228 // updates bindings by side effect, returns a single expression for
229 // the initialization, a LiteralUndefined node if there was no useful
230 // initialization.
231
232 Expr* Parser::varBindings(uint32_t* pos, boolbool is_const, int flags, uint32_t* numbindings, Expr** firstName)
233 {
234 AvmAssert( !is_const || firstName == NULL )do { } while (0);
235
236 Expr* inits = NULL__null;
237 eat(is_const ? T_Const : T_Var);
238 *pos = position();
239 if (numbindings)
240 *numbindings = 0;
241 if (firstName)
242 *firstName = NULL__null;
243 for (;;) {
244 Str* name = identifier();
245 QualifiedName* type_name = NULL__null;
246 if (match(T_Colon))
247 type_name = typeExpression();
248 if (numbindings)
249 *numbindings += 1;
250 if (!is_const)
251 addVarBinding(name, type_name);
252 /*
253 if (is_const && hd() != T_Assign)
254 compiler->syntaxError(*pos, SYNTAXERR_CONST_INIT_REQD);
255 */
256 if (match(T_Assign)) {
257 Expr* init = assignmentExpression(flags);
258 Expr* lhs = ALLOC(QualifiedName, (NULL, ALLOC(SimpleName, (name)), false, *pos))::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName
(__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName
(name), false, *pos)
;
259 if (is_const)
260 addConstBinding(name, type_name);
261 Expr* assign = ALLOC(AssignExpr, (is_const ? OPR_init : OPR_assign, lhs, init))::new (allocator->alloc(sizeof(AssignExpr))) AssignExpr (is_const
? OPR_init : OPR_assign, lhs, init)
;
262 if (firstName && *firstName == NULL__null)
263 *firstName = lhs;
264 if (inits == NULL__null)
265 inits = assign;
266 else
267 inits = ALLOC(BinaryExpr, (OPR_comma, inits, assign))::new (allocator->alloc(sizeof(BinaryExpr))) BinaryExpr (OPR_comma
, inits, assign)
;
268 }
269 else if (firstName && *firstName == NULL__null) {
270 *firstName = ALLOC(QualifiedName, (NULL, ALLOC(SimpleName, (name)), false, *pos))::new (allocator->alloc(sizeof(QualifiedName))) QualifiedName
(__null, ::new (allocator->alloc(sizeof(SimpleName))) SimpleName
(name), false, *pos)
;
271 }
272
273 if (!match(T_Comma))
274 break;
275 }
276 return inits ? inits : ALLOC(LiteralUndefined, (*pos))::new (allocator->alloc(sizeof(LiteralUndefined))) LiteralUndefined
(*pos)
;
277 }
278
279 Stmt* Parser::useStatement()
280 {
281 uint32_t pos = position();
282 eat(T_Use);
283 if (!match(T_Namespace))
284 compiler->syntaxError(pos, SYNTAXERR_ILLEGAL_USE);
285 Str* ns = identifier();
286 addOpenNamespace(ALLOC(NamespaceRef, (ns))::new (allocator->alloc(sizeof(NamespaceRef))) NamespaceRef
(ns)
);
287 return ALLOC(EmptyStmt, ())::new (allocator->alloc(sizeof(EmptyStmt))) EmptyStmt ();
288 }
289
290 // <import> ::= "import" <ident> { "." <ident> }* { "." "*" }
291 Stmt* Parser::importStatement()
292 {
293 SeqBuilder<Str*> name(allocator);
294 StringBuilder id(compiler);
295
296 eat(T_Import);
297 if (hd() == T_Identifier) {
298 name.addAtEnd(identValue());
299 id.append(identValue());
300 }
301 eat(T_Identifier);
302 boolbool qualified = truetrue;
303 while (match(T_Dot)) {
304 if (hd() == T_Multiply) {
305 match(T_Multiply);
306 qualified = falsefalse;
307 break;
308 }
309 id.append(".");
310 if (hd() == T_Identifier) {
311 name.addAtEnd(identValue());
312 id.append(identValue());
313 }
314 eat(T_Identifier);
315 }
316 Seq<Str*>* n = name.get();
317 if (qualified)
318 addQualifiedImport(n);
319 else {
320 addOpenNamespace(ALLOC(CommonNamespace, (id.str()))::new (allocator->alloc(sizeof(CommonNamespace))) CommonNamespace
(id.str())
);
321 addUnqualifiedImport(n);
322 }
323 return ALLOC(EmptyStmt, ())::new (allocator->alloc(sizeof(EmptyStmt))) EmptyStmt ();
324 }
325
326 Stmt* Parser::labeledStatement()
327 {
328 Str* label = identifier();
329 eat(T_Colon);
330
331 Stmt* stmt = statement();
332
333 Stmt* s = stmt;
334 while (s->isLabeledStmt())
335 s = ((LabeledStmt*)s)->stmt;
336 if (s->isLabelSetStmt()) {
337 LabelSetStmt* ls = (LabelSetStmt*)s;
338 ls->labels = ALLOC(Seq<Str*>, (label, ls->labels))::new (allocator->alloc(sizeof(Seq<Str*>))) Seq<Str
*> (label, ls->labels)
;
339 }
340
341 return ALLOC(LabeledStmt, (label, stmt))::new (allocator->alloc(sizeof(LabeledStmt))) LabeledStmt (
label, stmt)
;
342 }
343
344 Stmt* Parser::returnStatement()
345 {
346 eat (T_Return);
347 uint32_t pos = position();
348 if (topRib->tag != RIB_Function)
349 compiler->syntaxError(pos, SYNTAXERR_RETURN_OUTSIDE_FN);
350 Expr* expr = NULL__null;
351 if (noNewline()) {
352 if (topRib->is_void)
353 compiler->syntaxError(pos, SYNTAXERR_VOIDFN_RETURNS_VALUE);
354 expr = commaExpression(0);
355 }
356 return ALLOC(ReturnStmt, (pos, expr))::new (allocator->alloc(sizeof(ReturnStmt))) ReturnStmt (pos
, expr)
;
357 }
358
359 Stmt* Parser::breakStatement()
360 {
361 uint32_t pos = position();
362 return ALLOC(BreakStmt, (pos, breakOrContinueLabel(T_Break)))::new (allocator->alloc(sizeof(BreakStmt))) BreakStmt (pos
, breakOrContinueLabel(T_Break))
;
363 }
364
365 Stmt* Parser::continueStatement()
366 {
367 uint32_t pos = position();
368 return ALLOC(ContinueStmt, (pos, breakOrContinueLabel(T_Continue)))::new (allocator->alloc(sizeof(ContinueStmt))) ContinueStmt
(pos, breakOrContinueLabel(T_Continue))
;
369 }
370
371 Str* Parser::breakOrContinueLabel(Token tok)
372 {
373 eat(tok);
374 return noNewline() ? identifier() : NULL__null;
375 }
376
377 // 'default' has been consumed, hd() is the identifier 'xml'
378 Stmt* Parser::defaultXmlNamespaceStatement()
379 {
380 uint32_t pos = position();
381 if(hd() != T_Identifier || identValue() != compiler->SYM_xml)
382 goto failure;
383 eat(T_Identifier);
384 if(hd() != T_Namespace)
385 goto failure;
386 eat(T_Namespace);
387 eat(T_Assign);
388 setUsesDefaultXmlNamespace();
389 return ALLOC(DefaultXmlNamespaceStmt, (pos, commaExpression(0)))::new (allocator->alloc(sizeof(DefaultXmlNamespaceStmt))) DefaultXmlNamespaceStmt
(pos, commaExpression(0))
;
390 failure:
391 compiler->syntaxError(pos, SYNTAXERR_EXPECT_DXNS);
392 /*NOTREACHED*/
393 return NULL__null;
394 }
395
396 Stmt* Parser::ifStatement()
397 {
398 eat(T_If);
399 uint32_t pos = position();
400 Expr* test = parenExpression();
401 Stmt* consequent = statement();
402 Stmt* alternate = NULL__null;
403 if (match(T_Else))
404 alternate = statement();
405
406 return ALLOC(IfStmt, (pos, test, consequent, alternate))::new (allocator->alloc(sizeof(IfStmt))) IfStmt (pos, test
, consequent, alternate)
;
407 }
408
409 Stmt* Parser::whileStatement()
410 {
411 eat(T_While);
412 uint32_t pos = position();
413 Expr* expr = parenExpression();
414 Stmt* body = statement();
415
416 return ALLOC(WhileStmt, (pos, expr, body))::new (allocator->alloc(sizeof(WhileStmt))) WhileStmt (pos
, expr, body)
;
417 }
418
419 Stmt* Parser::doStatement()
420 {
421 eat(T_Do);
422 Stmt* body = statement();
423 eat(T_While);
424 uint32_t pos = position();
425 Expr* expr = parenExpression ();
426
427 return ALLOC(DoWhileStmt, (pos, expr, body))::new (allocator->alloc(sizeof(DoWhileStmt))) DoWhileStmt (
pos, expr, body)
;
428 }
429
430 Stmt* Parser::forStatement()
431 {
432 Expr* init=NULL__null;
433 Expr* lhs=NULL__null;
434 uint32_t numbindings = 0;
435 boolbool is_each = falsefalse;
436
437 eat (T_For);
438 if (hd() == T_Identifier && identValue() == compiler->SYM_each) {
439 is_each = truetrue;
440 eat(T_Identifier);
441 }
442 uint32_t pos = position();
443 eat (T_LeftParen);
444
445 if (hd() == T_Var)
446 {
447 uint32_t dummy = 0;
448 init = varBindings(&dummy, falsefalse, EFLAG_NoIn, &numbindings, &lhs);
449 }
450 else if (hd() == T_Semicolon)
451 ;
452 else
453 lhs = init = commaExpression(EFLAG_NoIn);
454
455 if (match(T_In)) {
456 if (numbindings > 1)
457 compiler->syntaxError(pos, SYNTAXERR_FOR_IN_ONEBINDING);
458
459 Expr* objexpr = commaExpression(0);
460 eat (T_RightParen);
461 Stmt* body = statement();
462
463 AvmAssert( lhs != NULL )do { } while (0);
464 return ALLOC(ForInStmt, (pos, lhs, init, objexpr, body, is_each))::new (allocator->alloc(sizeof(ForInStmt))) ForInStmt (pos
, lhs, init, objexpr, body, is_each)
;
465 }
466 else {
467 if (is_each)
468 compiler->syntaxError(pos, SYNTAXERR_FOR_EACH_REQS_IN);
469
470 eat(T_Semicolon);
471 Expr* test = hd() == T_Semicolon ? NULL__null : commaExpression(0);
472 eat(T_Semicolon);
473 Expr* update = hd() == T_RightParen ? NULL__null : commaExpression(0);
474 eat(T_RightParen);
475 Stmt* body = statement ();
476
477 return ALLOC(ForStmt, (pos, init, test, update, body))::new (allocator->alloc(sizeof(ForStmt))) ForStmt (pos, init
, test, update, body)
;
478 }
479 }
480
481 Stmt* Parser::switchStatement()
482 {
483 eat (T_Switch);
484 uint32_t pos = position();
485 Expr* expr = parenExpression ();
486
487 eat (T_LeftBrace);
488 Seq<CaseClause*>* cases = NULL__null;
489 if (hd() == T_Case || hd() == T_Default)
490 cases = caseElements();
491 eat(T_RightBrace);
492
493 return ALLOC(SwitchStmt, (pos, expr, cases))::new (allocator->alloc(sizeof(SwitchStmt))) SwitchStmt (pos
, expr, cases)
;
494 }
495
496 Seq<CaseClause*>* Parser::caseElements()
497 {
498 SeqBuilder<CaseClause*> cases(allocator);
499 boolbool hasDefault = falsefalse;
500 CaseClause* last = NULL__null;
501
502 for (;;) {
503 switch (hd ()) {
504 case T_RightBrace:
505 return cases.get();
506
507 case T_Default: {
508 if (hd2() != T_Colon)
509 goto just_a_statement; // default xml namespace
510 eat(T_Default);
511 eat(T_Colon);
512 if (hasDefault)
513 compiler->syntaxError(position(), SYNTAXERR_DUPLICATE_DEFAULT);
514 hasDefault = truetrue;
515 cases.addAtEnd(last = ALLOC(CaseClause, (0, NULL))::new (allocator->alloc(sizeof(CaseClause))) CaseClause (0
, __null)
);
516 break;
517 }
518
519 case T_Case: {
520 eat(T_Case);
521 uint32_t pos = position();
522 Expr* expr = commaExpression(0);
523 eat(T_Colon);
524 cases.addAtEnd(last = ALLOC(CaseClause, (pos, expr))::new (allocator->alloc(sizeof(CaseClause))) CaseClause (pos
, expr)
);
525 }
526 /*FALLTHROUGH*/
527 just_a_statement:
528 default: {
529 if (last == NULL__null)
530 compiler->syntaxError(position(), SYNTAXERR_EXPECT_CASE_OR_DEFAULT);
531 AvmAssert(last->stmts == NULL)do { } while (0);
532 SeqBuilder<Stmt*> stmts(allocator);
533 while (hd() != T_RightBrace && hd() != T_Case && hd() != T_Default)
534 stmts.addAtEnd(statement());
535 last->stmts = stmts.get();
536 break;
537 }
538 }
539 }
540 }
541
542 Stmt* Parser::throwStatement()
543 {
544 eat (T_Throw);
545 uint32_t pos = position();
546 return ALLOC(ThrowStmt, (pos, commaExpression(0)))::new (allocator->alloc(sizeof(ThrowStmt))) ThrowStmt (pos
, commaExpression(0))
;
547 }
548
549 Stmt* Parser::tryStatement()
550 {
551 eat (T_Try);
552
553 Seq<Stmt*>* tryblock = statementBlock();
554 Seq<CatchClause*>* catchblocks = catches();
555 Seq<Stmt*>* finallyblock = NULL__null;
556
557 if (match(T_Finally)) {
558 setUsesFinally();
559 finallyblock = statementBlock();
560 }
561
562 return ALLOC(TryStmt, (tryblock, catchblocks,finallyblock))::new (allocator->alloc(sizeof(TryStmt))) TryStmt (tryblock
, catchblocks,finallyblock)
;
563 }
564
565 Seq<CatchClause*>* Parser::catches()
566 {
567 SeqBuilder<CatchClause*> catches(allocator);
568
569 // Sort of silly that this allows multiple catches yet catchClause() does not
570 // allow the clauses to discriminate by type.
571
572 while (match(T_Catch)) {
573 setUsesCatch();
574 catches.addAtEnd(catchClause());
575 }
576
577 return catches.get();
578 }
579
580 CatchClause* Parser::catchClause()
581 {
582 eat (T_LeftParen);
583 Str* catchvar_name = identifier();
584 QualifiedName* catchvar_type_name = NULL__null;
585 if (match(T_Colon))
586 catchvar_type_name = typeExpression();
587 eat (T_RightParen);
588 Seq<Stmt*>* catchblock = statementBlock();
589 return ALLOC(CatchClause, (catchvar_name, catchvar_type_name, catchblock))::new (allocator->alloc(sizeof(CatchClause))) CatchClause (
catchvar_name, catchvar_type_name, catchblock)
;
590 }
591
592 Stmt* Parser::withStatement()
593 {
594 eat (T_With);
595 uint32_t pos = position();
596 Expr* expr = parenExpression();
597 Stmt* body = statement();
598 return ALLOC(WithStmt, (pos, expr, body))::new (allocator->alloc(sizeof(WithStmt))) WithStmt (pos, expr
, body)
;
599 }
600
601 // This also parses super expressions when they appear in the statement position.
602 Stmt* Parser::superStatement()
603 {
604 eat (T_Super);
605 uint32_t pos = position();
606 Seq<Expr*>* arguments = NULL__null;
607 boolbool argsPresent = falsefalse;
608 if (hd() == T_LeftParen) {
1
Taking true branch
609 argsPresent = truetrue;
610 arguments = argumentList();
611 }
612 if (argsPresent && hd() != T_Dot && hd() != T_LeftBracket)
2
Taking false branch
613 return ALLOC(SuperStmt, (pos, arguments))::new (allocator->alloc(sizeof(SuperStmt))) SuperStmt (pos
, arguments)
;
614 if (argsPresent && (arguments == NULL__null || arguments->tl != NULL__null))
3
Taking true branch
615 compiler->syntaxError(pos, SYNTAXERR_ONE_ARGUMENT_REQUIRED);
616 Expr* obj = argsPresent ? arguments->hd : ALLOC(ThisExpr, ())::new (allocator->alloc(sizeof(ThisExpr))) ThisExpr ();
4
'?' condition is true
5
Access to field 'hd' results in a dereference of a null pointer (loaded from variable 'arguments')
617 return ALLOC(ExprStmt, (pos, propertyOperator(ALLOC(SuperExpr, (obj)))))::new (allocator->alloc(sizeof(ExprStmt))) ExprStmt (pos, propertyOperator
(::new (allocator->alloc(sizeof(SuperExpr))) SuperExpr (obj
)))
;
618 }
619 }
620}
621
622#endif // VMCFG_EVAL