Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / gcc / go / gofrontend / gogo.cc
index c0aa496..80ae8d4 100644 (file)
 
 // Class Gogo.
 
-Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
-           int pointer_size)
+Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
   : backend_(backend),
     linemap_(linemap),
     package_(NULL),
     functions_(),
     globals_(new Bindings(NULL)),
+    file_block_names_(),
     imports_(),
     imported_unsafe_(false),
     packages_(),
@@ -83,6 +83,7 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
   this->add_named_type(Type::make_complex_type("complex128", 128,
                                               RUNTIME_TYPE_KIND_COMPLEX128));
 
+  int int_type_size = pointer_size;
   if (int_type_size < 32)
     int_type_size = 32;
   this->add_named_type(Type::make_integer_type("uint", true,
@@ -514,16 +515,23 @@ Gogo::add_import_init_fn(const std::string& package_name,
        p != this->imported_init_fns_.end();
        ++p)
     {
-      if (p->init_name() == init_name
-         && (p->package_name() != package_name || p->priority() != prio))
+      if (p->init_name() == init_name)
        {
-         error("duplicate package initialization name %qs",
-               Gogo::message_name(init_name).c_str());
-         inform(UNKNOWN_LOCATION, "used by package %qs at priority %d",
-                Gogo::message_name(p->package_name()).c_str(),
-                p->priority());
-         inform(UNKNOWN_LOCATION, " and by package %qs at priority %d",
-                Gogo::message_name(package_name).c_str(), prio);
+         // If a test of package P1, built as part of package P1,
+         // imports package P2, and P2 imports P1 (perhaps
+         // indirectly), then we will see the same import name with
+         // different import priorities.  That is OK, so don't give
+         // an error about it.
+         if (p->package_name() != package_name)
+           {
+             error("duplicate package initialization name %qs",
+                   Gogo::message_name(init_name).c_str());
+             inform(UNKNOWN_LOCATION, "used by package %qs at priority %d",
+                    Gogo::message_name(p->package_name()).c_str(),
+                    p->priority());
+             inform(UNKNOWN_LOCATION, " and by package %qs at priority %d",
+                    Gogo::message_name(package_name).c_str(), prio);
+           }
          return;
        }
     }
@@ -1243,6 +1251,33 @@ Gogo::define_global_names()
       else if (no->is_unknown())
        no->unknown_value()->set_real_named_object(global_no);
     }
+
+  // Give an error if any name is defined in both the package block
+  // and the file block.  For example, this can happen if one file
+  // imports "fmt" and another file defines a global variable fmt.
+  for (Bindings::const_declarations_iterator p =
+        this->package_->bindings()->begin_declarations();
+       p != this->package_->bindings()->end_declarations();
+       ++p)
+    {
+      if (p->second->is_unknown()
+         && p->second->unknown_value()->real_named_object() == NULL)
+       {
+         // No point in warning about an undefined name, as we will
+         // get other errors later anyhow.
+         continue;
+       }
+      File_block_names::const_iterator pf =
+       this->file_block_names_.find(p->second->name());
+      if (pf != this->file_block_names_.end())
+       {
+         std::string n = p->second->message_name();
+         error_at(p->second->location(),
+                  "%qs defined as both imported name and global name",
+                  n.c_str());
+         inform(pf->second, "%qs imported here", n.c_str());
+       }
+    }
 }
 
 // Clear out names in file scope.
@@ -1250,9 +1285,10 @@ Gogo::define_global_names()
 void
 Gogo::clear_file_scope()
 {
-  this->package_->bindings()->clear_file_scope();
+  this->package_->bindings()->clear_file_scope(this);
 
   // Warn about packages which were imported but not used.
+  bool quiet = saw_errors();
   for (Packages::iterator p = this->packages_.begin();
        p != this->packages_.end();
        ++p)
@@ -1262,7 +1298,7 @@ Gogo::clear_file_scope()
          && package->is_imported()
          && !package->used()
          && !package->uses_sink_alias()
-         && !saw_errors())
+         && !quiet)
        error_at(package->location(), "imported and not used: %s",
                 Gogo::message_name(package->package_name()).c_str());
       package->clear_is_imported();
@@ -1763,6 +1799,26 @@ Finalize_methods::type(Type* t)
              }
          }
 
