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

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

Issue 8286003: Create implicit super constructor call if necessary (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 1181 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 1192
1193 ArgumentListNode* setter_arguments = new ArgumentListNode(field_pos); 1193 ArgumentListNode* setter_arguments = new ArgumentListNode(field_pos);
1194 setter_arguments->Add(implicit_argument); 1194 setter_arguments->Add(implicit_argument);
1195 setter_arguments->Add(value); 1195 setter_arguments->Add(value);
1196 super_field = new StaticCallNode(field_pos, super_setter, setter_arguments); 1196 super_field = new StaticCallNode(field_pos, super_setter, setter_arguments);
1197 } 1197 }
1198 return super_field; 1198 return super_field;
1199 } 1199 }
1200 1200
1201 1201
1202 void Parser::GenerateSuperInitializerCall(const Class& cls,
1203 LocalVariable* receiver) {
1204 const intptr_t supercall_pos = token_index_;
1205 const Class& super_class = Class::Handle(cls.SuperClass());
1206 // Omit the implicit super() if there is no super class (i.e.
1207 // we're not compiling class Object), or if the super class is an
1208 // artificially generated "wrapper class" that has no constructor.
1209 if (super_class.IsNull() || (super_class.num_native_fields() > 0)) {
1210 return;
1211 }
1212 String& ctor_name = String::Handle(super_class.Name());
1213 String& ctor_suffix = String::Handle(String::NewSymbol("."));
1214 ctor_name = String::Concat(ctor_name, ctor_suffix);
1215 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
1216 // implicit 'this' parameter is the only argument.
1217 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, *receiver);
1218 arguments->Add(implicit_argument);
1219 const Function& super_ctor = Function::ZoneHandle(
1220 super_class.LookupConstructor(ctor_name));
1221 if (super_ctor.IsNull() ||
1222 !super_ctor.AreValidArguments(arguments->length(),
1223 arguments->names())) {
1224 ErrorMsg(supercall_pos,
1225 "unresolved implicit call to super constructor '%s()'",
1226 String::Handle(super_class.Name()).ToCString());
1227 }
1228 CheckFunctionIsCallable(supercall_pos, super_ctor);
1229 current_block_->statements->Add(
1230 new StaticCallNode(supercall_pos, super_ctor, arguments));
1231 }
1232
1233
1202 AstNode* Parser::ParseSuperInitializer(const Class& cls, 1234 AstNode* Parser::ParseSuperInitializer(const Class& cls,
1203 LocalVariable* receiver) { 1235 LocalVariable* receiver) {
1204 TRACE_PARSER("ParseSuperInitializer"); 1236 TRACE_PARSER("ParseSuperInitializer");
1205 ASSERT(CurrentToken() == Token::kSUPER); 1237 ASSERT(CurrentToken() == Token::kSUPER);
1206 const intptr_t supercall_pos = token_index_; 1238 const intptr_t supercall_pos = token_index_;
1207 ConsumeToken(); 1239 ConsumeToken();
1208 const Class& super_class = Class::Handle(cls.SuperClass()); 1240 const Class& super_class = Class::Handle(cls.SuperClass());
1209 ASSERT(!super_class.IsNull()); 1241 ASSERT(!super_class.IsNull());
1210 String& ctor_name = String::Handle(super_class.Name()); 1242 String& ctor_name = String::Handle(super_class.Name());
1211 String& ctor_suffix = String::Handle(String::NewSymbol(".")); 1243 String& ctor_suffix = String::Handle(String::NewSymbol("."));
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1321 FieldInitExpression initializer; 1353 FieldInitExpression initializer;
1322 initializer.inst_field = &field; 1354 initializer.inst_field = &field;
1323 initializer.expr = init_expr; 1355 initializer.expr = init_expr;
1324 initializers->Add(initializer); 1356 initializers->Add(initializer);
1325 } 1357 }
1326 } 1358 }
1327 SetPosition(saved_pos); 1359 SetPosition(saved_pos);
1328 } 1360 }
1329 1361
1330 1362
1331 void Parser::ParseInitializers(const Class& cls, LocalVariable* receiver) { 1363 void Parser::ParseInitializers(const Class& cls) {
1332 TRACE_PARSER("ParseInitializers"); 1364 TRACE_PARSER("ParseInitializers");
1333 AstNode* init_statement = NULL; 1365 LocalVariable* receiver = current_block_->scope->VariableAt(0);
1334 AstNode* super_init_statement = NULL; 1366 bool super_init_seen = false;
1335 // TODO(4995181): Allow super initializer to appear in any position 1367 if (CurrentToken() == Token::kCOLON) {
1336 // of the initializer list. 1368 ConsumeToken();
1337 if (CurrentToken() == Token::kSUPER) { 1369 if ((CurrentToken() == Token::kTHIS) &&
1338 super_init_statement = ParseSuperInitializer(cls, receiver); 1370 ((LookaheadToken(1) == Token::kLPAREN) ||
1339 } else { 1371 ((LookaheadToken(1) == Token::kPERIOD) &&
1340 init_statement = ParseInitializer(cls, receiver); 1372 (LookaheadToken(3) == Token::kLPAREN)))) {
1341 current_block_->statements->Add(init_statement); 1373 // Either we see this(...) or this.xxx(...) which is a
1374 // redirected constructor. We don't need to check whether
1375 // const fields are initialized. The other constructor will
1376 // guarantee that.
1377 ParseConstructorRedirection(cls, receiver);
1378 return;
1379 }
1380
1381 for (;;) {
regis 2011/10/13 19:32:29 If you do not consume the colon above (and increme
hausner 2011/10/13 20:24:09 Nice idea. Done.
1382 AstNode* init_statement = NULL;
1383 if (CurrentToken() == Token::kSUPER) {
1384 if (super_init_seen) {
1385 ErrorMsg("Duplicate call to super constructor");
1386 }
1387 init_statement = ParseSuperInitializer(cls, receiver);
1388 super_init_seen = true;
1389 } else {
1390 init_statement = ParseInitializer(cls, receiver);
1391 }
1392 current_block_->statements->Add(init_statement);
1393 if (CurrentToken() != Token::kCOMMA) {
1394 break;
1395 }
1396 ConsumeToken();
1397 }
1342 } 1398 }
1343 while (CurrentToken() == Token::kCOMMA) { 1399
1344 ConsumeToken(); 1400 // Generate implicit super() if we haven't seen an explicit super call
1345 init_statement = ParseInitializer(cls, receiver); 1401 // or constructor redirection.
1346 current_block_->statements->Add(init_statement); 1402 // Omit the implicit super() if there is no super class (i.e.
1403 // we're not compiling class Object), or if the super class is an
1404 // artificially generated "wrapper class" that has no constructor.
1405 if (!super_init_seen) {
1406 GenerateSuperInitializerCall(cls, receiver);
1347 } 1407 }
1348 // The call to super constructor is to be done after all initializers. 1408
1349 if (super_init_statement != NULL) { 1409 CheckConstFieldsInitialized(cls);
1350 current_block_->statements->Add(super_init_statement);
1351 }
1352 } 1410 }
1353 1411
1354 1412
1355 void Parser::ParseConstructorRedirection(const Class& cls, 1413 void Parser::ParseConstructorRedirection(const Class& cls,
1356 LocalVariable* receiver) { 1414 LocalVariable* receiver) {
1357 ASSERT(CurrentToken() == Token::kTHIS); 1415 ASSERT(CurrentToken() == Token::kTHIS);
1358 intptr_t call_pos = token_index_; 1416 intptr_t call_pos = token_index_;
1359 ConsumeToken(); 1417 ConsumeToken();
1360 String& ctor_name = String::Handle(cls.Name()); 1418 String& ctor_name = String::Handle(cls.Name());
1361 String& ctor_suffix = String::Handle(String::NewSymbol(".")); 1419 String& ctor_suffix = String::Handle(String::NewSymbol("."));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 const Field* field = initializers[i].inst_field; 1473 const Field* field = initializers[i].inst_field;
1416 AstNode* instance = new LoadLocalNode(field->token_index(), *receiver); 1474 AstNode* instance = new LoadLocalNode(field->token_index(), *receiver);
1417 AstNode* field_init = 1475 AstNode* field_init =
1418 new StoreInstanceFieldNode(field->token_index(), 1476 new StoreInstanceFieldNode(field->token_index(),
1419 instance, 1477 instance,
1420 *field, 1478 *field,
1421 initializers[i].expr); 1479 initializers[i].expr);
1422 current_block_->statements->Add(field_init); 1480 current_block_->statements->Add(field_init);
1423 } 1481 }
1424 1482
1425 // Super call to constructor of super class. 1483 GenerateSuperInitializerCall(cls, receiver);
1426 const Class& super_class = Class::Handle(cls.SuperClass());
1427 ASSERT(!super_class.IsNull());
1428 String& ctor_name = String::Handle(super_class.Name());
1429 String& ctor_suffix = String::Handle(String::NewSymbol("."));
1430 ctor_name = String::Concat(ctor_name, ctor_suffix);
1431 ctor_name = String::NewSymbol(ctor_name);
1432 ArgumentListNode* arguments = new ArgumentListNode(ctor_pos);
1433 AstNode* implicit_argument = new LoadLocalNode(ctor_pos, *receiver);
1434 arguments->Add(implicit_argument);
1435 const Function& super_ctor = Function::ZoneHandle(
1436 super_class.LookupConstructor(ctor_name));
1437 if (super_ctor.IsNull() ||
1438 !super_ctor.AreValidArgumentCounts(arguments->length(), 0)) {
1439 ErrorMsg(ctor_pos,
1440 "super class constructor '%s' not found",
1441 ctor_name.ToCString());
1442 }
1443 current_block_->statements->Add(
1444 new StaticCallNode(ctor_pos, super_ctor, arguments));
1445
1446 CheckConstFieldsInitialized(cls); 1484 CheckConstFieldsInitialized(cls);
1447 1485
1448 // Empty constructor body. 1486 // Empty constructor body.
1449 SequenceNode* statements = CloseBlock(); 1487 SequenceNode* statements = CloseBlock();
1450 return statements; 1488 return statements;
1451 } 1489 }
1452 1490
1453 1491
1454 // Parser is at the opening parenthesis of the formal parameter declaration 1492 // Parser is at the opening parenthesis of the formal parameter declaration
1455 // of function. Parse the formal parameters and code. 1493 // of function. Parse the formal parameters and code.
1456 SequenceNode* Parser::ParseFunc(const Function& func, 1494 SequenceNode* Parser::ParseFunc(const Function& func,
1457 Array& default_parameter_values) { 1495 Array& default_parameter_values) {
1458 if (IsLiteral("class")) { 1496 if (IsLiteral("class")) {
1459 // Special case: implicit constructor. There is no source text to 1497 // Special case: implicit constructor. There is no source text to
1460 // parse. We just build the sequence node by hand. 1498 // parse. We just build the sequence node by hand.
1461 return MakeImplicitConstructor(func); 1499 return MakeImplicitConstructor(func);
1462 } 1500 }
1463 1501
1502 const Class& cls = Class::Handle(func.owner());
1503 ASSERT(!cls.IsNull());
1504
1464 // Build local scope for function. 1505 // Build local scope for function.
1465 OpenFunctionBlock(func); 1506 OpenFunctionBlock(func);
1466 1507
1467 ParamList params; 1508 ParamList params;
1468 // Static functions do not have a receiver, except constructors, which are 1509 // Static functions do not have a receiver, except constructors, which are
1469 // passed the allocated but uninitialized instance to construct. 1510 // passed the allocated but uninitialized instance to construct.
1470 // An instance closure may capture and access the receiver, but via the 1511 // An instance closure may capture and access the receiver, but via the
1471 // context and not via the first formal parameter. 1512 // context and not via the first formal parameter.
1472 // The first parameter of a factory is the TypeArguments vector of the type 1513 // The first parameter of a factory is the TypeArguments vector of the type
1473 // of the instance to be allocated. We name this hidden parameter 'this'. 1514 // of the instance to be allocated. We name this hidden parameter 'this'.
(...skipping 21 matching lines...) Expand all
1495 1536
1496 // If this is a constructor, initialize instance fields that have an 1537 // If this is a constructor, initialize instance fields that have an
1497 // explicit initializer expression. This has to be done before code 1538 // explicit initializer expression. This has to be done before code
1498 // for field initializer parameters are is generated. 1539 // for field initializer parameters are is generated.
1499 // NB: the instance field initializers have to be compiled before 1540 // NB: the instance field initializers have to be compiled before
1500 // the parameters are added to the scope, so that a parameter 1541 // the parameters are added to the scope, so that a parameter
1501 // name cannot shadow a name used in the field initializer expression. 1542 // name cannot shadow a name used in the field initializer expression.
1502 1543
1503 GrowableArray<FieldInitExpression> initializers; 1544 GrowableArray<FieldInitExpression> initializers;
1504 if (func.IsConstructor()) { 1545 if (func.IsConstructor()) {
1505 Class& cls = Class::Handle(func.owner());
1506 ParseInitializedInstanceFields(cls, &initializers); 1546 ParseInitializedInstanceFields(cls, &initializers);
1507 } 1547 }
1508 1548
1509 // Now populate function scope with the formal parameters. 1549 // Now populate function scope with the formal parameters.
1510 AddFormalParamsToScope(&params, current_block_->scope); 1550 AddFormalParamsToScope(&params, current_block_->scope);
1511 1551
1512 // Now that the "this" parameter is in scope, we can generate the code 1552 // Now that the "this" parameter is in scope, we can generate the code
1513 // to strore the initializer expressions in the respective instance fields. 1553 // to strore the initializer expressions in the respective instance fields.
1514 // We do this before the field parameters and the initializers from the 1554 // We do this before the field parameters and the initializers from the
1515 // constuctor's initializer list get compiled. 1555 // constuctor's initializer list get compiled.
1516 if (initializers.length() > 0) { 1556 if (initializers.length() > 0) {
1517 LocalVariable* receiver = current_block_->scope->VariableAt(0); 1557 LocalVariable* receiver = current_block_->scope->VariableAt(0);
1518 for (int i = 0; i < initializers.length(); i++) { 1558 for (int i = 0; i < initializers.length(); i++) {
1519 const Field* field = initializers[i].inst_field; 1559 const Field* field = initializers[i].inst_field;
1520 AstNode* instance = new LoadLocalNode(field->token_index(), *receiver); 1560 AstNode* instance = new LoadLocalNode(field->token_index(), *receiver);
1521 AstNode* field_init = 1561 AstNode* field_init =
1522 new StoreInstanceFieldNode(field->token_index(), 1562 new StoreInstanceFieldNode(field->token_index(),
1523 instance, 1563 instance,
1524 *field, 1564 *field,
1525 initializers[i].expr); 1565 initializers[i].expr);
1526 current_block_->statements->Add(field_init); 1566 current_block_->statements->Add(field_init);
1527 } 1567 }
1528 } 1568 }
1529 1569
1530 // Turn formal field parameters into field initializers or report error 1570 // Turn formal field parameters into field initializers or report error
1531 // if the function is not a constructor 1571 // if the function is not a constructor
1532 if (params.has_field_initializer) { 1572 if (params.has_field_initializer) {
1533 LocalVariable* receiver = current_block_->scope->VariableAt(0); 1573 LocalVariable* receiver = current_block_->scope->VariableAt(0);
1534 Class& cls = Class::ZoneHandle(func.owner());
1535 for (int i = 0; i < params.parameters->length(); i++) { 1574 for (int i = 0; i < params.parameters->length(); i++) {
1536 ParamDesc& param = (*params.parameters)[i]; 1575 ParamDesc& param = (*params.parameters)[i];
1537 if (param.is_field_initializer) { 1576 if (param.is_field_initializer) {
1538 if (!func.IsConstructor()) { 1577 if (!func.IsConstructor()) {
1539 ErrorMsg(param.name_pos, 1578 ErrorMsg(param.name_pos,
1540 "field initializer only allowed in constructors"); 1579 "field initializer only allowed in constructors");
1541 } 1580 }
1542 1581
1543 const String& field_name = *param.name; 1582 const String& field_name = *param.name;
1544 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); 1583 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
(...skipping 10 matching lines...) Expand all
1555 ASSERT(p != NULL); 1594 ASSERT(p != NULL);
1556 AstNode* value = new LoadLocalNode(param.name_pos, *p); 1595 AstNode* value = new LoadLocalNode(param.name_pos, *p);
1557 AstNode* initializer = 1596 AstNode* initializer =
1558 new StoreInstanceFieldNode(param.name_pos, instance, field, value); 1597 new StoreInstanceFieldNode(param.name_pos, instance, field, value);
1559 current_block_->statements->Add(initializer); 1598 current_block_->statements->Add(initializer);
1560 } 1599 }
1561 } 1600 }
1562 } 1601 }
1563 1602
1564 if (func.IsConstructor()) { 1603 if (func.IsConstructor()) {
1565 Class& cls = Class::ZoneHandle(func.owner()); 1604 ParseInitializers(cls);
1566 bool initialized_check_needed = true;
1567 if (CurrentToken() == Token::kCOLON) {
1568 ConsumeToken();
1569 LocalVariable* receiver = current_block_->scope->VariableAt(0);
1570 ASSERT(receiver != NULL);
1571 if ((CurrentToken() == Token::kTHIS) &&
1572 ((LookaheadToken(1) == Token::kLPAREN) ||
1573 ((LookaheadToken(1) == Token::kPERIOD) &&
1574 (LookaheadToken(3) == Token::kLPAREN)))) {
1575 // Either we see this(...) or this.xxx(...) which is a
1576 // redirected constructor. We don't need to check whether
1577 // const fields are initialized. The other constructor will
1578 // guarantee that.
1579 initialized_check_needed = false;
1580 ParseConstructorRedirection(cls, receiver);
1581 } else {
1582 ParseInitializers(cls, receiver);
1583 }
1584 }
1585 if (initialized_check_needed) {
1586 CheckConstFieldsInitialized(cls);
1587 }
1588 } 1605 }
1589 1606
1590 if (current_block_->scope->function_level() > 0) { 1607 if (current_block_->scope->function_level() > 0) {
1591 // We are parsing, but not compiling, a local function. 1608 // We are parsing, but not compiling, a local function.
1592 // The instantiator may be required at run time for generic type checks or 1609 // The instantiator may be required at run time for generic type checks or
1593 // allocation of generic types. 1610 // allocation of generic types.
1594 if (current_class().IsParameterized() && 1611 if (current_class().IsParameterized() &&
1595 (!current_function().is_static() || 1612 (!current_function().is_static() ||
1596 current_function().IsInFactoryScope())) { 1613 current_function().IsInFactoryScope())) {
1597 // Make sure that the receiver of the enclosing instance function 1614 // Make sure that the receiver of the enclosing instance function
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1645 level++; 1662 level++;
1646 } else if (CurrentToken() == Token::kRPAREN) { 1663 } else if (CurrentToken() == Token::kRPAREN) {
1647 level--; 1664 level--;
1648 } 1665 }
1649 ConsumeToken(); 1666 ConsumeToken();
1650 } while ((level > 0) && (CurrentToken() != Token::kEOS)); 1667 } while ((level > 0) && (CurrentToken() != Token::kEOS));
1651 } 1668 }
1652 1669
1653 1670
1654 void Parser::SkipInitializers() { 1671 void Parser::SkipInitializers() {
1655 if (CurrentToken() == Token::kSUPER) { 1672 for (;;) {
regis 2011/10/13 19:32:29 Same comment here about a do loop instead of a for
hausner 2011/10/13 20:24:09 And done.
1673 if (CurrentToken() == Token::kSUPER) {
1674 ConsumeToken();
1675 if (CurrentToken() == Token::kPERIOD) {
1676 ConsumeToken();
1677 ExpectIdentifier("identifier expected");
1678 }
1679 if (CurrentToken() != Token::kLPAREN) {
1680 ErrorMsg("'(' expected");
1681 }
1682 SkipToMatchingParenthesis();
1683 } else {
1684 SkipIf(Token::kTHIS);
1685 SkipIf(Token::kPERIOD);
1686 ExpectIdentifier("identifier expected");
1687 ExpectToken(Token::kASSIGN);
1688 SetAllowFunctionLiterals(false);
1689 SkipExpr();
1690 SetAllowFunctionLiterals(true);
1691 }
1692 if (CurrentToken() != Token::kCOMMA) {
1693 break;
1694 }
1656 ConsumeToken(); 1695 ConsumeToken();
1657 if (CurrentToken() == Token::kPERIOD) {
1658 ConsumeToken();
1659 ExpectIdentifier("identifier expected");
1660 }
1661 if (CurrentToken() != Token::kLPAREN) {
1662 ErrorMsg("'(' expected");
1663 }
1664 SkipToMatchingParenthesis();
1665 } else {
1666 SkipIf(Token::kTHIS);
1667 SkipIf(Token::kPERIOD);
1668 ExpectIdentifier("identifier expected");
1669 ExpectToken(Token::kASSIGN);
1670 SetAllowFunctionLiterals(false);
1671 SkipExpr();
1672 SetAllowFunctionLiterals(true);
1673 }
1674 while (CurrentToken() == Token::kCOMMA) {
1675 ConsumeToken();
1676 SkipIf(Token::kTHIS);
1677 SkipIf(Token::kPERIOD);
1678 ExpectIdentifier("instance field expected");
1679 ExpectToken(Token::kASSIGN);
1680 SetAllowFunctionLiterals(false);
1681 SkipExpr();
1682 SetAllowFunctionLiterals(true);
1683 } 1696 }
1684 } 1697 }
1685 1698
1686 1699
1687 void Parser::ParseQualIdent(QualIdent* qual_ident) { 1700 void Parser::ParseQualIdent(QualIdent* qual_ident) {
1688 ASSERT(CurrentToken() == Token::kIDENT); 1701 ASSERT(CurrentToken() == Token::kIDENT);
1689 if (!is_top_level_) { 1702 if (!is_top_level_) {
1690 bool local_ident = ResolveIdentInLocalScope(token_index_, 1703 bool local_ident = ResolveIdentInLocalScope(token_index_,
1691 *CurrentLiteral(), 1704 *CurrentLiteral(),
1692 NULL); 1705 NULL);
(...skipping 5289 matching lines...) Expand 10 before | Expand all | Expand 10 after
6982 } 6995 }
6983 6996
6984 6997
6985 void Parser::SkipNestedExpr() { 6998 void Parser::SkipNestedExpr() {
6986 const bool saved_mode = SetAllowFunctionLiterals(true); 6999 const bool saved_mode = SetAllowFunctionLiterals(true);
6987 SkipExpr(); 7000 SkipExpr();
6988 SetAllowFunctionLiterals(saved_mode); 7001 SetAllowFunctionLiterals(saved_mode);
6989 } 7002 }
6990 7003
6991 } // namespace dart 7004 } // 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