Thread View: gnu.g++.bug
1 messages
1 total messages
Started by David Detlefs
Mon, 14 Aug 1989 19:51
G++, anonymous unions and gdb
Author: David Detlefs
Date: Mon, 14 Aug 1989 19:51
Date: Mon, 14 Aug 1989 19:51
173 lines
4755 bytes
4755 bytes
Michael et. al. --
Problem: G++ does not produce appropriate symbol table information for
anonymous unions. Consider the following program:
--------------------------------------------------
struct foo {
union {
int i;
char* j;
};
};
void main() {
foo f;
f.i = 7;
f.j = "foofoo";
}
--------------------------------------------------
G++ compiles this without complaint, and, as far as I can tell,
correctly. However, if you compile it with -g, and run it under
gdb, you can get the following script:
b main
Breakpoint 1 at 0xb5: file bug2.c, line 10.
gdb% run
Starting program: /usr0/dld/testing/bug2
Bpt 1, main (1, 2147481872, 2147481880) (bug2.c line 10)
10 f.i = 7;
gdb% p f
$1 = {}
gdb% p f.i
there is no field named i
gdb%
The problem is that when G++ generates symbol-table information for
"struct foo" in dbxout.c, it decides that "foo" has no members,
because it has no named members at the top-level.
Below is a fix to dbxout.c that makes G++ produce symbol-table
information that makes gdb treat members of anonymous unions as if
they are top-level members of the classes in which they occur. That
is, in the above case, you get
gdb% p f
$2 = {i = 0, j = 0x0}
gdb% p f.i
$3 = 0
gdb%
Ideally, we would also like gdb to print out extra sets of curly
braces to indicate which members of f are parts of the same anonymous
union:
gdb% p f
$2 = {{i = 0, j = 0x0}}
gdb% p f.i
$3 = 0
gdb%
...But I can't figure out a way to do this. I suspect that it would
require gdb modifications, since gdb seems to expect each field of a
record to have a name.
In the fix below, note that is important that the solution be
recursive, so that cases such as
--------------------------------------------------
struct bar {
union {
int i;
union {
float f;
char* s;
};
};
};
--------------------------------------------------
get treated correctly -- bar is considered to have three top-level
members i, f, and s that all start at the same offset.
Here is the fix to dbxout.c:
***After line 172, add:
static void dbxout_field ();
***Change the else clause that begins at line 439 to
else
dbxout_field(tem, type);
***Add the following function:
/* Output a field of a record type to the asm file. */
static void dbxout_field (field, type)
register tree field, type;
{
if ( DECL_NAME (field) == 0 )
if ( TREE_CODE( TREE_TYPE (field) ) == UNION_TYPE ) {
/* An anonymous union. Print out a field descriptor for each */
/* member of the union. */
tree tem2;
for (tem2 = TYPE_FIELDS( TREE_TYPE (field) ); tem2;
tem2 = TREE_CHAIN (tem2)) {
dbxout_field(tem2, type);
}
return;
} else
/* Is a null field, only there to take up space. */
return;
/* Otherwise, just output the description of the field. */
if (use_gdb_dbx_extensions || TREE_CODE (field) != CONST_DECL) {
/* Continue the line if necessary, but not before the first field. */
if (field != TYPE_FIELDS (type))
CONTIN;
fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (field)));
CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (field)));
if (use_gdb_dbx_extensions)
{
putc ('/', asmfile);
#ifdef TREE_PRIVATE
putc ((TREE_PRIVATE (field) ? '0' :
TREE_PROTECTED (field) ? '1' : '2'),
asmfile);
#endif
CHARS (2);
}
dbxout_type (TREE_TYPE (field), 0);
if (TREE_CODE (field) == VAR_DECL)
{
if (use_gdb_dbx_extensions)
{
char *name = XSTR (XEXP (DECL_RTL (field), 0), 0);
if (name[0] == '*')
name += 1;
/* Adding 1 here only works on systems
which flush an initial underscore. */
fprintf (asmfile, ":%s;", name+1);
CHARS (strlen (name));
}
else
{
fprintf (asmfile, ",0,0;");
}
}
else if (TREE_CODE (field) == CONST_DECL)
{
/* Only get here if using GDB's extensions to DBX format. */
fprintf (asmfile, "~i%d;", TREE_INT_CST_LOW (DECL_INITIAL (field)));
}
else
{
fprintf (asmfile, ",%d,%d;", DECL_OFFSET (field),
TREE_INT_CST_LOW (DECL_SIZE (field)) *
DECL_SIZE_UNIT (field));
}
CHARS (23);
}
}
Happier hacking.
Dave
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads