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

Unified Diff: runtime/vm/parser.cc

Issue 9414005: Fix issue 979: operator arity must be verified. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 4395)
+++ runtime/vm/parser.cc (working copy)
@@ -615,6 +615,7 @@
SequenceNode* Parser::ParseStaticConstGetter(const Function& func) {
+ TRACE_PARSER("ParseStaticConstGetter");
ParamList params;
ASSERT(func.num_fixed_parameters() == 0); // static.
ASSERT(func.num_optional_parameters() == 0);
@@ -1146,6 +1147,7 @@
AstNode* Parser::ParseSuperFieldAccess(const String& field_name) {
+ TRACE_PARSER("ParseSuperFieldAccess");
const intptr_t field_pos = token_index_;
const Class& super_class = Class::Handle(current_class().SuperClass());
if (super_class.IsNull()) {
@@ -1359,6 +1361,7 @@
void Parser::ParseInitializedInstanceFields(const Class& cls,
GrowableArray<FieldInitExpression>* initializers) {
+ TRACE_PARSER("ParseInitializedInstanceFields");
const Array& fields = Array::Handle(cls.fields());
Field& f = Field::Handle();
const intptr_t saved_pos = token_index_;
@@ -1426,6 +1429,7 @@
void Parser::ParseConstructorRedirection(const Class& cls,
LocalVariable* receiver) {
+ TRACE_PARSER("ParseConstructorRedirection");
ASSERT(CurrentToken() == Token::kTHIS);
const intptr_t call_pos = token_index_;
ConsumeToken();
@@ -1519,6 +1523,7 @@
// of function. Parse the formal parameters, initializers and code.
SequenceNode* Parser::ParseConstructor(const Function& func,
Array& default_parameter_values) {
+ TRACE_PARSER("ParseConstructor");
ASSERT(func.IsConstructor());
ASSERT(!func.IsFactory());
ASSERT(!func.is_static());
@@ -1770,6 +1775,7 @@
// Parse the formal parameters and code.
SequenceNode* Parser::ParseFunc(const Function& func,
Array& default_parameter_values) {
+ TRACE_PARSER("ParseFunc");
if (func.IsConstructor()) {
return ParseConstructor(func, default_parameter_values);
}
@@ -1900,6 +1906,7 @@
void Parser::ParseQualIdent(QualIdent* qual_ident) {
+ TRACE_PARSER("ParseQualIdent");
ASSERT(IsIdentifier());
ASSERT(!current_class().IsNull());
qual_ident->ident_pos = token_index_;
@@ -1935,6 +1942,7 @@
void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
+ TRACE_PARSER("ParseMethodOrConstructor");
ASSERT(CurrentToken() == Token::kLPAREN);
intptr_t method_pos = this->token_index_;
ASSERT(method->type != NULL);
@@ -2145,6 +2153,7 @@
void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
+ TRACE_PARSER("ParseFieldDefinition");
// The parser has read the first field name and is now at the token
// after the field name.
ASSERT(CurrentToken() == Token::kSEMICOLON ||
@@ -2250,7 +2259,29 @@
}
+void Parser::CheckOperatorArity(
+ const MemberDesc& member, Token::Kind operator_token) {
+ intptr_t expected_num_parameters; // Includes receiver.
+ if (operator_token == Token::kASSIGN_INDEX) {
+ expected_num_parameters = 3;
+ } else if ((operator_token == Token::kNEGATE) ||
+ (operator_token == Token::kBIT_NOT)) {
+ expected_num_parameters = 1;
+ } else {
+ expected_num_parameters = 2;
+ }
+ if ((member.params.num_optional_parameters > 0) ||
+ (member.params.has_named_optional_parameters) ||
+ (member.params.num_fixed_parameters != expected_num_parameters)) {
+ // Subtract receiver when reporting number of expected arguments.
+ ErrorMsg(member.name_pos, "operator %s expects %d argument(s)",
+ member.name->ToCString(), (expected_num_parameters - 1));
+ }
+}
+
+
void Parser::ParseClassMemberDefinition(ClassDesc* members) {
+ TRACE_PARSER("ParseClassMemberDefinition");
MemberDesc member;
current_member_ = &member;
if ((CurrentToken() == Token::kABSTRACT) &&
@@ -2318,6 +2349,7 @@
}
}
}
+ Token::Kind operator_token = Token::kILLEGAL;
// Optionally parse a (possibly named) constructor name or factory.
if (IsIdentifier() &&
(CurrentLiteral()->Equals(members->class_name()) || member.has_factory)) {
@@ -2408,10 +2440,11 @@
if (member.has_static) {
ErrorMsg("operator overloading functions cannot be static");
}
+ operator_token = CurrentToken();
member.kind = RawFunction::kFunction;
member.name_pos = this->token_index_;
member.name =
- &String::ZoneHandle(String::NewSymbol(Token::Str(CurrentToken())));
+ &String::ZoneHandle(String::NewSymbol(Token::Str(operator_token)));
ConsumeToken();
} else if (IsIdentifier()) {
member.name = CurrentLiteral();
@@ -2435,6 +2468,9 @@
member.type = &Type::ZoneHandle(Type::DynamicType());
}
ParseMethodOrConstructor(members, &member);
+ if (operator_token != Token::kILLEGAL) {
+ CheckOperatorArity(member, operator_token);
+ }
} else if (CurrentToken() == Token::kSEMICOLON ||
CurrentToken() == Token::kCOMMA ||
CurrentToken() == Token::kASSIGN) {
@@ -2866,6 +2902,7 @@
void Parser::ParseTypeParameters(const Class& cls) {
+ TRACE_PARSER("ParseTypeParameters");
if (CurrentToken() == Token::kLT) {
GrowableArray<AbstractType*> type_parameters_array;
GrowableArray<AbstractType*> bounds_array;
@@ -2915,6 +2952,7 @@
RawAbstractTypeArguments* Parser::ParseTypeArguments(
TypeResolution type_resolution) {
+ TRACE_PARSER("ParseTypeArguments");
if (CurrentToken() == Token::kLT) {
GrowableArray<AbstractType*> types;
do {
@@ -2938,6 +2976,7 @@
// Parse and return an array of interface types.
RawArray* Parser::ParseInterfaceList() {
+ TRACE_PARSER("ParseInterfaceList");
ASSERT((CurrentToken() == Token::kIMPLEMENTS) ||
(CurrentToken() == Token::kEXTENDS));
GrowableArray<AbstractType*> interfaces;
@@ -3005,6 +3044,7 @@
void Parser::ParseTopLevelVariable(TopLevel* top_level) {
+ TRACE_PARSER("ParseTopLevelVariable");
const bool is_final = (CurrentToken() == Token::kFINAL);
const bool is_static = true;
const AbstractType& type = AbstractType::ZoneHandle(ParseFinalVarOrType(
@@ -3062,6 +3102,7 @@
void Parser::ParseTopLevelFunction(TopLevel* top_level) {
+ TRACE_PARSER("ParseTopLevelFunction");
AbstractType& result_type = Type::Handle(Type::DynamicType());
const bool is_static = true;
if (CurrentToken() == Token::kVOID) {
@@ -3125,6 +3166,7 @@
void Parser::ParseTopLevelAccessor(TopLevel* top_level) {
+ TRACE_PARSER("ParseTopLevelAccessor");
const bool is_static = true;
AbstractType& result_type = AbstractType::Handle();
bool is_getter = (CurrentToken() == Token::kGET);
@@ -3205,6 +3247,7 @@
void Parser::ParseLibraryName() {
+ TRACE_PARSER("ParseLibraryName");
if ((script_.kind() == RawScript::kLibrary) &&
(CurrentToken() != Token::kLIBRARY)) {
// Handle error case early to get consistent error message.
@@ -3245,6 +3288,7 @@
void Parser::ParseLibraryImport() {
+ TRACE_PARSER("ParseLibraryImport");
while (CurrentToken() == Token::kIMPORT) {
const intptr_t import_pos = token_index_;
ConsumeToken();
@@ -3310,6 +3354,7 @@
void Parser::ParseLibraryInclude() {
+ TRACE_PARSER("ParseLibraryInclude");
const Array& import_map = Array::Handle(library_.import_map());
while (CurrentToken() == Token::kSOURCE) {
const intptr_t source_pos = token_index_;
@@ -3332,6 +3377,7 @@
void Parser::ParseLibraryDefinition() {
+ TRACE_PARSER("ParseLibraryDefinition");
// Handle the script tag.
if (CurrentToken() == Token::kSCRIPTTAG) {
// Nothing to do for script tags except to skip them.
@@ -3345,6 +3391,7 @@
void Parser::ParseTopLevel() {
+ TRACE_PARSER("ParseTopLevel");
// Collect the classes found at the top level in this growable array.
// They need to be registered with class finalization after parsing
// has been completed.
@@ -3526,6 +3573,7 @@
// Builds ReturnNode/NativeBodyNode for a native function.
void Parser::ParseNativeFunctionBlock(const ParamList* params,
const Function& func) {
+ TRACE_PARSER("ParseNativeFunctionBlock");
const Class& cls = Class::Handle(func.owner());
const int num_parameters = params->parameters->length();
@@ -3642,6 +3690,7 @@
// The presence of 'final' must be detected and remembered before the call.
// If a type is parsed, it is resolved (or not) according to type_resolution.
RawAbstractType* Parser::ParseFinalVarOrType(TypeResolution type_resolution) {
+ TRACE_PARSER("ParseFinalVarOrType");
if (CurrentToken() == Token::kVAR) {
ConsumeToken();
return Type::DynamicType();
@@ -4352,6 +4401,7 @@
AstNode* Parser::ParseForInStatement(intptr_t forin_pos,
SourceLabel* label) {
+ TRACE_PARSER("ParseForInStatement");
bool is_final = (CurrentToken() == Token::kFINAL);
const String* loop_var_name = NULL;
LocalVariable* loop_var = NULL;
@@ -4575,6 +4625,7 @@
AstNode* Parser::ParseAssertStatement() {
+ TRACE_PARSER("ParseAssertStatement");
ConsumeToken(); // Consume assert keyword.
ExpectToken(Token::kLPAREN);
const intptr_t condition_pos = token_index_;
@@ -4657,6 +4708,7 @@
SequenceNode* Parser::ParseFinallyBlock() {
+ TRACE_PARSER("ParseFinallyBlock");
OpenBlock();
ExpectToken(Token::kLBRACE);
ParseStatementSequence();
@@ -4952,6 +5004,7 @@
AstNode* Parser::ParseJump(String* label_name) {
+ TRACE_PARSER("ParseJump");
ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE);
Token::Kind jump_kind = CurrentToken();
const intptr_t jump_pos = token_index_;
@@ -5809,6 +5862,7 @@
AstNode* Parser::ParseInstanceCall(AstNode* receiver, const String& func_name) {
+ TRACE_PARSER("ParseInstanceCall");
const intptr_t call_pos = token_index_;
if (CurrentToken() != Token::kLPAREN) {
ErrorMsg(call_pos, "left parenthesis expected");
@@ -5819,6 +5873,7 @@
AstNode* Parser::ParseClosureCall(AstNode* closure) {
+ TRACE_PARSER("ParseClosureCall");
const intptr_t call_pos = token_index_;
ASSERT(CurrentToken() == Token::kLPAREN);
ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
@@ -6654,6 +6709,7 @@
// Parses type = [ident "."] ident ["<" type { "," type } ">"] and resolve it
// according to the given type_resolution.
RawAbstractType* Parser::ParseType(TypeResolution type_resolution) {
+ TRACE_PARSER("ParseType");
if (CurrentToken() != Token::kIDENT) {
ErrorMsg("type name expected");
}
@@ -7046,6 +7102,7 @@
AstNode* Parser::ParseCompoundLiteral() {
+ TRACE_PARSER("ParseCompoundLiteral");
bool is_const = false;
if (CurrentToken() == Token::kCONST) {
is_const = true;
@@ -7287,6 +7344,7 @@
// a string literal always begins and ends with a kSTRING token, and
// there are never two kSTRING tokens next to each other.
AstNode* Parser::ParseStringLiteral() {
+ TRACE_PARSER("ParseStringLiteral");
AstNode* primary = NULL;
const intptr_t literal_start = token_index_;
if ((CurrentToken() == Token::kSTRING) &&
@@ -7342,6 +7400,7 @@
// a string literal always begins and ends with a kSTRING token, and
// there are never two kSTRING tokens next to each other.
String* Parser::ParseImportStringLiteral() {
+ TRACE_PARSER("ParseImportStringLiteral");
if ((CurrentToken() == Token::kSTRING) &&
(LookaheadToken(1) != Token::kINTERPOL_VAR) &&
(LookaheadToken(1) != Token::kINTERPOL_START)) {
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698