From 05d556e8371b90c5de4175aa737a7ad83726eeee Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 14 Dec 2010 05:54:33 +0000 Subject: [PATCH] Don't incorrectly parse expression as type switch. Improve error reporting of invalid type assertions. From-SVN: r167787 --- gcc/go/gofrontend/expressions.cc | 25 +++++++++++++++---------- gcc/go/gofrontend/parse.cc | 17 +++++++++++------ gcc/go/gofrontend/statements.cc | 3 ++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 022f5ce..6320f09 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -11620,24 +11620,29 @@ Type_guard_expression::do_check_types(Gogo*) this->report_error(_("invalid unsafe.Pointer conversion")); } else if (expr_type->interface_type() == NULL) - this->report_error(_("type assertion only valid for interface types")); + { + if (!expr_type->is_error_type() && !this->type_->is_error_type()) + this->report_error(_("type assertion only valid for interface types")); + this->set_is_error(); + } else if (this->type_->interface_type() == NULL) { std::string reason; if (!expr_type->interface_type()->implements_interface(this->type_, &reason)) { - if (reason.empty()) - this->report_error(_("impossible type assertion: " - "type does not implement interface")); - else + if (!this->type_->is_error_type()) { - error_at(this->location(), - ("impossible type assertion: " - "type does not implement interface (%s)"), - reason.c_str()); - this->set_is_error(); + if (reason.empty()) + this->report_error(_("impossible type assertion: " + "type does not implement interface")); + else + error_at(this->location(), + ("impossible type assertion: " + "type does not implement interface (%s)"), + reason.c_str()); } + this->set_is_error(); } } } diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index c8b55c5..5f4cef5 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -2647,12 +2647,18 @@ Parse::selector(Expression* left, bool* is_type_switch) { this->advance_token(); Type* type = NULL; - if (is_type_switch == NULL - || !this->peek_token()->is_keyword(KEYWORD_TYPE)) + if (!this->peek_token()->is_keyword(KEYWORD_TYPE)) type = this->type(); else { - *is_type_switch = true; + if (is_type_switch != NULL) + *is_type_switch = true; + else + { + error_at(this->location(), + "use of %<.(type)%> outside type switch"); + type = Type::make_error_type(); + } this->advance_token(); } if (!this->peek_token()->is_op(OPERATOR_RPAREN)) @@ -2866,7 +2872,7 @@ Parse::expression(Precedence precedence, bool may_be_sink, left = this->verify_not_sink(left); Expression* right = this->expression(right_precedence, false, may_be_composite_lit, - is_type_switch); + NULL); if (op == OPERATOR_CHANOP) left = Expression::make_send(left, right, binop_location); else @@ -2959,8 +2965,7 @@ Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit, return Expression::make_type(this->type(), location); } - Expression* expr = this->unary_expr(false, may_be_composite_lit, - is_type_switch); + Expression* expr = this->unary_expr(false, may_be_composite_lit, NULL); if (expr->is_error_expression()) ; else if (op == OPERATOR_MULT && expr->is_type_expression()) diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 10fe7e4..2d17797 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -1296,7 +1296,8 @@ Tuple_type_guard_assignment_statement::do_lower(Gogo*, Block* enclosing) Type* expr_type = this->expr_->type(); if (expr_type->interface_type() == NULL) { - this->report_error(_("type assertion only valid for interface types")); + if (!expr_type->is_error_type() && !this->type_->is_error_type()) + this->report_error(_("type assertion only valid for interface types")); return Statement::make_error_statement(loc); } -- 2.7.4