OSDN Git Service

compiler: Error if importing same package twice with same name.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / gogo.cc
index 2fd1219..f9982cc 100644 (file)
@@ -32,6 +32,7 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
     imported_unsafe_(false),
     packages_(),
     init_functions_(),
+    var_deps_(),
     need_init_fn_(false),
     init_fn_name_(),
     imported_init_fns_(),
@@ -628,7 +629,7 @@ Gogo::start_function(const std::string& name, Function_type* type,
       Variable* this_param = new Variable(receiver->type(), NULL, false,
                                          true, true, location);
       std::string rname = receiver->name();
-      if (rname.empty())
+      if (rname.empty() || Gogo::is_sink_name(rname))
        {
          // We need to give receivers a name since they wind up in
          // DECL_ARGUMENTS.  FIXME.
@@ -638,8 +639,7 @@ Gogo::start_function(const std::string& name, Function_type* type,
          ++count;
          rname = buf;
        }
-      if (!Gogo::is_sink_name(rname))
-       block->bindings()->add_variable(rname, NULL, this_param);
+      block->bindings()->add_variable(rname, NULL, this_param);
     }
 
   const Typed_identifier_list* parameters = type->parameters();
@@ -880,7 +880,7 @@ Gogo::declare_function(const std::string& name, Function_type* type,
       else if (rtype->forward_declaration_type() != NULL)
        {
          Forward_declaration_type* ftype = rtype->forward_declaration_type();
-         return ftype->add_method_declaration(name, type, location);
+         return ftype->add_method_declaration(name, NULL, type, location);
        }
       else
        go_unreachable();
@@ -1205,13 +1205,13 @@ Specific_type_functions::type(Type* t)
     {
     case Type::TYPE_NAMED:
       {
+       Named_type* nt = t->named_type();
        if (!t->compare_is_identity(this->gogo_) && t->is_comparable())
-         t->type_functions(this->gogo_, t->named_type(), NULL, NULL, &hash_fn,
-                           &equal_fn);
+         t->type_functions(this->gogo_, nt, NULL, NULL, &hash_fn, &equal_fn);
 
        // If this is a struct type, we don't want to make functions
        // for the unnamed struct.
-       Type* rt = t->named_type()->real_type();
+       Type* rt = nt->real_type();
        if (rt->struct_type() == NULL)
          {
            if (Type::traverse(rt, this) == TRAVERSE_EXIT)
@@ -1219,8 +1219,20 @@ Specific_type_functions::type(Type* t)
          }
        else
          {
-           if (rt->struct_type()->traverse_field_types(this) == TRAVERSE_EXIT)
-             return TRAVERSE_EXIT;
+           // If this type is defined in another package, then we don't
+           // need to worry about the unexported fields.
+           bool is_defined_elsewhere = nt->named_object()->package() != NULL;
+           const Struct_field_list* fields = rt->struct_type()->fields();
+           for (Struct_field_list::const_iterator p = fields->begin();
+                p != fields->end();
+                ++p)
+             {
+               if (is_defined_elsewhere
+                   && Gogo::is_hidden_name(p->field_name()))
+                 continue;
+               if (Type::traverse(p->type(), this) == TRAVERSE_EXIT)
+                 return TRAVERSE_EXIT;
+             }
          }
 
        return TRAVERSE_SKIP_COMPONENTS;
@@ -1520,6 +1532,8 @@ Lower_parse_tree::expression(Expression** pexpr)
                                  &this->inserter_, this->iota_value_);
       if (enew == e)
        break;
+      if (enew->traverse_subexpressions(this) == TRAVERSE_EXIT)
+       return TRAVERSE_EXIT;
       *pexpr = enew;
     }
   return TRAVERSE_SKIP_COMPONENTS;
@@ -1640,8 +1654,12 @@ Finalize_methods::type(Type* t)
       }
 
     case Type::TYPE_STRUCT:
+      // Traverse the field types first in case there is an embedded
+      // field with methods that the struct should inherit.
+      if (t->struct_type()->traverse_field_types(this) == TRAVERSE_EXIT)
+          return TRAVERSE_EXIT;
       t->struct_type()->finalize_methods(this->gogo_);
-      break;
+      return TRAVERSE_SKIP_COMPONENTS;
 
     default:
       break;
@@ -2199,12 +2217,18 @@ Order_eval::statement(Block* block, size_t* pindex, Statement* s)
       Expression::traverse(&init, &find_eval_ordering);
     }
 
