summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/expressions.cc')
-rw-r--r--gcc/go/gofrontend/expressions.cc82
1 files changed, 70 insertions, 12 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index bd2e3183bfe..74ae9ddcd7d 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -555,6 +555,10 @@ class Error_expression : public Expression
{ return true; }
bool
+ do_is_immutable() const
+ { return true; }
+
+ bool
do_numeric_constant_value(Numeric_constant* nc) const
{
nc->set_unsigned_long(NULL, 0);
@@ -1422,6 +1426,10 @@ class Boolean_expression : public Expression
do_is_constant() const
{ return true; }
+ bool
+ do_is_immutable() const
+ { return true; }
+
Type*
do_type();
@@ -1790,6 +1798,10 @@ class Integer_expression : public Expression
{ return true; }
bool
+ do_is_immutable() const
+ { return true; }
+
+ bool
do_numeric_constant_value(Numeric_constant* nc) const;
Type*
@@ -2109,6 +2121,10 @@ class Float_expression : public Expression
{ return true; }
bool
+ do_is_immutable() const
+ { return true; }
+
+ bool
do_numeric_constant_value(Numeric_constant* nc) const
{
nc->set_float(this->type_, this->val_);
@@ -2292,6 +2308,10 @@ class Complex_expression : public Expression
{ return true; }
bool
+ do_is_immutable() const
+ { return true; }
+
+ bool
do_numeric_constant_value(Numeric_constant* nc) const
{
nc->set_complex(this->type_, this->real_, this->imag_);
@@ -2506,6 +2526,10 @@ class Const_expression : public Expression
{ return true; }
bool
+ do_is_immutable() const
+ { return true; }
+
+ bool
do_numeric_constant_value(Numeric_constant* nc) const;
bool
@@ -2768,12 +2792,12 @@ Const_expression::do_get_tree(Translate_context* context)
// If the type has been set for this expression, but the underlying
// object is an abstract int or float, we try to get the abstract
// value. Otherwise we may lose something in the conversion.
+ Expression* expr = this->constant_->const_value()->expr();
if (this->type_ != NULL
&& this->type_->is_numeric_type()
&& (this->constant_->const_value()->type() == NULL
|| this->constant_->const_value()->type()->is_abstract()))
{
- Expression* expr = this->constant_->const_value()->expr();
Numeric_constant nc;
if (expr->numeric_constant_value(&nc)
&& nc.set_type(this->type_, false, this->location()))
@@ -2783,15 +2807,9 @@ Const_expression::do_get_tree(Translate_context* context)
}
}
- Gogo* gogo = context->gogo();
- Bexpression* ret =
- tree_to_expr(this->constant_->get_tree(gogo, context->function()));
if (this->type_ != NULL)
- {
- Btype* btype = this->type_->get_backend(gogo);
- ret = gogo->backend()->convert_expression(btype, ret, this->location());
- }
- return expr_to_tree(ret);
+ expr = Expression::make_cast(this->type_, expr, this->location());
+ return expr->get_tree(context);
}
// Dump ast representation for constant expression.
@@ -2994,6 +3012,9 @@ class Type_conversion_expression : public Expression
do_is_constant() const;
bool
+ do_is_immutable() const;
+
+ bool
do_numeric_constant_value(Numeric_constant*) const;
bool
@@ -3175,6 +3196,27 @@ Type_conversion_expression::do_is_constant() const
return true;
}
+// Return whether a type conversion is immutable.
+
+bool
+Type_conversion_expression::do_is_immutable() const
+{
+ Type* type = this->type_;
+ Type* expr_type = this->expr_->type();
+
+ if (type->interface_type() != NULL
+ || expr_type->interface_type() != NULL)
+ return false;
+
+ if (!this->expr_->is_immutable())
+ return false;
+
+ if (Type::are_identical(type, expr_type, false, NULL))
+ return true;
+
+ return type->is_basic_type() && expr_type->is_basic_type();
+}
+
// Return the constant numeric value if there is one.
bool
@@ -3599,7 +3641,8 @@ class Unary_expression : public Expression
bool
do_is_immutable() const
- { return this->expr_->is_immutable(); }
+ { return this->expr_->is_immutable()
+ || (this->op_ == OPERATOR_AND && this->expr_->is_variable()); }
bool
do_numeric_constant_value(Numeric_constant*) const;
@@ -9570,9 +9613,20 @@ Call_expression::do_get_tree(Translate_context* context)
fn = Expression::make_compound(set_closure, fn, location);
}
- Btype* bft = fntype->get_backend_fntype(gogo);
Bexpression* bfn = tree_to_expr(fn->get_tree(context));
- bfn = gogo->backend()->convert_expression(bft, bfn, location);
+
+ // When not calling a named function directly, use a type conversion
+ // in case the type of the function is a recursive type which refers
+ // to itself. We don't do this for an interface method because 1)
+ // an interface method never refers to itself, so we always have a
+ // function type here; 2) we pass an extra first argument to an
+ // interface method, so fntype is not correct.
+ if (func == NULL && !is_interface_method)
+ {
+ Btype* bft = fntype->get_backend_fntype(gogo);
+ bfn = gogo->backend()->convert_expression(bft, bfn, location);
+ }
+
Bexpression* call = gogo->backend()->call_expression(bfn, fn_args, location);
if (this->results_ != NULL)
@@ -14076,6 +14130,10 @@ class Type_info_expression : public Expression
{ }
protected:
+ bool
+ do_is_immutable() const
+ { return true; }
+
Type*
do_type();