diff --git a/co19/tests/co19/co19-runtime.status b/co19/tests/co19/co19-runtime.status index 353f345375c..61c8085cf40 100644 --- a/co19/tests/co19/co19-runtime.status +++ b/co19/tests/co19/co19-runtime.status @@ -108,11 +108,7 @@ LangGuideTest/02_Language_Constructs/02_3_Interface_Injection/A01/t04: Skip LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Const_Expressions/A04/t01: Fail # Bug 5371433 LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A03/t02: Fail # Bug 5371433 -LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A06/t03: Fail # Bug 5371433 -LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A06/t04: Fail # Bug 5371433 -LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A08/t02: Fail # Bug 5371433 LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A10/t01: Fail # Bug 5371433 -LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A13/t01: Fail # Bug 5371433 LangGuideTest/02_Language_Constructs/02_5_Meaning_of_Names/Examples/A02/t01: Fail # Bug 5371433 LangGuideTest/02_Language_Constructs/02_5_Meaning_of_Names/Shadowing_and_Hiding_Names/A01/t02: Fail # Bug 5371433 LangGuideTest/02_Language_Constructs/02_5_Meaning_of_Names/Shadowing_and_Hiding_Names/A02/t01: Fail # Bug 5371433 @@ -120,6 +116,12 @@ LangGuideTest/02_Language_Constructs/02_8_Static_Methods/A02/t02: Fail # Bug 537 LibTest/core/Array/length/Array/length/A01/t02: Fail # Bug 5371433 LibTest/core/Date/Date/Date/A01/t03: Fail # Bug 5371433 + +# The illegal constructor initializer in this test does not get compiled. +# This test does fail as it's supposed to when invoked with the --compile_all flag. +LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A08/t02: Skip + + # Following tests define a main with an argument, per new specification # we do not pass any argument to main. LangGuideTest/07_Overriding/A05/t01: Fail,Okay diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc index 68cc217ff0b..9b2b59c2296 100644 --- a/runtime/vm/parser.cc +++ b/runtime/vm/parser.cc @@ -1024,7 +1024,7 @@ AstNode* Parser::ParseSuperCall(const String& function_name) { String::Handle(current_class().Name()).ToCString()); } // 'this' parameter is the first argument to super call. - AstNode* implicit_argument = LoadReceiver(); + AstNode* implicit_argument = LoadReceiver(supercall_pos); ArgumentListNode* arguments = ParseActualParameters(implicit_argument, kAllowConst); // Resolve the function. @@ -1068,7 +1068,7 @@ AstNode* Parser::ParseSuperFieldAccess(const String& field_name) { ErrorMsg("class '%s' does not have a superclass", String::Handle(current_class().Name()).ToCString()); } - AstNode* implicit_argument = LoadReceiver(); + AstNode* implicit_argument = LoadReceiver(field_pos); const String& getter_name = String::ZoneHandle(Field::GetterName(field_name)); @@ -1144,8 +1144,11 @@ AstNode* Parser::ParseSuperInitializer(const Class& cls, } // 'this' parameter is the first argument to super class constructor. AstNode* implicit_argument = new LoadLocalNode(supercall_pos, *receiver); + // 'this' parameter must not be accessible to the other super call arguments. + receiver->set_invisible(true); ArgumentListNode* arguments = ParseActualParameters(implicit_argument, kAllowConst); + receiver->set_invisible(false); // Resolve the constructor. const Function& super_ctor = Function::ZoneHandle( super_class.LookupConstructor(ctor_name)); @@ -1171,10 +1174,11 @@ AstNode* Parser::ParseInitializer(const Class& cls, LocalVariable* receiver) { const String& field_name = *ExpectIdentifier("field name expected"); ExpectToken(Token::kASSIGN); - // TODO(5412278): Need to check or ensure that the initializer expression - // does not have access to the instance fields of the object. const bool saved_mode = SetAllowFunctionLiterals(false); + // "this" must not be accessible in initializer expressions. + receiver->set_invisible(true); AstNode* init_expr = ParseConditionalExpr(); + receiver->set_invisible(false); SetAllowFunctionLiterals(saved_mode); Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); if (field.IsNull()) { @@ -3114,7 +3118,7 @@ void Parser::CaptureReceiver() { } -AstNode* Parser::LoadReceiver() { +AstNode* Parser::LoadReceiver(intptr_t token_pos) { // A nested function may access 'this', referring to the receiver of the // outermost enclosing function. // We should not be loading the receiver from a static scope. @@ -3123,7 +3127,7 @@ AstNode* Parser::LoadReceiver() { const bool kTestOnly = false; LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly); if (receiver == NULL) { - ErrorMsg("illegal access to 'this'"); + ErrorMsg(token_pos, "illegal access to 'this'"); } return new LoadLocalNode(token_index_, *receiver); } @@ -5355,7 +5359,7 @@ AstNode* Parser::ParsePostfixExpr() { name.ToCString()); } else { // Treat as call to unresolved (instance) method. - AstNode* receiver = LoadReceiver(); + AstNode* receiver = LoadReceiver(primary->token_index()); selector = ParseInstanceCall(receiver, name); } } else { @@ -5383,7 +5387,7 @@ AstNode* Parser::ParsePostfixExpr() { "from static function", func_name.ToCString()); } - selector = ParseInstanceCall(LoadReceiver(), func_name); + selector = ParseInstanceCall(LoadReceiver(primary_pos), func_name); } } else if (primary->primary().IsString()) { // Primary is an unresolved name. @@ -5394,7 +5398,7 @@ AstNode* Parser::ParsePostfixExpr() { name.ToCString()); } else { // Treat as call to unresolved (instance) method. - AstNode* receiver = LoadReceiver(); + AstNode* receiver = LoadReceiver(primary->token_index()); selector = ParseInstanceCall(receiver, name); } } else if (primary->primary().IsClass()) { @@ -5428,7 +5432,7 @@ AstNode* Parser::ParsePostfixExpr() { ident.ToCString()); } else { // Treat as call to unresolved (instance) field. - AstNode* receiver = LoadReceiver(); + AstNode* receiver = LoadReceiver(primary->token_index()); postfix_expr = ParseInstanceFieldAccess(receiver, ident); } } else if (left->AsPrimaryNode()->primary().IsFunction()) { @@ -5450,7 +5454,7 @@ AstNode* Parser::ParsePostfixExpr() { "illegal use of method '%s'", funcname.ToCString()); } - AstNode* receiver = LoadReceiver(); + AstNode* receiver = LoadReceiver(primary->token_index()); postfix_expr = ParseInstanceFieldAccess(receiver, funcname); } } @@ -5709,7 +5713,7 @@ bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, if (!field.IsNull()) { if (node != NULL) { CheckInstanceFieldAccess(ident_pos, ident); - *node = CallGetter(ident_pos, LoadReceiver(), ident); + *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); } return true; } @@ -5729,7 +5733,7 @@ bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, if (node != NULL) { CheckInstanceFieldAccess(ident_pos, ident); ASSERT(Type::Handle(func.result_type()).IsResolved()); - *node = CallGetter(ident_pos, LoadReceiver(), ident); + *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); } return true; } @@ -5753,7 +5757,7 @@ bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, // when we try to invoke the getter. CheckInstanceFieldAccess(ident_pos, ident); ASSERT(Type::Handle(func.result_type()).IsResolved()); - *node = CallGetter(ident_pos, LoadReceiver(), ident); + *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); } return true; } @@ -5900,7 +5904,7 @@ AstNode* Parser::ResolveVarOrField(intptr_t ident_pos, const String& ident) { ident.ToCString()); } else { // Treat as call to unresolved instance field. - var_or_field = CallGetter(ident_pos, LoadReceiver(), ident); + var_or_field = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); } } else if (primary->primary().IsFunction()) { ErrorMsg(ident_pos, "illegal reference to method '%s'", diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h index b25ecbadd92..80721caec18 100644 --- a/runtime/vm/parser.h +++ b/runtime/vm/parser.h @@ -258,7 +258,7 @@ class Parser : ValueObject { LocalVariable* LookupReceiver(LocalScope* from_scope, bool test_only); void CaptureReceiver(); - AstNode* LoadReceiver(); + AstNode* LoadReceiver(intptr_t token_index); AstNode* CallGetter(intptr_t token_index, AstNode* object, const String& name); diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc index 81fa2e5344f..854686e5048 100644 --- a/runtime/vm/scopes.cc +++ b/runtime/vm/scopes.cc @@ -186,7 +186,7 @@ SourceLabel* LocalScope::LocalLookupLabel(const String& name) const { LocalVariable* LocalScope::LocalLookupVariable(const String& name) const { for (intptr_t i = 0; i < variables_.length(); i++) { LocalVariable* var = variables_[i]; - if (var->name().Equals(name)) { + if (var->name().Equals(name) && !var->is_invisible_) { return var; } } diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h index 37116a336f3..7e9238c52f1 100644 --- a/runtime/vm/scopes.h +++ b/runtime/vm/scopes.h @@ -25,6 +25,7 @@ class LocalVariable : public ZoneAllocated { type_(type), is_final_(false), is_captured_(false), + is_invisible_(false), index_(LocalVariable::kUnitializedIndex_) { ASSERT(type.IsZoneHandle()); ASSERT(type.IsFinalized()); @@ -59,6 +60,10 @@ class LocalVariable : public ZoneAllocated { index_ = index; } + void set_invisible(bool value) { + is_invisible_ = value; + } + private: static const int kUnitializedIndex_ = INT_MIN; @@ -71,9 +76,11 @@ class LocalVariable : public ZoneAllocated { bool is_final_; // If true, this variable is readonly. bool is_captured_; // If true, this variable lives in the context, otherwise // in the stack frame. + bool is_invisible_; int index_; // Allocation index in words relative to frame pointer (if not // captured), or relative to the context pointer (if captured). + friend class LocalScope; DISALLOW_COPY_AND_ASSIGN(LocalVariable); };