OSDN Git Service

compiler: No error if shift operand inherits interface type.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / expressions.cc
index a266694..3fa1cd6 100644 (file)
@@ -168,7 +168,8 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
   if (lhs_type_tree == error_mark_node)
     return error_mark_node;
 
-  if (lhs_type != rhs_type && lhs_type->interface_type() != NULL)
+  if (lhs_type->forwarded() != rhs_type->forwarded()
+      && lhs_type->interface_type() != NULL)
     {
       if (rhs_type->interface_type() == NULL)
        return Expression::convert_type_to_interface(context, lhs_type,
@@ -179,7 +180,8 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
                                                          rhs_type, rhs_tree,
                                                          false, location);
     }
-  else if (lhs_type != rhs_type && rhs_type->interface_type() != NULL)
+  else if (lhs_type->forwarded() != rhs_type->forwarded()
+          && rhs_type->interface_type() != NULL)
     return Expression::convert_interface_to_type(context, lhs_type, rhs_type,
                                                 rhs_tree, location);
   else if (lhs_type->is_slice_type() && rhs_type->is_nil_type())
@@ -299,19 +301,25 @@ Expression::convert_type_to_interface(Translate_context* context,
       // object type: a list of function pointers for each interface
       // method.
       Named_type* rhs_named_type = rhs_type->named_type();
+      Struct_type* rhs_struct_type = rhs_type->struct_type();
       bool is_pointer = false;
-      if (rhs_named_type == NULL)
+      if (rhs_named_type == NULL && rhs_struct_type == NULL)
        {
          rhs_named_type = rhs_type->deref()->named_type();
+         rhs_struct_type = rhs_type->deref()->struct_type();
          is_pointer = true;
        }
       tree method_table;
-      if (rhs_named_type == NULL)
-       method_table = null_pointer_node;
-      else
+      if (rhs_named_type != NULL)
        method_table =
          rhs_named_type->interface_method_table(gogo, lhs_interface_type,
                                                 is_pointer);
+      else if (rhs_struct_type != NULL)
+       method_table =
+         rhs_struct_type->interface_method_table(gogo, lhs_interface_type,
+                                                 is_pointer);
+      else
+       method_table = null_pointer_node;
       first_field_value = fold_convert_loc(location.gcc_location(),
                                            const_ptr_type_node, method_table);
     }
@@ -1312,30 +1320,18 @@ Func_expression::do_get_tree(Translate_context* context)
             && TREE_CODE(TREE_OPERAND(fnaddr, 0)) == FUNCTION_DECL);
   TREE_ADDRESSABLE(TREE_OPERAND(fnaddr, 0)) = 1;
 
-  // For a normal non-nested function call, that is all we have to do.
-  if (!this->function_->is_function()
-      || this->function_->func_value()->enclosing() == NULL)
-    {
-      go_assert(this->closure_ == NULL);
-      return fnaddr;
-    }
+  // If there is no closure, that is all have to do.
+  if (this->closure_ == NULL)
+    return fnaddr;
 
-  // For a nested function call, we have to always allocate a
-  // trampoline.  If we don't always allocate, then closures will not
-  // be reliably distinct.
-  Expression* closure = this->closure_;
-  tree closure_tree;
-  if (closure == NULL)
-    closure_tree = null_pointer_node;
-  else
-    {
-      // Get the value of the closure.  This will be a pointer to
-      // space allocated on the heap.
-      closure_tree = closure->get_tree(context);
-      if (closure_tree == error_mark_node)
-       return error_mark_node;
-      go_assert(POINTER_TYPE_P(TREE_TYPE(closure_tree)));
-    }
+  go_assert(this->function_->func_value()->enclosing() != NULL);
+
+  // Get the value of the closure.  This will be a pointer to space
+  // allocated on the heap.
+  tree closure_tree = this->closure_->get_tree(context);
+  if (closure_tree == error_mark_node)
+    return error_mark_node;
+  go_assert(POINTER_TYPE_P(TREE_TYPE(closure_tree)));
 
   // Now we need to build some code on the heap.  This code will load
   // the static chain pointer with the closure and then jump to the
@@ -3606,8 +3602,7 @@ Unary_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
       return Expression::make_error(this->location());
     }
 
