fork(1) download
  1. #include <stdio.h>
  2. #include <stddef.h>
  3. #include <stdlib.h>
  4.  
  5. const int debug = 0;
  6.  
  7. void __pure_virtual_called() {
  8. fputs ("pure virtual function called\n", stderr);
  9. abort();
  10. }
  11.  
  12. /* Translation of:
  13.  
  14. class A
  15. {
  16. public:
  17.   virtual void OutA() = 0;
  18. };
  19. */
  20.  
  21. struct A;
  22.  
  23. typedef struct {
  24. void (*ptr__OutA) (struct A *__this);
  25. } vtable__A;
  26.  
  27. typedef struct A {
  28. vtable__A *__vptr;
  29. } A;
  30.  
  31. /* translation A::OutA()
  32.  * pure virtual function */
  33. void A__OutA (A *__this) {
  34. __pure_virtual_called();
  35. }
  36.  
  37. vtable__A vtable__A__A = { .ptr__OutA = A__OutA };
  38.  
  39. void A__constructor (A *__this) {
  40. if (debug)
  41. printf ("A__constructor %p\n", (void*)__this);
  42.  
  43. /* dynamic type is initialised to A */
  44. __this->__vptr = &vtable__A__A;
  45. }
  46.  
  47. /* Translation of:
  48.  
  49. class B
  50. {
  51. public:
  52.   virtual void OutB() = 0;
  53. };
  54.  
  55. */
  56.  
  57. struct B;
  58.  
  59. typedef struct {
  60. void (*ptr__OutB)(struct B *__this);
  61. } vtable__B;
  62.  
  63. typedef struct B {
  64. vtable__B *__vptr;
  65. } B;
  66.  
  67. /* translation B::OutB()
  68.  * pure virtual function */
  69. void B__OutB (B *__this) {
  70. __pure_virtual_called();
  71. }
  72.  
  73. vtable__B vtable__B__B = { .ptr__OutB = B__OutB };
  74.  
  75. void B__constructor (B *__this) {
  76. if (debug)
  77. printf ("B__constructor %p\n", (void*)__this);
  78.  
  79. /* dynamic type is initialised to B */
  80. __this->__vptr = &vtable__B__B;
  81. }
  82. /* Translation of:
  83.  
  84. class C : public A, public B
  85. {
  86. public:
  87.   void OutA(); // overrides A::OutA()
  88.   void OutB(); // overrides B::OutB()
  89.   // note :
  90.   // no new virtual function
  91. };
  92.  
  93. */
  94.  
  95. /* no new virtual function
  96.  * so no specific vtable type! */
  97.  
  98. typedef struct {
  99. /* no additional vptr, we already have 2! */
  100. A base__A;
  101. B base__B;
  102. } C;
  103.  
  104. /******* upcasts
  105.  * translation of
  106.  * static_cast<C*> (p)
  107.  */
  108.  
  109. /* translation of
  110.  * A *p;
  111.  * static_cast<C*> (p);
  112.  */
  113. C *static_cast__A__C (A *__ptr) {
  114. /*
  115. * base__A is first member of C
  116. * so offsetof(C, base__A) == 0
  117. * can skip the pointer adjustment
  118. */
  119. return (C*)__ptr;
  120. }
  121.  
  122. /* translation of
  123.  * B *p;
  124.  * static_cast<C*> (p);
  125.  */
  126. C *static_cast__B__C (B *__ptr) {
  127. /* locate enclosing C object:
  128. * __base__B is not first member
  129. * need to adjust pointer
  130. */
  131. return (C*)((char*)__ptr - offsetof(C, base__B));
  132. }
  133.  
  134. /* translation of virtual functions of C
  135.  * overriding function declarations from A
  136.  */
  137.  
  138. /* translation of C::OutA() */
  139.  
  140. /* C::OutA() called from C */
  141. void C__OutA (C *__this) {
  142. printf("Out A this=%p\n", (void*)__this);
  143. }
  144.  
  145. /* C::OutA() called from A */
  146. void C__A__OutA (A *__this) {
  147. if (debug)
  148. printf ("C__A__OutA %p\n", (void*)__this);
  149. C__OutA (static_cast__A__C (__this));
  150. }
  151.  
  152. vtable__A vtable__A__C = { .ptr__OutA = C__A__OutA };
  153.  
  154. /* translation of virtual functions of C
  155.  * overriding function declarations from B
  156.  */
  157.  
  158. /* translation of C::OutB() */
  159.  
  160. /* C::OutB() called from C */
  161. void C__OutB (C *__this) {
  162. printf("Out B this=%p\n", (void*)__this);
  163. }
  164.  
  165. /* C::OutB() called from B */
  166. void C__B__OutB (B *__this) {
  167. if (debug)
  168. printf ("C__B__OutB %p\n", (void*)__this);
  169. C__OutB (static_cast__B__C (__this));
  170. }
  171.  
  172. vtable__B vtable__B__C = { .ptr__OutB = C__B__OutB };
  173.  
  174. void C__constructor (C *__this) {
  175. if (debug)
  176. printf ("C__constructor %p\n", (void*)__this);
  177. /* construct subobjects */
  178. A__constructor (&__this->base__A);
  179. B__constructor (&__this->base__B);
  180.  
  181. /* adjust dynamic type of this to C */
  182. __this->base__A.__vptr = &vtable__A__C;
  183. __this->base__B.__vptr = &vtable__B__C;
  184. }
  185.  
  186. /* calls to C virtual functions with a C*
  187.  */
  188.  
  189. /* translation of
  190.  * C *p;
  191.  * p->OutA();
  192.  *
  193.  * is
  194.  * ((A*)p)->OutA();
  195.  *
  196.  * because C::OutA() is overrides A::OutA()
  197.  */
  198. void dyn__C__OutA (C *__this) {
  199. A *base_ptr__A = &__this->base__A;
  200. base_ptr__A->__vptr->ptr__OutA (base_ptr__A);
  201. }
  202.  
  203. /* translation of
  204.  
  205. int main()
  206. {
  207.   C obj;
  208.   obj.OutA();
  209.   obj.OutB();
  210.  
  211.   A *ap = &obj;
  212.   B *bp = &obj;
  213. C *cp = &obj;
  214.  
  215.   ap->OutA();
  216.   bp->OutB();
  217. cp->OutA();
  218.  
  219.   // Return
  220.   return 0;
  221. }
  222.  
  223.  *
  224.  */
  225.  
  226. int main () {
  227. /* translation of:
  228. C obj;
  229. */
  230. C obj;
  231. C__constructor (&obj);
  232.  
  233. /* translation of:
  234. obj.OutA();
  235. obj.OutB();
  236. * obj is a locally declared object
  237. * so dynamic type of obj is known as C
  238. * can make direct call to C::OutA(), C::OutB()
  239. */
  240. C__OutA (&obj);
  241. C__OutB (&obj);
  242.  
  243. /* dumb (zero optimisation) translation of:
  244.   A *ap = &obj;
  245.   B *bp = &obj;
  246. C *cp = &obj;
  247. */
  248. A *ap = &obj.base__A;
  249. B *bp = &obj.base__B;
  250. C *cp = &obj;
  251.  
  252. /* translation of:
  253.   ap->OutA();
  254.   bp->OutB();
  255.   cp->OutA();
  256.  
  257. * dumb compiler = no optimisation
  258. * so dynamic type of *ap, *bp, *cp is unknown
  259. * so make "virtual" calls using vtable
  260. */
  261. ap->__vptr->ptr__OutA(ap);
  262. bp->__vptr->ptr__OutB(bp);
  263. dyn__C__OutA (cp);
  264.  
  265. /* note: obj lifetime ends now
  266. * C has a trivial destructor
  267. * so no destructor call needed
  268. */
  269.  
  270. return 0;
  271. }
  272.  
  273.  
Success #stdin #stdout 0.01s 1676KB
stdin
Standard input is empty
stdout
Out A this=0xbfeee2ec
Out B this=0xbfeee2ec
Out A this=0xbfeee2ec
Out B this=0xbfeee2ec
Out A this=0xbfeee2ec