aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-10-03 15:14:50 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-10-03 15:14:50 +0000
commitacbe08d242491a93e90957116dffa81c9f91ee11 (patch)
treea72439f08ce92599a1d3699206a5d293f6fff94d
parentc6d129b0eaf2fb46b289b774057f5f04f23057f0 (diff)
downloadgcc-acbe08d242491a93e90957116dffa81c9f91ee11.zip
gcc-acbe08d242491a93e90957116dffa81c9f91ee11.tar.gz
gcc-acbe08d242491a93e90957116dffa81c9f91ee11.tar.bz2
compiler: Don't insert promoted methods that conflict with fields.
From-SVN: r215856
-rw-r--r--gcc/go/gofrontend/types.cc51
-rw-r--r--gcc/go/gofrontend/types.h12
2 files changed, 44 insertions, 19 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 302faee..99b9421 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -9387,9 +9387,14 @@ void
Type::finalize_methods(Gogo* gogo, const Type* type, Location location,
Methods** all_methods)
{
- *all_methods = NULL;
+ *all_methods = new Methods();
std::vector<const Named_type*> seen;
- Type::add_methods_for_type(type, NULL, 0, false, false, &seen, all_methods);
+ Type::add_methods_for_type(type, NULL, 0, false, false, &seen, *all_methods);
+ if ((*all_methods)->empty())
+ {
+ delete *all_methods;
+ *all_methods = NULL;
+ }
Type::build_stub_methods(gogo, type, *all_methods, location);
}
@@ -9408,7 +9413,7 @@ Type::add_methods_for_type(const Type* type,
bool is_embedded_pointer,
bool needs_stub_method,
std::vector<const Named_type*>* seen,
- Methods** methods)
+ Methods* methods)
{
// Pointer types may not have methods.
if (type->points_to() != NULL)
@@ -9457,15 +9462,12 @@ Type::add_local_methods_for_type(const Named_type* nt,
unsigned int depth,
bool is_embedded_pointer,
bool needs_stub_method,
- Methods** methods)
+ Methods* methods)
{
const Bindings* local_methods = nt->local_methods();
if (local_methods == NULL)
return;
- if (*methods == NULL)
- *methods = new Methods();
-
for (Bindings::const_declarations_iterator p =
local_methods->begin_declarations();
p != local_methods->end_declarations();
@@ -9476,7 +9478,7 @@ Type::add_local_methods_for_type(const Named_type* nt,
|| !Type::method_expects_pointer(no));
Method* m = new Named_method(no, field_indexes, depth, is_value_method,
(needs_stub_method || depth > 0));
- if (!(*methods)->insert(no->name(), m))
+ if (!methods->insert(no->name(), m))
delete m;
}
}
@@ -9492,7 +9494,7 @@ Type::add_embedded_methods_for_type(const Type* type,
bool is_embedded_pointer,
bool needs_stub_method,
std::vector<const Named_type*>* seen,
- Methods** methods)
+ Methods* methods)
{
// Look for anonymous fields in TYPE. TYPE has fields if it is a
// struct.
@@ -9530,13 +9532,35 @@ Type::add_embedded_methods_for_type(const Type* type,
sub_field_indexes->next = field_indexes;
sub_field_indexes->field_index = i;
+ Methods tmp_methods;
Type::add_methods_for_type(fnt, sub_field_indexes, depth + 1,
(is_embedded_pointer || is_pointer),
(needs_stub_method
|| is_pointer
|| i > 0),
seen,
- methods);
+ &tmp_methods);
+ // Check if there are promoted methods that conflict with field names and
+ // don't add them to the method map.
+ for (Methods::const_iterator p = tmp_methods.begin();
+ p != tmp_methods.end();
+ ++p)
+ {
+ bool found = false;
+ for (Struct_field_list::const_iterator fp = fields->begin();
+ fp != fields->end();
+ ++fp)
+ {
+ if (fp->field_name() == p->first)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found &&
+ !methods->insert(p->first, p->second))
+ delete p->second;
+ }
}
}
@@ -9548,7 +9572,7 @@ void
Type::add_interface_methods_for_type(const Type* type,
const Method::Field_indexes* field_indexes,
unsigned int depth,
- Methods** methods)
+ Methods* methods)
{
const Interface_type* it = type->interface_type();
if (it == NULL)
@@ -9558,9 +9582,6 @@ Type::add_interface_methods_for_type(const Type* type,
if (imethods == NULL)
return;
- if (*methods == NULL)
- *methods = new Methods();
-
for (Typed_identifier_list::const_iterator pm = imethods->begin();
pm != imethods->end();
++pm)
@@ -9576,7 +9597,7 @@ Type::add_interface_methods_for_type(const Type* type,
fntype = fntype->copy_with_receiver(const_cast<Type*>(type));
Method* m = new Interface_method(pm->name(), pm->location(), fntype,
field_indexes, depth);
- if (!(*methods)->insert(pm->name(), m))
+ if (!methods->insert(pm->name(), m))
delete m;
}
}
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 447861c..2173bab 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -384,6 +384,10 @@ class Methods
find(const std::string& name) const
{ return this->methods_.find(name); }
+ bool
+ empty() const
+ { return this->methods_.empty(); }
+
private:
Method_map methods_;
};
@@ -1228,24 +1232,24 @@ class Type
add_methods_for_type(const Type* type, const Method::Field_indexes*,
unsigned int depth, bool, bool,
std::vector<const Named_type*>*,
- Methods**);
+ Methods*);
static void
add_local_methods_for_type(const Named_type* type,
const Method::Field_indexes*,
- unsigned int depth, bool, bool, Methods**);
+ unsigned int depth, bool, bool, Methods*);
static void
add_embedded_methods_for_type(const Type* type,
const Method::Field_indexes*,
unsigned int depth, bool, bool,
std::vector<const Named_type*>*,
- Methods**);
+ Methods*);
static void
add_interface_methods_for_type(const Type* type,
const Method::Field_indexes*,
- unsigned int depth, Methods**);
+ unsigned int depth, Methods*);
// Build stub methods for a type.
static void