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

Side by Side Diff: runtime/vm/parser.cc

Issue 10825140: Add check for duplicate field initialization (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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 | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 ErrorMsg(supercall_pos, 1602 ErrorMsg(supercall_pos,
1603 "invalid arguments passed to super class constructor '%s': %s", 1603 "invalid arguments passed to super class constructor '%s': %s",
1604 ctor_name.ToCString(), 1604 ctor_name.ToCString(),
1605 error_message.ToCString()); 1605 error_message.ToCString());
1606 } 1606 }
1607 CheckFunctionIsCallable(supercall_pos, super_ctor); 1607 CheckFunctionIsCallable(supercall_pos, super_ctor);
1608 return new StaticCallNode(supercall_pos, super_ctor, arguments); 1608 return new StaticCallNode(supercall_pos, super_ctor, arguments);
1609 } 1609 }
1610 1610
1611 1611
1612 AstNode* Parser::ParseInitializer(const Class& cls, LocalVariable* receiver) { 1612 AstNode* Parser::ParseInitializer(const Class& cls,
1613 LocalVariable* receiver,
1614 GrowableArray<Field*>* initialized_fields) {
1613 TRACE_PARSER("ParseInitializer"); 1615 TRACE_PARSER("ParseInitializer");
1614 const intptr_t field_pos = TokenPos(); 1616 const intptr_t field_pos = TokenPos();
1615 if (CurrentToken() == Token::kTHIS) { 1617 if (CurrentToken() == Token::kTHIS) {
1616 ConsumeToken(); 1618 ConsumeToken();
1617 ExpectToken(Token::kPERIOD); 1619 ExpectToken(Token::kPERIOD);
1618 } 1620 }
1619 const String& field_name = *ExpectIdentifier("field name expected"); 1621 const String& field_name = *ExpectIdentifier("field name expected");
1620 ExpectToken(Token::kASSIGN); 1622 ExpectToken(Token::kASSIGN);
1621 1623
1622 const bool saved_mode = SetAllowFunctionLiterals(false); 1624 const bool saved_mode = SetAllowFunctionLiterals(false);
1623 // "this" must not be accessible in initializer expressions. 1625 // "this" must not be accessible in initializer expressions.
1624 receiver->set_invisible(true); 1626 receiver->set_invisible(true);
1625 AstNode* init_expr = ParseConditionalExpr(); 1627 AstNode* init_expr = ParseConditionalExpr();
1626 receiver->set_invisible(false); 1628 receiver->set_invisible(false);
1627 SetAllowFunctionLiterals(saved_mode); 1629 SetAllowFunctionLiterals(saved_mode);
1628 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); 1630 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
1629 if (field.IsNull()) { 1631 if (field.IsNull()) {
1630 ErrorMsg(field_pos, "unresolved reference to instance field '%s'", 1632 ErrorMsg(field_pos, "unresolved reference to instance field '%s'",
1631 field_name.ToCString()); 1633 field_name.ToCString());
1632 } 1634 }
1635 CheckDuplicateFieldInit(field_pos, initialized_fields, &field);
1633 AstNode* instance = new LoadLocalNode(field_pos, *receiver); 1636 AstNode* instance = new LoadLocalNode(field_pos, *receiver);
1634 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); 1637 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr);
1635 } 1638 }
1636 1639
1637 1640
1638 void Parser::CheckConstFieldsInitialized(const Class& cls) { 1641 void Parser::CheckConstFieldsInitialized(const Class& cls) {
1639 const Array& fields = Array::Handle(cls.fields()); 1642 const Array& fields = Array::Handle(cls.fields());
1640 Field& field = Field::Handle(); 1643 Field& field = Field::Handle();
1641 SequenceNode* initializers = current_block_->statements; 1644 SequenceNode* initializers = current_block_->statements;
1642 for (int field_num = 0; field_num < fields.Length(); field_num++) { 1645 for (int field_num = 0; field_num < fields.Length(); field_num++) {
(...skipping 21 matching lines...) Expand all
1664 } 1667 }
1665 1668
1666 1669
1667 struct FieldInitExpression { 1670 struct FieldInitExpression {
1668 Field* inst_field; 1671 Field* inst_field;
1669 AstNode* expr; 1672 AstNode* expr;
1670 }; 1673 };
1671 1674
1672 1675
1673 void Parser::ParseInitializedInstanceFields(const Class& cls, 1676 void Parser::ParseInitializedInstanceFields(const Class& cls,
1674 GrowableArray<FieldInitExpression>* initializers) { 1677 GrowableArray<FieldInitExpression>* initializers,
1678 GrowableArray<Field*>* initialized_fields) {
1675 TRACE_PARSER("ParseInitializedInstanceFields"); 1679 TRACE_PARSER("ParseInitializedInstanceFields");
1676 const Array& fields = Array::Handle(cls.fields()); 1680 const Array& fields = Array::Handle(cls.fields());
1677 Field& f = Field::Handle(); 1681 Field& f = Field::Handle();
1678 const intptr_t saved_pos = TokenPos(); 1682 const intptr_t saved_pos = TokenPos();
1679 for (int i = 0; i < fields.Length(); i++) { 1683 for (int i = 0; i < fields.Length(); i++) {
1680 f ^= fields.At(i); 1684 f ^= fields.At(i);
1681 if (!f.is_static() && f.has_initializer()) { 1685 if (!f.is_static() && f.has_initializer()) {
1682 Field& field = Field::ZoneHandle(); 1686 Field& field = Field::ZoneHandle();
1683 field ^= fields.At(i); 1687 field ^= fields.At(i);
1688 if (field.is_final()) {
1689 // Final fields with initializer expression may not be initialized
1690 // again by constructors. Remember that this field is already
1691 // initialized.
1692 initialized_fields->Add(&field);
1693 }
1684 intptr_t field_pos = field.token_pos(); 1694 intptr_t field_pos = field.token_pos();
1685 SetPosition(field_pos); 1695 SetPosition(field_pos);
1686 ASSERT(IsIdentifier()); 1696 ASSERT(IsIdentifier());
1687 ConsumeToken(); 1697 ConsumeToken();
1688 ExpectToken(Token::kASSIGN); 1698 ExpectToken(Token::kASSIGN);
1699 // TODO(hausner): Allow non-const expressions here for final fields.
1689 AstNode* init_expr = ParseConstExpr(); 1700 AstNode* init_expr = ParseConstExpr();
1690 ASSERT(init_expr != NULL); 1701 ASSERT(init_expr != NULL);
1691 FieldInitExpression initializer; 1702 FieldInitExpression initializer;
1692 initializer.inst_field = &field; 1703 initializer.inst_field = &field;
1693 initializer.expr = init_expr; 1704 initializer.expr = init_expr;
1694 initializers->Add(initializer); 1705 initializers->Add(initializer);
1695 } 1706 }
1696 } 1707 }
1697 SetPosition(saved_pos); 1708 SetPosition(saved_pos);
1698 } 1709 }
1699 1710
1700 1711
1701 void Parser::ParseInitializers(const Class& cls, LocalVariable* receiver) { 1712 void Parser::CheckDuplicateFieldInit(intptr_t init_pos,
1713 GrowableArray<Field*>* initialized_fields,
1714 Field* field) {
1715 ASSERT(!field->is_static());
1716 for (int i = 0; i < initialized_fields->length(); i++) {
1717 Field* initialized_field = (*initialized_fields)[i];
1718 if (initialized_field->raw() == field->raw()) {
1719 ErrorMsg(init_pos,
1720 "duplicate initialization for field %s",
1721 String::Handle(field->name()).ToCString());
1722 }
1723 }
1724 initialized_fields->Add(field);
1725 }
1726
1727
1728 void Parser::ParseInitializers(const Class& cls,
1729 LocalVariable* receiver,
1730 GrowableArray<Field*>* initialized_fields) {
1702 TRACE_PARSER("ParseInitializers"); 1731 TRACE_PARSER("ParseInitializers");
1703 bool super_init_seen = false; 1732 bool super_init_seen = false;
1704 if (CurrentToken() == Token::kCOLON) { 1733 if (CurrentToken() == Token::kCOLON) {
1705 if ((LookaheadToken(1) == Token::kTHIS) && 1734 if ((LookaheadToken(1) == Token::kTHIS) &&
1706 ((LookaheadToken(2) == Token::kLPAREN) || 1735 ((LookaheadToken(2) == Token::kLPAREN) ||
1707 ((LookaheadToken(2) == Token::kPERIOD) && 1736 ((LookaheadToken(2) == Token::kPERIOD) &&
1708 (LookaheadToken(4) == Token::kLPAREN)))) { 1737 (LookaheadToken(4) == Token::kLPAREN)))) {
1709 // Either we see this(...) or this.xxx(...) which is a 1738 // Either we see this(...) or this.xxx(...) which is a
1710 // redirected constructor. We don't need to check whether 1739 // redirected constructor. We don't need to check whether
1711 // const fields are initialized. The other constructor will 1740 // const fields are initialized. The other constructor will
1712 // guarantee that. 1741 // guarantee that.
1713 ConsumeToken(); // Colon. 1742 ConsumeToken(); // Colon.
1714 ParseConstructorRedirection(cls, receiver); 1743 ParseConstructorRedirection(cls, receiver);
1715 return; 1744 return;
1716 } 1745 }
1717 do { 1746 do {
1718 ConsumeToken(); // Colon or comma. 1747 ConsumeToken(); // Colon or comma.
1719 AstNode* init_statement; 1748 AstNode* init_statement;
1720 if (CurrentToken() == Token::kSUPER) { 1749 if (CurrentToken() == Token::kSUPER) {
1721 if (super_init_seen) { 1750 if (super_init_seen) {
1722 ErrorMsg("duplicate call to super constructor"); 1751 ErrorMsg("duplicate call to super constructor");
1723 } 1752 }
1724 init_statement = ParseSuperInitializer(cls, receiver); 1753 init_statement = ParseSuperInitializer(cls, receiver);
1725 super_init_seen = true; 1754 super_init_seen = true;
1726 } else { 1755 } else {
1727 init_statement = ParseInitializer(cls, receiver); 1756 init_statement = ParseInitializer(cls, receiver, initialized_fields);
1728 } 1757 }
1729 current_block_->statements->Add(init_statement); 1758 current_block_->statements->Add(init_statement);
1730 } while (CurrentToken() == Token::kCOMMA); 1759 } while (CurrentToken() == Token::kCOMMA);
1731 } 1760 }
1732 if (!super_init_seen) { 1761 if (!super_init_seen) {
1733 // Generate implicit super() if we haven't seen an explicit super call 1762 // Generate implicit super() if we haven't seen an explicit super call
1734 // or constructor redirection. 1763 // or constructor redirection.
1735 GenerateSuperConstructorCall(cls, receiver); 1764 GenerateSuperConstructorCall(cls, receiver);
1736 } 1765 }
1737 CheckConstFieldsInitialized(cls); 1766 CheckConstFieldsInitialized(cls);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) { 1821 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
1793 ASSERT(func.IsConstructor()); 1822 ASSERT(func.IsConstructor());
1794 const intptr_t ctor_pos = TokenPos(); 1823 const intptr_t ctor_pos = TokenPos();
1795 1824
1796 // Implicit 'this' is the only parameter/local variable. 1825 // Implicit 'this' is the only parameter/local variable.
1797 OpenFunctionBlock(func); 1826 OpenFunctionBlock(func);
1798 1827
1799 // Parse expressions of instance fields that have an explicit 1828 // Parse expressions of instance fields that have an explicit
1800 // initializers. 1829 // initializers.
1801 GrowableArray<FieldInitExpression> initializers; 1830 GrowableArray<FieldInitExpression> initializers;
1831 GrowableArray<Field*> initialized_fields;
1802 Class& cls = Class::Handle(func.owner()); 1832 Class& cls = Class::Handle(func.owner());
1803 ParseInitializedInstanceFields(cls, &initializers); 1833 ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
1804 1834
1805 LocalVariable* receiver = new LocalVariable( 1835 LocalVariable* receiver = new LocalVariable(
1806 ctor_pos, 1836 ctor_pos,
1807 String::ZoneHandle(Symbols::This()), 1837 String::ZoneHandle(Symbols::This()),
1808 Type::ZoneHandle(Type::DynamicType())); 1838 Type::ZoneHandle(Type::DynamicType()));
1809 current_block_->scope->AddVariable(receiver); 1839 current_block_->scope->AddVariable(receiver);
1810 1840
1811 LocalVariable* phase_parameter = new LocalVariable( 1841 LocalVariable* phase_parameter = new LocalVariable(
1812 ctor_pos, 1842 ctor_pos,
1813 String::ZoneHandle(Symbols::PhaseParameter()), 1843 String::ZoneHandle(Symbols::PhaseParameter()),
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1884 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); 1914 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
1885 ASSERT(func.NumberOfParameters() == params.parameters->length()); 1915 ASSERT(func.NumberOfParameters() == params.parameters->length());
1886 1916
1887 // Initialize instance fields that have an explicit initializer expression. 1917 // Initialize instance fields that have an explicit initializer expression.
1888 // This has to be done before code for field initializer parameters 1918 // This has to be done before code for field initializer parameters
1889 // is generated. 1919 // is generated.
1890 // NB: the instance field initializers have to be compiled before 1920 // NB: the instance field initializers have to be compiled before
1891 // the parameters are added to the scope, so that a parameter 1921 // the parameters are added to the scope, so that a parameter
1892 // name cannot shadow a name used in the field initializer expression. 1922 // name cannot shadow a name used in the field initializer expression.
1893 GrowableArray<FieldInitExpression> initializers; 1923 GrowableArray<FieldInitExpression> initializers;
1894 ParseInitializedInstanceFields(cls, &initializers); 1924 GrowableArray<Field*> initialized_fields;
1925 ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
1895 1926
1896 // Now populate function scope with the formal parameters. 1927 // Now populate function scope with the formal parameters.
1897 AddFormalParamsToScope(&params, current_block_->scope); 1928 AddFormalParamsToScope(&params, current_block_->scope);
1898 LocalVariable* receiver = current_block_->scope->VariableAt(0); 1929 LocalVariable* receiver = current_block_->scope->VariableAt(0);
1899 1930
1900 // Now that the "this" parameter is in scope, we can generate the code 1931 // Now that the "this" parameter is in scope, we can generate the code
1901 // to store the initializer expressions in the respective instance fields. 1932 // to store the initializer expressions in the respective instance fields.
1902 // We do this before the field parameters and the initializers from the 1933 // We do this before the field parameters and the initializers from the
1903 // constructor's initializer list get compiled. 1934 // constructor's initializer list get compiled.
1904 OpenBlock(); 1935 OpenBlock();
(...skipping 14 matching lines...) Expand all
1919 for (int i = 0; i < params.parameters->length(); i++) { 1950 for (int i = 0; i < params.parameters->length(); i++) {
1920 ParamDesc& param = (*params.parameters)[i]; 1951 ParamDesc& param = (*params.parameters)[i];
1921 if (param.is_field_initializer) { 1952 if (param.is_field_initializer) {
1922 const String& field_name = *param.name; 1953 const String& field_name = *param.name;
1923 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); 1954 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
1924 if (field.IsNull()) { 1955 if (field.IsNull()) {
1925 ErrorMsg(param.name_pos, 1956 ErrorMsg(param.name_pos,
1926 "unresolved reference to instance field '%s'", 1957 "unresolved reference to instance field '%s'",
1927 field_name.ToCString()); 1958 field_name.ToCString());
1928 } 1959 }
1960 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field);
1929 AstNode* instance = new LoadLocalNode(param.name_pos, *receiver); 1961 AstNode* instance = new LoadLocalNode(param.name_pos, *receiver);
1930 LocalVariable* p = 1962 LocalVariable* p =
1931 current_block_->scope->LookupVariable(*param.name, false); 1963 current_block_->scope->LookupVariable(*param.name, false);
1932 ASSERT(p != NULL); 1964 ASSERT(p != NULL);
1933 // Initializing formals cannot be used in the explicit initializer 1965 // Initializing formals cannot be used in the explicit initializer
1934 // list, nor can they be used in the constructor body. 1966 // list, nor can they be used in the constructor body.
1935 // Thus, make the parameter invisible. 1967 // Thus, make the parameter invisible.
1936 p->set_invisible(true); 1968 p->set_invisible(true);
1937 AstNode* value = new LoadLocalNode(param.name_pos, *p); 1969 AstNode* value = new LoadLocalNode(param.name_pos, *p);
1938 AstNode* initializer = new StoreInstanceFieldNode( 1970 AstNode* initializer = new StoreInstanceFieldNode(
1939 param.name_pos, instance, field, value); 1971 param.name_pos, instance, field, value);
1940 current_block_->statements->Add(initializer); 1972 current_block_->statements->Add(initializer);
1941 } 1973 }
1942 } 1974 }
1943 } 1975 }
1944 1976
1945 // Now parse the explicit initializer list or constructor redirection. 1977 // Now parse the explicit initializer list or constructor redirection.
1946 ParseInitializers(cls, receiver); 1978 ParseInitializers(cls, receiver, &initialized_fields);
1947 1979
1948 SequenceNode* init_statements = CloseBlock(); 1980 SequenceNode* init_statements = CloseBlock();
1949 if (init_statements->length() > 0) { 1981 if (init_statements->length() > 0) {
1950 // Generate guard around the initializer code. 1982 // Generate guard around the initializer code.
1951 LocalVariable* phase_param = LookupPhaseParameter(); 1983 LocalVariable* phase_param = LookupPhaseParameter();
1952 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param); 1984 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param);
1953 AstNode* phase_check = new BinaryOpNode( 1985 AstNode* phase_check = new BinaryOpNode(
1954 TokenPos(), Token::kBIT_AND, phase_value, 1986 TokenPos(), Token::kBIT_AND, phase_value,
1955 new LiteralNode(TokenPos(), 1987 new LiteralNode(TokenPos(),
1956 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); 1988 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit))));
(...skipping 6884 matching lines...) Expand 10 before | Expand all | Expand 10 after
8841 void Parser::SkipQualIdent() { 8873 void Parser::SkipQualIdent() {
8842 ASSERT(IsIdentifier()); 8874 ASSERT(IsIdentifier());
8843 ConsumeToken(); 8875 ConsumeToken();
8844 if (CurrentToken() == Token::kPERIOD) { 8876 if (CurrentToken() == Token::kPERIOD) {
8845 ConsumeToken(); // Consume the kPERIOD token. 8877 ConsumeToken(); // Consume the kPERIOD token.
8846 ExpectIdentifier("identifier expected after '.'"); 8878 ExpectIdentifier("identifier expected after '.'");
8847 } 8879 }
8848 } 8880 }
8849 8881
8850 } // namespace dart 8882 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698