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] fix exp/12117


Hi.

This patch fixes pr exp/12117.
http://sourceware.org/bugzilla/show_bug.cgi?id=12117

I will check this in in two days if there are no objections.

2010-10-13  Doug Evans  <dje@google.com>

	PR exp/12117
	* c-typeprint.c (c_print_type): Call CHECK_TYPEDEF after calling
	c_type_print_base.
	(c_type_print_modifier_flags): New function.
	(c_type_print_modifier): Call it.
	(c_type_print_base): Collect instance_flags while we're stripping
	typedefs.  Change calls to c_type_print_modifier to call
	c_type_print_modifier_flags instead.
	(c_type_print_base, case TYPE_CODE_TYPEDEF): Verify assumptions of
	when this case happens.  Print "<unnamed typedef>".
	* gdbtypes.h (strip_typedefs): Declare.
	* gdbtypes.c (strip_typedefs): New function.
	(check_typedef): Call it.

	testsuite/
	* gdb.cp/pr12117.cc: New file.
	* gdb.cp/pr12117.exp: New file.

Index: c-typeprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-typeprint.c,v
retrieving revision 1.62
diff -u -p -r1.62 c-typeprint.c
--- c-typeprint.c	13 Oct 2010 15:10:10 -0000	1.62
+++ c-typeprint.c	13 Oct 2010 17:29:30 -0000
@@ -53,10 +53,13 @@ c_print_type (struct type *type, const c
   int demangled_args;
   int need_post_space;
 
+  c_type_print_base (type, stream, show, level);
+
+  /* Do this *after* calling c_type_print_base so that it can see any
+     const/volatile flags that may be encoded in a typedef.  */
   if (show > 0)
     CHECK_TYPEDEF (type);
 
-  c_type_print_base (type, stream, show, level);
   code = TYPE_CODE (type);
   if ((varstring != NULL && *varstring != '\0')
   /* Need a space if going to print stars or brackets;
@@ -313,23 +316,20 @@ c_type_print_varspec_prefix (struct type
 
 /* Print out "const" and "volatile" attributes,
    and address space id if present.
-   TYPE is a pointer to the type being printed out.
+   FLAGS is the TYPE_INSTANCE_FLAGS flags of the type.
    STREAM is the output destination.
    NEED_PRE_SPACE = 1 indicates an initial white space is needed.
    NEED_POST_SPACE = 1 indicates a final white space is needed.  */
 
 static void
-c_type_print_modifier (struct type *type, struct ui_file *stream,
-		       int need_pre_space, int need_post_space)
+c_type_print_modifier_flags (int flags, struct ui_file *stream,
+			     struct gdbarch *gdbarch,
+			     int need_pre_space, int need_post_space)
 {
   int did_print_modifier = 0;
   const char *address_space_id;
 
-  /* We don't print `const' qualifiers for references --- since all
-     operators affect the thing referenced, not the reference itself,
-     every reference is `const'.  */
-  if (TYPE_CONST (type)
-      && TYPE_CODE (type) != TYPE_CODE_REF)
+  if (flags & TYPE_INSTANCE_FLAG_CONST)
     {
       if (need_pre_space)
 	fprintf_filtered (stream, " ");
@@ -337,7 +337,7 @@ c_type_print_modifier (struct type *type
       did_print_modifier = 1;
     }
 
-  if (TYPE_VOLATILE (type))
+  if (flags & TYPE_INSTANCE_FLAG_VOLATILE)
     {
       if (did_print_modifier || need_pre_space)
 	fprintf_filtered (stream, " ");
@@ -345,8 +345,7 @@ c_type_print_modifier (struct type *type
       did_print_modifier = 1;
     }
 
-  address_space_id = address_space_int_to_name (get_type_arch (type),
-						TYPE_INSTANCE_FLAGS (type));
+  address_space_id = address_space_int_to_name (gdbarch, flags);
   if (address_space_id)
     {
       if (did_print_modifier || need_pre_space)
@@ -359,6 +358,24 @@ c_type_print_modifier (struct type *type
     fprintf_filtered (stream, " ");
 }
 
+/* Wrapper for c_type_print_modifier_flags.
+   Print the modifier flags for TYPE.  */
+
+static void
+c_type_print_modifier (struct type *type, struct ui_file *stream,
+		       int need_pre_space, int need_post_space)
+{
+  int instance_flags = TYPE_INSTANCE_FLAGS (type);
+
+  /* We don't print `const' qualifiers for references --- since all
+     operators affect the thing referenced, not the reference itself,
+     every reference is `const'.  */
+  if (TYPE_CODE (type) == TYPE_CODE_REF)
+    instance_flags &= ~TYPE_INSTANCE_FLAG_CONST;
+
+  c_type_print_modifier_flags (instance_flags, stream, get_type_arch (type),
+			       need_pre_space, need_post_space);
+}
 
 /* Print out the arguments of TYPE, which should have TYPE_CODE_METHOD
    or TYPE_CODE_FUNC, to STREAM.  Artificial arguments, such as "this"
@@ -678,6 +695,8 @@ c_type_print_base (struct type *type, st
   section_type;
   int need_access_label = 0;
   int j, len2;
+  int instance_flags;
+  struct gdbarch *gdbarch;
 
   QUIT;
 
@@ -702,11 +721,33 @@ c_type_print_base (struct type *type, st
       return;
     }
 
+  /* Handle typedefs specially because we want to strip them, but as we're
+     stripping them we need to keep track of any instance-related flags,
+     e.g., const/volatile.  Furthermore, we would like to print the flags
+     once, and in a consistent order, so just accumulate them as we're
+     stripping.  */
+  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+    type = strip_typedefs (type, &instance_flags);
+  else
+    instance_flags = 0;
+
+  /* We've already stripped typedefs, but we still need to try to
+     update stubbed structs, etc.  */
   CHECK_TYPEDEF (type);
 
+  instance_flags |= TYPE_INSTANCE_FLAGS (type);
+  gdbarch = get_type_arch (type);
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_TYPEDEF:
+      /* If we get here, the typedef doesn't have a name, and we couldn't
+	 resolve TYPE_TARGET_TYPE.  Not much we can do.  */
+      gdb_assert (TYPE_NAME (type) == NULL);
+      gdb_assert (TYPE_TARGET_TYPE (type) == NULL);
+      fprintf_filtered (stream, _("<unnamed typedef>"));
+      break;
+
     case TYPE_CODE_ARRAY:
     case TYPE_CODE_PTR:
     case TYPE_CODE_MEMBERPTR:
@@ -718,7 +759,7 @@ c_type_print_base (struct type *type, st
       break;
 
     case TYPE_CODE_STRUCT:
-      c_type_print_modifier (type, stream, 0, 1);
+      c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
       if (TYPE_DECLARED_CLASS (type))
 	fprintf_filtered (stream, "class ");
       else
@@ -726,7 +767,7 @@ c_type_print_base (struct type *type, st
       goto struct_union;
 
     case TYPE_CODE_UNION:
-      c_type_print_modifier (type, stream, 0, 1);
+      c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
       fprintf_filtered (stream, "union ");
 
     struct_union:
@@ -1083,7 +1124,7 @@ c_type_print_base (struct type *type, st
       break;
 
     case TYPE_CODE_ENUM:
-      c_type_print_modifier (type, stream, 0, 1);
+      c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
       fprintf_filtered (stream, "enum ");
       /* Print the tag name if it exists.
          The aCC compiler emits a spurious 
@@ -1157,7 +1198,7 @@ c_type_print_base (struct type *type, st
          is no type name, then complain. */
       if (TYPE_NAME (type) != NULL)
 	{
-	  c_type_print_modifier (type, stream, 0, 1);
+	  c_type_print_modifier_flags (instance_flags, stream, gdbarch, 0, 1);
 	  fputs_filtered (TYPE_NAME (type), stream);
 	}
       else
Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.201
diff -u -p -r1.201 gdbtypes.c
--- gdbtypes.c	12 Oct 2010 20:58:17 -0000	1.201
+++ gdbtypes.c	13 Oct 2010 17:29:30 -0000
@@ -1347,36 +1347,21 @@ stub_noname_complaint (void)
   complaint (&symfile_complaints, _("stub type has NULL name"));
 }
 
-/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
+/* Strip all typedefs from TYPE.
+   Return the real type if possible.
 
-   If this is a stubbed struct (i.e. declared as struct foo *), see if
-   we can find a full definition in some other file. If so, copy this
-   definition, so we can use it in future.  There used to be a comment
-   (but not any code) that if we don't find a full definition, we'd
-   set a flag so we don't spend time in the future checking the same
-   type.  That would be a mistake, though--we might load in more
-   symbols which contain a full definition for the type.
+   NOTE: This will return a typedef if TYPE_TARGET_TYPE for the typedef has
+   not been computed and we're either in the middle of reading symbols, or
+   there was no name for the typedef in the debug info.
 
-   This used to be coded as a macro, but I don't think it is called 
-   often enough to merit such treatment.
-
-   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.
-
-   If TYPE is a TYPE_CODE_TYPEDEF, its length is (also) set to the length of
-   the target type instead of zero.  However, in the case of TYPE_CODE_TYPEDEF
-   check_typedef can still return different type than the original TYPE
-   pointer.  */
+   Any instance flags (e.g. const/volatile/address-space) that were stripped
+   away are stored in *INSTANCE_FLAGSP if non-NULL.  */
 
 struct type *
-check_typedef (struct type *type)
+strip_typedefs (struct type *type, int *instance_flagsp)
 {
-  struct type *orig_type = type;
-  int is_const, is_volatile;
-
-  gdb_assert (type);
+  if (instance_flagsp != NULL)
+    *instance_flagsp = 0;
 
   while (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
     {
@@ -1406,9 +1391,50 @@ check_typedef (struct type *type)
 	  else					/* TYPE_CODE_UNDEF */
 	    TYPE_TARGET_TYPE (type) = alloc_type_arch (get_type_arch (type));
 	}
+
+      if (instance_flagsp != NULL)
+	*instance_flagsp |= TYPE_INSTANCE_FLAGS (type);
+
       type = TYPE_TARGET_TYPE (type);
     }
 
+  return type;
+}
+
+/* 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.
+
+   NOTE: This will return a typedef if TYPE_TARGET_TYPE for the typedef has
+   not been computed and we're either in the middle of reading symbols, or
+   there was no name for the typedef in the debug info.
+
+   If TYPE is a TYPE_CODE_TYPEDEF, its length is updated to the length of
+   the target type.
+
+   If this is a stubbed struct (i.e. declared as struct foo *), see if
+   we can find a full definition in some other file. If so, copy this
+   definition, so we can use it in future.  There used to be a comment
+   (but not any code) that if we don't find a full definition, we'd
+   set a flag so we don't spend time in the future checking the same
+   type.  That would be a mistake, though--we might load in more
+   symbols which contain a full definition for the type.  */
+
+struct type *
+check_typedef (struct type *type)
+{
+  struct type *orig_type = type;
+  int is_const, is_volatile;
+
+  gdb_assert (type);
+
+  type = strip_typedefs (type, NULL);
+
+  /* If we still have a typedef, there's nothing more we can do.  */
+  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+    return type;
+
   is_const = TYPE_CONST (type);
   is_volatile = TYPE_VOLATILE (type);
 
Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.135
diff -u -p -r1.135 gdbtypes.h
--- gdbtypes.h	6 Oct 2010 08:44:14 -0000	1.135
+++ gdbtypes.h	13 Oct 2010 17:29:30 -0000
@@ -1361,6 +1361,8 @@ extern struct type *check_typedef (struc
     (TYPE) = check_typedef (TYPE);		\
   } while (0)
 
+extern struct type *strip_typedefs (struct type *, int *);
+
 extern void check_stub_method_group (struct type *, int);
 
 extern char *gdb_mangle_name (struct type *, int, int);
Index: testsuite/gdb.cp/pr12117.cc
===================================================================
RCS file: testsuite/gdb.cp/pr12117.cc
diff -N testsuite/gdb.cp/pr12117.cc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.cp/pr12117.cc	13 Oct 2010 17:29:31 -0000
@@ -0,0 +1,17 @@
+typedef int my_int;
+typedef const my_int const_my_int;
+typedef volatile my_int volatile_my_int;
+typedef volatile const_my_int volatile_const_my_int;
+typedef const volatile_my_int const_volatile_my_int;
+
+my_int v_my_int (0);
+const_my_int v_const_my_int (1);
+volatile_my_int v_volatile_my_int (2);
+const_volatile_my_int v_const_volatile_my_int (3);
+volatile_const_my_int v_volatile_const_my_int (4);
+
+int
+main ()
+{
+  return 0;
+}
Index: testsuite/gdb.cp/pr12117.exp
===================================================================
RCS file: testsuite/gdb.cp/pr12117.exp
diff -N testsuite/gdb.cp/pr12117.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.cp/pr12117.exp	13 Oct 2010 17:29:31 -0000
@@ -0,0 +1,55 @@
+# Copyright 2010 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/>.
+
+# This file is part of the gdb testsuite.
+
+if { [skip_cplus_tests] } { continue }
+
+load_lib "cp-support.exp"
+
+set testfile "pr12117"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested ${testfile}.exp
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint"
+    continue
+}
+
+gdb_test "whatis v_my_int" "my_int"
+gdb_test "ptype v_my_int" "int"
+
+gdb_test "whatis v_const_my_int" "const_my_int"
+gdb_test "ptype v_const_my_int" "const int"
+
+gdb_test "whatis v_volatile_my_int" "volatile_my_int"
+gdb_test "ptype v_volatile_my_int" "volatile int"
+
+gdb_test "whatis v_const_volatile_my_int" "const_volatile_my_int"
+gdb_test "ptype v_const_volatile_my_int" "const volatile int"
+
+gdb_test "whatis v_volatile_const_my_int" "volatile_const_my_int"
+setup_kfail "gcc/45997" *-*-*
+gdb_test "ptype v_volatile_const_my_int" "const volatile int"


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