diff --git a/gdb-6.8-bz377541-vla.patch b/gdb-6.8-bz377541-vla.patch new file mode 100644 index 0000000..9b3e886 --- /dev/null +++ b/gdb-6.8-bz377541-vla.patch @@ -0,0 +1,5062 @@ +diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c +index a6d5757..5c44b52 100644 +--- a/gdb/ada-lang.c ++++ b/gdb/ada-lang.c +@@ -1666,8 +1666,8 @@ ada_type_of_array (struct value *arr, int bounds) + return NULL; + while (arity > 0) + { +- struct type *range_type = alloc_type (objf); +- struct type *array_type = alloc_type (objf); ++ struct type *range_type = alloc_type (objf, NULL); ++ struct type *array_type = alloc_type (objf, NULL); + struct value *low = desc_one_bound (descriptor, arity, 0); + struct value *high = desc_one_bound (descriptor, arity, 1); + arity -= 1; +@@ -1774,9 +1774,9 @@ packed_array_type (struct type *type, long *elt_bits) + if (TYPE_CODE (type) != TYPE_CODE_ARRAY) + return type; + +- new_type = alloc_type (TYPE_OBJFILE (type)); + new_elt_type = packed_array_type (ada_check_typedef (TYPE_TARGET_TYPE (type)), + elt_bits); ++ new_type = alloc_type (TYPE_OBJFILE (type), new_elt_type); + create_array_type (new_type, new_elt_type, TYPE_INDEX_TYPE (type)); + TYPE_FIELD_BITSIZE (new_type, 0) = *elt_bits; + TYPE_NAME (new_type) = ada_type_name (type); +@@ -6790,7 +6790,7 @@ variant_field_index (struct type *type) + static struct type * + empty_record (struct objfile *objfile) + { +- struct type *type = alloc_type (objfile); ++ struct type *type = alloc_type (objfile, NULL); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + TYPE_NFIELDS (type) = 0; + TYPE_FIELDS (type) = NULL; +@@ -6847,7 +6847,7 @@ ada_template_to_fixed_record_type_1 (struct type *type, + nfields++; + } + +- rtype = alloc_type (TYPE_OBJFILE (type)); ++ rtype = alloc_type (TYPE_OBJFILE (type), NULL); + TYPE_CODE (rtype) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (rtype); + TYPE_NFIELDS (rtype) = nfields; +@@ -7034,7 +7034,8 @@ template_to_static_fixed_type (struct type *type0) + new_type = static_unwrap_type (field_type); + if (type == type0 && new_type != field_type) + { +- TYPE_TARGET_TYPE (type0) = type = alloc_type (TYPE_OBJFILE (type0)); ++ TYPE_TARGET_TYPE (type0) = type = alloc_type (TYPE_OBJFILE (type0), ++ NULL); + TYPE_CODE (type) = TYPE_CODE (type0); + INIT_CPLUS_SPECIFIC (type); + TYPE_NFIELDS (type) = nfields; +@@ -7079,7 +7080,7 @@ to_record_with_fixed_variant_part (struct type *type, const gdb_byte *valaddr, + else + dval = dval0; + +- rtype = alloc_type (TYPE_OBJFILE (type)); ++ rtype = alloc_type (TYPE_OBJFILE (type), NULL); + TYPE_CODE (rtype) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (rtype); + TYPE_NFIELDS (rtype) = nfields; +@@ -7251,7 +7252,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, + if (elt_type0 == elt_type) + result = type0; + else +- result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), ++ result = create_array_type (alloc_type (TYPE_OBJFILE (type0), NULL), + elt_type, TYPE_INDEX_TYPE (type0)); + } + else +@@ -7281,7 +7282,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, + struct type *range_type = + to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i), + dval, TYPE_OBJFILE (type0)); +- result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), ++ result = create_array_type (alloc_type (TYPE_OBJFILE (type0), NULL), + result, range_type); + } + if (!ignore_too_big && TYPE_LENGTH (result) > varsize_limit) +@@ -9546,7 +9547,7 @@ to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile) + if (L < INT_MIN || U > INT_MAX) + return raw_type; + else +- return create_range_type (alloc_type (objfile), raw_type, ++ return create_range_type (alloc_type (objfile, NULL), raw_type, + discrete_type_low_bound (raw_type), + discrete_type_high_bound (raw_type)); + } +@@ -9611,7 +9612,7 @@ to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile) + + if (objfile == NULL) + objfile = TYPE_OBJFILE (base_type); +- type = create_range_type (alloc_type (objfile), base_type, L, U); ++ type = create_range_type (alloc_type (objfile, NULL), base_type, L, U); + TYPE_NAME (type) = name; + return type; + } +diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c +index 0929516..2aaf9ad 100644 +--- a/gdb/c-typeprint.c ++++ b/gdb/c-typeprint.c +@@ -559,7 +559,12 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, + fprintf_filtered (stream, ")"); + + fprintf_filtered (stream, "["); +- if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 ++ if (TYPE_ARRAY_BOUND_IS_DWARF_BLOCK (type, 1)) ++ { ++ /* No _() - printed sources should not be locale dependent. */ ++ fprintf_filtered (stream, "variable"); ++ } ++ else if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 + && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) + fprintf_filtered (stream, "%d", + (TYPE_LENGTH (type) +diff --git a/gdb/coffread.c b/gdb/coffread.c +index 6059d68..6a24c2c 100644 +--- a/gdb/coffread.c ++++ b/gdb/coffread.c +@@ -346,7 +346,7 @@ coff_alloc_type (int index) + We will fill it in later if we find out how. */ + if (type == NULL) + { +- type = alloc_type (current_objfile); ++ type = alloc_type (current_objfile, NULL); + *type_addr = type; + } + return type; +diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c +index 75a4ec7..aa8ab33 100644 +--- a/gdb/dwarf2expr.c ++++ b/gdb/dwarf2expr.c +@@ -752,6 +752,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, + ctx->initialized = 0; + goto no_push; + ++ case DW_OP_push_object_address: ++ if (ctx->get_object_address == NULL) ++ error (_("DWARF-2 expression error: DW_OP_push_object_address must " ++ "have a value to push.")); ++ result = (ctx->get_object_address) (ctx->baton); ++ break; ++ + default: + error (_("Unhandled dwarf expression opcode 0x%x"), op); + } +diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h +index 7047922..a287b6f 100644 +--- a/gdb/dwarf2expr.h ++++ b/gdb/dwarf2expr.h +@@ -67,10 +67,10 @@ struct dwarf_expr_context + The result must be live until the current expression evaluation + is complete. */ + unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length); ++#endif + + /* Return the `object address' for DW_OP_push_object_address. */ + CORE_ADDR (*get_object_address) (void *baton); +-#endif + + /* The current depth of dwarf expression recursion, via DW_OP_call*, + DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum +diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c +index cad3db8..65751a4 100644 +--- a/gdb/dwarf2loc.c ++++ b/gdb/dwarf2loc.c +@@ -107,6 +107,9 @@ struct dwarf_expr_baton + { + struct frame_info *frame; + struct objfile *objfile; ++ /* From DW_TAG_variable's DW_AT_location (not DW_TAG_type's ++ DW_AT_data_location) for DW_OP_push_object_address. */ ++ CORE_ADDR object_address; + }; + + /* Helper functions for dwarf2_evaluate_loc_desc. */ +@@ -163,22 +166,32 @@ dwarf_expr_frame_base (void *baton, gdb_byte **start, size_t * length) + *start = find_location_expression (symbaton, length, + get_frame_address_in_block (frame)); + } +- else ++ else if (SYMBOL_OPS (framefunc) == &dwarf2_locexpr_funcs) + { + struct dwarf2_locexpr_baton *symbaton; ++ + symbaton = SYMBOL_LOCATION_BATON (framefunc); +- if (symbaton != NULL) +- { +- *length = symbaton->size; +- *start = symbaton->data; +- } +- else +- *start = NULL; ++ gdb_assert (symbaton != NULL); ++ *start = symbaton->data; ++ *length = symbaton->size; ++ } ++ else if (SYMBOL_OPS (framefunc) == &dwarf2_missing_funcs) ++ { ++ struct dwarf2_locexpr_baton *symbaton; ++ ++ symbaton = SYMBOL_LOCATION_BATON (framefunc); ++ gdb_assert (symbaton == NULL); ++ *start = NULL; ++ *length = 0; /* unused */ + } ++ else ++ internal_error (__FILE__, __LINE__, ++ _("Unsupported SYMBOL_OPS %p for \"%s\""), ++ SYMBOL_OPS (framefunc), SYMBOL_PRINT_NAME (framefunc)); + + if (*start == NULL) + error (_("Could not find the frame base for \"%s\"."), +- SYMBOL_NATURAL_NAME (framefunc)); ++ SYMBOL_PRINT_NAME (framefunc)); + } + + /* Using the objfile specified in BATON, find the address for the +@@ -191,6 +204,119 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset) + return target_translate_tls_address (debaton->objfile, offset); + } + ++static CORE_ADDR ++dwarf_expr_object_address (void *baton) ++{ ++ struct dwarf_expr_baton *debaton = baton; ++ ++ /* The message is suppressed in DWARF_BLOCK_EXEC. */ ++ if (debaton->object_address == 0) ++ error (_("Cannot resolve DW_OP_push_object_address for a missing object")); ++ ++ return debaton->object_address; ++} ++ ++/* Address of the variable we are currently referring to. It is set from ++ DW_TAG_variable's DW_AT_location (not DW_TAG_type's DW_AT_data_location) for ++ DW_OP_push_object_address. */ ++ ++static CORE_ADDR object_address; ++ ++/* Callers use object_address_set while their callers use the result set so we ++ cannot run the cleanup at the local block of our direct caller. Still we ++ should reset OBJECT_ADDRESS at least for the next GDB command. */ ++ ++static void ++object_address_cleanup (void *prev_save_voidp) ++{ ++ CORE_ADDR *prev_save = prev_save_voidp; ++ ++ object_address = *prev_save; ++ xfree (prev_save); ++} ++ ++/* Set the base address - DW_AT_location - of a variable. It is being later ++ used to derive other object addresses by DW_OP_push_object_address. ++ ++ It would be useful to sanity check ADDRESS - such as for some objects with ++ unset VALUE_ADDRESS - but some valid addresses may be zero (such as first ++ objects in relocatable .o files). */ ++ ++void ++object_address_set (CORE_ADDR address) ++{ ++ CORE_ADDR *prev_save; ++ ++ prev_save = xmalloc (sizeof *prev_save); ++ *prev_save = object_address; ++ make_cleanup (object_address_cleanup, prev_save); ++ ++ object_address = address; ++} ++ ++/* Evaluate DWARF expression at DATA ... DATA + SIZE with its result readable ++ by dwarf_expr_fetch (RETVAL, 0). FRAME parameter can be NULL to call ++ get_selected_frame to find it. Returned dwarf_expr_context freeing is ++ pushed on the cleanup chain. */ ++ ++static struct dwarf_expr_context * ++dwarf_expr_prep_ctx (struct frame_info *frame, gdb_byte *data, ++ unsigned short size, struct dwarf2_per_cu_data *per_cu) ++{ ++ struct dwarf_expr_context *ctx; ++ struct dwarf_expr_baton baton; ++ ++ if (!frame) ++ frame = get_selected_frame (NULL); ++ ++ baton.frame = frame; ++ baton.objfile = dwarf2_per_cu_objfile (per_cu); ++ baton.object_address = object_address; ++ ++ ctx = new_dwarf_expr_context (); ++ ctx->gdbarch = get_objfile_arch (baton.objfile); ++ ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); ++ ctx->baton = &baton; ++ ctx->read_reg = dwarf_expr_read_reg; ++ ctx->read_mem = dwarf_expr_read_mem; ++ ctx->get_frame_base = dwarf_expr_frame_base; ++ ctx->get_tls_address = dwarf_expr_tls_address; ++ ctx->get_object_address = dwarf_expr_object_address; ++ ++ make_cleanup ((make_cleanup_ftype *) free_dwarf_expr_context, ctx); ++ ++ dwarf_expr_eval (ctx, data, size); ++ ++ /* It was used only during dwarf_expr_eval. */ ++ ctx->baton = NULL; ++ ++ return ctx; ++} ++ ++/* Evaluate DWARF expression at DLBATON expecting it produces exactly one ++ CORE_ADDR result on the DWARF stack stack. */ ++ ++CORE_ADDR ++dwarf_locexpr_baton_eval (struct dwarf2_locexpr_baton *dlbaton) ++{ ++ struct dwarf_expr_context *ctx; ++ CORE_ADDR retval; ++ struct cleanup *back_to = make_cleanup (null_cleanup, 0); ++ ++ ctx = dwarf_expr_prep_ctx (NULL, dlbaton->data, dlbaton->size, ++ dlbaton->per_cu); ++ if (ctx->num_pieces > 0) ++ error (_("DW_OP_*piece is unsupported for DW_FORM_block")); ++ else if (ctx->in_reg) ++ error (_("Register result is unsupported for DW_FORM_block")); ++ ++ retval = dwarf_expr_fetch (ctx, 0); ++ ++ do_cleanups (back_to); ++ ++ return retval; ++} ++ + /* Evaluate a location description, starting at DATA and with length + SIZE, to find the current location of variable VAR in the context + of FRAME. */ +@@ -200,8 +326,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + struct dwarf2_per_cu_data *per_cu) + { + struct value *retval; +- struct dwarf_expr_baton baton; + struct dwarf_expr_context *ctx; ++ struct cleanup *back_to = make_cleanup (null_cleanup, 0); + + if (size == 0) + { +@@ -211,19 +337,8 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + return retval; + } + +- baton.frame = frame; +- baton.objfile = dwarf2_per_cu_objfile (per_cu); ++ ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu); + +- ctx = new_dwarf_expr_context (); +- ctx->gdbarch = get_objfile_arch (baton.objfile); +- ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); +- ctx->baton = &baton; +- ctx->read_reg = dwarf_expr_read_reg; +- ctx->read_mem = dwarf_expr_read_mem; +- ctx->get_frame_base = dwarf_expr_frame_base; +- ctx->get_tls_address = dwarf_expr_tls_address; +- +- dwarf_expr_eval (ctx, data, size); + if (ctx->num_pieces > 0) + { + int i; +@@ -261,6 +376,10 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + { + CORE_ADDR address = dwarf_expr_fetch (ctx, 0); + ++ /* object_address_set called here is required in ALLOCATE_VALUE's ++ CHECK_TYPEDEF for the object's possible DW_OP_push_object_address. */ ++ object_address_set (address); ++ + retval = allocate_value (SYMBOL_TYPE (var)); + VALUE_LVAL (retval) = lval_memory; + set_value_lazy (retval, 1); +@@ -269,7 +388,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, + + set_value_initialized (retval, ctx->initialized); + +- free_dwarf_expr_context (ctx); ++ do_cleanups (back_to); + + return retval; + } +@@ -587,7 +706,7 @@ static int + loclist_describe_location (struct symbol *symbol, struct ui_file *stream) + { + /* FIXME: Could print the entire list of locations. */ +- fprintf_filtered (stream, "a variable with multiple locations"); ++ fprintf_filtered (stream, _("a variable with multiple locations")); + return 1; + } + +@@ -603,16 +722,56 @@ loclist_tracepoint_var_ref (struct symbol * symbol, struct agent_expr * ax, + + data = find_location_expression (dlbaton, &size, ax->scope); + if (data == NULL) +- error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol)); ++ error (_("Variable \"%s\" is not available."), SYMBOL_PRINT_NAME (symbol)); + + dwarf2_tracepoint_var_ref (symbol, ax, value, data, size); + } + +-/* The set of location functions used with the DWARF-2 expression +- evaluator and location lists. */ ++/* The set of location functions used with the DWARF-2 location lists. */ + const struct symbol_ops dwarf2_loclist_funcs = { + loclist_read_variable, + loclist_read_needs_frame, + loclist_describe_location, + loclist_tracepoint_var_ref + }; ++ ++static struct value * ++missing_read_variable (struct symbol *symbol, struct frame_info *frame) ++{ ++ struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); ++ ++ gdb_assert (dlbaton == NULL); ++ error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol)); ++} ++ ++static int ++missing_read_needs_frame (struct symbol *symbol) ++{ ++ return 0; ++} ++ ++static int ++missing_describe_location (struct symbol *symbol, struct ui_file *stream) ++{ ++ fprintf_filtered (stream, _("a variable we are unable to resolve")); ++ return 1; ++} ++ ++static void ++missing_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax, ++ struct axs_value *value) ++{ ++ struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); ++ ++ gdb_assert (dlbaton == NULL); ++ error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol)); ++} ++ ++/* The set of location functions used with the DWARF-2 evaluator when we are ++ unable to resolve the symbols. */ ++const struct symbol_ops dwarf2_missing_funcs = { ++ missing_read_variable, ++ missing_read_needs_frame, ++ missing_describe_location, ++ missing_tracepoint_var_ref ++}; +diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h +index 76577f1..bf46761 100644 +--- a/gdb/dwarf2loc.h ++++ b/gdb/dwarf2loc.h +@@ -71,5 +71,11 @@ struct dwarf2_loclist_baton + + extern const struct symbol_ops dwarf2_locexpr_funcs; + extern const struct symbol_ops dwarf2_loclist_funcs; ++extern const struct symbol_ops dwarf2_missing_funcs; ++ ++extern void object_address_set (CORE_ADDR address); ++ ++extern CORE_ADDR dwarf_locexpr_baton_eval ++ (struct dwarf2_locexpr_baton *dlbaton); + + #endif /* dwarf2loc.h */ +diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c +index 925cfd0..481cdfc 100644 +--- a/gdb/dwarf2read.c ++++ b/gdb/dwarf2read.c +@@ -1024,7 +1024,14 @@ static void store_in_ref_table (struct die_info *, + + static unsigned int dwarf2_get_ref_die_offset (struct attribute *); + +-static int dwarf2_get_attr_constant_value (struct attribute *, int); ++enum dwarf2_get_attr_constant_value ++ { ++ dwarf2_attr_unknown, ++ dwarf2_attr_const, ++ dwarf2_attr_block ++ }; ++static enum dwarf2_get_attr_constant_value dwarf2_get_attr_constant_value ++ (struct attribute *attr, int *val_return); + + static struct die_info *follow_die_ref (struct die_info *, + struct attribute *, +@@ -1079,6 +1086,9 @@ static void age_cached_comp_units (void); + + static void free_one_cached_comp_unit (void *); + ++static void fetch_die_type_attrs (struct die_info *die, struct type *type, ++ struct dwarf2_cu *cu); ++ + static struct type *set_die_type (struct die_info *, struct type *, + struct dwarf2_cu *); + +@@ -1098,6 +1108,9 @@ static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); + + static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu); + ++static struct dwarf2_locexpr_baton *dwarf2_attr_to_locexpr_baton ++ (struct attribute *attr, struct dwarf2_cu *cu); ++ + /* Try to locate the sections we need for DWARF 2 debugging + information and return true if we have enough to do something. */ + +@@ -3900,7 +3913,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, + /* The name is already allocated along with this objfile, so we don't + need to duplicate it for the type. */ + fnp->physname = physname ? physname : ""; +- fnp->type = alloc_type (objfile); ++ fnp->type = alloc_type (objfile, NULL); + this_type = read_type_die (die, cu); + if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) + { +@@ -4084,7 +4097,7 @@ quirk_gcc_member_function_pointer (struct die_info *die, struct dwarf2_cu *cu) + return NULL; + + domain_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0)); +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + smash_to_method_type (type, domain_type, TYPE_TARGET_TYPE (pfn_type), + TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type), + TYPE_VARARGS (pfn_type)); +@@ -4121,7 +4134,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) + if (type) + return type; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + INIT_CPLUS_SPECIFIC (type); + name = dwarf2_name (die, cu); + if (name != NULL) +@@ -4334,7 +4347,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu) + struct attribute *attr; + const char *name; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + + TYPE_CODE (type) = TYPE_CODE_ENUM; + name = dwarf2_full_name (die, cu); +@@ -4484,6 +4497,29 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) + new_symbol (die, this_type, cu); + } + ++/* Create a new array dimension referencing its target type TYPE. ++ ++ Multidimensional arrays are internally represented as a stack of ++ singledimensional arrays being referenced by their TYPE_TARGET_TYPE. */ ++ ++static struct type * ++create_single_array_dimension (struct type *type, struct type *range_type, ++ struct die_info *die, struct dwarf2_cu *cu) ++{ ++ type = create_array_type (NULL, type, range_type); ++ ++ /* These generic type attributes need to be fetched by ++ evaluate_subexp_standard 's call of ++ value_subscripted_rvalue only for the innermost array type. */ ++ fetch_die_type_attrs (die, type, cu); ++ ++ /* These generic type attributes are checked for allocated/associated ++ validity while accessing FIELD_LOC_KIND_DWARF_BLOCK. */ ++ fetch_die_type_attrs (die, range_type, cu); ++ ++ return type; ++} ++ + /* Extract all information from a DW_TAG_array_type DIE and put it in + the DIE's type field. For now, this only handles one dimensional + arrays. */ +@@ -4497,7 +4533,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) + struct type *element_type, *range_type, *index_type; + struct type **range_types = NULL; + struct attribute *attr; +- int ndim = 0; ++ int ndim = 0, i; + struct cleanup *back_to; + char *name; + +@@ -4544,16 +4580,11 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) + type = element_type; + + if (read_array_order (die, cu) == DW_ORD_col_major) +- { +- int i = 0; +- while (i < ndim) +- type = create_array_type (NULL, type, range_types[i++]); +- } +- else +- { +- while (ndim-- > 0) +- type = create_array_type (NULL, type, range_types[ndim]); +- } ++ for (i = 0; i < ndim; i++) ++ type = create_single_array_dimension (type, range_types[i], die, cu); ++ else /* (read_array_order (die, cu) == DW_ORD_row_major) */ ++ for (i = ndim - 1; i >= 0; i--) ++ type = create_single_array_dimension (type, range_types[i], die, cu); + + /* Understand Dwarf2 support for vector types (like they occur on + the PowerPC w/ AltiVec). Gcc just adds another attribute to the +@@ -4909,29 +4940,95 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) + struct objfile *objfile = cu->objfile; + struct type *type, *range_type, *index_type, *char_type; + struct attribute *attr; +- unsigned int length; ++ int length; ++ ++ index_type = builtin_type_int32; ++ /* RANGE_TYPE is allocated from OBJFILE, not OBJFILE_INTERNAL. */ ++ range_type = alloc_type (objfile, index_type); ++ /* LOW_BOUND and HIGH_BOUND are set for real below. */ ++ range_type = create_range_type (range_type, index_type, 0, -1); ++ ++ /* C/C++ should probably have the low bound 0 but C/C++ does not use ++ DW_TAG_string_type. */ ++ TYPE_LOW_BOUND (range_type) = 1; + + attr = dwarf2_attr (die, DW_AT_string_length, cu); +- if (attr) +- { +- length = DW_UNSND (attr); +- } +- else +- { +- /* check for the DW_AT_byte_size attribute */ ++ switch (dwarf2_get_attr_constant_value (attr, &length)) ++ { ++ case dwarf2_attr_const: ++ /* We currently do not support a constant address where the location ++ should be read from - DWARF2_ATTR_BLOCK is expected instead. See ++ DWARF for the DW_AT_STRING_LENGTH vs. DW_AT_BYTE_SIZE difference. */ ++ /* PASSTHRU */ ++ case dwarf2_attr_unknown: + attr = dwarf2_attr (die, DW_AT_byte_size, cu); +- if (attr) +- { +- length = DW_UNSND (attr); +- } +- else +- { +- length = 1; +- } ++ switch (dwarf2_get_attr_constant_value (attr, &length)) ++ { ++ case dwarf2_attr_unknown: ++ length = 1; ++ /* PASSTHRU */ ++ case dwarf2_attr_const: ++ TYPE_HIGH_BOUND (range_type) = length; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = ++ dwarf2_attr_to_locexpr_baton (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ break; ++ } ++ break; ++ case dwarf2_attr_block: ++ /* Security check for a size overflow. */ ++ if (DW_BLOCK (attr)->size + 2 < DW_BLOCK (attr)->size) ++ { ++ TYPE_HIGH_BOUND (range_type) = 1; ++ break; ++ } ++ /* Extend the DWARF block by a new DW_OP_deref/DW_OP_deref_size ++ instruction as DW_AT_string_length specifies the length location, not ++ its value. */ ++ { ++ struct dwarf2_locexpr_baton *length_baton; ++ struct attribute *size_attr; ++ ++ length_baton = obstack_alloc (&cu->comp_unit_obstack, ++ sizeof (*length_baton)); ++ length_baton->per_cu = cu->per_cu; ++ length_baton->data = obstack_alloc (&cu->comp_unit_obstack, ++ DW_BLOCK (attr)->size + 2); ++ memcpy (length_baton->data, DW_BLOCK (attr)->data, ++ DW_BLOCK (attr)->size); ++ ++ /* DW_AT_BYTE_SIZE existing together with DW_AT_STRING_LENGTH specifies ++ the size of an integer to fetch. */ ++ ++ size_attr = dwarf2_attr (die, DW_AT_byte_size, cu); ++ if (size_attr) ++ { ++ length_baton->size = DW_BLOCK (attr)->size + 2; ++ length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref_size; ++ length_baton->data[DW_BLOCK (attr)->size + 1] ++ = DW_UNSND (size_attr); ++ if (length_baton->data[DW_BLOCK (attr)->size + 1] ++ != DW_UNSND (size_attr)) ++ complaint (&symfile_complaints, ++ _("DW_AT_string_length's DW_AT_byte_size integer " ++ "exceeds the byte size storage")); ++ } ++ else ++ { ++ length_baton->size = DW_BLOCK (attr)->size + 1; ++ length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref; ++ } ++ ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = length_baton; ++ TYPE_DYNAMIC (range_type) = 1; ++ } ++ break; + } + +- index_type = builtin_type_int32; +- range_type = create_range_type (NULL, index_type, 1, length); + type = create_string_type (NULL, range_type); + + return set_die_type (die, type, cu); +@@ -5025,7 +5122,6 @@ static struct type * + read_typedef (struct die_info *die, struct dwarf2_cu *cu) + { + struct objfile *objfile = cu->objfile; +- struct attribute *attr; + const char *name = NULL; + struct type *this_type; + +@@ -5131,8 +5227,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) + struct type *base_type; + struct type *range_type; + struct attribute *attr; +- int low = 0; +- int high = -1; ++ int low, high, byte_stride_int; ++ enum dwarf2_get_attr_constant_value high_type; + char *name; + + base_type = die_type (die, cu); +@@ -5145,42 +5241,90 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) + 0, NULL, cu->objfile); + } + +- if (cu->language == language_fortran) +- { +- /* FORTRAN implies a lower bound of 1, if not given. */ +- low = 1; +- } ++ /* LOW_BOUND and HIGH_BOUND are set for real below. */ ++ range_type = create_range_type (NULL, base_type, 0, -1); + +- /* FIXME: For variable sized arrays either of these could be +- a variable rather than a constant value. We'll allow it, +- but we don't know how to handle it. */ + attr = dwarf2_attr (die, DW_AT_lower_bound, cu); +- if (attr) +- low = dwarf2_get_attr_constant_value (attr, 0); ++ switch (dwarf2_get_attr_constant_value (attr, &low)) ++ { ++ case dwarf2_attr_unknown: ++ if (cu->language == language_fortran) ++ { ++ /* FORTRAN implies a lower bound of 1, if not given. */ ++ low = 1; ++ } ++ else ++ { ++ /* According to DWARF we should assume the value 0 only for ++ LANGUAGE_C and LANGUAGE_CPLUS. */ ++ low = 0; ++ } ++ /* PASSTHRU */ ++ case dwarf2_attr_const: ++ TYPE_LOW_BOUND (range_type) = low; ++ if (low >= 0) ++ TYPE_UNSIGNED (range_type) = 1; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 0); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 0) = dwarf2_attr_to_locexpr_baton ++ (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ /* For setting a default if DW_AT_UPPER_BOUND would be missing. */ ++ low = 0; ++ break; ++ } + + attr = dwarf2_attr (die, DW_AT_upper_bound, cu); +- if (attr) +- { +- if (attr->form == DW_FORM_block1) +- { +- /* GCC encodes arrays with unspecified or dynamic length +- with a DW_FORM_block1 attribute. +- FIXME: GDB does not yet know how to handle dynamic +- arrays properly, treat them as arrays with unspecified +- length for now. +- +- FIXME: jimb/2003-09-22: GDB does not really know +- how to handle arrays of unspecified length +- either; we just represent them as zero-length +- arrays. Choose an appropriate upper bound given +- the lower bound we've computed above. */ +- high = low - 1; +- } +- else +- high = dwarf2_get_attr_constant_value (attr, 1); ++ high_type = dwarf2_get_attr_constant_value (attr, &high); ++ if (high_type == dwarf2_attr_unknown) ++ { ++ attr = dwarf2_attr (die, DW_AT_count, cu); ++ high_type = dwarf2_get_attr_constant_value (attr, &high); ++ /* It does not hurt but it is needlessly ineffective in check_typedef. */ ++ if (high_type != dwarf2_attr_unknown) ++ { ++ TYPE_RANGE_HIGH_BOUND_IS_COUNT (range_type) = 1; ++ TYPE_DYNAMIC (range_type) = 1; ++ } ++ /* Pass it now as the regular DW_AT_upper_bound. */ ++ } ++ switch (high_type) ++ { ++ case dwarf2_attr_unknown: ++ TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type) = 1; ++ high = low - 1; ++ /* PASSTHRU */ ++ case dwarf2_attr_const: ++ TYPE_HIGH_BOUND (range_type) = high; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 1); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 1) = dwarf2_attr_to_locexpr_baton ++ (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ break; + } + +- range_type = create_range_type (NULL, base_type, low, high); ++ /* DW_AT_bit_stride is currently unsupported as we count in bytes. */ ++ attr = dwarf2_attr (die, DW_AT_byte_stride, cu); ++ switch (dwarf2_get_attr_constant_value (attr, &byte_stride_int)) ++ { ++ case dwarf2_attr_unknown: ++ break; ++ case dwarf2_attr_const: ++ if (byte_stride_int == 0) ++ complaint (&symfile_complaints, ++ _("Found DW_AT_byte_stride with unsupported value 0")); ++ TYPE_BYTE_STRIDE (range_type) = byte_stride_int; ++ break; ++ case dwarf2_attr_block: ++ TYPE_RANGE_BOUND_SET_DWARF_BLOCK (range_type, 2); ++ TYPE_FIELD_DWARF_BLOCK (range_type, 2) = dwarf2_attr_to_locexpr_baton ++ (attr, cu); ++ TYPE_DYNAMIC (range_type) = 1; ++ break; ++ } + + name = dwarf2_name (die, cu); + if (name) +@@ -7468,10 +7612,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym, + (i.e. when the value of a register or memory location is + referenced, or a thread-local block, etc.). Then again, it might + not be worthwhile. I'm assuming that it isn't unless performance +- or memory numbers show me otherwise. */ ++ or memory numbers show me otherwise. ++ ++ SYMBOL_CLASS may get overriden by dwarf2_symbol_mark_computed. */ + +- dwarf2_symbol_mark_computed (attr, sym, cu); + SYMBOL_CLASS (sym) = LOC_COMPUTED; ++ dwarf2_symbol_mark_computed (attr, sym, cu); + } + + /* Given a pointer to a DWARF information entry, figure out if we need +@@ -7504,6 +7650,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) + sizeof (struct symbol)); + OBJSTAT (objfile, n_syms++); + memset (sym, 0, sizeof (struct symbol)); ++ /* Some methods are called without checking SYMBOL_OPS validity. */ ++ SYMBOL_OPS (sym) = &dwarf2_missing_funcs; + + /* Cache this symbol's name and the name's demangled form (if any). */ + SYMBOL_LANGUAGE (sym) = cu->language; +@@ -9309,26 +9457,35 @@ dwarf2_get_ref_die_offset (struct attribute *attr) + return result; + } + +-/* Return the constant value held by the given attribute. Return -1 +- if the value held by the attribute is not constant. */ ++/* (*val_return) is filled only if returning dwarf2_attr_const. */ + +-static int +-dwarf2_get_attr_constant_value (struct attribute *attr, int default_value) ++static enum dwarf2_get_attr_constant_value ++dwarf2_get_attr_constant_value (struct attribute *attr, int *val_return) + { ++ if (attr == NULL) ++ return dwarf2_attr_unknown; + if (attr->form == DW_FORM_sdata) +- return DW_SND (attr); +- else if (attr->form == DW_FORM_udata +- || attr->form == DW_FORM_data1 +- || attr->form == DW_FORM_data2 +- || attr->form == DW_FORM_data4 +- || attr->form == DW_FORM_data8) +- return DW_UNSND (attr); +- else + { +- complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), +- dwarf_form_name (attr->form)); +- return default_value; ++ *val_return = DW_SND (attr); ++ return dwarf2_attr_const; + } ++ if (attr->form == DW_FORM_udata ++ || attr->form == DW_FORM_data1 ++ || attr->form == DW_FORM_data2 ++ || attr->form == DW_FORM_data4 ++ || attr->form == DW_FORM_data8) ++ { ++ *val_return = DW_UNSND (attr); ++ return dwarf2_attr_const; ++ } ++ if (attr->form == DW_FORM_block ++ || attr->form == DW_FORM_block1 ++ || attr->form == DW_FORM_block2 ++ || attr->form == DW_FORM_block4) ++ return dwarf2_attr_block; ++ complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), ++ dwarf_form_name (attr->form)); ++ return dwarf2_attr_unknown; + } + + /* THIS_CU has a reference to PER_CU. If necessary, load the new compilation +@@ -10106,6 +10263,34 @@ attr_form_is_constant (struct attribute *attr) + } + } + ++/* Convert DW_BLOCK into struct dwarf2_locexpr_baton. ATTR must be a DW_BLOCK ++ attribute type. */ ++ ++static struct dwarf2_locexpr_baton * ++dwarf2_attr_to_locexpr_baton (struct attribute *attr, struct dwarf2_cu *cu) ++{ ++ struct dwarf2_locexpr_baton *baton; ++ ++ gdb_assert (attr_form_is_block (attr)); ++ ++ baton = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (*baton)); ++ baton->per_cu = cu->per_cu; ++ gdb_assert (baton->per_cu); ++ ++ /* Note that we're just copying the block's data pointer ++ here, not the actual data. We're still pointing into the ++ info_buffer for SYM's objfile; right now we never release ++ that buffer, but when we do clean up properly this may ++ need to change. */ ++ baton->size = DW_BLOCK (attr)->size; ++ baton->data = DW_BLOCK (attr)->data; ++ gdb_assert (baton->size == 0 || baton->data != NULL); ++ ++ return baton; ++} ++ ++/* SYM may get its SYMBOL_CLASS overriden on invalid ATTR content. */ ++ + static void + dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + struct dwarf2_cu *cu) +@@ -10135,35 +10320,24 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, + SYMBOL_OPS (sym) = &dwarf2_loclist_funcs; + SYMBOL_LOCATION_BATON (sym) = baton; + } ++ else if (attr_form_is_block (attr)) ++ { ++ SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs; ++ SYMBOL_LOCATION_BATON (sym) = dwarf2_attr_to_locexpr_baton (attr, cu); ++ } + else + { +- struct dwarf2_locexpr_baton *baton; ++ dwarf2_invalid_attrib_class_complaint ("location description", ++ SYMBOL_NATURAL_NAME (sym)); + +- baton = obstack_alloc (&cu->objfile->objfile_obstack, +- sizeof (struct dwarf2_locexpr_baton)); +- baton->per_cu = cu->per_cu; +- gdb_assert (baton->per_cu); ++ /* Some methods are called without checking SYMBOL_OPS validity. */ ++ SYMBOL_OPS (sym) = &dwarf2_missing_funcs; ++ SYMBOL_LOCATION_BATON (sym) = NULL; + +- if (attr_form_is_block (attr)) +- { +- /* Note that we're just copying the block's data pointer +- here, not the actual data. We're still pointing into the +- info_buffer for SYM's objfile; right now we never release +- that buffer, but when we do clean up properly this may +- need to change. */ +- baton->size = DW_BLOCK (attr)->size; +- baton->data = DW_BLOCK (attr)->data; +- } +- else +- { +- dwarf2_invalid_attrib_class_complaint ("location description", +- SYMBOL_NATURAL_NAME (sym)); +- baton->size = 0; +- baton->data = NULL; +- } +- +- SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs; +- SYMBOL_LOCATION_BATON (sym) = baton; ++ /* For functions a missing DW_AT_frame_base does not optimize out the ++ whole function definition, only its frame base resolving. */ ++ if (attr->name == DW_AT_location) ++ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT; + } + } + +@@ -10438,6 +10612,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs) + return ofs_lhs->offset == ofs_rhs->offset; + } + ++/* Fill in generic attributes applicable for type DIEs. */ ++ ++static void ++fetch_die_type_attrs (struct die_info *die, struct type *type, ++ struct dwarf2_cu *cu) ++{ ++ struct attribute *attr; ++ ++ attr = dwarf2_attr (die, DW_AT_data_location, cu); ++ if (attr_form_is_block (attr)) ++ TYPE_DATA_LOCATION_DWARF_BLOCK (type) = dwarf2_attr_to_locexpr_baton (attr, ++ cu); ++ gdb_assert (!TYPE_DATA_LOCATION_IS_ADDR (type)); ++ ++ attr = dwarf2_attr (die, DW_AT_allocated, cu); ++ if (attr_form_is_block (attr)) ++ TYPE_ALLOCATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu); ++ gdb_assert (!TYPE_NOT_ALLOCATED (type)); ++ ++ attr = dwarf2_attr (die, DW_AT_associated, cu); ++ if (attr_form_is_block (attr)) ++ TYPE_ASSOCIATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu); ++ gdb_assert (!TYPE_NOT_ASSOCIATED (type)); ++} ++ + /* Set the type associated with DIE to TYPE. Save it in CU's hash + table if necessary. For convenience, return TYPE. */ + +@@ -10446,6 +10645,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) + { + struct dwarf2_offset_and_type **slot, ofs; + ++ fetch_die_type_attrs (die, type, cu); ++ + if (cu->type_hash == NULL) + { + gdb_assert (cu->per_cu != NULL); +diff --git a/gdb/eval.c b/gdb/eval.c +index 038334b..3e2c320 100644 +--- a/gdb/eval.c ++++ b/gdb/eval.c +@@ -40,6 +40,7 @@ + #include "regcache.h" + #include "user-regs.h" + #include "valprint.h" ++#include "dwarf2loc.h" + + #include "gdb_assert.h" + +@@ -671,6 +672,7 @@ evaluate_subexp_standard (struct type *expect_type, + long mem_offset; + struct type **arg_types; + int save_pos1; ++ struct cleanup *old_chain; + + pc = (*pos)++; + op = exp->elts[pc].opcode; +@@ -1529,7 +1531,10 @@ evaluate_subexp_standard (struct type *expect_type, + + /* First determine the type code we are dealing with. */ + arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); ++ old_chain = make_cleanup (null_cleanup, 0); ++ object_address_set (VALUE_ADDRESS (arg1)); + type = check_typedef (value_type (arg1)); ++ do_cleanups (old_chain); + code = TYPE_CODE (type); + + if (code == TYPE_CODE_PTR) +@@ -1963,13 +1968,19 @@ evaluate_subexp_standard (struct type *expect_type, + { + int subscript_array[MAX_FORTRAN_DIMS]; + int array_size_array[MAX_FORTRAN_DIMS]; ++ int byte_stride_array[MAX_FORTRAN_DIMS]; + int ndimensions = 1, i; + struct type *tmp_type; + int offset_item; /* The array offset where the item lives */ ++ CORE_ADDR offset_byte; /* byte_stride based offset */ ++ unsigned element_size; + + if (nargs > MAX_FORTRAN_DIMS) + error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS); + ++ old_chain = make_cleanup (null_cleanup, 0); ++ object_address_set (VALUE_ADDRESS (arg1)); ++ + tmp_type = check_typedef (value_type (arg1)); + ndimensions = calc_f77_array_dims (type); + +@@ -1999,6 +2010,9 @@ evaluate_subexp_standard (struct type *expect_type, + upper = f77_get_upperbound (tmp_type); + lower = f77_get_lowerbound (tmp_type); + ++ byte_stride_array[nargs - i - 1] = ++ TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type); ++ + array_size_array[nargs - i - 1] = upper - lower + 1; + + /* Zero-normalize subscripts so that offsetting will work. */ +@@ -2017,17 +2031,25 @@ evaluate_subexp_standard (struct type *expect_type, + tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type)); + } + +- /* Now let us calculate the offset for this item */ ++ /* Kept for the f77_get_upperbound / f77_get_lowerbound calls above. */ ++ do_cleanups (old_chain); + +- offset_item = subscript_array[ndimensions - 1]; ++ /* Now let us calculate the offset for this item */ + +- for (i = ndimensions - 1; i > 0; --i) +- offset_item = +- array_size_array[i - 1] * offset_item + subscript_array[i - 1]; ++ offset_item = 0; ++ offset_byte = 0; + +- /* Construct a value node with the value of the offset */ ++ for (i = ndimensions - 1; i >= 0; --i) ++ { ++ offset_item *= array_size_array[i]; ++ if (byte_stride_array[i] == 0) ++ offset_item += subscript_array[i]; ++ else ++ offset_byte += subscript_array[i] * byte_stride_array[i]; ++ } + +- arg2 = value_from_longest (builtin_type_int32, offset_item); ++ element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tmp_type)); ++ offset_byte += offset_item * element_size; + + /* Let us now play a dirty trick: we will take arg1 + which is a value node pointing to the topmost level +@@ -2037,7 +2059,7 @@ evaluate_subexp_standard (struct type *expect_type, + returns the correct type value */ + + deprecated_set_value_type (arg1, tmp_type); +- return value_subscripted_rvalue (arg1, arg2, 0); ++ return value_subscripted_rvalue (arg1, offset_byte); + } + + case BINOP_LOGICAL_AND: +@@ -2624,12 +2646,13 @@ evaluate_subexp_with_coercion (struct expression *exp, + { + case OP_VAR_VALUE: + var = exp->elts[pc + 2].symbol; ++ /* address_of_variable will call object_address_set for check_typedef. */ ++ val = address_of_variable (var, exp->elts[pc + 1].block); + type = check_typedef (SYMBOL_TYPE (var)); + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && CAST_IS_CONVERSION) + { + (*pos) += 4; +- val = address_of_variable (var, exp->elts[pc + 1].block); + return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)), + val); + } +@@ -2681,9 +2704,13 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos) + + case OP_VAR_VALUE: + (*pos) += 4; +- type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol)); +- return +- value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); ++ /* We do not need to call read_var_value but the object evaluation may ++ need to have executed object_address_set which needs valid ++ SYMBOL_VALUE_ADDRESS of the symbol. Still VALUE returned by ++ read_var_value we left as lazy. */ ++ type = value_type (read_var_value (exp->elts[pc + 2].symbol, ++ deprecated_safe_get_selected_frame ())); ++ return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type)); + + default: + val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); +diff --git a/gdb/f-lang.h b/gdb/f-lang.h +index 711bdba..123a783 100644 +--- a/gdb/f-lang.h ++++ b/gdb/f-lang.h +@@ -28,6 +28,10 @@ extern void f_error (char *); /* Defined in f-exp.y */ + extern void f_print_type (struct type *, char *, struct ui_file *, int, + int); + ++extern const char *f_object_address_data_valid_print_to_stream ++ (struct type *type, struct ui_file *stream); ++extern void f_object_address_data_valid_or_error (struct type *type); ++ + extern int f_val_print (struct type *, const gdb_byte *, int, CORE_ADDR, + struct ui_file *, int, + const struct value_print_options *); +diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c +index 6c9668f..852b9a8 100644 +--- a/gdb/f-typeprint.c ++++ b/gdb/f-typeprint.c +@@ -31,7 +31,7 @@ + #include "gdbcore.h" + #include "target.h" + #include "f-lang.h" +- ++#include "dwarf2loc.h" + #include "gdb_string.h" + #include + +@@ -48,6 +48,34 @@ void f_type_print_varspec_prefix (struct type *, struct ui_file *, + void f_type_print_base (struct type *, struct ui_file *, int, int); + + ++const char * ++f_object_address_data_valid_print_to_stream (struct type *type, ++ struct ui_file *stream) ++{ ++ const char *msg; ++ ++ msg = object_address_data_not_valid (type); ++ if (msg != NULL) ++ { ++ /* Assuming the content printed to STREAM should not be localized. */ ++ fprintf_filtered (stream, "<%s>", msg); ++ } ++ ++ return msg; ++} ++ ++void ++f_object_address_data_valid_or_error (struct type *type) ++{ ++ const char *msg; ++ ++ msg = object_address_data_not_valid (type); ++ if (msg != NULL) ++ { ++ error (_("Cannot access it because the %s."), _(msg)); ++ } ++} ++ + /* LEVEL is the depth to indent lines by. */ + + void +@@ -57,6 +85,9 @@ f_print_type (struct type *type, char *varstring, struct ui_file *stream, + enum type_code code; + int demangled_args; + ++ if (f_object_address_data_valid_print_to_stream (type, stream) != NULL) ++ return; ++ + f_type_print_base (type, stream, show, level); + code = TYPE_CODE (type); + if ((varstring != NULL && *varstring != '\0') +@@ -166,6 +197,9 @@ f_type_print_varspec_suffix (struct type *type, struct ui_file *stream, + + QUIT; + ++ if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF) ++ CHECK_TYPEDEF (type); ++ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: +diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c +index 5721041..a4d69fb 100644 +--- a/gdb/f-valprint.c ++++ b/gdb/f-valprint.c +@@ -54,15 +54,17 @@ int f77_array_offset_tbl[MAX_FORTRAN_DIMS + 1][2]; + /* The following macro gives us the size of the nth dimension, Where + n is 1 based. */ + +-#define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1]) ++#define F77_DIM_COUNT(n) (f77_array_offset_tbl[n][1]) + +-/* The following gives us the offset for row n where n is 1-based. */ ++/* The following gives us the element size for row n where n is 1-based. */ + +-#define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0]) ++#define F77_DIM_BYTE_STRIDE(n) (f77_array_offset_tbl[n][0]) + + int + f77_get_lowerbound (struct type *type) + { ++ f_object_address_data_valid_or_error (type); ++ + if (TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED (type)) + error (_("Lower bound may not be '*' in F77")); + +@@ -72,14 +74,17 @@ f77_get_lowerbound (struct type *type) + int + f77_get_upperbound (struct type *type) + { ++ f_object_address_data_valid_or_error (type); ++ + if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) + { +- /* We have an assumed size array on our hands. Assume that +- upper_bound == lower_bound so that we show at least 1 element. +- If the user wants to see more elements, let him manually ask for 'em +- and we'll subscript the array and show him. */ ++ /* We have an assumed size array on our hands. As type_length_get ++ already assumes a length zero of arrays with underfined bounds VALADDR ++ passed to the Fortran functions does not contained the real inferior ++ memory content. User should request printing of specific array ++ elements instead. */ + +- return f77_get_lowerbound (type); ++ return f77_get_lowerbound (type) - 1; + } + + return TYPE_ARRAY_UPPER_BOUND_VALUE (type); +@@ -135,24 +140,29 @@ f77_create_arrayprint_offset_tbl (struct type *type, struct ui_file *stream) + upper = f77_get_upperbound (tmp_type); + lower = f77_get_lowerbound (tmp_type); + +- F77_DIM_SIZE (ndimen) = upper - lower + 1; ++ F77_DIM_COUNT (ndimen) = upper - lower + 1; ++ ++ F77_DIM_BYTE_STRIDE (ndimen) = ++ TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type); + + tmp_type = TYPE_TARGET_TYPE (tmp_type); + ndimen++; + } + +- /* Now we multiply eltlen by all the offsets, so that later we ++ /* Now we multiply eltlen by all the BYTE_STRIDEs, so that later we + can print out array elements correctly. Up till now we +- know an offset to apply to get the item but we also ++ know an eltlen to apply to get the item but we also + have to know how much to add to get to the next item */ + + ndimen--; + eltlen = TYPE_LENGTH (tmp_type); +- F77_DIM_OFFSET (ndimen) = eltlen; ++ if (F77_DIM_BYTE_STRIDE (ndimen) == 0) ++ F77_DIM_BYTE_STRIDE (ndimen) = eltlen; + while (--ndimen > 0) + { +- eltlen *= F77_DIM_SIZE (ndimen + 1); +- F77_DIM_OFFSET (ndimen) = eltlen; ++ eltlen *= F77_DIM_COUNT (ndimen + 1); ++ if (F77_DIM_BYTE_STRIDE (ndimen) == 0) ++ F77_DIM_BYTE_STRIDE (ndimen) = eltlen; + } + } + +@@ -172,34 +182,34 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type, + + if (nss != ndimensions) + { +- for (i = 0; (i < F77_DIM_SIZE (nss) && (*elts) < options->print_max); i++) ++ for (i = 0; (i < F77_DIM_COUNT (nss) && (*elts) < options->print_max); i++) + { + fprintf_filtered (stream, "( "); + f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type), +- valaddr + i * F77_DIM_OFFSET (nss), +- address + i * F77_DIM_OFFSET (nss), ++ valaddr + i * F77_DIM_BYTE_STRIDE (nss), ++ address + i * F77_DIM_BYTE_STRIDE (nss), + stream, recurse, options, elts); + fprintf_filtered (stream, ") "); + } +- if (*elts >= options->print_max && i < F77_DIM_SIZE (nss)) ++ if (*elts >= options->print_max && i < F77_DIM_COUNT (nss)) + fprintf_filtered (stream, "..."); + } + else + { +- for (i = 0; i < F77_DIM_SIZE (nss) && (*elts) < options->print_max; ++ for (i = 0; i < F77_DIM_COUNT (nss) && (*elts) < options->print_max; + i++, (*elts)++) + { + val_print (TYPE_TARGET_TYPE (type), +- valaddr + i * F77_DIM_OFFSET (ndimensions), ++ valaddr + i * F77_DIM_BYTE_STRIDE (ndimensions), + 0, +- address + i * F77_DIM_OFFSET (ndimensions), ++ address + i * F77_DIM_BYTE_STRIDE (ndimensions), + stream, recurse, options, current_language); + +- if (i != (F77_DIM_SIZE (nss) - 1)) ++ if (i != (F77_DIM_COUNT (nss) - 1)) + fprintf_filtered (stream, ", "); + + if ((*elts == options->print_max - 1) +- && (i != (F77_DIM_SIZE (nss) - 1))) ++ && (i != (F77_DIM_COUNT (nss) - 1))) + fprintf_filtered (stream, "..."); + } + } +@@ -251,6 +261,9 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, + CORE_ADDR addr; + int index; + ++ if (f_object_address_data_valid_print_to_stream (type, stream) != NULL) ++ return 0; ++ + CHECK_TYPEDEF (type); + switch (TYPE_CODE (type)) + { +diff --git a/gdb/findvar.c b/gdb/findvar.c +index 1048887..b9e7711 100644 +--- a/gdb/findvar.c ++++ b/gdb/findvar.c +@@ -35,6 +35,7 @@ + #include "user-regs.h" + #include "block.h" + #include "objfiles.h" ++#include "dwarf2loc.h" + + /* Basic byte-swapping routines. GDB has needed these for a long time... + All extract a target-format integer at ADDR which is LEN bytes long. */ +@@ -382,27 +383,16 @@ symbol_read_needs_frame (struct symbol *sym) + /* Given a struct symbol for a variable, + and a stack frame id, read the value of the variable + and return a (pointer to a) struct value containing the value. +- If the variable cannot be found, return a zero pointer. */ ++ If the variable cannot be found, return a zero pointer. ++ We have to first find the address of the variable before allocating struct ++ value to return as its size may depend on DW_OP_PUSH_OBJECT_ADDRESS possibly ++ used by its type. */ + + struct value * + read_var_value (struct symbol *var, struct frame_info *frame) + { +- struct value *v; + struct type *type = SYMBOL_TYPE (var); + CORE_ADDR addr; +- int len; +- +- if (SYMBOL_CLASS (var) == LOC_COMPUTED +- || SYMBOL_CLASS (var) == LOC_REGISTER) +- /* These cases do not use V. */ +- v = NULL; +- else +- { +- v = allocate_value (type); +- VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */ +- } +- +- len = TYPE_LENGTH (type); + + if (symbol_read_needs_frame (var)) + gdb_assert (frame); +@@ -410,31 +400,39 @@ read_var_value (struct symbol *var, struct frame_info *frame) + switch (SYMBOL_CLASS (var)) + { + case LOC_CONST: +- /* Put the constant back in target format. */ +- store_signed_integer (value_contents_raw (v), len, +- (LONGEST) SYMBOL_VALUE (var)); +- VALUE_LVAL (v) = not_lval; +- return v; ++ { ++ /* Put the constant back in target format. */ ++ struct value *v = allocate_value (type); ++ VALUE_LVAL (v) = not_lval; ++ store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type), ++ (LONGEST) SYMBOL_VALUE (var)); ++ return v; ++ } + + case LOC_LABEL: +- /* Put the constant back in target format. */ +- if (overlay_debugging) +- { +- CORE_ADDR addr +- = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), +- SYMBOL_OBJ_SECTION (var)); +- store_typed_address (value_contents_raw (v), type, addr); +- } +- else +- store_typed_address (value_contents_raw (v), type, +- SYMBOL_VALUE_ADDRESS (var)); +- VALUE_LVAL (v) = not_lval; +- return v; ++ { ++ /* Put the constant back in target format. */ ++ struct value *v = allocate_value (type); ++ VALUE_LVAL (v) = not_lval; ++ if (overlay_debugging) ++ { ++ CORE_ADDR addr ++ = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var), ++ SYMBOL_OBJ_SECTION (var)); ++ store_typed_address (value_contents_raw (v), type, addr); ++ } ++ else ++ store_typed_address (value_contents_raw (v), type, ++ SYMBOL_VALUE_ADDRESS (var)); ++ return v; ++ } + + case LOC_CONST_BYTES: + { +- memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), len); ++ struct value *v = allocate_value (type); + VALUE_LVAL (v) = not_lval; ++ memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), ++ TYPE_LENGTH (type)); + return v; + } + +@@ -476,12 +474,23 @@ read_var_value (struct symbol *var, struct frame_info *frame) + break; + + case LOC_BLOCK: +- if (overlay_debugging) +- VALUE_ADDRESS (v) = symbol_overlayed_address +- (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)); +- else +- VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); +- return v; ++ { ++ CORE_ADDR addr; ++ struct value *v; ++ ++ if (overlay_debugging) ++ addr = symbol_overlayed_address ++ (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)); ++ else ++ addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var)); ++ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for ++ DW_OP_push_object_address. */ ++ object_address_set (addr); ++ v = allocate_value (type); ++ VALUE_ADDRESS (v) = addr; ++ VALUE_LVAL (v) = lval_memory; ++ return v; ++ } + + case LOC_REGISTER: + case LOC_REGPARM_ADDR: +@@ -499,7 +508,6 @@ read_var_value (struct symbol *var, struct frame_info *frame) + error (_("Value of register variable not available.")); + + addr = value_as_address (regval); +- VALUE_LVAL (v) = lval_memory; + } + else + { +@@ -542,18 +550,33 @@ read_var_value (struct symbol *var, struct frame_info *frame) + break; + + case LOC_OPTIMIZED_OUT: +- VALUE_LVAL (v) = not_lval; +- set_value_optimized_out (v, 1); +- return v; ++ { ++ struct value *v = allocate_value (type); ++ ++ VALUE_LVAL (v) = not_lval; ++ set_value_optimized_out (v, 1); ++ return v; ++ } + + default: + error (_("Cannot look up value of a botched symbol.")); + break; + } + +- VALUE_ADDRESS (v) = addr; +- set_value_lazy (v, 1); +- return v; ++ { ++ struct value *v; ++ ++ /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for ++ DW_OP_PUSH_OBJECT_ADDRESS. */ ++ object_address_set (addr); ++ v = allocate_value (type); ++ VALUE_ADDRESS (v) = addr; ++ VALUE_LVAL (v) = lval_memory; ++ ++ set_value_lazy (v, 1); ++ ++ return v; ++ } + } + + /* Install default attributes for register values. */ +@@ -590,10 +613,11 @@ struct value * + value_from_register (struct type *type, int regnum, struct frame_info *frame) + { + struct gdbarch *gdbarch = get_frame_arch (frame); +- struct type *type1 = check_typedef (type); + struct value *v; + +- if (gdbarch_convert_register_p (gdbarch, regnum, type1)) ++ type = check_typedef (type); ++ ++ if (gdbarch_convert_register_p (gdbarch, regnum, type)) + { + /* The ISA/ABI need to something weird when obtaining the + specified value from this register. It might need to +@@ -607,7 +631,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame) + VALUE_FRAME_ID (v) = get_frame_id (frame); + VALUE_REGNUM (v) = regnum; + gdbarch_register_to_value (gdbarch, +- frame, regnum, type1, value_contents_raw (v)); ++ frame, regnum, type, value_contents_raw (v)); + } + else + { +diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c +index 8102321..e6190cf 100644 +--- a/gdb/gdbtypes.c ++++ b/gdb/gdbtypes.c +@@ -38,6 +38,8 @@ + #include "cp-abi.h" + #include "gdb_assert.h" + #include "hashtab.h" ++#include "dwarf2expr.h" ++#include "dwarf2loc.h" + + /* These variables point to the objects + representing the predefined C data types. */ +@@ -146,6 +148,23 @@ static void print_bit_vector (B_TYPE *, int); + static void print_arg_types (struct field *, int, int); + static void dump_fn_fieldlists (struct type *, int); + static void print_cplus_stuff (struct type *, int); ++static void type_init_refc (struct type *new_type, struct type *parent_type); ++ ++/* A reference count structure for the type reference count map. Each ++ type in a hierarchy of types is mapped to the same reference ++ count. */ ++struct type_refc_entry ++{ ++ /* One type in the hierarchy. Each type in the hierarchy gets its ++ own slot. */ ++ struct type *type; ++ ++ /* A pointer to the shared reference count. */ ++ int *refc; ++}; ++ ++/* The hash table holding all reference counts. */ ++static htab_t type_refc_table; + + + /* Alloc a new type structure and fill it with some defaults. If +@@ -154,23 +173,25 @@ static void print_cplus_stuff (struct type *, int); + structure by xmalloc () (for permanent types). */ + + struct type * +-alloc_type (struct objfile *objfile) ++alloc_type (struct objfile *objfile, struct type *parent) + { + struct type *type; + + /* Alloc the structure and start off with all fields zeroed. */ + +- if (objfile == NULL) ++ switch ((long) objfile) + { ++ case (long) OBJFILE_INTERNAL: ++ case (long) OBJFILE_MALLOC: + type = XZALLOC (struct type); + TYPE_MAIN_TYPE (type) = XZALLOC (struct main_type); +- } +- else +- { ++ break; ++ default: + type = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct type); + TYPE_MAIN_TYPE (type) = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct main_type); + OBJSTAT (objfile, n_types++); ++ break; + } + + /* Initialize the fields that might not be zero. */ +@@ -180,6 +201,9 @@ alloc_type (struct objfile *objfile) + TYPE_VPTR_FIELDNO (type) = -1; + TYPE_CHAIN (type) = type; /* Chain back to itself. */ + ++ if (objfile == NULL) ++ type_init_refc (type, parent); ++ + return (type); + } + +@@ -194,16 +218,24 @@ alloc_type_instance (struct type *oldtype) + + /* Allocate the structure. */ + +- if (TYPE_OBJFILE (oldtype) == NULL) +- type = XZALLOC (struct type); +- else +- type = OBSTACK_ZALLOC (&TYPE_OBJFILE (oldtype)->objfile_obstack, +- struct type); +- ++ switch ((long) TYPE_OBJFILE (oldtype)) ++ { ++ case (long) OBJFILE_INTERNAL: ++ case (long) OBJFILE_MALLOC: ++ type = XZALLOC (struct type); ++ break; ++ default: ++ type = OBSTACK_ZALLOC (&TYPE_OBJFILE (oldtype)->objfile_obstack, ++ struct type); ++ break; ++ } + TYPE_MAIN_TYPE (type) = TYPE_MAIN_TYPE (oldtype); + + TYPE_CHAIN (type) = type; /* Chain back to itself for now. */ + ++ if (TYPE_OBJFILE (oldtype) == NULL) ++ type_init_refc (type, oldtype); ++ + return (type); + } + +@@ -248,7 +280,7 @@ make_pointer_type (struct type *type, struct type **typeptr) + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { +- ntype = alloc_type (TYPE_OBJFILE (type)); ++ ntype = alloc_type (TYPE_OBJFILE (type), type); + if (typeptr) + *typeptr = ntype; + } +@@ -260,6 +292,9 @@ make_pointer_type (struct type *type, struct type **typeptr) + smash_type (ntype); + TYPE_CHAIN (ntype) = chain; + TYPE_OBJFILE (ntype) = objfile; ++ ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (objfile); + } + + TYPE_TARGET_TYPE (ntype) = type; +@@ -328,7 +363,7 @@ make_reference_type (struct type *type, struct type **typeptr) + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { +- ntype = alloc_type (TYPE_OBJFILE (type)); ++ ntype = alloc_type (TYPE_OBJFILE (type), type); + if (typeptr) + *typeptr = ntype; + } +@@ -340,6 +375,9 @@ make_reference_type (struct type *type, struct type **typeptr) + smash_type (ntype); + TYPE_CHAIN (ntype) = chain; + TYPE_OBJFILE (ntype) = objfile; ++ ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (objfile); + } + + TYPE_TARGET_TYPE (ntype) = type; +@@ -388,7 +426,7 @@ make_function_type (struct type *type, struct type **typeptr) + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { +- ntype = alloc_type (TYPE_OBJFILE (type)); ++ ntype = alloc_type (TYPE_OBJFILE (type), type); + if (typeptr) + *typeptr = ntype; + } +@@ -398,6 +436,9 @@ make_function_type (struct type *type, struct type **typeptr) + objfile = TYPE_OBJFILE (ntype); + smash_type (ntype); + TYPE_OBJFILE (ntype) = objfile; ++ ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (objfile); + } + + TYPE_TARGET_TYPE (ntype) = type; +@@ -643,7 +684,7 @@ lookup_memberptr_type (struct type *type, struct type *domain) + { + struct type *mtype; + +- mtype = alloc_type (TYPE_OBJFILE (type)); ++ mtype = alloc_type (TYPE_OBJFILE (type), NULL); + smash_to_memberptr_type (mtype, domain, type); + return (mtype); + } +@@ -655,7 +696,7 @@ lookup_methodptr_type (struct type *to_type) + { + struct type *mtype; + +- mtype = alloc_type (TYPE_OBJFILE (to_type)); ++ mtype = alloc_type (TYPE_OBJFILE (to_type), NULL); + TYPE_TARGET_TYPE (mtype) = to_type; + TYPE_DOMAIN_TYPE (mtype) = TYPE_DOMAIN_TYPE (to_type); + TYPE_LENGTH (mtype) = cplus_method_ptr_size (to_type); +@@ -696,19 +737,20 @@ create_range_type (struct type *result_type, struct type *index_type, + int low_bound, int high_bound) + { + if (result_type == NULL) +- result_type = alloc_type (TYPE_OBJFILE (index_type)); ++ result_type = alloc_type (TYPE_OBJFILE (index_type), index_type); + TYPE_CODE (result_type) = TYPE_CODE_RANGE; + TYPE_TARGET_TYPE (result_type) = index_type; + if (TYPE_STUB (index_type)) + TYPE_TARGET_STUB (result_type) = 1; + else + TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type)); +- TYPE_NFIELDS (result_type) = 2; ++ TYPE_NFIELDS (result_type) = 3; + TYPE_FIELDS (result_type) = TYPE_ZALLOC (result_type, + TYPE_NFIELDS (result_type) + * sizeof (struct field)); + TYPE_LOW_BOUND (result_type) = low_bound; + TYPE_HIGH_BOUND (result_type) = high_bound; ++ TYPE_BYTE_STRIDE (result_type) = 0; + + if (low_bound >= 0) + TYPE_UNSIGNED (result_type) = 1; +@@ -727,6 +769,9 @@ get_discrete_bounds (struct type *type, LONGEST *lowp, LONGEST *highp) + switch (TYPE_CODE (type)) + { + case TYPE_CODE_RANGE: ++ if (TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (type) ++ || TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (type)) ++ return -1; + *lowp = TYPE_LOW_BOUND (type); + *highp = TYPE_HIGH_BOUND (type); + return 1; +@@ -805,30 +850,65 @@ create_array_type (struct type *result_type, + + if (result_type == NULL) + { +- result_type = alloc_type (TYPE_OBJFILE (range_type)); ++ result_type = alloc_type (TYPE_OBJFILE (range_type), range_type); + } ++ else ++ { ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (TYPE_OBJFILE (result_type)); ++ } ++ + TYPE_CODE (result_type) = TYPE_CODE_ARRAY; + TYPE_TARGET_TYPE (result_type) = element_type; +- if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) +- low_bound = high_bound = 0; +- CHECK_TYPEDEF (element_type); +- /* Be careful when setting the array length. Ada arrays can be +- empty arrays with the high_bound being smaller than the low_bound. +- In such cases, the array length should be zero. */ +- if (high_bound < low_bound) +- TYPE_LENGTH (result_type) = 0; +- else +- TYPE_LENGTH (result_type) = +- TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); + TYPE_NFIELDS (result_type) = 1; + TYPE_FIELDS (result_type) = + (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field)); ++ /* FIXME: type alloc. */ + TYPE_INDEX_TYPE (result_type) = range_type; + TYPE_VPTR_FIELDNO (result_type) = -1; + +- /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays */ ++ /* DWARF blocks may depend on runtime information like ++ DW_OP_PUSH_OBJECT_ADDRESS not being available during the ++ CREATE_ARRAY_TYPE time. */ ++ if (TYPE_RANGE_BOUND_IS_DWARF_BLOCK (range_type, 0) ++ || TYPE_RANGE_BOUND_IS_DWARF_BLOCK (range_type, 1) ++ || TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type) ++ || TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (range_type) ++ || get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) ++ { ++ low_bound = 0; ++ high_bound = -1; ++ } ++ ++ /* Be careful when setting the array length. Ada arrays can be ++ empty arrays with the high_bound being smaller than the low_bound. ++ In such cases, the array length should be zero. TYPE_TARGET_STUB needs to ++ be checked as it may have dependencies on DWARF blocks depending on ++ runtime information not available during the CREATE_ARRAY_TYPE time. */ ++ if (high_bound < low_bound || TYPE_TARGET_STUB (element_type)) ++ TYPE_LENGTH (result_type) = 0; ++ else ++ { ++ CHECK_TYPEDEF (element_type); ++ TYPE_LENGTH (result_type) = ++ TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); ++ } ++ ++ if (TYPE_DYNAMIC (range_type)) ++ TYPE_DYNAMIC (result_type) = 1; ++ ++ /* Multidimensional dynamic arrays need to have all the outer dimensions ++ dynamic to update the outer TYPE_TARGET_TYPE pointer with the new type ++ with statically evaluated dimensions. */ ++ if (TYPE_DYNAMIC (element_type)) ++ TYPE_DYNAMIC (result_type) = 1; ++ + if (TYPE_LENGTH (result_type) == 0) +- TYPE_TARGET_STUB (result_type) = 1; ++ { ++ /* The real size will be computed for specific instances by ++ CHECK_TYPEDEF. */ ++ TYPE_TARGET_STUB (result_type) = 1; ++ } + + return (result_type); + } +@@ -865,7 +945,12 @@ create_set_type (struct type *result_type, struct type *domain_type) + { + if (result_type == NULL) + { +- result_type = alloc_type (TYPE_OBJFILE (domain_type)); ++ result_type = alloc_type (TYPE_OBJFILE (domain_type), domain_type); ++ } ++ else ++ { ++ /* Callers may only supply storage if there is an objfile. */ ++ gdb_assert (TYPE_OBJFILE (result_type)); + } + TYPE_CODE (result_type) = TYPE_CODE_SET; + TYPE_NFIELDS (result_type) = 1; +@@ -1368,6 +1453,65 @@ stub_noname_complaint (void) + complaint (&symfile_complaints, _("stub type has NULL name")); + } + ++/* Calculate the memory length of array TYPE. ++ ++ TARGET_TYPE should be set to `check_typedef (TYPE_TARGET_TYPE (type))' as ++ a performance hint. Feel free to pass NULL. Set FULL_SPAN to return the ++ size incl. the possible padding of the last element - it may differ from the ++ cleared FULL_SPAN return value (the expected SIZEOF) for non-zero ++ TYPE_BYTE_STRIDE values. */ ++ ++static CORE_ADDR ++type_length_get (struct type *type, struct type *target_type, int full_span) ++{ ++ struct type *range_type; ++ int count; ++ CORE_ADDR byte_stride = 0; /* `= 0' for a false GCC warning. */ ++ CORE_ADDR element_size; ++ ++ if (TYPE_CODE (type) != TYPE_CODE_ARRAY ++ && TYPE_CODE (type) != TYPE_CODE_STRING) ++ return TYPE_LENGTH (type); ++ ++ /* Avoid executing TYPE_HIGH_BOUND for invalid (unallocated/unassociated) ++ Fortran arrays. The allocated data will never be used so they can be ++ zero-length. */ ++ if (object_address_data_not_valid (type)) ++ return 0; ++ ++ range_type = TYPE_INDEX_TYPE (type); ++ if (TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (range_type) ++ || TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (range_type)) ++ return 0; ++ count = TYPE_HIGH_BOUND (range_type) - TYPE_LOW_BOUND (range_type) + 1; ++ /* It may happen for wrong DWARF annotations returning garbage data. */ ++ if (count < 0) ++ warning (_("Range for type %s has invalid bounds %d..%d"), ++ TYPE_NAME (type), TYPE_LOW_BOUND (range_type), ++ TYPE_HIGH_BOUND (range_type)); ++ /* The code below does not handle count == 0 right. */ ++ if (count <= 0) ++ return 0; ++ if (full_span || count > 1) ++ { ++ /* We do not use TYPE_ARRAY_BYTE_STRIDE_VALUE (type) here as we want to ++ force FULL_SPAN to 1. */ ++ byte_stride = TYPE_BYTE_STRIDE (range_type); ++ if (byte_stride == 0) ++ { ++ if (target_type == NULL) ++ target_type = check_typedef (TYPE_TARGET_TYPE (type)); ++ byte_stride = type_length_get (target_type, NULL, 1); ++ } ++ } ++ if (full_span) ++ return count * byte_stride; ++ if (target_type == NULL) ++ target_type = check_typedef (TYPE_TARGET_TYPE (type)); ++ element_size = type_length_get (target_type, NULL, 1); ++ return (count - 1) * byte_stride + element_size; ++} ++ + /* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989. + + If this is a stubbed struct (i.e. declared as struct foo *), see if +@@ -1384,7 +1528,8 @@ stub_noname_complaint (void) + /* Find the real type of TYPE. This function returns the real type, + after removing all layers of typedefs and completing opaque or stub + types. Completion changes the TYPE argument, but stripping of +- typedefs does not. */ ++ typedefs does not. Still original passed TYPE will have TYPE_LENGTH ++ updated. FIXME: Remove this dependency (only ada_to_fixed_type?). */ + + struct type * + check_typedef (struct type *type) +@@ -1420,7 +1565,7 @@ check_typedef (struct type *type) + if (sym) + TYPE_TARGET_TYPE (type) = SYMBOL_TYPE (sym); + else /* TYPE_CODE_UNDEF */ +- TYPE_TARGET_TYPE (type) = alloc_type (NULL); ++ TYPE_TARGET_TYPE (type) = alloc_type (NULL, NULL); + } + type = TYPE_TARGET_TYPE (type); + } +@@ -1494,34 +1639,37 @@ check_typedef (struct type *type) + } + } + +- if (TYPE_TARGET_STUB (type)) ++ /* copy_type_recursive automatically makes the resulting type containing only ++ constant values expected by the callers of this function. */ ++ if (TYPE_DYNAMIC (type)) ++ { ++ htab_t copied_types; ++ struct type *type_old = type; ++ ++ copied_types = create_copied_types_hash (NULL); ++ type = copy_type_recursive (type, copied_types); ++ htab_delete (copied_types); ++ ++ gdb_assert (TYPE_DYNAMIC (type) == 0); ++ } ++ ++ if (!currently_reading_symtab ++ && (TYPE_TARGET_STUB (type) || TYPE_DYNAMIC (type))) + { +- struct type *range_type; + struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type)); + ++ if (TYPE_DYNAMIC (type)) ++ TYPE_TARGET_TYPE (type) = target_type; + if (TYPE_STUB (target_type) || TYPE_TARGET_STUB (target_type)) + { + /* Empty. */ + } + else if (TYPE_CODE (type) == TYPE_CODE_ARRAY +- && TYPE_NFIELDS (type) == 1 +- && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type)) +- == TYPE_CODE_RANGE)) ++ || TYPE_CODE (type) == TYPE_CODE_STRING) + { + /* Now recompute the length of the array type, based on its +- number of elements and the target type's length. +- Watch out for Ada null Ada arrays where the high bound +- is smaller than the low bound. */ +- const int low_bound = TYPE_LOW_BOUND (range_type); +- const int high_bound = TYPE_HIGH_BOUND (range_type); +- int nb_elements; +- +- if (high_bound < low_bound) +- nb_elements = 0; +- else +- nb_elements = high_bound - low_bound + 1; +- +- TYPE_LENGTH (type) = nb_elements * TYPE_LENGTH (target_type); ++ number of elements and the target type's length. */ ++ TYPE_LENGTH (type) = type_length_get (type, target_type, 0); + TYPE_TARGET_STUB (type) = 0; + } + else if (TYPE_CODE (type) == TYPE_CODE_RANGE) +@@ -1529,9 +1677,12 @@ check_typedef (struct type *type) + TYPE_LENGTH (type) = TYPE_LENGTH (target_type); + TYPE_TARGET_STUB (type) = 0; + } ++ TYPE_DYNAMIC (type) = 0; + } ++ + /* Cache TYPE_LENGTH for future use. */ + TYPE_LENGTH (orig_type) = TYPE_LENGTH (type); ++ + return type; + } + +@@ -1753,7 +1904,7 @@ init_type (enum type_code code, int length, int flags, + { + struct type *type; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + TYPE_CODE (type) = code; + TYPE_LENGTH (type) = length; + +@@ -1783,15 +1934,24 @@ init_type (enum type_code code, int length, int flags, + if (flags & TYPE_FLAG_FIXED_INSTANCE) + TYPE_FIXED_INSTANCE (type) = 1; + +- if ((name != NULL) && (objfile != NULL)) +- { +- TYPE_NAME (type) = obsavestring (name, strlen (name), +- &objfile->objfile_obstack); +- } +- else +- { +- TYPE_NAME (type) = name; +- } ++ if (name) ++ switch ((long) objfile) ++ { ++ case (long) OBJFILE_INTERNAL: ++ TYPE_NAME (type) = name; ++ break; ++ case (long) OBJFILE_MALLOC: ++ TYPE_NAME (type) = xstrdup (name); ++ break; ++#if 0 /* OBJFILE_MALLOC duplication now. */ ++ case (long) NULL: ++ internal_error (__FILE__, __LINE__, ++ _("OBJFILE pointer NULL should be OBJFILE_* instead")); ++#endif ++ default: ++ TYPE_NAME (type) = obsavestring (name, strlen (name), ++ &objfile->objfile_obstack); ++ } + + /* C++ fancies. */ + +@@ -1803,6 +1963,10 @@ init_type (enum type_code code, int length, int flags, + { + INIT_CPLUS_SPECIFIC (type); + } ++ ++ if (!objfile) ++ type_incref (type); ++ + return (type); + } + +@@ -2916,33 +3080,47 @@ type_pair_eq (const void *item_lhs, const void *item_rhs) + } + + /* Allocate the hash table used by copy_type_recursive to walk +- types without duplicates. We use OBJFILE's obstack, because +- OBJFILE is about to be deleted. */ ++ types without duplicates. */ + + htab_t + create_copied_types_hash (struct objfile *objfile) + { +- return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, +- NULL, &objfile->objfile_obstack, +- hashtab_obstack_allocate, +- dummy_obstack_deallocate); ++ if (objfile == NULL) ++ { ++ /* NULL OBJFILE is for TYPE_DYNAMIC types already contained in ++ OBJFILE_MALLOC memory, such as those from VALUE_HISTORY_CHAIN. Table ++ element entries get allocated by xmalloc - so use xfree. */ ++ return htab_create (1, type_pair_hash, type_pair_eq, xfree); ++ } ++ else ++ { ++ /* Use OBJFILE's obstack, because OBJFILE is about to be deleted. Table ++ element entries get allocated by xmalloc - so use xfree. */ ++ return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, ++ xfree, &objfile->objfile_obstack, ++ hashtab_obstack_allocate, ++ dummy_obstack_deallocate); ++ } + } + +-/* Recursively copy (deep copy) TYPE, if it is associated with +- OBJFILE. Return a new type allocated using malloc, a saved type if +- we have already visited TYPE (using COPIED_TYPES), or TYPE if it is +- not associated with OBJFILE. */ ++/* A helper for copy_type_recursive. This does all the work. ++ REPRESENTATIVE is a pointer to a type. This is used to register ++ newly-created types in the type_refc_table. Initially it pointer ++ to a NULL pointer, but it is filled in the first time a type is ++ copied. OBJFILE is used only for an assertion checking. */ + +-struct type * +-copy_type_recursive (struct objfile *objfile, +- struct type *type, +- htab_t copied_types) ++static struct type * ++copy_type_recursive_1 (struct objfile *objfile, ++ struct type *type, ++ htab_t copied_types, ++ struct type **representative) + { + struct type_pair *stored, pair; + void **slot; + struct type *new_type; + +- if (TYPE_OBJFILE (type) == NULL) ++ if (TYPE_OBJFILE (type) == OBJFILE_INTERNAL ++ || (objfile == OBJFILE_MALLOC && !TYPE_DYNAMIC (type))) + return type; + + /* This type shouldn't be pointing to any types in other objfiles; +@@ -2954,11 +3132,15 @@ copy_type_recursive (struct objfile *objfile, + if (*slot != NULL) + return ((struct type_pair *) *slot)->new; + +- new_type = alloc_type (NULL); ++ new_type = alloc_type (OBJFILE_MALLOC, *representative); ++ if (!*representative) ++ *representative = new_type; + + /* We must add the new type to the hash table immediately, in case +- we encounter this type again during a recursive call below. */ +- stored = obstack_alloc (&objfile->objfile_obstack, sizeof (struct type_pair)); ++ we encounter this type again during a recursive call below. Memory could ++ be allocated from OBJFILE in the case we will be removing OBJFILE, this ++ optimization is missed and xfree is called for it from COPIED_TYPES. */ ++ stored = xmalloc (sizeof (*stored)); + stored->old = type; + stored->new = new_type; + *slot = stored; +@@ -2968,6 +3150,13 @@ copy_type_recursive (struct objfile *objfile, + *TYPE_MAIN_TYPE (new_type) = *TYPE_MAIN_TYPE (type); + TYPE_OBJFILE (new_type) = NULL; + ++ /* Pre-clear the fields processed by delete_main_type. If DWARF block ++ evaluations below call error we would leave an unfreeable TYPE. */ ++ TYPE_TARGET_TYPE (new_type) = NULL; ++ TYPE_VPTR_BASETYPE (new_type) = NULL; ++ TYPE_NFIELDS (new_type) = 0; ++ TYPE_FIELDS (new_type) = NULL; ++ + if (TYPE_NAME (type)) + TYPE_NAME (new_type) = xstrdup (TYPE_NAME (type)); + if (TYPE_TAG_NAME (type)) +@@ -2976,12 +3165,45 @@ copy_type_recursive (struct objfile *objfile, + TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); + TYPE_LENGTH (new_type) = TYPE_LENGTH (type); + ++ if (TYPE_ALLOCATED (new_type)) ++ { ++ gdb_assert (!TYPE_NOT_ALLOCATED (new_type)); ++ ++ if (!dwarf_locexpr_baton_eval (TYPE_ALLOCATED (new_type))) ++ TYPE_NOT_ALLOCATED (new_type) = 1; ++ TYPE_ALLOCATED (new_type) = NULL; ++ } ++ ++ if (TYPE_ASSOCIATED (new_type)) ++ { ++ gdb_assert (!TYPE_NOT_ASSOCIATED (new_type)); ++ ++ if (!dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (new_type))) ++ TYPE_NOT_ASSOCIATED (new_type) = 1; ++ TYPE_ASSOCIATED (new_type) = NULL; ++ } ++ ++ if (!TYPE_DATA_LOCATION_IS_ADDR (new_type) ++ && TYPE_DATA_LOCATION_DWARF_BLOCK (new_type)) ++ { ++ if (TYPE_NOT_ALLOCATED (new_type) ++ || TYPE_NOT_ASSOCIATED (new_type)) ++ TYPE_DATA_LOCATION_DWARF_BLOCK (new_type) = NULL; ++ else ++ { ++ TYPE_DATA_LOCATION_IS_ADDR (new_type) = 1; ++ TYPE_DATA_LOCATION_ADDR (new_type) = dwarf_locexpr_baton_eval ++ (TYPE_DATA_LOCATION_DWARF_BLOCK (new_type)); ++ } ++ } ++ + /* Copy the fields. */ + if (TYPE_NFIELDS (type)) + { + int i, nfields; + + nfields = TYPE_NFIELDS (type); ++ TYPE_NFIELDS (new_type) = nfields; + TYPE_FIELDS (new_type) = XCALLOC (nfields, struct field); + for (i = 0; i < nfields; i++) + { +@@ -2990,8 +3212,8 @@ copy_type_recursive (struct objfile *objfile, + TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i); + if (TYPE_FIELD_TYPE (type, i)) + TYPE_FIELD_TYPE (new_type, i) +- = copy_type_recursive (objfile, TYPE_FIELD_TYPE (type, i), +- copied_types); ++ = copy_type_recursive_1 (objfile, TYPE_FIELD_TYPE (type, i), ++ copied_types, representative); + if (TYPE_FIELD_NAME (type, i)) + TYPE_FIELD_NAME (new_type, i) = + xstrdup (TYPE_FIELD_NAME (type, i)); +@@ -3010,6 +3232,16 @@ copy_type_recursive (struct objfile *objfile, + xstrdup (TYPE_FIELD_STATIC_PHYSNAME (type, + i))); + break; ++ case FIELD_LOC_KIND_DWARF_BLOCK: ++ /* `struct dwarf2_locexpr_baton' is too bound to its objfile so ++ it is expected to be made constant by CHECK_TYPEDEF. */ ++ if (TYPE_NOT_ALLOCATED (new_type) ++ || TYPE_NOT_ASSOCIATED (new_type)) ++ SET_FIELD_DWARF_BLOCK (TYPE_FIELD (new_type, i), NULL); ++ else ++ SET_FIELD_BITPOS (TYPE_FIELD (new_type, i), ++ dwarf_locexpr_baton_eval (TYPE_FIELD_DWARF_BLOCK (type, i))); ++ break; + default: + internal_error (__FILE__, __LINE__, + _("Unexpected type field location kind: %d"), +@@ -3018,17 +3250,32 @@ copy_type_recursive (struct objfile *objfile, + } + } + ++ /* Convert TYPE_RANGE_HIGH_BOUND_IS_COUNT into a regular bound. */ ++ if (TYPE_CODE (type) == TYPE_CODE_RANGE ++ && TYPE_RANGE_HIGH_BOUND_IS_COUNT (type)) ++ { ++ TYPE_RANGE_HIGH_BOUND_IS_COUNT (new_type) = 0; ++ TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (type) ++ + TYPE_HIGH_BOUND (type) - 1; ++ } ++ ++ /* Both FIELD_LOC_KIND_DWARF_BLOCK and TYPE_RANGE_HIGH_BOUND_IS_COUNT were ++ possibly converted. */ ++ TYPE_DYNAMIC (new_type) = 0; ++ + /* Copy pointers to other types. */ + if (TYPE_TARGET_TYPE (type)) + TYPE_TARGET_TYPE (new_type) = +- copy_type_recursive (objfile, +- TYPE_TARGET_TYPE (type), +- copied_types); ++ copy_type_recursive_1 (objfile, ++ TYPE_TARGET_TYPE (type), ++ copied_types, ++ representative); + if (TYPE_VPTR_BASETYPE (type)) + TYPE_VPTR_BASETYPE (new_type) = +- copy_type_recursive (objfile, +- TYPE_VPTR_BASETYPE (type), +- copied_types); ++ copy_type_recursive_1 (objfile, ++ TYPE_VPTR_BASETYPE (type), ++ copied_types, ++ representative); + /* Maybe copy the type_specific bits. + + NOTE drow/2005-12-09: We do not copy the C++-specific bits like +@@ -3046,6 +3293,20 @@ copy_type_recursive (struct objfile *objfile, + return new_type; + } + ++/* Recursively copy (deep copy) TYPE. Return a new type allocated using ++ malloc, a saved type if we have already visited TYPE (using COPIED_TYPES), ++ or TYPE if it is not associated with OBJFILE. */ ++ ++struct type * ++copy_type_recursive (struct type *type, ++ htab_t copied_types) ++{ ++ struct type *representative = NULL; ++ ++ return copy_type_recursive_1 (TYPE_OBJFILE (type), type, copied_types, ++ &representative); ++} ++ + /* Make a copy of the given TYPE, except that the pointer & reference + types are not preserved. + +@@ -3059,7 +3320,7 @@ copy_type (const struct type *type) + + gdb_assert (TYPE_OBJFILE (type) != NULL); + +- new_type = alloc_type (TYPE_OBJFILE (type)); ++ new_type = alloc_type (TYPE_OBJFILE (type), NULL); + TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type); + TYPE_LENGTH (new_type) = TYPE_LENGTH (type); + memcpy (TYPE_MAIN_TYPE (new_type), TYPE_MAIN_TYPE (type), +@@ -3068,6 +3329,242 @@ copy_type (const struct type *type) + return new_type; + } + ++static void delete_type (struct type *type); ++ ++/* A helper for delete_type which deletes a main_type and the things to which ++ it refers. TYPE is a type whose main_type we wish to destroy. */ ++ ++static void ++delete_main_type (struct main_type *main_type) ++{ ++ int i; ++ void **slot; ++ struct ++ { ++ struct main_type *main_type; ++ } type_local = { main_type }, *type = &type_local; ++ ++ gdb_assert (TYPE_OBJFILE (type) == OBJFILE_MALLOC); ++ ++ xfree (TYPE_NAME (type)); ++ xfree (TYPE_TAG_NAME (type)); ++ ++ for (i = 0; i < TYPE_NFIELDS (type); ++i) ++ { ++ xfree (TYPE_FIELD_NAME (type, i)); ++ ++ if (TYPE_FIELD_LOC_KIND (type, i) == FIELD_LOC_KIND_PHYSNAME) ++ xfree (TYPE_FIELD_STATIC_PHYSNAME (type, i)); ++ } ++ xfree (TYPE_FIELDS (type)); ++ ++ /* Strangely, HAVE_CPLUS_STRUCT will return true when there isn't ++ one at all. */ ++ gdb_assert (!HAVE_CPLUS_STRUCT (type) || !TYPE_CPLUS_SPECIFIC (type)); ++ ++ xfree (TYPE_MAIN_TYPE (type)); ++} ++ ++/* Store `struct main_type *' entries which got `struct type *' deleted. */ ++ ++static htab_t deleted_main_types_hash; ++ ++/* To be called before any call of delete_type. */ ++ ++static void ++delete_type_begin (void) ++{ ++ gdb_assert (deleted_main_types_hash == NULL); ++ ++ deleted_main_types_hash = htab_create_alloc (10, htab_hash_pointer, ++ htab_eq_pointer, NULL, xcalloc, xfree); ++} ++ ++/* Helper for delete_type_finish. */ ++ ++static int ++delete_type_finish_traverse (void **slot, void *unused) ++{ ++ struct main_type *main_type = *slot; ++ ++ delete_main_type (main_type); ++ ++ return 1; ++} ++ ++/* To be called after all the calls of delete_type. Each MAIN_TYPE must have ++ either none or all of its TYPE entries deleted. */ ++ ++static void ++delete_type_finish (void) ++{ ++ htab_traverse (deleted_main_types_hash, delete_type_finish_traverse, NULL); ++ ++ htab_delete (deleted_main_types_hash); ++ deleted_main_types_hash = NULL; ++} ++ ++/* Delete TYPE and remember MAIN_TYPE it references. TYPE must have been ++ allocated using xmalloc -- not using an objfile. You must wrap calls of ++ this function by delete_type_begin and delete_type_finish. */ ++ ++static void ++delete_type (struct type *type) ++{ ++ void **slot; ++ ++ if (!type) ++ return; ++ ++ if (TYPE_OBJFILE (type) == OBJFILE_INTERNAL) ++ return; ++ gdb_assert (TYPE_OBJFILE (type) == OBJFILE_MALLOC); ++ ++ slot = htab_find_slot (deleted_main_types_hash, TYPE_MAIN_TYPE (type), ++ INSERT); ++ gdb_assert (!*slot); ++ *slot = TYPE_MAIN_TYPE (type); ++ ++ xfree (type); ++} ++ ++/* Hash function for type_refc_table. */ ++ ++static hashval_t ++type_refc_hash (const void *p) ++{ ++ const struct type_refc_entry *entry = p; ++ return htab_hash_pointer (entry->type); ++} ++ ++/* Equality function for type_refc_table. */ ++ ++static int ++type_refc_equal (const void *a, const void *b) ++{ ++ const struct type_refc_entry *left = a; ++ const struct type_refc_entry *right = b; ++ return left->type == right->type; ++} ++ ++/* Insert the new type NEW_TYPE into the table. Does nothing if ++ NEW_TYPE has an objfile. If PARENT_TYPE is not NULL, then NEW_TYPE ++ will be inserted into the same hierarchy as PARENT_TYPE. In this ++ case, PARENT_TYPE must already exist in the reference count map. ++ If PARENT_TYPE is NULL, a new reference count is allocated and set ++ to one. */ ++ ++static void ++type_init_refc (struct type *new_type, struct type *parent_type) ++{ ++ int *refc; ++ void **slot; ++ struct type_refc_entry *new_entry; ++ ++ if (TYPE_OBJFILE (new_type)) ++ return; ++ ++ if (parent_type) ++ { ++ struct type_refc_entry entry, *found; ++ entry.type = parent_type; ++ found = htab_find (type_refc_table, &entry); ++ gdb_assert (found); ++ refc = found->refc; ++ } ++ else ++ { ++ refc = xmalloc (sizeof (int)); ++ *refc = 0; ++ } ++ ++ new_entry = XNEW (struct type_refc_entry); ++ new_entry->type = new_type; ++ new_entry->refc = refc; ++ ++ slot = htab_find_slot (type_refc_table, new_entry, INSERT); ++ gdb_assert (!*slot); ++ *slot = new_entry; ++} ++ ++/* Increment the reference count for TYPE. */ ++ ++void ++type_incref (struct type *type) ++{ ++ struct type_refc_entry entry, *found; ++ ++ if (TYPE_OBJFILE (type)) ++ return; ++ ++ entry.type = type; ++ found = htab_find (type_refc_table, &entry); ++ gdb_assert (found); ++ ++*(found->refc); ++} ++ ++/* A traverse callback for type_refc_table which removes any entry ++ whose reference count pointer is REFC. REFC may be NULL to delete all the ++ unused entries - use such cleanup only in the GDB idle state as GDB code ++ does not necessarily reference county TYPEs during its processing. */ ++ ++static int ++type_refc_remove (void **slot, void *refc) ++{ ++ struct type_refc_entry *entry = *slot; ++ ++ if (entry->refc == refc || (refc == NULL && *entry->refc == 0)) ++ { ++ delete_type (entry->type); ++ ++ xfree (entry); ++ htab_clear_slot (type_refc_table, slot); ++ } ++ ++ return 1; ++} ++ ++/* Decrement the reference count for TYPE. If TYPE has no more ++ references, delete it. */ ++ ++void ++type_decref (struct type *type) ++{ ++ struct type_refc_entry entry, *found; ++ ++ if (TYPE_OBJFILE (type)) ++ return; ++ ++ entry.type = type; ++ found = htab_find (type_refc_table, &entry); ++ gdb_assert (found); ++ --*(found->refc); ++ if (*(found->refc) == 0) ++ { ++ void *refc = found->refc; ++ ++ /* Clear all table entries referring to this count. CHECK: Should not be ++ the deletion delayed till free_all_types? */ ++ delete_type_begin (); ++ htab_traverse (type_refc_table, type_refc_remove, refc); ++ delete_type_finish (); ++ ++ /* Delete the reference count itself. */ ++ xfree (refc); ++ } ++} ++ ++/* Free all the types that have been allocated (except for those released). ++ Called after each command, successful or not. */ ++ ++void ++free_all_types (void) ++{ ++ delete_type_begin (); ++ htab_traverse (type_refc_table, type_refc_remove, NULL); ++ delete_type_finish (); ++} ++ + static struct type * + build_flt (int bit, char *name, const struct floatformat **floatformats) + { +@@ -3105,7 +3602,7 @@ build_complex (int bit, char *name, struct type *target_type) + return builtin_type_error; + } + t = init_type (TYPE_CODE_COMPLEX, 2 * bit / TARGET_CHAR_BIT, +- 0, name, (struct objfile *) NULL); ++ 0, name, OBJFILE_INTERNAL); + TYPE_TARGET_TYPE (t) = target_type; + return t; + } +@@ -3119,56 +3616,56 @@ gdbtypes_post_init (struct gdbarch *gdbarch) + builtin_type->builtin_void = + init_type (TYPE_CODE_VOID, 1, + 0, +- "void", (struct objfile *) NULL); ++ "void", OBJFILE_INTERNAL); + builtin_type->builtin_char = + init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + (TYPE_FLAG_NOSIGN + | (gdbarch_char_signed (gdbarch) ? 0 : TYPE_FLAG_UNSIGNED)), +- "char", (struct objfile *) NULL); ++ "char", OBJFILE_INTERNAL); + builtin_type->builtin_signed_char = + init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "signed char", (struct objfile *) NULL); ++ "signed char", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_char = + init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, +- "unsigned char", (struct objfile *) NULL); ++ "unsigned char", OBJFILE_INTERNAL); + builtin_type->builtin_short = + init_type (TYPE_CODE_INT, + gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "short", (struct objfile *) NULL); ++ 0, "short", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_short = + init_type (TYPE_CODE_INT, + gdbarch_short_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned short", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_int = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "int", (struct objfile *) NULL); ++ 0, "int", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_int = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned int", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_long = + init_type (TYPE_CODE_INT, + gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "long", (struct objfile *) NULL); ++ 0, "long", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_long = + init_type (TYPE_CODE_INT, + gdbarch_long_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_long_long = + init_type (TYPE_CODE_INT, + gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT, +- 0, "long long", (struct objfile *) NULL); ++ 0, "long long", OBJFILE_INTERNAL); + builtin_type->builtin_unsigned_long_long = + init_type (TYPE_CODE_INT, + gdbarch_long_long_bit (gdbarch) / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, "unsigned long long", +- (struct objfile *) NULL); ++ OBJFILE_INTERNAL); + builtin_type->builtin_float + = build_flt (gdbarch_float_bit (gdbarch), "float", + gdbarch_float_format (gdbarch)); +@@ -3187,26 +3684,26 @@ gdbtypes_post_init (struct gdbarch *gdbarch) + builtin_type->builtin_string = + init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "string", (struct objfile *) NULL); ++ "string", OBJFILE_INTERNAL); + builtin_type->builtin_bool = + init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "bool", (struct objfile *) NULL); ++ "bool", OBJFILE_INTERNAL); + + /* The following three are about decimal floating point types, which + are 32-bits, 64-bits and 128-bits respectively. */ + builtin_type->builtin_decfloat + = init_type (TYPE_CODE_DECFLOAT, 32 / 8, + 0, +- "_Decimal32", (struct objfile *) NULL); ++ "_Decimal32", OBJFILE_INTERNAL); + builtin_type->builtin_decdouble + = init_type (TYPE_CODE_DECFLOAT, 64 / 8, + 0, +- "_Decimal64", (struct objfile *) NULL); ++ "_Decimal64", OBJFILE_INTERNAL); + builtin_type->builtin_declong + = init_type (TYPE_CODE_DECFLOAT, 128 / 8, + 0, +- "_Decimal128", (struct objfile *) NULL); ++ "_Decimal128", OBJFILE_INTERNAL); + + /* Pointer/Address types. */ + +@@ -3245,27 +3742,28 @@ gdbtypes_post_init (struct gdbarch *gdbarch) + init_type (TYPE_CODE_INT, + gdbarch_addr_bit (gdbarch) / 8, + TYPE_FLAG_UNSIGNED, +- "__CORE_ADDR", (struct objfile *) NULL); ++ "__CORE_ADDR", OBJFILE_INTERNAL); + + + /* The following set of types is used for symbols with no + debug information. */ + builtin_type->nodebug_text_symbol = + init_type (TYPE_CODE_FUNC, 1, 0, +- "", NULL); ++ "", OBJFILE_INTERNAL); + TYPE_TARGET_TYPE (builtin_type->nodebug_text_symbol) = + builtin_type->builtin_int; + builtin_type->nodebug_data_symbol = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, +- "", NULL); ++ "", OBJFILE_INTERNAL); + builtin_type->nodebug_unknown_symbol = + init_type (TYPE_CODE_INT, 1, 0, +- "", NULL); ++ "", ++ OBJFILE_INTERNAL); + builtin_type->nodebug_tls_symbol = + init_type (TYPE_CODE_INT, + gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0, +- "", NULL); ++ "", OBJFILE_INTERNAL); + + return builtin_type; + } +@@ -3276,6 +3774,9 @@ _initialize_gdbtypes (void) + { + gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init); + ++ type_refc_table = htab_create_alloc (20, type_refc_hash, type_refc_equal, ++ NULL, xcalloc, xfree); ++ + /* FIXME: The following types are architecture-neutral. However, + they contain pointer_type and reference_type fields potentially + caching pointer or reference types that *are* architecture +@@ -3284,47 +3785,47 @@ _initialize_gdbtypes (void) + builtin_type_int0 = + init_type (TYPE_CODE_INT, 0 / 8, + 0, +- "int0_t", (struct objfile *) NULL); ++ "int0_t", OBJFILE_INTERNAL); + builtin_type_int8 = + init_type (TYPE_CODE_INT, 8 / 8, + TYPE_FLAG_NOTTEXT, +- "int8_t", (struct objfile *) NULL); ++ "int8_t", OBJFILE_INTERNAL); + builtin_type_uint8 = + init_type (TYPE_CODE_INT, 8 / 8, + TYPE_FLAG_UNSIGNED | TYPE_FLAG_NOTTEXT, +- "uint8_t", (struct objfile *) NULL); ++ "uint8_t", OBJFILE_INTERNAL); + builtin_type_int16 = + init_type (TYPE_CODE_INT, 16 / 8, + 0, +- "int16_t", (struct objfile *) NULL); ++ "int16_t", OBJFILE_INTERNAL); + builtin_type_uint16 = + init_type (TYPE_CODE_INT, 16 / 8, + TYPE_FLAG_UNSIGNED, +- "uint16_t", (struct objfile *) NULL); ++ "uint16_t", OBJFILE_INTERNAL); + builtin_type_int32 = + init_type (TYPE_CODE_INT, 32 / 8, + 0, +- "int32_t", (struct objfile *) NULL); ++ "int32_t", OBJFILE_INTERNAL); + builtin_type_uint32 = + init_type (TYPE_CODE_INT, 32 / 8, + TYPE_FLAG_UNSIGNED, +- "uint32_t", (struct objfile *) NULL); ++ "uint32_t", OBJFILE_INTERNAL); + builtin_type_int64 = + init_type (TYPE_CODE_INT, 64 / 8, + 0, +- "int64_t", (struct objfile *) NULL); ++ "int64_t", OBJFILE_INTERNAL); + builtin_type_uint64 = + init_type (TYPE_CODE_INT, 64 / 8, + TYPE_FLAG_UNSIGNED, +- "uint64_t", (struct objfile *) NULL); ++ "uint64_t", OBJFILE_INTERNAL); + builtin_type_int128 = + init_type (TYPE_CODE_INT, 128 / 8, + 0, +- "int128_t", (struct objfile *) NULL); ++ "int128_t", OBJFILE_INTERNAL); + builtin_type_uint128 = + init_type (TYPE_CODE_INT, 128 / 8, + TYPE_FLAG_UNSIGNED, +- "uint128_t", (struct objfile *) NULL); ++ "uint128_t", OBJFILE_INTERNAL); + + builtin_type_ieee_single = + build_flt (-1, "builtin_type_ieee_single", floatformats_ieee_single); +@@ -3344,15 +3845,15 @@ _initialize_gdbtypes (void) + builtin_type_void = + init_type (TYPE_CODE_VOID, 1, + 0, +- "void", (struct objfile *) NULL); ++ "void", OBJFILE_INTERNAL); + builtin_type_true_char = + init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, +- "true character", (struct objfile *) NULL); ++ "true character", OBJFILE_INTERNAL); + builtin_type_true_unsigned_char = + init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + TYPE_FLAG_UNSIGNED, +- "true character", (struct objfile *) NULL); ++ "true character", OBJFILE_INTERNAL); + + add_setshow_zinteger_cmd ("overload", no_class, &overload_debug, _("\ + Set debugging of C++ overloading."), _("\ +diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h +index c90b6d7..86df022 100644 +--- a/gdb/gdbtypes.h ++++ b/gdb/gdbtypes.h +@@ -209,6 +209,11 @@ enum type_instance_flag_value + + #define TYPE_TARGET_STUB(t) (TYPE_MAIN_TYPE (t)->flag_target_stub) + ++/* Type needs to be evaluated on each CHECK_TYPEDEF and its results must not be ++ sticky. */ ++ ++#define TYPE_DYNAMIC(t) (TYPE_MAIN_TYPE (t)->flag_dynamic) ++ + /* Static type. If this is set, the corresponding type had + * a static modifier. + * Note: This may be unnecessary, since static data members +@@ -266,6 +271,36 @@ enum type_instance_flag_value + + #define TYPE_NOTTEXT(t) (TYPE_MAIN_TYPE (t)->flag_nottext) + ++/* Is HIGH_BOUND a low-bound relative count (1) or the high bound itself (0)? */ ++ ++#define TYPE_RANGE_HIGH_BOUND_IS_COUNT(range_type) \ ++ (TYPE_MAIN_TYPE (range_type)->flag_range_high_bound_is_count) ++ ++/* Not allocated. TYPE_ALLOCATED(t) must be NULL in such case. If this flag ++ is unset and TYPE_ALLOCATED(t) is NULL then the type is allocated. If this ++ flag is unset and TYPE_ALLOCATED(t) is not NULL then its DWARF block ++ determines the actual allocation state. */ ++ ++#define TYPE_NOT_ALLOCATED(t) (TYPE_MAIN_TYPE (t)->flag_not_allocated) ++ ++/* Not associated. TYPE_ASSOCIATED(t) must be NULL in such case. If this flag ++ is unset and TYPE_ASSOCIATED(t) is NULL then the type is associated. If ++ this flag is unset and TYPE_ASSOCIATED(t) is not NULL then its DWARF block ++ determines the actual association state. */ ++ ++#define TYPE_NOT_ASSOCIATED(t) (TYPE_MAIN_TYPE (t)->flag_not_associated) ++ ++/* Address of the actual data as for DW_AT_data_location. Its dwarf block must ++ not be evaluated unless both TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are ++ false. If TYPE_DATA_LOCATION_IS_ADDR set then TYPE_DATA_LOCATION_ADDR value ++ is the actual data address value. If unset and ++ TYPE_DATA_LOCATION_DWARF_BLOCK is NULL then the value is the normal ++ VALUE_ADDRESS copy. If unset and TYPE_DATA_LOCATION_DWARF_BLOCK is not NULL ++ then its DWARF block determines the actual data address. */ ++ ++#define TYPE_DATA_LOCATION_IS_ADDR(t) \ ++ (TYPE_MAIN_TYPE (t)->flag_data_location_is_addr) ++ + /* Constant type. If this is set, the corresponding type has a + * const modifier. + */ +@@ -352,6 +387,11 @@ struct main_type + unsigned int flag_stub_supported : 1; + unsigned int flag_nottext : 1; + unsigned int flag_fixed_instance : 1; ++ unsigned int flag_dynamic : 1; ++ unsigned int flag_range_high_bound_is_count : 1; ++ unsigned int flag_not_allocated : 1; ++ unsigned int flag_not_associated : 1; ++ unsigned int flag_data_location_is_addr : 1; + + /* Number of fields described for this type. This field appears at + this location because it packs nicely here. */ +@@ -414,6 +454,20 @@ struct main_type + + struct type *target_type; + ++ /* For DW_AT_data_location. */ ++ union ++ { ++ struct dwarf2_locexpr_baton *dwarf_block; ++ CORE_ADDR addr; ++ } ++ data_location; ++ ++ /* For DW_AT_allocated. */ ++ struct dwarf2_locexpr_baton *allocated; ++ ++ /* For DW_AT_associated. */ ++ struct dwarf2_locexpr_baton *associated; ++ + /* For structure and union types, a description of each field. + For set and pascal array types, there is one "field", + whose type is the domain type of the set or array. +@@ -795,9 +849,9 @@ extern void allocate_cplus_struct_type (struct type *); + #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type + #define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type + #define TYPE_CHAIN(thistype) (thistype)->chain +-/* Note that if thistype is a TYPEDEF type, you have to call check_typedef. +- But check_typedef does set the TYPE_LENGTH of the TYPEDEF type, +- so you only have to call check_typedef once. Since allocate_value ++/* Note that if thistype is a TYPEDEF, ARRAY or STRING type, you have to call ++ check_typedef. But check_typedef does set the TYPE_LENGTH of the TYPEDEF ++ type, so you only have to call check_typedef once. Since allocate_value + calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */ + #define TYPE_LENGTH(thistype) (thistype)->length + #define TYPE_OBJFILE(thistype) TYPE_MAIN_TYPE(thistype)->objfile +@@ -807,23 +861,44 @@ extern void allocate_cplus_struct_type (struct type *); + #define TYPE_NFIELDS(thistype) TYPE_MAIN_TYPE(thistype)->nfields + #define TYPE_FIELDS(thistype) TYPE_MAIN_TYPE(thistype)->fields + #define TYPE_TEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->template_args ++#define TYPE_DATA_LOCATION_DWARF_BLOCK(thistype) TYPE_MAIN_TYPE (thistype)->data_location.dwarf_block ++#define TYPE_DATA_LOCATION_ADDR(thistype) TYPE_MAIN_TYPE (thistype)->data_location.addr ++#define TYPE_ALLOCATED(thistype) TYPE_MAIN_TYPE (thistype)->allocated ++#define TYPE_ASSOCIATED(thistype) TYPE_MAIN_TYPE (thistype)->associated + + #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0) + #define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0) + #define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1) +- +-/* Moto-specific stuff for FORTRAN arrays */ +- +-#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \ +- (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),1)) ++#define TYPE_BYTE_STRIDE(range_type) TYPE_FIELD_BITPOS (range_type, 2) ++ ++/* Whether we should use TYPE_FIELD_DWARF_BLOCK (and not TYPE_FIELD_BITPOS). */ ++#define TYPE_RANGE_BOUND_IS_DWARF_BLOCK(range_type, fieldno) \ ++ (TYPE_FIELD_LOC_KIND (range_type, fieldno) == FIELD_LOC_KIND_DWARF_BLOCK) ++#define TYPE_RANGE_BOUND_SET_DWARF_BLOCK(range_type, fieldno) \ ++ (TYPE_FIELD_LOC_KIND (range_type, fieldno) = FIELD_LOC_KIND_DWARF_BLOCK) ++#define TYPE_ARRAY_BOUND_IS_DWARF_BLOCK(array_type, fieldno) \ ++ TYPE_RANGE_BOUND_IS_DWARF_BLOCK (TYPE_INDEX_TYPE (array_type), fieldno) ++ ++/* Unbound arrays, such as GCC array[]; at end of struct. */ ++#define TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED(rangetype) \ ++ TYPE_FIELD_ARTIFICIAL((rangetype),0) ++#define TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED(rangetype) \ ++ TYPE_FIELD_ARTIFICIAL((rangetype),1) + #define TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED(arraytype) \ +- (TYPE_FIELD_ARTIFICIAL(TYPE_INDEX_TYPE((arraytype)),0)) +- +-#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \ +- (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE((arraytype)))) ++ TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype)) ++#define TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED(arraytype) \ ++ TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED (TYPE_INDEX_TYPE (arraytype)) + + #define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \ +- (TYPE_LOW_BOUND(TYPE_INDEX_TYPE((arraytype)))) ++ TYPE_LOW_BOUND (TYPE_INDEX_TYPE (arraytype)) ++#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \ ++ TYPE_HIGH_BOUND (TYPE_INDEX_TYPE (arraytype)) ++/* TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) with a fallback to the ++ element size if no specific stride value is known. */ ++#define TYPE_ARRAY_BYTE_STRIDE_VALUE(arraytype) \ ++ (TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) == 0 \ ++ ? TYPE_LENGTH (TYPE_TARGET_TYPE (arraytype)) \ ++ : TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype))) + + /* C++ */ + +@@ -1078,6 +1153,16 @@ extern struct type *builtin_type_error; + (TYPE_UNSIGNED(t) ? UMIN_OF_SIZE(TYPE_LENGTH(t)) \ + : MIN_OF_SIZE(TYPE_LENGTH(t))) + ++/* Virtual OBJFILE used for builtin types. */ ++#define OBJFILE_INTERNAL ((struct objfile *) 1L) ++ ++/* Virtual OBJFILE used for types allocated by malloc. FIXME: Currently ++ backward compatible with the old NULL value; fix then also init_type. */ ++#define OBJFILE_MALLOC ((struct objfile *) 0L) ++ ++#define OBJFILE_IS_VIRTUAL(objfile) ((objfile) == OBJFILE_INTERNAL \ ++ || (objfile) == OBJFILE_MALLOC) ++ + /* Allocate space for storing data associated with a particular type. + We ensure that the space is allocated using the same mechanism that + was used to allocate the space for the type structure itself. I.E. +@@ -1087,18 +1172,18 @@ extern struct type *builtin_type_error; + builtin types), then the data space will be allocated with xmalloc, + the same as for the type structure. */ + +-#define TYPE_ALLOC(t,size) \ +- (TYPE_OBJFILE (t) != NULL \ +- ? obstack_alloc (&TYPE_OBJFILE (t) -> objfile_obstack, size) \ +- : xmalloc (size)) ++#define TYPE_ALLOC(t,size) \ ++ (OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (t)) \ ++ ? xmalloc (size) \ ++ : obstack_alloc (&TYPE_OBJFILE (t) -> objfile_obstack, size)) + +-#define TYPE_ZALLOC(t,size) \ +- (TYPE_OBJFILE (t) != NULL \ +- ? memset (obstack_alloc (&TYPE_OBJFILE (t)->objfile_obstack, size), \ +- 0, size) \ +- : xzalloc (size)) ++#define TYPE_ZALLOC(t,size) \ ++ (OBJFILE_IS_VIRTUAL (TYPE_OBJFILE (t)) \ ++ ? xzalloc (size) \ ++ : memset (obstack_alloc (&TYPE_OBJFILE (t)->objfile_obstack, size), \ ++ 0, size)) + +-extern struct type *alloc_type (struct objfile *); ++extern struct type *alloc_type (struct objfile *, struct type *); + + extern struct type *init_type (enum type_code, int, int, char *, + struct objfile *); +@@ -1172,6 +1257,16 @@ extern struct type *create_range_type (struct type *, struct type *, int, + extern struct type *create_array_type (struct type *, struct type *, + struct type *); + ++extern CORE_ADDR type_range_any_field_internal (struct type *range_type, ++ int fieldno); ++ ++extern int type_range_high_bound_internal (struct type *range_type); ++ ++extern int type_range_count_bound_internal (struct type *range_type); ++ ++extern CORE_ADDR type_range_byte_stride_internal (struct type *range_type, ++ struct type *element_type); ++ + extern struct type *create_string_type (struct type *, struct type *); + + extern struct type *create_set_type (struct type *, struct type *); +@@ -1263,10 +1358,15 @@ extern void maintenance_print_type (char *, int); + + extern htab_t create_copied_types_hash (struct objfile *objfile); + +-extern struct type *copy_type_recursive (struct objfile *objfile, +- struct type *type, ++extern struct type *copy_type_recursive (struct type *type, + htab_t copied_types); + + extern struct type *copy_type (const struct type *type); + ++extern void type_incref (struct type *type); ++ ++extern void type_decref (struct type *type); ++ ++extern void free_all_types (void); ++ + #endif /* GDBTYPES_H */ +diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c +index 0728866..cc82cb4 100644 +--- a/gdb/jv-lang.c ++++ b/gdb/jv-lang.c +@@ -302,7 +302,7 @@ type_from_class (struct value *clas) + if (type != NULL) + return type; + +- type = alloc_type (objfile); ++ type = alloc_type (objfile, NULL); + TYPE_CODE (type) = TYPE_CODE_STRUCT; + INIT_CPLUS_SPECIFIC (type); + +diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c +index 7cbcc59..e507c3b 100644 +--- a/gdb/mdebugread.c ++++ b/gdb/mdebugread.c +@@ -4696,7 +4696,7 @@ new_type (char *name) + { + struct type *t; + +- t = alloc_type (current_objfile); ++ t = alloc_type (current_objfile, NULL); + TYPE_NAME (t) = name; + TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default; + return t; +diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c +index b905a9e..83c6b48 100644 +--- a/gdb/mi/mi-main.c ++++ b/gdb/mi/mi-main.c +@@ -1317,6 +1317,7 @@ mi_cmd_execute (struct mi_parse *parse) + struct cleanup *cleanup; + int i; + free_all_values (); ++ free_all_types (); + + current_token = xstrdup (parse->token); + cleanup = make_cleanup (free_current_contents, ¤t_token); +diff --git a/gdb/printcmd.c b/gdb/printcmd.c +index a51ba68..55a39f5 100644 +--- a/gdb/printcmd.c ++++ b/gdb/printcmd.c +@@ -878,6 +878,11 @@ print_command_1 (char *exp, int inspect, int voidprint) + else + val = access_value_history (0); + ++ /* Do not try to OBJECT_ADDRESS_SET here anything. We are interested in the ++ source variable base addresses as found by READ_VAR_VALUE. The value here ++ can be already a calculated expression address inappropriate for ++ DW_OP_push_object_address. */ ++ + if (voidprint || (val && value_type (val) && + TYPE_CODE (value_type (val)) != TYPE_CODE_VOID)) + { +diff --git a/gdb/stabsread.c b/gdb/stabsread.c +index 3457784..976a5a7 100644 +--- a/gdb/stabsread.c ++++ b/gdb/stabsread.c +@@ -322,7 +322,7 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) + + if (typenums[0] == -1) + { +- return (alloc_type (objfile)); ++ return (alloc_type (objfile, NULL)); + } + + type_addr = dbx_lookup_type (typenums); +@@ -332,7 +332,7 @@ dbx_alloc_type (int typenums[2], struct objfile *objfile) + We will fill it in later if we find out how. */ + if (*type_addr == 0) + { +- *type_addr = alloc_type (objfile); ++ *type_addr = alloc_type (objfile, NULL); + } + + return (*type_addr); +diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S +new file mode 100644 +index 0000000..66f7a39 +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S +@@ -0,0 +1,455 @@ ++ .file "x86_64-vla-typedef.c" ++ .section .debug_abbrev,"",@progbits ++.Ldebug_abbrev0: ++ .section .debug_info,"",@progbits ++.Ldebug_info0: ++ .section .debug_line,"",@progbits ++.Ldebug_line0: ++ .text ++.Ltext0: ++.globl foo ++ .type foo, @function ++foo: ++.LFB2: ++ .file 1 "x86_64-vla-typedef.c" ++ .loc 1 22 0 ++ pushq %rbp ++.LCFI0: ++ movq %rsp, %rbp ++.LCFI1: ++ subq $64, %rsp ++.LCFI2: ++ movl %edi, -36(%rbp) ++ .loc 1 22 0 ++ movq %rsp, %rax ++ movq %rax, -48(%rbp) ++ .loc 1 23 0 ++ movl -36(%rbp), %edx ++ movslq %edx,%rax ++ subq $1, %rax ++ movq %rax, -24(%rbp) ++ .loc 1 24 0 ++ movslq %edx,%rax ++ addq $15, %rax ++ addq $15, %rax ++ shrq $4, %rax ++ salq $4, %rax ++ subq %rax, %rsp ++ movq %rsp, -56(%rbp) ++ movq -56(%rbp), %rax ++ addq $15, %rax ++ shrq $4, %rax ++ salq $4, %rax ++ movq %rax, -56(%rbp) ++ movq -56(%rbp), %rax ++ movq %rax, -16(%rbp) ++ .loc 1 27 0 ++ movl $0, -4(%rbp) ++ jmp .L2 ++.L3: ++ .loc 1 28 0 ++ movl -4(%rbp), %esi ++ movl -4(%rbp), %eax ++ movl %eax, %ecx ++ movq -16(%rbp), %rdx ++ movslq %esi,%rax ++ movb %cl, (%rdx,%rax) ++ .loc 1 27 0 ++ addl $1, -4(%rbp) ++.L2: ++ movl -4(%rbp), %eax ++ cmpl -36(%rbp), %eax ++ jl .L3 ++ .loc 1 30 0 ++ .globl break_here ++break_here: ++ movq -16(%rbp), %rax ++ movb $0, (%rax) ++ movq -48(%rbp), %rsp ++ .loc 1 31 0 ++ leave ++ ret ++.LFE2: ++ .size foo, .-foo ++ .section .debug_frame,"",@progbits ++.Lframe0: ++ .long .LECIE0-.LSCIE0 ++.LSCIE0: ++ .long 0xffffffff ++ .byte 0x1 ++ .string "" ++ .uleb128 0x1 ++ .sleb128 -8 ++ .byte 0x10 ++ .byte 0xc ++ .uleb128 0x7 ++ .uleb128 0x8 ++ .byte 0x90 ++ .uleb128 0x1 ++ .align 8 ++.LECIE0: ++.LSFDE0: ++ .long .LEFDE0-.LASFDE0 ++.LASFDE0: ++ .long .Lframe0 ++ .quad .LFB2 ++ .quad .LFE2-.LFB2 ++ .byte 0x4 ++ .long .LCFI0-.LFB2 ++ .byte 0xe ++ .uleb128 0x10 ++ .byte 0x86 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x6 ++ .align 8 ++.LEFDE0: ++ .section .eh_frame,"a",@progbits ++.Lframe1: ++ .long .LECIE1-.LSCIE1 ++.LSCIE1: ++ .long 0x0 ++ .byte 0x1 ++ .string "zR" ++ .uleb128 0x1 ++ .sleb128 -8 ++ .byte 0x10 ++ .uleb128 0x1 ++ .byte 0x3 ++ .byte 0xc ++ .uleb128 0x7 ++ .uleb128 0x8 ++ .byte 0x90 ++ .uleb128 0x1 ++ .align 8 ++.LECIE1: ++.LSFDE1: ++ .long .LEFDE1-.LASFDE1 ++.LASFDE1: ++ .long .LASFDE1-.Lframe1 ++ .long .LFB2 ++ .long .LFE2-.LFB2 ++ .uleb128 0x0 ++ .byte 0x4 ++ .long .LCFI0-.LFB2 ++ .byte 0xe ++ .uleb128 0x10 ++ .byte 0x86 ++ .uleb128 0x2 ++ .byte 0x4 ++ .long .LCFI1-.LCFI0 ++ .byte 0xd ++ .uleb128 0x6 ++ .align 8 ++.LEFDE1: ++ .text ++.Letext0: ++ .section .debug_loc,"",@progbits ++.Ldebug_loc0: ++.LLST0: ++ .quad .LFB2-.Ltext0 ++ .quad .LCFI0-.Ltext0 ++ .value 0x2 ++ .byte 0x77 ++ .sleb128 8 ++ .quad .LCFI0-.Ltext0 ++ .quad .LCFI1-.Ltext0 ++ .value 0x2 ++ .byte 0x77 ++ .sleb128 16 ++ .quad .LCFI1-.Ltext0 ++ .quad .LFE2-.Ltext0 ++ .value 0x2 ++ .byte 0x76 ++ .sleb128 16 ++ .quad 0x0 ++ .quad 0x0 ++ .section .debug_info ++ .long .Ldebug_end - .Ldebug_start ++.Ldebug_start: ++ .value 0x2 ++ .long .Ldebug_abbrev0 ++ .byte 0x8 ++ .uleb128 0x1 ++ .long .LASF2 ++ .byte 0x1 ++ .long .LASF3 ++ .long .LASF4 ++ .quad .Ltext0 ++ .quad .Letext0 ++ .long .Ldebug_line0 ++ .uleb128 0x2 ++ .byte 0x1 ++ .string "foo" ++ .byte 0x1 ++ .byte 0x16 ++ .byte 0x1 ++ .quad .LFB2 ++ .quad .LFE2 ++ .long .LLST0 ++ .long 0x83 ++ .uleb128 0x3 ++ .long .LASF5 ++ .byte 0x1 ++ .byte 0x15 ++ .long 0x83 ++ .byte 0x2 ++ .byte 0x91 ++ .sleb128 -52 ++.Ltag_typedef: ++ .uleb128 0x4 ++ .long .LASF6 ++ .byte 0x1 ++ .byte 0x17 ++ .long .Ltag_array_type - .debug_info ++ .uleb128 0x5 /* Abbrev Number: 5 (DW_TAG_variable) */ ++ .long .LASF0 ++ .byte 0x1 ++ .byte 0x18 ++#if 1 ++ .long .Ltag_typedef - .debug_info ++#else ++ /* Debugging only: Skip the typedef indirection. */ ++ .long .Ltag_array_type - .debug_info ++#endif ++ /* DW_AT_location: DW_FORM_block1: start */ ++ .byte 0x3 ++ .byte 0x91 ++ .sleb128 -32 ++#if 0 ++ .byte 0x6 /* DW_OP_deref */ ++#else ++ .byte 0x96 /* DW_OP_nop */ ++#endif ++ /* DW_AT_location: DW_FORM_block1: end */ ++ .uleb128 0x6 ++ .string "i" ++ .byte 0x1 ++ .byte 0x19 ++ .long 0x83 ++ .byte 0x2 ++ .byte 0x91 ++ .sleb128 -20 ++ .byte 0x0 ++ .uleb128 0x7 ++ .byte 0x4 ++ .byte 0x5 ++ .string "int" ++.Ltag_array_type: ++ .uleb128 0x8 /* Abbrev Number: 8 (DW_TAG_array_type) */ ++ .long 0xa0 + (2f - 1f) /* DW_AT_type: DW_FORM_ref4 */ ++ .long 0x9d + (2f - 1f) /* DW_AT_sibling: DW_FORM_ref4 */ ++1: /* DW_AT_data_location: DW_FORM_block1: start */ ++ .byte 2f - 3f /* length */ ++3: ++ .byte 0x97 /* DW_OP_push_object_address */ ++ .byte 0x6 /* DW_OP_deref */ ++2: /* DW_AT_data_location: DW_FORM_block1: end */ ++ .uleb128 0x9 ++ .long 0x9d + (2b - 1b) /* DW_AT_type: DW_FORM_ref4 */ ++ .byte 0x3 ++ .byte 0x91 ++ .sleb128 -40 ++ .byte 0x6 ++ .byte 0x0 ++ .uleb128 0xa ++ .byte 0x8 ++ .byte 0x7 ++ .uleb128 0xb ++ .byte 0x1 ++ .byte 0x6 ++ .long .LASF1 ++ .byte 0x0 ++.Ldebug_end: ++ .section .debug_abbrev ++ .uleb128 0x1 ++ .uleb128 0x11 ++ .byte 0x1 ++ .uleb128 0x25 ++ .uleb128 0xe ++ .uleb128 0x13 ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x1b ++ .uleb128 0xe ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x10 ++ .uleb128 0x6 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x2 ++ .uleb128 0x2e ++ .byte 0x1 ++ .uleb128 0x3f ++ .uleb128 0xc ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x27 ++ .uleb128 0xc ++ .uleb128 0x11 ++ .uleb128 0x1 ++ .uleb128 0x12 ++ .uleb128 0x1 ++ .uleb128 0x40 ++ .uleb128 0x6 ++ .uleb128 0x1 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x5 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x4 ++ .uleb128 0x16 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x5 ++ .uleb128 0x34 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0xe ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x6 ++ .uleb128 0x34 ++ .byte 0x0 ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .uleb128 0x3a ++ .uleb128 0xb ++ .uleb128 0x3b ++ .uleb128 0xb ++ .uleb128 0x49 ++ .uleb128 0x13 ++ .uleb128 0x2 ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x7 ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0x8 ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x8 /* Abbrev Number: 8 (DW_TAG_array_type) */ ++ .uleb128 0x1 ++ .byte 0x1 ++ .uleb128 0x49 /* DW_AT_type */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x1 /* DW_AT_sibling */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x50 /* DW_AT_data_location */ ++ .uleb128 0xa /* DW_FORM_block1 */ ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0x9 ++ .uleb128 0x21 ++ .byte 0x0 ++ .uleb128 0x49 /* DW_AT_type */ ++ .uleb128 0x13 /* DW_FORM_ref4 */ ++ .uleb128 0x2f ++ .uleb128 0xa ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0xa ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .byte 0x0 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0x24 ++ .byte 0x0 ++ .uleb128 0xb ++ .uleb128 0xb ++ .uleb128 0x3e ++ .uleb128 0xb ++ .uleb128 0x3 ++ .uleb128 0xe ++ .byte 0x0 ++ .byte 0x0 ++ .byte 0x0 ++ .section .debug_pubnames,"",@progbits ++ .long 0x16 ++ .value 0x2 ++ .long .Ldebug_info0 ++ .long 0xa8 ++ .long 0x2d ++ .string "foo" ++ .long 0x0 ++ .section .debug_aranges,"",@progbits ++ .long 0x2c ++ .value 0x2 ++ .long .Ldebug_info0 ++ .byte 0x8 ++ .byte 0x0 ++ .value 0x0 ++ .value 0x0 ++ .quad .Ltext0 ++ .quad .Letext0-.Ltext0 ++ .quad 0x0 ++ .quad 0x0 ++ .section .debug_str,"MS",@progbits,1 ++.LASF0: ++ .string "array" ++.LASF5: ++ .string "size" ++.LASF3: ++ .string "x86_64-vla-typedef.c" ++.LASF6: ++ .string "array_t" ++.LASF1: ++ .string "char" ++.LASF4: ++ .string "gdb.arch" ++.LASF2: ++ .string "GNU C 4.3.2 20081105 (Red Hat 4.3.2-7)" ++ .ident "GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)" ++ .section .note.GNU-stack,"",@progbits +diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c +new file mode 100644 +index 0000000..b809c4e +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c +@@ -0,0 +1,43 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 Free Software Foundation, Inc. ++ ++ 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 . */ ++ ++#if 0 ++ ++void ++foo (int size) ++{ ++ typedef char array_t[size]; ++ array_t array; ++ int i; ++ ++ for (i = 0; i < size; i++) ++ array[i] = i; ++ ++ array[0] = 0; /* break-here */ ++} ++ ++#else ++ ++int ++main (void) ++{ ++ foo (26); ++ foo (78); ++ return 0; ++} ++ ++#endif +diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp +new file mode 100644 +index 0000000..b05411e +--- /dev/null ++++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp +@@ -0,0 +1,64 @@ ++# Copyright 2009 Free Software Foundation, Inc. ++ ++# 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 . ++ ++# Test DW_AT_data_location accessed through DW_TAG_typedef intermediate. ++ ++if ![istarget "x86_64-*-*"] then { ++ verbose "Skipping over gdb.arch/x86_64-vla-typedef.exp test made only for x86_64." ++ return ++} ++ ++set testfile x86_64-vla-typedef ++set srcasmfile ${testfile}-foo.S ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++set binobjfile ${objdir}/${subdir}/${testfile}-foo.o ++if { [gdb_compile "${srcdir}/${subdir}/${srcasmfile}" "${binobjfile}" object {}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${binobjfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto_main] { ++ untested x86_64-vla-typedef ++ return -1 ++} ++ ++gdb_breakpoint "break_here" ++ ++gdb_continue_to_breakpoint "break_here" ++ ++gdb_test "whatis array" "type = array_t" "first: whatis array" ++ ++gdb_test "ptype array" "type = char \\\[26\\\]" "first: ptype array" ++ ++gdb_test "p array\[1\]" "\\$\[0-9\] = 1 '\\\\001'" ++gdb_test "p array\[2\]" "\\$\[0-9\] = 2 '\\\\002'" ++gdb_test "p array\[3\]" "\\$\[0-9\] = 3 '\\\\003'" ++gdb_test "p array\[4\]" "\\$\[0-9\] = 4 '\\\\004'" ++ ++gdb_continue_to_breakpoint "break_here" ++ ++gdb_test "whatis array" "type = array_t" "second: whatis array" ++ ++gdb_test "ptype array" "type = char \\\[78\\\]" "second: ptype array" +diff --git a/gdb/testsuite/gdb.base/vla-overflow.c b/gdb/testsuite/gdb.base/vla-overflow.c +new file mode 100644 +index 0000000..c5d5ee0 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla-overflow.c +@@ -0,0 +1,30 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 Free Software Foundation, Inc. ++ ++ 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 . */ ++ ++#include ++ ++int ++main (int argc, char **argv) ++{ ++ int array[argc]; ++ ++ array[0] = array[0]; ++ ++ abort (); ++ ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/vla-overflow.exp b/gdb/testsuite/gdb.base/vla-overflow.exp +new file mode 100644 +index 0000000..7203a48 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla-overflow.exp +@@ -0,0 +1,108 @@ ++# Copyright 2008 Free Software Foundation, Inc. ++ ++# 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 . ++ ++# We could crash in: ++# #0 block_linkage_function (bl=0x0) at ../../gdb/block.c:69 ++# #1 in dwarf_block_get_frame_base (...) at ../../gdb/dwarf2block.c:97 ++# 97 framefunc = block_linkage_function (get_frame_block (frame, NULL)); ++# #2 in execute_stack_op (...) at ../../gdb/dwarf2expr.c:496 ++# #3 in dwarf_block_exec_core () at ../../gdb/dwarf2block.c:156 ++# #4 dwarf_block_exec (...) at ../../gdb/dwarf2block.c:206 ++# #5 in range_type_count_bound_internal (...) at ../../gdb/gdbtypes.c:1430 ++# #6 in create_array_type (...) at ../../gdb/gdbtypes.c:840 ++# ... ++# #21 in psymtab_to_symtab (...) at ../../gdb/symfile.c:292 ++# ... ++# #29 in backtrace_command_1 () at ../../gdb/stack.c:1273 ++ ++set testfile vla-overflow ++set shfile ${objdir}/${subdir}/${testfile}-gdb.sh ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++set f [open "|getconf PAGESIZE" "r"] ++gets $f pagesize ++close $f ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set pid_of_gdb [exp_pid -i [board_info host fileid]] ++ ++if { [runto_main] < 0 } { ++ untested vla-overflow ++ return -1 ++} ++ ++# Get the GDB memory size when we stay at main. ++ ++proc memory_v_pages_get {} { ++ global pid_of_gdb pagesize ++ set fd [open "/proc/$pid_of_gdb/statm"] ++ gets $fd line ++ close $fd ++ # number of pages of virtual memory ++ scan $line "%d" drs ++ return $drs ++} ++ ++set pages_found [memory_v_pages_get] ++ ++set mb_reserve 10 ++verbose -log "pages_found = $pages_found, mb_reserve = $mb_reserve" ++set kb_found [expr $pages_found * $pagesize / 1024] ++set kb_permit [expr $kb_found + 1 * 1024 + $mb_reserve * 1024] ++verbose -log "kb_found = $kb_found, kb_permit = $kb_permit" ++ ++# Create the ulimit wrapper. ++set f [open $shfile "w"] ++puts $f "#! /bin/sh" ++puts $f "ulimit -v $kb_permit" ++puts $f "exec $GDB \"\$@\"" ++close $f ++remote_exec host "chmod +x $shfile" ++ ++gdb_exit ++set GDBold $GDB ++set GDB "$shfile" ++gdb_start ++set GDB $GDBold ++ ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set pid_of_gdb [exp_pid -i [board_info host fileid]] ++ ++# Check the size again after the second run. ++# We must not stop in main as it would cache `array' and never crash later. ++ ++gdb_run_cmd ++ ++verbose -log "kb_found before abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" ++ ++gdb_test "" "Program received signal SIGABRT, Aborted..*" "Enter abort()" ++ ++verbose -log "kb_found in abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" ++ ++# `abort' can get expressed as `*__GI_abort'. ++gdb_test "bt" "in \[^ \]*abort \\(.* in main \\(.*" "Backtrace after abort()" ++ ++verbose -log "kb_found in bt after abort() = [expr [memory_v_pages_get] * $pagesize / 1024]" +diff --git a/gdb/testsuite/gdb.base/vla.c b/gdb/testsuite/gdb.base/vla.c +new file mode 100644 +index 0000000..e1f3ed1 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla.c +@@ -0,0 +1,55 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2008 Free Software Foundation, Inc. ++ ++ 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 . */ ++ ++#include ++ ++void ++marker (void) ++{ ++} ++ ++void ++bar (char *a, char *b, char *c, int size) ++{ ++ memset (a, '1', size); ++ memset (b, '2', size); ++ memset (c, '3', 48); ++} ++ ++void ++foo (int size) ++{ ++ char temp1[size]; ++ char temp3[48]; ++ ++ temp1[size - 1] = '\0'; ++ { ++ char temp2[size]; ++ ++ bar (temp1, temp2, temp3, size); ++ ++ marker (); /* break-here */ ++ } ++} ++ ++int ++main (void) ++{ ++ foo (26); ++ foo (78); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.base/vla.exp b/gdb/testsuite/gdb.base/vla.exp +new file mode 100644 +index 0000000..5da7378 +--- /dev/null ++++ b/gdb/testsuite/gdb.base/vla.exp +@@ -0,0 +1,62 @@ ++# Copyright 2008 Free Software Foundation, Inc. ++ ++# 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 . ++ ++set testfile vla ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto_main] { ++ untested vla ++ return -1 ++} ++ ++gdb_breakpoint [gdb_get_line_number "break-here"] ++ ++gdb_continue_to_breakpoint "break-here" ++ ++gdb_test "whatis temp1" "type = char \\\[variable\\\]" "first: whatis temp1" ++gdb_test "whatis temp2" "type = char \\\[variable\\\]" "first: whatis temp2" ++gdb_test "whatis temp3" "type = char \\\[48\\\]" "first: whatis temp3" ++ ++gdb_test "ptype temp1" "type = char \\\[26\\\]" "first: ptype temp1" ++gdb_test "ptype temp2" "type = char \\\[26\\\]" "first: ptype temp2" ++gdb_test "ptype temp3" "type = char \\\[48\\\]" "first: ptype temp3" ++ ++gdb_test "p temp1" " = '1' " "first: print temp1" ++gdb_test "p temp2" " = '2' " "first: print temp2" ++gdb_test "p temp3" " = '3' " "first: print temp3" ++ ++gdb_continue_to_breakpoint "break-here" ++ ++gdb_test "whatis temp1" "type = char \\\[variable\\\]" "second: whatis temp1" ++gdb_test "whatis temp2" "type = char \\\[variable\\\]" "second: whatis temp2" ++gdb_test "whatis temp3" "type = char \\\[48\\\]" "second: whatis temp3" ++ ++gdb_test "ptype temp1" "type = char \\\[78\\\]" "second: ptype temp1" ++gdb_test "ptype temp2" "type = char \\\[78\\\]" "second: ptype temp2" ++gdb_test "ptype temp3" "type = char \\\[48\\\]" "second: ptype temp3" ++ ++gdb_test "p temp1" " = '1' " "second: print temp1" ++gdb_test "p temp2" " = '2' " "second: print temp2" ++gdb_test "p temp3" " = '3' " "second: print temp3" +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.c b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c +new file mode 100644 +index 0000000..1f02d90 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c +@@ -0,0 +1,42 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2004 Free Software Foundation, Inc. ++ ++ 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 2 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, write to the Free Software ++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ USA. */ ++ ++ ++/* The function `func1' traced into must have debug info on offset > 0; ++ (DW_UNSND (attr)). This is the reason of `func0' existence. */ ++ ++void ++func0(int a, int b) ++{ ++} ++ ++/* `func1' being traced into must have some arguments to dump. */ ++ ++void ++func1(int a, int b) ++{ ++ func0 (a,b); ++} ++ ++int ++main(void) ++{ ++ func1 (1, 2); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp +new file mode 100644 +index 0000000..1c6e84a +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp +@@ -0,0 +1,79 @@ ++# Copyright 2006 Free Software Foundation, Inc. ++ ++# 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 2 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, write to the Free Software ++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++# Minimal DWARF-2 unit test ++ ++# This test can only be run on targets which support DWARF-2. ++# For now pick a sampling of likely targets. ++if {![istarget *-*-linux*] ++ && ![istarget *-*-gnu*] ++ && ![istarget *-*-elf*] ++ && ![istarget *-*-openbsd*] ++ && ![istarget arm-*-eabi*] ++ && ![istarget powerpc-*-eabi*]} { ++ return 0 ++} ++ ++set testfile "dw2-stripped" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile}.x ++ ++remote_exec build "rm -f ${binfile}" ++ ++# get the value of gcc_compiled ++if [get_compiler_info ${binfile}] { ++ return -1 ++} ++ ++# This test can only be run on gcc as we use additional_flags=FIXME ++if {$gcc_compiled == 0} { ++ return 0 ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-ggdb3}] != "" } { ++ return -1 ++} ++ ++remote_exec build "objcopy -R .debug_loc ${binfile}" ++set strip_output [remote_exec build "objdump -h ${binfile}"] ++ ++set test "stripping test file preservation" ++if [ regexp ".debug_info " $strip_output] { ++ pass "$test (.debug_info preserved)" ++} else { ++ fail "$test (.debug_info got also stripped)" ++} ++ ++set test "stripping test file functionality" ++if [ regexp ".debug_loc " $strip_output] { ++ fail "$test (.debug_loc still present)" ++} else { ++ pass "$test (.debug_loc stripped)" ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# For C programs, "start" should stop in main(). ++ ++gdb_test "start" \ ++ ".*main \\(\\) at .*" \ ++ "start" ++gdb_test "step" \ ++ "func.* \\(.*\\) at .*" \ ++ "step" +diff --git a/gdb/testsuite/gdb.fortran/dynamic.exp b/gdb/testsuite/gdb.fortran/dynamic.exp +new file mode 100644 +index 0000000..77a1203 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/dynamic.exp +@@ -0,0 +1,156 @@ ++# Copyright 2007 Free Software Foundation, Inc. ++ ++# 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 2 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, write to the Free Software ++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++# This file was written by Jan Kratochvil . ++ ++# This file is part of the gdb testsuite. It contains tests for dynamically ++# allocated Fortran arrays. ++# It depends on the GCC dynamic Fortran arrays DWARF support: ++# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22244 ++ ++set testfile "dynamic" ++set srcfile ${testfile}.f90 ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto MAIN__] then { ++ perror "couldn't run to breakpoint MAIN__" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "varx-init"] ++gdb_continue_to_breakpoint "varx-init" ++gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx unallocated" ++gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx unallocated" ++gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) unallocated" ++gdb_test "p varx(1,5,17)=1" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17)=1 unallocated" ++gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) unallocated" ++ ++gdb_breakpoint [gdb_get_line_number "varx-allocated"] ++gdb_continue_to_breakpoint "varx-allocated" ++# $1 = (( ( 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0) --- , 0) ) ( ( 0, 0, ...) ...) ...) ++gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx allocated" ++# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1. ++gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varx allocated" ++ ++gdb_breakpoint [gdb_get_line_number "varx-filled"] ++gdb_continue_to_breakpoint "varx-filled" ++gdb_test "p varx(2, 5, 17)" "\\$\[0-9\]* = 6" ++gdb_test "p varx(1, 5, 17)" "\\$\[0-9\]* = 7" ++gdb_test "p varx(2, 6, 18)" "\\$\[0-9\]* = 8" ++gdb_test "p varx(6, 15, 28)" "\\$\[0-9\]* = 9" ++# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type. ++gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv unassociated" ++gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv unassociated" ++ ++gdb_breakpoint [gdb_get_line_number "varv-associated"] ++gdb_continue_to_breakpoint "varv-associated" ++gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 6" "p varx(3, 7, 19) with varv associated" ++gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 6" "p varv(3, 7, 19) associated" ++# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1. ++gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varv associated" ++gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx with varv associated" ++# Intel Fortran Compiler 10.1.008 uses the pointer type. ++gdb_test "ptype varv" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)\\)?" "ptype varv associated" ++ ++gdb_breakpoint [gdb_get_line_number "varv-filled"] ++gdb_continue_to_breakpoint "varv-filled" ++gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 10" "p varx(3, 7, 19) with varv filled" ++gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 10" "p varv(3, 7, 19) filled" ++ ++gdb_breakpoint [gdb_get_line_number "varv-deassociated"] ++gdb_continue_to_breakpoint "varv-deassociated" ++# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type. ++gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv deassociated" ++gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv deassociated" ++gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varv deassociated" ++gdb_test "p varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\." ++gdb_test "ptype varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\." ++ ++gdb_breakpoint [gdb_get_line_number "varx-deallocated"] ++gdb_continue_to_breakpoint "varx-deallocated" ++gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx deallocated" ++gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx deallocated" ++gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varx deallocated" ++gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) deallocated" ++gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) deallocated" ++ ++gdb_breakpoint [gdb_get_line_number "vary-passed"] ++gdb_continue_to_breakpoint "vary-passed" ++# $1 = (( ( 1, 1, 1, 1, 1, 1) ( 1, 1, 1, 1, 1, 1) --- , 1) ) ( ( 1, 1, ...) ...) ...) ++gdb_test "p vary" "\\$\[0-9\]* = \\(\[()1, .\]*\\)" ++ ++gdb_breakpoint [gdb_get_line_number "vary-filled"] ++gdb_continue_to_breakpoint "vary-filled" ++gdb_test "ptype vary" "type = real(\\(kind=4\\)|\\*4) \\(10,10\\)" ++gdb_test "p vary(1, 1)" "\\$\[0-9\]* = 8" ++gdb_test "p vary(2, 2)" "\\$\[0-9\]* = 9" ++gdb_test "p vary(1, 3)" "\\$\[0-9\]* = 10" ++# $1 = (( ( 3, 3, 3, 3, 3, 3) ( 3, 3, 3, 3, 3, 3) --- , 3) ) ( ( 3, 3, ...) ...) ...) ++gdb_test "p varw" "\\$\[0-9\]* = \\(\[()3, .\]*\\)" ++ ++gdb_breakpoint [gdb_get_line_number "varw-almostfilled"] ++gdb_continue_to_breakpoint "varw-almostfilled" ++gdb_test "ptype varw" "type = real(\\(kind=4\\)|\\*4) \\(5,4,3\\)" ++gdb_test "p varw(3,1,1)=1" "\\$\[0-9\]* = 1" ++# $1 = (( ( 6, 5, 1, 5, 5, 5) ( 5, 5, 5, 5, 5, 5) --- , 5) ) ( ( 5, 5, ...) ...) ...) ++gdb_test "p varw" "\\$\[0-9\]* = \\( *\\( *\\( *6, *5, *1,\[()5, .\]*\\)" "p varw filled" ++# "up" works with GCC but other Fortran compilers may copy the values into the ++# outer function only on the exit of the inner function. ++gdb_test "finish" ".*call bar \\(y, x\\)" ++gdb_test "p z(2,4,5)" "\\$\[0-9\]* = 3" ++gdb_test "p z(2,4,6)" "\\$\[0-9\]* = 6" ++gdb_test "p z(2,4,7)" "\\$\[0-9\]* = 5" ++gdb_test "p z(4,4,6)" "\\$\[0-9\]* = 1" ++ ++gdb_breakpoint [gdb_get_line_number "varz-almostfilled"] ++gdb_continue_to_breakpoint "varz-almostfilled" ++# GCC uses the pointer type here, Intel Fortran Compiler 10.1.008 does not. ++gdb_test "ptype varz" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(\\*\\)\\)?" ++# Intel Fortran Compiler 10.1.008 has a bug here - (2:11,7:7) ++# as it produces DW_AT_lower_bound == DW_AT_upper_bound == 7. ++gdb_test "ptype vart" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(2:11,7:\\*\\)\\)?" ++gdb_test "p varz" "\\$\[0-9\]* = \\(\\)" ++gdb_test "p vart" "\\$\[0-9\]* = \\(\\)" ++gdb_test "p varz(3)" "\\$\[0-9\]* = 4" ++# maps to foo::vary(1,1) ++gdb_test "p vart(2,7)" "\\$\[0-9\]* = 8" ++# maps to foo::vary(2,2) ++gdb_test "p vart(3,8)" "\\$\[0-9\]* = 9" ++# maps to foo::vary(1,3) ++gdb_test "p vart(2,9)" "\\$\[0-9\]* = 10" ++ ++set test "quit #1" ++gdb_test_multiple "quit" $test { ++ -re "The program is running. Quit anyway \\(and kill it\\)\\? \\(y or n\\) " { ++ pass $test ++ } ++} ++set test "quit #2" ++gdb_test_multiple "y" $test { ++ eof { ++ pass $test ++ } ++} +diff --git a/gdb/testsuite/gdb.fortran/dynamic.f90 b/gdb/testsuite/gdb.fortran/dynamic.f90 +new file mode 100644 +index 0000000..0f43564 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/dynamic.f90 +@@ -0,0 +1,98 @@ ++! Copyright 2007 Free Software Foundation, Inc. ++! ++! 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 2 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, write to the Free Software ++! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++! ++! Ihis file is the Fortran source file for dynamic.exp. ++! Original file written by Jakub Jelinek . ++! Modified for the GDB testcase by Jan Kratochvil . ++ ++subroutine baz ++ real, target, allocatable :: varx (:, :, :) ++ real, pointer :: varv (:, :, :) ++ real, target :: varu (1, 2, 3) ++ logical :: l ++ allocate (varx (1:6, 5:15, 17:28)) ! varx-init ++ l = allocated (varx) ++ varx(:, :, :) = 6 ! varx-allocated ++ varx(1, 5, 17) = 7 ++ varx(2, 6, 18) = 8 ++ varx(6, 15, 28) = 9 ++ varv => varx ! varx-filled ++ l = associated (varv) ++ varv(3, 7, 19) = 10 ! varv-associated ++ varv => null () ! varv-filled ++ l = associated (varv) ++ deallocate (varx) ! varv-deassociated ++ l = allocated (varx) ++ varu(:, :, :) = 10 ! varx-deallocated ++ allocate (varv (1:6, 5:15, 17:28)) ++ l = associated (varv) ++ varv(:, :, :) = 6 ++ varv(1, 5, 17) = 7 ++ varv(2, 6, 18) = 8 ++ varv(6, 15, 28) = 9 ++ deallocate (varv) ++ l = associated (varv) ++ varv => varu ++ varv(1, 1, 1) = 6 ++ varv(1, 2, 3) = 7 ++ l = associated (varv) ++end subroutine baz ++subroutine foo (vary, varw) ++ real :: vary (:, :) ++ real :: varw (:, :, :) ++ vary(:, :) = 4 ! vary-passed ++ vary(1, 1) = 8 ++ vary(2, 2) = 9 ++ vary(1, 3) = 10 ++ varw(:, :, :) = 5 ! vary-filled ++ varw(1, 1, 1) = 6 ++ varw(2, 2, 2) = 7 ! varw-almostfilled ++end subroutine foo ++subroutine bar (varz, vart) ++ real :: varz (*) ++ real :: vart (2:11, 7:*) ++ varz(1:3) = 4 ++ varz(2) = 5 ! varz-almostfilled ++ vart(2,7) = vart(2,7) ++end subroutine bar ++program test ++ interface ++ subroutine foo (vary, varw) ++ real :: vary (:, :) ++ real :: varw (:, :, :) ++ end subroutine ++ end interface ++ interface ++ subroutine bar (varz, vart) ++ real :: varz (*) ++ real :: vart (2:11, 7:*) ++ end subroutine ++ end interface ++ real :: x (10, 10), y (5), z(8, 8, 8) ++ x(:,:) = 1 ++ y(:) = 2 ++ z(:,:,:) = 3 ++ call baz ++ call foo (x, z(2:6, 4:7, 6:8)) ++ call bar (y, x) ++ if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort ++ if (x (1, 3) .ne. 10) call abort ++ if (z (2, 4, 6) .ne. 6 .or. z (3, 5, 7) .ne. 7 .or. z (2, 4, 7) .ne. 5) call abort ++ if (any (y .ne. (/4, 5, 4, 2, 2/))) call abort ++ call foo (transpose (x), z) ++ if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort ++ if (x (3, 1) .ne. 10) call abort ++end +diff --git a/gdb/testsuite/gdb.fortran/string.exp b/gdb/testsuite/gdb.fortran/string.exp +new file mode 100644 +index 0000000..ab72206 +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/string.exp +@@ -0,0 +1,72 @@ ++# Copyright 2008 Free Software Foundation, Inc. ++ ++# 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 2 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, write to the Free Software ++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++# This file was written by Jan Kratochvil . ++ ++# This file is part of the gdb testsuite. It contains tests for Fortran ++# strings with dynamic length. ++ ++set testfile "string" ++set srcfile ${testfile}.f90 ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } { ++ untested "Couldn't compile ${srcfile}" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++if ![runto MAIN__] then { ++ perror "couldn't run to breakpoint MAIN__" ++ continue ++} ++ ++gdb_breakpoint [gdb_get_line_number "var-init"] ++gdb_continue_to_breakpoint "var-init" ++gdb_test "ptype c" "type = character(\\(kind=1\\)|\\*1)" ++gdb_test "ptype d" "type = character(\\(kind=8\\)|\\*8)" ++gdb_test "ptype e" "type = character(\\(kind=4\\)|\\*4)" ++gdb_test "ptype f" "type = character(\\(kind=4\\)|\\*4) \\(7,8:10\\)" ++gdb_test "ptype *e" "Attempt to take contents of a non-pointer value." ++gdb_test "ptype *f" "type = character(\\(kind=4\\)|\\*4) \\(7\\)" ++gdb_test "p c" "\\$\[0-9\]* = 'c'" ++gdb_test "p d" "\\$\[0-9\]* = 'd '" ++gdb_test "p e" "\\$\[0-9\]* = 'g '" ++gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\( 'h ', 'h ', 'h ', 'h ', 'h ', 'h ', 'h '\\) \\)" ++gdb_test "p *e" "Attempt to take contents of a non-pointer value." ++gdb_test "p *f" "Attempt to take contents of a non-pointer value." ++ ++gdb_breakpoint [gdb_get_line_number "var-finish"] ++gdb_continue_to_breakpoint "var-finish" ++gdb_test "p e" "\\$\[0-9\]* = 'e '" "p e re-set" ++gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'f ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\( 'f2 ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\( 'f ', 'f ', 'f ', 'f ', 'f ', 'f ', 'f '\\) \\)" "p *f re-set" ++ ++set test "quit #1" ++gdb_test_multiple "quit" $test { ++ -re "The program is running. Quit anyway \\(and kill it\\)\\? \\(y or n\\) " { ++ pass $test ++ } ++} ++set test "quit #2" ++gdb_test_multiple "y" $test { ++ eof { ++ pass $test ++ } ++} +diff --git a/gdb/testsuite/gdb.fortran/string.f90 b/gdb/testsuite/gdb.fortran/string.f90 +new file mode 100644 +index 0000000..226dc5d +--- /dev/null ++++ b/gdb/testsuite/gdb.fortran/string.f90 +@@ -0,0 +1,37 @@ ++! Copyright 2008 Free Software Foundation, Inc. ++! ++! 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 2 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, write to the Free Software ++! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++! ++! Ihis file is the Fortran source file for dynamic.exp. ++! Original file written by Jakub Jelinek . ++! Modified for the GDB testcase by Jan Kratochvil . ++ ++subroutine foo (e, f) ++ character (len=1) :: c ++ character (len=8) :: d ++ character (len=*) :: e ++ character (len=*) :: f (1:7, 8:10) ++ c = 'c' ++ d = 'd' ++ e = 'e' ! var-init ++ f = 'f' ++ f(1,9) = 'f2' ++ c = 'c' ! var-finish ++end subroutine foo ++ character (len=4) :: g, h (1:7, 8:10) ++ g = 'g' ++ h = 'h' ++ call foo (g, h) ++end +diff --git a/gdb/top.c b/gdb/top.c +index d5ef706..6045e21 100644 +--- a/gdb/top.c ++++ b/gdb/top.c +@@ -377,6 +377,7 @@ execute_command (char *p, int from_tty) + } + + free_all_values (); ++ free_all_types (); + + /* Force cleanup of any alloca areas if using C alloca instead of + a builtin alloca. */ +diff --git a/gdb/typeprint.c b/gdb/typeprint.c +index 1f824fa..60a4c5b 100644 +--- a/gdb/typeprint.c ++++ b/gdb/typeprint.c +@@ -35,6 +35,7 @@ + #include "gdb_string.h" + #include "exceptions.h" + #include "valprint.h" ++#include "dwarf2loc.h" + #include + + extern void _initialize_typeprint (void); +@@ -76,6 +77,9 @@ void + type_print (struct type *type, char *varstring, struct ui_file *stream, + int show) + { ++ if (show >= 0) ++ type = check_typedef (type); ++ + LA_PRINT_TYPE (type, varstring, stream, show, 0); + } + +@@ -115,7 +119,8 @@ whatis_exp (char *exp, int show) + { + struct expression *expr; + struct value *val; +- struct cleanup *old_chain = NULL; ++ /* Required at least for the object_address_set call. */ ++ struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + struct type *real_type = NULL; + struct type *type; + int full = 0; +@@ -126,12 +131,13 @@ whatis_exp (char *exp, int show) + if (exp) + { + expr = parse_expression (exp); +- old_chain = make_cleanup (free_current_contents, &expr); ++ make_cleanup (free_current_contents, &expr); + val = evaluate_type (expr); + } + else + val = access_value_history (0); + ++ object_address_set (VALUE_ADDRESS (val)); + type = value_type (val); + + get_user_print_options (&opts); +@@ -168,8 +174,7 @@ whatis_exp (char *exp, int show) + type_print (type, "", gdb_stdout, show); + printf_filtered ("\n"); + +- if (exp) +- do_cleanups (old_chain); ++ do_cleanups (old_chain); + } + + static void +diff --git a/gdb/valarith.c b/gdb/valarith.c +index f38cdb8..8e103cf 100644 +--- a/gdb/valarith.c ++++ b/gdb/valarith.c +@@ -164,9 +164,9 @@ an integer nor a pointer of the same type.")); + struct value * + value_subscript (struct value *array, struct value *idx) + { +- struct value *bound; + int c_style = current_language->c_style_arrays; + struct type *tarray; ++ LONGEST index = value_as_long (idx); + + array = coerce_ref (array); + tarray = check_typedef (value_type (array)); +@@ -179,13 +179,26 @@ value_subscript (struct value *array, struct value *idx) + get_discrete_bounds (range_type, &lowerbound, &upperbound); + + if (VALUE_LVAL (array) != lval_memory) +- return value_subscripted_rvalue (array, idx, lowerbound); ++ { ++ if (index >= lowerbound && index <= upperbound) ++ { ++ CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray)); ++ CORE_ADDR offset = (index - lowerbound) * element_size; ++ ++ return value_subscripted_rvalue (array, offset); ++ } ++ error (_("array or string index out of range")); ++ } + + if (c_style == 0) + { +- LONGEST index = value_as_long (idx); + if (index >= lowerbound && index <= upperbound) +- return value_subscripted_rvalue (array, idx, lowerbound); ++ { ++ CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray)); ++ CORE_ADDR offset = (index - lowerbound) * element_size; ++ ++ return value_subscripted_rvalue (array, offset); ++ } + /* Emit warning unless we have an array of unknown size. + An array of unknown size has lowerbound 0 and upperbound -1. */ + if (upperbound > -1) +@@ -194,49 +207,52 @@ value_subscript (struct value *array, struct value *idx) + c_style = 1; + } + +- if (lowerbound != 0) +- { +- bound = value_from_longest (value_type (idx), (LONGEST) lowerbound); +- idx = value_binop (idx, bound, BINOP_SUB); +- } +- ++ index -= lowerbound; + array = value_coerce_array (array); + } + + if (c_style) +- return value_ind (value_ptradd (array, idx)); ++ { ++ struct value *idx; ++ ++ idx = value_from_longest (builtin_type_int32, index); ++ return value_ind (value_ptradd (array, idx)); ++ } + else + error (_("not an array or string")); + } + +-/* Return the value of EXPR[IDX], expr an aggregate rvalue +- (eg, a vector register). This routine used to promote floats +- to doubles, but no longer does. */ ++/* Return the value of *((void *) ARRAY + ELEMENT), ARRAY an aggregate rvalue ++ (eg, a vector register). This routine used to promote floats to doubles, ++ but no longer does. OFFSET is zero-based with 0 for the lowermost existing ++ element, it must be expressed in bytes (therefore multiplied by ++ check_typedef (TYPE_TARGET_TYPE (array_type)). */ + + struct value * +-value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound) ++value_subscripted_rvalue (struct value *array, CORE_ADDR offset) + { + struct type *array_type = check_typedef (value_type (array)); + struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type)); +- unsigned int elt_size = TYPE_LENGTH (elt_type); +- LONGEST index = value_as_long (idx); +- unsigned int elt_offs = elt_size * longest_to_int (index - lowerbound); + struct value *v; + +- if (index < lowerbound || elt_offs >= TYPE_LENGTH (array_type)) +- error (_("no such vector element")); ++ /* Do not check TYPE_LENGTH (array_type) as we may have been given the ++ innermost dimension of a multi-dimensional Fortran array where its length ++ is shorter than the possibly accessed element offset. */ + + v = allocate_value (elt_type); + if (VALUE_LVAL (array) == lval_memory && value_lazy (array)) + set_value_lazy (v, 1); + else +- memcpy (value_contents_writeable (v), +- value_contents (array) + elt_offs, elt_size); ++ { ++ unsigned int elt_size = TYPE_LENGTH (elt_type); ++ memcpy (value_contents_writeable (v), ++ value_contents (array) + offset, elt_size); ++ } + + set_value_component_location (v, array); + VALUE_REGNUM (v) = VALUE_REGNUM (array); + VALUE_FRAME_ID (v) = VALUE_FRAME_ID (array); +- set_value_offset (v, value_offset (array) + elt_offs); ++ set_value_offset (v, value_offset (array) + offset); + return v; + } + +diff --git a/gdb/valops.c b/gdb/valops.c +index 9810f2b..c3a48b4 100644 +--- a/gdb/valops.c ++++ b/gdb/valops.c +@@ -38,6 +38,7 @@ + #include "cp-support.h" + #include "dfp.h" + #include "user-regs.h" ++#include "dwarf2loc.h" + + #include + #include "gdb_string.h" +@@ -371,8 +372,6 @@ value_cast (struct type *type, struct value *arg2) + new_length = val_length / element_length; + if (val_length % element_length != 0) + warning (_("array element type size does not divide object size in cast")); +- /* FIXME-type-allocation: need a way to free this type when +- we are done with it. */ + range_type = create_range_type ((struct type *) NULL, + TYPE_TARGET_TYPE (range_type), + low_bound, +@@ -568,6 +567,64 @@ value_one (struct type *type, enum lval_type lv) + return val; + } + ++/* object_address_set must be already called before this function. */ ++ ++const char * ++object_address_data_not_valid (struct type *type) ++{ ++ /* Attributes are present only at the target type of a typedef. Make the ++ call conditional as it would otherwise loop through type_length_get. */ ++ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) ++ CHECK_TYPEDEF (type); ++ ++ /* DW_AT_associated has a preference over DW_AT_allocated. */ ++ if (TYPE_NOT_ASSOCIATED (type) ++ || (TYPE_ASSOCIATED (type) != NULL ++ && 0 == dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (type)))) ++ return N_("object is not associated"); ++ ++ if (TYPE_NOT_ALLOCATED (type) ++ || (TYPE_ALLOCATED (type) != NULL ++ && 0 == dwarf_locexpr_baton_eval (TYPE_ALLOCATED (type)))) ++ return N_("object is not allocated"); ++ ++ return NULL; ++} ++ ++/* Return non-zero if the variable is valid. If it is valid the function ++ may store the data address (DW_AT_DATA_LOCATION) of TYPE at *ADDRESS_RETURN. ++ You must set *ADDRESS_RETURN as VALUE_ADDRESS (VAL) before calling this ++ function. If no DW_AT_DATA_LOCATION is present for TYPE the address at ++ *ADDRESS_RETURN is left unchanged. ADDRESS_RETURN must not be NULL, use ++ object_address_data_not_valid () for just the data validity check. */ ++ ++int ++object_address_get_data (struct type *type, CORE_ADDR *address_return) ++{ ++ gdb_assert (address_return != NULL); ++ ++ object_address_set (*address_return); ++ ++ /* TYPE_DATA_LOCATION_DWARF_BLOCK / TYPE_DATA_LOCATION_ADDR are present only ++ at the target type of a typedef. */ ++ CHECK_TYPEDEF (type); ++ ++ if (object_address_data_not_valid (type) != NULL) ++ { ++ /* Do not try to evaluate DW_AT_data_location as it may even crash ++ (it would just return the value zero in the gfortran case). */ ++ return 0; ++ } ++ ++ if (TYPE_DATA_LOCATION_IS_ADDR (type)) ++ *address_return = TYPE_DATA_LOCATION_ADDR (type); ++ else if (TYPE_DATA_LOCATION_DWARF_BLOCK (type) != NULL) ++ *address_return ++ = dwarf_locexpr_baton_eval (TYPE_DATA_LOCATION_DWARF_BLOCK (type)); ++ ++ return 1; ++} ++ + /* Return a value with type TYPE located at ADDR. + + Call value_at only if the data needs to be fetched immediately; +@@ -637,11 +694,19 @@ value_fetch_lazy (struct value *val) + allocate_value_contents (val); + if (VALUE_LVAL (val) == lval_memory) + { +- CORE_ADDR addr = VALUE_ADDRESS (val) + value_offset (val); +- int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val))); ++ CORE_ADDR addr = VALUE_ADDRESS (val); + +- if (length) +- read_memory (addr, value_contents_all_raw (val), length); ++ if (object_address_get_data (value_type (val), &addr)) ++ { ++ struct type *type = value_enclosing_type (val); ++ int length = TYPE_LENGTH (check_typedef (type)); ++ ++ if (length) ++ { ++ addr += value_offset (val); ++ read_memory (addr, value_contents_all_raw (val), length); ++ } ++ } + } + else if (VALUE_LVAL (val) == lval_register) + { +@@ -1036,7 +1101,8 @@ address_of_variable (struct symbol *var, struct block *b) + + val = value_of_variable (var, b); + +- if ((VALUE_LVAL (val) == lval_memory && value_lazy (val)) ++ if ((VALUE_LVAL (val) == lval_memory && value_lazy (val) ++ && object_address_get_data (type, &VALUE_ADDRESS (val))) + || TYPE_CODE (type) == TYPE_CODE_FUNC) + { + CORE_ADDR addr = VALUE_ADDRESS (val); +@@ -1145,6 +1211,7 @@ struct value * + value_coerce_array (struct value *arg1) + { + struct type *type = check_typedef (value_type (arg1)); ++ CORE_ADDR address; + + /* If the user tries to do something requiring a pointer with an + array that has not yet been pushed to the target, then this would +@@ -1154,8 +1221,12 @@ value_coerce_array (struct value *arg1) + if (VALUE_LVAL (arg1) != lval_memory) + error (_("Attempt to take address of value not located in memory.")); + ++ address = VALUE_ADDRESS (arg1); ++ if (!object_address_get_data (type, &address)) ++ error (_("Attempt to take address of non-valid value.")); ++ + return value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)), +- (VALUE_ADDRESS (arg1) + value_offset (arg1))); ++ address + value_offset (arg1)); + } + + /* Given a value which is a function, return a value which is a pointer +@@ -2989,8 +3060,6 @@ value_slice (struct value *array, int lowbound, int length) + || lowbound + length - 1 > upperbound) + error (_("slice out of range")); + +- /* FIXME-type-allocation: need a way to free this type when we are +- done with it. */ + slice_range_type = create_range_type ((struct type *) NULL, + TYPE_TARGET_TYPE (range_type), + lowbound, +diff --git a/gdb/value.c b/gdb/value.c +index 4d4329e..47739c9 100644 +--- a/gdb/value.c ++++ b/gdb/value.c +@@ -225,7 +225,9 @@ allocate_value_lazy (struct type *type) + val->next = all_values; + all_values = val; + val->type = type; ++ type_incref (type); + val->enclosing_type = type; ++ type_incref (type); + VALUE_LVAL (val) = not_lval; + VALUE_ADDRESS (val) = 0; + VALUE_FRAME_ID (val) = null_frame_id; +@@ -269,13 +271,9 @@ struct value * + allocate_repeat_value (struct type *type, int count) + { + int low_bound = current_language->string_lower_bound; /* ??? */ +- /* FIXME-type-allocation: need a way to free this type when we are +- done with it. */ + struct type *range_type + = create_range_type ((struct type *) NULL, builtin_type_int32, + low_bound, count + low_bound - 1); +- /* FIXME-type-allocation: need a way to free this type when we are +- done with it. */ + return allocate_value (create_array_type ((struct type *) NULL, + type, range_type)); + } +@@ -335,6 +333,8 @@ value_type (struct value *value) + void + deprecated_set_value_type (struct value *value, struct type *type) + { ++ type_incref (type); ++ type_decref (value->type); + value->type = type; + } + +@@ -552,6 +552,9 @@ value_free (struct value *val) + { + if (val) + { ++ type_decref (val->type); ++ type_decref (val->enclosing_type); ++ + if (VALUE_LVAL (val) == lval_computed) + { + struct lval_funcs *funcs = val->location.computed.funcs; +@@ -655,6 +658,8 @@ value_copy (struct value *arg) + val = allocate_value_lazy (encl_type); + else + val = allocate_value (encl_type); ++ type_incref (arg->type); ++ type_decref (val->type); + val->type = arg->type; + VALUE_LVAL (val) = VALUE_LVAL (arg); + val->location = arg->location; +@@ -693,6 +698,7 @@ set_value_component_location (struct value *component, struct value *whole) + VALUE_LVAL (component) = VALUE_LVAL (whole); + + component->location = whole->location; ++ + if (VALUE_LVAL (whole) == lval_computed) + { + struct lval_funcs *funcs = whole->location.computed.funcs; +@@ -700,6 +706,8 @@ set_value_component_location (struct value *component, struct value *whole) + if (funcs->copy_closure) + component->location.computed.closure = funcs->copy_closure (whole); + } ++ ++ object_address_get_data (value_type (whole), &VALUE_ADDRESS (component)); + } + + +@@ -830,6 +838,25 @@ show_values (char *num_exp, int from_tty) + num_exp[1] = '\0'; + } + } ++ ++/* Sanity check for memory leaks and proper types reference counting. */ ++ ++static void ++value_history_cleanup (void *unused) ++{ ++ while (value_history_chain) ++ { ++ struct value_history_chunk *chunk = value_history_chain; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE (chunk->values); i++) ++ value_free (chunk->values[i]); ++ ++ value_history_chain = chunk->next; ++ xfree (chunk); ++ } ++ value_history_count = 0; ++} + + /* Internal variables. These are variables within the debugger + that hold values assigned by debugger commands. +@@ -1067,12 +1094,21 @@ preserve_one_value (struct value *value, struct objfile *objfile, + htab_t copied_types) + { + if (TYPE_OBJFILE (value->type) == objfile) +- value->type = copy_type_recursive (objfile, value->type, copied_types); ++ { ++ /* No need to decref the old type here, since we know it has no ++ reference count. */ ++ value->type = copy_type_recursive (value->type, copied_types); ++ type_incref (value->type); ++ } + + if (TYPE_OBJFILE (value->enclosing_type) == objfile) +- value->enclosing_type = copy_type_recursive (objfile, +- value->enclosing_type, +- copied_types); ++ { ++ /* No need to decref the old type here, since we know it has no ++ reference count. */ ++ value->enclosing_type = copy_type_recursive (value->enclosing_type, ++ copied_types); ++ type_incref (value->enclosing_type); ++ } + } + + /* Update the internal variables and value history when OBJFILE is +@@ -1461,6 +1497,8 @@ value_static_field (struct type *type, int fieldno) + struct value * + value_change_enclosing_type (struct value *val, struct type *new_encl_type) + { ++ type_incref (new_encl_type); ++ type_decref (val->enclosing_type); + if (TYPE_LENGTH (new_encl_type) > TYPE_LENGTH (value_enclosing_type (val))) + val->contents = + (gdb_byte *) xrealloc (val->contents, TYPE_LENGTH (new_encl_type)); +@@ -1516,6 +1554,8 @@ value_primitive_field (struct value *arg1, int offset, + memcpy (value_contents_all_raw (v), value_contents_all_raw (arg1), + TYPE_LENGTH (value_enclosing_type (arg1))); + } ++ type_incref (type); ++ type_decref (v->type); + v->type = type; + v->offset = value_offset (arg1); + v->embedded_offset = (offset + value_embedded_offset (arg1) +@@ -1944,4 +1984,6 @@ init-if-undefined VARIABLE = EXPRESSION\n\ + Set an internal VARIABLE to the result of the EXPRESSION if it does not\n\ + exist or does not contain a value. The EXPRESSION is not evaluated if the\n\ + VARIABLE is already initialized.")); ++ ++ make_final_cleanup (value_history_cleanup, NULL); + } +diff --git a/gdb/value.h b/gdb/value.h +index aa43365..ad5306a 100644 +--- a/gdb/value.h ++++ b/gdb/value.h +@@ -348,6 +348,10 @@ extern struct value *value_from_decfloat (struct type *type, + const gdb_byte *decbytes); + extern struct value *value_from_string (char *string); + ++extern const char *object_address_data_not_valid (struct type *type); ++extern int object_address_get_data (struct type *type, ++ CORE_ADDR *address_return); ++ + extern struct value *value_at (struct type *type, CORE_ADDR addr); + extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr); + +@@ -658,5 +662,7 @@ extern struct value *value_allocate_space_in_inferior (int); + + extern struct value *value_of_local (const char *name, int complain); + +-extern struct value * value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound); ++extern struct value *value_subscripted_rvalue (struct value *array, ++ CORE_ADDR offset); ++ + #endif /* !defined (VALUE_H) */ diff --git a/gdb-readline6.patch b/gdb-readline6.patch new file mode 100644 index 0000000..460e1fe --- /dev/null +++ b/gdb-readline6.patch @@ -0,0 +1,35 @@ +--- gdb/tui/tui-io.c.orig 2009-03-10 11:34:01.000000000 +0100 ++++ gdb/tui/tui-io.c 2009-03-10 11:34:45.000000000 +0100 +@@ -512,7 +512,7 @@ + void + tui_setup_io (int mode) + { +- extern int readline_echoing_p; ++ extern int _rl_echoing_p; + + if (mode) + { +@@ -522,12 +522,12 @@ + tui_old_rl_prep_terminal = rl_prep_term_function; + tui_old_rl_getc_function = rl_getc_function; + tui_old_rl_outstream = rl_outstream; +- tui_old_readline_echoing_p = readline_echoing_p; ++ tui_old_readline_echoing_p = _rl_echoing_p; + rl_redisplay_function = tui_redisplay_readline; + rl_deprep_term_function = tui_deprep_terminal; + rl_prep_term_function = tui_prep_terminal; + rl_getc_function = tui_getc; +- readline_echoing_p = 0; ++ _rl_echoing_p = 0; + rl_outstream = tui_rl_outstream; + rl_prompt = 0; + rl_completion_display_matches_hook = tui_rl_display_match_list; +@@ -564,7 +564,7 @@ + rl_getc_function = tui_old_rl_getc_function; + rl_outstream = tui_old_rl_outstream; + rl_completion_display_matches_hook = 0; +- readline_echoing_p = tui_old_readline_echoing_p; ++ _rl_echoing_p = tui_old_readline_echoing_p; + rl_already_prompted = 0; + + /* Save tty for SIGCONT. */ diff --git a/gdb.changes b/gdb.changes index f174c78..2d307f4 100644 --- a/gdb.changes +++ b/gdb.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Tue Mar 10 11:14:25 CET 2009 - rguenther@suse.de + +- Add VLA support patch from Fedora to fix possible + dwarf_expr_frame_base NULL checking regression. +- Fix readline incompatibility. + ------------------------------------------------------------------- Mon Mar 2 11:42:03 CET 2009 - rguenther@suse.de diff --git a/gdb.spec b/gdb.spec index b22b085..730528b 100644 --- a/gdb.spec +++ b/gdb.spec @@ -20,7 +20,7 @@ Name: gdb Summary: The GNU Debugger Version: 6.8.50.20090216 -Release: 2 +Release: 3 BuildRequires: bison dejagnu flex gcc-c++ gcc-fortran gcc-java gcc-objc python-devel readline-devel zlib-devel %if 0%{?suse_version} > 1020 BuildRequires: libexpat-devel @@ -55,7 +55,11 @@ Patch7: pie-relocate.diff Patch8: find-separate-debug-file.diff Patch9: fix-gdb-backtrace.diff Patch10: expand-line-sal-maybe.diff +Patch11: gdb-readline6.patch # Patches from Fedora +# Fix/implement the Fortran dynamic arrays support (BZ 377541). +# Fix the variable-length-arrays support (BZ 468266, feature BZ 377541). +Patch305: gdb-6.8-bz377541-vla.patch # Support transparent debugging of inlined functions for an optimized code. Patch327: gdb-6.8-inlining.patch Patch350: gdb-6.8-inlining-addon.patch @@ -128,6 +132,8 @@ Authors: %patch8 %patch9 %patch10 +%patch11 +%patch305 -p1 %patch327 -p1 %patch350 -p1 %patch328 -p1 @@ -207,6 +213,10 @@ rm -rf $RPM_BUILD_ROOT %endif %changelog +* Tue Mar 10 2009 rguenther@suse.de +- Add VLA support patch from Fedora to fix possible + dwarf_expr_frame_base NULL checking regression. +- Fix readline incompatibility. * Mon Mar 02 2009 rguenther@suse.de - Integrate support for transparently debugging inline functions. * Mon Feb 16 2009 schwab@suse.de