-  if (find_eval_ordering.size() <= 1)
-    {
-      // If there is only one expression with a side-effect, we can
-      // leave it in place.
-      return TRAVERSE_CONTINUE;
-    }
+  size_t c = find_eval_ordering.size();
+  if (c == 0)
+    return TRAVERSE_CONTINUE;
+
+  // If there is only one expression with a side-effect, we can
+  // usually leave it in place.  However, for an assignment statement,
+  // we need to evaluate an expression on the right hand side before
+  // we evaluate any index expression on the left hand side, so for
+  // that case we always move the expression.  Otherwise we mishandle
+  // m[0] = len(m) where m is a map.
+  if (c == 1 && s->classification() != Statement::STATEMENT_ASSIGNMENT)
+    return TRAVERSE_CONTINUE;
 
   bool is_thunk = s->thunk_statement() != NULL;
   for (Find_eval_ordering::const_iterator p = find_eval_ordering.begin();
@@ -2486,6 +2510,9 @@ Build_recover_thunks::function(Named_object* orig_no)
 
   Call_expression* call = Expression::make_call(fn, args, false, location);
 
+  // Any varargs call has already been lowered.
+  call->set_varargs_are_lowered();
+
   Statement* s;
   if (orig_fntype->results() == NULL || orig_fntype->results()->empty())
     s = Statement::make_statement(call, true);
@@ -2845,6 +2872,7 @@ Gogo::do_exports()
   exp.export_globals(this->package_name(),
                     this->unique_prefix(),
                     this->package_priority(),
+                    this->imports_,
                     (this->need_init_fn_ && !this->is_main_package()
                      ? this->get_init_fn_name()
                      : ""),
@@ -2915,8 +2943,6 @@ Gogo::convert_named_types()
 
   Runtime::convert_types(this);
 
-  Function_type::convert_types(this);
-
   this->named_types_are_converted_ = true;
 }
 
@@ -3262,7 +3288,10 @@ Function::export_func_with_type(Export* exp, const std::string& name,
   if (fntype->is_method())
     {
       exp->write_c_string("(");
-      exp->write_type(fntype->receiver()->type());
+      const Typed_identifier* receiver = fntype->receiver();
+      exp->write_name(receiver->name());
+      exp->write_c_string(" ");
+      exp->write_type(receiver->type());
       exp->write_c_string(") ");
     }
 
@@ -3282,6 +3311,8 @@ Function::export_func_with_type(Export* exp, const std::string& name,
            first = false;
          else
            exp->write_c_string(", ");
+         exp->write_name(p->name());
+         exp->write_c_string(" ");
          if (!is_varargs || p + 1 != parameters->end())
            exp->write_type(p->type());
          else
@@ -3296,7 +3327,7 @@ Function::export_func_with_type(Export* exp, const std::string& name,
   const Typed_identifier_list* results = fntype->results();
   if (results != NULL)
     {
-      if (results->size() == 1)
+      if (results->size() == 1 && results->begin()->name().empty())
        {
          exp->write_c_string(" ");
          exp->write_type(results->begin()->type());
@@ -3313,6 +3344,8 @@ Function::export_func_with_type(Export* exp, const std::string& name,
                first = false;
              else
                exp->write_c_string(", ");
+             exp->write_name(p->name());
+             exp->write_c_string(" ");
              exp->write_type(p->type());
            }
          exp->write_c_string(")");
@@ -3336,9 +3369,10 @@ Function::import_func(Import* imp, std::string* pname,
   if (imp->peek_char() == '(')
     {
       imp->require_c_string("(");
+      std::string name = imp->read_name();
+      imp->require_c_string(" ");
       Type* rtype = imp->read_type();
-      *preceiver = new Typed_identifier(Import::import_marker, rtype,
-                                       imp->location());
+      *preceiver = new Typed_identifier(name, rtype, imp->location());
       imp->require_c_string(") ");
     }
 
@@ -3354,6 +3388,9 @@ Function::import_func(Import* imp, std::string* pname,
       parameters = new Typed_identifier_list();
       while (true)
        {
+         std::string name = imp->read_name();
+         imp->require_c_string(" ");
+
          if (imp->match_c_string("..."))
            {
              imp->advance(3);
@@ -3363,8 +3400,8 @@ Function::import_func(Import* imp, std::string* pname,
          Type* ptype = imp->read_type();
          if (*is_varargs)
            ptype = Type::make_array_type(ptype, NULL);
-         parameters->push_back(Typed_identifier(Import::import_marker,
-                                                ptype, imp->location()));
+         parameters->push_back(Typed_identifier(name, ptype,
+                                                imp->location()));
          if (imp->peek_char() != ',')
            break;
          go_assert(!*is_varargs);
@@ -3384,17 +3421,18 @@ Function::import_func(Import* imp, std::string* pname,
       if (imp->peek_char() != '(')
        {
          Type* rtype = imp->read_type();
-         results->push_back(Typed_identifier(Import::import_marker, rtype,
-                                             imp->location()));
+         results->push_back(Typed_identifier("", rtype, imp->location()));
        }
       else
        {
          imp->require_c_string("(");
          while (true)
            {
+             std::string name = imp->read_name();
+             imp->require_c_string(" ");
              Type* rtype = imp->read_type();
-             results->push_back(Typed_identifier(Import::import_marker,
-                                                 rtype, imp->location()));
+             results->push_back(Typed_identifier(name, rtype,
+                                                 imp->location()));
              if (imp->peek_char() != ',')
                break;
              imp->require_c_string(", ");
@@ -3783,6 +3821,10 @@ void
 Variable::lower_init_expression(Gogo* gogo, Named_object* function,
                                Statement_inserter* inserter)
 {
+  Named_object* dep = gogo->var_depends_on(this);
+  if (dep != NULL && dep->is_variable())
+    dep->var_value()->lower_init_expression(gogo, function, inserter);
+
   if (this->init_ != NULL && !this->init_is_lowered_)
     {
       if (this->seen_)
@@ -3834,6 +3876,24 @@ Variable::add_preinit_statement(Gogo* gogo, Statement* s)
   b->set_end_location(s->location());
 }
 
+// Whether this variable has a type.
+
+bool
+Variable::has_type() const
+{
+  if (this->type_ == NULL)
+    return false;
+
+  // A variable created in a type switch case nil does not actually
+  // have a type yet.  It will be changed to use the initializer's
+  // type in determine_type.
+  if (this->is_type_switch_var_
+      && this->type_->is_nil_constant_as_type())
+    return false;
+
+  return true;
+}
+
 // In an assignment which sets a variable to a tuple of EXPR, return
 // the type of the first element of the tuple.
 
@@ -4148,6 +4208,11 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
                                            package != NULL,
                                            Gogo::is_hidden_name(name),
                                            this->location_);
+         else if (function == NULL)
+           {
+             go_assert(saw_errors());
+             bvar = backend->error_variable();
+           }
          else
            {
              tree fndecl = function->func_value()->get_decl();
@@ -4293,11 +4358,12 @@ Type_declaration::add_method(const std::string& name, Function* function)
 
 Named_object*
 Type_declaration::add_method_declaration(const std::string&  name,
+                                        Package* package,
                                         Function_type* type,
                                         Location location)
 {
-  Named_object* ret = Named_object::make_function_declaration(name, NULL, type,
-                                                             location);
+  Named_object* ret = Named_object::make_function_declaration(name, package,
+                                                             type, location);
   this->methods_.push_back(ret);
   return ret;
 }
@@ -4880,11 +4946,6 @@ Bindings::new_definition(Named_object* old_object, Named_object* new_object)
       break;
 
     case Named_object::NAMED_OBJECT_PACKAGE:
-      if (new_object->is_package()
-         && (old_object->package_value()->name()
-             == new_object->package_value()->name()))
-       return old_object;
-
       break;
     }
 
@@ -5297,5 +5358,5 @@ Statement_inserter::insert(Statement* s)
   else if (this->var_ != NULL)
     this->var_->add_preinit_statement(this->gogo_, s);
   else
-    go_unreachable();
+    go_assert(saw_errors());
 }