error:Field not supported in union.

Bug #1393017 reported by blueshell

This bug report was converted into a question: question #257655: error:Field not supported in union..

6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Cheerp
Invalid
Undecided
Unassigned

Bug Description

is the error means, cheerp does not support union?

Revision history for this message
blueshell (shell3000) wrote :

I don't know when will it happens.
i will test it to give more detail.

Changed in cheerp:
status: New → Invalid
Revision history for this message
Alessandro Pignotti (a-pignotti) wrote :

Cheerp supports unions containing data (char, short, int, float, double), but not pointers.

Revision history for this message
blueshell (shell3000) wrote :

Ok I just find out that , it does not support struct.
but i did not find the tips on wiki.

if i change the type using static_cast instead of union, is the Cheerp supported?

here are my test file.

// The cheerp/clientlib.h header contains declarations
// for all the browser APIs.
#include <cheerp/clientlib.h>

class Event
{
public:

 struct sMouseEventStruct
 {
  int windowX;
  int windowY;
  int stageX;
  int stageY;
  int mouseId;
  int mouseKey;
  float pressure; //0-1
 } ;

 struct sKeyboardEventStruct
 {
  int keyCode;
  float pressure; //0-1
  int deviceId;
 };

 struct sUserEventStruct
 {
  int userData0;
  int userData1;
  int userData2;
  int userData3;
  int userData4;
  int userData5;
  int userData6;
  int userData7;
 } ;

public:

 Event (){};
public :
 int type;
protected:
 union
 {
  struct sMouseEventStruct _MouseEvent;
  struct sKeyboardEventStruct _KeyboardEvent;
  struct sUserEventStruct _UserEvent;

 } param;
public:
 Event (int evtid)
 {
  type = evtid;
 }

 struct sUserEventStruct* getUserEventStruct()
 {
  return &param._UserEvent;
 }

 const struct sUserEventStruct* getUserEventStruct() const
 {
  return &param._UserEvent;
 }

};

// webMain is the entry point for web applications written in Cheerp.
void webMain()
{
    Event e;
    // client is a C++ namespace that contains all browser APIs
    client::console.log("Hello World Wide Web!");
}

Revision history for this message
Alessandro Pignotti (a-pignotti) wrote :

Cheerp needs strong type safety, so static casting the type will definitely not work .We plan to support your use case in the future, but at the moment you should just avoid the union and use a struct of struct.

Revision history for this message
Alessandro Pignotti (a-pignotti) wrote :

By the way, anonymous structures inside unions are supported, for example

union Vector3
{
    float v[3];
    struct
    {
        float x;
        float y;
        float z;
    }
};

But this is not useful in your case. Sorry about that.

Revision history for this message
blueshell (shell3000) wrote :

union data
{
     struct A a;
     struct B b;
};

i change it to

char data[sizeof(A)];

when i using it
i just (A*)(data);

is it supported?

Revision history for this message
Alessandro Pignotti (a-pignotti) wrote :

That would not work either since it's not type safe. I advise you not to worry too much about memory consumption at the moment and just use 3 structures. Structures inside unions will be fully supported in the future.

Revision history for this message
Alessandro Pignotti (a-pignotti) wrote :

In general, we love to know what kind of projects Cheerp is being used on. If you feel like sharing any information please drop me an email: <email address hidden>

Revision history for this message
blueshell (shell3000) wrote :

I am try to port my little game from cpp to js.
BTW,I port the game from cpp to actionscript3 (Adobe Flash) already (using Adobe Alchemy). and can be played well.
(cpp version is wrote on both opengl and DirectX 11)
so the render code is already totally separated from game logic.

I used to think it will be successfully for i don't use any complex grammar.
but i did use a lot code which type is not safe.
i am worry about the problem.
so it is not the problem of memory consumption.
in your meaning, I don't know which code will error even it compiled successfully.

BTW,my game has a MACRO that ,if the memory pool mode is defined, i will malloc a block memory of enough size. and handle all malloc and free in this memory pool. i think the mode is not supported ?

Revision history for this message
blueshell (shell3000) wrote :

and is there a list to show those code which are not type safe?
and is there any solution for those code?

Revision history for this message
blueshell (shell3000) wrote :

I'v test some code.
such as

struct A
{
 int a;
 int b;
 int c;
};

    A test = {123,145,456};
    int* _convert = (&test.a);

    _convert[0] = 333;//ok
    _convert[1] = 444;//fail

   char buffer[128];
   sprintf(buffer , "a %d , b %d , c %d" , test.a,test.b,test.c);

///////////////////////
so i think cheerp is suitable for create a new project with strict code guide but not port a old project.
some code can be rewrite , but will be too hard to find out.

Revision history for this message
Alessandro Pignotti (a-pignotti) wrote :

About memory pools: yes you should disable them

In general, to be successfully compiled by Cheerp code must be more type safe than usual. The Cheerp compiler is already able to report errors and warning to help you find out some possible issues at compile time, but this is, of course, not perfect and and the moment it won't be able to find the problem in the code you posted. Cheerp has been already used to port very large existing code bases to the Web (~1 millions lines of C++ code), so we believe that, although there is a lot of room for improvements, it is suitable to port an existing project.

It would not be hard to fix this code, for example you could take advantage of anonymous structures inside unions, like this:

