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

Side by Side Diff: src/preparser.cc

Issue 1084983002: [strong] Implement static restrictions on switch statement (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix scope issue Created 5 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
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <cmath> 5 #include <cmath>
6 6
7 #include "src/allocation.h" 7 #include "src/allocation.h"
8 #include "src/base/logging.h" 8 #include "src/base/logging.h"
9 #include "src/conversions-inl.h" 9 #include "src/conversions-inl.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 if (!*ok) return Statement::Default(); \ 228 if (!*ok) return Statement::Default(); \
229 ((void)0 229 ((void)0
230 #define DUMMY ) // to make indentation work 230 #define DUMMY ) // to make indentation work
231 #undef DUMMY 231 #undef DUMMY
232 232
233 233
234 PreParser::Statement PreParser::ParseStatement(bool* ok) { 234 PreParser::Statement PreParser::ParseStatement(bool* ok) {
235 // Statement :: 235 // Statement ::
236 // EmptyStatement 236 // EmptyStatement
237 // ... 237 // ...
238
239 if (peek() == Token::SEMICOLON) {
240 Next();
241 return Statement::Default();
242 }
238 return ParseSubStatement(ok); 243 return ParseSubStatement(ok);
239 } 244 }
240 245
241 246
242 PreParser::Statement PreParser::ParseSubStatement(bool* ok) { 247 PreParser::Statement PreParser::ParseSubStatement(bool* ok) {
243 // Statement :: 248 // Statement ::
244 // Block 249 // Block
245 // VariableStatement 250 // VariableStatement
246 // EmptyStatement 251 // EmptyStatement
247 // ExpressionStatement 252 // ExpressionStatement
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 393
389 394
390 PreParser::Statement PreParser::ParseBlock(bool* ok) { 395 PreParser::Statement PreParser::ParseBlock(bool* ok) {
391 // Block :: 396 // Block ::
392 // '{' Statement* '}' 397 // '{' Statement* '}'
393 398
394 // Note that a Block does not introduce a new execution scope! 399 // Note that a Block does not introduce a new execution scope!
395 // (ECMA-262, 3rd, 12.2) 400 // (ECMA-262, 3rd, 12.2)
396 // 401 //
397 Expect(Token::LBRACE, CHECK_OK); 402 Expect(Token::LBRACE, CHECK_OK);
403 Statement final = Statement::Default();
398 while (peek() != Token::RBRACE) { 404 while (peek() != Token::RBRACE) {
399 if (is_strict(language_mode())) { 405 if (is_strict(language_mode())) {
400 ParseStatementListItem(CHECK_OK); 406 final = ParseStatementListItem(CHECK_OK);
401 } else { 407 } else {
402 ParseStatement(CHECK_OK); 408 final = ParseStatement(CHECK_OK);
403 } 409 }
404 } 410 }
405 Expect(Token::RBRACE, ok); 411 Expect(Token::RBRACE, ok);
406 return Statement::Default(); 412 return final;
407 } 413 }
408 414
409 415
410 PreParser::Statement PreParser::ParseVariableStatement( 416 PreParser::Statement PreParser::ParseVariableStatement(
411 VariableDeclarationContext var_context, 417 VariableDeclarationContext var_context,
412 bool* ok) { 418 bool* ok) {
413 // VariableStatement :: 419 // VariableStatement ::
414 // VariableDeclarations ';' 420 // VariableDeclarations ';'
415 421
416 Statement result = ParseVariableDeclarations(var_context, nullptr, nullptr, 422 Statement result = ParseVariableDeclarations(var_context, nullptr, nullptr,
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 // Even if the expression starts with an identifier, it is not necessarily an 544 // Even if the expression starts with an identifier, it is not necessarily an
539 // identifier. For example, "foo + bar" starts with an identifier but is not 545 // identifier. For example, "foo + bar" starts with an identifier but is not
540 // an identifier. 546 // an identifier.
541 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) { 547 if (starts_with_identifier && expr.IsIdentifier() && peek() == Token::COLON) {
542 // Expression is a single identifier, and not, e.g., a parenthesized 548 // Expression is a single identifier, and not, e.g., a parenthesized
543 // identifier. 549 // identifier.
544 DCHECK(!expr.AsIdentifier().IsFutureReserved()); 550 DCHECK(!expr.AsIdentifier().IsFutureReserved());
545 DCHECK(is_sloppy(language_mode()) || 551 DCHECK(is_sloppy(language_mode()) ||
546 !IsFutureStrictReserved(expr.AsIdentifier())); 552 !IsFutureStrictReserved(expr.AsIdentifier()));
547 Consume(Token::COLON); 553 Consume(Token::COLON);
548 return ParseStatement(ok); 554 Statement statement = ParseStatement(ok);
555 if (statement.IsJumpStatement()) {
rossberg 2015/04/15 19:56:34 Nit: Use return with ?:
conradw 2015/04/16 10:59:57 Done.
556 return Statement::Default();
557 }
558 return statement;
549 // Preparsing is disabled for extensions (because the extension details 559 // Preparsing is disabled for extensions (because the extension details
550 // aren't passed to lazily compiled functions), so we don't 560 // aren't passed to lazily compiled functions), so we don't
551 // accept "native function" in the preparser. 561 // accept "native function" in the preparser.
552 } 562 }
553 // Parsed expression statement. 563 // Parsed expression statement.
554 // Detect attempts at 'let' declarations in sloppy mode. 564 // Detect attempts at 'let' declarations in sloppy mode.
555 if (peek() == Token::IDENTIFIER && is_sloppy(language_mode()) && 565 if (peek() == Token::IDENTIFIER && is_sloppy(language_mode()) &&
556 expr.IsIdentifier() && expr.AsIdentifier().IsLet()) { 566 expr.IsIdentifier() && expr.AsIdentifier().IsLet()) {
557 ReportMessage("sloppy_lexical", NULL); 567 ReportMessage("sloppy_lexical", NULL);
558 *ok = false; 568 *ok = false;
559 return Statement::Default(); 569 return Statement::Default();
560 } 570 }
561 ExpectSemicolon(CHECK_OK); 571 ExpectSemicolon(CHECK_OK);
562 return Statement::ExpressionStatement(expr); 572 return Statement::ExpressionStatement(expr);
563 } 573 }
564 574
565 575
566 PreParser::Statement PreParser::ParseIfStatement(bool* ok) { 576 PreParser::Statement PreParser::ParseIfStatement(bool* ok) {
567 // IfStatement :: 577 // IfStatement ::
568 // 'if' '(' Expression ')' Statement ('else' Statement)? 578 // 'if' '(' Expression ')' Statement ('else' Statement)?
569 579
570 Expect(Token::IF, CHECK_OK); 580 Expect(Token::IF, CHECK_OK);
571 Expect(Token::LPAREN, CHECK_OK); 581 Expect(Token::LPAREN, CHECK_OK);
572 ParseExpression(true, CHECK_OK); 582 ParseExpression(true, CHECK_OK);
573 Expect(Token::RPAREN, CHECK_OK); 583 Expect(Token::RPAREN, CHECK_OK);
574 ParseSubStatement(CHECK_OK); 584 Statement stat = ParseSubStatement(CHECK_OK);
575 if (peek() == Token::ELSE) { 585 if (peek() == Token::ELSE) {
576 Next(); 586 Next();
577 ParseSubStatement(CHECK_OK); 587 Statement else_stat = ParseSubStatement(CHECK_OK);
588 stat = (else_stat.IsJumpStatement()) ? stat : Statement::Default();
rossberg 2015/04/15 19:56:34 This doesn't seem quite right, since stat may be s
conradw 2015/04/16 10:59:57 Done.
589 } else {
590 stat = Statement::Default();
578 } 591 }
579 return Statement::Default(); 592 return stat;
580 } 593 }
581 594
582 595
583 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { 596 PreParser::Statement PreParser::ParseContinueStatement(bool* ok) {
584 // ContinueStatement :: 597 // ContinueStatement ::
585 // 'continue' [no line terminator] Identifier? ';' 598 // 'continue' [no line terminator] Identifier? ';'
586 599
587 Expect(Token::CONTINUE, CHECK_OK); 600 Expect(Token::CONTINUE, CHECK_OK);
588 Token::Value tok = peek(); 601 Token::Value tok = peek();
589 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 602 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
590 tok != Token::SEMICOLON && 603 tok != Token::SEMICOLON &&
591 tok != Token::RBRACE && 604 tok != Token::RBRACE &&
592 tok != Token::EOS) { 605 tok != Token::EOS) {
593 // ECMA allows "eval" or "arguments" as labels even in strict mode. 606 // ECMA allows "eval" or "arguments" as labels even in strict mode.
594 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); 607 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
595 } 608 }
596 ExpectSemicolon(CHECK_OK); 609 ExpectSemicolon(CHECK_OK);
597 return Statement::Default(); 610 return Statement::Jump();
598 } 611 }
599 612
600 613
601 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { 614 PreParser::Statement PreParser::ParseBreakStatement(bool* ok) {
602 // BreakStatement :: 615 // BreakStatement ::
603 // 'break' [no line terminator] Identifier? ';' 616 // 'break' [no line terminator] Identifier? ';'
604 617
605 Expect(Token::BREAK, CHECK_OK); 618 Expect(Token::BREAK, CHECK_OK);
606 Token::Value tok = peek(); 619 Token::Value tok = peek();
607 if (!scanner()->HasAnyLineTerminatorBeforeNext() && 620 if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
608 tok != Token::SEMICOLON && 621 tok != Token::SEMICOLON &&
609 tok != Token::RBRACE && 622 tok != Token::RBRACE &&
610 tok != Token::EOS) { 623 tok != Token::EOS) {
611 // ECMA allows "eval" or "arguments" as labels even in strict mode. 624 // ECMA allows "eval" or "arguments" as labels even in strict mode.
612 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK); 625 ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
613 } 626 }
614 ExpectSemicolon(CHECK_OK); 627 ExpectSemicolon(CHECK_OK);
615 return Statement::Default(); 628 return Statement::Jump();
616 } 629 }
617 630
618 631
619 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { 632 PreParser::Statement PreParser::ParseReturnStatement(bool* ok) {
620 // ReturnStatement :: 633 // ReturnStatement ::
621 // 'return' [no line terminator] Expression? ';' 634 // 'return' [no line terminator] Expression? ';'
622 635
623 // Consume the return token. It is necessary to do before 636 // Consume the return token. It is necessary to do before
624 // reporting any errors on it, because of the way errors are 637 // reporting any errors on it, because of the way errors are
625 // reported (underlining). 638 // reported (underlining).
(...skipping 14 matching lines...) Expand all
640 i::IsConstructor(function_state_->kind())) { 653 i::IsConstructor(function_state_->kind())) {
641 int pos = peek_position(); 654 int pos = peek_position();
642 ReportMessageAt(Scanner::Location(pos, pos + 1), 655 ReportMessageAt(Scanner::Location(pos, pos + 1),
643 "strong_constructor_return_value"); 656 "strong_constructor_return_value");
644 *ok = false; 657 *ok = false;
645 return Statement::Default(); 658 return Statement::Default();
646 } 659 }
647 ParseExpression(true, CHECK_OK); 660 ParseExpression(true, CHECK_OK);
648 } 661 }
649 ExpectSemicolon(CHECK_OK); 662 ExpectSemicolon(CHECK_OK);
650 return Statement::Default(); 663 return Statement::Jump();
651 } 664 }
652 665
653 666
654 PreParser::Statement PreParser::ParseWithStatement(bool* ok) { 667 PreParser::Statement PreParser::ParseWithStatement(bool* ok) {
655 // WithStatement :: 668 // WithStatement ::
656 // 'with' '(' Expression ')' Statement 669 // 'with' '(' Expression ')' Statement
657 Expect(Token::WITH, CHECK_OK); 670 Expect(Token::WITH, CHECK_OK);
658 if (is_strict(language_mode())) { 671 if (is_strict(language_mode())) {
659 ReportMessageAt(scanner()->location(), "strict_mode_with"); 672 ReportMessageAt(scanner()->location(), "strict_mode_with");
660 *ok = false; 673 *ok = false;
(...skipping 23 matching lines...) Expand all
684 Token::Value token = peek(); 697 Token::Value token = peek();
685 while (token != Token::RBRACE) { 698 while (token != Token::RBRACE) {
686 if (token == Token::CASE) { 699 if (token == Token::CASE) {
687 Expect(Token::CASE, CHECK_OK); 700 Expect(Token::CASE, CHECK_OK);
688 ParseExpression(true, CHECK_OK); 701 ParseExpression(true, CHECK_OK);
689 } else { 702 } else {
690 Expect(Token::DEFAULT, CHECK_OK); 703 Expect(Token::DEFAULT, CHECK_OK);
691 } 704 }
692 Expect(Token::COLON, CHECK_OK); 705 Expect(Token::COLON, CHECK_OK);
693 token = peek(); 706 token = peek();
707 Statement statement = Statement::Jump();
694 while (token != Token::CASE && 708 while (token != Token::CASE &&
695 token != Token::DEFAULT && 709 token != Token::DEFAULT &&
696 token != Token::RBRACE) { 710 token != Token::RBRACE) {
697 ParseStatementListItem(CHECK_OK); 711 statement = ParseStatementListItem(CHECK_OK);
698 token = peek(); 712 token = peek();
699 } 713 }
714 if (is_strong(language_mode()) &&
715 !statement.IsJumpStatement()) {
rossberg 2015/04/15 19:56:34 Nit: stray line break But more importantly, don't
conradw 2015/04/16 10:59:57 Done, and I made the same mistake in parser
716 ReportMessageAt(scanner()->location(), "strong_switch_fallthrough");
717 *ok = false;
718 return Statement::Default();
719 }
700 } 720 }
701 Expect(Token::RBRACE, ok); 721 Expect(Token::RBRACE, ok);
702 return Statement::Default(); 722 return Statement::Default();
703 } 723 }
704 724
705 725
706 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { 726 PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
707 // DoStatement :: 727 // DoStatement ::
708 // 'do' Statement 'while' '(' Expression ')' ';' 728 // 'do' Statement 'while' '(' Expression ')' ';'
709 729
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 // 'throw' [no line terminator] Expression ';' 840 // 'throw' [no line terminator] Expression ';'
821 841
822 Expect(Token::THROW, CHECK_OK); 842 Expect(Token::THROW, CHECK_OK);
823 if (scanner()->HasAnyLineTerminatorBeforeNext()) { 843 if (scanner()->HasAnyLineTerminatorBeforeNext()) {
824 ReportMessageAt(scanner()->location(), "newline_after_throw"); 844 ReportMessageAt(scanner()->location(), "newline_after_throw");
825 *ok = false; 845 *ok = false;
826 return Statement::Default(); 846 return Statement::Default();
827 } 847 }
828 ParseExpression(true, CHECK_OK); 848 ParseExpression(true, CHECK_OK);
829 ExpectSemicolon(ok); 849 ExpectSemicolon(ok);
830 return Statement::Default(); 850 return Statement::Jump();
831 } 851 }
832 852
833 853
834 PreParser::Statement PreParser::ParseTryStatement(bool* ok) { 854 PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
835 // TryStatement :: 855 // TryStatement ::
836 // 'try' Block Catch 856 // 'try' Block Catch
837 // 'try' Block Finally 857 // 'try' Block Finally
838 // 'try' Block Catch Finally 858 // 'try' Block Catch Finally
839 // 859 //
840 // Catch :: 860 // Catch ::
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 1065
1046 DCHECK(!spread_pos.IsValid()); 1066 DCHECK(!spread_pos.IsValid());
1047 1067
1048 return Expression::Default(); 1068 return Expression::Default();
1049 } 1069 }
1050 1070
1051 #undef CHECK_OK 1071 #undef CHECK_OK
1052 1072
1053 1073
1054 } } // v8::internal 1074 } } // v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698