// 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_(),
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,
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;
}
}
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.
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)
&& 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();
}
}
+ // 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;
}
: 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)
{
}
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);
btype,
package != NULL,
Gogo::is_hidden_name(name),
+ this->in_unique_section_,
this->location_);
else if (function == NULL)
{
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);
// Clear imports.
void
-Bindings::clear_file_scope()
+Bindings::clear_file_scope(Gogo* gogo)
{
Contour::iterator p = this->bindings_.begin();
while (p != this->bindings_.end())
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);
+ }
}
}
}
// 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 =
== 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;
+ }
+ }
}
}