Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* C++ nested classes, namespaces, structs, and compound statements
@ 2002-04-05 20:42 Jim Blandy
  2002-04-05 22:05 ` Daniel Berlin
                   ` (4 more replies)
  0 siblings, 5 replies; 38+ messages in thread
From: Jim Blandy @ 2002-04-05 20:42 UTC (permalink / raw)
  To: gdb; +Cc: Benjamin Kosnik, Daniel Berlin


At the moment, GDB doesn't handle C++ namespaces or nested classes
very well.  I have a general idea of how we could address these
limitations, which I'd like to put up for shredding M-DEL discussion.

Let me admit up front that I don't really know C++, so I may be saying
stupid things.  Please set me straight if you notice something.

In C, structs are essentially lists of member names, types, and
locations (offsets from the structure's base address):

  struct S { int x; char y; struct T t; }

(Unions are just the same, except that the offsets are all zero.  That
relationship carries through the entire discussion here, so I'm not
going to talk about unions any more.)

If you think about it just right (or just wrong), this is really very
similar to the set of local variables associated with a compound
statement:

  {
    int x;
    char y;
    struct T t;

    ...
  }

As far as scoping is concerned, this compound statement is also just a
list of names, types, and locations.  The locations here are a bit
less restricted: whereas a struct's members' locations are all offsets
from the start of the struct, a compound statement's variables'
locations can be registers, regions of the stack frame, fixed
addresses (i.e., static variables), and so on.  But just as a struct
type divides up a block of storage into individual members with types,
a compound statement's local variables divide up a function
invocation's stack frame and registers into individual variables with
types.

The analogy isn't perfect, of course.  Structs don't enclose blocks of
code.  And a compound statement is less restricted: it can also
contain typedefs, definitions of struct and enum tags, and so on:

  {
    int x;
    char y;
    struct T t;
    struct L { int j, k; };
    typedef struct L L_t;

    ...
  }

Here the definitions of `struct L' and L_t are local to the compound
statement.  In structs, however, things behave differently: struct
tags defined within another struct have the same scope as the
containing struct; and you can't put typedefs in a struct at all.  So
structs are really very restricted with regards to what they can
contain.

However, C++ loosens a lot of these restrictions, generalizing structs
and classes until they really begin to look very much like compound
statements.  (The only difference between structs and classes in C++
is whether members are public by default.  So I'm not going to talk
about classes any more.)

For example, in C++, you can declare typedefs inside structs:

  $ cat local-typedef.C
  struct S
  {
    typedef int smootz;

    smootz a, b;
  };

  smootz c;
  $ $GccB/g++ -c local-typedef.C 
  local-typedef.C:8: 'smootz' is used as a type, but is not defined as a type.

The compiler accepts the definition of the typedef `smootz' and its
use within `struct S', but outside of S the typedef isn't visible.
Struct tags behave similarly.

You can also declare "static" struct members --- you can access them
with the `->' and `.' operators, just like ordinary members, but
they're actually variables at fixed addresses in the .data segment ---
much like a "static" variable in a C compound statement.  But this
means that a simple offset from a base address is no longer sufficient
to describe a struct's member's location --- you actually start
needing something like GDB's enum address_class.  Multiple inheritance
and virtual base classes introduce further complexity here.

There's another difference between compound statements and structs
goes away.  In C, you can only reference a struct's members using the
`.' and `->' operators, whereas you refer to a compound statement's
variables by simply naming them.  But in C++, a struct's member
functions can refer to the struct's members by simply naming them.
The struct's bindings become another rib in the search path for
identifier bindings.

In summary, the data structure GDB needs to represent C++ structs
(classes, unions, whatever) has a lot of similarities to the structure
GDB needs to represent the local variables of a compound statement.
They both need to carry bindings for several namespaces (ordinary
identifiers and structure tags).  The names can refer to any manner of
things: variables, functions, namespaces, base classes, and so on.
For variables, there are a variety of locations they might occupy.


So I would like to introduce to GDB a new type, `struct environment'
(or is `struct env' better?) which does about the same thing that the
`nsyms' and `sym' members of `struct block', and the `nfields' and
`fields' members of `struct type', do now: it's just a bunch of
bindings for names.  We would use `struct environment':

- in `struct block', to represent the block's local variables, replacing
  `nsyms' and `sym';
- in `struct type', to represent a struct's members, instead of
  `struct fields'; and
- in our representation for C++ namespaces, which seem pretty much
  like structs that can only contain static members and member
  functions (i.e., you can't ever create an instance of one).

There'd be a single set of functions for building `struct environment'
objects, and looking up bindings in them; you'd use it for variable
lookup, and in the `.' and `->' operators.  It could handle hashing,
when appropriate.

Basically, we would take two distinct areas of GDB (and a third,
namespaces, which we haven't implemented yet but will need to), and
support them all with a single structure and a single bunch of
support functions.  GDB would become easier to read.

As a half-baked idea, perhaps a `struct environment' object would have
a list of other `struct environment' objects you should search, too,
if you didn't find what you were looking for.  We could use this to
search a compound statement's enclosing scopes to find bindings
further out, find members inherited from base classes, and resolve C++
`using' declarations.

How does this strike people?

Open issues:

- This "list of other places to search" thing may be ill-formed.  I
  mean, sure, there are a set of similar behaviors going on there, but
  are they similar enough?  For example:
  - You need a frame to find a variable's value, but you need an
    object address to find a member's value.
  - If you find a member in a base class, then you will often
    need to adjust the object's base address in some way.
  - And what about ambiguous member names?
  Maybe these questions mean this `list of other places to search'
  can't be handled in a uniform way.

- What really happens when you start using `struct symbol' objects for
  structure members?  Do we need new address classes now for `offset
  from object base address'?  Does the LOC_COMPUTED idea I've been
  pushing still work?

- How do member functions work in this arrangement?  Virtual member
  functions?  Virtual base classes?

- How would we introduce this incrementally?


^ permalink raw reply	[flat|nested] 38+ messages in thread
* Re: C++ nested classes, namespaces, structs, and compound statements
@ 2002-04-05 22:02 Michael Elizabeth Chastain
  2002-04-05 22:13 ` Daniel Berlin
  0 siblings, 1 reply; 38+ messages in thread
From: Michael Elizabeth Chastain @ 2002-04-05 22:02 UTC (permalink / raw)
  To: gdb, jimb; +Cc: bkoz, dan

I'll bite.

> In summary, the data structure GDB needs to represent C++ structs
> (classes, unions, whatever) has a lot of similarities to the structure
> GDB needs to represent the local variables of a compound statement.

Sounds reasonable to me.

It also sounds dangerous.  It's true that namespaces, structs,
and compound statements are all identifier binding contexts.
But if you start treating a struct as a type of compound statement
you could get into a maze of twisty forced meanings.  You have to
reach down and create a new paradigm and then port both structs
and compound statements to it.

Think about how much context information an identifier-binding-object
needs to do its job.  I think it would be difficult to come up with a
universal context object that both structs and compound statements
can use.  Each identifier-binding-object has its own specialized
context requirements.

> - And what about ambiguous member names?

The C++ language spec says: if class A inherits from both class B and
class C, and both B and C have a member "foo_", then an unqualified
reference to a.foo_ is illegal.  The programmer has to say a::B.foo_
or a::C.foo_.

The last time I checked, gdb just grabs one of the a.foo_ values and
uses it.  I think it would be a lot better for gdb to enforce the
ambiguity rule.

What happens right now if 10 C source files have a static variable
named "i" and I say "print i" and I am not in any of those source
files at the moment?  What *should* happen?

It's late ... I'm rambling.

Michael C


^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2002-04-16 21:58 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-04-05 20:42 C++ nested classes, namespaces, structs, and compound statements Jim Blandy
2002-04-05 22:05 ` Daniel Berlin
2002-04-05 22:34 ` Daniel Jacobowitz
2002-04-05 23:49   ` Daniel Berlin
2002-04-06  7:18     ` Dan Kegel
2002-04-06  9:26     ` Gianni Mariani
2002-04-06 11:57       ` Daniel Berlin
2002-04-08 17:24       ` Jim Blandy
2002-04-08 17:03   ` Jim Blandy
2002-04-08 18:59     ` Daniel Jacobowitz
2002-04-09 18:35       ` Jim Blandy
2002-04-09 20:56         ` Daniel Jacobowitz
2002-04-12 15:08           ` Jim Blandy
2002-04-12 16:32             ` Daniel Jacobowitz
2002-04-08 17:19   ` Jim Blandy
2002-04-08 18:49     ` Daniel Jacobowitz
2002-04-10 10:31       ` Jim Blandy
2002-04-10 12:08         ` Daniel Jacobowitz
2002-04-12 13:58           ` Jim Blandy
2002-04-12 16:56             ` Daniel Jacobowitz
2002-04-16 12:08               ` Jim Blandy
2002-04-16 14:01                 ` Daniel Jacobowitz
2002-04-16 14:52               ` Jim Blandy
2002-04-16 14:58                 ` Daniel Jacobowitz
2002-04-06  6:31 ` Andrew Cagney
2002-04-06  7:58   ` Daniel Berlin
2002-04-08  0:59   ` Joel Brobecker
2002-04-08  2:01     ` Doubt in GDB SathisKanna k
2002-04-06  8:49 ` C++ nested classes, namespaces, structs, and compound statements Per Bothner
2002-04-08 16:29 ` Jim Blandy
2002-04-08 16:48   ` Daniel Jacobowitz
2002-04-09  6:55   ` Petr Sorfa
2002-04-10 10:34     ` Jim Blandy
2002-04-10 12:31       ` Daniel Berlin
2002-04-10 12:53         ` Petr Sorfa
2002-04-05 22:02 Michael Elizabeth Chastain
2002-04-05 22:13 ` Daniel Berlin
2002-04-05 22:30   ` Daniel Berlin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox