aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gdb')
-rw-r--r--gdb/dwarf2/attribute.c73
-rw-r--r--gdb/dwarf2/attribute.h43
-rw-r--r--gdb/dwarf2/cooked-index-storage.c56
-rw-r--r--gdb/dwarf2/cooked-index-storage.h26
-rw-r--r--gdb/dwarf2/cooked-indexer.c7
-rw-r--r--gdb/dwarf2/read-debug-names.c5
-rw-r--r--gdb/dwarf2/read-gdb-index.c2
-rw-r--r--gdb/dwarf2/read.c441
-rw-r--r--gdb/dwarf2/read.h49
-rw-r--r--gdb/testsuite/gdb.base/enum_cond.c16
-rw-r--r--gdb/testsuite/gdb.base/enum_cond.exp15
-rw-r--r--gdb/testsuite/lib/gdb.exp12
12 files changed, 368 insertions, 377 deletions
diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index f777c14..49c0bc0 100644
--- a/gdb/dwarf2/attribute.c
+++ b/gdb/dwarf2/attribute.c
@@ -164,6 +164,27 @@ attribute::constant_value (int default_value) const
/* See attribute.h. */
+std::optional<ULONGEST>
+attribute::unsigned_constant () const
+{
+ if (form_is_strictly_signed ())
+ {
+ if (u.snd >= 0)
+ return u.snd;
+ complaint (_("Attribute value is not unsigned (%s)"),
+ dwarf_form_name (form));
+ }
+ else if (form_is_constant ())
+ return u.unsnd;
+
+ /* For DW_FORM_data16 see attribute::form_is_constant. */
+ complaint (_("Attribute value is not a constant (%s)"),
+ dwarf_form_name (form));
+ return {};
+}
+
+/* See attribute.h. */
+
bool
attribute::form_is_unsigned () const
{
@@ -189,7 +210,7 @@ attribute::form_is_unsigned () const
/* See attribute.h. */
bool
-attribute::form_is_signed () const
+attribute::form_is_strictly_signed () const
{
return form == DW_FORM_sdata || form == DW_FORM_implicit_const;
}
@@ -216,21 +237,24 @@ attribute::form_requires_reprocessing () const
dwarf_defaulted_attribute
attribute::defaulted () const
{
- LONGEST value = constant_value (-1);
+ std::optional<ULONGEST> value = unsigned_constant ();
- switch (value)
+ if (value.has_value ())
{
- case DW_DEFAULTED_no:
- case DW_DEFAULTED_in_class:
- case DW_DEFAULTED_out_of_class:
- return (dwarf_defaulted_attribute) value;
+ switch (*value)
+ {
+ case DW_DEFAULTED_no:
+ case DW_DEFAULTED_in_class:
+ case DW_DEFAULTED_out_of_class:
+ return (dwarf_defaulted_attribute) *value;
+
+ default:
+ complaint (_("unrecognized DW_AT_defaulted value (%s)"),
+ plongest (*value));
+ break;
+ }
}
- /* If the form was not constant, we already complained in
- constant_value, so there's no need to complain again. */
- if (form_is_constant ())
- complaint (_("unrecognized DW_AT_defaulted value (%s)"),
- plongest (value));
return DW_DEFAULTED_no;
}
@@ -239,21 +263,24 @@ attribute::defaulted () const
dwarf_virtuality_attribute
attribute::as_virtuality () const
{
- LONGEST value = constant_value (-1);
+ std::optional<ULONGEST> value = unsigned_constant ();
- switch (value)
+ if (value.has_value ())
{
- case DW_VIRTUALITY_none:
- case DW_VIRTUALITY_virtual:
- case DW_VIRTUALITY_pure_virtual:
- return (dwarf_virtuality_attribute) value;
+ switch (*value)
+ {
+ case DW_VIRTUALITY_none:
+ case DW_VIRTUALITY_virtual:
+ case DW_VIRTUALITY_pure_virtual:
+ return (dwarf_virtuality_attribute) *value;
+
+ default:
+ complaint (_("unrecognized DW_AT_virtuality value (%s)"),
+ plongest (*value));
+ break;
+ }
}
- /* If the form was not constant, we already complained in
- constant_value, so there's no need to complain again. */
- if (form_is_constant ())
- complaint (_("unrecognized DW_AT_virtuality value (%s)"),
- plongest (value));
return DW_VIRTUALITY_none;
}
diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h
index 115d006..4dce04d 100644
--- a/gdb/dwarf2/attribute.h
+++ b/gdb/dwarf2/attribute.h
@@ -69,7 +69,7 @@ struct attribute
form. */
LONGEST as_signed () const
{
- gdb_assert (form_is_signed ());
+ gdb_assert (form_is_strictly_signed ());
return u.snd;
}
@@ -91,28 +91,6 @@ struct attribute
return u.unsnd;
}
- /* Return true if the value is nonnegative. Requires that that
- reprocessing not be needed. */
- bool is_nonnegative () const
- {
- if (form_is_unsigned ())
- return true;
- if (form_is_signed ())
- return as_signed () >= 0;
- return false;
- }
-
- /* Return the nonnegative value. Requires that that reprocessing not be
- needed. */
- ULONGEST as_nonnegative () const
- {
- if (form_is_unsigned ())
- return as_unsigned ();
- if (form_is_signed ())
- return (ULONGEST)as_signed ();
- gdb_assert (false);
- }
-
/* Return non-zero if ATTR's value is a section offset --- classes
lineptr, loclistptr, macptr or rangelistptr --- or zero, otherwise.
You may use the as_unsigned method to retrieve such offsets.
@@ -124,6 +102,18 @@ struct attribute
bool form_is_section_offset () const;
+ /* Return an unsigned constant value. This only handles constant
+ forms (i.e., form_is_constant -- and not the extended list of
+ "unsigned" forms) and assumes an unsigned value is desired. This
+ can intended for use with DWARF-defined enumerations like DW_CC_*
+ or DW_INL_*, but also in situations where a nonnegative constant
+ integer is specified by DWARF.
+
+ If a signed form and negative value is used, or if a non-constant
+ form is used, then complaint is issued and an empty value is
+ returned. */
+ std::optional<ULONGEST> unsigned_constant () const;
+
/* Return non-zero if ATTR's value falls in the 'constant' class, or
zero otherwise. When this function returns true, you can apply
the constant_value method to it.
@@ -168,8 +158,11 @@ struct attribute
/* Check if the attribute's form is an unsigned integer form. */
bool form_is_unsigned () const;
- /* Check if the attribute's form is a signed integer form. */
- bool form_is_signed () const;
+ /* Check if the attribute's form is a signed integer form. This
+ only returns true for forms that are strictly signed -- that is,
+ for a context-dependent form like DW_FORM_data1, this returns
+ false. */
+ bool form_is_strictly_signed () const;
/* Check if the attribute's form is a form that requires
"reprocessing". */
diff --git a/gdb/dwarf2/cooked-index-storage.c b/gdb/dwarf2/cooked-index-storage.c
index 820989e..9c05cf5 100644
--- a/gdb/dwarf2/cooked-index-storage.c
+++ b/gdb/dwarf2/cooked-index-storage.c
@@ -22,11 +22,7 @@
/* See cooked-index-storage.h. */
cooked_index_storage::cooked_index_storage ()
- : m_reader_hash (htab_create_alloc (10, hash_cutu_reader,
- eq_cutu_reader,
- htab_delete_entry<cutu_reader>,
- xcalloc, xfree)),
- m_shard (new cooked_index_shard)
+ : m_shard (new cooked_index_shard)
{
}
@@ -35,9 +31,8 @@ cooked_index_storage::cooked_index_storage ()
cutu_reader *
cooked_index_storage::get_reader (dwarf2_per_cu *per_cu)
{
- int index = per_cu->index;
- return (cutu_reader *) htab_find_with_hash (m_reader_hash.get (),
- &index, index);
+ auto it = m_reader_hash.find (*per_cu);
+ return it != m_reader_hash.end () ? it->get () : nullptr;
}
/* See cooked-index-storage.h. */
@@ -47,30 +42,43 @@ cooked_index_storage::preserve (cutu_reader_up reader)
{
m_abbrev_table_cache.add (reader->release_abbrev_table ());
- int index = reader->cu ()->per_cu->index;
- void **slot = htab_find_slot_with_hash (m_reader_hash.get (), &index,
- index, INSERT);
- gdb_assert (*slot == nullptr);
- cutu_reader *result = reader.get ();
- *slot = reader.release ();
- return result;
+ auto [it, inserted] = m_reader_hash.insert (std::move (reader));
+ gdb_assert (inserted);
+
+ return it->get();
+}
+
+/* See cooked-index-storage.h. */
+
+std::uint64_t
+cooked_index_storage::cutu_reader_hash::operator()
+ (const cutu_reader_up &reader) const noexcept
+{
+ return (*this) (*reader->cu ()->per_cu);
+}
+
+/* See cooked-index-storage.h. */
+
+std::uint64_t
+cooked_index_storage::cutu_reader_hash::operator() (const dwarf2_per_cu &per_cu)
+ const noexcept
+{
+ return per_cu.index;
}
/* See cooked-index-storage.h. */
-hashval_t
-cooked_index_storage::hash_cutu_reader (const void *a)
+bool
+cooked_index_storage::cutu_reader_eq::operator() (const cutu_reader_up &a,
+ const cutu_reader_up &b) const noexcept
{
- const cutu_reader *reader = (const cutu_reader *) a;
- return reader->cu ()->per_cu->index;
+ return (*this) (*a->cu ()->per_cu, b);
}
/* See cooked-index-storage.h. */
-int
-cooked_index_storage::eq_cutu_reader (const void *a, const void *b)
+bool cooked_index_storage::cutu_reader_eq::operator()
+ (const dwarf2_per_cu &per_cu, const cutu_reader_up &reader) const noexcept
{
- const cutu_reader *ra = (const cutu_reader *) a;
- const int *rb = (const int *) b;
- return ra->cu ()->per_cu->index == *rb;
+ return per_cu.index == reader->cu ()->per_cu->index;
}
diff --git a/gdb/dwarf2/cooked-index-storage.h b/gdb/dwarf2/cooked-index-storage.h
index 3d0b5b2..449fbe1 100644
--- a/gdb/dwarf2/cooked-index-storage.h
+++ b/gdb/dwarf2/cooked-index-storage.h
@@ -90,18 +90,34 @@ public:
}
private:
+ /* The abbrev table cache used by this indexer. */
+ abbrev_table_cache m_abbrev_table_cache;
/* Hash function for a cutu_reader. */
- static hashval_t hash_cutu_reader (const void *a);
+ struct cutu_reader_hash
+ {
+ using is_transparent = void;
+
+ std::uint64_t operator() (const cutu_reader_up &reader) const noexcept;
+ std::uint64_t operator() (const dwarf2_per_cu &per_cu) const noexcept;
+ };
/* Equality function for cutu_reader. */
- static int eq_cutu_reader (const void *a, const void *b);
+ struct cutu_reader_eq
+ {
+ using is_transparent = void;
- /* The abbrev table cache used by this indexer. */
- abbrev_table_cache m_abbrev_table_cache;
+ bool operator() (const cutu_reader_up &a,
+ const cutu_reader_up &b) const noexcept;
+
+ bool operator() (const dwarf2_per_cu &per_cu,
+ const cutu_reader_up &reader) const noexcept;
+ };
/* A hash table of cutu_reader objects. */
- htab_up m_reader_hash;
+ gdb::unordered_set<cutu_reader_up, cutu_reader_hash, cutu_reader_eq>
+ m_reader_hash;
+
/* The index shard that is being constructed. */
cooked_index_shard_up m_shard;
diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c
index 441a852..3b80cd6 100644
--- a/gdb/dwarf2/cooked-indexer.c
+++ b/gdb/dwarf2/cooked-indexer.c
@@ -202,8 +202,11 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
the DW_AT_calling_convention attribute was used instead as
the only means available. We handle both variants then. */
case DW_AT_calling_convention:
- if (attr.constant_value (DW_CC_normal) == DW_CC_program)
- *flags |= IS_MAIN;
+ {
+ std::optional<ULONGEST> value = attr.unsigned_constant ();
+ if (value.has_value () && *value == DW_CC_program)
+ *flags |= IS_MAIN;
+ }
break;
case DW_AT_declaration:
diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
index 8c265dd..edac713 100644
--- a/gdb/dwarf2/read-debug-names.c
+++ b/gdb/dwarf2/read-debug-names.c
@@ -424,13 +424,12 @@ cooked_index_worker_debug_names::do_reading ()
exceptions.push_back (std::move (exc));
}
- dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
- per_bfd->quick_file_names_table
- = create_quick_file_names_table (per_bfd->all_units.size ());
m_results.emplace_back (nullptr,
complaint_handler.release (),
std::move (exceptions),
parent_map ());
+
+ dwarf2_per_bfd *per_bfd = m_per_objfile->per_bfd;
cooked_index *table
= (gdb::checked_static_cast<cooked_index *>
(per_bfd->index_table.get ()));
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index f6c73d0..3439163 100644
--- a/gdb/dwarf2/read-gdb-index.c
+++ b/gdb/dwarf2/read-gdb-index.c
@@ -1558,8 +1558,6 @@ dwarf2_read_gdb_index
set_main_name_from_gdb_index (per_objfile, map.get ());
per_bfd->index_table = std::move (map);
- per_bfd->quick_file_names_table =
- create_quick_file_names_table (per_bfd->all_units.size ());
return true;
}
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index f41723c..b9040a5 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -265,31 +265,6 @@ struct loclists_rnglists_header
unsigned int offset_entry_count;
};
-/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
- This includes type_unit_group and quick_file_names. */
-
-struct stmt_list_hash
-{
- /* The DWO unit this table is from or NULL if there is none. */
- struct dwo_unit *dwo_unit;
-
- /* Offset in .debug_line or .debug_line.dwo. */
- sect_offset line_sect_off;
-};
-
-/* Each element of dwarf2_per_bfd->type_unit_groups is a pointer to
- an object of this type. This contains elements of type unit groups
- that can be shared across objfiles. The non-shareable parts are in
- type_unit_group_unshareable. */
-
-struct type_unit_group
-{
- /* The data used to construct the hash key. */
- struct stmt_list_hash hash {};
-};
-
-using type_unit_group_up = std::unique_ptr<type_unit_group>;
-
/* These sections are what may appear in a (real or virtual) DWO file. */
struct dwo_sections
@@ -1535,9 +1510,6 @@ dwarf2_per_bfd::start_reading (dwarf_scanner_base_up new_table)
line_header when we're done and don't need to record it here. */
struct quick_file_names
{
- /* The data used to construct the hash key. */
- struct stmt_list_hash hash;
-
/* The number of entries in file_names, real_names. */
unsigned int num_file_names;
@@ -1579,64 +1551,34 @@ struct readnow_functions : public dwarf2_base_index_functions
}
};
-/* Utility hash function for a stmt_list_hash. */
-
-static hashval_t
-hash_stmt_list_entry (const struct stmt_list_hash *stmt_list_hash)
-{
- hashval_t v = 0;
-
- if (stmt_list_hash->dwo_unit != NULL)
- v += (uintptr_t) stmt_list_hash->dwo_unit->dwo_file;
- v += to_underlying (stmt_list_hash->line_sect_off);
- return v;
-}
-
-/* Utility equality function for a stmt_list_hash. */
+/* See read.h. */
-static int
-eq_stmt_list_entry (const struct stmt_list_hash *lhs,
- const struct stmt_list_hash *rhs)
+std::uint64_t
+stmt_list_hash_hash::operator() (const stmt_list_hash &key) const noexcept
{
- if ((lhs->dwo_unit != NULL) != (rhs->dwo_unit != NULL))
- return 0;
- if (lhs->dwo_unit != NULL
- && lhs->dwo_unit->dwo_file != rhs->dwo_unit->dwo_file)
- return 0;
-
- return lhs->line_sect_off == rhs->line_sect_off;
-}
+ std::uint64_t v = 0;
-/* Hash function for a quick_file_names. */
+ if (key.dwo_unit != nullptr)
+ v += ankerl::unordered_dense::hash<dwo_file *> () (key.dwo_unit->dwo_file);
-static hashval_t
-hash_file_name_entry (const void *e)
-{
- const struct quick_file_names *file_data
- = (const struct quick_file_names *) e;
-
- return hash_stmt_list_entry (&file_data->hash);
+ v += (ankerl::unordered_dense::hash<std::uint64_t> ()
+ (to_underlying (key.line_sect_off)));
+ return v;
}
-/* Equality function for a quick_file_names. */
+/* See read.h. */
-static int
-eq_file_name_entry (const void *a, const void *b)
+bool
+stmt_list_hash::operator== (const stmt_list_hash &rhs) const noexcept
{
- const struct quick_file_names *ea = (const struct quick_file_names *) a;
- const struct quick_file_names *eb = (const struct quick_file_names *) b;
-
- return eq_stmt_list_entry (&ea->hash, &eb->hash);
-}
+ if ((this->dwo_unit != nullptr) != (rhs.dwo_unit != nullptr))
+ return false;
-/* See read.h. */
+ if (this->dwo_unit != nullptr
+ && this->dwo_unit->dwo_file != rhs.dwo_unit->dwo_file)
+ return false;
-htab_up
-create_quick_file_names_table (unsigned int nr_initial_entries)
-{
- return htab_up (htab_create_alloc (nr_initial_entries,
- hash_file_name_entry, eq_file_name_entry,
- nullptr, xcalloc, xfree));
+ return this->line_sect_off == rhs.line_sect_off;
}
/* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE. This
@@ -1759,9 +1701,7 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
{
dwarf2_per_cu *this_cu = cu->per_cu;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
- struct attribute *attr;
- void **slot;
- struct quick_file_names *qfn;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
gdb_assert (! this_cu->is_debug_types);
@@ -1771,29 +1711,24 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
if (comp_unit_die->tag == DW_TAG_partial_unit)
return;
- slot = NULL;
-
line_header_up lh;
- sect_offset line_offset {};
file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu);
+ std::optional<stmt_list_hash> stmt_list_hash_key;
+ attribute *attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
- attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
if (attr != nullptr && attr->form_is_unsigned ())
{
- struct quick_file_names find_entry;
-
- line_offset = (sect_offset) attr->as_unsigned ();
+ sect_offset line_offset = (sect_offset) attr->as_unsigned ();
/* We may have already read in this line header (TU line header sharing).
If we have we're done. */
- find_entry.hash.dwo_unit = cu->dwo_unit;
- find_entry.hash.line_sect_off = line_offset;
- slot = htab_find_slot (per_objfile->per_bfd->quick_file_names_table.get (),
- &find_entry, INSERT);
- if (*slot != NULL)
+ stmt_list_hash_key = {cu->dwo_unit, line_offset};
+
+ if (auto it = per_bfd->quick_file_names_table.find (*stmt_list_hash_key);
+ it != per_bfd->quick_file_names_table.end ())
{
- this_cu->file_names = (struct quick_file_names *) *slot;
+ this_cu->file_names = it->second;
return;
}
@@ -1806,12 +1741,11 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
else if (lh == nullptr)
return;
- qfn = XOBNEW (&per_objfile->per_bfd->obstack, struct quick_file_names);
- qfn->hash.dwo_unit = cu->dwo_unit;
- qfn->hash.line_sect_off = line_offset;
+ auto *qfn = XOBNEW (&per_bfd->obstack, quick_file_names);
+
/* There may not be a DW_AT_stmt_list. */
- if (slot != nullptr)
- *slot = qfn;
+ if (stmt_list_hash_key.has_value ())
+ per_bfd->quick_file_names_table.emplace (*stmt_list_hash_key, qfn);
std::vector<const char *> include_names;
if (lh != nullptr)
@@ -1831,9 +1765,8 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die)
qfn->num_file_names = offset + include_names.size ();
qfn->comp_dir = fnd.intern_comp_dir (per_objfile->objfile);
- qfn->file_names =
- XOBNEWVEC (&per_objfile->per_bfd->obstack, const char *,
- qfn->num_file_names);
+ qfn->file_names
+ = XOBNEWVEC (&per_bfd->obstack, const char *, qfn->num_file_names);
if (offset != 0)
qfn->file_names[0] = per_objfile->objfile->intern (fnd.get_name ());
@@ -2348,9 +2281,6 @@ dwarf2_initialize_objfile (struct objfile *objfile,
dwarf_read_debug_printf ("readnow requested");
create_all_units (per_objfile);
- per_bfd->quick_file_names_table
- = create_quick_file_names_table (per_bfd->all_units.size ());
-
objfile->qf.emplace_front (new readnow_functions);
}
/* Was a GDB index already read when we processed an objfile sharing
@@ -2599,7 +2529,7 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0
|| (to_underlying (sig_entry->type_offset_in_section)
== to_underlying (dwo_entry->type_offset_in_tu)));
- gdb_assert (sig_entry->type_unit_group == NULL);
+ gdb_assert (!sig_entry->type_unit_group_key.has_value ());
gdb_assert (sig_entry->dwo_unit == NULL
|| sig_entry->dwo_unit == dwo_entry);
@@ -3320,71 +3250,21 @@ cutu_reader::cutu_reader (dwarf2_per_cu *this_cu,
together. A future step could be to put the types in the same symtab as
the CU the types ultimately came from. */
-static hashval_t
-hash_type_unit_group (const void *item)
-{
- const struct type_unit_group *tu_group
- = (const struct type_unit_group *) item;
-
- return hash_stmt_list_entry (&tu_group->hash);
-}
-
-static int
-eq_type_unit_group (const void *item_lhs, const void *item_rhs)
-{
- const struct type_unit_group *lhs = (const struct type_unit_group *) item_lhs;
- const struct type_unit_group *rhs = (const struct type_unit_group *) item_rhs;
-
- return eq_stmt_list_entry (&lhs->hash, &rhs->hash);
-}
-
-/* Allocate a hash table for type unit groups. */
-
-static htab_up
-allocate_type_unit_groups_table ()
-{
- return htab_up (htab_create_alloc (3,
- hash_type_unit_group,
- eq_type_unit_group,
- htab_delete_entry<type_unit_group>,
- xcalloc, xfree));
-}
-
/* Type units that don't have DW_AT_stmt_list are grouped into their own
partial symtabs. We combine several TUs per psymtab to not let the size
of any one psymtab grow too big. */
#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB (1 << 31)
#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB_SIZE 10
-/* Helper routine for get_type_unit_group.
- Create the type_unit_group object used to hold one or more TUs. */
-
-static type_unit_group_up
-create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
-{
- auto tu_group = std::make_unique<type_unit_group> ();
-
- tu_group->hash.dwo_unit = cu->dwo_unit;
- tu_group->hash.line_sect_off = line_offset_struct;
-
- return tu_group;
-}
-
-/* Look up the type_unit_group for type unit CU, and create it if necessary.
- STMT_LIST is a DW_AT_stmt_list attribute. */
+/* Get the type unit group key for type unit CU. STMT_LIST is a DW_AT_stmt_list
+ attribute. */
-static struct type_unit_group *
-get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
+static stmt_list_hash
+get_type_unit_group_key (struct dwarf2_cu *cu, const struct attribute *stmt_list)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
- struct type_unit_group *tu_group;
- void **slot;
unsigned int line_offset;
- struct type_unit_group type_unit_group_for_lookup;
-
- if (per_objfile->per_bfd->type_unit_groups == NULL)
- per_objfile->per_bfd->type_unit_groups = allocate_type_unit_groups_table ();
/* Do we need to create a new group, or can we use an existing one? */
@@ -3406,21 +3286,7 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
++tu_stats->nr_stmt_less_type_units;
}
- type_unit_group_for_lookup.hash.dwo_unit = cu->dwo_unit;
- type_unit_group_for_lookup.hash.line_sect_off = (sect_offset) line_offset;
- slot = htab_find_slot (per_objfile->per_bfd->type_unit_groups.get (),
- &type_unit_group_for_lookup, INSERT);
- if (*slot == nullptr)
- {
- sect_offset line_offset_struct = (sect_offset) line_offset;
- auto grp = create_type_unit_group (cu, line_offset_struct);
- *slot = grp.release ();
- ++tu_stats->nr_symtabs;
- }
-
- tu_group = (struct type_unit_group *) *slot;
- gdb_assert (tu_group != nullptr);
- return tu_group;
+ return {cu->dwo_unit, static_cast<sect_offset> (line_offset)};
}
/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
@@ -3525,9 +3391,6 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
abbrev_table_up abbrev_table;
sect_offset abbrev_offset;
- /* It's up to the caller to not call us multiple times. */
- gdb_assert (per_objfile->per_bfd->type_unit_groups == NULL);
-
if (per_objfile->per_bfd->all_type_units.size () == 0)
return;
@@ -3781,8 +3644,6 @@ cooked_index_worker_debug_info::do_reading ()
create_all_units (m_per_objfile);
build_type_psymtabs (m_per_objfile, &m_index_storage);
- per_bfd->quick_file_names_table
- = create_quick_file_names_table (per_bfd->all_units.size ());
if (!per_bfd->debug_aranges.empty ())
read_addrmap_from_aranges (m_per_objfile, &per_bfd->debug_aranges,
m_index_storage.get_addrmap (),
@@ -4856,16 +4717,15 @@ rust_union_quirks (struct dwarf2_cu *cu)
/* See read.h. */
type_unit_group_unshareable *
-dwarf2_per_objfile::get_type_unit_group_unshareable (type_unit_group *tu_group)
+dwarf2_per_objfile::get_type_unit_group_unshareable
+ (stmt_list_hash tu_group_key)
{
- auto iter = m_type_units.find (tu_group);
- if (iter != m_type_units.end ())
- return iter->second.get ();
+ auto [it, inserted] = m_type_units.emplace (tu_group_key, nullptr);
- type_unit_group_unshareable_up uniq (new type_unit_group_unshareable);
- type_unit_group_unshareable *result = uniq.get ();
- m_type_units[tu_group] = std::move (uniq);
- return result;
+ if (inserted)
+ it->second = std::make_unique<type_unit_group_unshareable> ();
+
+ return it->second.get ();
}
struct type *
@@ -5137,7 +4997,7 @@ process_full_type_unit (dwarf2_cu *cu)
of it with end_expandable_symtab. Otherwise, complete the addition of
this TU's symbols to the existing symtab. */
type_unit_group_unshareable *tug_unshare =
- per_objfile->get_type_unit_group_unshareable (sig_type->type_unit_group);
+ per_objfile->get_type_unit_group_unshareable (*sig_type->type_unit_group_key);
if (tug_unshare->compunit_symtab == NULL)
{
buildsym_compunit *builder = cu->get_builder ();
@@ -5947,17 +5807,14 @@ read_decl_line (struct die_info *die, struct dwarf2_cu *cu)
struct attribute *decl_line = dwarf2_attr (die, DW_AT_decl_line, cu);
if (decl_line == nullptr)
return 0;
- if (decl_line->form_is_constant ())
- {
- LONGEST val = decl_line->constant_value (0);
- if (0 <= val && val <= UINT_MAX)
- return (unsigned int) val;
+ std::optional<ULONGEST> val = decl_line->unsigned_constant ();
+ if (val.has_value ())
+ {
+ if (*val <= UINT_MAX)
+ return (unsigned int) *val;
complaint (_("Declared line for using directive is too large"));
- return 0;
}
-
- complaint (_("Declared line for using directive is of incorrect format"));
return 0;
}
@@ -6328,7 +6185,6 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
void
dwarf2_cu::setup_type_unit_groups (struct die_info *die)
{
- struct type_unit_group *tu_group;
int first_time;
struct attribute *attr;
unsigned int i;
@@ -6341,16 +6197,15 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
/* If we're using .gdb_index (includes -readnow) then
per_cu->type_unit_group may not have been set up yet. */
- if (sig_type->type_unit_group == NULL)
- sig_type->type_unit_group = get_type_unit_group (this, attr);
- tu_group = sig_type->type_unit_group;
+ if (!sig_type->type_unit_group_key.has_value ())
+ sig_type->type_unit_group_key = get_type_unit_group_key (this, attr);
/* If we've already processed this stmt_list there's no real need to
do it again, we could fake it and just recreate the part we need
(file name,index -> symtab mapping). If data shows this optimization
is useful we can do it then. */
type_unit_group_unshareable *tug_unshare
- = per_objfile->get_type_unit_group_unshareable (tu_group);
+ = per_objfile->get_type_unit_group_unshareable (*sig_type->type_unit_group_key);
first_time = tug_unshare->compunit_symtab == NULL;
/* We have to handle the case of both a missing DW_AT_stmt_list or bad
@@ -8499,8 +8354,10 @@ dwarf2_func_is_main_p (struct die_info *die, struct dwarf2_cu *cu)
if (dwarf2_flag_true_p (die, DW_AT_main_subprogram, cu))
return true;
struct attribute *attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
- return (attr != nullptr
- && attr->constant_value (DW_CC_normal) == DW_CC_program);
+ if (attr == nullptr)
+ return false;
+ std::optional<ULONGEST> value = attr->unsigned_constant ();
+ return value.has_value () && *value == DW_CC_program;
}
/* A helper to handle Ada's "Pragma Import" feature when it is applied
@@ -8620,11 +8477,14 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_external, cu);
bool external_p = attr != nullptr && attr->as_boolean ();
attr = dwarf2_attr (die, DW_AT_inline, cu);
- bool inlined_p
- = (attr != nullptr
- && attr->is_nonnegative ()
- && (attr->as_nonnegative () == DW_INL_inlined
- || attr->as_nonnegative () == DW_INL_declared_inlined));
+ bool inlined_p = false;
+ if (attr != nullptr)
+ {
+ std::optional<ULONGEST> value = attr->unsigned_constant ();
+ inlined_p = (value.has_value ()
+ && (*value == DW_INL_inlined
+ || *value == DW_INL_declared_inlined));
+ }
attr = dwarf2_attr (die, DW_AT_declaration, cu);
bool decl_p = attr != nullptr && attr->as_boolean ();
if (!external_p && !inlined_p && !decl_p)
@@ -9962,8 +9822,8 @@ dwarf2_record_block_entry_pc (struct die_info *die, struct block *block,
{
/* We could possibly handle signed constants, but this is out
of spec, so for now, just complain and ignore it. */
- complaint (_("Unhandled constant for DW_AT_entry_pc, value (%s)"),
- plongest (attr->as_nonnegative ()));
+ complaint (_("Invalid form for DW_AT_entry_pc: %s"),
+ dwarf_form_name (attr->form));
}
}
else
@@ -10093,13 +9953,16 @@ dwarf2_access_attribute (struct die_info *die, struct dwarf2_cu *cu)
attribute *attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr != nullptr)
{
- LONGEST value = attr->constant_value (-1);
- if (value == DW_ACCESS_public
- || value == DW_ACCESS_protected
- || value == DW_ACCESS_private)
- return (dwarf_access_attribute) value;
- complaint (_("Unhandled DW_AT_accessibility value (%s)"),
- plongest (value));
+ std::optional<ULONGEST> value = attr->unsigned_constant ();
+ if (value.has_value ())
+ {
+ if (*value == DW_ACCESS_public
+ || *value == DW_ACCESS_protected
+ || *value == DW_ACCESS_private)
+ return (dwarf_access_attribute) *value;
+ complaint (_("Unhandled DW_AT_accessibility value (%s)"),
+ pulongest (*value));
+ }
}
if (cu->header.version < 3 || cu->producer_is_gxx_lt_4_6 ())
@@ -11126,16 +10989,11 @@ get_alignment (struct dwarf2_cu *cu, struct die_info *die)
return 0;
}
- LONGEST val = attr->constant_value (0);
- if (val < 0)
- {
- complaint (_("DW_AT_alignment value must not be negative"
- " - DIE at %s [in module %s]"),
- sect_offset_str (die->sect_off),
- objfile_name (cu->per_objfile->objfile));
- return 0;
- }
- ULONGEST align = val;
+ std::optional<ULONGEST> val = attr->unsigned_constant ();
+ if (!val.has_value ())
+ return 0;
+
+ ULONGEST align = *val;
if (align == 0)
{
@@ -11302,12 +11160,16 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
the die. Otherwise the calling convention remains set to
the default value DW_CC_normal. */
attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
- if (attr != nullptr
- && is_valid_DW_AT_calling_convention_for_type (attr->constant_value (0)))
+ if (attr != nullptr)
{
- ALLOCATE_CPLUS_STRUCT_TYPE (type);
- TYPE_CPLUS_CALLING_CONVENTION (type)
- = (enum dwarf_calling_convention) (attr->constant_value (0));
+ std::optional<ULONGEST> value = attr->unsigned_constant ();
+ if (value.has_value ()
+ && is_valid_DW_AT_calling_convention_for_type (*value))
+ {
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_CPLUS_CALLING_CONVENTION (type)
+ = (enum dwarf_calling_convention) *value;
+ }
}
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
@@ -11773,19 +11635,26 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order)
attribute *attr = dwarf2_attr (die, DW_AT_endianity, cu);
if (attr != nullptr && attr->form_is_constant ())
{
- int endianity = attr->constant_value (0);
+ std::optional<ULONGEST> endianity = attr->unsigned_constant ();
- switch (endianity)
+ if (endianity.has_value ())
{
- case DW_END_big:
- new_order = BFD_ENDIAN_BIG;
- break;
- case DW_END_little:
- new_order = BFD_ENDIAN_LITTLE;
- break;
- default:
- complaint (_("DW_AT_endianity has unrecognized value %d"), endianity);
- break;
+ switch (*endianity)
+ {
+ case DW_END_default:
+ /* Nothing. */
+ break;
+ case DW_END_big:
+ new_order = BFD_ENDIAN_BIG;
+ break;
+ case DW_END_little:
+ new_order = BFD_ENDIAN_LITTLE;
+ break;
+ default:
+ complaint (_("DW_AT_endianity has unrecognized value %s"),
+ pulongest (*endianity));
+ break;
+ }
}
}
@@ -12439,9 +12308,10 @@ read_array_order (struct die_info *die, struct dwarf2_cu *cu)
if (attr != nullptr)
{
- LONGEST val = attr->constant_value (-1);
- if (val == DW_ORD_row_major || val == DW_ORD_col_major)
- return (enum dwarf_array_dim_ordering) val;
+ std::optional<ULONGEST> val = attr->unsigned_constant ();
+ if (val.has_value () &&
+ (*val == DW_ORD_row_major || *val == DW_ORD_col_major))
+ return (enum dwarf_array_dim_ordering) *val;
}
/* GNU F77 is a special case, as at 08/2004 array type info is the
@@ -12847,7 +12717,7 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
struct type *type;
struct attribute *attr_byte_size;
struct attribute *attr_address_class;
- int byte_size, addr_class;
+ int byte_size;
struct type *target_type;
target_type = die_type (die, cu);
@@ -12866,8 +12736,10 @@ read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
byte_size = cu_header->addr_size;
attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu);
+ ULONGEST addr_class;
if (attr_address_class)
- addr_class = attr_address_class->constant_value (DW_ADDR_none);
+ addr_class = (attr_address_class->unsigned_constant ()
+ .value_or (DW_ADDR_none));
else
addr_class = DW_ADDR_none;
@@ -13269,10 +13141,14 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
the subroutine die. Otherwise set the calling convention to
the default value DW_CC_normal. */
attr = dwarf2_attr (die, DW_AT_calling_convention, cu);
- if (attr != nullptr
- && is_valid_DW_AT_calling_convention_for_subroutine (attr->constant_value (0)))
- TYPE_CALLING_CONVENTION (ftype)
- = (enum dwarf_calling_convention) attr->constant_value (0);
+ if (attr != nullptr)
+ {
+ std::optional<ULONGEST> value = attr->unsigned_constant ();
+ if (value.has_value ()
+ && is_valid_DW_AT_calling_convention_for_subroutine (*value))
+ TYPE_CALLING_CONVENTION (ftype)
+ = (enum dwarf_calling_convention) *value;
+ }
else if (cu->producer_is_xlc_opencl ())
TYPE_CALLING_CONVENTION (ftype) = DW_CC_GDB_IBM_OpenCL;
else
@@ -13863,12 +13739,17 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
struct objfile *objfile = cu->per_objfile->objfile;
struct type *type;
struct attribute *attr;
- int encoding = 0, bits = 0;
+ ULONGEST encoding = 0;
+ int bits = 0;
const char *name;
attr = dwarf2_attr (die, DW_AT_encoding, cu);
- if (attr != nullptr && attr->form_is_constant ())
- encoding = attr->constant_value (0);
+ if (attr != nullptr)
+ {
+ std::optional<ULONGEST> value = attr->unsigned_constant ();
+ if (value.has_value ())
+ encoding = *value;
+ }
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr != nullptr)
bits = attr->constant_value (0) * TARGET_CHAR_BIT;
@@ -15699,7 +15580,7 @@ leb128_size (const gdb_byte *buf)
/* Converts DWARF language names to GDB language names. */
enum language
-dwarf_lang_to_enum_language (unsigned int lang)
+dwarf_lang_to_enum_language (ULONGEST lang)
{
enum language language;
@@ -16973,33 +16854,36 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
inlined_func ? DW_AT_call_line : DW_AT_decl_line,
cu);
if (attr != nullptr)
- sym->set_line (attr->constant_value (0));
+ sym->set_line (attr->unsigned_constant ().value_or (0));
struct dwarf2_cu *file_cu = cu;
attr = dwarf2_attr (die,
inlined_func ? DW_AT_call_file : DW_AT_decl_file,
&file_cu);
- if (attr != nullptr && attr->is_nonnegative ())
+ if (attr != nullptr)
{
- file_name_index file_index
- = (file_name_index) attr->as_nonnegative ();
- struct file_entry *fe;
-
- if (file_cu->line_header == nullptr)
+ std::optional<ULONGEST> index_cst = attr->unsigned_constant ();
+ if (index_cst.has_value ())
{
- file_and_directory fnd (nullptr, nullptr);
- handle_DW_AT_stmt_list (file_cu->dies, file_cu, fnd, {}, false);
- }
+ file_name_index file_index = (file_name_index) *index_cst;
+ struct file_entry *fe;
- if (file_cu->line_header != nullptr)
- fe = file_cu->line_header->file_name_at (file_index);
- else
- fe = NULL;
+ if (file_cu->line_header == nullptr)
+ {
+ file_and_directory fnd (nullptr, nullptr);
+ handle_DW_AT_stmt_list (file_cu->dies, file_cu, fnd, {}, false);
+ }
- if (fe == NULL)
- complaint (_("file index out of range"));
- else
- sym->set_symtab (fe->symtab);
+ if (file_cu->line_header != nullptr)
+ fe = file_cu->line_header->file_name_at (file_index);
+ else
+ fe = NULL;
+
+ if (fe == NULL)
+ complaint (_("file index out of range"));
+ else
+ sym->set_symtab (fe->symtab);
+ }
}
switch (die->tag)
@@ -19730,8 +19614,15 @@ cutu_reader::prepare_one_comp_unit (struct dwarf2_cu *cu,
}
else if (attr != nullptr)
{
- lang = dwarf_lang_to_enum_language (attr->constant_value (0));
- dw_lang = (dwarf_source_language) attr->constant_value (0);
+ std::optional<ULONGEST> lang_val = attr->unsigned_constant ();
+ if (lang_val.has_value ())
+ {
+ lang = dwarf_lang_to_enum_language (*lang_val);
+ if (lang_val <= DW_LANG_hi_user)
+ dw_lang = (dwarf_source_language) *lang_val;
+ }
+ else
+ lang = language_minimal;
}
else
lang = pretend_language;
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index be6549b..ba2dd07 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -55,7 +55,6 @@ struct dwarf2_per_cu;
struct mapped_index;
struct mapped_debug_names;
struct signatured_type;
-struct type_unit_group;
/* One item on the queue of compilation units to read in full symbols
for. */
@@ -74,6 +73,27 @@ struct dwarf2_queue_item
dwarf2_per_objfile *per_objfile;
};
+/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
+ This includes type_unit_group and quick_file_names. */
+
+struct stmt_list_hash
+{
+ bool operator== (const stmt_list_hash &other) const noexcept;
+
+ /* The DWO unit this table is from or NULL if there is none. */
+ struct dwo_unit *dwo_unit;
+
+ /* Offset in .debug_line or .debug_line.dwo. */
+ sect_offset line_sect_off;
+};
+
+struct stmt_list_hash_hash
+{
+ using is_avalanching = void;
+
+ std::uint64_t operator() (const stmt_list_hash &key) const noexcept;
+};
+
/* A deleter for dwarf2_per_cu that knows to downcast to signatured_type as
appropriate. This approach lets us avoid a virtual destructor, which saves
a bit of space. */
@@ -376,8 +396,9 @@ struct signatured_type : public dwarf2_per_cu
sect_offset type_offset_in_section {};
/* Type units are grouped by their DW_AT_stmt_list entry so that they
- can share them. This points to the containing symtab. */
- struct type_unit_group *type_unit_group = nullptr;
+ can share them. This is the key of the group this type unit is part
+ of. */
+ std::optional<stmt_list_hash> type_unit_group_key;
/* Containing DWO unit.
This field is valid iff per_cu.reading_dwo_directly. */
@@ -603,10 +624,6 @@ public:
std::vector<dwarf2_per_cu *> all_comp_units_index_cus;
std::vector<dwarf2_per_cu *> all_comp_units_index_tus;
- /* Table of struct type_unit_group objects.
- The hash key is the DW_AT_stmt_list value. */
- htab_up type_unit_groups;
-
/* Set of signatured_types, used to look up by signature. */
signatured_type_set signatured_types;
@@ -644,7 +661,8 @@ public:
sorted all the TUs into "type unit groups", grouped by their
DW_AT_stmt_list value. Therefore the only sharing done here is with a
CU and its associated TU group if there is one. */
- htab_up quick_file_names_table;
+ gdb::unordered_map<stmt_list_hash, quick_file_names *, stmt_list_hash_hash>
+ quick_file_names_table;
/* The CUs we recently read. */
std::vector<dwarf2_per_cu *> just_read_cus;
@@ -815,10 +833,10 @@ struct dwarf2_per_objfile
/* Set the compunit_symtab associated to PER_CU. */
void set_symtab (const dwarf2_per_cu *per_cu, compunit_symtab *symtab);
- /* Get the type_unit_group_unshareable corresponding to TU_GROUP. If one
+ /* Get the type_unit_group_unshareable corresponding to TU_GROUP_KEY. If one
does not exist, create it. */
type_unit_group_unshareable *get_type_unit_group_unshareable
- (type_unit_group *tu_group);
+ (stmt_list_hash tu_group_key);
struct type *get_type_for_signatured_type (signatured_type *sig_type) const;
@@ -885,9 +903,10 @@ private:
expanded yet. */
std::vector<compunit_symtab *> m_symtabs;
- /* Map from a type unit group to the corresponding unshared
+ /* Map from a type unit group key to the corresponding unshared
structure. */
- gdb::unordered_map<type_unit_group *, type_unit_group_unshareable_up>
+ gdb::unordered_map<stmt_list_hash, type_unit_group_unshareable_up,
+ stmt_list_hash_hash>
m_type_units;
/* Map from signatured types to the corresponding struct type. */
@@ -1047,7 +1066,7 @@ private:
/* Converts DWARF language names to GDB language names. */
-enum language dwarf_lang_to_enum_language (unsigned int lang);
+enum language dwarf_lang_to_enum_language (ULONGEST lang);
/* Get the dwarf2_per_objfile associated to OBJFILE. */
@@ -1194,10 +1213,6 @@ extern void finalize_all_units (dwarf2_per_bfd *per_bfd);
extern void create_all_units (dwarf2_per_objfile *per_objfile);
-/* Create a quick_file_names hash table. */
-
-extern htab_up create_quick_file_names_table (unsigned int nr_initial_entries);
-
/* Find the base address of the compilation unit for range lists and
location lists. It will normally be specified by DW_AT_low_pc.
In DWARF-3 draft 4, the base address could be overridden by
diff --git a/gdb/testsuite/gdb.base/enum_cond.c b/gdb/testsuite/gdb.base/enum_cond.c
index 35e126a..df8830f 100644
--- a/gdb/testsuite/gdb.base/enum_cond.c
+++ b/gdb/testsuite/gdb.base/enum_cond.c
@@ -46,3 +46,19 @@ main (void)
return 0;
}
+void
+exit (int status)
+{
+#if HAVE_BUILTIN_TRAP
+ __builtin_trap ();
+#endif
+ while (1)
+ ;
+}
+
+void
+_start (void)
+{
+ main ();
+ exit (0);
+}
diff --git a/gdb/testsuite/gdb.base/enum_cond.exp b/gdb/testsuite/gdb.base/enum_cond.exp
index 3ee90f8..d58da47 100644
--- a/gdb/testsuite/gdb.base/enum_cond.exp
+++ b/gdb/testsuite/gdb.base/enum_cond.exp
@@ -19,7 +19,20 @@
standard_testfile .c
-set opts [list debug additional_flags=-fshort-enums]
+set opts {}
+lappend opts debug
+lappend opts additional_flags=-fshort-enums
+# Without -nostdlib, on arm we run into:
+#
+# ld: warning: enum_cond.o uses variable-size enums yet the output is to use
+# 32-bit enums; use of enum values across objects may fail
+#
+# due to conflicting values for Tag_ABI_enum_size between enum_cond.o and
+# linked-in objects. Work around this by using -nostdlib, making sure there's
+# just one object, and no such conflict can happen.
+lappend opts additional_flags=-nostdlib
+lappend opts additional_flags=-DHAVE_BUILTIN_TRAP=[have_builtin_trap]
+
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $opts] != "" } {
untested "failed to compile"
return -1
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 481f9ec..3349da7 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -11072,5 +11072,17 @@ proc section_get {exec section} {
return $retval
}
+# Return 1 if the compiler supports __builtin_trap, else return 0.
+
+gdb_caching_proc have_builtin_trap {} {
+
+ return [gdb_can_simple_compile builtin_trap {
+ int main() {
+ __builtin_trap ();
+ return 0;
+ }
+ } executable]
+}
+
# Always load compatibility stuff.
load_lib future.exp