aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/escape.cc35
-rw-r--r--gcc/go/gofrontend/expressions.cc47
-rw-r--r--gcc/go/gofrontend/expressions.h65
4 files changed, 102 insertions, 47 deletions
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<Type_conversion_expression, EXPRESSION_CONVERSION>(); }
+ // 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<Unsafe_type_conversion_expression,
+ EXPRESSION_UNSAFE_CONVERSION>();
+ }
+
// 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*);