compiler/libec; ecere; ide: (Emscripten WIP) Address virtual method issues
[sdk] / compiler / bootstrap / libec / bootstrap / pass15.c
index cbc7edd..8bd85f8 100644 (file)
@@ -51,7 +51,7 @@ typedef unsigned __int64 uint64;
 #include <sys/types.h>
 enum yytokentype
 {
-IDENTIFIER = 258, CONSTANT = 259, STRING_LITERAL = 260, SIZEOF = 261, PTR_OP = 262, INC_OP = 263, DEC_OP = 264, LEFT_OP = 265, RIGHT_OP = 266, LE_OP = 267, GE_OP = 268, EQ_OP = 269, NE_OP = 270, AND_OP = 271, OR_OP = 272, MUL_ASSIGN = 273, DIV_ASSIGN = 274, MOD_ASSIGN = 275, ADD_ASSIGN = 276, SUB_ASSIGN = 277, LEFT_ASSIGN = 278, RIGHT_ASSIGN = 279, AND_ASSIGN = 280, XOR_ASSIGN = 281, OR_ASSIGN = 282, TYPE_NAME = 283, TYPEDEF = 284, EXTERN = 285, STATIC = 286, AUTO = 287, REGISTER = 288, CHAR = 289, SHORT = 290, INT = 291, UINT = 292, INT64 = 293, LONG = 294, SIGNED = 295, UNSIGNED = 296, FLOAT = 297, DOUBLE = 298, CONST = 299, VOLATILE = 300, VOID = 301, VALIST = 302, STRUCT = 303, UNION = 304, ENUM = 305, ELLIPSIS = 306, CASE = 307, DEFAULT = 308, IF = 309, SWITCH = 310, WHILE = 311, DO = 312, FOR = 313, GOTO = 314, CONTINUE = 315, BREAK = 316, RETURN = 317, IFX = 318, ELSE = 319, CLASS = 320, THISCLASS = 321, CLASS_NAME = 322, PROPERTY = 323, SETPROP = 324, GETPROP = 325, NEWOP = 326, RENEW = 327, DELETE = 328, EXT_DECL = 329, EXT_STORAGE = 330, IMPORT = 331, DEFINE = 332, VIRTUAL = 333, ATTRIB = 334, PUBLIC = 335, PRIVATE = 336, TYPED_OBJECT = 337, ANY_OBJECT = 338, _INCREF = 339, EXTENSION = 340, ASM = 341, TYPEOF = 342, WATCH = 343, STOPWATCHING = 344, FIREWATCHERS = 345, WATCHABLE = 346, CLASS_DESIGNER = 347, CLASS_NO_EXPANSION = 348, CLASS_FIXED = 349, ISPROPSET = 350, CLASS_DEFAULT_PROPERTY = 351, PROPERTY_CATEGORY = 352, CLASS_DATA = 353, CLASS_PROPERTY = 354, SUBCLASS = 355, NAMESPACE = 356, NEW0OP = 357, RENEW0 = 358, VAARG = 359, DBTABLE = 360, DBFIELD = 361, DBINDEX = 362, DATABASE_OPEN = 363, ALIGNOF = 364, ATTRIB_DEP = 365, __ATTRIB = 366, BOOL = 367, _BOOL = 368, _COMPLEX = 369, _IMAGINARY = 370, RESTRICT = 371, THREAD = 372, WIDE_STRING_LITERAL = 373
+IDENTIFIER = 258, CONSTANT = 259, STRING_LITERAL = 260, SIZEOF = 261, PTR_OP = 262, INC_OP = 263, DEC_OP = 264, LEFT_OP = 265, RIGHT_OP = 266, LE_OP = 267, GE_OP = 268, EQ_OP = 269, NE_OP = 270, AND_OP = 271, OR_OP = 272, MUL_ASSIGN = 273, DIV_ASSIGN = 274, MOD_ASSIGN = 275, ADD_ASSIGN = 276, SUB_ASSIGN = 277, LEFT_ASSIGN = 278, RIGHT_ASSIGN = 279, AND_ASSIGN = 280, XOR_ASSIGN = 281, OR_ASSIGN = 282, TYPE_NAME = 283, TYPEDEF = 284, EXTERN = 285, STATIC = 286, AUTO = 287, REGISTER = 288, CHAR = 289, SHORT = 290, INT = 291, UINT = 292, INT64 = 293, LONG = 294, SIGNED = 295, UNSIGNED = 296, FLOAT = 297, DOUBLE = 298, CONST = 299, VOLATILE = 300, VOID = 301, VALIST = 302, STRUCT = 303, UNION = 304, ENUM = 305, ELLIPSIS = 306, CASE = 307, DEFAULT = 308, IF = 309, SWITCH = 310, WHILE = 311, DO = 312, FOR = 313, GOTO = 314, CONTINUE = 315, BREAK = 316, RETURN = 317, IFX = 318, ELSE = 319, CLASS = 320, THISCLASS = 321, CLASS_NAME = 322, PROPERTY = 323, SETPROP = 324, GETPROP = 325, NEWOP = 326, RENEW = 327, DELETE = 328, EXT_DECL = 329, EXT_STORAGE = 330, IMPORT = 331, DEFINE = 332, VIRTUAL = 333, ATTRIB = 334, PUBLIC = 335, PRIVATE = 336, TYPED_OBJECT = 337, ANY_OBJECT = 338, _INCREF = 339, EXTENSION = 340, ASM = 341, TYPEOF = 342, WATCH = 343, STOPWATCHING = 344, FIREWATCHERS = 345, WATCHABLE = 346, CLASS_DESIGNER = 347, CLASS_NO_EXPANSION = 348, CLASS_FIXED = 349, ISPROPSET = 350, CLASS_DEFAULT_PROPERTY = 351, PROPERTY_CATEGORY = 352, CLASS_DATA = 353, CLASS_PROPERTY = 354, SUBCLASS = 355, NAMESPACE = 356, NEW0OP = 357, RENEW0 = 358, VAARG = 359, DBTABLE = 360, DBFIELD = 361, DBINDEX = 362, DATABASE_OPEN = 363, ALIGNOF = 364, ATTRIB_DEP = 365, __ATTRIB = 366, BOOL = 367, _BOOL = 368, _COMPLEX = 369, _IMAGINARY = 370, RESTRICT = 371, THREAD = 372, WIDE_STRING_LITERAL = 373, BUILTIN_OFFSETOF = 374
 };
 
 extern int returnCode;
@@ -1380,6 +1380,11 @@ struct
 struct Expression * exp;
 struct TypeName * typeName;
 } ecere_gcc_struct vaArg;
+struct
+{
+struct TypeName * typeName;
+struct Identifier * id;
+} ecere_gcc_struct offset;
 } ecere_gcc_struct __anon1;
 unsigned int debugValue;
 struct __ecereNameSpace__ecere__com__DataValue val;
