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

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

Issue 27619002: Check that class member names do not conflict with type parameters (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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-co19.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 "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/bigint_operations.h" 8 #include "vm/bigint_operations.h"
9 #include "vm/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 has_static = false; 524 has_static = false;
525 has_var = false; 525 has_var = false;
526 has_factory = false; 526 has_factory = false;
527 has_operator = false; 527 has_operator = false;
528 metadata_pos = -1; 528 metadata_pos = -1;
529 operator_token = Token::kILLEGAL; 529 operator_token = Token::kILLEGAL;
530 type = NULL; 530 type = NULL;
531 name_pos = 0; 531 name_pos = 0;
532 name = NULL; 532 name = NULL;
533 redirect_name = NULL; 533 redirect_name = NULL;
534 constructor_name = NULL; 534 dict_name = NULL;
535 params.Clear(); 535 params.Clear();
536 kind = RawFunction::kRegularFunction; 536 kind = RawFunction::kRegularFunction;
537 field_ = NULL;
537 } 538 }
538 bool IsConstructor() const { 539 bool IsConstructor() const {
539 return (kind == RawFunction::kConstructor) && !has_static; 540 return (kind == RawFunction::kConstructor) && !has_static;
540 } 541 }
541 bool IsFactory() const { 542 bool IsFactory() const {
542 return (kind == RawFunction::kConstructor) && has_static; 543 return (kind == RawFunction::kConstructor) && has_static;
543 } 544 }
544 bool IsFactoryOrConstructor() const { 545 bool IsFactoryOrConstructor() const {
545 return (kind == RawFunction::kConstructor); 546 return (kind == RawFunction::kConstructor);
546 } 547 }
547 bool IsGetter() const { 548 bool IsGetter() const {
548 return kind == RawFunction::kGetterFunction; 549 return kind == RawFunction::kGetterFunction;
549 } 550 }
550 bool IsSetter() const { 551 bool IsSetter() const {
551 return kind == RawFunction::kSetterFunction; 552 return kind == RawFunction::kSetterFunction;
552 } 553 }
554 const char* ToCString() const {
555 if (field_ != NULL) {
556 return "field";
557 } else if (IsConstructor()) {
558 return "constructor";
559 } else if (IsFactory()) {
560 return "factory";
561 } else if (IsGetter()) {
562 return "getter";
563 } else if (IsSetter()) {
564 return "setter";
565 }
566 return "method";
567 }
568 String* DictName() const {
569 return (dict_name != NULL) ? dict_name : name;
570 }
553 bool has_abstract; 571 bool has_abstract;
554 bool has_external; 572 bool has_external;
555 bool has_final; 573 bool has_final;
556 bool has_const; 574 bool has_const;
557 bool has_static; 575 bool has_static;
558 bool has_var; 576 bool has_var;
559 bool has_factory; 577 bool has_factory;
560 bool has_operator; 578 bool has_operator;
561 intptr_t metadata_pos; 579 intptr_t metadata_pos;
562 Token::Kind operator_token; 580 Token::Kind operator_token;
563 const AbstractType* type; 581 const AbstractType* type;
564 intptr_t name_pos; 582 intptr_t name_pos;
565 intptr_t decl_begin_pos; 583 intptr_t decl_begin_pos;
566 String* name; 584 String* name;
567 // For constructors: NULL or name of redirected to constructor. 585 // For constructors: NULL or name of redirected to constructor.
568 String* redirect_name; 586 String* redirect_name;
587 // dict_name is the name used for the class namespace, if it
588 // differs from 'name'.
569 // For constructors: NULL for unnamed constructor, 589 // For constructors: NULL for unnamed constructor,
570 // identifier after classname for named constructors. 590 // identifier after classname for named constructors.
571 String* constructor_name; 591 // For getters and setters: unmangled name.
592 String* dict_name;
572 ParamList params; 593 ParamList params;
573 RawFunction::Kind kind; 594 RawFunction::Kind kind;
595 // NULL for functions, field object for static or instance fields.
596 Field* field_;
574 }; 597 };
575 598
576 599
577 class ClassDesc : public ValueObject { 600 class ClassDesc : public ValueObject {
578 public: 601 public:
579 ClassDesc(const Class& cls, 602 ClassDesc(const Class& cls,
580 const String& cls_name, 603 const String& cls_name,
581 bool is_interface, 604 bool is_interface,
582 intptr_t token_pos) 605 intptr_t token_pos)
583 : clazz_(cls), 606 : clazz_(cls),
584 class_name_(cls_name), 607 class_name_(cls_name),
585 token_pos_(token_pos), 608 token_pos_(token_pos),
586 functions_(GrowableObjectArray::Handle(GrowableObjectArray::New())), 609 functions_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
587 fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) { 610 fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) {
588 } 611 }
589 612
590 // Parameter 'name' is the unmangled name, i.e. without the setter
591 // name mangling.
592 bool FunctionNameExists(const String& name, RawFunction::Kind kind) const {
593 // First check if a function or field of same name exists.
594 if ((kind != RawFunction::kSetterFunction) && FunctionExists(name)) {
595 return true;
596 }
597 // Now check whether there is a field and whether its implicit getter
598 // or setter collides with the name.
599 Field* field = LookupField(name);
600 if (field != NULL) {
601 if (kind == RawFunction::kSetterFunction) {
602 // It's ok to have an implicit getter, it does not collide with
603 // this setter function.
604 if (!field->is_final()) {
605 return true;
606 }
607 } else {
608 // The implicit getter of the field collides with the name.
609 return true;
610 }
611 }
612
613 String& accessor_name = String::Handle();
614 if (kind == RawFunction::kSetterFunction) {
615 // Check if a setter function of same name exists.
616 accessor_name = Field::SetterName(name);
617 if (FunctionExists(accessor_name)) {
618 return true;
619 }
620 } else {
621 // Check if a getter function of same name exists.
622 accessor_name = Field::GetterName(name);
623 if (FunctionExists(accessor_name)) {
624 return true;
625 }
626 }
627 return false;
628 }
629
630 bool FieldNameExists(const String& name, bool check_setter) const {
631 // First check if a function or field of same name exists.
632 if (FunctionExists(name) || FieldExists(name)) {
633 return true;
634 }
635 // Now check if a getter/setter function of same name exists.
636 String& getter_name = String::Handle(Field::GetterName(name));
637 if (FunctionExists(getter_name)) {
638 return true;
639 }
640 if (check_setter) {
641 String& setter_name = String::Handle(Field::SetterName(name));
642 if (FunctionExists(setter_name)) {
643 return true;
644 }
645 }
646 return false;
647 }
648
649 void AddFunction(const Function& function) { 613 void AddFunction(const Function& function) {
650 ASSERT(!FunctionExists(String::Handle(function.name())));
651 functions_.Add(function); 614 functions_.Add(function);
652 } 615 }
653 616
654 const GrowableObjectArray& functions() const { 617 const GrowableObjectArray& functions() const {
655 return functions_; 618 return functions_;
656 } 619 }
657 620
658 void AddField(const Field& field) { 621 void AddField(const Field& field) {
659 ASSERT(!FieldExists(String::Handle(field.name())));
660 fields_.Add(field); 622 fields_.Add(field);
661 } 623 }
662 624
663 const GrowableObjectArray& fields() const { 625 const GrowableObjectArray& fields() const {
664 return fields_; 626 return fields_;
665 } 627 }
666 628
667 const Class& clazz() const { 629 const Class& clazz() const {
668 return clazz_; 630 return clazz_;
669 } 631 }
(...skipping 28 matching lines...) Expand all
698 MemberDesc* LookupMember(const String& name) const { 660 MemberDesc* LookupMember(const String& name) const {
699 for (int i = 0; i < members_.length(); i++) { 661 for (int i = 0; i < members_.length(); i++) {
700 if (name.Equals(*members_[i].name)) { 662 if (name.Equals(*members_[i].name)) {
701 return &members_[i]; 663 return &members_[i];
702 } 664 }
703 } 665 }
704 return NULL; 666 return NULL;
705 } 667 }
706 668
707 private: 669 private:
708 Field* LookupField(const String& name) const {
709 String& test_name = String::Handle();
710 Field& field = Field::Handle();
711 for (int i = 0; i < fields_.Length(); i++) {
712 field ^= fields_.At(i);
713 test_name = field.name();
714 if (name.Equals(test_name)) {
715 return &field;
716 }
717 }
718 return NULL;
719 }
720
721 bool FieldExists(const String& name) const {
722 return LookupField(name) != NULL;
723 }
724
725 Function* LookupFunction(const String& name) const {
726 String& test_name = String::Handle();
727 Function& func = Function::Handle();
728 for (int i = 0; i < functions_.Length(); i++) {
729 func ^= functions_.At(i);
730 test_name = func.name();
731 if (name.Equals(test_name)) {
732 return &func;
733 }
734 }
735 return NULL;
736 }
737
738 bool FunctionExists(const String& name) const {
739 return LookupFunction(name) != NULL;
740 }
741
742 const Class& clazz_; 670 const Class& clazz_;
743 const String& class_name_; 671 const String& class_name_;
744 intptr_t token_pos_; // Token index of "class" keyword. 672 intptr_t token_pos_; // Token index of "class" keyword.
745 GrowableObjectArray& functions_; 673 GrowableObjectArray& functions_;
746 GrowableObjectArray& fields_; 674 GrowableObjectArray& fields_;
747 GrowableArray<MemberDesc> members_; 675 GrowableArray<MemberDesc> members_;
748 }; 676 };
749 677
750 678
751 struct TopLevel { 679 struct TopLevel {
(...skipping 2315 matching lines...) Expand 10 before | Expand all | Expand 10 after
3067 if ((method->operator_token == Token::kSUB) && 2995 if ((method->operator_token == Token::kSUB) &&
3068 (method->params.num_fixed_parameters == 1)) { 2996 (method->params.num_fixed_parameters == 1)) {
3069 // Patch up name for unary operator - so it does not clash with the 2997 // Patch up name for unary operator - so it does not clash with the
3070 // name for binary operator -. 2998 // name for binary operator -.
3071 method->operator_token = Token::kNEGATE; 2999 method->operator_token = Token::kNEGATE;
3072 *method->name = Symbols::New(Token::Str(Token::kNEGATE)); 3000 *method->name = Symbols::New(Token::Str(Token::kNEGATE));
3073 } 3001 }
3074 CheckOperatorArity(*method); 3002 CheckOperatorArity(*method);
3075 } 3003 }
3076 3004
3077 if (members->FunctionNameExists(*method->name, method->kind)) {
3078 ErrorMsg(method->name_pos,
3079 "field or method '%s' already defined", method->name->ToCString());
3080 }
3081
3082 // Mangle the name for getter and setter functions and check function 3005 // Mangle the name for getter and setter functions and check function
3083 // arity. 3006 // arity.
3084 if (method->IsGetter() || method->IsSetter()) { 3007 if (method->IsGetter() || method->IsSetter()) {
3085 int expected_num_parameters = 0; 3008 int expected_num_parameters = 0;
3086 if (method->IsGetter()) { 3009 if (method->IsGetter()) {
3087 expected_num_parameters = (method->has_static) ? 0 : 1; 3010 expected_num_parameters = (method->has_static) ? 0 : 1;
3011 method->dict_name = method->name;
3088 method->name = &String::ZoneHandle(Field::GetterSymbol(*method->name)); 3012 method->name = &String::ZoneHandle(Field::GetterSymbol(*method->name));
3089 } else { 3013 } else {
3090 ASSERT(method->IsSetter()); 3014 ASSERT(method->IsSetter());
3091 expected_num_parameters = (method->has_static) ? 1 : 2; 3015 expected_num_parameters = (method->has_static) ? 1 : 2;
3016 method->dict_name =
3017 &String::ZoneHandle(String::Concat(*method->name, Symbols::Equals()));
3092 method->name = &String::ZoneHandle(Field::SetterSymbol(*method->name)); 3018 method->name = &String::ZoneHandle(Field::SetterSymbol(*method->name));
3093 } 3019 }
3094 if ((method->params.num_fixed_parameters != expected_num_parameters) || 3020 if ((method->params.num_fixed_parameters != expected_num_parameters) ||
3095 (method->params.num_optional_parameters != 0)) { 3021 (method->params.num_optional_parameters != 0)) {
3096 ErrorMsg(method->name_pos, "illegal %s parameters", 3022 ErrorMsg(method->name_pos, "illegal %s parameters",
3097 method->IsGetter() ? "getter" : "setter"); 3023 method->IsGetter() ? "getter" : "setter");
3098 } 3024 }
3099 } 3025 }
3100 3026
3101 // Parse redirecting factory constructor. 3027 // Parse redirecting factory constructor.
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
3309 } 3235 }
3310 if (field->has_external) { 3236 if (field->has_external) {
3311 ErrorMsg("keyword 'external' not allowed in field declaration"); 3237 ErrorMsg("keyword 'external' not allowed in field declaration");
3312 } 3238 }
3313 if (field->has_factory) { 3239 if (field->has_factory) {
3314 ErrorMsg("keyword 'factory' not allowed in field declaration"); 3240 ErrorMsg("keyword 'factory' not allowed in field declaration");
3315 } 3241 }
3316 if (!field->has_static && field->has_const) { 3242 if (!field->has_static && field->has_const) {
3317 ErrorMsg(field->name_pos, "instance field may not be 'const'"); 3243 ErrorMsg(field->name_pos, "instance field may not be 'const'");
3318 } 3244 }
3319 if (members->FieldNameExists(*field->name, !field->has_final)) {
3320 ErrorMsg(field->name_pos,
3321 "field or method '%s' already defined", field->name->ToCString());
3322 }
3323 Function& getter = Function::Handle(); 3245 Function& getter = Function::Handle();
3324 Function& setter = Function::Handle(); 3246 Function& setter = Function::Handle();
3325 Field& class_field = Field::Handle(); 3247 Field& class_field = Field::ZoneHandle();
3326 Instance& init_value = Instance::Handle(); 3248 Instance& init_value = Instance::Handle();
3327 while (true) { 3249 while (true) {
3328 bool has_initializer = CurrentToken() == Token::kASSIGN; 3250 bool has_initializer = CurrentToken() == Token::kASSIGN;
3329 bool has_simple_literal = false; 3251 bool has_simple_literal = false;
3330 if (has_initializer) { 3252 if (has_initializer) {
3331 ConsumeToken(); 3253 ConsumeToken();
3332 init_value = Object::sentinel().raw(); 3254 init_value = Object::sentinel().raw();
3333 // For static const fields and static final non-const fields, the 3255 // For static const fields and static final non-const fields, the
3334 // initialization expression will be parsed through the 3256 // initialization expression will be parsed through the
3335 // kImplicitStaticFinalGetter method invocation/compilation. 3257 // kImplicitStaticFinalGetter method invocation/compilation.
(...skipping 27 matching lines...) Expand all
3363 // Create the field object. 3285 // Create the field object.
3364 class_field = Field::New(*field->name, 3286 class_field = Field::New(*field->name,
3365 field->has_static, 3287 field->has_static,
3366 field->has_final, 3288 field->has_final,
3367 field->has_const, 3289 field->has_const,
3368 current_class(), 3290 current_class(),
3369 field->name_pos); 3291 field->name_pos);
3370 class_field.set_type(*field->type); 3292 class_field.set_type(*field->type);
3371 class_field.set_has_initializer(has_initializer); 3293 class_field.set_has_initializer(has_initializer);
3372 members->AddField(class_field); 3294 members->AddField(class_field);
3295 field->field_ = &class_field;
3373 if (field->metadata_pos >= 0) { 3296 if (field->metadata_pos >= 0) {
3374 library_.AddFieldMetadata(class_field, field->metadata_pos); 3297 library_.AddFieldMetadata(class_field, field->metadata_pos);
3375 } 3298 }
3376 3299
3377 // For static final fields (this includes static const fields), set value to 3300 // For static final fields (this includes static const fields), set value to
3378 // "uninitialized" and create a kImplicitStaticFinalGetter getter method. 3301 // "uninitialized" and create a kImplicitStaticFinalGetter getter method.
3379 if (field->has_static && has_initializer) { 3302 if (field->has_static && has_initializer) {
3380 class_field.set_value(init_value); 3303 class_field.set_value(init_value);
3381 if (!has_simple_literal) { 3304 if (!has_simple_literal) {
3382 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); 3305 String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
3456 member.params.has_optional_positional_parameters || 3379 member.params.has_optional_positional_parameters ||
3457 member.params.has_optional_named_parameters || 3380 member.params.has_optional_named_parameters ||
3458 (member.params.num_fixed_parameters != expected_num_parameters)) { 3381 (member.params.num_fixed_parameters != expected_num_parameters)) {
3459 // Subtract receiver when reporting number of expected arguments. 3382 // Subtract receiver when reporting number of expected arguments.
3460 ErrorMsg(member.name_pos, "operator %s expects %" Pd " argument(s)", 3383 ErrorMsg(member.name_pos, "operator %s expects %" Pd " argument(s)",
3461 member.name->ToCString(), (expected_num_parameters - 1)); 3384 member.name->ToCString(), (expected_num_parameters - 1));
3462 } 3385 }
3463 } 3386 }
3464 3387
3465 3388
3389 void Parser::CheckMemberNameConflict(ClassDesc* members,
3390 MemberDesc* member) {
3391 const String& name = *member->DictName();
3392 if (name.Equals(members->class_name())) {
3393 ErrorMsg(member->name_pos,
3394 "%s '%s' conflicts with class name",
3395 member->ToCString(),
3396 name.ToCString());
3397 }
3398 if (members->clazz().LookupTypeParameter(name) != TypeParameter::null()) {
3399 ErrorMsg(member->name_pos,
3400 "%s '%s' conflicts with type parameter",
3401 member->ToCString(),
3402 name.ToCString());
3403 }
3404 for (int i = 0; i < members->members().length(); i++) {
3405 MemberDesc* existing_member = &members->members()[i];
3406 if (name.Equals(*existing_member->DictName())) {
3407 ErrorMsg(member->name_pos,
3408 "%s '%s' conflicts with previously declared %s",
3409 member->ToCString(),
3410 name.ToCString(),
3411 existing_member->ToCString());
3412 }
3413 }
3414 }
3415
3416
3466 void Parser::ParseClassMemberDefinition(ClassDesc* members, 3417 void Parser::ParseClassMemberDefinition(ClassDesc* members,
3467 intptr_t metadata_pos) { 3418 intptr_t metadata_pos) {
3468 TRACE_PARSER("ParseClassMemberDefinition"); 3419 TRACE_PARSER("ParseClassMemberDefinition");
3469 MemberDesc member; 3420 MemberDesc member;
3470 current_member_ = &member; 3421 current_member_ = &member;
3471 member.metadata_pos = metadata_pos; 3422 member.metadata_pos = metadata_pos;
3472 member.decl_begin_pos = TokenPos(); 3423 member.decl_begin_pos = TokenPos();
3473 if ((CurrentToken() == Token::kEXTERNAL) && 3424 if ((CurrentToken() == Token::kEXTERNAL) &&
3474 (LookaheadToken(1) != Token::kLPAREN)) { 3425 (LookaheadToken(1) != Token::kLPAREN)) {
3475 ConsumeToken(); 3426 ConsumeToken();
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
3572 result_type_class, 3523 result_type_class,
3573 TypeArguments::Handle(current_class().type_parameters()), 3524 TypeArguments::Handle(current_class().type_parameters()),
3574 member.name_pos)); 3525 member.name_pos));
3575 3526
3576 // We must be dealing with a constructor or named constructor. 3527 // We must be dealing with a constructor or named constructor.
3577 member.kind = RawFunction::kConstructor; 3528 member.kind = RawFunction::kConstructor;
3578 *member.name = String::Concat(*member.name, Symbols::Dot()); 3529 *member.name = String::Concat(*member.name, Symbols::Dot());
3579 if (CurrentToken() == Token::kPERIOD) { 3530 if (CurrentToken() == Token::kPERIOD) {
3580 // Named constructor. 3531 // Named constructor.
3581 ConsumeToken(); 3532 ConsumeToken();
3582 member.constructor_name = ExpectIdentifier("identifier expected"); 3533 member.dict_name = ExpectIdentifier("identifier expected");
3583 *member.name = String::Concat(*member.name, *member.constructor_name); 3534 *member.name = String::Concat(*member.name, *member.dict_name);
3584 } 3535 }
3585 // Ensure that names are symbols. 3536 // Ensure that names are symbols.
3586 *member.name = Symbols::New(*member.name); 3537 *member.name = Symbols::New(*member.name);
3587 3538
3588 if (CurrentToken() != Token::kLPAREN) { 3539 if (CurrentToken() != Token::kLPAREN) {
3589 ErrorMsg("left parenthesis expected"); 3540 ErrorMsg("left parenthesis expected");
3590 } 3541 }
3591 } else if ((CurrentToken() == Token::kGET) && !member.has_var && 3542 } else if ((CurrentToken() == Token::kGET) && !member.has_var &&
3592 (LookaheadToken(1) != Token::kLPAREN) && 3543 (LookaheadToken(1) != Token::kLPAREN) &&
3593 (LookaheadToken(1) != Token::kASSIGN) && 3544 (LookaheadToken(1) != Token::kASSIGN) &&
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3636 ConsumeToken(); 3587 ConsumeToken();
3637 } else if (IsIdentifier()) { 3588 } else if (IsIdentifier()) {
3638 member.name = CurrentLiteral(); 3589 member.name = CurrentLiteral();
3639 member.name_pos = TokenPos(); 3590 member.name_pos = TokenPos();
3640 ConsumeToken(); 3591 ConsumeToken();
3641 } else { 3592 } else {
3642 ErrorMsg("identifier expected"); 3593 ErrorMsg("identifier expected");
3643 } 3594 }
3644 3595
3645 ASSERT(member.name != NULL); 3596 ASSERT(member.name != NULL);
3646 if (member.kind != RawFunction::kConstructor) {
3647 if (member.name->Equals(members->class_name())) {
3648 ErrorMsg(member.name_pos,
3649 "class member must not have the same name as its class");
3650 }
3651 }
3652
3653 if (CurrentToken() == Token::kLPAREN || member.IsGetter()) { 3597 if (CurrentToken() == Token::kLPAREN || member.IsGetter()) {
3654 // Constructor or method. 3598 // Constructor or method.
3655 if (member.type == NULL) { 3599 if (member.type == NULL) {
3656 member.type = &Type::ZoneHandle(Type::DynamicType()); 3600 member.type = &Type::ZoneHandle(Type::DynamicType());
3657 } 3601 }
3658 ASSERT(member.IsFactory() == member.has_factory); 3602 ASSERT(member.IsFactory() == member.has_factory);
3659 ParseMethodOrConstructor(members, &member); 3603 ParseMethodOrConstructor(members, &member);
3660 } else if (CurrentToken() == Token::kSEMICOLON || 3604 } else if (CurrentToken() == Token::kSEMICOLON ||
3661 CurrentToken() == Token::kCOMMA || 3605 CurrentToken() == Token::kCOMMA ||
3662 CurrentToken() == Token::kASSIGN) { 3606 CurrentToken() == Token::kASSIGN) {
3663 // Field definition. 3607 // Field definition.
3664 if (member.has_const) { 3608 if (member.has_const) {
3665 // const fields are implicitly final. 3609 // const fields are implicitly final.
3666 member.has_final = true; 3610 member.has_final = true;
3667 } 3611 }
3668 if (member.type == NULL) { 3612 if (member.type == NULL) {
3669 if (member.has_final) { 3613 if (member.has_final) {
3670 member.type = &Type::ZoneHandle(Type::DynamicType()); 3614 member.type = &Type::ZoneHandle(Type::DynamicType());
3671 } else { 3615 } else {
3672 ErrorMsg("missing 'var', 'final', 'const' or type" 3616 ErrorMsg("missing 'var', 'final', 'const' or type"
3673 " in field declaration"); 3617 " in field declaration");
3674 } 3618 }
3675 } 3619 }
3676 ParseFieldDefinition(members, &member); 3620 ParseFieldDefinition(members, &member);
3677 } else { 3621 } else {
3678 UnexpectedToken(); 3622 UnexpectedToken();
3679 } 3623 }
3680 current_member_ = NULL; 3624 current_member_ = NULL;
3625 CheckMemberNameConflict(members, &member);
3681 members->AddMember(member); 3626 members->AddMember(member);
3682 } 3627 }
3683 3628
3684 3629
3685 void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, 3630 void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes,
3686 intptr_t metadata_pos) { 3631 intptr_t metadata_pos) {
3687 TRACE_PARSER("ParseClassDeclaration"); 3632 TRACE_PARSER("ParseClassDeclaration");
3688 bool is_patch = false; 3633 bool is_patch = false;
3689 bool is_abstract = false; 3634 bool is_abstract = false;
3690 if (is_patch_source() && 3635 if (is_patch_source() &&
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
3938 &Type::ZoneHandle(Type::SmiType())); 3883 &Type::ZoneHandle(Type::SmiType()));
3939 3884
3940 AddFormalParamsToFunction(&params, ctor); 3885 AddFormalParamsToFunction(&params, ctor);
3941 // The body of the constructor cannot modify the type of the constructed 3886 // The body of the constructor cannot modify the type of the constructed
3942 // instance, which is passed in as the receiver. 3887 // instance, which is passed in as the receiver.
3943 ctor.set_result_type(*receiver_type); 3888 ctor.set_result_type(*receiver_type);
3944 cls.AddFunction(ctor); 3889 cls.AddFunction(ctor);
3945 } 3890 }
3946 3891
3947 3892
3948 // Check for cycles in constructor redirection. Also check whether a 3893 // Check for cycles in constructor redirection.
3949 // named constructor collides with the name of another class member.
3950 void Parser::CheckConstructors(ClassDesc* class_desc) { 3894 void Parser::CheckConstructors(ClassDesc* class_desc) {
3951 // Check for cycles in constructor redirection. 3895 // Check for cycles in constructor redirection.
3952 const GrowableArray<MemberDesc>& members = class_desc->members(); 3896 const GrowableArray<MemberDesc>& members = class_desc->members();
3953 for (int i = 0; i < members.length(); i++) { 3897 for (int i = 0; i < members.length(); i++) {
3954 MemberDesc* member = &members[i]; 3898 MemberDesc* member = &members[i];
3955 3899 if (member->redirect_name == NULL) {
3956 if (member->constructor_name != NULL) { 3900 continue;
3957 // Check whether constructor name conflicts with a member name.
3958 if (class_desc->FunctionNameExists(
3959 *member->constructor_name, member->kind)) {
3960 ErrorMsg(member->name_pos,
3961 "Named constructor '%s' conflicts with method or field '%s'",
3962 member->name->ToCString(),
3963 member->constructor_name->ToCString());
3964 }
3965 } 3901 }
3966
3967 GrowableArray<MemberDesc*> ctors; 3902 GrowableArray<MemberDesc*> ctors;
3968 while ((member != NULL) && (member->redirect_name != NULL)) { 3903 while ((member != NULL) && (member->redirect_name != NULL)) {
3969 ASSERT(member->IsConstructor()); 3904 ASSERT(member->IsConstructor());
3970 // Check whether we have already seen this member. 3905 // Check whether we have already seen this member.
3971 for (int i = 0; i < ctors.length(); i++) { 3906 for (int i = 0; i < ctors.length(); i++) {
3972 if (ctors[i] == member) { 3907 if (ctors[i] == member) {
3973 ErrorMsg(member->name_pos, 3908 ErrorMsg(member->name_pos,
3974 "cyclic reference in constructor redirection"); 3909 "cyclic reference in constructor redirection");
3975 } 3910 }
3976 } 3911 }
(...skipping 6642 matching lines...) Expand 10 before | Expand all | Expand 10 after
10619 void Parser::SkipQualIdent() { 10554 void Parser::SkipQualIdent() {
10620 ASSERT(IsIdentifier()); 10555 ASSERT(IsIdentifier());
10621 ConsumeToken(); 10556 ConsumeToken();
10622 if (CurrentToken() == Token::kPERIOD) { 10557 if (CurrentToken() == Token::kPERIOD) {
10623 ConsumeToken(); // Consume the kPERIOD token. 10558 ConsumeToken(); // Consume the kPERIOD token.
10624 ExpectIdentifier("identifier expected after '.'"); 10559 ExpectIdentifier("identifier expected after '.'");
10625 } 10560 }
10626 } 10561 }
10627 10562
10628 } // namespace dart 10563 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-co19.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698