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

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

Issue 11369219: Check result type of redirecting factory in checked mode. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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
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 9100 matching lines...) Expand 10 before | Expand all | Expand 10 after
9111 AstNode* Parser::ParseNewOperator() { 9111 AstNode* Parser::ParseNewOperator() {
9112 TRACE_PARSER("ParseNewOperator"); 9112 TRACE_PARSER("ParseNewOperator");
9113 const intptr_t new_pos = TokenPos(); 9113 const intptr_t new_pos = TokenPos();
9114 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST)); 9114 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST));
9115 bool is_const = (CurrentToken() == Token::kCONST); 9115 bool is_const = (CurrentToken() == Token::kCONST);
9116 ConsumeToken(); 9116 ConsumeToken();
9117 if (!IsIdentifier()) { 9117 if (!IsIdentifier()) {
9118 ErrorMsg("type name expected"); 9118 ErrorMsg("type name expected");
9119 } 9119 }
9120 intptr_t type_pos = TokenPos(); 9120 intptr_t type_pos = TokenPos();
9121 AbstractType& type = AbstractType::Handle( 9121 AbstractType& type = AbstractType::ZoneHandle(
9122 ParseType(ClassFinalizer::kCanonicalizeForCreation)); 9122 ParseType(ClassFinalizer::kCanonicalizeForCreation));
9123 // In case the type is malformed, throw a dynamic type error after finishing 9123 // In case the type is malformed, throw a dynamic type error after finishing
9124 // parsing the instance creation expression. 9124 // parsing the instance creation expression.
9125 if (type.IsTypeParameter() || type.IsDynamicType()) { 9125 if (type.IsTypeParameter() || type.IsDynamicType()) {
9126 ASSERT(!type.IsMalformed()); 9126 ASSERT(!type.IsMalformed());
9127 // Replace the type with a malformed type. 9127 // Replace the type with a malformed type.
9128 type = ClassFinalizer::NewFinalizedMalformedType( 9128 type = ClassFinalizer::NewFinalizedMalformedType(
9129 Error::Handle(), // No previous error. 9129 Error::Handle(), // No previous error.
9130 current_class(), 9130 current_class(),
9131 type_pos, 9131 type_pos,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
9243 // Class finalization verifies that the factory class has identical type 9243 // Class finalization verifies that the factory class has identical type
9244 // parameters as the interface. 9244 // parameters as the interface.
9245 constructor_class_name = factory_class.Name(); 9245 constructor_class_name = factory_class.Name();
9246 } 9246 }
9247 // Always change the result type of the constructor to the factory type. 9247 // Always change the result type of the constructor to the factory type.
9248 constructor_class = factory_class.raw(); 9248 constructor_class = factory_class.raw();
9249 // The finalized type_arguments are still those of the interface type. 9249 // The finalized type_arguments are still those of the interface type.
9250 ASSERT(!constructor_class.is_interface()); 9250 ASSERT(!constructor_class.is_interface());
9251 } 9251 }
9252 9252
9253 // An additional type check of the result of a redirecting factory may be
9254 // required.
9255 bool check_result_type = false;
9256
9253 // Make sure that an appropriate constructor exists. 9257 // Make sure that an appropriate constructor exists.
9254 const String& constructor_name = 9258 const String& constructor_name =
9255 BuildConstructorName(constructor_class_name, named_constructor); 9259 BuildConstructorName(constructor_class_name, named_constructor);
9256 Function& constructor = Function::ZoneHandle( 9260 Function& constructor = Function::ZoneHandle(
9257 constructor_class.LookupConstructor(constructor_name)); 9261 constructor_class.LookupConstructor(constructor_name));
9258 if (constructor.IsNull()) { 9262 if (constructor.IsNull()) {
9259 constructor = constructor_class.LookupFactory(constructor_name); 9263 constructor = constructor_class.LookupFactory(constructor_name);
9260 if (constructor.IsNull()) { 9264 if (constructor.IsNull()) {
9261 const String& external_constructor_name = 9265 const String& external_constructor_name =
9262 (named_constructor ? constructor_name : constructor_class_name); 9266 (named_constructor ? constructor_name : constructor_class_name);
9263 // Replace the type with a malformed type and compile a throw or report a 9267 // Replace the type with a malformed type and compile a throw or report a
9264 // compile-time error if the constructor is const. 9268 // compile-time error if the constructor is const.
9265 type = ClassFinalizer::NewFinalizedMalformedType( 9269 type = ClassFinalizer::NewFinalizedMalformedType(
9266 Error::Handle(), // No previous error. 9270 Error::Handle(), // No previous error.
9267 current_class(), 9271 current_class(),
9268 call_pos, 9272 call_pos,
9269 ClassFinalizer::kTryResolve, // No compile-time error. 9273 ClassFinalizer::kTryResolve, // No compile-time error.
9270 "class '%s' has no constructor or factory named '%s'", 9274 "class '%s' has no constructor or factory named '%s'",
9271 String::Handle(constructor_class.Name()).ToCString(), 9275 String::Handle(constructor_class.Name()).ToCString(),
9272 external_constructor_name.ToCString()); 9276 external_constructor_name.ToCString());
9273 if (is_const) { 9277 if (is_const) {
9274 const Error& error = Error::Handle(type.malformed_error()); 9278 const Error& error = Error::Handle(type.malformed_error());
9275 ErrorMsg(error); 9279 ErrorMsg(error);
9276 } 9280 }
9277 return ThrowNoSuchMethodError(call_pos, external_constructor_name); 9281 return ThrowNoSuchMethodError(call_pos, external_constructor_name);
9278 } else if (constructor.IsRedirectingFactory()) { 9282 } else if (constructor.IsRedirectingFactory()) {
9279 type = constructor.RedirectionType(); 9283 Type& redirect_type = Type::Handle(constructor.RedirectionType());
9280 if (type.IsMalformed()) { 9284 if (!redirect_type.IsMalformed() && !redirect_type.IsInstantiated()) {
9285 // The type arguments of the redirection type are instantiated from the
9286 // type arguments of the parsed type of the 'new' or 'const' expression.
9287 redirect_type ^= redirect_type.InstantiateFrom(type_arguments);
9288 }
9289 if (redirect_type.IsMalformed()) {
9281 if (is_const) { 9290 if (is_const) {
9282 const Error& error = Error::Handle(type.malformed_error()); 9291 const Error& error = Error::Handle(redirect_type.malformed_error());
9283 ErrorMsg(error); 9292 ErrorMsg(error);
9284 } 9293 }
9285 return ThrowTypeError(type.token_pos(), type); 9294 return ThrowTypeError(redirect_type.token_pos(), redirect_type);
9286 } 9295 }
9296 check_result_type =
9297 FLAG_enable_type_checks && !redirect_type.IsSubtypeOf(type, NULL);
9298 type = redirect_type.raw();
9299 type_class = type.type_class();
9300 type_arguments = type.arguments();
9287 constructor = constructor.RedirectionTarget(); 9301 constructor = constructor.RedirectionTarget();
9288 ASSERT(!constructor.IsNull()); 9302 ASSERT(!constructor.IsNull());
9289 type_class = type.type_class();
9290 type_arguments = type.arguments();
9291 constructor_class = constructor.Owner(); 9303 constructor_class = constructor.Owner();
9292 ASSERT(type_class.raw() == constructor_class.raw()); 9304 ASSERT(type_class.raw() == constructor_class.raw());
9293 } 9305 }
9294 if (constructor.IsFactory()) { 9306 if (constructor.IsFactory()) {
9295 // A factory does not have the implicit 'phase' parameter. 9307 // A factory does not have the implicit 'phase' parameter.
9296 arguments_length -= 1; 9308 arguments_length -= 1;
9297 } 9309 }
9298 } 9310 }
9299 9311
9300 // It is ok to call a factory method of an abstract class, but it is 9312 // It is ok to call a factory method of an abstract class, but it is
9301 // a dynamic error to instantiate an abstract class. 9313 // a dynamic error to instantiate an abstract class.
9302 ASSERT(!constructor.IsNull()); 9314 ASSERT(!constructor.IsNull());
9303 if (constructor_class.is_abstract() && 9315 if (constructor_class.is_abstract() && !constructor.IsFactory()) {
9304 !constructor.IsFactory()) {
9305 ArgumentListNode* arguments = new ArgumentListNode(type_pos); 9316 ArgumentListNode* arguments = new ArgumentListNode(type_pos);
9306 arguments->Add(new LiteralNode( 9317 arguments->Add(new LiteralNode(
9307 TokenPos(), Integer::ZoneHandle(Integer::New(type_pos)))); 9318 TokenPos(), Integer::ZoneHandle(Integer::New(type_pos))));
9308 arguments->Add(new LiteralNode( 9319 arguments->Add(new LiteralNode(
9309 TokenPos(), String::ZoneHandle(constructor_class_name.raw()))); 9320 TokenPos(), String::ZoneHandle(constructor_class_name.raw())));
9310 const String& cls_name = 9321 const String& cls_name =
9311 String::Handle(Symbols::AbstractClassInstantiationError()); 9322 String::Handle(Symbols::AbstractClassInstantiationError());
9312 const String& func_name = String::Handle(Symbols::ThrowNew()); 9323 const String& func_name = String::Handle(Symbols::ThrowNew());
9313 return MakeStaticCall(cls_name, func_name, arguments); 9324 return MakeStaticCall(cls_name, func_name, arguments);
9314 } 9325 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
9392 EvaluateConstConstructorCall(constructor_class, 9403 EvaluateConstConstructorCall(constructor_class,
9393 type_arguments, 9404 type_arguments,
9394 constructor, 9405 constructor,
9395 arguments)); 9406 arguments));
9396 if (constructor_result.IsUnhandledException()) { 9407 if (constructor_result.IsUnhandledException()) {
9397 new_object = GenerateRethrow(new_pos, constructor_result); 9408 new_object = GenerateRethrow(new_pos, constructor_result);
9398 } else { 9409 } else {
9399 const Instance& const_instance = Instance::Cast(constructor_result); 9410 const Instance& const_instance = Instance::Cast(constructor_result);
9400 new_object = new LiteralNode(new_pos, 9411 new_object = new LiteralNode(new_pos,
9401 Instance::ZoneHandle(const_instance.raw())); 9412 Instance::ZoneHandle(const_instance.raw()));
9413 if (check_result_type) {
9414 ASSERT(!type.IsMalformed());
9415 Error& malformed_error = Error::Handle();
9416 if (!const_instance.IsInstanceOf(type,
9417 TypeArguments::Handle(),
9418 &malformed_error)) {
9419 type = ClassFinalizer::NewFinalizedMalformedType(
9420 malformed_error,
9421 current_class(),
9422 new_pos,
9423 ClassFinalizer::kTryResolve, // No compile-time error.
9424 "const factory result is not an instance of '%s'",
9425 String::Handle(type.UserVisibleName()).ToCString());
9426 new_object = ThrowTypeError(new_pos, type);
9427 }
9428 check_result_type = false;
9429 }
9402 } 9430 }
9403 } else { 9431 } else {
9404 CheckFunctionIsCallable(new_pos, constructor); 9432 CheckFunctionIsCallable(new_pos, constructor);
9405 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments); 9433 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments);
9406 if (!type_arguments.IsNull() && 9434 if (!type_arguments.IsNull() &&
9407 !type_arguments.IsInstantiated() && 9435 !type_arguments.IsInstantiated() &&
9408 (current_block_->scope->function_level() > 0)) { 9436 (current_block_->scope->function_level() > 0)) {
9409 // Make sure that the instantiator is captured. 9437 // Make sure that the instantiator is captured.
9410 CaptureInstantiator(); 9438 CaptureInstantiator();
9411 } 9439 }
9412 // If the type argument vector is not instantiated, we verify in checked 9440 // If the type argument vector is not instantiated, we verify in checked
9413 // mode at runtime that it is within its declared bounds. 9441 // mode at runtime that it is within its declared bounds.
9414 new_object = CreateConstructorCallNode( 9442 new_object = CreateConstructorCallNode(
9415 new_pos, type_arguments, constructor, arguments); 9443 new_pos, type_arguments, constructor, arguments);
9416 } 9444 }
9445 if (check_result_type) {
9446 const String& dst_name = String::ZoneHandle(Symbols::New("factory result"));
hausner 2012/11/13 19:06:37 Would it make sense to add this string to the symb
regis 2012/11/13 19:29:26 I'll do it in a following cl. Thanks.
9447 new_object = new AssignableNode(new_pos, new_object, type, dst_name);
9448 }
9417 return new_object; 9449 return new_object;
9418 } 9450 }
9419 9451
9420 9452
9421 String& Parser::Interpolate(ArrayNode* values) { 9453 String& Parser::Interpolate(ArrayNode* values) {
9422 const String& class_name = String::Handle(Symbols::StringBase()); 9454 const String& class_name = String::Handle(Symbols::StringBase());
9423 const Class& cls = Class::Handle(LookupCoreClass(class_name)); 9455 const Class& cls = Class::Handle(LookupCoreClass(class_name));
9424 ASSERT(!cls.IsNull()); 9456 ASSERT(!cls.IsNull());
9425 const String& func_name = String::Handle(Symbols::Interpolate()); 9457 const String& func_name = String::Handle(Symbols::Interpolate());
9426 const Function& func = 9458 const Function& func =
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
10016 void Parser::SkipQualIdent() { 10048 void Parser::SkipQualIdent() {
10017 ASSERT(IsIdentifier()); 10049 ASSERT(IsIdentifier());
10018 ConsumeToken(); 10050 ConsumeToken();
10019 if (CurrentToken() == Token::kPERIOD) { 10051 if (CurrentToken() == Token::kPERIOD) {
10020 ConsumeToken(); // Consume the kPERIOD token. 10052 ConsumeToken(); // Consume the kPERIOD token.
10021 ExpectIdentifier("identifier expected after '.'"); 10053 ExpectIdentifier("identifier expected after '.'");
10022 } 10054 }
10023 } 10055 }
10024 10056
10025 } // namespace dart 10057 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698