+       // Finalize the types of all methods that are declared but not
+       // defined, since we won't see the declarations otherwise.
+       if (nt->named_object()->package() == NULL
+           && nt->local_methods() != NULL)
+         {
+           const Bindings* methods = nt->local_methods();
+           for (Bindings::const_declarations_iterator p =
+                  methods->begin_declarations();
+                p != methods->end_declarations();
+                p++)
+             {
+               if (p->second->is_function_declaration())
+                 {
+                   Type* mt = p->second->func_declaration_value()->type();
+                   if (Type::traverse(mt, this) == TRAVERSE_EXIT)
+                     return TRAVERSE_EXIT;
+                 }
+             }
+         }
+
        return TRAVERSE_SKIP_COMPONENTS;
       }
 
@@ -3073,8 +3129,9 @@ Function::Function(Function_type* type, Function* enclosing, Block* block,
   : type_(type), enclosing_(enclosing), results_(NULL),
     closure_var_(NULL), block_(block), location_(location), labels_(),
     local_type_count_(0), fndecl_(NULL), defer_stack_(NULL),
-    results_are_named_(false), calls_recover_(false), is_recover_thunk_(false),
-    has_recover_thunk_(false)
+    results_are_named_(false), nointerface_(false), calls_recover_(false),
+    is_recover_thunk_(false), has_recover_thunk_(false),
+    in_unique_section_(false)
 {
 }
 
@@ -3895,7 +3952,7 @@ Variable::Variable(Type* type, Expression* init, bool is_global,
     seen_(false), init_is_lowered_(false), type_from_init_tuple_(false),
     type_from_range_index_(false), type_from_range_value_(false),
     type_from_chan_element_(false), is_type_switch_var_(false),
-    determined_type_(false)
+    determined_type_(false), in_unique_section_(false)
 {
   go_assert(type != NULL || init != NULL);
   go_assert(!is_parameter || init == NULL);
@@ -4314,6 +4371,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
                                            btype,
                                            package != NULL,
                                            Gogo::is_hidden_name(name),
+                                           this->in_unique_section_,
                                            this->location_);
          else if (function == NULL)
            {
@@ -4488,7 +4546,7 @@ Type_declaration::has_methods() const
 void
 Type_declaration::define_methods(Named_type* nt)
 {
-  for (Methods::const_iterator p = this->methods_.begin();
+  for (std::vector<Named_object*>::const_iterator p = this->methods_.begin();
        p != this->methods_.end();
        ++p)
     nt->add_existing_method(*p);
@@ -4832,7 +4890,7 @@ Bindings::Bindings(Bindings* enclosing)
 // Clear imports.
 
 void
-Bindings::clear_file_scope()
+Bindings::clear_file_scope(Gogo* gogo)
 {
   Contour::iterator p = this->bindings_.begin();
   while (p != this->bindings_.end())
@@ -4852,7 +4910,10 @@ Bindings::clear_file_scope()
       if (keep)
        ++p;
       else
-       p = this->bindings_.erase(p);
+       {
+         gogo->add_file_block_name(p->second->name(), p->second->location());
+         p = this->bindings_.erase(p);
+       }
     }
 }
 
@@ -5227,8 +5288,7 @@ Bindings::traverse(Traverse* traverse, bool is_global)
     }
 
   // If we need to traverse types, check the function declarations,
-  // which have types.  We don't need to check the type declarations,
-  // as those are just names.
+  // which have types.  Also check any methods of a type declaration.
   if ((traverse_mask & e_or_t) != 0)
     {
       for (Bindings::const_declarations_iterator p =
@@ -5243,6 +5303,27 @@ Bindings::traverse(Traverse* traverse, bool is_global)
                  == TRAVERSE_EXIT)
                return TRAVERSE_EXIT;
            }
+         else if (p->second->is_type_declaration())
+           {
+             const std::vector<Named_object*>* methods =
+               p->second->type_declaration_value()->methods();
+             for (std::vector<Named_object*>::const_iterator pm =
+                    methods->begin();
+                  pm != methods->end();
+                  pm++)
+               {
+                 Named_object* no = *pm;
+                 Type *t;
+                 if (no->is_function())
+                   t = no->func_value()->type();
+                 else if (no->is_function_declaration())
+                   t = no->func_declaration_value()->type();
+                 else
+                   continue;
+                 if (Type::traverse(t, traverse) == TRAVERSE_EXIT)
+                   return TRAVERSE_EXIT;
+               }
+           }
        }
     }