/* Support routines for manipulating internal types for GDB.
- Copyright (C) 1992-2016 Free Software Foundation, Inc.
+ Copyright (C) 1992-2017 Free Software Foundation, Inc.
Contributed by Cygnus Support, using pieces from other GDB modules.
#include "bcache.h"
#include "dwarf2loc.h"
#include "gdbcore.h"
+#include "floatformat.h"
/* Initialize BADNESS constants. */
const struct rank INTEGER_PROMOTION_BADNESS = {1,0};
const struct rank FLOAT_PROMOTION_BADNESS = {1,0};
const struct rank BASE_PTR_CONVERSION_BADNESS = {1,0};
+const struct rank CV_CONVERSION_BADNESS = {1, 0};
const struct rank INTEGER_CONVERSION_BADNESS = {2,0};
const struct rank FLOAT_CONVERSION_BADNESS = {2,0};
const struct rank INT_FLOAT_CONVERSION_BADNESS = {2,0};
/* Lookup a C++ `reference' to a type TYPE. TYPEPTR, if nonzero,
points to a pointer to memory where the reference type should be
stored. If *TYPEPTR is zero, update it to point to the reference
- type we return. We allocate new memory if needed. */
+ type we return. We allocate new memory if needed. REFCODE denotes
+ the kind of reference type to lookup (lvalue or rvalue reference). */
struct type *
-make_reference_type (struct type *type, struct type **typeptr)
+make_reference_type (struct type *type, struct type **typeptr,
+ enum type_code refcode)
{
struct type *ntype; /* New type */
+ struct type **reftype;
struct type *chain;
- ntype = TYPE_REFERENCE_TYPE (type);
+ gdb_assert (refcode == TYPE_CODE_REF || refcode == TYPE_CODE_RVALUE_REF);
+
+ ntype = (refcode == TYPE_CODE_REF ? TYPE_REFERENCE_TYPE (type)
+ : TYPE_RVALUE_REFERENCE_TYPE (type));
if (ntype)
{
}
TYPE_TARGET_TYPE (ntype) = type;
- TYPE_REFERENCE_TYPE (type) = ntype;
+ reftype = (refcode == TYPE_CODE_REF ? &TYPE_REFERENCE_TYPE (type)
+ : &TYPE_RVALUE_REFERENCE_TYPE (type));
+
+ *reftype = ntype;
/* FIXME! Assume the machine has only one representation for
references, and that it matches the (only) representation for
TYPE_LENGTH (ntype) =
gdbarch_ptr_bit (get_type_arch (type)) / TARGET_CHAR_BIT;
- TYPE_CODE (ntype) = TYPE_CODE_REF;
+ TYPE_CODE (ntype) = refcode;
- if (!TYPE_REFERENCE_TYPE (type)) /* Remember it, if don't have one. */
- TYPE_REFERENCE_TYPE (type) = ntype;
+ *reftype = ntype;
/* Update the length of all the other variants of this type. */
chain = TYPE_CHAIN (ntype);
details. */
struct type *
-lookup_reference_type (struct type *type)
+lookup_reference_type (struct type *type, enum type_code refcode)
+{
+ return make_reference_type (type, (struct type **) 0, refcode);
+}
+
+/* Lookup the lvalue reference type for the type TYPE. */
+
+struct type *
+lookup_lvalue_reference_type (struct type *type)
+{
+ return lookup_reference_type (type, TYPE_CODE_REF);
+}
+
+/* Lookup the rvalue reference type for the type TYPE. */
+
+struct type *
+lookup_rvalue_reference_type (struct type *type)
{
- return make_reference_type (type, (struct type **) 0);
+ return lookup_reference_type (type, TYPE_CODE_RVALUE_REF);
}
/* Lookup a function type that returns type TYPE. TYPEPTR, if
gdb_assert (nparams == 0);
TYPE_PROTOTYPED (fn) = 1;
}
+ else
+ TYPE_PROTOTYPED (fn) = 1;
}
TYPE_NFIELDS (fn) = nparams;
lookup_struct_elt_type (struct type *type, const char *name, int noerr)
{
int i;
- char *type_name;
for (;;)
{
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION)
{
- type_name = type_to_string (type);
- make_cleanup (xfree, type_name);
- error (_("Type %s is not a structure or union type."), type_name);
+ std::string type_name = type_to_string (type);
+ error (_("Type %s is not a structure or union type."),
+ type_name.c_str ());
}
#if 0
return NULL;
}
- type_name = type_to_string (type);
- make_cleanup (xfree, type_name);
- error (_("Type %s has no component named %s."), type_name, name);
+ std::string type_name = type_to_string (type);
+ error (_("Type %s has no component named %s."), type_name.c_str (), name);
}
/* Store in *MAX the largest number representable by unsigned integer type
/* Suppress error messages. */
saved_gdb_stderr = gdb_stderr;
- gdb_stderr = ui_file_new ();
+ gdb_stderr = &null_stream;
/* Call parse_and_eval_type() without fear of longjmp()s. */
TRY
END_CATCH
/* Stop suppressing error messages. */
- ui_file_delete (gdb_stderr);
gdb_stderr = saved_gdb_stderr;
return type;
determined by the floatformat. Returns size to be used. */
static int
-verify_floatformat (int bit, const struct floatformat **floatformats)
+verify_floatformat (int bit, const struct floatformat *floatformat)
{
+ gdb_assert (floatformat != NULL);
+
if (bit == -1)
- {
- gdb_assert (floatformats != NULL);
- gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL);
- bit = floatformats[0]->totalsize;
- }
+ bit = floatformat->totalsize;
+
gdb_assert (bit >= 0);
+ gdb_assert (bit >= floatformat->totalsize);
- if (floatformats != NULL)
- {
- size_t len = bit / TARGET_CHAR_BIT;
+ return bit;
+}
- gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0]));
- gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1]));
- }
+/* Return the floating-point format for a floating-point variable of
+ type TYPE. */
- return bit;
+const struct floatformat *
+floatformat_from_type (const struct type *type)
+{
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+ gdb_assert (TYPE_FLOATFORMAT (type));
+ return TYPE_FLOATFORMAT (type);
}
/* Helper function to initialize the standard scalar types.
least as long as OBJFILE. */
struct type *
-init_type (struct objfile *objfile, enum type_code code, int length,
+init_type (struct objfile *objfile, enum type_code code, int bit,
const char *name)
{
struct type *type;
type = alloc_type (objfile);
set_type_code (type, code);
- TYPE_LENGTH (type) = length;
+ gdb_assert ((bit % TARGET_CHAR_BIT) == 0);
+ TYPE_LENGTH (type) = bit / TARGET_CHAR_BIT;
TYPE_NAME (type) = name;
- /* C++ fancies. */
+ return type;
+}
- if (name && strcmp (name, "char") == 0)
- TYPE_NOSIGN (type) = 1;
+/* Allocate a TYPE_CODE_ERROR type structure associated with OBJFILE,
+ to use with variables that have no debug info. NAME is the type
+ name. */
- return type;
+static struct type *
+init_nodebug_var_type (struct objfile *objfile, const char *name)
+{
+ return init_type (objfile, TYPE_CODE_ERROR, 0, name);
}
/* Allocate a TYPE_CODE_INT type structure associated with OBJFILE.
{
struct type *t;
- t = init_type (objfile, TYPE_CODE_INT, bit / TARGET_CHAR_BIT, name);
+ t = init_type (objfile, TYPE_CODE_INT, bit, name);
if (unsigned_p)
TYPE_UNSIGNED (t) = 1;
{
struct type *t;
- t = init_type (objfile, TYPE_CODE_CHAR, bit / TARGET_CHAR_BIT, name);
+ t = init_type (objfile, TYPE_CODE_CHAR, bit, name);
if (unsigned_p)
TYPE_UNSIGNED (t) = 1;
{
struct type *t;
- t = init_type (objfile, TYPE_CODE_BOOL, bit / TARGET_CHAR_BIT, name);
+ t = init_type (objfile, TYPE_CODE_BOOL, bit, name);
if (unsigned_p)
TYPE_UNSIGNED (t) = 1;
int bit, const char *name,
const struct floatformat **floatformats)
{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ const struct floatformat *fmt = floatformats[gdbarch_byte_order (gdbarch)];
struct type *t;
- bit = verify_floatformat (bit, floatformats);
- t = init_type (objfile, TYPE_CODE_FLT, bit / TARGET_CHAR_BIT, name);
- TYPE_FLOATFORMAT (t) = floatformats;
+ bit = verify_floatformat (bit, fmt);
+ t = init_type (objfile, TYPE_CODE_FLT, bit, name);
+ TYPE_FLOATFORMAT (t) = fmt;
return t;
}
{
struct type *t;
- t = init_type (objfile, TYPE_CODE_DECFLOAT, bit / TARGET_CHAR_BIT, name);
+ t = init_type (objfile, TYPE_CODE_DECFLOAT, bit, name);
return t;
}
struct type *t;
t = init_type (objfile, TYPE_CODE_COMPLEX,
- 2 * TYPE_LENGTH (target_type), name);
+ 2 * TYPE_LENGTH (target_type) * TARGET_CHAR_BIT, name);
TYPE_TARGET_TYPE (t) = target_type;
return t;
}
{
struct type *t;
- t = init_type (objfile, TYPE_CODE_PTR, bit / TARGET_CHAR_BIT, name);
+ t = init_type (objfile, TYPE_CODE_PTR, bit, name);
TYPE_TARGET_TYPE (t) = target_type;
TYPE_UNSIGNED (t) = 1;
return t;
|| (TYPE_CODE (t) == TYPE_CODE_BOOL)));
}
+int
+is_floating_type (struct type *t)
+{
+ t = check_typedef (t);
+ return
+ ((t != NULL)
+ && ((TYPE_CODE (t) == TYPE_CODE_FLT)
+ || (TYPE_CODE (t) == TYPE_CODE_DECFLOAT)));
+}
+
/* Return true if TYPE is scalar. */
int
{
struct rank rank = {0,0};
- if (types_equal (parm, arg))
- return EXACT_MATCH_BADNESS;
-
/* Resolve typedefs */
if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF)
parm = check_typedef (parm);
if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
arg = check_typedef (arg);
+ if (TYPE_IS_REFERENCE (parm) && value != NULL)
+ {
+ if (VALUE_LVAL (value) == not_lval)
+ {
+ /* Rvalues should preferably bind to rvalue references or const
+ lvalue references. */
+ if (TYPE_CODE (parm) == TYPE_CODE_RVALUE_REF)
+ rank.subrank = REFERENCE_CONVERSION_RVALUE;
+ else if (TYPE_CONST (TYPE_TARGET_TYPE (parm)))
+ rank.subrank = REFERENCE_CONVERSION_CONST_LVALUE;
+ else
+ return INCOMPATIBLE_TYPE_BADNESS;
+ return sum_ranks (rank, REFERENCE_CONVERSION_BADNESS);
+ }
+ else
+ {
+ /* Lvalues should prefer lvalue overloads. */
+ if (TYPE_CODE (parm) == TYPE_CODE_RVALUE_REF)
+ {
+ rank.subrank = REFERENCE_CONVERSION_RVALUE;
+ return sum_ranks (rank, REFERENCE_CONVERSION_BADNESS);
+ }
+ }
+ }
+
+ if (types_equal (parm, arg))
+ {
+ struct type *t1 = parm;
+ struct type *t2 = arg;
+
+ /* For pointers and references, compare target type. */
+ if (TYPE_CODE (parm) == TYPE_CODE_PTR || TYPE_IS_REFERENCE (parm))
+ {
+ t1 = TYPE_TARGET_TYPE (parm);
+ t2 = TYPE_TARGET_TYPE (arg);
+ }
+
+ /* Make sure they are CV equal, too. */
+ if (TYPE_CONST (t1) != TYPE_CONST (t2))
+ rank.subrank |= CV_CONVERSION_CONST;
+ if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
+ rank.subrank |= CV_CONVERSION_VOLATILE;
+ if (rank.subrank != 0)
+ return sum_ranks (CV_CONVERSION_BADNESS, rank);
+ return EXACT_MATCH_BADNESS;
+ }
+
/* See through references, since we can almost make non-references
references. */
- if (TYPE_CODE (arg) == TYPE_CODE_REF)
+
+ if (TYPE_IS_REFERENCE (arg))
return (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg), NULL),
REFERENCE_CONVERSION_BADNESS));
- if (TYPE_CODE (parm) == TYPE_CODE_REF)
+ if (TYPE_IS_REFERENCE (parm))
return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL),
REFERENCE_CONVERSION_BADNESS));
if (overload_debug)
return INCOMPATIBLE_TYPE_BADNESS;
case TYPE_CODE_ARRAY:
- if (types_equal (TYPE_TARGET_TYPE (parm),
- TYPE_TARGET_TYPE (arg)))
- return EXACT_MATCH_BADNESS;
- return INCOMPATIBLE_TYPE_BADNESS;
+ {
+ struct type *t1 = TYPE_TARGET_TYPE (parm);
+ struct type *t2 = TYPE_TARGET_TYPE (arg);
+
+ if (types_equal (t1, t2))
+ {
+ /* Make sure they are CV equal. */
+ if (TYPE_CONST (t1) != TYPE_CONST (t2))
+ rank.subrank |= CV_CONVERSION_CONST;
+ if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
+ rank.subrank |= CV_CONVERSION_VOLATILE;
+ if (rank.subrank != 0)
+ return sum_ranks (CV_CONVERSION_BADNESS, rank);
+ return EXACT_MATCH_BADNESS;
+ }
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
case TYPE_CODE_FUNC:
return rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL);
case TYPE_CODE_INT:
{
puts_filtered (" TYPE_TARGET_STUB");
}
- if (TYPE_STATIC (type))
- {
- puts_filtered (" TYPE_STATIC");
- }
if (TYPE_PROTOTYPED (type))
{
puts_filtered (" TYPE_PROTOTYPED");
case TYPE_SPECIFIC_FLOATFORMAT:
printfi_filtered (spaces, "floatformat ");
- if (TYPE_FLOATFORMAT (type) == NULL)
+ if (TYPE_FLOATFORMAT (type) == NULL
+ || TYPE_FLOATFORMAT (type)->name == NULL)
puts_filtered ("(null)");
else
- {
- puts_filtered ("{ ");
- if (TYPE_FLOATFORMAT (type)[0] == NULL
- || TYPE_FLOATFORMAT (type)[0]->name == NULL)
- puts_filtered ("(null)");
- else
- puts_filtered (TYPE_FLOATFORMAT (type)[0]->name);
-
- puts_filtered (", ");
- if (TYPE_FLOATFORMAT (type)[1] == NULL
- || TYPE_FLOATFORMAT (type)[1]->name == NULL)
- puts_filtered ("(null)");
- else
- puts_filtered (TYPE_FLOATFORMAT (type)[1]->name);
-
- puts_filtered (" }");
- }
+ puts_filtered (TYPE_FLOATFORMAT (type)->name);
puts_filtered ("\n");
break;
struct type *
arch_type (struct gdbarch *gdbarch,
- enum type_code code, int length, const char *name)
+ enum type_code code, int bit, const char *name)
{
struct type *type;
type = alloc_type_arch (gdbarch);
set_type_code (type, code);
- TYPE_LENGTH (type) = length;
+ gdb_assert ((bit % TARGET_CHAR_BIT) == 0);
+ TYPE_LENGTH (type) = bit / TARGET_CHAR_BIT;
if (name)
TYPE_NAME (type) = gdbarch_obstack_strdup (gdbarch, name);
{
struct type *t;
- t = arch_type (gdbarch, TYPE_CODE_INT, bit / TARGET_CHAR_BIT, name);
+ t = arch_type (gdbarch, TYPE_CODE_INT, bit, name);
if (unsigned_p)
TYPE_UNSIGNED (t) = 1;
- if (name && strcmp (name, "char") == 0)
- TYPE_NOSIGN (t) = 1;
return t;
}
{
struct type *t;
- t = arch_type (gdbarch, TYPE_CODE_CHAR, bit / TARGET_CHAR_BIT, name);
+ t = arch_type (gdbarch, TYPE_CODE_CHAR, bit, name);
if (unsigned_p)
TYPE_UNSIGNED (t) = 1;
{
struct type *t;
- t = arch_type (gdbarch, TYPE_CODE_BOOL, bit / TARGET_CHAR_BIT, name);
+ t = arch_type (gdbarch, TYPE_CODE_BOOL, bit, name);
if (unsigned_p)
TYPE_UNSIGNED (t) = 1;
int bit, const char *name,
const struct floatformat **floatformats)
{
+ const struct floatformat *fmt = floatformats[gdbarch_byte_order (gdbarch)];
struct type *t;
- bit = verify_floatformat (bit, floatformats);
- t = arch_type (gdbarch, TYPE_CODE_FLT, bit / TARGET_CHAR_BIT, name);
- TYPE_FLOATFORMAT (t) = floatformats;
+ bit = verify_floatformat (bit, fmt);
+ t = arch_type (gdbarch, TYPE_CODE_FLT, bit, name);
+ TYPE_FLOATFORMAT (t) = fmt;
return t;
}
{
struct type *t;
- t = arch_type (gdbarch, TYPE_CODE_DECFLOAT, bit / TARGET_CHAR_BIT, name);
+ t = arch_type (gdbarch, TYPE_CODE_DECFLOAT, bit, name);
return t;
}
struct type *t;
t = arch_type (gdbarch, TYPE_CODE_COMPLEX,
- 2 * TYPE_LENGTH (target_type), name);
+ 2 * TYPE_LENGTH (target_type) * TARGET_CHAR_BIT, name);
TYPE_TARGET_TYPE (t) = target_type;
return t;
}
{
struct type *t;
- t = arch_type (gdbarch, TYPE_CODE_PTR, bit / TARGET_CHAR_BIT, name);
+ t = arch_type (gdbarch, TYPE_CODE_PTR, bit, name);
TYPE_TARGET_TYPE (t) = target_type;
TYPE_UNSIGNED (t) = 1;
return t;
}
/* Allocate a TYPE_CODE_FLAGS type structure associated with GDBARCH.
- NAME is the type name. LENGTH is the size of the flag word in bytes. */
+ NAME is the type name. BIT is the size of the flag word in bits. */
struct type *
-arch_flags_type (struct gdbarch *gdbarch, const char *name, int length)
+arch_flags_type (struct gdbarch *gdbarch, const char *name, int bit)
{
- int max_nfields = length * TARGET_CHAR_BIT;
struct type *type;
- type = arch_type (gdbarch, TYPE_CODE_FLAGS, length, name);
+ type = arch_type (gdbarch, TYPE_CODE_FLAGS, bit, name);
TYPE_UNSIGNED (type) = 1;
TYPE_NFIELDS (type) = 0;
/* Pre-allocate enough space assuming every field is one bit. */
TYPE_FIELDS (type)
- = (struct field *) TYPE_ZALLOC (type, max_nfields * sizeof (struct field));
+ = (struct field *) TYPE_ZALLOC (type, bit * sizeof (struct field));
return type;
}
/* Basic types. */
builtin_type->builtin_void
- = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
+ = arch_type (gdbarch, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void");
builtin_type->builtin_char
= arch_integer_type (gdbarch, TARGET_CHAR_BIT,
!gdbarch_char_signed (gdbarch), "char");
+ TYPE_NOSIGN (builtin_type->builtin_char) = 1;
builtin_type->builtin_signed_char
= arch_integer_type (gdbarch, TARGET_CHAR_BIT,
0, "signed char");
= arch_complex_type (gdbarch, "double complex",
builtin_type->builtin_double);
builtin_type->builtin_string
- = arch_type (gdbarch, TYPE_CODE_STRING, 1, "string");
+ = arch_type (gdbarch, TYPE_CODE_STRING, TARGET_CHAR_BIT, "string");
builtin_type->builtin_bool
- = arch_type (gdbarch, TYPE_CODE_BOOL, 1, "bool");
+ = arch_type (gdbarch, TYPE_CODE_BOOL, TARGET_CHAR_BIT, "bool");
/* The following three are about decimal floating point types, which
are 32-bits, 64-bits and 128-bits respectively. */
/* Wide character types. */
builtin_type->builtin_char16
- = arch_integer_type (gdbarch, 16, 0, "char16_t");
+ = arch_integer_type (gdbarch, 16, 1, "char16_t");
builtin_type->builtin_char32
- = arch_integer_type (gdbarch, 32, 0, "char32_t");
-
+ = arch_integer_type (gdbarch, 32, 1, "char32_t");
+ builtin_type->builtin_wchar
+ = arch_integer_type (gdbarch, gdbarch_wchar_bit (gdbarch),
+ !gdbarch_wchar_signed (gdbarch), "wchar_t");
/* Default data/code pointer types. */
builtin_type->builtin_data_ptr
/* Basic types. */
objfile_type->builtin_void
- = init_type (objfile, TYPE_CODE_VOID, 1, "void");
+ = init_type (objfile, TYPE_CODE_VOID, TARGET_CHAR_BIT, "void");
objfile_type->builtin_char
= init_integer_type (objfile, TARGET_CHAR_BIT,
!gdbarch_char_signed (gdbarch), "char");
+ TYPE_NOSIGN (objfile_type->builtin_char) = 1;
objfile_type->builtin_signed_char
= init_integer_type (objfile, TARGET_CHAR_BIT,
0, "signed char");
/* The following set of types is used for symbols with no
debug information. */
objfile_type->nodebug_text_symbol
- = init_type (objfile, TYPE_CODE_FUNC, 1,
+ = init_type (objfile, TYPE_CODE_FUNC, TARGET_CHAR_BIT,
"<text variable, no debug info>");
- TYPE_TARGET_TYPE (objfile_type->nodebug_text_symbol)
- = objfile_type->builtin_int;
objfile_type->nodebug_text_gnu_ifunc_symbol
- = init_type (objfile, TYPE_CODE_FUNC, 1,
+ = init_type (objfile, TYPE_CODE_FUNC, TARGET_CHAR_BIT,
"<text gnu-indirect-function variable, no debug info>");
+ /* Ifunc resolvers return a function address. */
TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol)
- = objfile_type->nodebug_text_symbol;
+ = init_integer_type (objfile, gdbarch_addr_bit (gdbarch), 1,
+ "__IFUNC_RESOLVER_RET");
TYPE_GNU_IFUNC (objfile_type->nodebug_text_gnu_ifunc_symbol) = 1;
objfile_type->nodebug_got_plt_symbol
= init_pointer_type (objfile, gdbarch_addr_bit (gdbarch),
"<text from jump slot in .got.plt, no debug info>",
objfile_type->nodebug_text_symbol);
objfile_type->nodebug_data_symbol
- = init_integer_type (objfile, gdbarch_int_bit (gdbarch), 0,
- "<data variable, no debug info>");
+ = init_nodebug_var_type (objfile, "<data variable, no debug info>");
objfile_type->nodebug_unknown_symbol
- = init_integer_type (objfile, TARGET_CHAR_BIT, 0,
- "<variable (not text or data), no debug info>");
+ = init_nodebug_var_type (objfile, "<variable (not text or data), no debug info>");
objfile_type->nodebug_tls_symbol
- = init_integer_type (objfile, gdbarch_int_bit (gdbarch), 0,
- "<thread local variable, no debug info>");
+ = init_nodebug_var_type (objfile, "<thread local variable, no debug info>");
/* NOTE: on some targets, addresses and pointers are not necessarily
the same.
return objfile_type;
}
-extern initialize_file_ftype _initialize_gdbtypes;
-
void
_initialize_gdbtypes (void)
{