diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 199ba948ac5..dd94df5082f 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -a5122ab435cf40c22b110487eb5f189ee28e77f4 +1b3d945d201bcb1238f15ef154c6e4671e4c6f5c The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc index d54b7cc9eb2..3a5738381d4 100644 --- a/gcc/go/gofrontend/escape.cc +++ b/gcc/go/gofrontend/escape.cc @@ -547,6 +547,41 @@ Build_connection_graphs::resolve_var_reference(Expression* expr) expr = expr->type_guard_expression()->expr(); break; + case Expression::EXPRESSION_UNSAFE_CONVERSION: + { + Expression* e = expr->unsafe_conversion_expression()->expr(); + if (e->call_result_expression() != NULL + && e->call_result_expression()->index() == 0) + { + // a, ok := p.(T) gets lowered into a call to one of the interface + // to type conversion functions instead of a type guard expression. + // We only want to make a connection between a and p, the bool + // result should not escape because p escapes. + e = e->call_result_expression()->call(); + + Named_object* fn = + e->call_expression()->fn()->func_expression()->named_object(); + std::string fn_name = fn->name(); + if (fn->package() == NULL + && fn->is_function_declaration() + && !fn->func_declaration_value()->asm_name().empty()) + { + if (fn_name == "ifaceI2E2" + || fn_name == "ifaceI2I2") + e = e->call_expression()->args()->at(0); + else if (fn_name == "ifaceE2I2" + || fn_name == "ifaceI2I2" + || fn_name == "ifaceE2T2P" + || fn_name == "ifaceI2T2P" + || fn_name == "ifaceE2T2" + || fn_name == "ifaceI2T2") + e = e->call_expression()->args()->at(1); + } + } + expr = e; + } + break; + default: done = true; break; diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index c9ba9884489..76b83286c09 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3391,52 +3391,7 @@ Expression::make_cast(Type* type, Expression* val, Location location) return new Type_conversion_expression(type, val, location); } -// An unsafe type conversion, used to pass values to builtin functions. - -class Unsafe_type_conversion_expression : public Expression -{ - public: - Unsafe_type_conversion_expression(Type* type, Expression* expr, - Location location) - : Expression(EXPRESSION_UNSAFE_CONVERSION, location), - type_(type), expr_(expr) - { } - - protected: - int - do_traverse(Traverse* traverse); - - bool - do_is_immutable() const; - - Type* - do_type() - { return this->type_; } - - void - do_determine_type(const Type_context*) - { this->expr_->determine_type_no_context(); } - - Expression* - do_copy() - { - return new Unsafe_type_conversion_expression(this->type_, - this->expr_->copy(), - this->location()); - } - - Bexpression* - do_get_backend(Translate_context*); - - void - do_dump_expression(Ast_dump_context*) const; - - private: - // The type to convert to. - Type* type_; - // The expression to convert. - Expression* expr_; -}; +// Class Unsafe_type_conversion_expression. // Traversal. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 0c4ea6ba454..6d0f6a4c011 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -32,6 +32,7 @@ class Temporary_reference_expression; class Set_and_use_temporary_expression; class String_expression; class Type_conversion_expression; +class Unsafe_type_conversion_expression; class Unary_expression; class Binary_expression; class Call_expression; @@ -571,6 +572,15 @@ class Expression conversion_expression() { return this->convert(); } + // If this is an unsafe conversion expression, return the + // Unsafe_type_conversion_expression structure. Otherwise, return NULL. + Unsafe_type_conversion_expression* + unsafe_conversion_expression() + { + return this->convert(); + } + // Return whether this is the expression nil. bool is_nil_expression() const @@ -1505,6 +1515,57 @@ class Type_conversion_expression : public Expression bool may_convert_function_types_; }; +// An unsafe type conversion, used to pass values to builtin functions. + +class Unsafe_type_conversion_expression : public Expression +{ + public: + Unsafe_type_conversion_expression(Type* type, Expression* expr, + Location location) + : Expression(EXPRESSION_UNSAFE_CONVERSION, location), + type_(type), expr_(expr) + { } + + Expression* + expr() const + { return this->expr_; } + + protected: + int + do_traverse(Traverse* traverse); + + bool + do_is_immutable() const; + + Type* + do_type() + { return this->type_; } + + void + do_determine_type(const Type_context*) + { this->expr_->determine_type_no_context(); } + + Expression* + do_copy() + { + return new Unsafe_type_conversion_expression(this->type_, + this->expr_->copy(), + this->location()); + } + + Bexpression* + do_get_backend(Translate_context*); + + void + do_dump_expression(Ast_dump_context*) const; + + private: + // The type to convert to. + Type* type_; + // The expression to convert. + Expression* expr_; +}; + // A Unary expression. class Unary_expression : public Expression @@ -2024,6 +2085,10 @@ class Call_result_expression : public Expression call() const { return this->call_; } + unsigned int + index() const + { return this->index_; } + protected: int do_traverse(Traverse*);