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

Unified Diff: runtime/vm/parser.cc

Issue 23542051: Fix redirecting constructors (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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/language/language.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 27627)
+++ runtime/vm/parser.cc (working copy)
@@ -2349,18 +2349,6 @@
TRACE_PARSER("ParseInitializers");
bool super_init_seen = false;
if (CurrentToken() == Token::kCOLON) {
- if ((LookaheadToken(1) == Token::kTHIS) &&
- ((LookaheadToken(2) == Token::kLPAREN) ||
- ((LookaheadToken(2) == Token::kPERIOD) &&
- (LookaheadToken(4) == Token::kLPAREN)))) {
- // Either we see this(...) or this.xxx(...) which is a
- // redirected constructor. We don't need to check whether
- // const fields are initialized. The other constructor will
- // guarantee that.
- ConsumeToken(); // Colon.
- ParseConstructorRedirection(cls, receiver);
- return;
- }
do {
ConsumeToken(); // Colon or comma.
AstNode* init_statement;
@@ -2388,6 +2376,7 @@
void Parser::ParseConstructorRedirection(const Class& cls,
LocalVariable* receiver) {
TRACE_PARSER("ParseConstructorRedirection");
+ ExpectToken(Token::kCOLON);
ASSERT(CurrentToken() == Token::kTHIS);
const intptr_t call_pos = TokenPos();
ConsumeToken();
@@ -2568,24 +2557,36 @@
// Now populate function scope with the formal parameters.
AddFormalParamsToScope(&params, current_block_->scope);
- // Initialize instance fields that have an explicit initializer expression.
- // The formal parameter names must not be visible to the instance
- // field initializer expressions, yet the parameters must be added to
- // the scope so the expressions use the correct offsets for 'this' when
- // storing values. We make the formal parameters temporarily invisible
- // while parsing the instance field initializer expressions.
- params.SetInvisible(true);
+ const bool is_redirecting_constructor =
+ (CurrentToken() == Token::kCOLON) &&
+ ((LookaheadToken(1) == Token::kTHIS) &&
+ ((LookaheadToken(2) == Token::kLPAREN) ||
+ ((LookaheadToken(2) == Token::kPERIOD) &&
+ (LookaheadToken(4) == Token::kLPAREN))));
+
GrowableArray<Field*> initialized_fields;
- LocalVariable* receiver = current_block_->scope->VariableAt(0);
+ LocalVariable* receiver = (*params.parameters)[0].var;
OpenBlock();
- ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
- // Make the parameters (which are in the outer scope) visible again.
- params.SetInvisible(false);
- // Turn formal field parameters into field initializers or report error
- // if the function is not a constructor.
+ // If this is not a redirecting constructor, initialize
+ // instance fields that have an explicit initializer expression.
+ if (!is_redirecting_constructor) {
+ // The formal parameter names must not be visible to the instance
+ // field initializer expressions, yet the parameters must be added to
+ // the scope so the expressions use the correct offsets for 'this' when
+ // storing values. We make the formal parameters temporarily invisible
+ // while parsing the instance field initializer expressions.
+ params.SetInvisible(true);
+ ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
+ // Make the parameters (which are in the outer scope) visible again.
+ params.SetInvisible(false);
+ }
+
+ // Turn formal field parameters into field initializers.
if (params.has_field_initializer) {
- for (int i = 0; i < params.parameters->length(); i++) {
+ // First two parameters are implicit receiver and phase.
+ ASSERT(params.parameters->length() >= 2);
+ for (int i = 2; i < params.parameters->length(); i++) {
ParamDesc& param = (*params.parameters)[i];
if (param.is_field_initializer) {
const String& field_name = *param.name;
@@ -2595,6 +2596,11 @@
"unresolved reference to instance field '%s'",
field_name.ToCString());
}
+ if (is_redirecting_constructor) {
+ ErrorMsg(param.name_pos,
+ "redirecting constructors may not have "
+ "initializing formal parameters");
+ }
CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field);
AstNode* instance = new LoadLocalNode(param.name_pos, receiver);
// Initializing formals cannot be used in the explicit initializer
@@ -2612,8 +2618,11 @@
}
}
- // Now parse the explicit initializer list or constructor redirection.
- ParseInitializers(cls, receiver, &initialized_fields);
+ if (is_redirecting_constructor) {
+ ParseConstructorRedirection(cls, receiver);
+ } else {
+ ParseInitializers(cls, receiver, &initialized_fields);
+ }
SequenceNode* init_statements = CloseBlock();
if (init_statements->length() > 0) {
@@ -2660,6 +2669,11 @@
// saves the evaluated actual arguments in temporary variables.
// The temporary variables are necessary so that the argument
// expressions are not evaluated twice.
+ // Note: we should never get here in the case of a redirecting
+ // constructor. In that case, the call to the target constructor
+ // is the "super call" and is implicitly at the end of the
+ // initializer list.
+ ASSERT(!is_redirecting_constructor);
ArgumentListNode* ctor_args = super_call->arguments();
// The super initializer call has at least 2 arguments: the
// implicit receiver, and the hidden construction phase.
@@ -2719,6 +2733,9 @@
}
if (CurrentToken() == Token::kLBRACE) {
+ // We checked in the top-level parse phase that a redirecting
+ // constructor does not have a body.
+ ASSERT(!is_redirecting_constructor);
ConsumeToken();
ParseStatementSequence();
ExpectToken(Token::kRBRACE);
« no previous file with comments | « no previous file | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698