@@ -1395,6 +1400,9 @@ unsigned int addedThis;
 unsigned int needCast;
 unsigned int thisPtr;
 unsigned int opDestType;
+unsigned int usedInComparison;
+unsigned int ambiguousUnits;
+unsigned int parentOpDestType;
 unsigned int needTemplateCast;
 } ecere_gcc_struct;
 
@@ -7574,7 +7582,7 @@ struct Type * type = exp->expType;
 
 if(type)
 {
-while(type->kind == 8 && type->__anon1._class->__anon1.registered && (type->__anon1._class->__anon1.registered->type == 2 || type->__anon1._class->__anon1.registered->type == 3 || type->__anon1._class->__anon1.registered->type == 4))
+while(type->kind == 8 && type->__anon1._class && type->__anon1._class->__anon1.registered && (type->__anon1._class->__anon1.registered->type == 2 || type->__anon1._class->__anon1.registered->type == 3 || type->__anon1._class->__anon1.registered->type == 4))
 {
 if(!type->__anon1._class->__anon1.registered->dataType)
 type->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type->__anon1._class->__anon1.registered->dataTypeString, 0);
@@ -7930,6 +7938,15 @@ break;
 }
 }
 
+unsigned int RelatedUnits(struct __ecereNameSpace__ecere__com__Class * c1, struct __ecereNameSpace__ecere__com__Class * c2)
+{
+if(c1->base->type == 3)
+c1 = c1->base;
+if(c2->base->type == 3)
+c2 = c2->base;
+return c1 == c2;
+}
+
 extern char *  __ecereNameSpace__ecere__com__PrintString(struct __ecereNameSpace__ecere__com__Class * class, const void * object, ...);
 
 extern struct __ecereNameSpace__ecere__com__Class * __ecereClass___ecereNameSpace__ecere__sys__TempFile;
@@ -8228,17 +8245,27 @@ unsigned int backOutputLineNumbers = outputLineNumbers;
 outputLineNumbers = 0;
 if(exp)
 OutputExpression(exp, f);
-((unsigned int (*)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode))__extension__ ({
+(__extension__ ({
+unsigned int (*  __internal_VirtualMethod)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode);
+
+__internal_VirtualMethod = ((unsigned int (*)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode))__extension__ ({
 struct __ecereNameSpace__ecere__com__Instance * __internal_ClassInst = f;
 
 __internal_ClassInst ? __internal_ClassInst->_vTbl : __ecereClass___ecereNameSpace__ecere__sys__TempFile->_vTbl;
-})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Seek])(f, 0, 0);
+})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Seek]);
+__internal_VirtualMethod ? __internal_VirtualMethod(f, 0, 0) : (unsigned int)1;
+}));
 count = strlen(string);
-count += ((int (*)(struct __ecereNameSpace__ecere__com__Instance *, void *  buffer, unsigned int size, unsigned int count))__extension__ ({
+count += (__extension__ ({
+int (*  __internal_VirtualMethod)(struct __ecereNameSpace__ecere__com__Instance *, void *  buffer, unsigned int size, unsigned int count);
+
+__internal_VirtualMethod = ((int (*)(struct __ecereNameSpace__ecere__com__Instance *, void *  buffer, unsigned int size, unsigned int count))__extension__ ({
 struct __ecereNameSpace__ecere__com__Instance * __internal_ClassInst = f;
 
 __internal_ClassInst ? __internal_ClassInst->_vTbl : __ecereClass___ecereNameSpace__ecere__sys__TempFile->_vTbl;
-})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Read])(f, string + count, 1, 1023);
+})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Read]);
+__internal_VirtualMethod ? __internal_VirtualMethod(f, string + count, 1, 1023) : (int)1;
+}));
 string[count] = '\0';
 (__ecereNameSpace__ecere__com__eInstance_DecRef(f), f = 0);
 outputLineNumbers = backOutputLineNumbers;
@@ -8299,7 +8326,11 @@ FreeExpContents(checkedExp);
 FreeType(checkedExp->expType);
 FreeType(checkedExp->destType);
 *checkedExp = *newExp;
-((newExp ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)newExp) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(newExp)) : 0), newExp = 0);
+((newExp ? __extension__ ({
+void * __ecerePtrToDelete = (newExp);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), newExp = 0);
 checkedExp->prev = prev;
 checkedExp->next = next;
 }
@@ -8308,30 +8339,49 @@ void FinishTemplatesContext(struct Context * context)
 {
 PopContext(context);
 FreeContext(context);
-((context ? (__ecereClass_Context->Destructor ? __ecereClass_Context->Destructor((void *)context) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(context)) : 0), context = 0);
+((context ? __extension__ ({
+void * __ecerePtrToDelete = (context);
+
+__ecereClass_Context->Destructor ? __ecereClass_Context->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), context = 0);
 }
 
 static __attribute__((unused)) void UnusedFunction()
 {
 int a;
 
-((const char *  (*)(struct __ecereNameSpace__ecere__com__Class *, const void *, char *  tempString, void *  fieldData, unsigned int *  needClass))__ecereClass_int->_vTbl[__ecereVMethodID_class_OnGetString])(__ecereClass_int, (void *)&a, 0, 0, 0);
+(__extension__ ({
+const char *  (*  __internal_VirtualMethod)(struct __ecereNameSpace__ecere__com__Class * , const void * , char *  tempString, void *  fieldData, unsigned int *  needClass);
+
+__internal_VirtualMethod = ((const char *  (*)(struct __ecereNameSpace__ecere__com__Class *, const void *, char *  tempString, void *  fieldData, unsigned int *  needClass))__ecereClass_int->_vTbl[__ecereVMethodID_class_OnGetString]);
+__internal_VirtualMethod ? __internal_VirtualMethod(__ecereClass_int, (void *)&a, 0, 0, 0) : (const char * )1;
+}));
 }
 
 struct Expression * ParseExpressionString(char * expression)
 {
 parseError = 0;
 fileInput = __ecereNameSpace__ecere__com__eInstance_New(__ecereClass___ecereNameSpace__ecere__sys__TempFile);
-((int (*)(struct __ecereNameSpace__ecere__com__Instance *, const void *  buffer, unsigned int size, unsigned int count))__extension__ ({
+(__extension__ ({
+int (*  __internal_VirtualMethod)(struct __ecereNameSpace__ecere__com__Instance *, const void *  buffer, unsigned int size, unsigned int count);
+
+__internal_VirtualMethod = ((int (*)(struct __ecereNameSpace__ecere__com__Instance *, const void *  buffer, unsigned int size, unsigned int count))__extension__ ({
 struct __ecereNameSpace__ecere__com__Instance * __internal_ClassInst = fileInput;
 
 __internal_ClassInst ? __internal_ClassInst->_vTbl : __ecereClass___ecereNameSpace__ecere__sys__File->_vTbl;
-})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Write])(fileInput, expression, 1, strlen(expression));
-((unsigned int (*)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode))__extension__ ({
+})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Write]);
+__internal_VirtualMethod ? __internal_VirtualMethod(fileInput, expression, 1, strlen(expression)) : (int)1;
+}));
+(__extension__ ({
+unsigned int (*  __internal_VirtualMethod)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode);
+
+__internal_VirtualMethod = ((unsigned int (*)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode))__extension__ ({
 struct __ecereNameSpace__ecere__com__Instance * __internal_ClassInst = fileInput;
 
 __internal_ClassInst ? __internal_ClassInst->_vTbl : __ecereClass___ecereNameSpace__ecere__sys__File->_vTbl;
-})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Seek])(fileInput, 0, 0);
+})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Seek]);
+__internal_VirtualMethod ? __internal_VirtualMethod(fileInput, 0, 0) : (unsigned int)1;
+}));
 echoOn = 0;
 parsedExpression = (((void *)0));
 resetScanner();
