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

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

Issue 11404004: Fix result type checking of redirecting factory in checked mode (issue 6596). (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 9061 matching lines...) Expand 10 before | Expand all | Expand 10 after
9072 AstNode* Parser::ParseNewOperator() { 9072 AstNode* Parser::ParseNewOperator() {
9073 TRACE_PARSER("ParseNewOperator"); 9073 TRACE_PARSER("ParseNewOperator");
9074 const intptr_t new_pos = TokenPos(); 9074 const intptr_t new_pos = TokenPos();
9075 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST)); 9075 ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST));
9076 bool is_const = (CurrentToken() == Token::kCONST); 9076 bool is_const = (CurrentToken() == Token::kCONST);
9077 ConsumeToken(); 9077 ConsumeToken();
9078 if (!IsIdentifier()) { 9078 if (!IsIdentifier()) {
9079 ErrorMsg("type name expected"); 9079 ErrorMsg("type name expected");
9080 } 9080 }
9081 intptr_t type_pos = TokenPos(); 9081 intptr_t type_pos = TokenPos();
9082 AbstractType& type = AbstractType::ZoneHandle( 9082 AbstractType& type = AbstractType::Handle(
9083 ParseType(ClassFinalizer::kCanonicalizeForCreation)); 9083 ParseType(ClassFinalizer::kCanonicalizeForCreation));
9084 // In case the type is malformed, throw a dynamic type error after finishing 9084 // In case the type is malformed, throw a dynamic type error after finishing
9085 // parsing the instance creation expression. 9085 // parsing the instance creation expression.
9086 if (type.IsTypeParameter() || type.IsDynamicType()) { 9086 if (type.IsTypeParameter() || type.IsDynamicType()) {
9087 ASSERT(!type.IsMalformed()); 9087 ASSERT(!type.IsMalformed());
9088 // Replace the type with a malformed type. 9088 // Replace the type with a malformed type.
9089 type = ClassFinalizer::NewFinalizedMalformedType( 9089 type = ClassFinalizer::NewFinalizedMalformedType(
9090 Error::Handle(), // No previous error. 9090 Error::Handle(), // No previous error.
9091 current_class(), 9091 current_class(),
9092 type_pos, 9092 type_pos,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
9206 constructor_class_name = factory_class.Name(); 9206 constructor_class_name = factory_class.Name();
9207 } 9207 }
9208 // Always change the result type of the constructor to the factory type. 9208 // Always change the result type of the constructor to the factory type.
9209 constructor_class = factory_class.raw(); 9209 constructor_class = factory_class.raw();
9210 // The finalized type_arguments are still those of the interface type. 9210 // The finalized type_arguments are still those of the interface type.
9211 ASSERT(!constructor_class.is_interface()); 9211 ASSERT(!constructor_class.is_interface());
9212 } 9212 }
9213 9213
9214 // An additional type check of the result of a redirecting factory may be 9214 // An additional type check of the result of a redirecting factory may be
9215 // required. 9215 // required.
9216 bool check_result_type = false; 9216 AbstractType& type_bound = AbstractType::ZoneHandle();
9217 9217
9218 // Make sure that an appropriate constructor exists. 9218 // Make sure that an appropriate constructor exists.
9219 const String& constructor_name = 9219 const String& constructor_name =
9220 BuildConstructorName(constructor_class_name, named_constructor); 9220 BuildConstructorName(constructor_class_name, named_constructor);
9221 Function& constructor = Function::ZoneHandle( 9221 Function& constructor = Function::ZoneHandle(
9222 constructor_class.LookupConstructor(constructor_name)); 9222 constructor_class.LookupConstructor(constructor_name));
9223 if (constructor.IsNull()) { 9223 if (constructor.IsNull()) {
9224 constructor = constructor_class.LookupFactory(constructor_name); 9224 constructor = constructor_class.LookupFactory(constructor_name);
9225 if (constructor.IsNull()) { 9225 if (constructor.IsNull()) {
9226 const String& external_constructor_name = 9226 const String& external_constructor_name =
(...skipping 20 matching lines...) Expand all
9247 // type arguments of the parsed type of the 'new' or 'const' expression. 9247 // type arguments of the parsed type of the 'new' or 'const' expression.
9248 redirect_type ^= redirect_type.InstantiateFrom(type_arguments); 9248 redirect_type ^= redirect_type.InstantiateFrom(type_arguments);
9249 } 9249 }
9250 if (redirect_type.IsMalformed()) { 9250 if (redirect_type.IsMalformed()) {
9251 if (is_const) { 9251 if (is_const) {
9252 const Error& error = Error::Handle(redirect_type.malformed_error()); 9252 const Error& error = Error::Handle(redirect_type.malformed_error());
9253 ErrorMsg(error); 9253 ErrorMsg(error);
9254 } 9254 }
9255 return ThrowTypeError(redirect_type.token_pos(), redirect_type); 9255 return ThrowTypeError(redirect_type.token_pos(), redirect_type);
9256 } 9256 }
9257 check_result_type = 9257 if (FLAG_enable_type_checks && !redirect_type.IsSubtypeOf(type, NULL)) {
9258 FLAG_enable_type_checks && !redirect_type.IsSubtypeOf(type, NULL); 9258 // Additional type checking of the result is necessary.
9259 type_bound = type.raw();
9260 }
9259 type = redirect_type.raw(); 9261 type = redirect_type.raw();
9260 type_class = type.type_class(); 9262 type_class = type.type_class();
9261 type_arguments = type.arguments(); 9263 type_arguments = type.arguments();
9262 constructor = constructor.RedirectionTarget(); 9264 constructor = constructor.RedirectionTarget();
9263 ASSERT(!constructor.IsNull()); 9265 ASSERT(!constructor.IsNull());
9264 constructor_class = constructor.Owner(); 9266 constructor_class = constructor.Owner();
9265 ASSERT(type_class.raw() == constructor_class.raw()); 9267 ASSERT(type_class.raw() == constructor_class.raw());
9266 } 9268 }
9267 if (constructor.IsFactory()) { 9269 if (constructor.IsFactory()) {
9268 // A factory does not have the implicit 'phase' parameter. 9270 // A factory does not have the implicit 'phase' parameter.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
9364 EvaluateConstConstructorCall(constructor_class, 9366 EvaluateConstConstructorCall(constructor_class,
9365 type_arguments, 9367 type_arguments,
9366 constructor, 9368 constructor,
9367 arguments)); 9369 arguments));
9368 if (constructor_result.IsUnhandledException()) { 9370 if (constructor_result.IsUnhandledException()) {
9369 new_object = GenerateRethrow(new_pos, constructor_result); 9371 new_object = GenerateRethrow(new_pos, constructor_result);
9370 } else { 9372 } else {
9371 const Instance& const_instance = Instance::Cast(constructor_result); 9373 const Instance& const_instance = Instance::Cast(constructor_result);
9372 new_object = new LiteralNode(new_pos, 9374 new_object = new LiteralNode(new_pos,
9373 Instance::ZoneHandle(const_instance.raw())); 9375 Instance::ZoneHandle(const_instance.raw()));
9374 if (check_result_type) { 9376 if (!type_bound.IsNull()) {
9375 ASSERT(!type.IsMalformed()); 9377 ASSERT(!type_bound.IsMalformed());
9376 Error& malformed_error = Error::Handle(); 9378 Error& malformed_error = Error::Handle();
9377 if (!const_instance.IsInstanceOf(type, 9379 if (!const_instance.IsInstanceOf(type_bound,
9378 TypeArguments::Handle(), 9380 TypeArguments::Handle(),
9379 &malformed_error)) { 9381 &malformed_error)) {
9380 type = ClassFinalizer::NewFinalizedMalformedType( 9382 type_bound = ClassFinalizer::NewFinalizedMalformedType(
9381 malformed_error, 9383 malformed_error,
9382 current_class(), 9384 current_class(),
9383 new_pos, 9385 new_pos,
9384 ClassFinalizer::kTryResolve, // No compile-time error. 9386 ClassFinalizer::kTryResolve, // No compile-time error.
9385 "const factory result is not an instance of '%s'", 9387 "const factory result is not an instance of '%s'",
9386 String::Handle(type.UserVisibleName()).ToCString()); 9388 String::Handle(type_bound.UserVisibleName()).ToCString());
9387 new_object = ThrowTypeError(new_pos, type); 9389 new_object = ThrowTypeError(new_pos, type_bound);
9388 } 9390 }
9389 check_result_type = false; 9391 type_bound = AbstractType::null();
9390 } 9392 }
9391 } 9393 }
9392 } else { 9394 } else {
9393 CheckFunctionIsCallable(new_pos, constructor); 9395 CheckFunctionIsCallable(new_pos, constructor);
9394 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments); 9396 CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments);
9395 if (!type_arguments.IsNull() && 9397 if (!type_arguments.IsNull() &&
9396 !type_arguments.IsInstantiated() && 9398 !type_arguments.IsInstantiated() &&
9397 (current_block_->scope->function_level() > 0)) { 9399 (current_block_->scope->function_level() > 0)) {
9398 // Make sure that the instantiator is captured. 9400 // Make sure that the instantiator is captured.
9399 CaptureInstantiator(); 9401 CaptureInstantiator();
9400 } 9402 }
9401 // If the type argument vector is not instantiated, we verify in checked 9403 // If the type argument vector is not instantiated, we verify in checked
9402 // mode at runtime that it is within its declared bounds. 9404 // mode at runtime that it is within its declared bounds.
9403 new_object = CreateConstructorCallNode( 9405 new_object = CreateConstructorCallNode(
9404 new_pos, type_arguments, constructor, arguments); 9406 new_pos, type_arguments, constructor, arguments);
9405 } 9407 }
9406 if (check_result_type) { 9408 if (!type_bound.IsNull()) {
9407 const String& dst_name = String::ZoneHandle(Symbols::FactoryResult()); 9409 const String& dst_name = String::ZoneHandle(Symbols::FactoryResult());
9408 new_object = new AssignableNode(new_pos, new_object, type, dst_name); 9410 new_object = new AssignableNode(new_pos, new_object, type_bound, dst_name);
9409 } 9411 }
9410 return new_object; 9412 return new_object;
9411 } 9413 }
9412 9414
9413 9415
9414 String& Parser::Interpolate(ArrayNode* values) { 9416 String& Parser::Interpolate(ArrayNode* values) {
9415 const String& class_name = String::Handle(Symbols::StringBase()); 9417 const String& class_name = String::Handle(Symbols::StringBase());
9416 const Class& cls = Class::Handle(LookupCoreClass(class_name)); 9418 const Class& cls = Class::Handle(LookupCoreClass(class_name));
9417 ASSERT(!cls.IsNull()); 9419 ASSERT(!cls.IsNull());
9418 const String& func_name = String::Handle(Symbols::Interpolate()); 9420 const String& func_name = String::Handle(Symbols::Interpolate());
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
10009 void Parser::SkipQualIdent() { 10011 void Parser::SkipQualIdent() {
10010 ASSERT(IsIdentifier()); 10012 ASSERT(IsIdentifier());
10011 ConsumeToken(); 10013 ConsumeToken();
10012 if (CurrentToken() == Token::kPERIOD) { 10014 if (CurrentToken() == Token::kPERIOD) {
10013 ConsumeToken(); // Consume the kPERIOD token. 10015 ConsumeToken(); // Consume the kPERIOD token.
10014 ExpectIdentifier("identifier expected after '.'"); 10016 ExpectIdentifier("identifier expected after '.'");
10015 } 10017 }
10016 } 10018 }
10017 10019
10018 } // namespace dart 10020 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/language/factory_redirection_test.dart » ('j') | tests/language/language_dart2js.status » ('J')

Powered by Google App Engine
This is Rietveld 408576698