[comp.lang.c++] Problems with cfront v2

asc@concurrent.co.uk (Andy Chittenden) (12/19/89)

We have recently purchased version 2 of C++ and have managed to
get it ported to our system V.2 UNIX system.  However, we have hit upon
a snag when taking generated C over to our proprietary platform which
did not occur with version 1.2. 

The C compiler on our proprietary platform is fairly ancient and does
not support enumerated types.  It appears that cfront v2 generates enum
statements when the original source contained enums (for an example use
iostream.h).  With v1.2, cfront did not emit enum statements. Has anyone
come across this problem and found a fix?

In addition, we would like to use virtual inheritence with v2.  However,
we have hit upon a snag.  In v 2.0, objects derived from virtual base
class objects contain pointers to the base class objects.  Our objects
will be saved and retrieved from disk.  Such persistent objects cannot
contain pointers, only relative addresses or offsets.

Below is an example based upon the supplied ZooAnimal classes (note we
do not need virtual functions just virtual inheritence) - we have
anotated the style of generated C that we would require. 

The following simple example illustrates the required changes to the
generated C for access to a virtual base class object.

  class ZooAnimal {
        int a;
        // ...
  };
  class Bear : virtual ZooAnimal {
        int b;
      // ...
  };

  class Raccoon : virtual ZooAnimal {};
  class Panda : Raccoon, Bear {};

  static    Raccoon r:
  static    Panda p:

  main()
  {
   ZooAnimal *a = &(ZooAnimal)p;  // A
   ZooAnimal *b = &(ZooAnimal)r;  // B
   return (0);
  }

Currently, lines A and B are generated as:

 __1a = (((struct ZooAnimal *)(& p )-> PZooAnimal));
 __1b = (((struct ZooAnimal *)(& r )-> PZooAnimal));

where PZooAnimal is declared as
    struct ZooAnimal *PZooAnimal;

within each class derived from ZooAnimal.

In the proposed implementation, PZooAnimal would be declared as int,
and lines A and B would be generated as:


    __1a = (struct ZooAnimal *)((char *) &p + p.PZooAnimal);
    __1b = (struct ZooAnimal *)((char *) &r + r.PZooAnimal);

with the PZooAnimal field in each object having been initialized to
the offset of the ZooAnimal object from the start of the derived object.
For simplicity, changes to initialization code are not shown here.

Note that we do not have to worry about virtual functions and the vtbl
pointer  because virtual functions are not permitted within our
application (it is achieved using a bespoke object manager).

Firstly, does anybody know of any reason why such a change is not
feasible?  Secondly, can anybody point us at the areas of cfront that
would require changing to get such C code generated? 

Rgds, Andy Chittenden
--
             ___________
            / _________/_   |   DOMAIN:     asc@concurrent.co.uk
           /_/________/ /   |   UUCP:       ...!uunet!ukc!concurrent!asc
  Concurrent/__________/    |   Royal Mail: 227 Bath Road
Computer Corporation        |               Slough SL1 4AX, England

roger@decvax.UUCP (Roger H. Scott) (12/21/89)

In article <959@sl10c.concurrent.co.uk> asc@concurrent.co.uk (Andy Chittenden) writes:
>We have recently purchased version 2 of C++ and have managed to
>get it ported to our system V.2 UNIX system.
>...
>In addition, we would like to use virtual inheritence with v2.  However,
>we have hit upon a snag.  In v 2.0, objects derived from virtual base
>class objects contain pointers to the base class objects.  Our objects
>will be saved and retrieved from disk.  Such persistent objects cannot
>contain pointers, only relative addresses or offsets.

We have a similar problem at PROCASE.  Our system (as CASE system for C
programs) is built on a persistent C++ object database.  With a tolerable
amount of grundge we know how to passivate and activate "simple" (1.2 and
2.0 with single inheritance) C++ objects.  The mechanisms used to implement
MI in AT&T's 2.0 are *much* more difficult to passivate and activate - so much
so that we quickly decided that we could not use MI in our work either.  While
this is a significant issue for us, it is far from the most important reason
for our avoiding MI - the outrageous cost in both space and time.  I am
preparing a scathing indictment of AT&T's MI implementation for publication
in this news group sometime soon.  Just to whet your appetites, see if you can
guess how big a single instance of class Der<i> is as a function of <i>, below:

    // all are abstract classes - no data members whatsoever

    struct Base {
	virtual void f();
    };

    struct Der1 : virtual public Base {
    };

    struct Der2 : virtual public Der1 {
    };

    ...

    struct Der<i> : virtual public Der<i-1> {
    };

asc@concurrent.co.uk (Andrew Chittenden,ADT) (01/11/90)

We have recently purchased version 2 of C++ and have managed to
get it ported to our system V.2 UNIX system.  However, we have hit upon
a snag when taking generated C over to our proprietary platform which
did not occur with version 1.2. 

The C compiler on our proprietary platform is fairly ancient and does
not support enumerated types.  It appears that cfront v2 generates enum
statements when the original source contained enums (for an example use
iostream.h).  The generated C doesn't actually use the enums so there is
no requirement to emit them.  With v1.2, cfront did not emit enum
statements.  Has anyone come across this problem and found a fix? 

In addition, we would like to use virtual inheritence with v2.  However,
we have hit upon a snag.  In v 2.0, objects derived from virtual base
class objects contain pointers to the base class objects.  Our objects
will be saved and retrieved from disk.  Such persistent objects cannot
contain pointers, only relative addresses or offsets.

Below is an example based upon the supplied ZooAnimal classes (note we
do not need virtual functions just virtual inheritence) - we have
anotated the style of generated C that we would require. 

The following simple example illustrates the required changes to the
generated C for access to a virtual base class object.

  class ZooAnimal {
        int a;
        // ...
  };
  class Bear : virtual ZooAnimal {
        int b;
      // ...
  };

  class Raccoon : virtual ZooAnimal {};
  class Panda : Raccoon, Bear {};

  static    Raccoon r:
  static    Panda p:

  main()
  {
   ZooAnimal *a = &(ZooAnimal)p;  // A
   ZooAnimal *b = &(ZooAnimal)r;  // B
   return (0);
  }

Currently, lines A and B are generated as:

 __1a = (((struct ZooAnimal *)(& p )-> PZooAnimal));
 __1b = (((struct ZooAnimal *)(& r )-> PZooAnimal));

where PZooAnimal is declared as
    struct ZooAnimal *PZooAnimal;

within each class derived from ZooAnimal.

In the proposed implementation, PZooAnimal would be declared as int,
and lines A and B would be generated as:


    __1a = (struct ZooAnimal *)((char *) &p + p.PZooAnimal);
    __1b = (struct ZooAnimal *)((char *) &r + r.PZooAnimal);

with the PZooAnimal field in each object having been initialized to
the offset of the ZooAnimal object from the start of the derived object.
For simplicity, changes to initialization code are not shown here.

Note that we do not have to worry about virtual functions and the vtbl
pointer  because virtual functions are not permitted within our
application (it is achieved using a bespoke object manager).

Firstly, does anybody know of any reason why such a change is not
feasible?  Secondly, can anybody point us at the areas of cfront that
would require changing to get such C code generated? 

Rgds, Andy Chittenden
- --
             ___________
            / _________/_   |   DOMAIN:     asc@concurrent.co.uk
           /_/________/ /   |   UUCP:       ...!uunet!ukc!concurrent!asc
  Concurrent/__________/    |   Royal Mail: 227 Bath Road
Computer Corporation        |               Slough SL1 4AX, England