@@ -9873,6 +9923,8 @@ if(!id->_class || !id->_class->__anon1.__anon1.name || strcmp(id->_class->__anon
 {
 for(ctx = curContext; ctx != topContext->parent && !symbol; ctx = ctx->parent)
 {
+if(!ctx)
+break;
 symbol = (struct Symbol *)__ecereMethod___ecereNameSpace__ecere__sys__BinaryTree_FindString(&ctx->symbols, id->string);
 if(symbol)
 break;
@@ -10092,7 +10144,11 @@ if(exp->destType)
 exp->destType->refCount--;
 if(exp->expType)
 exp->expType->refCount--;
-((newExp ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)newExp) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(newExp)) : 0), newExp = 0);
+((newExp ? __extension__ ({
+void * __ecerePtrToDelete = (newExp);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), newExp = 0);
 }
 else
 {
@@ -10156,7 +10212,11 @@ if(exp->destType)
 exp->destType->refCount--;
 if(exp->expType)
 exp->expType->refCount--;
-((newExp ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)newExp) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(newExp)) : 0), newExp = 0);
+((newExp ? __extension__ ({
+void * __ecerePtrToDelete = (newExp);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), newExp = 0);
 }
 else
 {
@@ -10214,7 +10274,11 @@ if(type)
 {
 FreeType(exp->destType);
 FreeType(exp->expType);
-((newExp ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)newExp) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(newExp)) : 0), newExp = 0);
+((newExp ? __extension__ ({
+void * __ecerePtrToDelete = (newExp);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), newExp = 0);
 break;
 }
 }
@@ -10688,7 +10752,7 @@ if(_class->structAlignment)
 if(_class->memberOffset % _class->structAlignment)
 extra += _class->structAlignment - (_class->memberOffset % _class->structAlignment);
 }
-_class->structSize = (_class->base ? (_class->base->templateClass ? _class->base->templateClass->structSize : _class->base->structSize) : 0) + _class->memberOffset + extra;
+_class->structSize = (_class->base ? (_class->base->templateClass ? (_class->base->type == 5 ? _class->base->templateClass->memberOffset : _class->base->templateClass->structSize) : (_class->base->type == 5 ? _class->base->memberOffset : _class->base->structSize)) : 0) + _class->memberOffset + extra;
 if(!member)
 {
 struct __ecereNameSpace__ecere__com__Property * prop;
@@ -10711,7 +10775,7 @@ struct __ecereNameSpace__ecere__com__Class * deriv = derivative->data;
 
 if(deriv->computeSize)
 {
-deriv->offset = _class->structSize;
+deriv->offset = (_class->type == 5 ? _class->memberOffset : _class->structSize);
 deriv->memberOffset = 0;
 deriv->structSize = deriv->offset;
 ComputeClassMembers(deriv, 0);
@@ -10920,7 +10984,7 @@ else if(source->__anon1._class && dest->__anon1._class && (dest->classObjectType
 return 1;
 else
 {
-if(enumBaseType && dest->__anon1._class && dest->__anon1._class->__anon1.registered && dest->__anon1._class->__anon1.registered->type == 4 && ((source->__anon1._class && source->__anon1._class->__anon1.registered && source->__anon1._class->__anon1.registered->type != 4) || source->kind == 8))
+if(dest->__anon1._class && dest->__anon1._class->__anon1.registered && source->__anon1._class && source->__anon1._class->__anon1.registered && (dest->casted || (enumBaseType && dest->__anon1._class->__anon1.registered->type == 4 && (source->kind == 8 || source->__anon1._class->__anon1.registered->type != 4))))
 {
 if(__ecereNameSpace__ecere__com__eClass_IsDerived(dest->__anon1._class->__anon1.registered, source->__anon1._class->__anon1.registered))
 {
@@ -11752,7 +11816,11 @@ FreeExpContents(exp);
 FreeType(exp->expType);
 FreeType(exp->destType);
 *exp = *exp2;
-((exp2 ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)exp2) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(exp2)) : 0), exp2 = 0);
+((exp2 ? __extension__ ({
+void * __ecerePtrToDelete = (exp2);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), exp2 = 0);
 break;
 }
 case '-':
@@ -12428,7 +12496,6 @@ struct External * _DeclareStruct(struct External * neededBy, const char * name,
 struct External * external = (((void *)0));
 struct Symbol * classSym = FindClass(name);
 struct __ecereNameSpace__ecere__sys__OldList * curDeclarations = (((void *)0));
-struct Specifier * curSpec = (((void *)0));
 
 if(!inCompiler || !classSym)
 return (((void *)0));
@@ -12444,7 +12511,6 @@ struct Specifier * spec;
 for(spec = external->__anon1.declaration->__anon1.__anon1.specifiers ? (*external->__anon1.declaration->__anon1.__anon1.specifiers).first : (((void *)0)); spec; spec = spec->next)
 if(spec->type == 3 || spec->type == 4)
 {
-curSpec = spec;
 curDeclarations = spec->__anon1.__anon2.definitions;
 break;
 }
@@ -12455,15 +12521,14 @@ struct __ecereNameSpace__ecere__sys__OldList * specifiers, * declarators;
 struct __ecereNameSpace__ecere__sys__OldList * declarations = (((void *)0));
 char structName[1024];
 unsigned int addedPadding = 0;
+struct Specifier * curSpec = (((void *)0));
 
 classSym->declaring++;
 if(strchr(classSym->string, '<'))
 {
 if(classSym->__anon1.registered->templateClass)
-{
 external = _DeclareStruct(neededBy, classSym->__anon1.registered->templateClass->fullName, skipNoHead, needDereference, fwdDecl);
 classSym->declaring--;
-}
 return external;
 }
 structName[0] = 0;
@@ -12485,6 +12550,18 @@ if(!skipNoHead)
 declarations = MkList();
 AddMembers(external, declarations, classSym->__anon1.registered, 0, (((void *)0)), classSym->__anon1.registered, &addedPadding);
 }
+if(external->__anon1.declaration)
+{
+struct Specifier * spec;
+
+for(spec = external->__anon1.declaration->__anon1.__anon1.specifiers ? (*external->__anon1.declaration->__anon1.__anon1.specifiers).first : (((void *)0)); spec; spec = spec->next)
+if(spec->type == 3 || spec->type == 4)
+{
+curSpec = spec;
+curDeclarations = spec->__anon1.__anon2.definitions;
+break;
+}
+}
 if(declarations && (!(*declarations).count || ((*declarations).count == 1 && addedPadding)))
 {
 FreeList(declarations, (void *)(FreeClassDef));
@@ -12975,7 +13052,11 @@ struct Conversion * convert = converts.first;
 __ecereMethod___ecereNameSpace__ecere__sys__OldList_Remove(&converts, convert);
 __ecereMethod___ecereNameSpace__ecere__sys__OldList_Add(conversions, convert);
 }
-((type ? (__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)type) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(type)) : 0), type = 0);
+((type ? __extension__ ({
+void * __ecerePtrToDelete = (type);
+
+__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), type = 0);
 return 1;
 }
 }
@@ -12983,7 +13064,11 @@ return 1;
 }
 if(converts.first)
 __ecereMethod___ecereNameSpace__ecere__sys__OldList_Free(&converts, (void *)(FreeConvert));
-((type ? (__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)type) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(type)) : 0), type = 0);
+((type ? __extension__ ({
+void * __ecerePtrToDelete = (type);
+
+__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), type = 0);
 }
 }
 for(nameSpace = (struct __ecereNameSpace__ecere__com__NameSpace *)__ecereProp___ecereNameSpace__ecere__sys__BinaryTree_Get_first(&nameSpace->nameSpaces); nameSpace != (((void *)0)); nameSpace = (struct __ecereNameSpace__ecere__com__NameSpace *)__ecereProp___ecereNameSpace__ecere__sys__BTNode_Get_next(((struct __ecereNameSpace__ecere__sys__BTNode *)nameSpace)))
