[V4,1/2] CTF: fix incorrect function return type

Message ID 1619485254-7340-2-git-send-email-weimin.pan@oracle.com
State New
Headers show
Series
  • CTF: bug fixes and new features.
Related show

Commit Message

Mike Frysinger via Gdb-patches April 27, 2021, 1 a.m.
The problems can be illustrated, with any program, below:

(gdb) print main
$1 = {main} 0x0

The return type was incorrectly set in read_func_kind_type, with
the name of the function, which leads c_type_print_base_1 to print
it. In addition, the address of a new function needs to be set with
that info in its minimal symtab entry, when the new function is added.

After the fix:

(gdb) print main
$1 = {int ()} 0x4004b7 <main>

A new test, gdb.ctf/funcreturn.exp, is added to the testsuite.
---
 gdb/ChangeLog                        |   6 +
 gdb/ctfread.c                        |  57 +++---
 gdb/testsuite/ChangeLog              |   5 +
 gdb/testsuite/gdb.ctf/funcreturn.exp | 190 ++++++++++++++++++++
 gdb/testsuite/gdb.ctf/whatis.c       | 339 +++++++++++++++++++++++++++++++++++
 5 files changed, 566 insertions(+), 31 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ctf/funcreturn.exp
 create mode 100644 gdb/testsuite/gdb.ctf/whatis.c

-- 
1.8.3.1

Comments

Tom Tromey May 7, 2021, 8:07 p.m. | #1
>>>>> ">" == Weimin Pan via Gdb-patches <gdb-patches@sourceware.org> writes:


>> The problems can be illustrated, with any program, below:

>> (gdb) print main

>> $1 = {main} 0x0


Hi.  Sorry about the delay in my re-review.
It's fine (and expected) to send patch pings to the list.
It helps keep us honest I guess.

>> -      sym->compute_and_set_names (name.get (), true, objfile->per_bfd);

>> +      sym->compute_and_set_names (name, true, objfile->per_bfd);


If the lifetime of 'name' is ok, then you don't need to copy it here --
so you can pass 'false' as the second parameter.  See the comment in
symtab.c just before general_symbol_info::compute_and_set_names.

>> +  name = ctf_type_name_raw (fp, tid);

>> +  if (name == nullptr || strlen (name) == 0)

