Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: src/parser.cc

Issue 220473014: Make stray 'return' an early error (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/runtime.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 } 583 }
584 // ...and one more time for '~foo' => 'foo^(~0)'. 584 // ...and one more time for '~foo' => 'foo^(~0)'.
585 if (op == Token::BIT_NOT) { 585 if (op == Token::BIT_NOT) {
586 return factory->NewBinaryOperation( 586 return factory->NewBinaryOperation(
587 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos); 587 Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
588 } 588 }
589 return factory->NewUnaryOperation(op, expression, pos); 589 return factory->NewUnaryOperation(op, expression, pos);
590 } 590 }
591 591
592 592
593 Expression* ParserTraits::NewThrowReferenceError( 593 Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) {
594 const char* message, int pos) {
595 return NewThrowError( 594 return NewThrowError(
596 parser_->isolate()->factory()->MakeReferenceError_string(), 595 parser_->isolate()->factory()->MakeReferenceError_string(),
597 message, HandleVector<Object>(NULL, 0), pos); 596 message, HandleVector<Object>(NULL, 0), pos);
598 } 597 }
599 598
600 599
601 Expression* ParserTraits::NewThrowSyntaxError( 600 Expression* ParserTraits::NewThrowSyntaxError(
602 const char* message, Handle<Object> arg, int pos) { 601 const char* message, Handle<Object> arg, int pos) {
603 int argc = arg.is_null() ? 0 : 1; 602 int argc = arg.is_null() ? 0 : 1;
604 Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc); 603 Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
605 return NewThrowError( 604 return NewThrowError(
606 parser_->isolate()->factory()->MakeSyntaxError_string(), 605 parser_->isolate()->factory()->MakeSyntaxError_string(),
607 message, arguments, pos); 606 message, arguments, pos);
608 } 607 }
609 608
610 609
611 Expression* ParserTraits::NewThrowTypeError( 610 Expression* ParserTraits::NewThrowTypeError(
612 const char* message, Handle<Object> arg1, Handle<Object> arg2, int pos) { 611 const char* message, Handle<Object> arg, int pos) {
613 ASSERT(!arg1.is_null() && !arg2.is_null()); 612 int argc = arg.is_null() ? 0 : 1;
614 Handle<Object> elements[] = { arg1, arg2 }; 613 Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
615 Vector< Handle<Object> > arguments =
616 HandleVector<Object>(elements, ARRAY_SIZE(elements));
617 return NewThrowError( 614 return NewThrowError(
618 parser_->isolate()->factory()->MakeTypeError_string(), 615 parser_->isolate()->factory()->MakeTypeError_string(),
619 message, arguments, pos); 616 message, arguments, pos);
620 } 617 }
621 618
622 619
623 Expression* ParserTraits::NewThrowError( 620 Expression* ParserTraits::NewThrowError(
624 Handle<String> constructor, const char* message, 621 Handle<String> constructor, const char* message,
625 Vector<Handle<Object> > arguments, int pos) { 622 Vector<Handle<Object> > arguments, int pos) {
626 Zone* zone = parser_->zone(); 623 Zone* zone = parser_->zone();
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1747 // 1744 //
1748 // function () { let x; { var x; } } 1745 // function () { let x; { var x; } }
1749 // 1746 //
1750 // because the var declaration is hoisted to the function scope where 'x' 1747 // because the var declaration is hoisted to the function scope where 'x'
1751 // is already bound. 1748 // is already bound.
1752 ASSERT(IsDeclaredVariableMode(var->mode())); 1749 ASSERT(IsDeclaredVariableMode(var->mode()));
1753 if (allow_harmony_scoping() && strict_mode() == STRICT) { 1750 if (allow_harmony_scoping() && strict_mode() == STRICT) {
1754 // In harmony we treat re-declarations as early errors. See 1751 // In harmony we treat re-declarations as early errors. See
1755 // ES5 16 for a definition of early errors. 1752 // ES5 16 for a definition of early errors.
1756 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); 1753 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1757 const char* elms[2] = { "Variable", c_string.get() }; 1754 const char* elms[1] = { c_string.get() };
1758 Vector<const char*> args(elms, 2); 1755 Vector<const char*> args(elms, 1);
1759 ReportMessage("redeclaration", args); 1756 ReportMessage("var_redeclaration", args);
1760 *ok = false; 1757 *ok = false;
1761 return; 1758 return;
1762 } 1759 }
1763 Handle<String> message_string = 1760 Expression* expression = NewThrowTypeError(
1764 isolate()->factory()->InternalizeOneByteString( 1761 "var_redeclaration", name, declaration->position());
1765 STATIC_ASCII_VECTOR("Variable"));
1766 Expression* expression =
1767 NewThrowTypeError("redeclaration",
1768 message_string, name, declaration->position());
1769 declaration_scope->SetIllegalRedeclaration(expression); 1762 declaration_scope->SetIllegalRedeclaration(expression);
1770 } 1763 }
1771 } 1764 }
1772 1765
1773 // We add a declaration node for every declaration. The compiler 1766 // We add a declaration node for every declaration. The compiler
1774 // will only generate code if necessary. In particular, declarations 1767 // will only generate code if necessary. In particular, declarations
1775 // for inner local variables that do not represent functions won't 1768 // for inner local variables that do not represent functions won't
1776 // result in any generated code. 1769 // result in any generated code.
1777 // 1770 //
1778 // Note that we always add an unresolved proxy even if it's not 1771 // Note that we always add an unresolved proxy even if it's not
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
2367 // identifier. 2360 // identifier.
2368 VariableProxy* var = expr->AsVariableProxy(); 2361 VariableProxy* var = expr->AsVariableProxy();
2369 Handle<String> label = var->name(); 2362 Handle<String> label = var->name();
2370 // TODO(1240780): We don't check for redeclaration of labels 2363 // TODO(1240780): We don't check for redeclaration of labels
2371 // during preparsing since keeping track of the set of active 2364 // during preparsing since keeping track of the set of active
2372 // labels requires nontrivial changes to the way scopes are 2365 // labels requires nontrivial changes to the way scopes are
2373 // structured. However, these are probably changes we want to 2366 // structured. However, these are probably changes we want to
2374 // make later anyway so we should go back and fix this then. 2367 // make later anyway so we should go back and fix this then.
2375 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) { 2368 if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2376 SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS); 2369 SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
2377 const char* elms[2] = { "Label", c_string.get() }; 2370 const char* elms[1] = { c_string.get() };
2378 Vector<const char*> args(elms, 2); 2371 Vector<const char*> args(elms, 1);
2379 ReportMessage("redeclaration", args); 2372 ReportMessage("label_redeclaration", args);
2380 *ok = false; 2373 *ok = false;
2381 return NULL; 2374 return NULL;
2382 } 2375 }
2383 if (labels == NULL) { 2376 if (labels == NULL) {
2384 labels = new(zone()) ZoneStringList(4, zone()); 2377 labels = new(zone()) ZoneStringList(4, zone());
2385 } 2378 }
2386 labels->Add(label, zone()); 2379 labels->Add(label, zone());
2387 // Remove the "ghost" variable that turned out to be a label 2380 // Remove the "ghost" variable that turned out to be a label
2388 // from the top scope. This way, we don't try to resolve it 2381 // from the top scope. This way, we don't try to resolve it
2389 // during the scope processing. 2382 // during the scope processing.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2514 2507
2515 2508
2516 Statement* Parser::ParseReturnStatement(bool* ok) { 2509 Statement* Parser::ParseReturnStatement(bool* ok) {
2517 // ReturnStatement :: 2510 // ReturnStatement ::
2518 // 'return' Expression? ';' 2511 // 'return' Expression? ';'
2519 2512
2520 // Consume the return token. It is necessary to do that before 2513 // Consume the return token. It is necessary to do that before
2521 // reporting any errors on it, because of the way errors are 2514 // reporting any errors on it, because of the way errors are
2522 // reported (underlining). 2515 // reported (underlining).
2523 Expect(Token::RETURN, CHECK_OK); 2516 Expect(Token::RETURN, CHECK_OK);
2524 int pos = position(); 2517 Scanner::Location loc = scanner()->location();
2525 2518
2526 Token::Value tok = peek(); 2519 Token::Value tok = peek();
2527 Statement* result; 2520 Statement* result;
2528 Expression* return_value; 2521 Expression* return_value;
2529 if (scanner()->HasAnyLineTerminatorBeforeNext() || 2522 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
2530 tok == Token::SEMICOLON || 2523 tok == Token::SEMICOLON ||
2531 tok == Token::RBRACE || 2524 tok == Token::RBRACE ||
2532 tok == Token::EOS) { 2525 tok == Token::EOS) {
2533 return_value = GetLiteralUndefined(position()); 2526 return_value = GetLiteralUndefined(position());
2534 } else { 2527 } else {
2535 return_value = ParseExpression(true, CHECK_OK); 2528 return_value = ParseExpression(true, CHECK_OK);
2536 } 2529 }
2537 ExpectSemicolon(CHECK_OK); 2530 ExpectSemicolon(CHECK_OK);
2538 if (is_generator()) { 2531 if (is_generator()) {
2539 Expression* generator = factory()->NewVariableProxy( 2532 Expression* generator = factory()->NewVariableProxy(
2540 function_state_->generator_object_variable()); 2533 function_state_->generator_object_variable());
2541 Expression* yield = factory()->NewYield( 2534 Expression* yield = factory()->NewYield(
2542 generator, return_value, Yield::FINAL, pos); 2535 generator, return_value, Yield::FINAL, loc.beg_pos);
2543 result = factory()->NewExpressionStatement(yield, pos); 2536 result = factory()->NewExpressionStatement(yield, loc.beg_pos);
2544 } else { 2537 } else {
2545 result = factory()->NewReturnStatement(return_value, pos); 2538 result = factory()->NewReturnStatement(return_value, loc.beg_pos);
2546 } 2539 }
2547 2540
2548 // An ECMAScript program is considered syntactically incorrect if it 2541 Scope* decl_scope = scope_->DeclarationScope();
2549 // contains a return statement that is not within the body of a 2542 if (decl_scope->is_global_scope() || decl_scope->is_eval_scope()) {
2550 // function. See ECMA-262, section 12.9, page 67. 2543 ReportMessageAt(loc, "illegal_return");
2551 // 2544 *ok = false;
2552 // To be consistent with KJS we report the syntax error at runtime. 2545 return NULL;
2553 Scope* declaration_scope = scope_->DeclarationScope();
2554 if (declaration_scope->is_global_scope() ||
2555 declaration_scope->is_eval_scope()) {
2556 Expression* throw_error =
2557 NewThrowSyntaxError("illegal_return", Handle<Object>::null(), pos);
2558 return factory()->NewExpressionStatement(throw_error, pos);
2559 } 2546 }
2560 return result; 2547 return result;
2561 } 2548 }
2562 2549
2563 2550
2564 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) { 2551 Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
2565 // WithStatement :: 2552 // WithStatement ::
2566 // 'with' '(' Expression ')' Statement 2553 // 'with' '(' Expression ')' Statement
2567 2554
2568 Expect(Token::WITH, CHECK_OK); 2555 Expect(Token::WITH, CHECK_OK);
(...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after
3662 } 3649 }
3663 3650
3664 3651
3665 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { 3652 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
3666 Declaration* decl = scope->CheckConflictingVarDeclarations(); 3653 Declaration* decl = scope->CheckConflictingVarDeclarations();
3667 if (decl != NULL) { 3654 if (decl != NULL) {
3668 // In harmony mode we treat conflicting variable bindinds as early 3655 // In harmony mode we treat conflicting variable bindinds as early
3669 // errors. See ES5 16 for a definition of early errors. 3656 // errors. See ES5 16 for a definition of early errors.
3670 Handle<String> name = decl->proxy()->name(); 3657 Handle<String> name = decl->proxy()->name();
3671 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); 3658 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
3672 const char* elms[2] = { "Variable", c_string.get() }; 3659 const char* elms[1] = { c_string.get() };
3673 Vector<const char*> args(elms, 2); 3660 Vector<const char*> args(elms, 1);
3674 int position = decl->proxy()->position(); 3661 int position = decl->proxy()->position();
3675 Scanner::Location location = position == RelocInfo::kNoPosition 3662 Scanner::Location location = position == RelocInfo::kNoPosition
3676 ? Scanner::Location::invalid() 3663 ? Scanner::Location::invalid()
3677 : Scanner::Location(position, position + 1); 3664 : Scanner::Location(position, position + 1);
3678 ParserTraits::ReportMessageAt(location, "redeclaration", args); 3665 ParserTraits::ReportMessageAt(location, "var_redeclaration", args);
3679 *ok = false; 3666 *ok = false;
3680 } 3667 }
3681 } 3668 }
3682 3669
3683 3670
3684 // ---------------------------------------------------------------------------- 3671 // ----------------------------------------------------------------------------
3685 // Parser support 3672 // Parser support
3686 3673
3687 3674
3688 bool Parser::TargetStackContainsLabel(Handle<String> label) { 3675 bool Parser::TargetStackContainsLabel(Handle<String> label) {
(...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after
4689 ASSERT(info()->isolate()->has_pending_exception()); 4676 ASSERT(info()->isolate()->has_pending_exception());
4690 } else { 4677 } else {
4691 result = ParseProgram(); 4678 result = ParseProgram();
4692 } 4679 }
4693 } 4680 }
4694 info()->SetFunction(result); 4681 info()->SetFunction(result);
4695 return (result != NULL); 4682 return (result != NULL);
4696 } 4683 }
4697 4684
4698 } } // namespace v8::internal 4685 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | src/runtime.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698