@@ -13146,13 +13231,23 @@ struct __ecereNameSpace__ecere__sys__OldList * list = exp->__anon1.list;
 struct Expression * prev = exp->prev;
 struct Expression * next = exp->next;
 
+if(exp->expType && exp->expType->kind == 8 && (!e->expType || e->expType->kind != 8))
+{
+FreeType(e->expType);
+e->expType = exp->expType;
+e->expType->refCount++;
+}
 ComputeExpression(e);
 FreeType(exp->expType);
 FreeType(exp->destType);
 *exp = *e;
 exp->prev = prev;
 exp->next = next;
-((e ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)e) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(e)) : 0), e = 0);
+((e ? __extension__ ({
+void * __ecerePtrToDelete = (e);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), e = 0);
 (__ecereNameSpace__ecere__com__eSystem_Delete(list), list = 0);
 }
 else
@@ -13871,7 +13966,7 @@ value = strtoll(computedExp->__anon1.__anon1.constant, (((void *)0)), 0);
 else
 value = strtoull(computedExp->__anon1.__anon1.constant, (((void *)0)), 0);
 }
-else if(computedExp->type == 4 && sourceExp->__anon1.op.op == '-' && !computedExp->__anon1.op.exp1 && computedExp->__anon1.op.exp2 && computedExp->__anon1.op.exp2->type == 2)
+else if(computedExp->type == 4 && computedExp->__anon1.op.op == '-' && !computedExp->__anon1.op.exp1 && computedExp->__anon1.op.exp2 && computedExp->__anon1.op.exp2->type == 2)
 {
 if(source->isSigned)
 value = -strtoll(computedExp->__anon1.op.exp2->__anon1.__anon1.constant, (((void *)0)), 0);
@@ -13927,7 +14022,11 @@ sourceExp->expType = dest;
 dest->refCount++;
 }
 flag = 1;
-((tempType ? (__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)tempType) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(tempType)) : 0), tempType = 0);
+((tempType ? __extension__ ({
+void * __ecerePtrToDelete = (tempType);
+
+__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), tempType = 0);
 }
 }
 if(_class && _class->type == 2 && source->kind != 8)
@@ -14012,7 +14111,11 @@ dest->classObjectType = source->classObjectType;
 FreeType(source);
 source = _class->dataType;
 source->refCount++;
-((tempType ? (__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)tempType) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(tempType)) : 0), tempType = 0);
+((tempType ? __extension__ ({
+void * __ecerePtrToDelete = (tempType);
+
+__ecereClass_Type->Destructor ? __ecereClass_Type->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), tempType = 0);
 }
 }
 }
