/* Convert types from GDB to GCC
- Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ Copyright (C) 2014-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "gdbtypes.h"
#include "compile-internal.h"
+#include "objfiles.h"
+
/* An object that maps a gdb type to a gcc type. */
struct type_map_instance
/* The corresponding gcc type handle. */
- gcc_type gcc_type;
+ gcc_type gcc_type_handle;
};
/* Hash a type_map_instance. */
static hashval_t
hash_type_map_instance (const void *p)
{
- const struct type_map_instance *inst = p;
+ const struct type_map_instance *inst = (const struct type_map_instance *) p;
return htab_hash_pointer (inst->type);
}
static int
eq_type_map_instance (const void *a, const void *b)
{
- const struct type_map_instance *insta = a;
- const struct type_map_instance *instb = b;
+ const struct type_map_instance *insta = (const struct type_map_instance *) a;
+ const struct type_map_instance *instb = (const struct type_map_instance *) b;
return insta->type == instb->type;
}
void **slot;
inst.type = type;
- inst.gcc_type = gcc_type;
+ inst.gcc_type_handle = gcc_type;
slot = htab_find_slot (context->type_map, &inst, INSERT);
- add = *slot;
+ add = (struct type_map_instance *) *slot;
/* The type might have already been inserted in order to handle
recursive types. */
- if (add != NULL && add->gcc_type != gcc_type)
+ if (add != NULL && add->gcc_type_handle != gcc_type)
error (_("Unexpected type id from GCC, check you use recent enough GCC."));
if (add == NULL)
|| TYPE_HIGH_BOUND_KIND (range) == PROP_LOCLIST)
{
gcc_type result;
- char *upper_bound;
if (TYPE_VECTOR (type))
return C_CTX (context)->c_ops->error (C_CTX (context),
_("variably-sized vector type"
" is not supported"));
- upper_bound = c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high);
+ std::string upper_bound
+ = c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high);
result = C_CTX (context)->c_ops->build_vla_array_type (C_CTX (context),
element_type,
- upper_bound);
- xfree (upper_bound);
+ upper_bound.c_str ());
return result;
}
else
int i;
struct gcc_c_context *ctx = C_CTX (context);
- int_type = ctx->c_ops->int_type (ctx,
- TYPE_UNSIGNED (type),
- TYPE_LENGTH (type));
+ int_type = ctx->c_ops->int_type_v0 (ctx,
+ TYPE_UNSIGNED (type),
+ TYPE_LENGTH (type));
result = ctx->c_ops->build_enum_type (ctx, int_type);
for (i = 0; i < TYPE_NFIELDS (type); ++i)
struct gcc_type_array array;
int is_varargs = TYPE_VARARGS (type) || !TYPE_PROTOTYPED (type);
+ struct type *target_type = TYPE_TARGET_TYPE (type);
+
+ /* Functions with no debug info have no return type. Ideally we'd
+ want to fallback to the type of the cast just before the
+ function, like GDB's built-in expression parser, but we don't
+ have access to that type here. For now, fallback to int, like
+ GDB's parser used to do. */
+ if (target_type == NULL)
+ {
+ if (TYPE_OBJFILE_OWNED (type))
+ target_type = objfile_type (TYPE_OWNER (type).objfile)->builtin_int;
+ else
+ target_type = builtin_type (TYPE_OWNER (type).gdbarch)->builtin_int;
+ warning (_("function has unknown return type; assuming int"));
+ }
+
/* This approach means we can't make self-referential function
types. Those are impossible in C, though. */
- return_type = convert_type (context, TYPE_TARGET_TYPE (type));
+ return_type = convert_type (context, target_type);
array.n_elements = TYPE_NFIELDS (type);
array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type));
static gcc_type
convert_int (struct compile_c_instance *context, struct type *type)
{
- return C_CTX (context)->c_ops->int_type (C_CTX (context),
- TYPE_UNSIGNED (type),
- TYPE_LENGTH (type));
+ if (C_CTX (context)->c_ops->c_version >= GCC_C_FE_VERSION_1)
+ {
+ if (TYPE_NOSIGN (type))
+ {
+ gdb_assert (TYPE_LENGTH (type) == 1);
+ return C_CTX (context)->c_ops->char_type (C_CTX (context));
+ }
+ return C_CTX (context)->c_ops->int_type (C_CTX (context),
+ TYPE_UNSIGNED (type),
+ TYPE_LENGTH (type),
+ TYPE_NAME (type));
+ }
+ else
+ return C_CTX (context)->c_ops->int_type_v0 (C_CTX (context),
+ TYPE_UNSIGNED (type),
+ TYPE_LENGTH (type));
}
/* Convert a floating-point type to its gcc representation. */
static gcc_type
convert_float (struct compile_c_instance *context, struct type *type)
{
- return C_CTX (context)->c_ops->float_type (C_CTX (context),
- TYPE_LENGTH (type));
+ if (C_CTX (context)->c_ops->c_version >= GCC_C_FE_VERSION_1)
+ return C_CTX (context)->c_ops->float_type (C_CTX (context),
+ TYPE_LENGTH (type),
+ TYPE_NAME (type));
+ else
+ return C_CTX (context)->c_ops->float_type_v0 (C_CTX (context),
+ TYPE_LENGTH (type));
}
/* Convert the 'void' type to its gcc representation. */
{
struct type *unqual = make_unqualified_type (type);
gcc_type unqual_converted;
- int quals = 0;
+ gcc_qualifiers_flags quals = 0;
unqual_converted = convert_type (context, unqual);
case TYPE_CODE_COMPLEX:
return convert_complex (context, type);
+
+ case TYPE_CODE_ERROR:
+ {
+ /* Ideally, if we get here due to a cast expression, we'd use
+ the cast-to type as the variable's type, like GDB's
+ built-in parser does. For now, assume "int" like GDB's
+ built-in parser used to do, but at least warn. */
+ struct type *fallback;
+ if (TYPE_OBJFILE_OWNED (type))
+ fallback = objfile_type (TYPE_OWNER (type).objfile)->builtin_int;
+ else
+ fallback = builtin_type (TYPE_OWNER (type).gdbarch)->builtin_int;
+ warning (_("variable has unknown type; assuming int"));
+ return convert_int (context, fallback);
+ }
}
return C_CTX (context)->c_ops->error (C_CTX (context),
/* We don't ever have to deal with typedefs in this code, because
those are only needed as symbols by the C compiler. */
- CHECK_TYPEDEF (type);
+ type = check_typedef (type);
inst.type = type;
- found = htab_find (context->type_map, &inst);
+ found = (struct type_map_instance *) htab_find (context->type_map, &inst);
if (found != NULL)
- return found->gcc_type;
+ return found->gcc_type_handle;
result = convert_type_basic (context, type);
insert_type (context, type, result);