aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2006-09-29 22:34:01 +0000
committerIan Lance Taylor <iant@google.com>2006-09-29 22:34:01 +0000
commit5482377ddc6d4104399a7e2e49518a6e893dca65 (patch)
tree17d8018e5b63b67fee207053404b8479c00f6843 /gold
parent61ba1cf93601b0a0877a8ade94ba3c674a09f77e (diff)
downloadbinutils-5482377ddc6d4104399a7e2e49518a6e893dca65.zip
binutils-5482377ddc6d4104399a7e2e49518a6e893dca65.tar.gz
binutils-5482377ddc6d4104399a7e2e49518a6e893dca65.tar.bz2
Clean up HAVE_MEMBER_TEMPLATE_SPECIFICATIONS somewhat.
Diffstat (limited to 'gold')
-rw-r--r--gold/gold.h56
-rw-r--r--gold/object.h17
-rw-r--r--gold/output.cc26
-rw-r--r--gold/output.h5
-rw-r--r--gold/resolve.cc10
-rw-r--r--gold/symtab.cc66
-rw-r--r--gold/symtab.h18
7 files changed, 96 insertions, 102 deletions
diff --git a/gold/gold.h b/gold/gold.h
index cb17ae7..9ddf2f7 100644
--- a/gold/gold.h
+++ b/gold/gold.h
@@ -79,6 +79,62 @@ struct hash<T*>
namespace gold
{
+// This is a hack to work around a problem with older versions of g++.
+// The problem is that they don't support calling a member template by
+// specifying the template parameters. It works to pass in an
+// argument for argument dependent lookup.
+
+// To use this, the member template method declaration should put
+// ACCEPT_SIZE or ACCEPT_SIZE_ENDIAN after the last parameter. If the
+// method takes no parameters, use ACCEPT_SIZE_ONLY or
+// ACCEPT_SIZE_ENDIAN_ONLY.
+
+// When calling the method, instead of using fn<size>, use fn
+// SELECT_SIZE_NAME or SELECT_SIZE_ENDIAN_NAME. And after the last
+// argument, put SELECT_SIZE(size) or SELECT_SIZE_ENDIAN(size,
+// big_endian). If there is only one argment, use the _ONLY variants.
+
+#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
+
+#define SELECT_SIZE_NAME <size>
+#define SELECT_SIZE(size)
+#define SELECT_SIZE_ONLY(size)
+#define ACCEPT_SIZE
+#define ACCEPT_SIZE_ONLY
+
+#define SELECT_SIZE_ENDIAN_NAME <size, big_endian>
+#define SELECT_SIZE_ENDIAN(size, big_endian)
+#define SELECT_SIZE_ENDIAN_ONLY(size, big_endian)
+#define ACCEPT_SIZE_ENDIAN
+#define ACCEPT_SIZE_ENDIAN_ONLY
+
+#else // !defined(HAVE_MEMBER_TEMPLATE_SPECIFICATIONS)
+
+template<int size>
+class Select_size { };
+template<int size, bool big_endian>
+class Select_size_endian { };
+
+#define SELECT_SIZE_NAME
+#define SELECT_SIZE(size) , Select_size<size>()
+#define SELECT_SIZE_ONLY(size) Select_size<size>()
+#define ACCEPT_SIZE , Select_size<size>
+#define ACCEPT_SIZE_ONLY Select_size<size>
+
+#define SELECT_SIZE_ENDIAN_NAME
+#define SELECT_SIZE_ENDIAN(size, big_endian) \
+ , Select_size_endian<size, big_endian>()
+#define SELECT_SIZE_ENDIAN_ONLY(size, big_endian) \
+ Select_size_endian<size, big_endian>()
+#define ACCEPT_SIZE_ENDIAN , Select_size_endian<size, big_endian>
+#define ACCEPT_SIZE_ENDIAN_ONLY Select_size_endian<size, big_endian>
+
+#endif // !defined(HAVE_MEMBER_TEMPLATE_SPECIFICATIONS)
+
+} // End namespace gold.
+
+namespace gold
+{
class General_options;
class Input_objects;
diff --git a/gold/object.h b/gold/object.h
index 198e015..cea0f06 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -85,14 +85,12 @@ class Object
is_locked() const
{ return this->input_file_->file().is_locked(); }
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
// Return the sized target structure associated with this object.
// This is like the target method but it returns a pointer of
// appropriate checked type.
template<int size, bool big_endian>
Sized_target<size, big_endian>*
- sized_target();
-#endif
+ sized_target(ACCEPT_SIZE_ENDIAN_ONLY);
// Read the symbol and relocation information.
Read_symbols_data
@@ -232,22 +230,18 @@ class Object
std::vector<Map_to_output> map_to_output_;
};
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
-
// Implement sized_target inline for efficiency. This approach breaks
// static type checking, but is made safe using asserts.
template<int size, bool big_endian>
inline Sized_target<size, big_endian>*
-Object::sized_target()
+Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY)
{
assert(this->target_->get_size() == size);
assert(this->target_->is_big_endian() ? big_endian : !big_endian);
return static_cast<Sized_target<size, big_endian>*>(this->target_);
}
-#endif
-
// A regular object file. This is size and endian specific.
template<int size, bool big_endian>
@@ -288,11 +282,8 @@ class Sized_object : public Object
Sized_target<size, big_endian>*
sized_target()
{
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
- return this->Object::sized_target<size, big_endian>();
-#else
- return static_cast<Sized_target<size, big_endian>*>(this->target());
-#endif
+ return this->Object::sized_target SELECT_SIZE_ENDIAN_NAME (
+ SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
}
private:
diff --git a/gold/output.cc b/gold/output.cc
index ababd8c..82e2ca5 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -140,7 +140,8 @@ Output_section_headers::do_sized_write(Output_file* of)
for (Layout::Segment_list::const_iterator p = this->segment_list_.begin();
p != this->segment_list_.end();
++p)
- v = (*p)->write_section_headers<size, big_endian>(this->secnamepool_, v);
+ v = (*p)->write_section_headers SELECT_SIZE_ENDIAN_NAME (
+ this->secnamepool_, v SELECT_SIZE_ENDIAN(size, big_endian));
for (Layout::Section_list::const_iterator p = this->section_list_.begin();
p != this->section_list_.end();
++p)
@@ -324,7 +325,8 @@ Output_file_header::do_sized_write(Output_file* of)
else
{
Sized_symbol<size>* ssym;
- ssym = this->symtab_->get_sized_symbol<size>(sym);
+ ssym = this->symtab_->get_sized_symbol SELECT_SIZE_NAME (
+ sym SELECT_SIZE(size));
v = ssym->value();
}
oehdr.put_e_entry(v);
@@ -715,14 +717,13 @@ Output_segment::write_header(elfcpp::Phdr_write<size, big_endian>* ophdr) const
template<int size, bool big_endian>
unsigned char*
Output_segment::write_section_headers(const Stringpool* secnamepool,
- unsigned char* v) const
-{
- v = this->write_section_headers_list<size, big_endian>(secnamepool,
- &this->output_data_,
- v);
- v = this->write_section_headers_list<size, big_endian>(secnamepool,
- &this->output_bss_,
- v);
+ unsigned char* v
+ ACCEPT_SIZE_ENDIAN) const
+{
+ v = this->write_section_headers_list SELECT_SIZE_ENDIAN_NAME (
+ secnamepool, &this->output_data_, v SELECT_SIZE_ENDIAN(size, big_endian));
+ v = this->write_section_headers_list SELECT_SIZE_ENDIAN_NAME (
+ secnamepool, &this->output_bss_, v SELECT_SIZE_ENDIAN(size, big_endian));
return v;
}
@@ -730,7 +731,8 @@ template<int size, bool big_endian>
unsigned char*
Output_segment::write_section_headers_list(const Stringpool* secnamepool,
const Output_data_list* pdl,
- unsigned char* v) const
+ unsigned char* v
+ ACCEPT_SIZE_ENDIAN) const
{
const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
for (Output_data_list::const_iterator p = pdl->begin();
@@ -739,7 +741,7 @@ Output_segment::write_section_headers_list(const Stringpool* secnamepool,
{
if ((*p)->is_section())
{
- Output_section* ps = static_cast<const Output_section*>(*p);
+ const Output_section* ps = static_cast<const Output_section*>(*p);
elfcpp::Shdr_write<size, big_endian> oshdr(v);
ps->write_header(secnamepool, &oshdr);
v += shdr_size;
diff --git a/gold/output.h b/gold/output.h
index c6f2c78..368e4ba 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -481,7 +481,8 @@ class Output_segment
// Write the section headers of associated sections into V.
template<int size, bool big_endian>
unsigned char*
- write_section_headers(const Stringpool*, unsigned char* v) const;
+ write_section_headers(const Stringpool*,
+ unsigned char* v ACCEPT_SIZE_ENDIAN) const;
private:
Output_segment(const Output_segment&);
@@ -501,7 +502,7 @@ class Output_segment
template<int size, bool big_endian>
unsigned char*
write_section_headers_list(const Stringpool*, const Output_data_list*,
- unsigned char* v) const;
+ unsigned char* v ACCEPT_SIZE_ENDIAN) const;
// The list of output data with contents attached to this segment.
Output_data_list output_data_;
diff --git a/gold/resolve.cc b/gold/resolve.cc
index 669fbaf..98e93f0 100644
--- a/gold/resolve.cc
+++ b/gold/resolve.cc
@@ -53,14 +53,8 @@ Symbol_table::resolve(Sized_symbol<size>* to,
if (object->target()->has_resolve())
{
Sized_target<size, big_endian>* sized_target;
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
- sized_target = object->sized_target<size, big_endian>();
-#else
- Target* target = object->target();
- assert(target->get_size() == size);
- assert(target->is_big_endian() ? big_endian : !big_endian);
- sized_target = static_cast<Sized_target<size, big_endian>*>(target);
-#endif
+ sized_target = object->sized_target SELECT_SIZE_ENDIAN_NAME (
+ SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
sized_target->resolve(to, sym, object);
return;
}
diff --git a/gold/symtab.cc b/gold/symtab.cc
index cc77b37..2251ea7 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -133,11 +133,10 @@ Symbol_table::lookup(const char* name, const char* version) const
// version is the default version. Because this is unusual, we do
// this the slow way, by converting back to an ELF symbol.
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
-
template<int size, bool big_endian>
void
-Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from)
+Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from
+ ACCEPT_SIZE_ENDIAN)
{
unsigned char buf[elfcpp::Elf_sizes<size>::sym_size];
elfcpp::Sym_write<size, big_endian> esym(buf);
@@ -150,40 +149,6 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from)
Symbol_table::resolve(to, esym.sym(), from->object());
}
-#else
-
-template<int size>
-void
-Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from,
- bool big_endian)
-{
- unsigned char buf[elfcpp::Elf_sizes<size>::sym_size];
- if (big_endian)
- {
- elfcpp::Sym_write<size, true> esym(buf);
- // We don't bother to set the st_name field.
- esym.put_st_value(from->value());
- esym.put_st_size(from->symsize());
- esym.put_st_info(from->binding(), from->type());
- esym.put_st_other(from->visibility(), from->other());
- esym.put_st_shndx(from->shnum());
- Symbol_table::resolve(to, esym.sym(), from->object());
- }
- else
- {
- elfcpp::Sym_write<size, false> esym(buf);
- // We don't bother to set the st_name field.
- esym.put_st_value(from->value());
- esym.put_st_size(from->symsize());
- esym.put_st_info(from->binding(), from->type());
- esym.put_st_other(from->visibility(), from->other());
- esym.put_st_shndx(from->shnum());
- Symbol_table::resolve(to, esym.sym(), from->object());
- }
-}
-
-#endif
-
// Add one symbol from OBJECT to the symbol table. NAME is symbol
// name and VERSION is the version; both are canonicalized. DEF is
// whether this is the default version.
@@ -236,12 +201,8 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
if (!ins.second)
{
// We already have an entry for NAME/VERSION.
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
- ret = this->get_sized_symbol<size>(ins.first->second);
-#else
- assert(size == this->get_size());
- ret = static_cast<Sized_symbol<size>*>(ins.first->second);
-#endif
+ ret = this->get_sized_symbol SELECT_SIZE_NAME (ins.first->second
+ SELECT_SIZE(size));
assert(ret != NULL);
Symbol_table::resolve(ret, sym, object);
@@ -258,13 +219,11 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
// This is the unfortunate case where we already have
// entries for both NAME/VERSION and NAME/NULL.
const Sized_symbol<size>* sym2;
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
- sym2 = this->get_sized_symbol<size>(insdef.first->second);
- Symbol_table::resolve<size, big_endian>(ret, sym2);
-#else
- sym2 = static_cast<Sized_symbol<size>*>(insdef.first->second);
- Symbol_table::resolve(ret, sym2, big_endian);
-#endif
+ sym2 = this->get_sized_symbol SELECT_SIZE_NAME (
+ insdef.first->second
+ SELECT_SIZE(size));
+ Symbol_table::resolve SELECT_SIZE_ENDIAN_NAME (
+ ret, sym2 SELECT_SIZE_ENDIAN(size, big_endian));
this->make_forwarder(insdef.first->second, ret);
insdef.first->second = ret;
}
@@ -278,11 +237,8 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
{
// We already have an entry for NAME/NULL. Make
// NAME/VERSION point to it.
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
- ret = this->get_sized_symbol<size>(insdef.first->second);
-#else
- ret = static_cast<Sized_symbol<size>*>(insdef.first->second);
-#endif
+ ret = this->get_sized_symbol SELECT_SIZE_NAME (insdef.first->second
+ SELECT_SIZE(size));
Symbol_table::resolve(ret, sym, object);
ins.first->second = ret;
}
diff --git a/gold/symtab.h b/gold/symtab.h
index 51bb269..23d54e4 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -236,11 +236,11 @@ class Symbol_table
// Return the sized version of a symbol in this table.
template<int size>
Sized_symbol<size>*
- get_sized_symbol(Symbol*) const;
+ get_sized_symbol(Symbol* ACCEPT_SIZE) const;
template<int size>
const Sized_symbol<size>*
- get_sized_symbol(const Symbol*) const;
+ get_sized_symbol(const Symbol* ACCEPT_SIZE) const;
// Finalize the symbol table after we have set the final addresses
// of all the input sections. This sets the final symbol values and
@@ -280,16 +280,10 @@ class Symbol_table
const elfcpp::Sym<size, big_endian>& sym,
Object*);
-#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
template<int size, bool big_endian>
static void
- resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from);
-#else
- template<int size>
- static void
- resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from,
- bool big_endian);
-#endif
+ resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from
+ ACCEPT_SIZE_ENDIAN);
// Finalize symbols specialized for size.
template<int size>
@@ -345,7 +339,7 @@ class Symbol_table
template<int size>
Sized_symbol<size>*
-Symbol_table::get_sized_symbol(Symbol* sym) const
+Symbol_table::get_sized_symbol(Symbol* sym ACCEPT_SIZE) const
{
assert(size == this->get_size());
return static_cast<Sized_symbol<size>*>(sym);
@@ -353,7 +347,7 @@ Symbol_table::get_sized_symbol(Symbol* sym) const
template<int size>
const Sized_symbol<size>*
-Symbol_table::get_sized_symbol(const Symbol* sym) const
+Symbol_table::get_sized_symbol(const Symbol* sym ACCEPT_SIZE) const
{
assert(size == this->get_size());
return static_cast<const Sized_symbol<size>*>(sym);