union A
{
    struct
    {
        int a;
        int b;
        int c;
     };
     int v[3];
};

    A test;
    test.a = 123;
    test.b = 145;
    test.c = 456;
    int* _convert = test.v;

    _convert[0] = 333;//ok
    _convert[1] = 444;//ok

   char buffer[128];
   sprintf(buffer , "a %d , b %d , c %d" , test.a,test.b,test.c);

Revision history for this message
blueshell (shell3000) wrote :

I know how to fix the code.
but it is hard to find them out (not all code wrote by myself).

in game, we usually use static cast , and when using socket(webSocket),all data will be deal with char[] ,and convert to int or float.

such as
char* _socket_buffer;
short a = *((short*)(_socket_buffer)); _socket_buffer+=2;
float b = *((float *)(_socket_buffer)); _socket_buffer+=4;
int c = *((int*)(_socket_buffer)); _socket_buffer+=4;

i know there is no float supported in javascript; I think the compiler could decode the float in bits (IEEE754),and convert it to double. Is it difficult to implament?

Revision history for this message
blueshell (shell3000) wrote :

I'v test some code.
such as

struct A
{
 int a;
 int b;
 int c;
};

    A test = {123,145,456};
    int* _convert = (&test.a);

    _convert[0] = 333;//ok
    _convert[1] = 444;//fail

   char buffer[128];
   sprintf(buffer , "a %d , b %d , c %d" , test.a,test.b,test.c);

I think it is hard to report errors in compiling for line "_convert[1] = 444;"
do you considering alert it in js runtime, while _DEBUG id defined?

Revision history for this message
blueshell (shell3000) wrote :

and such as

int* a = NULL;
a[0] = 0;

do you considering alert it in js runtime, while _DEBUG id defined?
for some project may not have a pure cpp version to find the error.

Revision history for this message
Alessandro Pignotti (a-pignotti) wrote :

Decoding floats from chars: This is currently supported using unions, for example

union
{
    float f;
    char c[4];
} u;

memcpy(u.c, buffer, 4);
float result = u.f;

Dynamic NULL checks: This is already supported in some cases at no cost, but not always

Dynamic checks for correct assignments: This is actually a good idea and we will consider implementing this. Moreover, in the future the Object.freeze API should make it possible to let the browser do such checks at no cost.

Please note that there is a custom cheerp warning which is emitted on every unsafe type cast. It's a bit too verbose at the moment, but it should be helpful in finding out what code might be problematic.

Revision history for this message
blueshell (shell3000) wrote :

when Cheerp support non-anonymous struct in union i will try it again (hopes new version support win xp)
and in my habit , i always use (A*) ,not static_cast or reinterpret_cast . so it may cost a lot of time to find all of them.

do you consider define a new cast keyword such as cheerp_cast
when using pure cpp version,i can #define cheerp_cast reinterpret_cast

such as:

struct A
{
 int a;
 int b;
 int c;
};

A test = {123,145,456};
int* _convert = cheerp_cast< int*> (&test);
memcpy(cheerp_cast< char*>_convert , _buffer , sizeof(A));

when meet a cheerp_cast , compiler can collect all conversion in context , and generate a local union such as

union cheerp_cast_A
{
    struct
    {
        int a;
        int b;
        int c;
     };
     int cheerp_cast_int[sizeof(A)/sizeof(int)];
     int cheerp_cast_char[sizeof(A)/sizeof(char)];

     inline void fromA(A& in_a) {
        a = in_a.a;
        b = in_a.b;
        c = in_a.c;
     }

      inline void toA(A& out_a) {
       out_a.a = a;
       out_a.b = b;
       out_a.c = c;
     }
};

so the code convert automaticly to follows witch can be supported by cheerp.

A test = {123,145,456};
cheerp_cast_A _tmp;
_tmp.fromA(test);
int* _convert = _tmp.cheerp_cast_int;
memcpy(_tmp.cheerp_cast_char, _buffer , sizeof(A));
_tmp.toA(test);

I know cheerp memory mode is different from Emscripten. so it may hard for unsafe type code.
but I think code conversion is not a complex thing for a compiler.
if you provide a keyword as such cheerp_cast. the source will be more clearly (avoid using union and memcpy for simple convert ).

Revision history for this message
blueshell (shell3000) wrote :

i made a mistake
the line
int cheerp_cast_char[sizeof(A)/sizeof(char)];
should be
char cheerp_cast_char[sizeof(A)/sizeof(char)];

Revision history for this message
blueshell (shell3000) wrote :

such as
float b = *(cheerp_cast<float *>(_socket_buffer)); _socket_buffer+=4;

should convert the code to

inine floart× cheerp_cast_to_float_from_char(char* in_c)
{
  union
  {
     float f;
     char c[4];
  } u_cheerp_cast_to_float_from_char;

 static u_cheerp_cast_to_float_from_char convert;

 convert.c[0] = in_c[0];
 convert.c[1] = in_c[1];
 convert.c[2] = in_c[2];
 convert.c[3] = in_c[3]; //I think 4 bytes , memcpy is slower than this.

return &u_cheerp_cast_to_float_from_char.f;

}

float b = *(cheerp_cast_to_float_from_char(_socket_buffer));

if you deal cheerp_cast as a pretreatment, cheerp can out put a converted file for user to check whether the conversion is correct.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Related questions

Remote bug watches

Bug watches keep track of this bug in other bug trackers.