@@ -14138,7 +14241,13 @@ ListAdd(specs, MkSpecifier(BOOL));
 else if(dest->kind == 1 && (source->kind == 24 || source->kind == 1 || source->kind == 15 || source->kind == 2 || source->kind == 3) && (dest->isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
 {
 if(source->kind == 3)
+{
+FreeType(dest);
+FreeType(source);
+if(backupSourceExpType)
+FreeType(backupSourceExpType);
 return 1;
+}
 else
 {
 specs = MkList();
@@ -14150,7 +14259,13 @@ ListAdd(specs, MkSpecifier(CHAR));
 else if(dest->kind == 2 && (source->kind == 15 || source->kind == 24 || source->kind == 1 || source->kind == 2 || (source->kind == 3 && (dest->isSigned ? (value >= -32768 && value <= 32767) : (value >= 0 && value <= 65535)))))
 {
 if(source->kind == 3)
+{
+FreeType(dest);
+FreeType(source);
+if(backupSourceExpType)
+FreeType(backupSourceExpType);
 return 1;
+}
 else
 {
 specs = MkList();
@@ -14671,7 +14786,7 @@ if(spec->__anon1.specifier == TYPED_OBJECT)
 struct Declarator * d = param->declarator;
 struct TypeName * newParam = (newParam = __ecereNameSpace__ecere__com__eInstance_New(__ecereClass_TypeName), newParam->qualifiers = MkListOne(MkSpecifier(VOID)), newParam->declarator = MkDeclaratorPointer(MkPointer((((void *)0)), (((void *)0))), d), newParam);
 
-if(d->type != 5)
+if(!d || d->type != 5)
 __ecereMethod___ecereNameSpace__ecere__sys__OldList_Insert((&*newParam->qualifiers), (((void *)0)), MkSpecifier(CONST));
 FreeList(param->qualifiers, (void *)(FreeSpecifier));
 param->qualifiers = MkListOne(MkStructOrUnion(3, MkIdentifier("__ecereNameSpace__ecere__com__Class"), (((void *)0))));
@@ -14687,7 +14802,7 @@ struct Declarator * d = param->declarator;
 
 FreeList(param->qualifiers, (void *)(FreeSpecifier));
 param->qualifiers = MkListOne(MkSpecifier(VOID));
-if(d->type != 5)
+if(!d || d->type != 5)
 __ecereMethod___ecereNameSpace__ecere__sys__OldList_Insert((&*param->qualifiers), (((void *)0)), MkSpecifier(CONST));
 param->declarator = MkDeclaratorPointer(MkPointer((((void *)0)), (((void *)0))), d);
 break;
@@ -14708,6 +14823,13 @@ else if(spec->type == 1)
 {
 ProcessSpecifier(spec, isFunction, 1);
 }
+else if((spec->type == 3 || spec->type == 4) && !spec->__anon1.__anon2.definitions && spec->__anon1.__anon2.id && spec->__anon1.__anon2.id->string)
+{
+struct Declarator * d = param->declarator;
+
+if(!d || d->type != 5)
+DeclareStruct(curExternal, spec->__anon1.__anon2.id->string, 0, 1);
+}
 }
 }
 if(param->declarator)
@@ -15682,7 +15804,11 @@ ProcessClass(_class->definitions, _class->symbol);
 if(inCompiler)
 {
 __ecereMethod___ecereNameSpace__ecere__sys__OldList_Remove((&*ast), external);
-((external ? (__ecereClass_External->Destructor ? __ecereClass_External->Destructor((void *)external) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(external)) : 0), external = 0);
+((external ? __extension__ ({
+void * __ecerePtrToDelete = (external);
+
+__ecereClass_External->Destructor ? __ecereClass_External->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), external = 0);
 }
 }
 else if(external->type == 4)
@@ -15739,8 +15865,13 @@ break;
 }
 else
 {
-struct Symbol * symbol = FindSymbol(id->string, curContext, topContext, 0, id->_class && id->_class->__anon1.__anon1.name == (((void *)0)));
+struct Symbol * symbol = (((void *)0));
+unsigned int findInGlobal = 0;
 
+if(!topContext->parent && exp->destType && exp->destType->kind == 8 && exp->destType->__anon1._class && exp->destType->__anon1._class->__anon1.registered && exp->destType->__anon1._class->__anon1.registered->type == 4)
+findInGlobal = 1;
+else
+symbol = FindSymbol(id->string, curContext, topContext, 0, id->_class && id->_class->__anon1.__anon1.name == (((void *)0)));
 if(!symbol)
 {
 if(exp->destType && CheckExpressionType(exp, exp->destType, 0, 0))
@@ -15764,6 +15895,8 @@ break;
 symbol = FindSymbol(id->string, topContext->parent, globalContext, 0, id->_class && id->_class->__anon1.__anon1.name == (((void *)0)));
 }
 }
+if(findInGlobal)
+symbol = FindSymbol(id->string, curContext, topContext, 0, id->_class && id->_class->__anon1.__anon1.name == (((void *)0)));
 if(symbol)
 {
 struct Type * type = symbol->type;
@@ -15844,16 +15977,26 @@ struct __ecereNameSpace__ecere__com__Instance * backInput = fileInput;
 
 definedExpStack[definedExpStackPos++] = definedExp;
 fileInput = __ecereNameSpace__ecere__com__eInstance_New(__ecereClass___ecereNameSpace__ecere__sys__TempFile);
-((int (*)(struct __ecereNameSpace__ecere__com__Instance *, const void *  buffer, unsigned int size, unsigned int count))__extension__ ({
+(__extension__ ({
+int (*  __internal_VirtualMethod)(struct __ecereNameSpace__ecere__com__Instance *, const void *  buffer, unsigned int size, unsigned int count);
+
+__internal_VirtualMethod = ((int (*)(struct __ecereNameSpace__ecere__com__Instance *, const void *  buffer, unsigned int size, unsigned int count))__extension__ ({
 struct __ecereNameSpace__ecere__com__Instance * __internal_ClassInst = fileInput;
 
 __internal_ClassInst ? __internal_ClassInst->_vTbl : __ecereClass___ecereNameSpace__ecere__sys__File->_vTbl;
-})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Write])(fileInput, definedExp->value, 1, strlen(definedExp->value));
-((unsigned int (*)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode))__extension__ ({
+})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Write]);
+__internal_VirtualMethod ? __internal_VirtualMethod(fileInput, definedExp->value, 1, strlen(definedExp->value)) : (int)1;
+}));
+(__extension__ ({
+unsigned int (*  __internal_VirtualMethod)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode);
+
+__internal_VirtualMethod = ((unsigned int (*)(struct __ecereNameSpace__ecere__com__Instance *, int pos, int mode))__extension__ ({
 struct __ecereNameSpace__ecere__com__Instance * __internal_ClassInst = fileInput;
 
 __internal_ClassInst ? __internal_ClassInst->_vTbl : __ecereClass___ecereNameSpace__ecere__sys__File->_vTbl;
-})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Seek])(fileInput, 0, 0);
+})[__ecereVMethodID___ecereNameSpace__ecere__sys__File_Seek]);
+__internal_VirtualMethod ? __internal_VirtualMethod(fileInput, 0, 0) : (unsigned int)1;
+}));
 echoOn = 0;
 parsedExpression = (((void *)0));
 resetScanner();
@@ -16112,6 +16255,8 @@ unsigned int useDestType = 0, useSideType = 0;
 struct Location oldyylloc = yylloc;
 unsigned int useSideUnit = 0;
 struct __ecereNameSpace__ecere__com__Class * destClass = (exp->destType && exp->destType->kind == 8 && exp->destType->__anon1._class) ? exp->destType->__anon1._class->__anon1.registered : (((void *)0));
+unsigned int powerOp = 0, relationOp = 0;
+struct __ecereNameSpace__ecere__com__Class * c1 = (((void *)0)), * c2 = (((void *)0));
 struct Type * dummy = (dummy = __ecereNameSpace__ecere__com__eInstance_New(__ecereClass_Type), dummy->count = 1, dummy->refCount = 1, dummy);
 
 switch(exp->__anon1.op.op)
@@ -16144,6 +16289,7 @@ case GE_OP:
 case NE_OP:
 boolResult = 1;
 useSideType = 1;
+relationOp = 1;
 break;
 case '+':
 case '-':
@@ -16163,6 +16309,8 @@ case '/':
 case '%':
 useSideType = 1;
 useDestType = 1;
+if(exp->__anon1.op.op == '/')
+powerOp = 1;
 break;
 case '&':
 case '*':
