This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] [VLA 2/2] Interpret FIELD_LOC_KIND_DWARF_BLOCK fields


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 <type> 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  <jan.kratochvil@redhat.com>

	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 <dwarf2_attr_block>): 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 <FIELD_LOC_KIND_DWARF_BLOCK>): 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  <jan.kratochvil@redhat.com>

	* 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) : "<NULL>");
+      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 <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+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 <http://www.gnu.org/licenses/>.
+
+# 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' <repeats 26 times>" "first: print temp1"
+if $xfail { setup_xfail "*-*-*" }
+gdb_test "p temp2" "\\$\[0-9\]+ = '2' <repeats 26 times>" "first: print temp2"
+gdb_test "p temp3" "\\$\[0-9\]+ = '3' <repeats 48 times>" "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' <repeats 78 times>" "second: print temp1"
+if $xfail { setup_xfail "*-*-*" }
+gdb_test "p temp2" "\\$\[0-9\]+ = '2' <repeats 78 times>" "second: print temp2"
+gdb_test "p temp3" "\\$\[0-9\]+ = '3' <repeats 48 times>" "second: print temp3"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]