>> +  {


The braces (and the code they surround) look under-indented to me.

>> -  ccp->pst->add_psymbol (name.get (), true,

>> +  ccp->pst->add_psymbol (name, true,


Same here.

>> -      pst->add_psymbol (tname.get (), true,

>> +      pst->add_psymbol (tname, true,


And here.

If you fix these up, and it still works, it is fine to push.
If it doesn't work then that would tend to put some doubt on the other
parts of the patch that don't copy names.

thanks,
Tom
Mike Frysinger via Gdb-patches May 10, 2021, 2:40 a.m. | #2
On 5/7/2021 1:07 PM, Tom Tromey wrote:
>>>>>> ">" == Weimin Pan via Gdb-patches <gdb-patches@sourceware.org> writes:

>>> The problems can be illustrated, with any program, below:

>>> (gdb) print main

>>> $1 = {main} 0x0

> Hi.  Sorry about the delay in my re-review.

> It's fine (and expected) to send patch pings to the list.

> It helps keep us honest I guess.

Sorry about that. Shall follow the protocol by pinging the patch going 
forward.

>

>>> -      sym->compute_and_set_names (name.get (), true, objfile->per_bfd);

>>> +      sym->compute_and_set_names (name, true, objfile->per_bfd);

> If the lifetime of 'name' is ok, then you don't need to copy it here --

> so you can pass 'false' as the second parameter.  See the comment in

> symtab.c just before general_symbol_info::compute_and_set_names.


Thanks - passing 'false' as the second parameter to compute_and_set_names is
the right thing to do. All CTF tests are still passing with the change.

>>> +  name = ctf_type_name_raw (fp, tid);

>>> +  if (name == nullptr || strlen (name) == 0)

>>> +  {

> The braces (and the code they surround) look under-indented to me.


Corrected.

>>> -  ccp->pst->add_psymbol (name.get (), true,

>>> +  ccp->pst->add_psymbol (name, true,

> Same here.


Sorry, the only place I can find is here and it looks indented correctly?

-  if (name == nullptr || strlen (name.get ()) == 0)
+  const char *name = ctf_type_name_raw (ccp->fp, tid);
+  if (name == nullptr || strlen (name) == 0)
      return 0;

-  ccp->pst->add_psymbol (name.get (), true,
+  ccp->pst->add_psymbol (name, true,

>

>>> -      pst->add_psymbol (tname.get (), true,

>>> +      pst->add_psymbol (tname, true,

> And here.


Also the indentation looks correct?

        else
         aclass = LOC_TYPEDEF;

-      pst->add_psymbol (tname.get (), true,
+      pst->add_psymbol (tname, true,

>

> If you fix these up, and it still works, it is fine to push.

> If it doesn't work then that would tend to put some doubt on the other

> parts of the patch that don't copy names.


OK, thank you.

>

> thanks,

> Tom
Tom Tromey May 10, 2021, 2 p.m. | #3
>>>> -  ccp->pst->add_psymbol (name.get (), true,

>>>> +  ccp->pst->add_psymbol (name, true,

>> Same here.


> Sorry, the only place I can find is here and it looks indented correctly?


My apologies - I was unclear here, I meant that the "true" could be
"false" here as well.

>>>> -      pst->add_psymbol (tname.get (), true,

>>>> +      pst->add_psymbol (tname, true,

>> And here.


> Also the indentation looks correct?


This was also the true/false thing, to avoid name copying.

Tom

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e817ba6..8abea2d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@ 
+2021-04-16  Weimin Pan  <weimin.pan@oracle.com>
+
+	* ctfread.c (new_symbol): Set function address.
+	(read_func_kind_type): Remove incorrect type name setting.
+	Use ctf_type_name_raw to get type name throughout file.
+
 2021-04-07  Weimin Pan  <weimin.pan@oracle.com>
 
 	* ctfread.c (fetch_tid_type): New function, use throughout file.
diff --git a/gdb/ctfread.c b/gdb/ctfread.c
index e2b65b6..97355bf 100644
--- a/gdb/ctfread.c
+++ b/gdb/ctfread.c
@@ -462,14 +462,14 @@  struct ctf_tid_and_type
   ctf_dict_t *fp = ccp->fp;
   struct symbol *sym = nullptr;
 
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
+  const char *name = ctf_type_name_raw (fp, tid);
   if (name != nullptr)
     {
       sym = new (&objfile->objfile_obstack) symbol;
       OBJSTAT (objfile, n_syms++);
 
       sym->set_language (language_c, &objfile->objfile_obstack);
-      sym->compute_and_set_names (name.get (), true, objfile->per_bfd);
+      sym->compute_and_set_names (name, true, objfile->per_bfd);
       SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
       SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
 
@@ -487,6 +487,7 @@  struct ctf_tid_and_type
 	    break;
 	  case CTF_K_FUNCTION:
 	    SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
+	    set_symbol_address (objfile, sym, sym->linkage_name ());
 	    break;
 	  case CTF_K_CONST:
 	    if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_VOID)
@@ -525,7 +526,7 @@  struct ctf_tid_and_type
   ctf_dict_t *fp = ccp->fp;
   ctf_encoding_t cet;
   struct type *type = nullptr;
-  char *name;
+  const char *name;
   uint32_t kind;
 
   if (ctf_type_encoding (fp, tid, &cet))
@@ -535,16 +536,15 @@  struct ctf_tid_and_type
       return nullptr;
     }
 
-  gdb::unique_xmalloc_ptr<char> copied_name (ctf_type_aname_raw (fp, tid));
-  if (copied_name == nullptr || strlen (copied_name.get ()) == 0)
-    {
+  name = ctf_type_name_raw (fp, tid);
+  if (name == nullptr || strlen (name) == 0)
+  {
       name = ctf_type_aname (fp, tid);
       if (name == nullptr)
 	complaint (_("ctf_type_aname read_base_type failed - %s"),
 		   ctf_errmsg (ctf_errno (fp)));
-    }
-  else
-    name = obstack_strdup (&of->objfile_obstack, copied_name.get ());
+  }
+
 
   kind = ctf_type_kind (fp, tid);
   if (kind == CTF_K_INTEGER)
@@ -623,9 +623,9 @@  struct ctf_tid_and_type
 
   type = alloc_type (of);
 
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != nullptr && strlen (name.get ()) != 0)
-    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
+  const char *name = ctf_type_name_raw (fp, tid);
+  if (name != nullptr && strlen (name) != 0)
+    type->set_name (name);
 
   kind = ctf_type_kind (fp, tid);
   if (kind == CTF_K_UNION)
@@ -682,10 +682,6 @@  struct ctf_tid_and_type
 
   type = alloc_type (of);
 
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != nullptr && strlen (name.get ()) != 0)
-    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
-
   type->set_code (TYPE_CODE_FUNC);
   ctf_func_type_info (fp, tid, &cfi);
   rettype = fetch_tid_type (ccp, cfi.ctc_return);
@@ -734,9 +730,9 @@  struct ctf_tid_and_type
 
   type = alloc_type (of);
 
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != nullptr && strlen (name.get ()) != 0)
-    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
+  const char *name = ctf_type_name_raw (fp, tid);
+  if (name != nullptr && strlen (name) != 0)
+    type->set_name (name);
 
   type->set_code (TYPE_CODE_ENUM);
   TYPE_LENGTH (type) = ctf_type_size (fp, tid);
@@ -972,9 +968,9 @@  struct ctf_tid_and_type
 
   type = alloc_type (of);
 
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
-  if (name != NULL && strlen (name.get()) != 0)
-    type->set_name (obstack_strdup (&of->objfile_obstack, name.get ()));
+  const char *name = ctf_type_name_raw (fp, tid);
+  if (name != nullptr && strlen (name) != 0)
+    type->set_name (name);
 
   kind = ctf_type_kind_forwarded (fp, tid);
   if (kind == CTF_K_UNION)
@@ -1017,9 +1013,9 @@  struct ctf_tid_and_type
 	break;
       case CTF_K_TYPEDEF:
 	{
-	  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (fp, tid));
+	  const char *name = ctf_type_name_raw (fp, tid);
 	  btid = ctf_type_reference (fp, tid);
-	  type = read_typedef_type (ccp, tid, btid, name.get ());
+	  type = read_typedef_type (ccp, tid, btid, name);
 	}
 	break;
       case CTF_K_VOLATILE:
@@ -1219,8 +1215,7 @@  struct ctf_tid_and_type
   if (ctf_func_args (ccp->fp, idx, argc, argv) == CTF_ERR)
     return nullptr;
 
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, idx));
-  if (name == nullptr)
+  if (ctf_type_name_raw (ccp->fp, idx) == nullptr)
     return nullptr;
 
   tid = ctf_lookup_by_symbol (ccp->fp, idx);
@@ -1444,7 +1439,6 @@  struct ctf_tid_and_type
   short section = -1;
 
   ccp = (struct ctf_context *) arg;
-  gdb::unique_xmalloc_ptr<char> name (ctf_type_aname_raw (ccp->fp, tid));
 
   domain_enum domain = UNDEF_DOMAIN;
   enum address_class aclass = LOC_UNDEF;
@@ -1486,10 +1480,11 @@  struct ctf_tid_and_type
 	return 0;
     }
 
-  if (name == nullptr || strlen (name.get ()) == 0)
+  const char *name = ctf_type_name_raw (ccp->fp, tid);
+  if (name == nullptr || strlen (name) == 0)
     return 0;
 
-  ccp->pst->add_psymbol (name.get (), true,
+  ccp->pst->add_psymbol (name, true,
 			 domain, aclass, section,
 			 psymbol_placement::GLOBAL,
 			 0, language_c, ccp->partial_symtabs, ccp->of);
@@ -1545,7 +1540,7 @@  struct ctf_tid_and_type
 	else
 	  continue;
 	}
-      gdb::unique_xmalloc_ptr<char> tname (ctf_type_aname_raw (cfp, tid));
+      const char *tname = ctf_type_name_raw (cfp, tid);
       uint32_t kind = ctf_type_kind (cfp, tid);
       address_class aclass;
       domain_enum tdomain;
@@ -1568,7 +1563,7 @@  struct ctf_tid_and_type
       else
 	aclass = LOC_TYPEDEF;
 
-      pst->add_psymbol (tname.get (), true,
+      pst->add_psymbol (tname, true,
 			tdomain, aclass, -1,
 			psymbol_placement::STATIC,
 			0, language_c, partial_symtabs, of);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 53333f9..3d800c2 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@ 
+2021-04-16  Weimin Pan  <weimin.pan@oracle.com>
+
+	* gdb.ctf/cross-tu-cyclic.exp: New file.
+	* gdb.ctf/multi.exp: New file.
+
 2021-04-07  Weimin Pan  <weimin.pan@oracle.com>
 
 	* gdb.base/ctf-ptype.c: Add struct link containing a forward
diff --git a/gdb/testsuite/gdb.ctf/funcreturn.exp b/gdb/testsuite/gdb.ctf/funcreturn.exp
new file mode 100644
index 0000000..874160e
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/funcreturn.exp
@@ -0,0 +1,190 @@ 
+# Copyright 2021 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/>.
+
+if [skip_ctf_tests] {
+    unsupported "no CTF debug format support, or CTF disabled in GDB"
+    return 0
+}
+
+if [target_info exists no_long_long] {
+    set exec_opts [list debug additional_flags=-DNO_LONG_LONG]
+} else {
+    set exec_opts [list debug]
+}
+
+standard_testfile whatis.c
+
+# Using `-gt` generates full-fledged CTF debug information.
+set opts "additional_flags=-gt -Wl,--export-dynamic"
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+	  [list $srcfile] [list $opts nowarnings]] } {
+    return 0
+}
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info] {
+    return -1
+}
+
+# test print command with functions return type
+set void "(void|)"
+gdb_test "print v_char_func" \
+    "$decimal = \{char \\(\\)\} 0x\[0-9a-z\]+ <v_char_func>.*" \
+    "print char function"
+
+gdb_test "print v_signed_char_func" \
+    "$decimal = \{signed char \\(\\)\} 0x\[0-9a-z\]+ <v_signed_char_func>.*" \
+    "print signed char function"
+
+gdb_test "print v_unsigned_char_func" \
+    "$decimal = \{unsigned char \\(\\)\} 0x\[0-9a-z\]+ <v_unsigned_char_func>.*" \
+    "print unsigned char function"
+
+gdb_test "print v_short_func" \
+    "$decimal = \{short \\(\\)\} 0x\[0-9a-z\]+ <v_short_func>.*" \
+    "print short function"
+
+gdb_test "print v_signed_short_func" \
+    "$decimal = \{signed short|short \\(\\)\} 0x\[0-9a-z\]+ <v_signed_short_func>.*" \
+    "print signed short function"
+
+gdb_test "print v_unsigned_short_func" \
+    "$decimal = \{unsigned short \\(\\)\} 0x\[0-9a-z\]+ <v_unsigned_short_func>.*" \
+    "print unsigned short function"
+
+gdb_test "print v_int_func" \
+    "$decimal = \{int \\(\\)\} 0x\[0-9a-z\]+ <v_int_func>.*" \
+    "print int function"
+
+gdb_test "print v_signed_int_func" \
+    "$decimal = \{signed int|int \\(\\)\} 0x\[0-9a-z\]+ <v_signed_int_func>.*" \
+    "print signed int function"
+
+gdb_test "print v_unsigned_int_func" \
+    "$decimal = \{unsigned int \\(\\)\} 0x\[0-9a-z\]+ <v_unsigned_int_func>.*" \
+    "print unsigned int function"
+
+gdb_test "print v_long_func" \
+    "$decimal = \{long \\(\\)\} 0x\[0-9a-z\]+ <v_long_func>.*" \
+    "print long function"
+
+gdb_test "print v_signed_long_func" \
+    "$decimal = \{signed long|long \\(\\)\} 0x\[0-9a-z\]+ <v_signed_long_func>.*" \
+    "print signed long function"
+
+gdb_test "print v_unsigned_long_func" \
+    "$decimal = \{unsigned long|long \\(\\)\} 0x\[0-9a-z\]+ <v_unsigned_long_func>.*" \
+    "print unsigned long function"
+
+if ![target_info exists no_long_long] {
+    gdb_test "print v_long_long_func" \
+	    "$decimal = \{long long \\(\\)\} 0x\[0-9a-z\]+ <v_long_long_func>.*" \
+		"print long long function"
+
+    gdb_test "print v_signed_long_long_func" \
+	    "$decimal = \{long long \\(\\)\} 0x\[0-9a-z\]+ <v_signed_long_long_func>.*" \
+		"print signed long long function"
+
+    gdb_test "print v_unsigned_long_long_func" \
+	    "$decimal = \{unsigned long long \\(\\)\} 0x\[0-9a-z\]+ <v_unsigned_long_long_func>.*" \
+		"print unsigned long long function"
+}
+
+# Sun /bin/cc calls this a function returning double.
+if {!$gcc_compiled} then {setup_xfail "*-sun-sunos4*"}
+	gdb_test "print v_float_func" \
+	    "$decimal = \{float \\(\\)\} 0x\[0-9a-z\]+.*" \
+	    "print float function"
+
+	gdb_test "print v_double_func" \
+	    "$decimal = \{double \\(\\)\} 0x\[0-9a-z\]+.*" \
+	    "print double function" \
+}
+
+# test whatis command with functions return type
+gdb_test "whatis v_char_func" \
+    "type = (signed |unsigned |)char \\($void\\)" \
+    "whatis char function"
+
+gdb_test "whatis v_signed_char_func" \
+    "type = (signed |unsigned |)char \\($void\\)" \
+    "whatis signed char function"
+
+gdb_test "whatis v_unsigned_char_func" \
+    "type = unsigned char \\($void\\)"	\
+    "whatis unsigned char function"
+
+gdb_test "whatis v_short_func" \
+    "type = short (int |)\\($void\\)" \
+    "whatis short function"
+
+gdb_test "whatis v_signed_short_func" \
+    "type = (signed |)short (int |)\\($void\\)" \
+    "whatis signed short function"
+
+gdb_test "whatis v_unsigned_short_func" \
+    "type = (unsigned short|short unsigned int) \\($void\\)" \
+    "whatis unsigned short function"
+
+gdb_test "whatis v_int_func" \
+    "type = int \\($void\\)" \
+    "whatis int function"
+
+gdb_test "whatis v_signed_int_func" \
+    "type = (signed |)int \\($void\\)" \
+    "whatis signed int function"
+
+gdb_test "whatis v_unsigned_int_func" \
+    "type = unsigned int \\($void\\)" \
+    "whatis unsigned int function"
+
+gdb_test "whatis v_long_func" \
+    "type = (long|int|long int) \\($void\\)" \
+    "whatis long function"
+
+gdb_test "whatis v_signed_long_func" \
+    "type = (signed |)(int|long|long int) \\($void\\)" \
+    "whatis signed long function"
+
+gdb_test "whatis v_unsigned_long_func" \
+    "type = (unsigned (int|long|long int)|long unsigned int) \\($void\\)" \
+    "whatis unsigned long function"
+
+if ![target_info exists no_long_long] {
+    gdb_test "whatis v_long_long_func" \
+	"type = long long(| int) \\($void\\)" \
+	"whatis long long function"
+
+    gdb_test "whatis v_signed_long_long_func" \
+	"type = (signed |)long long(| int) \\($void\\)" \
+	"whatis signed long long function"
+
+    gdb_test "whatis v_unsigned_long_long_func" \
+	"type = (unsigned long long(| int)|long long unsigned int) \\($void\\)" \
+	"whatis unsigned long long function"
+}
+
+# Sun /bin/cc calls this a function returning double.
+if {!$gcc_compiled} then {setup_xfail "*-sun-sunos4*"}
+	gdb_test "whatis v_float_func" \
+	    "type = float \\($void\\)" \
+	    "whatis float function"
+
+	gdb_test "whatis v_double_func" \
+	    "type = double \\($void\\)" \
+	    "whatis double function" \
+}
diff --git a/gdb/testsuite/gdb.ctf/whatis.c b/gdb/testsuite/gdb.ctf/whatis.c
new file mode 100644
index 0000000..aec899d
--- /dev/null
+++ b/gdb/testsuite/gdb.ctf/whatis.c
@@ -0,0 +1,339 @@ 
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 1992-2021 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 file with lots of different types, for testing the
+ *	"whatis" command.
+ */
+
+/*
+ *	First the basic C types.
+ */
+
+char		v_char;
+signed char	v_signed_char;
+unsigned char	v_unsigned_char;
+
+short		v_short;
+signed short	v_signed_short;
+unsigned short	v_unsigned_short;
+
+int		v_int;
+signed int	v_signed_int;
+unsigned int	v_unsigned_int;
+
+long		v_long;
+signed long	v_signed_long;
+unsigned long	v_unsigned_long;
+
+#ifndef NO_LONG_LONG
+long long		v_long_long;
+signed long long	v_signed_long_long;
+unsigned long long	v_unsigned_long_long;
+#endif
+
+float		v_float;
+double		v_double;
+
+/*
+ *	Now some derived types, which are arrays, functions-returning,
+ *	pointers, structures, unions, and enumerations.
+ */
+
+/**** arrays *******/
+
+char		v_char_array[2];
+signed char	v_signed_char_array[2];
+unsigned char	v_unsigned_char_array[2];
+
+short		v_short_array[2];
+signed short	v_signed_short_array[2];
+unsigned short	v_unsigned_short_array[2];
+
+int		v_int_array[2];
+signed int	v_signed_int_array[2];
+unsigned int	v_unsigned_int_array[2];
+
+long		v_long_array[2];
+signed long	v_signed_long_array[2];
+unsigned long	v_unsigned_long_array[2];
+
+#ifndef NO_LONG_LONG
+long long		v_long_long_array[2];
+signed long long	v_signed_long_long_array[2];
+unsigned long long	v_unsigned_long_long_array[2];
+#endif
+
+float		v_float_array[2];
+double		v_double_array[2];
+
+/**** pointers *******/
+
+/* Make sure they still print as pointer to foo even there is a typedef
+   for that type.  Test this not just for char *, which might be
+   a special case kludge in GDB (Unix system include files like to define
+   caddr_t), but for a variety of types.  */
+typedef char *char_addr;
+char_addr a_char_addr;
+typedef unsigned short *ushort_addr;
+ushort_addr a_ushort_addr;
+typedef signed long *slong_addr;
+slong_addr a_slong_addr;
+#ifndef NO_LONG_LONG
+typedef signed long long *slong_long_addr;
+slong_long_addr a_slong_long_addr;
+#endif
+
+char		*v_char_pointer;
+signed char	*v_signed_char_pointer;
+unsigned char	*v_unsigned_char_pointer;
+
+short		*v_short_pointer;
+signed short	*v_signed_short_pointer;
+unsigned short	*v_unsigned_short_pointer;
+
+int		*v_int_pointer;
+signed int	*v_signed_int_pointer;
+unsigned int	*v_unsigned_int_pointer;
+
+long		*v_long_pointer;
+signed long	*v_signed_long_pointer;
+unsigned long	*v_unsigned_long_pointer;
+
+#ifndef NO_LONG_LONG
+long long		*v_long_long_pointer;
+signed long long	*v_signed_long_long_pointer;
+unsigned long long	*v_unsigned_long_long_pointer;
+#endif
+
+float		*v_float_pointer;
+double		*v_double_pointer;
+
+/**** structs *******/
+
+struct t_struct {
+    char	v_char_member;
+    short	v_short_member;
+    int		v_int_member;
+    long	v_long_member;
+#ifndef NO_LONG_LONG
+    long long	v_long_long_member;
+#endif
+    float	v_float_member;
+    double	v_double_member;
+} v_struct1, *v_struct_ptr1;
+
+struct {
+    char	v_char_member;
+    short	v_short_member;
+    int		v_int_member;
+    long	v_long_member;
+#ifndef NO_LONG_LONG
+    long long	v_long_long_member;
+#endif
+    float	v_float_member;
+    double	v_double_member;
+} v_struct2, *v_struct_ptr2;
+
+/**** unions *******/
+
+union t_union {
+    char	v_char_member;
+    short	v_short_member;
+    int		v_int_member;
+    long	v_long_member;
+#ifndef NO_LONG_LONG
+    long long	v_long_long_member;
+#endif
+    float	v_float_member;
+    double	v_double_member;
+} v_union, *v_union_ptr;
+
+union {
+    char	v_char_member;
+    short	v_short_member;
+    int		v_int_member;
+    long	v_long_member;
+#ifndef NO_LONG_LONG
+    long long	v_long_long_member;
+#endif
+    float	v_float_member;
+    double	v_double_member;
+} v_union2, *v_union_ptr2;
+
+/*** Functions returning type ********/
+
+char		v_char_func () { return(0); }
+signed char	v_signed_char_func () { return (0); }
+unsigned char	v_unsigned_char_func () { return (0); }
+
+short		v_short_func () { return (0); }
+signed short	v_signed_short_func () { return (0); }
+unsigned short	v_unsigned_short_func () { return (0); }
+
+int		v_int_func () { return (0); }
+signed int	v_signed_int_func () { return (0); }
+unsigned int	v_unsigned_int_func () { return (0); }
+
+long		v_long_func () { return (0); }
+signed long	v_signed_long_func () { return (0); }
+unsigned long	v_unsigned_long_func () { return (0); }
+
+#ifndef NO_LONG_LONG
+long long		v_long_long_func () { return (0); }
+signed long long	v_signed_long_long_func () { return (0); }
+unsigned long long	v_unsigned_long_long_func () { return (0); }
+#endif
+
+float		v_float_func () { return (0.0); }
+double		v_double_func () { return (0.0); }
+
+/**** Some misc more complicated things *******/
+
+struct link {
+	struct link *next;
+#ifdef __STDC__
+	struct link *(*linkfunc) (struct link *self, int flags);
+#else
+	struct link *(*linkfunc) ();
+#endif
+	struct t_struct stuff[1][2][3];
+} *s_link;
+
+union tu_link {
+	struct link *next;
+#ifdef __STDC__
+	struct link *(*linkfunc) (struct link *self, int flags);
+#else
+	struct link *(*linkfunc) ();
+#endif
+	struct t_struct stuff[1][2][3];
+} u_link;
+
+struct outer_struct {
+	int outer_int;
+	struct inner_struct {
+		int inner_int;
+		long inner_long;
+	}inner_struct_instance;
+	union inner_union {
+		int inner_union_int;
+		long inner_union_long;
+	}inner_union_instance;
+	long outer_long;
+} nested_su;
+
+/**** Enumerations *******/
+
+enum colors {red, green, blue} color;
+enum cars {chevy, ford, porsche} clunker;
+
+/***********/
+
+int main ()
+{
+  /* Some linkers (e.g. on AIX) remove unreferenced variables,
+     so make sure to reference them. */
+  v_char = 0;
+  v_signed_char = 1;
+  v_unsigned_char = 2;
+
+  v_short = 3;
+  v_signed_short = 4;
+  v_unsigned_short = 5;    
+
+  v_int = 6;
+  v_signed_int = 7;
+  v_unsigned_int = 8;    
+
+  v_long = 9;
+  v_signed_long = 10;
+  v_unsigned_long = 11;    
+
+#ifndef NO_LONG_LONG
+  v_long_long = 12;
+  v_signed_long_long = 13;
+  v_unsigned_long_long = 14;
+#endif
+
+  v_float = 100.0;
+  v_double = 200.0;
+
+
+  v_char_array[0] = v_char;
+  v_signed_char_array[0] = v_signed_char;
+  v_unsigned_char_array[0] = v_unsigned_char;
+
+  v_short_array[0] = v_short;
+  v_signed_short_array[0] = v_signed_short;
+  v_unsigned_short_array[0] = v_unsigned_short;
+
+  v_int_array[0] = v_int;
+  v_signed_int_array[0] = v_signed_int;
+  v_unsigned_int_array[0] = v_unsigned_int;
+
+  v_long_array[0] = v_long;
+  v_signed_long_array[0] = v_signed_long;
+  v_unsigned_long_array[0] = v_unsigned_long;
+
+#ifndef NO_LONG_LONG
+  v_long_long_array[0] = v_long_long;
+  v_signed_long_long_array[0] = v_signed_long_long;
+  v_unsigned_long_long_array[0] = v_unsigned_long_long;
+#endif
+
+  v_float_array[0] = v_float;
+  v_double_array[0] = v_double;
+
+  v_char_pointer = &v_char;
+  v_signed_char_pointer = &v_signed_char;
+  v_unsigned_char_pointer = &v_unsigned_char;
+
+  v_short_pointer = &v_short;
+  v_signed_short_pointer = &v_signed_short;
+  v_unsigned_short_pointer = &v_unsigned_short;
+
+  v_int_pointer = &v_int;
+  v_signed_int_pointer = &v_signed_int;
+  v_unsigned_int_pointer = &v_unsigned_int;
+
+  v_long_pointer = &v_long;
+  v_signed_long_pointer = &v_signed_long;
+  v_unsigned_long_pointer = &v_unsigned_long;
+
+#ifndef NO_LONG_LONG
+  v_long_long_pointer = &v_long_long;
+  v_signed_long_long_pointer = &v_signed_long_long;
+  v_unsigned_long_long_pointer = &v_unsigned_long_long;
+#endif
+
+  v_float_pointer = &v_float;
+  v_double_pointer = &v_double;
+
+  color = red;
+  clunker = porsche;
+
+  u_link.next = s_link;
+
+  v_union2.v_short_member = v_union.v_short_member;
+
+  v_struct1.v_char_member = 0;
+  v_struct2.v_char_member = 0;
+
+  nested_su.outer_int = 0;
+  return 0;
+}