@@ -16170,6 +16318,8 @@ if(exp->__anon1.op.exp1)
 {
 useSideType = 1;
 useDestType = 1;
+if(exp->__anon1.op.op == '*')
+powerOp = 1;
 }
 break;
 }
@@ -16213,6 +16363,17 @@ if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
 exp->__anon1.op.exp1->destType = dummy;
 dummy->refCount++;
+if(powerOp)
+exp->__anon1.op.exp1->opDestType = 1;
+if(relationOp)
+exp->__anon1.op.exp1->usedInComparison = 1;
+}
+if(exp->__anon1.op.op == '+' || exp->__anon1.op.op == '-')
+{
+if(exp->opDestType)
+exp->__anon1.op.exp1->parentOpDestType = 1;
+if(exp->usedInComparison)
+exp->__anon1.op.exp1->usedInComparison = 1;
 }
 if(exp->__anon1.op.exp1->destType && exp->__anon1.op.op != '=')
 exp->__anon1.op.exp1->destType->count++;
@@ -16220,6 +16381,7 @@ ProcessExpressionType(exp->__anon1.op.exp1);
 if(exp->__anon1.op.exp1->destType && exp->__anon1.op.op != '=')
 exp->__anon1.op.exp1->destType->count--;
 exp->__anon1.op.exp1->opDestType = 0;
+exp->__anon1.op.exp1->usedInComparison = 0;
 if(!exp->__anon1.op.exp2 && (exp->__anon1.op.op == INC_OP || exp->__anon1.op.op == DEC_OP) && exp->__anon1.op.exp1->expType && exp->__anon1.op.exp1->expType->kind == 8 && exp->__anon1.op.exp1->expType->__anon1._class && exp->__anon1.op.exp1->expType->__anon1._class->__anon1.registered && exp->__anon1.op.exp1->expType->__anon1._class->__anon1.registered->type == 3)
 {
 exp->__anon1.op.exp2 = MkExpConstant("1");
@@ -16318,6 +16480,10 @@ if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
 exp->__anon1.op.exp2->destType = dummy;
 dummy->refCount++;
+if(powerOp)
+exp->__anon1.op.exp2->opDestType = 1;
+if(relationOp)
+exp->__anon1.op.exp2->usedInComparison = 1;
 }
 if(type1 && boolResult && useSideType && type1->kind == 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && (type1->__anon1._class->__anon1.registered->type == 2 || type1->__anon1._class->__anon1.registered->type == 4))
 {
@@ -16344,8 +16510,16 @@ e = (*e->__anon1.list).last;
 if(e->type == 11 && e->__anon1.cast.exp)
 e->__anon1.cast.exp->needCast = 1;
 }
+if(exp->__anon1.op.op == '+' || exp->__anon1.op.op == '-')
+{
+if(exp->opDestType)
+exp->__anon1.op.exp2->parentOpDestType = 1;
+if(exp->usedInComparison)
+exp->__anon1.op.exp2->usedInComparison = 1;
+}
 ProcessExpressionType(exp->__anon1.op.exp2);
 exp->__anon1.op.exp2->opDestType = 0;
+exp->__anon1.op.exp2->usedInComparison = 0;
 if(exp->__anon1.op.exp2->destType && exp->__anon1.op.op != '=')
 exp->__anon1.op.exp2->destType->count--;
 if(!assign && (exp->__anon1.op.exp1 || exp->__anon1.op.op == '~'))
@@ -16417,6 +16591,17 @@ if(type2)
 type2->refCount++;
 }
 }
+c1 = type1 && type1->kind == 8 && type1->__anon1._class ? type1->__anon1._class->__anon1.registered : (((void *)0));
+c2 = type2 && type2->kind == 8 && type2->__anon1._class ? type2->__anon1._class->__anon1.registered : (((void *)0));
+if(relationOp && ((exp->__anon1.op.exp1 && exp->__anon1.op.exp1->ambiguousUnits && (!c2 || c2->type != 3)) || (exp->__anon1.op.exp2 && exp->__anon1.op.exp2->ambiguousUnits && (!c1 || c1->type != 3))))
+Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "ambiguous units in relational operation\n", (((void *)0))));
+if(!relationOp && ((exp->__anon1.op.exp1 && exp->__anon1.op.exp1->ambiguousUnits) || (exp->__anon1.op.exp2 && exp->__anon1.op.exp2->ambiguousUnits)) && (!powerOp || !c1 || c1->type != 3 || !c2 || c2->type != 3 || !RelatedUnits(c1, c2)))
+{
+if(exp->opDestType || exp->usedInComparison)
+exp->ambiguousUnits = 1;
+else
+Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "ambiguous units\n", (((void *)0))));
+}
 dummy->kind = 0;
 if(exp->__anon1.op.op == SIZEOF)
 {
@@ -16445,6 +16630,10 @@ exp->expType->refCount++;
 }
 else if(!assign)
 {
+if(c1 && !c1->dataType)
+c1->dataType = ProcessTypeString(c1->dataTypeString, 0);
+if(c2 && !c2->dataType)
+c2->dataType = ProcessTypeString(c2->dataTypeString, 0);
 if(boolOps)
 {
 if(exp->__anon1.op.exp1)
@@ -16476,19 +16665,36 @@ exp->__anon1.op.exp2->expType = MkClassType("bool");
 exp->__anon1.op.exp2->expType->truth = 1;
 }
 }
+else if(powerOp && exp->__anon1.op.exp1 && exp->__anon1.op.exp2 && ((c1 && c1->type == 3) || (c2 && c2->type == 3)))
+{
+if(c1 && c1->type == 3 && c2 && c2->type == 3)
+{
+if(c1->dataType->kind == 7)
+exp->expType = c1->dataType;
+else if(c2->dataType->kind == 7)
+exp->expType = c2->dataType;
+else if(c1->dataType->kind == 6)
+exp->expType = c1->dataType;
+else if(c2->dataType->kind == 6)
+exp->expType = c2->dataType;
+else
+exp->expType = c1->dataType;
+}
+else if((c1 && c1->type == 3) || exp->__anon1.op.op == '/')
+exp->expType = type1;
+else
+exp->expType = type2;
+if(exp->expType)
+exp->expType->refCount++;
+}
 else if(exp->__anon1.op.exp1 && exp->__anon1.op.exp2 && ((useSideType) || ((!type1 || type1->kind != 8 || !strcmp(type1->__anon1._class->string, "String")) && (!type2 || type2->kind != 8 || !strcmp(type2->__anon1._class->string, "String")))))
 {
 if(type1 && type2 && ((type1->kind == 8 && type1->__anon1._class && strcmp(type1->__anon1._class->string, "String")) == (type2->kind == 8 && type2->__anon1._class && strcmp(type2->__anon1._class->string, "String"))))
 {
-if(exp->__anon1.op.op == '-' && ((type1->kind == 8 && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 4) || (type2->kind == 8 && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4)))
+if(exp->__anon1.op.op == '-' && ((c1 && c1->type == 4) || (c2 && c2->type == 4)))
 {
-struct Type * intType;
+struct Type * intType = ProcessTypeString((c1 && c1->dataType->kind == 4) || (c2 && c2->dataType->kind == 4) ? "int64" : "int", 0);
 
-if(!type1->__anon1._class->__anon1.registered->dataType)
-type1->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type1->__anon1._class->__anon1.registered->dataTypeString, 0);
-if(!type2->__anon1._class->__anon1.registered->dataType)
-type2->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type2->__anon1._class->__anon1.registered->dataTypeString, 0);
-intType = ProcessTypeString((type1->__anon1._class->__anon1.registered->dataType->kind == 4 || type2->__anon1._class->__anon1.registered->dataType->kind == 4) ? "int64" : "int", 0);
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
 if(exp->__anon1.op.exp2->destType)
@@ -16508,8 +16714,13 @@ FreeType(exp->__anon1.op.exp1->destType);
 exp->__anon1.op.exp1->destType = type2;
 type2->refCount++;
 }