-  if (op == OPERATOR_PLUS || op == OPERATOR_MINUS
-      || op == OPERATOR_NOT || op == OPERATOR_XOR)
+  if (op == OPERATOR_PLUS || op == OPERATOR_MINUS || op == OPERATOR_XOR)
     {
       Numeric_constant nc;
       if (expr->numeric_constant_value(&nc))
@@ -3697,10 +3692,10 @@ Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
       else
        go_unreachable();
 
-    case OPERATOR_NOT:
     case OPERATOR_XOR:
       break;
 
+    case OPERATOR_NOT:
     case OPERATOR_AND:
     case OPERATOR_MULT:
       return false;
@@ -3713,7 +3708,10 @@ Unary_expression::eval_constant(Operator op, const Numeric_constant* unc,
     return false;
 
   mpz_t uval;
-  unc->get_int(&uval);
+  if (unc->is_rune())
+    unc->get_rune(&uval);
+  else
+    unc->get_int(&uval);
   mpz_t val;
   mpz_init(val);
 
@@ -3911,6 +3909,10 @@ Unary_expression::do_check_types(Gogo*)
       break;
 
     case OPERATOR_NOT:
+      if (!type->is_boolean_type())
+       this->report_error(_("expected boolean type"));
+      break;
+
     case OPERATOR_XOR:
       if (type->integer_type() == NULL
          && !type->is_boolean_type())
@@ -4038,19 +4040,50 @@ Unary_expression::do_get_tree(Translate_context* context)
 
       if (this->create_temp_
          && !TREE_ADDRESSABLE(TREE_TYPE(expr))
-         && !DECL_P(expr)
+         && (TREE_CODE(expr) == CONST_DECL || !DECL_P(expr))
          && TREE_CODE(expr) != INDIRECT_REF
          && TREE_CODE(expr) != COMPONENT_REF)
        {
-         tree tmp = create_tmp_var(TREE_TYPE(expr), get_name(expr));
-         DECL_IGNORED_P(tmp) = 1;
-         DECL_INITIAL(tmp) = expr;
-         TREE_ADDRESSABLE(tmp) = 1;
-         return build2_loc(loc.gcc_location(), COMPOUND_EXPR,
-                           build_pointer_type(TREE_TYPE(expr)),
-                           build1_loc(loc.gcc_location(), DECL_EXPR,
-                                       void_type_node, tmp),
-                           build_fold_addr_expr_loc(loc.gcc_location(), tmp));
+         if (current_function_decl != NULL)
+           {
+             tree tmp = create_tmp_var(TREE_TYPE(expr), get_name(expr));
+             DECL_IGNORED_P(tmp) = 1;
+             DECL_INITIAL(tmp) = expr;
+             TREE_ADDRESSABLE(tmp) = 1;
+             return build2_loc(loc.gcc_location(), COMPOUND_EXPR,
+                               build_pointer_type(TREE_TYPE(expr)),
+                               build1_loc(loc.gcc_location(), DECL_EXPR,
+                                          void_type_node, tmp),
+                               build_fold_addr_expr_loc(loc.gcc_location(),
+                                                        tmp));
+           }
+         else
+           {
+             tree tmp = build_decl(loc.gcc_location(), VAR_DECL,
+                                   create_tmp_var_name("A"), TREE_TYPE(expr));
+             DECL_EXTERNAL(tmp) = 0;
+             TREE_PUBLIC(tmp) = 0;
+             TREE_STATIC(tmp) = 1;
+             DECL_ARTIFICIAL(tmp) = 1;
+             TREE_ADDRESSABLE(tmp) = 1;
+             tree make_tmp;
+             if (!TREE_CONSTANT(expr))
+               make_tmp = fold_build2_loc(loc.gcc_location(), INIT_EXPR,
+                                          void_type_node, tmp, expr);
+             else
+               {
+                 TREE_READONLY(tmp) = 1;
+                 TREE_CONSTANT(tmp) = 1;
+                 DECL_INITIAL(tmp) = expr;
+                 make_tmp = NULL_TREE;
+               }
+             rest_of_decl_compilation(tmp, 1, 0);
+             tree addr = build_fold_addr_expr_loc(loc.gcc_location(), tmp);
+             if (make_tmp == NULL_TREE)
+               return addr;
+             return build2_loc(loc.gcc_location(), COMPOUND_EXPR,
+                               TREE_TYPE(addr), make_tmp, addr);
+           }
        }
 
       return build_fold_addr_expr_loc(loc.gcc_location(), expr);
@@ -4450,9 +4483,8 @@ Binary_expression::eval_constant(Operator op, Numeric_constant* left_nc,
     case OPERATOR_LE:
     case OPERATOR_GT:
     case OPERATOR_GE:
-      // These return boolean values and as such must be handled
-      // elsewhere.
-      go_unreachable();
+      // These return boolean values, not numeric.
+      return false;
     default:
       break;
     }
@@ -5058,7 +5090,7 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
                                                     &right_nc, location,
                                                     &result))
              return this;
