Nicholas Sherlock <n.sherlock@xxxxxxxxx> writes: > I'm developing a translator which converts code from a language I'm > designing (which is an object-oriented language similar to Java) into > C. At the moment, I'm making heavy use of GCC's GNU99 > statement-blocks-as-expressions extension. This means that the code I > generate can't be used by my friends who use VC++ or other > compilers. I would like to generate code much closer to standard C99. > > At the moment I am using this extension to call virtual methods in my > language. For a virtual call on an object instance "objectexpression", > with a signature like "int square(int)", with "5" as the argument, I > generate this expression: > > ({ struct object_header * temp=objectexpression; ((int(*)(struct > object_header *, int))(temp->vmt[VMTINDEX_MyObject_square]))(temp, > 5);}) > > "struct object_header" is the struct that all of my object types begin > with. "object_header.vmt" is a void** - an array of function pointers > for the VMT of my object. "VMTINDEX_MyObject_square" is the index of > the method I want to call in the VMT. The first argument to the called > function is the address of the object instance being used. > > The problem is that I cannot figure out a good way of writing this > without using this GCC-specific extension. "objectexpression" can have > side effects, so I cannot evaluate it more than once. And yet I need > to use it at least twice: firstly to look up the entry in the object's > VMT, and secondly to provide the evaluated expression as the "this" > argument for the method. Since you are generating C code, you control the horizontal and the vertical. Count the number of virtual calls you have, and emit struct object_header *__my_private_temp_1; struct object_header *__my_private_temp_2; ... at the start of the C function. Then for each virtual call do (__my_private_temp_N = objectexpression, ((int(*)(struct object_header *, int)) (temp->vmt[VMTINDEX_MyObject_square))(__my_private_temp_N, 5))) replacing N with the index of the call. Ian