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

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

Issue 23190035: Distinguish between malformed and malbounded types (fix issues 12552 and 12554). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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
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 2949 matching lines...) Expand 10 before | Expand all | Expand 10 after
2960 if (!type.IsMalformed() && type.IsTypeParameter()) { 2960 if (!type.IsMalformed() && type.IsTypeParameter()) {
2961 // Replace the type with a malformed type and compile a throw when called. 2961 // Replace the type with a malformed type and compile a throw when called.
2962 redirection_type = ClassFinalizer::NewFinalizedMalformedType( 2962 redirection_type = ClassFinalizer::NewFinalizedMalformedType(
2963 Error::Handle(), // No previous error. 2963 Error::Handle(), // No previous error.
2964 current_class(), 2964 current_class(),
2965 type_pos, 2965 type_pos,
2966 "factory '%s' may not redirect to type parameter '%s'", 2966 "factory '%s' may not redirect to type parameter '%s'",
2967 method->name->ToCString(), 2967 method->name->ToCString(),
2968 String::Handle(type.UserVisibleName()).ToCString()); 2968 String::Handle(type.UserVisibleName()).ToCString());
2969 } else { 2969 } else {
2970 // TODO(regis): What if the redirection type is malbounded?
2970 redirection_type ^= type.raw(); 2971 redirection_type ^= type.raw();
2971 } 2972 }
2972 if (CurrentToken() == Token::kPERIOD) { 2973 if (CurrentToken() == Token::kPERIOD) {
2973 // Named constructor or factory. 2974 // Named constructor or factory.
2974 ConsumeToken(); 2975 ConsumeToken();
2975 redirection_identifier = ExpectIdentifier("identifier expected")->raw(); 2976 redirection_identifier = ExpectIdentifier("identifier expected")->raw();
2976 } 2977 }
2977 } else if (CurrentToken() == Token::kCOLON) { 2978 } else if (CurrentToken() == Token::kCOLON) {
2978 // Parse initializers. 2979 // Parse initializers.
2979 if (!method->IsConstructor()) { 2980 if (!method->IsConstructor()) {
(...skipping 2430 matching lines...) Expand 10 before | Expand all | Expand 10 after
5410 if (variable_name != NULL) { 5411 if (variable_name != NULL) {
5411 // Patch the function type of the variable now that the signature is known. 5412 // Patch the function type of the variable now that the signature is known.
5412 function_type.set_type_class(signature_class); 5413 function_type.set_type_class(signature_class);
5413 function_type.set_arguments(signature_type_arguments); 5414 function_type.set_arguments(signature_type_arguments);
5414 5415
5415 // Mark the function type as malformed if the signature type is malformed. 5416 // Mark the function type as malformed if the signature type is malformed.
5416 if (signature_type.IsMalformed()) { 5417 if (signature_type.IsMalformed()) {
5417 const Error& error = Error::Handle(signature_type.malformed_error()); 5418 const Error& error = Error::Handle(signature_type.malformed_error());
5418 function_type.set_malformed_error(error); 5419 function_type.set_malformed_error(error);
5419 } 5420 }
5421 // TODO(regis): What if the signature is malbounded?
5420 5422
5421 // The function type was initially marked as instantiated, but it may 5423 // The function type was initially marked as instantiated, but it may
5422 // actually be uninstantiated. 5424 // actually be uninstantiated.
5423 function_type.ResetIsFinalized(); 5425 function_type.ResetIsFinalized();
5424 5426
5425 // The function variable type should have been patched above. 5427 // The function variable type should have been patched above.
5426 ASSERT((function_variable == NULL) || 5428 ASSERT((function_variable == NULL) ||
5427 (function_variable->type().raw() == function_type.raw())); 5429 (function_variable->type().raw() == function_type.raw()));
5428 } 5430 }
5429 5431
(...skipping 1654 matching lines...) Expand 10 before | Expand all | Expand 10 after
7084 if (node != NULL) { 7086 if (node != NULL) {
7085 sequence->Add(node); 7087 sequence->Add(node);
7086 } 7088 }
7087 return sequence; 7089 return sequence;
7088 } 7090 }
7089 return node->AsSequenceNode(); 7091 return node->AsSequenceNode();
7090 } 7092 }
7091 7093
7092 7094
7093 AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) { 7095 AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) {
7094 ASSERT(type.IsMalformed());
7095 ArgumentListNode* arguments = new ArgumentListNode(type_pos); 7096 ArgumentListNode* arguments = new ArgumentListNode(type_pos);
7096 // Location argument. 7097 // Location argument.
7097 arguments->Add(new LiteralNode( 7098 arguments->Add(new LiteralNode(
7098 type_pos, Integer::ZoneHandle(Integer::New(type_pos)))); 7099 type_pos, Integer::ZoneHandle(Integer::New(type_pos))));
7099 // Src value argument. 7100 // Src value argument.
7100 arguments->Add(new LiteralNode(type_pos, Instance::ZoneHandle())); 7101 arguments->Add(new LiteralNode(type_pos, Instance::ZoneHandle()));
7101 // Dst type name argument. 7102 // Dst type name argument.
7102 arguments->Add(new LiteralNode(type_pos, Symbols::Malformed())); 7103 arguments->Add(new LiteralNode(type_pos, Symbols::Malformed()));
7103 // Dst name argument. 7104 // Dst name argument.
7104 arguments->Add(new LiteralNode(type_pos, Symbols::Empty())); 7105 arguments->Add(new LiteralNode(type_pos, Symbols::Empty()));
7105 // Malformed type error. 7106 // Malformed type error or malbounded type error.
7106 const Error& error = Error::Handle(type.malformed_error()); 7107 Error& error = Error::Handle();
7108 if (type.IsMalformed()) {
7109 error = type.malformed_error();
7110 } else {
7111 const bool is_malbounded = type.IsMalbounded(&error);
7112 ASSERT(is_malbounded);
7113 }
7107 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle( 7114 arguments->Add(new LiteralNode(type_pos, String::ZoneHandle(
7108 Symbols::New(error.ToErrorCString())))); 7115 Symbols::New(error.ToErrorCString()))));
7109 return MakeStaticCall(Symbols::TypeError(), 7116 return MakeStaticCall(Symbols::TypeError(),
7110 PrivateCoreLibName(Symbols::ThrowNew()), 7117 PrivateCoreLibName(Symbols::ThrowNew()),
7111 arguments); 7118 arguments);
7112 } 7119 }
7113 7120
7114 7121
7115 // TODO(regis): Providing the argument values is not always feasible, since 7122 // TODO(regis): Providing the argument values is not always feasible, since
7116 // evaluating them could throw an error. 7123 // evaluating them could throw an error.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
7196 } 7203 }
7197 const intptr_t type_pos = TokenPos(); 7204 const intptr_t type_pos = TokenPos();
7198 const AbstractType& type = AbstractType::ZoneHandle( 7205 const AbstractType& type = AbstractType::ZoneHandle(
7199 ParseType(ClassFinalizer::kCanonicalize)); 7206 ParseType(ClassFinalizer::kCanonicalize));
7200 if (!type.IsInstantiated() && 7207 if (!type.IsInstantiated() &&
7201 (current_block_->scope->function_level() > 0)) { 7208 (current_block_->scope->function_level() > 0)) {
7202 // Make sure that the instantiator is captured. 7209 // Make sure that the instantiator is captured.
7203 CaptureInstantiator(); 7210 CaptureInstantiator();
7204 } 7211 }
7205 right_operand = new TypeNode(type_pos, type); 7212 right_operand = new TypeNode(type_pos, type);
7206 // If the type is malformed, it is actually malbounded in checked mode. 7213 // The type is never malformed (mapped to dynamic), but it can be
7207 ASSERT(!type.IsMalformed() || FLAG_enable_type_checks); 7214 // malbounded in checked mode.
7215 ASSERT(!type.IsMalformed());
7208 if (((op_kind == Token::kIS) || (op_kind == Token::kISNOT)) && 7216 if (((op_kind == Token::kIS) || (op_kind == Token::kISNOT)) &&
7209 type.IsMalformed()) { 7217 type.IsMalbounded(NULL)) {
7210 // Note that a type error is thrown even if the tested value is null 7218 // Note that a type error is thrown even if the tested value is null
7211 // in a type test. However, no cast exception is thrown if the value 7219 // in a type test. However, no cast exception is thrown if the value
7212 // is null in a type cast. 7220 // is null in a type cast.
7213 return ThrowTypeError(type_pos, type); 7221 return ThrowTypeError(type_pos, type);
7214 } 7222 }
7215 } 7223 }
7216 if (Token::IsRelationalOperator(op_kind) 7224 if (Token::IsRelationalOperator(op_kind)
7217 || Token::IsTypeTestOperator(op_kind) 7225 || Token::IsTypeTestOperator(op_kind)
7218 || Token::IsTypeCastOperator(op_kind) 7226 || Token::IsTypeCastOperator(op_kind)
7219 || Token::IsEqualityOperator(op_kind)) { 7227 || Token::IsEqualityOperator(op_kind)) {
(...skipping 2344 matching lines...) Expand 10 before | Expand all | Expand 10 after
9564 ASSERT((op_kind == Token::kNEW) || (op_kind == Token::kCONST)); 9572 ASSERT((op_kind == Token::kNEW) || (op_kind == Token::kCONST));
9565 bool is_const = (op_kind == Token::kCONST); 9573 bool is_const = (op_kind == Token::kCONST);
9566 if (!IsIdentifier()) { 9574 if (!IsIdentifier()) {
9567 ErrorMsg("type name expected"); 9575 ErrorMsg("type name expected");
9568 } 9576 }
9569 intptr_t type_pos = TokenPos(); 9577 intptr_t type_pos = TokenPos();
9570 AbstractType& type = AbstractType::Handle( 9578 AbstractType& type = AbstractType::Handle(
9571 ParseType(ClassFinalizer::kCanonicalizeWellFormed)); 9579 ParseType(ClassFinalizer::kCanonicalizeWellFormed));
9572 // In case the type is malformed, throw a dynamic type error after finishing 9580 // In case the type is malformed, throw a dynamic type error after finishing
9573 // parsing the instance creation expression. 9581 // parsing the instance creation expression.
9574 if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) { 9582 if (!type.IsMalformed()) {
9575 // Replace the type with a malformed type. 9583 if (type.IsTypeParameter() || type.IsDynamicType()) {
9576 type = ClassFinalizer::NewFinalizedMalformedType( 9584 // Replace the type with a malformed type.
9577 Error::Handle(), // No previous error. 9585 type = ClassFinalizer::NewFinalizedMalformedType(
9578 current_class(), 9586 Error::Handle(), // No previous error.
9579 type_pos, 9587 current_class(),
9580 "%s'%s' cannot be instantiated", 9588 type_pos,
9581 type.IsTypeParameter() ? "type parameter " : "", 9589 "%s'%s' cannot be instantiated",
9582 type.IsTypeParameter() ? 9590 type.IsTypeParameter() ? "type parameter " : "",
9583 String::Handle(type.UserVisibleName()).ToCString() : "dynamic"); 9591 type.IsTypeParameter() ?
9592 String::Handle(type.UserVisibleName()).ToCString() : "dynamic");
9593 } else if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
9594 Error& bound_error = Error::Handle();
9595 if (type.IsMalbounded(&bound_error)) {
9596 // Replace the type with a malformed type.
9597 type = ClassFinalizer::NewFinalizedMalformedType(
9598 bound_error,
9599 current_class(),
9600 type_pos,
9601 "malbounded type '%s' cannot be instantiated",
9602 String::Handle(type.UserVisibleName()).ToCString());
9603 }
9604 }
9584 } 9605 }
9585 9606
9586 // The grammar allows for an optional ('.' identifier)? after the type, which 9607 // The grammar allows for an optional ('.' identifier)? after the type, which
9587 // is a named constructor. Note that ParseType() above will not consume it as 9608 // is a named constructor. Note that ParseType() above will not consume it as
9588 // part of a misinterpreted qualified identifier, because only a valid library 9609 // part of a misinterpreted qualified identifier, because only a valid library
9589 // prefix is accepted as qualifier. 9610 // prefix is accepted as qualifier.
9590 String* named_constructor = NULL; 9611 String* named_constructor = NULL;
9591 if (CurrentToken() == Token::kPERIOD) { 9612 if (CurrentToken() == Token::kPERIOD) {
9592 ConsumeToken(); 9613 ConsumeToken();
9593 named_constructor = ExpectIdentifier("name of constructor expected"); 9614 named_constructor = ExpectIdentifier("name of constructor expected");
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
10364 void Parser::SkipQualIdent() { 10385 void Parser::SkipQualIdent() {
10365 ASSERT(IsIdentifier()); 10386 ASSERT(IsIdentifier());
10366 ConsumeToken(); 10387 ConsumeToken();
10367 if (CurrentToken() == Token::kPERIOD) { 10388 if (CurrentToken() == Token::kPERIOD) {
10368 ConsumeToken(); // Consume the kPERIOD token. 10389 ConsumeToken(); // Consume the kPERIOD token.
10369 ExpectIdentifier("identifier expected after '.'"); 10390 ExpectIdentifier("identifier expected after '.'");
10370 } 10391 }
10371 } 10392 }
10372 10393
10373 } // namespace dart 10394 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698