From: Ian Lance Taylor Date: Fri, 21 Dec 2012 22:23:23 +0000 (+0000) Subject: compiler: Error if name defined in both package and file blocks. X-Git-Tag: upstream/12.2.0~72062 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5c167ca0a208115ab6c8496946a2d9c208d8d859;p=platform%2Fupstream%2Fgcc.git compiler: Error if name defined in both package and file blocks. From-SVN: r194685 --- diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 41f9665..735b4c8 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 cffdd21..f96ffcd 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 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. diff --git a/libgo/go/image/image_test.go b/libgo/go/image/image_test.go index 2b3f149..2656757 100644 --- a/libgo/go/image/image_test.go +++ b/libgo/go/image/image_test.go @@ -10,7 +10,7 @@ import ( "testing" ) -type image interface { +type timage interface { Image Opaque() bool Set(int, int, color.Color) @@ -24,7 +24,7 @@ func cmp(t *testing.T, cm color.Model, c0, c1 color.Color) bool { } func TestImage(t *testing.T) { - testImage := []image{ + testImage := []timage{ NewRGBA(Rect(0, 0, 10, 10)), NewRGBA64(Rect(0, 0, 10, 10)), NewNRGBA(Rect(0, 0, 10, 10)), @@ -52,11 +52,11 @@ func TestImage(t *testing.T) { t.Errorf("%T: at (6, 3), want a non-zero color, got %v", m, m.At(6, 3)) continue } - if !m.SubImage(Rect(6, 3, 7, 4)).(image).Opaque() { + if !m.SubImage(Rect(6, 3, 7, 4)).(timage).Opaque() { t.Errorf("%T: at (6, 3) was not opaque", m) continue } - m = m.SubImage(Rect(3, 2, 9, 8)).(image) + m = m.SubImage(Rect(3, 2, 9, 8)).(timage) if !Rect(3, 2, 9, 8).Eq(m.Bounds()) { t.Errorf("%T: sub-image want bounds %v, got %v", m, Rect(3, 2, 9, 8), m.Bounds()) continue @@ -97,7 +97,7 @@ func Test16BitsPerColorChannel(t *testing.T) { continue } } - testImage := []image{ + testImage := []timage{ NewRGBA64(Rect(0, 0, 10, 10)), NewNRGBA64(Rect(0, 0, 10, 10)), NewAlpha16(Rect(0, 0, 10, 10)),