aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2012-12-21 22:23:23 +0000
committerIan Lance Taylor <iant@google.com>2012-12-21 22:23:23 +0000
commita3b5889709b113680a3af8e196c1a42951e22090 (patch)
treecf96cd27ec81f37394a138f6e77fc0e662004482 /gcc/go
parent4ca70aea692e1645ee0f7d52bfd5feb19f25799b (diff)
compiler: Error if name defined in both package and file blocks.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@194685 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/gogo.cc37
-rw-r--r--gcc/go/gofrontend/gogo.h13
2 files changed, 46 insertions, 4 deletions
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 41f9665e724..735b4c81204 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -29,6 +29,7 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
package_(NULL),
functions_(),
globals_(new Bindings(NULL)),
+ file_block_names_(),
imports_(),
imported_unsafe_(false),
packages_(),
@@ -1243,6 +1244,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,7 +1278,7 @@ 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();
@@ -4855,7 +4883,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())
@@ -4875,7 +4903,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);
+ }
}
}
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index cffdd219118..f96ffcdfdb9 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -377,6 +377,11 @@ class Gogo
void
add_named_object(Named_object*);
+ // Add an identifier to the list of names seen in the file block.
+ void
+ add_file_block_name(const std::string& name, Location location)
+ { this->file_block_names_[name] = location; }
+
// Mark all local variables in current bindings as used. This is
// used when there is a parse error to avoid useless errors.
void
@@ -678,6 +683,10 @@ class Gogo
// This is used for initialization dependency analysis.
typedef std::map<Variable*, Named_object*> Var_deps;
+ // Type used to map identifiers in the file block to the location
+ // where they were defined.
+ typedef Unordered_map(std::string, Location) File_block_names;
+
// Type used to queue writing a type specific function.
struct Specific_type_function
{
@@ -710,6 +719,8 @@ class Gogo
// The global binding contour. This includes the builtin functions
// and the package we are compiling.
Bindings* globals_;
+ // The list of names we have seen in the file block.
+ File_block_names file_block_names_;
// Mapping from import file names to packages.
Imports imports_;
// Whether the magic unsafe package was imported.
@@ -2265,7 +2276,7 @@ class Bindings
// Clear all names in file scope from the bindings.
void
- clear_file_scope();
+ clear_file_scope(Gogo*);
// Look up a name in this binding contour and in any enclosing
// binding contours. This returns NULL if the name is not found.