-if(!boolResult && type1->kind == 8 && (!exp->destType || exp->destType->kind != 8) && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3 && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3 && type1->__anon1._class->__anon1.registered != type2->__anon1._class->__anon1.registered)
+if(!boolResult && !exp->opDestType && (!exp->destType || exp->destType->kind != 8) && c1 && c1->type == 3 && c2 && c2->type == 3 && c1 != c2)
+{
+if(exp->usedInComparison || exp->parentOpDestType)
+exp->ambiguousUnits = 1;
+else
 Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "operating on %s and %s with an untyped result, assuming %s\n", (((void *)0))), type1->__anon1._class->string, type2->__anon1._class->string, type1->__anon1._class->string);
+}
 if(type1->kind == 13 && type1->__anon1.type->kind == 20 && type2->kind != 13)
 {
 struct Expression * argExp = GetTemplateArgExp(type1->__anon1.type->__anon1.templateParameter, thisClass, 1);
@@ -16529,6 +16740,7 @@ if(!exp->__anon1.op.exp2->expType)
 if(type2)
 FreeType(type2);
 type2 = exp->__anon1.op.exp2->expType = ProcessTypeString("int", 0);
+c2 = (((void *)0));
 type2->refCount++;
 }
 ProcessExpressionType(exp->__anon1.op.exp2);
@@ -16658,7 +16870,7 @@ Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "incompatibl
 }
 }
 }
-else if(!boolResult && (!useSideUnit) && type2 && type1 && type2->kind == 8 && type1->kind != 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3)
+else if(!boolResult && !useSideUnit && c2 && c2->type == 3 && type1 && type1->kind != 8)
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
@@ -16670,7 +16882,7 @@ exp->expType = type2;
 if(type2)
 type2->refCount++;
 }
-else if(!boolResult && (!useSideUnit) && type1 && type2 && type1->kind == 8 && type2->kind != 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3)
+else if(!boolResult && !useSideUnit && c1 && c1->type == 3 && type2 && type2->kind != 8)
 {
 if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
@@ -16686,40 +16898,38 @@ else if(type1)
 {
 unsigned int valid = 0;
 
-if(!boolResult && useSideUnit && type1 && type1->kind == 8 && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3 && type2 && type2->kind != 8)
+if(!boolResult && useSideUnit && c1 && c1->type == 3 && type2 && type2->kind != 8)
 {
 if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
-if(!type1->__anon1._class->__anon1.registered->dataType)
-type1->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type1->__anon1._class->__anon1.registered->dataTypeString, 0);
-exp->__anon1.op.exp2->destType = type1->__anon1._class->__anon1.registered->dataType;
+exp->__anon1.op.exp2->destType = c1->dataType;
 exp->__anon1.op.exp2->destType->refCount++;
 CheckExpressionType(exp->__anon1.op.exp2, exp->__anon1.op.exp2->destType, 0, 0);
 if(type2)
 FreeType(type2);
 type2 = exp->__anon1.op.exp2->destType;
+c2 = type2 && type2->kind == 8 && type2->__anon1._class ? type2->__anon1._class->__anon1.registered : (((void *)0));
 if(type2)
 type2->refCount++;
 exp->expType = type2;
 type2->refCount++;
 }
-if(!boolResult && useSideUnit && type2 && type2->kind == 8 && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3 && type1 && type1->kind != 8)
+if(!boolResult && useSideUnit && c2 && c2->type == 3 && type1 && type1->kind != 8)
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
-if(!type2->__anon1._class->__anon1.registered->dataType)
-type2->__anon1._class->__anon1.registered->dataType = ProcessTypeString(type2->__anon1._class->__anon1.registered->dataTypeString, 0);
-exp->__anon1.op.exp1->destType = type2->__anon1._class->__anon1.registered->dataType;
+exp->__anon1.op.exp1->destType = c2->dataType;
 exp->__anon1.op.exp1->destType->refCount++;
 CheckExpressionType(exp->__anon1.op.exp1, exp->__anon1.op.exp1->destType, 0, 0);
 type1 = exp->__anon1.op.exp1->destType;
+c1 = type1 && type1->kind == 8 && type1->__anon1._class ? type1->__anon1._class->__anon1.registered : (((void *)0));
 exp->expType = type1;
 type1->refCount++;
 }
 if(!boolResult || exp->__anon1.op.op == '>' || exp->__anon1.op.op == '<' || exp->__anon1.op.op == GE_OP || exp->__anon1.op.op == LE_OP)
 {
-unsigned int op1IsEnum = type1 && type1->kind == 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 4;
-unsigned int op2IsEnum = type2 && type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4;
+unsigned int op1IsEnum = c1 && c1->type == 4;
+unsigned int op2IsEnum = c2 && c2->type == 4;
 
 if(exp->__anon1.op.op == '*' || exp->__anon1.op.op == '/' || exp->__anon1.op.op == '-' || exp->__anon1.op.op == '|' || exp->__anon1.op.op == '^')
 {
@@ -16778,7 +16988,7 @@ valid = 1;
 }
 if(!valid)
 {
-if(type2 && type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3 && (type1->kind != 8 || !type1->__anon1._class || !type1->__anon1._class->__anon1.registered || type1->__anon1._class->__anon1.registered->type != 3))
+if(c2 && c2->type == 3 && (!c1 || c1->type != 3))
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
@@ -16828,13 +17038,13 @@ PrintType(exp->__anon1.op.exp1->expType, type1String, 0, 1);
 PrintType(exp->__anon1.op.exp2->expType, type2String, 0, 1);
 }
 Compiler_Warning(__ecereNameSpace__ecere__GetTranslatedString("ec", "incompatible expressions %s (%s) and %s (%s)\n", (((void *)0))), expString1, type1String, expString2, type2String);
-if(type1->kind == 8 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 4)
+if(c1 && c1->type == 4)
 {
 exp->expType = exp->__anon1.op.exp1->expType;
 if(exp->__anon1.op.exp1->expType)
 exp->__anon1.op.exp1->expType->refCount++;
 }
-else if(type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4)
+else if(c2 && c2->type == 4)
 {
 exp->expType = exp->__anon1.op.exp2->expType;
 if(exp->__anon1.op.exp2->expType)
@@ -16846,7 +17056,7 @@ exp->__anon1.op.exp2->expType->refCount++;
 }
 else if(type2)
 {
-if(type2->kind == 8 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 4)
+if(c2 && c2->type == 4)
 {
 struct Type * oldType = exp->__anon1.op.exp1->expType;
 
@@ -16872,7 +17082,7 @@ exp->__anon1.op.exp1->destType->refCount++;
 }
 else if(type2 && (!type1 || (type2->kind == 8 && type1->kind != 8)))
 {
-if(type1 && type2->__anon1._class && type2->__anon1._class->__anon1.registered && type2->__anon1._class->__anon1.registered->type == 3)
+if(type1 && c2 && c2->type == 3)
 {
 if(exp->__anon1.op.exp1->destType)
 FreeType(exp->__anon1.op.exp1->destType);
@@ -16895,7 +17105,7 @@ type2->refCount++;
 }
 else if(type1 && (!type2 || (type1->kind == 8 && type2->kind != 8)))
 {
-if(type2 && type1->__anon1._class && type1->__anon1._class->__anon1.registered && type1->__anon1._class->__anon1.registered->type == 3)
+if(c2 && c2->type == 3)
 {
 if(exp->__anon1.op.exp2->destType)
 FreeType(exp->__anon1.op.exp2->destType);
@@ -16968,6 +17178,8 @@ if(!e->next)
 {
 FreeType(e->destType);
 e->opDestType = exp->opDestType;
+e->usedInComparison = exp->usedInComparison;
+e->parentOpDestType = exp->parentOpDestType;
 e->destType = exp->destType;
 if(e->destType)
 {
@@ -16975,11 +17187,14 @@ exp->destType->refCount++;
 }
 }
 ProcessExpressionType(e);
+if(e->ambiguousUnits)
+exp->ambiguousUnits = 1;
 if(!exp->expType && !e->next)
 {
 exp->expType = e->expType;
 if(e->expType)
 e->expType->refCount++;
+exp->needCast = e->needCast;
 }
 if(!e->isConstant)
 exp->isConstant = 0;
@@ -16995,7 +17210,11 @@ FreeType(exp->destType);
 *exp = *e;
 exp->prev = prev;
 exp->next = next;
-((e ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)e) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(e)) : 0), e = 0);
+((e ? __extension__ ({
+void * __ecerePtrToDelete = (e);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), e = 0);
 ProcessExpressionType(exp);
 }
 break;
@@ -18423,7 +18642,11 @@ FreeType(exp->expType);
 FreeType(exp->destType);
 exp->expType = expType;
 exp->destType = destType;
-((castExp ? (__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)castExp) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(castExp)) : 0), castExp = 0);
+((castExp ? __extension__ ({
+void * __ecerePtrToDelete = (castExp);
+
+__ecereClass_Expression->Destructor ? __ecereClass_Expression->Destructor((void *)__ecerePtrToDelete) : 0, __ecereNameSpace__ecere__com__eSystem_Delete(__ecerePtrToDelete);
+}) : 0), castExp = 0);
 exp->prev = prev;
 exp->next = next;
 }