-           return Expression::make_cast(Type::lookup_bool_type(),
+           return Expression::make_cast(Type::make_boolean_type(),
                                         Expression::make_boolean(result,
                                                                  location),
                                         location);
@@ -5089,10 +5121,7 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*,
            {
              int cmp = left_string.compare(right_string);
              bool r = Binary_expression::cmp_to_bool(op, cmp);
-             return Expression::make_cast(Type::lookup_bool_type(),
-                                          Expression::make_boolean(r,
-                                                                   location),
-                                          location);
+             return Expression::make_boolean(r, location);
            }
        }
     }
@@ -5161,6 +5190,9 @@ Binary_expression::lower_struct_comparison(Gogo* gogo,
        pf != fields->end();
        ++pf, ++field_index)
     {
+      if (Gogo::is_sink_name(pf->field_name()))
+       continue;
+
       if (field_index > 0)
        {
          if (left_temp == NULL)
@@ -5279,24 +5311,13 @@ Binary_expression::operand_address(Statement_inserter* inserter,
 bool
 Binary_expression::do_numeric_constant_value(Numeric_constant* nc) const
 {
-  Operator op = this->op_;
-
-  if (op == OPERATOR_EQEQ
-      || op == OPERATOR_NOTEQ
-      || op == OPERATOR_LT
-      || op == OPERATOR_LE
-      || op == OPERATOR_GT
-      || op == OPERATOR_GE)
-    return false;
-
   Numeric_constant left_nc;
   if (!this->left_->numeric_constant_value(&left_nc))
     return false;
   Numeric_constant right_nc;
   if (!this->right_->numeric_constant_value(&right_nc))
     return false;
-
-  return Binary_expression::eval_constant(op, &left_nc, &right_nc,
+  return Binary_expression::eval_constant(this->op_, &left_nc, &right_nc,
                                          this->location(), nc);
 }
 
@@ -5321,15 +5342,15 @@ Binary_expression::do_type()
 
   switch (this->op_)
     {
-    case OPERATOR_OROR:
-    case OPERATOR_ANDAND:
     case OPERATOR_EQEQ:
     case OPERATOR_NOTEQ:
     case OPERATOR_LT:
     case OPERATOR_LE:
     case OPERATOR_GT:
     case OPERATOR_GE:
-      return Type::lookup_bool_type();
+      if (this->type_ == NULL)
+       this->type_ = Type::make_boolean_type();
+      return this->type_;
 
     case OPERATOR_PLUS:
     case OPERATOR_MINUS:
@@ -5340,6 +5361,8 @@ Binary_expression::do_type()
     case OPERATOR_MOD:
     case OPERATOR_AND:
     case OPERATOR_BITCLEAR:
+    case OPERATOR_OROR:
+    case OPERATOR_ANDAND:
       {
        Type* type;
        if (!Binary_expression::operation_type(this->op_,
@@ -5436,7 +5459,8 @@ Binary_expression::do_determine_type(const Type_context* context)
          && (this->left_->type()->integer_type() == NULL
              || (subcontext.type->integer_type() == NULL
                  && subcontext.type->float_type() == NULL
-                 && subcontext.type->complex_type() == NULL)))
+                 && subcontext.type->complex_type() == NULL
+                 && subcontext.type->interface_type() == NULL)))
        this->report_error(("invalid context-determined non-integer type "
                            "for shift operand"));
 
@@ -5447,6 +5471,16 @@ Binary_expression::do_determine_type(const Type_context* context)
     }
 
   this->right_->determine_type(&subcontext);
+
+  if (is_comparison)
+    {
+      if (this->type_ != NULL && !this->type_->is_abstract())
+       ;
+      else if (context->type != NULL && context->type->is_boolean_type())
+       this->type_ = context->type;
+      else if (!context->may_be_abstract)
+       this->type_ = Type::lookup_bool_type();
+    }
 }
 
 // Report an error if the binary operator OP does not support TYPE.
@@ -5658,7 +5692,7 @@ Binary_expression::do_get_tree(Translate_context* context)
     case OPERATOR_LE:
     case OPERATOR_GT:
     case OPERATOR_GE:
-      return Expression::comparison_tree(context, this->op_,
+      return Expression::comparison_tree(context, this->type_, this->op_,
                                         this->left_->type(), left,
                                         this->right_->type(), right,
                                         this->location());
@@ -6119,8 +6153,8 @@ Expression::make_binary(Operator op, Expression* left, Expression* right,
 // Implement a comparison.
 
 tree
-Expression::comparison_tree(Translate_context* context, Operator op,
-                           Type* left_type, tree left_tree,
+Expression::comparison_tree(Translate_context* context, Type* result_type,
+                           Operator op, Type* left_type, tree left_tree,
                            Type* right_type, tree right_tree,
                            Location location)
 {
@@ -6188,7 +6222,9 @@ Expression::comparison_tree(Translate_context* context, Operator op,
          make_tmp = NULL_TREE;
          arg = right_tree;
        }
-      else if (TREE_ADDRESSABLE(TREE_TYPE(right_tree)) || DECL_P(right_tree))
+      else if (TREE_ADDRESSABLE(TREE_TYPE(right_tree))
+              || (TREE_CODE(right_tree) != CONST_DECL
+                  && DECL_P(right_tree)))
        {
          make_tmp = NULL_TREE;
          arg = build_fold_addr_expr_loc(location.gcc_location(), right_tree);
@@ -6359,7 +6395,13 @@ Expression::comparison_tree(Translate_context* context, Operator op,
   if (left_tree == error_mark_node || right_tree == error_mark_node)
     return error_mark_node;
 
-  tree ret = fold_build2(code, boolean_type_node, left_tree, right_tree);
+  tree result_type_tree;
+  if (result_type == NULL)
+    result_type_tree = boolean_type_node;
+  else
+    result_type_tree = type_to_tree(result_type->get_backend(context->gogo()));
+
+  tree ret = fold_build2(code, result_type_tree, left_tree, right_tree);
   if (CAN_HAVE_LOCATION_P(ret))
     SET_EXPR_LOCATION(ret, location.gcc_location());
   return ret;
@@ -6650,38 +6692,6 @@ Builtin_call_expression::do_set_recover_arg(Expression* arg)
   this->set_args(new_args);
 }
 
-// A traversal class which looks for a call expression.
-
-class Find_call_expression : public Traverse
-{
- public:
-  Find_call_expression()
-    : Traverse(traverse_expressions),
-      found_(false)
-  { }
-
-  int
-  expression(Expression**);
-
-  bool
-  found()
-  { return this->found_; }
-
- private:
-  bool found_;
-};
-
-int
-Find_call_expression::expression(Expression** pexpr)
-{
-  if ((*pexpr)->call_expression() != NULL)
-    {
-      this->found_ = true;
-      return TRAVERSE_EXIT;
-    }
-  return TRAVERSE_CONTINUE;
-}
-
 // Lower a builtin call expression.  This turns new and make into
 // specific expressions.  We also convert to a constant if we can.
 
@@ -6702,20 +6712,6 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
 
   if (this->is_constant())
     {
-      // We can only lower len and cap if there are no function calls
-      // in the arguments.  Otherwise we have to make the call.
-      if (this->code_ == BUILTIN_LEN || this->code_ == BUILTIN_CAP)
-       {
-         Expression* arg = this->one_arg();
-         if (arg != NULL && !arg->is_constant())
-           {
-             Find_call_expression find_call;
-             Expression::traverse(&arg, &find_call);
-             if (find_call.found())
-               return this;
-           }
-       }
-
       Numeric_constant nc;
       if (this->numeric_constant_value(&nc))
        return nc.expression(loc);
@@ -7032,8 +7028,42 @@ Builtin_call_expression::one_arg() const
   return args->front();
 }
 
-// Return whether this is constant: len of a string, or len or cap of
-// a fixed array, or unsafe.Sizeof, unsafe.Offsetof, unsafe.Alignof.
+// A traversal class which looks for a call or receive expression.
+
+class Find_call_expression : public Traverse
+{
+ public:
+  Find_call_expression()
+    : Traverse(traverse_expressions),
+      found_(false)
+  { }
+
+  int
+  expression(Expression**);
+
+  bool
+  found()
+  { return this->found_; }
+
+ private:
+  bool found_;
+};
+
+int
+Find_call_expression::expression(Expression** pexpr)
+{
+  if ((*pexpr)->call_expression() != NULL
+      || (*pexpr)->receive_expression() != NULL)
+    {
+      this->found_ = true;
+      return TRAVERSE_EXIT;
+    }
+  return TRAVERSE_CONTINUE;
+}
+
+// Return whether this is constant: len of a string constant, or len
+// or cap of an array, or unsafe.Sizeof, unsafe.Offsetof,
+// unsafe.Alignof.
 
 bool
 Builtin_call_expression::do_is_constant() const
@@ -7056,6 +7086,17 @@ Builtin_call_expression::do_is_constant() const
            && !arg_type->points_to()->is_slice_type())
          arg_type = arg_type->points_to();
 
+       // The len and cap functions are only constant if there are no
+       // function calls or channel operations in the arguments.
+       // Otherwise we have to make the call.
+       if (!arg->is_constant())
+         {
+           Find_call_expression find_call;
+           Expression::traverse(&arg, &find_call);
+           if (find_call.found())
+             return false;
+         }
+
        if (arg_type->array_type() != NULL
            && arg_type->array_type()->length() != NULL)
          return true;
@@ -7442,7 +7483,7 @@ Builtin_call_expression::do_determine_type(const Type_context* context)
        if (args != NULL && args->size() == 2)
          {
            Type* t1 = args->front()->type();
-           Type* t2 = args->front()->type();
+           Type* t2 = args->back()->type();
            if (!t1->is_abstract())
              arg_type = t1;
            else if (!t2->is_abstract())
@@ -11786,8 +11827,7 @@ Open_array_construction_expression::do_get_tree(Translate_context* context)
       if (this->indexes() == NULL)
        max_index = this->vals()->size() - 1;
       else
-       max_index = *std::max_element(this->indexes()->begin(),
-                                     this->indexes()->end());
+       max_index = this->indexes()->back();
       tree max_tree = size_int(max_index);
       tree constructor_type = build_array_type(element_type_tree,
                                               build_index_type(max_tree));
@@ -12538,6 +12578,17 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
   return ret;
 }
 
+// Used to sort an index/value array.
+
+class Index_value_compare
+{
+ public:
+  bool
+  operator()(const std::pair<unsigned long, Expression*>& a,
+            const std::pair<unsigned long, Expression*>& b)
+  { return a.first < b.first; }
+};
+
 // Lower an array composite literal.
 
 Expression*
@@ -12549,6 +12600,7 @@ Composite_literal_expression::lower_array(Type* type)
 
   std::vector<unsigned long>* indexes = new std::vector<unsigned long>;
   indexes->reserve(this->vals_->size());
+  bool indexes_out_of_order = false;
   Expression_list* vals = new Expression_list();
   vals->reserve(this->vals_->size());
   unsigned long index = 0;
@@ -12619,6 +12671,9 @@ Composite_literal_expression::lower_array(Type* type)
              return Expression::make_error(location);
            }
 
+         if (!indexes->empty() && index < indexes->back())
+           indexes_out_of_order = true;
+
          indexes->push_back(index);
        }
 
@@ -12633,6 +12688,34 @@ Composite_literal_expression::lower_array(Type* type)
       indexes = NULL;
     }
 
+  if (indexes_out_of_order)
+    {
+      typedef std::vector<std::pair<unsigned long, Expression*> > V;
+
+      V v;
+      v.reserve(indexes->size());
+      std::vector<unsigned long>::const_iterator pi = indexes->begin();
+      for (Expression_list::const_iterator pe = vals->begin();
+          pe != vals->end();
+          ++pe, ++pi)
+       v.push_back(std::make_pair(*pi, *pe));
+
+      std::sort(v.begin(), v.end(), Index_value_compare());
+
+      delete indexes;
+      delete vals;
+      indexes = new std::vector<unsigned long>();
+      indexes->reserve(v.size());
+      vals = new Expression_list();
+      vals->reserve(v.size());
+
+      for (V::const_iterator p = v.begin(); p != v.end(); ++p)
+       {
+         indexes->push_back(p->first);
+         vals->push_back(p->second);
+       }
+    }
+
   return this->make_array(type, indexes, vals);
 }
 
@@ -12653,7 +12736,9 @@ Composite_literal_expression::make_array(
       size_t size;
       if (vals == NULL)
        size = 0;
-      else if (indexes == NULL)
+      else if (indexes != NULL)
+       size = indexes->back() + 1;
+      else
        {
          size = vals->size();
          Integer_type* it = Type::lookup_integer_type("int")->integer_type();
@@ -12664,11 +12749,6 @@ Composite_literal_expression::make_array(
              return Expression::make_error(location);
            }
        }
-      else
-       {
-         size = *std::max_element(indexes->begin(), indexes->end());
-         ++size;
-       }
 
       mpz_t vlen;
       mpz_init_set_ui(vlen, size);
@@ -12696,8 +12776,7 @@ Composite_literal_expression::make_array(
            }
          else
            {
-             unsigned long max = *std::max_element(indexes->begin(),
-                                                   indexes->end());
+             unsigned long max = indexes->back();
              if (max >= val)
                {
                  error_at(location,
@@ -12868,26 +12947,8 @@ Type_guard_expression::do_traverse(Traverse* traverse)
 void
 Type_guard_expression::do_check_types(Gogo*)
 {
-  // 6g permits using a type guard with unsafe.pointer; we are
-  // compatible.
   Type* expr_type = this->expr_->type();
-  if (expr_type->is_unsafe_pointer_type())
-    {
-      if (this->type_->points_to() == NULL
-         && (this->type_->integer_type() == NULL
-             || (this->type_->forwarded()
-                 != Type::lookup_integer_type("uintptr"))))
-       this->report_error(_("invalid unsafe.Pointer conversion"));
-    }
-  else if (this->type_->is_unsafe_pointer_type())
-    {
-      if (expr_type->points_to() == NULL
-         && (expr_type->integer_type() == NULL
-             || (expr_type->forwarded()
-                 != Type::lookup_integer_type("uintptr"))))
-       this->report_error(_("invalid unsafe.Pointer conversion"));
-    }
-  else if (expr_type->interface_type() == NULL)
+  if (expr_type->interface_type() == NULL)
     {
       if (!expr_type->is_error() && !this->type_->is_error())
        this->report_error(_("type assertion only valid for interface types"));
@@ -12920,23 +12981,10 @@ Type_guard_expression::do_check_types(Gogo*)
 tree
 Type_guard_expression::do_get_tree(Translate_context* context)
 {
-  Gogo* gogo = context->gogo();
   tree expr_tree = this->expr_->get_tree(context);
   if (expr_tree == error_mark_node)
     return error_mark_node;
-  Type* expr_type = this->expr_->type();
-  if ((this->type_->is_unsafe_pointer_type()
-       && (expr_type->points_to() != NULL
-          || expr_type->integer_type() != NULL))
-      || (expr_type->is_unsafe_pointer_type()
-         && this->type_->points_to() != NULL))
-    return convert_to_pointer(type_to_tree(this->type_->get_backend(gogo)),
-                             expr_tree);
-  else if (expr_type->is_unsafe_pointer_type()
-          && this->type_->integer_type() != NULL)
-    return convert_to_integer(type_to_tree(this->type_->get_backend(gogo)),
-                             expr_tree);
-  else if (this->type_->interface_type() != NULL)
+  if (this->type_->interface_type() != NULL)
     return Expression::convert_interface_to_interface(context, this->type_,
                                                      this->expr_->type(),
                                                      expr_tree, true,