RE: how to support C type qualifiers applied to arrays?

Gary Funck
2006-12-14T20:22:00Z

> -----Original Message-----
> From: Daniel Jacobowitz
> Sent: Monday, November 27, 2006 3:55 PM
>
> Thanks. Having dug through the archives, Jim's message suggests that
> it should be just a matter of a couple hours for someone interested to
> fix GCC.

The referenced PR is here:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8354

Jim's reply is here,
http://gcc.gnu.org/bugzilla/attachment.cgi?id=12702

After spending a few days on this, I can pretty safely say
that it doesn't appear to me that fixing this in GCC is
straightforward.

The main difficulty is that GCC doesn't create new qualified
types for declarations. Rather, it sets TREE_READONLY()
and TREE_THIS_VOLATILE() in the DECL node for declarations
such as:

volatile int A[10];

Structures add an additional wrinkle:

struct s_struct
{
int a;
float b;
char c[10];
};
volatile struct s_struct S;

Here, GCC sets TREE_THIS_VOLATILE in the DECL node of S,
but does not attempt to clone the type description of
s_struct, and to populate the volatile qualifier across all
contained member types. This works for GCC because it
propagates the qualifiers as it evaluates expressions.
Thus when evaluating S.c[10], GCC starts with the knowledge
that S is volatile, thus S.c is volatile, and S.c[1] is
volatile.

For GCC to fix the problem, it need to rewrite the type
definition for the type of S, along these lines:

typedef volatile int v_int;
typedef volatile float v_float;
typedef volatile char v_char;
struct v_s_struct
{
v_int a;
v_float b;
v_char c[10];
};
typedef volatile struct v_s_struct v_s_t;
v_s_t S;

Typedefs above are used to illustrate that "volatile" must
be factored to the lowest level types of the components,
and must also appear at the struct level to accommodate
operations on the entire structure.

When things are done this way, GDB gets understands
that everything related to S is volatile:

(gdb) ptype S
type = volatile struct v_s_struct {
volatile int a;
volatile float b;
char c[10];
}

well, almost. GDB didn't track the fact that the
struct member "c" is also volatile, because GCC failed
to encode the element type of the array as being
volatile:

<2><70>: Abbrev Number: 6 (DW_TAG_member)
DW_AT_name : c
DW_AT_decl_file : 1
DW_AT_decl_line : 8
DW_AT_type : <94>
DW_AT_data_member_location: 2 byte block: 23 8 (DW_OP_plus_uconst:
8)
<1><94>: Abbrev Number: 2 (DW_TAG_volatile_type)
DW_AT_type : <7d>
<1><7d>: Abbrev Number: 7 (DW_TAG_array_type)
DW_AT_sibling : <8d>
DW_AT_type : <45>
<1><45>: Abbrev Number: 4 (DW_TAG_base_type)
DW_AT_name : (indirect string, offset: 0x3f): char
DW_AT_byte_size : 1
DW_AT_encoding : 6 (signed char)

If GDB tracked the type qualifiers applied during
expression evaluation in a fashion similar to GCC, there
would be no issue.

This lack of ability to properly track qualifiers when
evaluating expressions isn't much of an issue for regular "C",
though it might confuse users of GDB who do things like
ptype S.a
and expect GDB to come back with "volatile int" (in the
first version of the example which did not use typedefs).

To implement debugging of "UPC" programs it
is important to be able to track the "shared" qualifier,
because accesses to shared variables generally requires
callng a runtime procedure in the program being debugged,
or knowledge of the methods for accessing shared variables.

The bottom line is that the fix in GCC appears to be more
difficult than it first appears, and probably the best
approach is for GDB to properly track type qualifiers
as it evaluates expressions.

I'd appreciate hearing from developers more knowledgeable
in the internals of GCC and GDB, to confirm/deny my observations
above, and to perhaps suggest better approaches.