@@ -18715,6 +18938,10 @@ __ecereMethod___ecereNameSpace__ecere__sys__OldList_Add(&exp->expType->__anon1._
 }
 }
 }
+if(!notByReference && exp->expType && exp->expType->kind == 8 && exp->expType->__anon1._class && exp->expType->__anon1._class->__anon1.registered && exp->expType->__anon1._class->__anon1.registered->type == 5 && (!exp->destType || (exp->destType->kind != 3 && exp->destType->kind != 4 && exp->destType->kind != 22 && exp->destType->kind != 23 && exp->destType->kind != 5 && exp->destType->kind != 2 && exp->destType->kind != 1 && exp->destType->kind != 24)))
+{
+exp->byReference = 1;
+}
 yylloc = exp->loc;
 if(exp->destType && (exp->destType->kind == 18))
 ;
@@ -18803,7 +19030,7 @@ struct Expression * nbExp = GetNonBracketsExp(exp);
 unsigned int skipWarning = 0;
 int kind = exp->destType->kind;
 
-if(nbExp->type == 12 && !nbExp->destType->casted && nbExp->destType->kind == exp->destType->kind)
+if(nbExp->type == 12 && nbExp->destType && !nbExp->destType->casted && nbExp->destType->kind == exp->destType->kind)
 skipWarning = 1;
 if((kind == 1 || kind == 2) && exp->destType->isSigned == exp->expType->signedBeforePromotion && nbExp->type == 4 && nbExp->__anon1.op.exp1 && nbExp->__anon1.op.exp2)
 {
@@ -19137,7 +19364,7 @@ if(_class->fixed)
 {
 struct Expression * e;
 
-if(_class->offset && _class->offset == _class->base->structSize)
+if(_class->offset && _class->offset == (_class->base->type == 5 ? _class->base->memberOffset : _class->base->structSize))
 {
 e = MkExpClassSize(MkSpecifierName(_class->base->fullName));
 ProcessExpressionType(e);
@@ -19440,6 +19667,7 @@ __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ParseExpressionString",
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ReplaceExpContents", "void ReplaceExpContents(Expression checkedExp, Expression newExp)", ReplaceExpContents, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ApplyAnyObjectLogic", "void ApplyAnyObjectLogic(Expression e)", ApplyAnyObjectLogic, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ApplyLocation", "void ApplyLocation(Expression exp, Location loc)", ApplyLocation, module, 1);
+__ecereNameSpace__ecere__com__eSystem_RegisterFunction("RelatedUnits", "bool RelatedUnits(ecere::com::Class c1, ecere::com::Class c2)", RelatedUnits, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ProcessExpressionType", "void ProcessExpressionType(Expression exp)", ProcessExpressionType, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("DeclareFunctionUtil", "void DeclareFunctionUtil(External neededBy, const String s)", DeclareFunctionUtil, module, 1);
 __ecereNameSpace__ecere__com__eSystem_RegisterFunction("ComputeDataTypes", "void ComputeDataTypes(void)", ComputeDataTypes, module, 1);