mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 23:23:09 +00:00
I think that the CHECK_TYPEDEF macro is not necessary, and even a bit
annoying. It makes unclear the fact that the "type" variables gets
overwritten. It has actually bitten me a few times. I think the
following, explicit form, is better.
type = check_typedef (type);
This patches changes all instances of CHECK_TYPEDEF for an equivalent
call to check_typedef. The bulk of the change was done with this sed:
sed -i 's/CHECK_TYPEDEF (\([^)]*\));/\1 = check_typedef (\1);/' <file>.c
The ChangeLog was generated using David Malcom's generate_changelog.py.
I manually fixed those places where it gets the wrong function name,
hopefully all of them.
The patch was built-tested, and I ran a few smoke tests.
gdb/ChangeLog:
* gdbtypes.h (CHECK_TYPEDEF): Remove.
* aarch64-tdep.c (aarch64_return_in_memory): Replace CHECK_TYPEDEF
with check_typedef.
* ada-lang.c (decode_constrained_packed_array_type): Likewise.
(ada_array_length): Likewise.
(find_parallel_type_by_descriptive_type): Likewise.
(ada_check_typedef): Likewise.
* arm-tdep.c (arm_return_in_memory): Likewise.
* ax-gdb.c (gen_trace_static_fields): Likewise.
(gen_struct_ref_recursive): Likewise.
* c-exp.y (exp : SIZEOF '(' type ')' %prec UNARY): Likewise.
(variable: block COLONCOLON name): Likewise.
(qualified_name: TYPENAME COLONCOLON name): Likewise.
* c-lang.c (classify_type): Likewise.
* c-typeprint.c (c_print_type): Likewise.
(c_print_typedef): Likewise.
(c_type_print_base): Likewise.
* c-valprint.c (c_val_print): Likewise.
* compile/compile-c-types.c (convert_type): Likewise.
* compile/compile-object-load.c (get_out_value_type): Likewise.
* completer.c (add_struct_fields): Likewise.
(expression_completer): Likewise.
* cp-namespace.c (cp_find_type_baseclass_by_name): Likewise.
(cp_lookup_nested_symbol_1): Likewise.
(cp_lookup_nested_symbol): Likewise.
* cp-valprint.c (cp_print_value_fields): Likewise.
(cp_print_static_field): Likewise.
* d-valprint.c (d_val_print): Likewise.
* eval.c (evaluate_subexp_standard): Likewise.
(evaluate_subexp_for_sizeof): Likewise.
* f-exp.y (exp : SIZEOF '(' type ')' %prec UNARY): Likewise.
* f-typeprint.c (f_type_print_base): Likewise.
* f-valprint.c (f_val_print): Likewise.
* gdbtypes.c (get_discrete_bounds): Likewise.
(create_array_type_with_stride): Likewise.
(type_name_no_tag_or_error): Likewise.
(lookup_struct_elt_type): Likewise.
(get_unsigned_type_max): Likewise.
(internal_type_vptr_fieldno): Likewise.
(set_type_vptr_fieldno): Likewise.
(internal_type_vptr_basetype): Likewise.
(set_type_vptr_basetype): Likewise.
(get_vptr_fieldno): Likewise.
(is_integral_type): Likewise.
(is_scalar_type): Likewise.
(is_scalar_type_recursive): Likewise.
(distance_to_ancestor): Likewise.
(is_unique_ancestor_worker): Likewise.
(check_types_equal): Likewise.
* gnu-v2-abi.c (gnuv2_value_rtti_type): Likewise.
* gnu-v3-abi.c (gnuv3_dynamic_class): Likewise.
(gnuv3_get_vtable): Likewise.
(gnuv3_pass_by_reference): Likewise.
* go-exp.y (exp : SIZEOF_KEYWORD '(' type ')' %prec UNARY): Likewise.
* go-lang.c (gccgo_string_p): Likewise.
(go_classify_struct_type): Likewise.
* go-typeprint.c (go_print_type): Likewise.
* go-valprint.c (go_val_print): Likewise.
* guile/scm-math.c (vlscm_binop): Likewise.
* guile/scm-value.c (gdbscm_value_dynamic_type): Likewise.
(gdbscm_value_to_bytevector): Likewise.
(gdbscm_value_to_bool): Likewise.
(gdbscm_value_to_integer): Likewise.
(gdbscm_value_to_real): Likewise.
* infcall.c (call_function_by_hand_dummy): Likewise.
* infcmd.c (get_return_value): Likewise.
* jv-lang.c (is_object_type): Likewise.
* jv-typeprint.c (java_type_print_base): Likewise.
* jv-valprint.c (java_print_value_fields): Likewise.
(java_val_print): Likewise.
* linespec.c (find_methods): Likewise.
(collect_one_symbol): Likewise.
* m2-typeprint.c (m2_print_type): Likewise.
(m2_print_typedef): Likewise.
(m2_get_discrete_bounds): Likewise.
* m2-valprint.c (m2_print_long_set): Likewise.
(m2_print_unbounded_array): Likewise.
(m2_print_array_contents): Likewise.
(m2_val_print): Likewise.
* opencl-lang.c (opencl_print_type): Likewise.
* p-exp.y (exp : SIZEOF '(' type ')' %prec UNARY): Likewise.
* p-typeprint.c (pascal_print_type): Likewise.
(pascal_print_typedef): Likewise.
(pascal_type_print_base): Likewise.
* p-valprint.c (pascal_val_print): Likewise.
(pascal_object_print_value_fields): Likewise.
(pascal_object_print_static_field): Likewise.
* python/py-type.c (typy_fields_items): Likewise.
(typy_get_composite): Likewise.
* python/py-value.c (valpy_get_dynamic_type): Likewise.
(valpy_binop): Likewise.
(valpy_long): Likewise.
(valpy_float): Likewise.
* stack.c (return_command): Likewise.
* symtab.c (check_field): Likewise.
(lookup_symbol_aux): Likewise.
* tic6x-tdep.c (tic6x_return_value): Likewise.
* typeprint.c (print_type_scalar): Likewise.
* valarith.c (value_vector_widen): Likewise.
* valops.c (value_cast): Likewise.
(value_assign): Likewise.
(do_search_struct_field): Likewise.
(search_struct_method): Likewise.
(find_method_list): Likewise.
* valprint.c (val_print_scalar_type_p): Likewise.
(valprint_check_validity): Likewise.
(generic_val_print): Likewise.
* value.c (unpack_double): Likewise.
(value_primitive_field): Likewise.
(unpack_bits_as_long): Likewise.
438 lines
12 KiB
C
438 lines
12 KiB
C
/* Convert types from GDB to GCC
|
||
|
||
Copyright (C) 2014-2015 Free Software Foundation, Inc.
|
||
|
||
This file is part of GDB.
|
||
|
||
This program is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
|
||
|
||
#include "defs.h"
|
||
#include "gdbtypes.h"
|
||
#include "compile-internal.h"
|
||
/* An object that maps a gdb type to a gcc type. */
|
||
|
||
struct type_map_instance
|
||
{
|
||
/* The gdb type. */
|
||
|
||
struct type *type;
|
||
|
||
/* The corresponding gcc type handle. */
|
||
|
||
gcc_type gcc_type;
|
||
};
|
||
|
||
/* Hash a type_map_instance. */
|
||
|
||
static hashval_t
|
||
hash_type_map_instance (const void *p)
|
||
{
|
||
const struct type_map_instance *inst = p;
|
||
|
||
return htab_hash_pointer (inst->type);
|
||
}
|
||
|
||
/* Check two type_map_instance objects for equality. */
|
||
|
||
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;
|
||
|
||
return insta->type == instb->type;
|
||
}
|
||
|
||
|
||
|
||
/* Insert an entry into the type map associated with CONTEXT that maps
|
||
from the gdb type TYPE to the gcc type GCC_TYPE. It is ok for a
|
||
given type to be inserted more than once, provided that the exact
|
||
same association is made each time. This simplifies how type
|
||
caching works elsewhere in this file -- see how struct type caching
|
||
is handled. */
|
||
|
||
static void
|
||
insert_type (struct compile_c_instance *context, struct type *type,
|
||
gcc_type gcc_type)
|
||
{
|
||
struct type_map_instance inst, *add;
|
||
void **slot;
|
||
|
||
inst.type = type;
|
||
inst.gcc_type = gcc_type;
|
||
slot = htab_find_slot (context->type_map, &inst, INSERT);
|
||
|
||
add = *slot;
|
||
/* The type might have already been inserted in order to handle
|
||
recursive types. */
|
||
if (add != NULL && add->gcc_type != gcc_type)
|
||
error (_("Unexpected type id from GCC, check you use recent enough GCC."));
|
||
|
||
if (add == NULL)
|
||
{
|
||
add = XNEW (struct type_map_instance);
|
||
*add = inst;
|
||
*slot = add;
|
||
}
|
||
}
|
||
|
||
/* Convert a pointer type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_pointer (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
gcc_type target = convert_type (context, TYPE_TARGET_TYPE (type));
|
||
|
||
return C_CTX (context)->c_ops->build_pointer_type (C_CTX (context),
|
||
target);
|
||
}
|
||
|
||
/* Convert an array type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_array (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
gcc_type element_type;
|
||
struct type *range = TYPE_INDEX_TYPE (type);
|
||
|
||
element_type = convert_type (context, TYPE_TARGET_TYPE (type));
|
||
|
||
if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST)
|
||
return C_CTX (context)->c_ops->error (C_CTX (context),
|
||
_("array type with non-constant"
|
||
" lower bound is not supported"));
|
||
if (TYPE_LOW_BOUND (range) != 0)
|
||
return C_CTX (context)->c_ops->error (C_CTX (context),
|
||
_("cannot convert array type with "
|
||
"non-zero lower bound to C"));
|
||
|
||
if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
|
||
|| 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);
|
||
result = C_CTX (context)->c_ops->build_vla_array_type (C_CTX (context),
|
||
element_type,
|
||
upper_bound);
|
||
xfree (upper_bound);
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
LONGEST low_bound, high_bound, count;
|
||
|
||
if (get_array_bounds (type, &low_bound, &high_bound) == 0)
|
||
count = -1;
|
||
else
|
||
{
|
||
gdb_assert (low_bound == 0); /* Ensured above. */
|
||
count = high_bound + 1;
|
||
}
|
||
|
||
if (TYPE_VECTOR (type))
|
||
return C_CTX (context)->c_ops->build_vector_type (C_CTX (context),
|
||
element_type,
|
||
count);
|
||
return C_CTX (context)->c_ops->build_array_type (C_CTX (context),
|
||
element_type, count);
|
||
}
|
||
}
|
||
|
||
/* Convert a struct or union type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_struct_or_union (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
int i;
|
||
gcc_type result;
|
||
|
||
/* First we create the resulting type and enter it into our hash
|
||
table. This lets recursive types work. */
|
||
if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
|
||
result = C_CTX (context)->c_ops->build_record_type (C_CTX (context));
|
||
else
|
||
{
|
||
gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
|
||
result = C_CTX (context)->c_ops->build_union_type (C_CTX (context));
|
||
}
|
||
insert_type (context, type, result);
|
||
|
||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||
{
|
||
gcc_type field_type;
|
||
unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i);
|
||
|
||
field_type = convert_type (context, TYPE_FIELD_TYPE (type, i));
|
||
if (bitsize == 0)
|
||
bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
|
||
C_CTX (context)->c_ops->build_add_field (C_CTX (context), result,
|
||
TYPE_FIELD_NAME (type, i),
|
||
field_type,
|
||
bitsize,
|
||
TYPE_FIELD_BITPOS (type, i));
|
||
}
|
||
|
||
C_CTX (context)->c_ops->finish_record_or_union (C_CTX (context), result,
|
||
TYPE_LENGTH (type));
|
||
return result;
|
||
}
|
||
|
||
/* Convert an enum type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_enum (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
gcc_type int_type, result;
|
||
int i;
|
||
struct gcc_c_context *ctx = C_CTX (context);
|
||
|
||
int_type = ctx->c_ops->int_type (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)
|
||
{
|
||
ctx->c_ops->build_add_enum_constant (ctx,
|
||
result,
|
||
TYPE_FIELD_NAME (type, i),
|
||
TYPE_FIELD_ENUMVAL (type, i));
|
||
}
|
||
|
||
ctx->c_ops->finish_enum_type (ctx, result);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* Convert a function type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_func (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
int i;
|
||
gcc_type result, return_type;
|
||
struct gcc_type_array array;
|
||
int is_varargs = TYPE_VARARGS (type) || !TYPE_PROTOTYPED (type);
|
||
|
||
/* 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));
|
||
|
||
array.n_elements = TYPE_NFIELDS (type);
|
||
array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type));
|
||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||
array.elements[i] = convert_type (context, TYPE_FIELD_TYPE (type, i));
|
||
|
||
result = C_CTX (context)->c_ops->build_function_type (C_CTX (context),
|
||
return_type,
|
||
&array, is_varargs);
|
||
xfree (array.elements);
|
||
|
||
return result;
|
||
}
|
||
|
||
/* Convert an integer type to its gcc representation. */
|
||
|
||
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));
|
||
}
|
||
|
||
/* 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));
|
||
}
|
||
|
||
/* Convert the 'void' type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_void (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
return C_CTX (context)->c_ops->void_type (C_CTX (context));
|
||
}
|
||
|
||
/* Convert a boolean type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_bool (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
return C_CTX (context)->c_ops->bool_type (C_CTX (context));
|
||
}
|
||
|
||
/* Convert a qualified type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_qualified (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
struct type *unqual = make_unqualified_type (type);
|
||
gcc_type unqual_converted;
|
||
int quals = 0;
|
||
|
||
unqual_converted = convert_type (context, unqual);
|
||
|
||
if (TYPE_CONST (type))
|
||
quals |= GCC_QUALIFIER_CONST;
|
||
if (TYPE_VOLATILE (type))
|
||
quals |= GCC_QUALIFIER_VOLATILE;
|
||
if (TYPE_RESTRICT (type))
|
||
quals |= GCC_QUALIFIER_RESTRICT;
|
||
|
||
return C_CTX (context)->c_ops->build_qualified_type (C_CTX (context),
|
||
unqual_converted,
|
||
quals);
|
||
}
|
||
|
||
/* Convert a complex type to its gcc representation. */
|
||
|
||
static gcc_type
|
||
convert_complex (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
gcc_type base = convert_type (context, TYPE_TARGET_TYPE (type));
|
||
|
||
return C_CTX (context)->c_ops->build_complex_type (C_CTX (context), base);
|
||
}
|
||
|
||
/* A helper function which knows how to convert most types from their
|
||
gdb representation to the corresponding gcc form. This examines
|
||
the TYPE and dispatches to the appropriate conversion function. It
|
||
returns the gcc type. */
|
||
|
||
static gcc_type
|
||
convert_type_basic (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
/* If we are converting a qualified type, first convert the
|
||
unqualified type and then apply the qualifiers. */
|
||
if ((TYPE_INSTANCE_FLAGS (type) & (TYPE_INSTANCE_FLAG_CONST
|
||
| TYPE_INSTANCE_FLAG_VOLATILE
|
||
| TYPE_INSTANCE_FLAG_RESTRICT)) != 0)
|
||
return convert_qualified (context, type);
|
||
|
||
switch (TYPE_CODE (type))
|
||
{
|
||
case TYPE_CODE_PTR:
|
||
return convert_pointer (context, type);
|
||
|
||
case TYPE_CODE_ARRAY:
|
||
return convert_array (context, type);
|
||
|
||
case TYPE_CODE_STRUCT:
|
||
case TYPE_CODE_UNION:
|
||
return convert_struct_or_union (context, type);
|
||
|
||
case TYPE_CODE_ENUM:
|
||
return convert_enum (context, type);
|
||
|
||
case TYPE_CODE_FUNC:
|
||
return convert_func (context, type);
|
||
|
||
case TYPE_CODE_INT:
|
||
return convert_int (context, type);
|
||
|
||
case TYPE_CODE_FLT:
|
||
return convert_float (context, type);
|
||
|
||
case TYPE_CODE_VOID:
|
||
return convert_void (context, type);
|
||
|
||
case TYPE_CODE_BOOL:
|
||
return convert_bool (context, type);
|
||
|
||
case TYPE_CODE_COMPLEX:
|
||
return convert_complex (context, type);
|
||
}
|
||
|
||
return C_CTX (context)->c_ops->error (C_CTX (context),
|
||
_("cannot convert gdb type "
|
||
"to gcc type"));
|
||
}
|
||
|
||
/* See compile-internal.h. */
|
||
|
||
gcc_type
|
||
convert_type (struct compile_c_instance *context, struct type *type)
|
||
{
|
||
struct type_map_instance inst, *found;
|
||
gcc_type result;
|
||
|
||
/* We don't ever have to deal with typedefs in this code, because
|
||
those are only needed as symbols by the C compiler. */
|
||
type = check_typedef (type);
|
||
|
||
inst.type = type;
|
||
found = htab_find (context->type_map, &inst);
|
||
if (found != NULL)
|
||
return found->gcc_type;
|
||
|
||
result = convert_type_basic (context, type);
|
||
insert_type (context, type, result);
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
/* Delete the compiler instance C. */
|
||
|
||
static void
|
||
delete_instance (struct compile_instance *c)
|
||
{
|
||
struct compile_c_instance *context = (struct compile_c_instance *) c;
|
||
|
||
context->base.fe->ops->destroy (context->base.fe);
|
||
htab_delete (context->type_map);
|
||
if (context->symbol_err_map != NULL)
|
||
htab_delete (context->symbol_err_map);
|
||
xfree (context);
|
||
}
|
||
|
||
/* See compile-internal.h. */
|
||
|
||
struct compile_instance *
|
||
new_compile_instance (struct gcc_c_context *fe)
|
||
{
|
||
struct compile_c_instance *result = XCNEW (struct compile_c_instance);
|
||
|
||
result->base.fe = &fe->base;
|
||
result->base.destroy = delete_instance;
|
||
result->base.gcc_target_options = ("-std=gnu11"
|
||
/* Otherwise the .o file may need
|
||
"_Unwind_Resume" and
|
||
"__gcc_personality_v0". */
|
||
" -fno-exceptions");
|
||
|
||
result->type_map = htab_create_alloc (10, hash_type_map_instance,
|
||
eq_type_map_instance,
|
||
xfree, xcalloc, xfree);
|
||
|
||
fe->c_ops->set_callbacks (fe, gcc_convert_symbol,
|
||
gcc_symbol_address, result);
|
||
|
||
return &result->base;
|
||
}
|