#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};
const struct rank BOOL_CONVERSION_BADNESS = {3,0};
const struct rank BASE_CONVERSION_BADNESS = {2,0};
const struct rank REFERENCE_CONVERSION_BADNESS = {2,0};
-const struct rank LVALUE_REFERENCE_TO_RVALUE_BINDING_BADNESS = {5,0};
-const struct rank DIFFERENT_REFERENCE_TYPE_BADNESS = {6,0};
const struct rank NULL_POINTER_CONVERSION_BADNESS = {2,0};
const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0};
const struct rank NS_INTEGER_POINTER_CONVERSION_BADNESS = {3,0};
gdb_assert (nparams == 0);
TYPE_PROTOTYPED (fn) = 1;
}
+ else
+ TYPE_PROTOTYPED (fn) = 1;
}
TYPE_NFIELDS (fn) = nparams;
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 (floatformats != NULL);
- gdb_assert (floatformats[0] != NULL && floatformats[1] != NULL);
+ gdb_assert (floatformat != NULL);
if (bit == -1)
- bit = floatformats[0]->totalsize;
- gdb_assert (bit >= 0);
+ bit = floatformat->totalsize;
- size_t len = bit / TARGET_CHAR_BIT;
- gdb_assert (len >= floatformat_totalsize_bytes (floatformats[0]));
- gdb_assert (len >= floatformat_totalsize_bytes (floatformats[1]));
+ gdb_assert (bit >= 0);
+ gdb_assert (bit >= floatformat->totalsize);
return bit;
}
+/* Return the floating-point format for a floating-point variable of
+ type TYPE. */
+
+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.
If NAME is non-NULL, then it is used to initialize the type name.
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;
return type;
}
+/* Allocate a TYPE_CODE_ERROR type structure associated with OBJFILE,
+ to use with variables that have no debug info. NAME is the type
+ name. */
+
+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.
BIT is the type size in bits. If UNSIGNED_P is non-zero, set
the type's TYPE_UNSIGNED flag. NAME is the type name. */
{
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
if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
arg = check_typedef (arg);
- if (value != NULL)
+ if (TYPE_IS_REFERENCE (parm) && value != NULL)
{
- /* An rvalue argument cannot be bound to a non-const lvalue
- reference parameter... */
- if (VALUE_LVAL (value) == not_lval
- && TYPE_CODE (parm) == TYPE_CODE_REF
- && !TYPE_CONST (parm->main_type->target_type))
- return INCOMPATIBLE_TYPE_BADNESS;
-
- /* ... and an lvalue argument cannot be bound to an rvalue
- reference parameter. [C++ 13.3.3.1.4p3] */
- if (VALUE_LVAL (value) != not_lval
- && TYPE_CODE (parm) == TYPE_CODE_RVALUE_REF)
- return INCOMPATIBLE_TYPE_BADNESS;
+ 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))
- return EXACT_MATCH_BADNESS;
-
- /* An lvalue reference to a function should get higher priority than an
- rvalue reference to a function. */
-
- if (value != NULL && TYPE_CODE (arg) == TYPE_CODE_RVALUE_REF
- && TYPE_CODE (TYPE_TARGET_TYPE (arg)) == TYPE_CODE_FUNC)
{
- return (sum_ranks (rank_one_type (parm,
- lookup_pointer_type (TYPE_TARGET_TYPE (arg)), NULL),
- DIFFERENT_REFERENCE_TYPE_BADNESS));
- }
+ struct type *t1 = parm;
+ struct type *t2 = arg;
- /* If a conversion to one type of reference is an identity conversion, and a
- conversion to the second type of reference is a non-identity conversion,
- choose the first type. */
-
- if (value != NULL && TYPE_IS_REFERENCE (parm) && TYPE_IS_REFERENCE (arg)
- && TYPE_CODE (parm) != TYPE_CODE (arg))
- {
- return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm),
- TYPE_TARGET_TYPE (arg), NULL), DIFFERENT_REFERENCE_TYPE_BADNESS));
- }
-
- /* An rvalue should be first tried to bind to an rvalue reference, and then to
- an lvalue reference. */
+ /* 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);
+ }
- if (value != NULL && TYPE_CODE (parm) == TYPE_CODE_REF
- && VALUE_LVAL (value) == not_lval)
- {
- if (TYPE_IS_REFERENCE (arg))
- arg = TYPE_TARGET_TYPE (arg);
- return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL),
- LVALUE_REFERENCE_TO_RVALUE_BINDING_BADNESS));
+ /* 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
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;
{
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");
= 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. */
/* 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");
/* 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)
{