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

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

Issue 10905109: Add named constructor name checking (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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/language/bad_constructor_test.dart » ('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"
11 #include "vm/dart_api_impl.h" 11 #include "vm/dart_api_impl.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/flags.h" 13 #include "vm/flags.h"
14 #include "vm/growable_array.h" 14 #include "vm/growable_array.h"
15 #include "vm/longjump.h" 15 #include "vm/longjump.h"
16 #include "vm/native_entry.h" 16 #include "vm/native_entry.h"
17 #include "vm/object.h" 17 #include "vm/object.h"
18 #include "vm/object_store.h" 18 #include "vm/object_store.h"
19 #include "vm/resolver.h" 19 #include "vm/resolver.h"
20 #include "vm/scopes.h" 20 #include "vm/scopes.h"
21 #include "vm/symbols.h" 21 #include "vm/symbols.h"
22 22
23 namespace dart { 23 namespace dart {
24 24
25 DEFINE_FLAG(bool, constructor_name_check, false,
26 "Named constructors may not clash with other members");
25 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); 27 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements.");
26 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); 28 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks.");
27 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); 29 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
28 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); 30 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
29 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); 31 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
30 DEFINE_FLAG(bool, warn_legacy_map_literal, false, 32 DEFINE_FLAG(bool, warn_legacy_map_literal, false,
31 "Warning on legacy map literal syntax (single type argument)"); 33 "Warning on legacy map literal syntax (single type argument)");
32 34
33 static void CheckedModeHandler(bool value) { 35 static void CheckedModeHandler(bool value) {
34 FLAG_enable_asserts = value; 36 FLAG_enable_asserts = value;
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 has_final = false; 475 has_final = false;
474 has_const = false; 476 has_const = false;
475 has_static = false; 477 has_static = false;
476 has_var = false; 478 has_var = false;
477 has_factory = false; 479 has_factory = false;
478 has_operator = false; 480 has_operator = false;
479 type = NULL; 481 type = NULL;
480 name_pos = 0; 482 name_pos = 0;
481 name = NULL; 483 name = NULL;
482 redirect_name = NULL; 484 redirect_name = NULL;
485 constructor_name = NULL;
483 params.Clear(); 486 params.Clear();
484 kind = RawFunction::kRegularFunction; 487 kind = RawFunction::kRegularFunction;
485 } 488 }
486 bool IsConstructor() const { 489 bool IsConstructor() const {
487 return (kind == RawFunction::kConstructor) && !has_static; 490 return (kind == RawFunction::kConstructor) && !has_static;
488 } 491 }
489 bool IsFactory() const { 492 bool IsFactory() const {
490 return (kind == RawFunction::kConstructor) && has_static; 493 return (kind == RawFunction::kConstructor) && has_static;
491 } 494 }
492 bool IsFactoryOrConstructor() const { 495 bool IsFactoryOrConstructor() const {
493 return (kind == RawFunction::kConstructor); 496 return (kind == RawFunction::kConstructor);
494 } 497 }
495 bool IsGetter() const { 498 bool IsGetter() const {
496 return kind == RawFunction::kGetterFunction; 499 return kind == RawFunction::kGetterFunction;
497 } 500 }
498 bool IsSetter() const { 501 bool IsSetter() const {
499 return kind == RawFunction::kSetterFunction; 502 return kind == RawFunction::kSetterFunction;
500 } 503 }
501 bool has_abstract; 504 bool has_abstract;
502 bool has_external; 505 bool has_external;
503 bool has_final; 506 bool has_final;
504 bool has_const; 507 bool has_const;
505 bool has_static; 508 bool has_static;
506 bool has_var; 509 bool has_var;
507 bool has_factory; 510 bool has_factory;
508 bool has_operator; 511 bool has_operator;
509 const AbstractType* type; 512 const AbstractType* type;
510 intptr_t name_pos; 513 intptr_t name_pos;
511 String* name; 514 String* name;
512 String* redirect_name; // For constructors: NULL or redirected constructor. 515 // For constructors: NULL or redirected constructor.
516 String* redirect_name;
517 // For constructors: NULL for unnamed constructor,
518 // identifier after classname for named constructors.
519 String* constructor_name;
513 ParamList params; 520 ParamList params;
514 RawFunction::Kind kind; 521 RawFunction::Kind kind;
515 }; 522 };
516 523
517 524
518 class ClassDesc : public ValueObject { 525 class ClassDesc : public ValueObject {
519 public: 526 public:
520 ClassDesc(const Class& cls, 527 ClassDesc(const Class& cls,
521 const String& cls_name, 528 const String& cls_name,
522 bool is_interface, 529 bool is_interface,
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after
1862 ASSERT(!func.IsFactory()); 1869 ASSERT(!func.IsFactory());
1863 ASSERT(!func.is_static()); 1870 ASSERT(!func.is_static());
1864 ASSERT(!func.IsLocalFunction()); 1871 ASSERT(!func.IsLocalFunction());
1865 const Class& cls = Class::Handle(func.Owner()); 1872 const Class& cls = Class::Handle(func.Owner());
1866 ASSERT(!cls.IsNull()); 1873 ASSERT(!cls.IsNull());
1867 1874
1868 if (CurrentToken() == Token::kCLASS) { 1875 if (CurrentToken() == Token::kCLASS) {
1869 // Special case: implicit constructor. 1876 // Special case: implicit constructor.
1870 // The parser adds an implicit default constructor when a class 1877 // The parser adds an implicit default constructor when a class
1871 // does not have any explicit constructor or factory (see 1878 // does not have any explicit constructor or factory (see
1872 // Parser::CheckConstructors). The token position of this implicit 1879 // Parser::AddImplicitConstructor). The token position of this implicit
1873 // constructor points to the 'class' keyword, which is followed 1880 // constructor points to the 'class' keyword, which is followed
1874 // by the name of the class (which is also the constructor name). 1881 // by the name of the class (which is also the constructor name).
1875 // There is no source text to parse. We just build the 1882 // There is no source text to parse. We just build the
1876 // sequence node by hand. 1883 // sequence node by hand.
1877 return MakeImplicitConstructor(func); 1884 return MakeImplicitConstructor(func);
1878 } 1885 }
1879 1886
1880 OpenFunctionBlock(func); 1887 OpenFunctionBlock(func);
1881 ParamList params; 1888 ParamList params;
1882 const bool allow_explicit_default_values = true; 1889 const bool allow_explicit_default_values = true;
(...skipping 975 matching lines...) Expand 10 before | Expand all | Expand 10 after
2858 member.name_pos = TokenPos(); 2865 member.name_pos = TokenPos();
2859 member.name = CurrentLiteral(); 2866 member.name = CurrentLiteral();
2860 ConsumeToken(); 2867 ConsumeToken();
2861 } 2868 }
2862 // We must be dealing with a constructor or named constructor. 2869 // We must be dealing with a constructor or named constructor.
2863 member.kind = RawFunction::kConstructor; 2870 member.kind = RawFunction::kConstructor;
2864 String& ctor_suffix = String::ZoneHandle(Symbols::Dot()); 2871 String& ctor_suffix = String::ZoneHandle(Symbols::Dot());
2865 if (CurrentToken() == Token::kPERIOD) { 2872 if (CurrentToken() == Token::kPERIOD) {
2866 // Named constructor. 2873 // Named constructor.
2867 ConsumeToken(); 2874 ConsumeToken();
2868 const String* name = ExpectIdentifier("identifier expected"); 2875 member.constructor_name = ExpectIdentifier("identifier expected");
2869 ctor_suffix = String::Concat(ctor_suffix, *name); 2876 ctor_suffix = String::Concat(ctor_suffix, *member.constructor_name);
2870 } 2877 }
2871 *member.name = String::Concat(*member.name, ctor_suffix); 2878 *member.name = String::Concat(*member.name, ctor_suffix);
2872 // Ensure that names are symbols. 2879 // Ensure that names are symbols.
2873 *member.name = Symbols::New(*member.name); 2880 *member.name = Symbols::New(*member.name);
2874 if (member.type == NULL) { 2881 if (member.type == NULL) {
2875 ASSERT(!member.has_factory); 2882 ASSERT(!member.has_factory);
2876 // The body of the constructor cannot modify the type arguments of the 2883 // The body of the constructor cannot modify the type arguments of the
2877 // constructed instance, which is passed in as a hidden parameter. 2884 // constructed instance, which is passed in as a hidden parameter.
2878 // Therefore, there is no need to set the result type to be checked. 2885 // Therefore, there is no need to set the result type to be checked.
2879 member.type = &Type::ZoneHandle(Type::DynamicType()); 2886 member.type = &Type::ZoneHandle(Type::DynamicType());
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
3088 3095
3089 if (is_abstract || members.is_abstract()) { 3096 if (is_abstract || members.is_abstract()) {
3090 cls.set_is_abstract(); 3097 cls.set_is_abstract();
3091 } 3098 }
3092 3099
3093 // Add an implicit constructor if no explicit constructor is present. No 3100 // Add an implicit constructor if no explicit constructor is present. No
3094 // implicit constructors are needed for patch classes. 3101 // implicit constructors are needed for patch classes.
3095 if (!members.has_constructor() && !is_patch) { 3102 if (!members.has_constructor() && !is_patch) {
3096 AddImplicitConstructor(&members); 3103 AddImplicitConstructor(&members);
3097 } 3104 }
3098 CheckConstructorCycles(&members); 3105 CheckConstructors(&members);
3099 3106
3100 Array& array = Array::Handle(); 3107 Array& array = Array::Handle();
3101 array = Array::MakeArray(members.fields()); 3108 array = Array::MakeArray(members.fields());
3102 cls.SetFields(array); 3109 cls.SetFields(array);
3103 3110
3104 // Creating a new array for functions marks the class as parsed. 3111 // Creating a new array for functions marks the class as parsed.
3105 array = Array::MakeArray(members.functions()); 3112 array = Array::MakeArray(members.functions());
3106 cls.SetFunctions(array); 3113 cls.SetFunctions(array);
3107 3114
3108 if (!is_patch) { 3115 if (!is_patch) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3146 &Type::ZoneHandle(Type::SmiType())); 3153 &Type::ZoneHandle(Type::SmiType()));
3147 3154
3148 AddFormalParamsToFunction(&params, ctor); 3155 AddFormalParamsToFunction(&params, ctor);
3149 // The body of the constructor cannot modify the type of the constructed 3156 // The body of the constructor cannot modify the type of the constructed
3150 // instance, which is passed in as the receiver. 3157 // instance, which is passed in as the receiver.
3151 ctor.set_result_type(*((*params.parameters)[0].type)); 3158 ctor.set_result_type(*((*params.parameters)[0].type));
3152 class_desc->AddFunction(ctor); 3159 class_desc->AddFunction(ctor);
3153 } 3160 }
3154 3161
3155 3162
3156 // Check for cycles in constructor redirection. 3163 // Check for cycles in constructor redirection. Also check whether a
3157 void Parser::CheckConstructorCycles(ClassDesc* class_desc) { 3164 // named constructor collides with the name of another class member.
3165 void Parser::CheckConstructors(ClassDesc* class_desc) {
3158 // Check for cycles in constructor redirection. 3166 // Check for cycles in constructor redirection.
3159 const GrowableArray<MemberDesc>& members = class_desc->members(); 3167 const GrowableArray<MemberDesc>& members = class_desc->members();
3160 for (int i = 0; i < members.length(); i++) { 3168 for (int i = 0; i < members.length(); i++) {
3161 MemberDesc* member = &members[i]; 3169 MemberDesc* member = &members[i];
3170
3171 if (FLAG_constructor_name_check && member->constructor_name != NULL) {
3172 if (class_desc->FunctionNameExists(
3173 *member->constructor_name, member->kind)) {
3174 ErrorMsg(member->name_pos,
3175 "Named constructor '%s' conflicts with method or field '%s'",
3176 member->name->ToCString(),
3177 member->constructor_name->ToCString());
3178 }
3179 }
3180
3162 GrowableArray<MemberDesc*> ctors; 3181 GrowableArray<MemberDesc*> ctors;
3163 while ((member != NULL) && (member->redirect_name != NULL)) { 3182 while ((member != NULL) && (member->redirect_name != NULL)) {
3164 ASSERT(member->IsConstructor()); 3183 ASSERT(member->IsConstructor());
3165 // Check whether we have already seen this member. 3184 // Check whether we have already seen this member.
3166 for (int i = 0; i < ctors.length(); i++) { 3185 for (int i = 0; i < ctors.length(); i++) {
3167 if (ctors[i] == member) { 3186 if (ctors[i] == member) {
3168 ErrorMsg(member->name_pos, 3187 ErrorMsg(member->name_pos,
3169 "cyclic reference in constructor redirection"); 3188 "cyclic reference in constructor redirection");
3170 } 3189 }
3171 } 3190 }
(...skipping 6213 matching lines...) Expand 10 before | Expand all | Expand 10 after
9385 void Parser::SkipQualIdent() { 9404 void Parser::SkipQualIdent() {
9386 ASSERT(IsIdentifier()); 9405 ASSERT(IsIdentifier());
9387 ConsumeToken(); 9406 ConsumeToken();
9388 if (CurrentToken() == Token::kPERIOD) { 9407 if (CurrentToken() == Token::kPERIOD) {
9389 ConsumeToken(); // Consume the kPERIOD token. 9408 ConsumeToken(); // Consume the kPERIOD token.
9390 ExpectIdentifier("identifier expected after '.'"); 9409 ExpectIdentifier("identifier expected after '.'");
9391 } 9410 }
9392 } 9411 }
9393 9412
9394 } // namespace dart 9413 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/bad_constructor_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698