From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22507 invoked by alias); 13 Jan 2009 01:42:41 -0000 Received: (qmail 22235 invoked by uid 22791); 13 Jan 2009 01:42:38 -0000 X-SWARE-Spam-Status: No, hits=-1.3 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_33,J_CHICKENPOX_55,J_CHICKENPOX_57,KAM_MX,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx2.redhat.com (HELO mx2.redhat.com) (66.187.237.31) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 13 Jan 2009 01:42:04 +0000 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n0D1fRHx020203; Mon, 12 Jan 2009 20:41:27 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n0D1fR0E006026; Mon, 12 Jan 2009 20:41:28 -0500 Received: from host0.dyn.jankratochvil.net (sebastian-int.corp.redhat.com [172.16.52.221]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n0D1fPaw000629; Mon, 12 Jan 2009 20:41:26 -0500 Received: from host0.dyn.jankratochvil.net (localhost [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.3/8.14.3) with ESMTP id n0D1fN62028676; Tue, 13 Jan 2009 02:41:24 +0100 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.3/8.14.2/Submit) id n0D1fMa3028673; Tue, 13 Jan 2009 02:41:22 +0100 Date: Tue, 13 Jan 2009 01:42:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Cc: Joel Brobecker , Ulrich Weigand , Jim Blandy , Tobias Burnus Subject: [patch] [VLA 2/2] Interpret FIELD_LOC_KIND_DWARF_BLOCK fields Message-ID: <20090113014122.GA27831@host0.dyn.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-01/txt/msg00266.txt.bz2 Hi, this patch provides the interpreter for simple C variable length arrays (VLA). check_typedef() will contain a memory leak with this patch. This has been fixed by Tom Tromey's + mine garbage collector to be posted later from: http://sourceware.org/gdb/wiki/ArcherBranchManagement archer-jankratochvil-type-refcount No regressions for both patches on x86_64-unknown-linux-gnu, Fedora gcc-4.3.2-7. Thanks, Jan gdb/ 2009-01-13 Jan Kratochvil Interpret FIELD_LOC_KIND_DWARF_BLOCK fields. * c-typeprint.c (c_type_print_varspec_suffix): Display a marker for the variable length arrays. * dwarf2loc.c (dwarf2_evaluate_loc_desc): Wrap the function body by a cleanup block. Move the BATON variable with the DATA and SIZE evaluation to ... (dwarf_expr_prep_ctx): ... a new function here. (dwarf_locexpr_baton_eval): New function. * dwarf2loc.h (dwarf_locexpr_baton_eval): New declaration. * dwarf2read.c (read_subrange_type ): Set TYPE_DYNAMIC for RANGE_TYPE. * gdbtypes.c: New include dwarf2loc.h. (create_array_type): Do not call get_discrete_bounds for TYPE_DYNAMIC types. Fix/remove TYPE_TARGET_STUB which was set for static zero length arrays. Call complaint for negative length static arrays. Set TYPE_DYNAMIC appropriately for new RESULT_TYPE. (check_typedef): Make TYPE_DYNAMIC types parameters static. (create_copied_types_hash): Permit NULL OBJFILE. Move the comment. (copy_type_recursive ): New. (copy_type_recursive): Clear TYPE_DYNAMIC for NEW_TYPE. * gdbtypes.h (TYPE_DYNAMIC): New define. (struct main_type): New field flag_dynamic. (TYPE_LENGTH): Update the comment for array types. gdb/testsuite/ 2009-01-13 Jan Kratochvil * gdb.base/vla.c, gdb.base/vla.exp: New. --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/c-typeprint.c 2009-01-11 17:09:13.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/c-typeprint.c 2009-01-12 14:26:54.000000000 +0100 @@ -559,8 +559,13 @@ c_type_print_varspec_suffix (struct type fprintf_filtered (stream, ")"); fprintf_filtered (stream, "["); - if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 - && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) + if (TYPE_DYNAMIC (TYPE_INDEX_TYPE (type))) + { + /* Do not translate it as it is a part of the printed source. */ + 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) / TYPE_LENGTH (TYPE_TARGET_TYPE (type)))); --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/dwarf2loc.c 2009-01-11 17:09:14.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/dwarf2loc.c 2009-01-12 22:43:25.000000000 +0100 @@ -191,6 +191,67 @@ dwarf_expr_tls_address (void *baton, COR return target_translate_tls_address (debaton->objfile, offset); } +/* Evaluate DWARF expression at DATA ... DATA + SIZE with its result readable + by dwarf_expr_fetch (RETVAL, 0). FRAME parameter can be left NULL to call + get_selected_frame to get its value. Freeing of returned dwarf_expr_context + is remembered on the current 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); + + 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; + + make_cleanup ((make_cleanup_ftype *) free_dwarf_expr_context, ctx); + + dwarf_expr_eval (ctx, data, size); + + /* The field has been used only above 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. */ @@ -201,8 +262,8 @@ dwarf2_evaluate_loc_desc (struct symbol { struct gdbarch *arch = get_frame_arch (frame); 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) { @@ -212,19 +273,8 @@ dwarf2_evaluate_loc_desc (struct symbol return retval; } - baton.frame = frame; - baton.objfile = dwarf2_per_cu_objfile (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; + ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu); - dwarf_expr_eval (ctx, data, size); if (ctx->num_pieces > 0) { int i; @@ -270,7 +320,7 @@ dwarf2_evaluate_loc_desc (struct symbol set_value_initialized (retval, ctx->initialized); - free_dwarf_expr_context (ctx); + do_cleanups (back_to); return retval; } --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/dwarf2loc.h 2009-01-11 17:09:14.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/dwarf2loc.h 2009-01-12 10:37:22.000000000 +0100 @@ -72,4 +72,7 @@ struct dwarf2_loclist_baton extern const struct symbol_ops dwarf2_locexpr_funcs; extern const struct symbol_ops dwarf2_loclist_funcs; +extern CORE_ADDR dwarf_locexpr_baton_eval + (struct dwarf2_locexpr_baton *dlbaton); + #endif /* dwarf2loc.h */ --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/dwarf2read.c 2009-01-12 22:57:30.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/dwarf2read.c 2009-01-12 22:57:29.000000000 +0100 @@ -5171,6 +5171,7 @@ read_subrange_type (struct die_info *die SET_FIELD_DWARF_BLOCK (TYPE_FIELD (range_type, 0), dwarf_block_to_locexpr_baton (DW_BLOCK (attr), cu)); + TYPE_DYNAMIC (range_type) = 1; break; } @@ -5188,6 +5189,7 @@ read_subrange_type (struct die_info *die SET_FIELD_DWARF_BLOCK (TYPE_FIELD (range_type, 1), dwarf_block_to_locexpr_baton (DW_BLOCK (attr), cu)); + TYPE_DYNAMIC (range_type) = 1; break; } --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/gdbtypes.c 2009-01-11 17:09:15.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/gdbtypes.c 2009-01-13 00:54:24.000000000 +0100 @@ -38,6 +38,7 @@ #include "cp-abi.h" #include "gdb_assert.h" #include "hashtab.h" +#include "dwarf2loc.h" /* These variables point to the objects representing the predefined C data types. */ @@ -822,17 +823,6 @@ create_array_type (struct type *result_t } 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_ALLOC (result_type, sizeof (struct field)); @@ -840,11 +830,44 @@ create_array_type (struct type *result_t TYPE_INDEX_TYPE (result_type) = range_type; TYPE_VPTR_FIELDNO (result_type) = -1; - /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays */ - if (TYPE_LENGTH (result_type) == 0) - TYPE_TARGET_STUB (result_type) = 1; + /* The resulting array type needs to have evaluated the original TYPE_DYNAMIC + RANGE_TYPE expressions on each check_typedef call. Therefore we mark + RESULT_TYPE by TYPE_TARGET_STUB and TYPE_LENGTH can be left unset for the + later check_typedef call by the RESULT_TYPE consumer. + TYPE_RANGE_LOWER_BOUND_IS_UNDEFINED or TYPE_RANGE_UPPER_BOUND_IS_UNDEFINED + will result in a non-TYPE_TARGET_STUB array with TYPE_LENGTH set to 0. */ + if (TYPE_TARGET_STUB (element_type) + || TYPE_DYNAMIC (range_type) + || get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) + { + TYPE_TARGET_STUB (result_type) = 1; + TYPE_LENGTH (result_type) = 0; + } + else if (high_bound + 1 < low_bound) + { + complaint (&symfile_complaints, _("Range type %s is invalid"), + TYPE_NAME (range_type) ? TYPE_NAME (range_type) : ""); + TYPE_LENGTH (result_type) = 0; + } + else + { + CHECK_TYPEDEF (element_type); + TYPE_LENGTH (result_type) = TYPE_LENGTH (element_type) + * (high_bound - low_bound + 1); + } - return (result_type); + /* Propagate FIELD_LOC_KIND_DWARF_BLOCK bounds. */ + if (TYPE_DYNAMIC (range_type)) + TYPE_DYNAMIC (result_type) = 1; + + /* Multidimensional TYPE_DYNAMIC arrays need to have all the outer dimensions + also TYPE_DYNAMIC. check_typedef will have to update the TYPE_TARGET_TYPE + pointer in the outer dimension with the new type (+main_type) copy + containing the constant evaluated parameters. */ + if (TYPE_DYNAMIC (element_type)) + TYPE_DYNAMIC (result_type) = 1; + + return result_type; } /* Create a string type using either a blank type supplied in @@ -1512,6 +1535,21 @@ check_typedef (struct type *type) } } + /* copy_type_recursive automatically makes the resulting type containing only + constant values expected by the callers of this function. + + FIXME: New TYPE memory leaks here on each check_typedef call. */ + if (TYPE_DYNAMIC (type)) + { + htab_t copied_types; + + copied_types = create_copied_types_hash (NULL); + type = copy_type_recursive (TYPE_OBJFILE (type), type, copied_types); + htab_delete (copied_types); + + gdb_assert (TYPE_DYNAMIC (type) == 0); + } + if (TYPE_TARGET_STUB (type)) { struct type *range_type; @@ -2915,16 +2953,21 @@ type_pair_eq (const void *item_lhs, cons } /* 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) + return htab_create (1, type_pair_hash, type_pair_eq, NULL); + else + { + /* Use OBJFILE's obstack, because OBJFILE is about to be deleted. */ + return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq, + NULL, &objfile->objfile_obstack, + hashtab_obstack_allocate, + dummy_obstack_deallocate); + } } /* Recursively copy (deep copy) TYPE, if it is associated with @@ -3010,6 +3053,12 @@ copy_type_recursive (struct objfile *obj 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. */ + 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,6 +3067,9 @@ copy_type_recursive (struct objfile *obj } } + /* FIELD_LOC_KIND_DWARF_BLOCK fields have been possibly converted. */ + TYPE_DYNAMIC (new_type) = 0; + /* Copy pointers to other types. */ if (TYPE_TARGET_TYPE (type)) TYPE_TARGET_TYPE (new_type) = --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/gdbtypes.h 2009-01-11 19:37:36.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/gdbtypes.h 2009-01-13 00:25:22.000000000 +0100 @@ -209,6 +209,14 @@ enum type_instance_flag_value #define TYPE_TARGET_STUB(t) (TYPE_MAIN_TYPE (t)->flag_target_stub) +/* Type needs to be made static by check_typedef creating a new copy no longer + being TYPE_DYNAMIC. Difference to TYPE_STUB or TYPE_TARGET_STUB is that the + original type must be preserved intact. Check_typedef must return its copy + (of main_type, not just type). For example FIELD_LOC_KIND_DWARF_BLOCK + fields will get resolved to the static form FIELD_LOC_KIND_BITPOS. */ + +#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 @@ -352,6 +360,7 @@ 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; /* Number of fields described for this type. This field appears at this location because it packs nicely here. */ @@ -795,9 +804,9 @@ extern void allocate_cplus_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 or ARRAY 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 --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/testsuite/gdb.base/vla.c 1970-01-01 01:00:00.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/testsuite/gdb.base/vla.c 2009-01-13 00:14:34.000000000 +0100 @@ -0,0 +1,55 @@ +/* This testcase is part of GDB, the GNU debugger. + + 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 . */ + +#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; +} --- gdb-cvs-dwarf2_get_attr_constant_value/gdb/testsuite/gdb.base/vla.exp 1970-01-01 01:00:00.000000000 +0100 +++ gdb-cvs-dwarf_block-eval/gdb/testsuite/gdb.base/vla.exp 2009-01-13 01:29:08.000000000 +0100 @@ -0,0 +1,81 @@ +# 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 C variable length arrays. + +set srcfile vla.c + +if [prepare_for_testing vla.exp "vla"] { + return -1 +} +if ![runto_main] { + untested vla.exp + return -1 +} + +gdb_breakpoint [gdb_get_line_number "break-here"] +gdb_continue_to_breakpoint "break-here" + +# Set if the compiler has produced no DW_FORM_block*. +set xfail 0 + +set test "first: whatis temp1" +gdb_test_multiple "whatis temp1" $test { + -re "type = char \\\[\\\]\r\n$gdb_prompt $" { + # Compiler has produced no DW_FORM_block*? + setup_xfail "*-*-*" + fail $test + + set xfail 1 + } + -re "type = char \\\[variable\\\]\r\n$gdb_prompt $" { + pass $test + } +} +if $xfail { setup_xfail "*-*-*" } +gdb_test "whatis temp2" "type = char \\\[variable\\\]" "first: whatis temp2" +gdb_test "whatis temp3" "type = char \\\[48\\\]" "first: whatis temp3" + +if $xfail { setup_xfail "*-*-*" } +gdb_test "ptype temp1" "type = char \\\[26\\\]" "first: ptype temp1" +if $xfail { setup_xfail "*-*-*" } +gdb_test "ptype temp2" "type = char \\\[26\\\]" "first: ptype temp2" +gdb_test "ptype temp3" "type = char \\\[48\\\]" "first: ptype temp3" + +if $xfail { setup_xfail "*-*-*" } +gdb_test "p temp1" "\\$\[0-9\]+ = '1' " "first: print temp1" +if $xfail { setup_xfail "*-*-*" } +gdb_test "p temp2" "\\$\[0-9\]+ = '2' " "first: print temp2" +gdb_test "p temp3" "\\$\[0-9\]+ = '3' " "first: print temp3" + +gdb_continue_to_breakpoint "break-here" + +if $xfail { setup_xfail "*-*-*" } +gdb_test "whatis temp1" "type = char \\\[variable\\\]" "second: whatis temp1" +if $xfail { setup_xfail "*-*-*" } +gdb_test "whatis temp2" "type = char \\\[variable\\\]" "second: whatis temp2" +gdb_test "whatis temp3" "type = char \\\[48\\\]" "second: whatis temp3" + +if $xfail { setup_xfail "*-*-*" } +gdb_test "ptype temp1" "type = char \\\[78\\\]" "second: ptype temp1" +if $xfail { setup_xfail "*-*-*" } +gdb_test "ptype temp2" "type = char \\\[78\\\]" "second: ptype temp2" +gdb_test "ptype temp3" "type = char \\\[48\\\]" "second: ptype temp3" + +if $xfail { setup_xfail "*-*-*" } +gdb_test "p temp1" "\\$\[0-9\]+ = '1' " "second: print temp1" +if $xfail { setup_xfail "*-*-*" } +gdb_test "p temp2" "\\$\[0-9\]+ = '2' " "second: print temp2" +gdb_test "p temp3" "\\$\[0-9\]+ = '3' " "second: print temp3"