samples/audio; Installer: Added SineTone sample
[sdk] / compiler / libec / src / pass15.ec
index 3323619..4d4d489 100644 (file)
@@ -1,9 +1,5 @@
 import "ecdefs"
 
-#define uint _uint
-#include <stdlib.h>  // For strtoll
-#undef uint
-
 // UNTIL IMPLEMENTED IN GRAMMAR
 #define ACCESS_CLASSDATA(_class, baseClass) \
    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
@@ -47,6 +43,8 @@ Time findSymbolTotalTime;
    {
       TempFile f { };
       int count;
+      bool backOutputLineNumbers = outputLineNumbers;
+      outputLineNumbers = false;
 
       if(exp)
          OutputExpression(exp, f);
@@ -55,6 +53,8 @@ Time findSymbolTotalTime;
       count += f.Read(string + count, 1, 1023);
       string[count] = '\0';
       delete f;
+
+      outputLineNumbers = backOutputLineNumbers;
    }
 }
 
@@ -84,7 +84,7 @@ bool NeedCast(Type type1, Type type2)
       return false;
    }
 
-   if(type1.kind == type2.kind)
+   if(type1.kind == type2.kind && type1.isLong == type2.isLong)
    {
       switch(type1.kind)
       {
@@ -101,7 +101,7 @@ bool NeedCast(Type type1, Type type2)
          case classType:
             return type1._class != type2._class;
          case pointerType:
-            return NeedCast(type1.type, type2.type);
+            return (type1.type && type2.type && type1.type.constant != type2.type.constant) || NeedCast(type1.type, type2.type);
          default:
             return true; //false; ????
       }
@@ -121,6 +121,7 @@ static void ReplaceClassMembers(Expression exp, Class _class)
          // First, check if the identifier is declared inside the function
          for(ctx = curContext; ctx != topContext.parent && !symbol; ctx = ctx.parent)
          {
+            if(!ctx) break;   // This happened opening old mapTileCache.ec from archives?
             symbol = (Symbol)ctx.symbols.FindString(id.string);
             if(symbol) break;
          }
@@ -201,10 +202,12 @@ static void ReplaceClassMembers(Expression exp, Class _class)
 public char * PrintInt(int64 result)
 {
    char temp[100];
-   if(result > MAXINT64)
-      sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
+   if(result > MAXINT)
+      sprintf(temp, FORMAT64HEX /*"0x%I64XLL"*/, result);
    else
-      sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+      sprintf(temp, FORMAT64D /*"%I64d"*/, result);
+   if(result > MAXINT || result < MININT)
+      strcat(temp, "LL");
    return CopyString(temp);
 }
 
@@ -212,7 +215,7 @@ public char * PrintUInt(uint64 result)
 {
    char temp[100];
    if(result > MAXDWORD)
-      sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
+      sprintf(temp, FORMAT64HEXLL /*"0x%I64X"*/, result);
    else if(result > MAXINT)
       sprintf(temp, FORMAT64HEX /*"0x%I64X"*/, result);
    else
@@ -220,20 +223,25 @@ public char * PrintUInt(uint64 result)
    return CopyString(temp);
 }
 
-public char * PrintInt64(int64 result)
+public char *  PrintInt64(int64 result)
 {
    char temp[100];
-   sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+   if(result > MAXINT || result < MININT)
+      sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+   else
+      sprintf(temp, FORMAT64D /*"%I64d"*/, result);
    return CopyString(temp);
 }
 
 public char * PrintUInt64(uint64 result)
 {
    char temp[100];
-   if(result > MAXINT64)
+   if(result > MAXDWORD)
       sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
+   else if(result > MAXINT)
+      sprintf(temp, FORMAT64HEX /*"0x%I64XLL"*/, result);
    else
-      sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+      sprintf(temp, FORMAT64D /*"%I64d"*/, result);
    return CopyString(temp);
 }
 
@@ -241,9 +249,11 @@ public char * PrintHexUInt(uint64 result)
 {
    char temp[100];
    if(result > MAXDWORD)
-      sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
+      sprintf(temp, FORMAT64HEX /*"0x%I64xLL"*/, result);
    else
       sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
+   if(result > MAXDWORD)
+      strcat(temp, "LL");
    return CopyString(temp);
 }
 
@@ -297,14 +307,44 @@ public char * PrintUChar(unsigned char result)
 public char * PrintFloat(float result)
 {
    char temp[350];
-   sprintf(temp, "%.16ff", result);
+   if(result.isInf)
+   {
+      if(result.signBit)
+         strcpy(temp, "-inf");
+      else
+         strcpy(temp, "inf");
+   }
+   else if(result.isNan)
+   {
+      if(result.signBit)
+         strcpy(temp, "-nan");
+      else
+         strcpy(temp, "nan");
+   }
+   else
+      sprintf(temp, "%.16ff", result);
    return CopyString(temp);
 }
 
 public char * PrintDouble(double result)
 {
    char temp[350];
-   sprintf(temp, "%.16f", result);
+   if(result.isInf)
+   {
+      if(result.signBit)
+         strcpy(temp, "-inf");
+      else
+         strcpy(temp, "inf");
+   }
+   else if(result.isNan)
+   {
+      if(result.signBit)
+         strcpy(temp, "-nan");
+      else
+         strcpy(temp, "nan");
+   }
+   else
+      sprintf(temp, "%.16f", result);
    return CopyString(temp);
 }
 
@@ -314,9 +354,8 @@ public char * PrintDouble(double result)
 //public Operand GetOperand(Expression exp);
 
 #define GETVALUE(name, t) \
-   public bool Get##name(Expression exp, t * value2) \
+   public bool GetOp##name(Operand op2, t * value2) \
    {                                                        \
-      Operand op2 = GetOperand(exp);                        \
       if(op2.kind == intType && op2.type.isSigned) *value2 = (t) op2.i; \
       else if(op2.kind == intType) *value2 = (t) op2.ui;                 \
       else if(op2.kind == int64Type && op2.type.isSigned) *value2 = (t) op2.i64; \
@@ -335,9 +374,14 @@ public char * PrintDouble(double result)
       else                                                                          \
          return false;                                                              \
       return true;                                                                  \
+   } \
+   public bool Get##name(Expression exp, t * value2) \
+   {                                                        \
+      Operand op2 = GetOperand(exp);                        \
+      return GetOp##name(op2, value2); \
    }
 
-// To help the deubugger currently not preprocessing...
+// To help the debugger currently not preprocessing...
 #define HELP(x) x
 
 GETVALUE(Int, HELP(int));
@@ -364,7 +408,6 @@ void ComputeClassMembers(Class _class, bool isMember)
    if(member || ((_class.type == bitClass || _class.type == normalClass || _class.type == structClass || _class.type == noHeadClass) &&
                  (_class.type == bitClass || (!_class.structSize || _class.structSize == _class.offset)) && _class.computeSize))
    {
-      int c;
       int unionMemberOffset = 0;
       int bitFields = 0;
 
@@ -624,7 +667,9 @@ void ComputeClassMembers(Class _class, bool isMember)
                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 == noHeadClass ? _class.base.templateClass.memberOffset : _class.base.templateClass.structSize) :
+                  (_class.base.type == noHeadClass ? _class.base.memberOffset : _class.base.structSize) ) : 0) + _class.memberOffset + extra;
             if(!member)
             {
                Property prop;
@@ -648,7 +693,7 @@ void ComputeClassMembers(Class _class, bool isMember)
                   if(deriv.computeSize)
                   {
                      // TESTING THIS NEW CODE HERE... TRYING TO FIX ScrollBar MEMBERS DEBUGGING
-                     deriv.offset = /*_class.offset + */_class.structSize;
+                     deriv.offset = /*_class.offset + */(_class.type == noHeadClass ? _class.memberOffset : _class.structSize);
                      deriv.memberOffset = 0;
                      // ----------------------
 
@@ -689,8 +734,8 @@ public int ComputeTypeSize(Type type)
          case charType: type.alignment = size = sizeof(char); break;
          case intType: type.alignment = size = sizeof(int); break;
          case int64Type: type.alignment = size = sizeof(int64); break;
-         case intPtrType: type.alignment = size = targetBits / 8; break;
-         case intSizeType: type.alignment = size = targetBits / 8; break;
+         case intPtrType: type.alignment = size = targetBits / 8; type.pointerAlignment = true; break;
+         case intSizeType: type.alignment = size = targetBits / 8; type.pointerAlignment = true; break;
          case longType: type.alignment = size = sizeof(long); break;
          case shortType: type.alignment = size = sizeof(short); break;
          case floatType: type.alignment = size = sizeof(float); break;
@@ -704,6 +749,7 @@ public int ComputeTypeSize(Type type)
                // Ensure all members are properly registered
                ComputeClassMembers(_class, false);
                type.alignment = _class.structAlignment;
+               type.pointerAlignment = (bool)_class.pointerAlignment;
                size = _class.structSize;
                if(type.alignment && size % type.alignment)
                   size += type.alignment - (size % type.alignment);
@@ -718,16 +764,26 @@ public int ComputeTypeSize(Type type)
                size = type.alignment = ComputeTypeSize(_class.dataType);
             }
             else
+            {
                size = type.alignment = targetBits / 8; // sizeof(Instance *);
+               type.pointerAlignment = true;
+            }
             break;
          }
-         case pointerType: case subClassType: size = type.alignment = targetBits / 8; /*sizeof(void *); */break;
+         case pointerType: case subClassType: size = type.alignment = targetBits / 8; /*sizeof(void *); */ type.pointerAlignment = true; break;
          case arrayType:
             if(type.arraySizeExp)
             {
                ProcessExpressionType(type.arraySizeExp);
                ComputeExpression(type.arraySizeExp);
-               if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType && type.arraySizeExp.expType.kind != enumType &&
+               if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType &&
+                  type.arraySizeExp.expType.kind != shortType &&
+                  type.arraySizeExp.expType.kind != charType &&
+                  type.arraySizeExp.expType.kind != longType &&
+                  type.arraySizeExp.expType.kind != int64Type &&
+                  type.arraySizeExp.expType.kind != intSizeType &&
+                  type.arraySizeExp.expType.kind != intPtrType &&
+                  type.arraySizeExp.expType.kind != enumType &&
                   (type.arraySizeExp.expType.kind != classType || !type.arraySizeExp.expType._class.registered || type.arraySizeExp.expType._class.registered.type != enumClass)))
                {
                   Location oldLoc = yylloc;
@@ -760,45 +816,84 @@ public int ComputeTypeSize(Type type)
 
             size = ComputeTypeSize(type.type) * type.arraySize;
             if(type.type)
+            {
                type.alignment = type.type.alignment;
+               type.pointerAlignment = type.type.pointerAlignment;
+            }
 
             break;
          case structType:
          {
-            Type member;
-            for(member = type.members.first; member; member = member.next)
+            if(!type.members.first && type.enumName)
             {
-               uint addSize = ComputeTypeSize(member);
+               Symbol symbol = FindStruct(curContext, type.enumName);
+               if(symbol && symbol.type)
+               {
+                  ComputeTypeSize(symbol.type);
+                  size = symbol.type.size;
+               }
+            }
+            else
+            {
+               Type member;
+               for(member = type.members.first; member; member = member.next)
+               {
+                  uint addSize = ComputeTypeSize(member);
 
-               member.offset = size;
-               if(member.alignment && size % member.alignment)
-                  member.offset += member.alignment - (size % member.alignment);
-               size = member.offset;
+                  member.offset = size;
+                  if(member.alignment && size % member.alignment)
+                     member.offset += member.alignment - (size % member.alignment);
+                  size = member.offset;
 
-               type.alignment = Max(type.alignment, member.alignment);
-               size += addSize;
+                  if(member.pointerAlignment && type.size <= 4)
+                     type.pointerAlignment = true;
+                  else if(!member.pointerAlignment && member.alignment >= 8)
+                     type.pointerAlignment = false;
+
+                  type.alignment = Max(type.alignment, member.alignment);
+                  size += addSize;
+               }
+               if(type.alignment && size % type.alignment)
+                  size += type.alignment - (size % type.alignment);
             }
-            if(type.alignment && size % type.alignment)
-               size += type.alignment - (size % type.alignment);
             break;
          }
          case unionType:
          {
-            Type member;
-            for(member = type.members.first; member; member = member.next)
+            if(!type.members.first && type.enumName)
+            {
+               Symbol symbol = FindStruct(curContext, type.enumName);
+               if(symbol && symbol.type)
+               {
+                  ComputeTypeSize(symbol.type);
+                  size = symbol.type.size;
+                  type.alignment = symbol.type.alignment;
+               }
+            }
+            else
             {
-               uint addSize = ComputeTypeSize(member);
+               Type member;
+               for(member = type.members.first; member; member = member.next)
+               {
+                  uint addSize = ComputeTypeSize(member);
+
+                  member.offset = size;
+                  if(member.alignment && size % member.alignment)
+                     member.offset += member.alignment - (size % member.alignment);
+                  size = member.offset;
+
+                  if(member.pointerAlignment && type.size <= 4)
+                     type.pointerAlignment = true;
+                  else if(!member.pointerAlignment && member.alignment >= 8)
+                     type.pointerAlignment = false;
 
-               member.offset = size;
-               if(member.alignment && size % member.alignment)
-                  member.offset += member.alignment - (size % member.alignment);
-               size = member.offset;
+                  type.alignment = Max(type.alignment, member.alignment);
 
-               type.alignment = Max(type.alignment, member.alignment);
-               size = Max(size, addSize);
+                  size = Max(size, addSize);
+               }
+               if(type.alignment && size % type.alignment)
+                  size += type.alignment - (size % type.alignment);
             }
-            if(type.alignment && size % type.alignment)
-               size += type.alignment - (size % type.alignment);
             break;
          }
          case templateType:
@@ -809,6 +904,7 @@ public int ComputeTypeSize(Type type)
             {
                size = ComputeTypeSize(baseType);
                type.alignment = baseType.alignment;
+               type.pointerAlignment = baseType.pointerAlignment;
             }
             else
                type.alignment = size = sizeof(uint64);
@@ -822,6 +918,7 @@ public int ComputeTypeSize(Type type)
          case thisClassType:
          {
             type.alignment = size = targetBits / 8; //sizeof(void *);
+            type.pointerAlignment = true;
             break;
          }
       }
@@ -832,14 +929,16 @@ public int ComputeTypeSize(Type type)
 }
 
 
-/*static */int AddMembers(OldList * declarations, Class _class, bool isMember, uint * retSize, Class topClass, bool *addedPadding)
+/*static */int AddMembers(External neededBy, OldList * declarations, Class _class, bool isMember, uint * retSize, Class topClass, bool *addedPadding)
 {
    // This function is in need of a major review when implementing private members etc.
    DataMember topMember = isMember ? (DataMember) _class : null;
    uint totalSize = 0;
    uint maxSize = 0;
-   int alignment, size;
+   int alignment;
+   uint size;
    DataMember member;
+   int anonID = 1;
    Context context = isMember ? null : SetupTemplatesContext(_class);
    if(addedPadding)
       *addedPadding = false;
@@ -851,7 +950,7 @@ public int ComputeTypeSize(Type type)
       {
          // DANGER: Testing this noHeadClass here...
          if(_class.type == structClass || _class.type == noHeadClass)
-            /*totalSize = */AddMembers(declarations, _class.base, false, &totalSize, topClass, null);
+            /*totalSize = */AddMembers(neededBy, declarations, _class.base, false, &totalSize, topClass, null);
          else
          {
             uint baseSize = _class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize;
@@ -888,7 +987,7 @@ public int ComputeTypeSize(Type type)
 
                   {
                      Type type = ProcessType(specs, decl);
-                     DeclareType(member.dataType, false, false);
+                     DeclareType(neededBy, member.dataType, true, false);
                      FreeType(type);
                   }
                   /*
@@ -914,12 +1013,14 @@ public int ComputeTypeSize(Type type)
             case structMember:
             {
                OldList * specs = MkList(), * list = MkList();
+               char id[100];
+               sprintf(id, "__anon%d", anonID++);
 
                size = 0;
-               AddMembers(list, (Class)member, true, &size, topClass, null);
+               AddMembers(neededBy, list, (Class)member, true, &size, topClass, null);
                ListAdd(specs,
                   MkStructOrUnion((member.type == unionMember)?unionSpecifier:structSpecifier, null, list));
-               ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, null, null)));
+               ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, MkListOne(MkDeclaratorIdentifier(MkIdentifier(id))),null)));
                alignment = member.structAlignment;
 
                if(alignment)
@@ -961,15 +1062,14 @@ public int ComputeTypeSize(Type type)
    return topMember ? topMember.memberID : _class.memberID;
 }
 
-static int DeclareMembers(Class _class, bool isMember)
+static int DeclareMembers(External neededBy, Class _class, bool isMember)
 {
    DataMember topMember = isMember ? (DataMember) _class : null;
-   uint totalSize = 0;
    DataMember member;
    Context context = isMember ? null : SetupTemplatesContext(_class);
 
    if(!isMember && (_class.type == structClass || _class.type == noHeadClass) && _class.base.type != systemClass)
-      DeclareMembers(_class.base, false);
+      DeclareMembers(neededBy, _class.base, false);
 
    for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
    {
@@ -979,21 +1079,16 @@ static int DeclareMembers(Class _class, bool isMember)
          {
             case normalMember:
             {
-               /*
-               if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
-                  member.dataType._class.registered && member.dataType._class.registered.type == structClass)
-                  DeclareStruct(member.dataType._class.string, false);
-                  */
                if(!member.dataType && member.dataTypeString)
                   member.dataType = ProcessTypeString(member.dataTypeString, false);
                if(member.dataType)
-                  DeclareType(member.dataType, false, false);
+                  DeclareType(neededBy, member.dataType, true, false);
                break;
             }
             case unionMember:
             case structMember:
             {
-               DeclareMembers((Class)member, true);
+               DeclareMembers(neededBy, (Class)member, true);
                break;
             }
          }
@@ -1005,488 +1100,526 @@ static int DeclareMembers(Class _class, bool isMember)
    return topMember ? topMember.memberID : _class.memberID;
 }
 
-void DeclareStruct(char * name, bool skipNoHead)
+static void IdentifyAnonStructs(OldList/*<ClassDef>*/ *  definitions)
+{
+   ClassDef def;
+   int anonID = 1;
+   for(def = definitions->first; def; def = def.next)
+   {
+      if(def.type == declarationClassDef)
+      {
+         Declaration decl = def.decl;
+         if(decl && decl.specifiers)
+         {
+            Specifier spec;
+            bool isStruct = false;
+            for(spec = decl.specifiers->first; spec; spec = spec.next)
+            {
+               if(spec.type == structSpecifier || spec.type == unionSpecifier)
+               {
+                  if(spec.definitions)
+                     IdentifyAnonStructs(spec.definitions);
+                  isStruct = true;
+               }
+            }
+            if(isStruct)
+            {
+               Declarator d = null;
+               if(decl.declarators)
+               {
+                  for(d = decl.declarators->first; d; d = d.next)
+                  {
+                     Identifier idDecl = GetDeclId(d);
+                     if(idDecl)
+                        break;
+                  }
+               }
+               if(!d)
+               {
+                  char id[100];
+                  sprintf(id, "__anon%d", anonID++);
+                  if(!decl.declarators)
+                     decl.declarators = MkList();
+                  ListAdd(decl.declarators, MkDeclaratorIdentifier(MkIdentifier(id)));
+               }
+            }
+         }
+      }
+   }
+}
+
+External DeclareStruct(External neededBy, const char * name, bool skipNoHead, bool needDereference)
+{
+   return _DeclareStruct(neededBy, name, skipNoHead, needDereference, false);
+}
+
+External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, bool needDereference, bool fwdDecl)
 {
    External external = null;
    Symbol classSym = FindClass(name);
+   OldList * curDeclarations = null;
 
-   if(!inCompiler || !classSym) return;
+   if(!inCompiler || !classSym) return null;
 
    // We don't need any declaration for bit classes...
    if(classSym.registered &&
       (classSym.registered.type == bitClass || classSym.registered.type == unitClass || classSym.registered.type == enumClass))
-      return;
+      return null;
 
-   /*if(classSym.registered.templateClass)
-      return DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
-   */
+   if(!classSym.registered || (classSym.registered.type == normalClass && classSym.registered.structSize && classSym.registered.base && classSym.registered.base.base))
+      _DeclareStruct(neededBy, "ecere::com::Instance", false, true, fwdDecl);
+
+   external = classSym.structExternal;
 
-   if(classSym.registered && classSym.imported && !classSym.declaredStructSym)
+   if(external && external.declaration)
+   {
+      Specifier spec;
+      for(spec = external.declaration.specifiers ? external.declaration.specifiers->first : null; spec; spec = spec.next)
+         if(spec.type == structSpecifier || spec.type == unionSpecifier)
+         {
+            curDeclarations = spec.definitions;
+            break;
+         }
+   }
+
+   if(classSym.registered && !classSym.declaring && classSym.imported && (!classSym.declaredStructSym || (classSym.registered.type == noHeadClass && !skipNoHead && external && !curDeclarations)))
    {
-      // Add typedef struct
-      Declaration decl;
       OldList * specifiers, * declarators;
       OldList * declarations = null;
       char structName[1024];
-      external = (classSym.registered && classSym.registered.type == structClass) ?
-         classSym.pointerExternal : classSym.structExternal;
-
-      // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
-      // Moved this one up because DeclareClass done later will need it
+      bool addedPadding = false;
+      Specifier curSpec = null;
 
       classSym.declaring++;
 
       if(strchr(classSym.string, '<'))
       {
          if(classSym.registered.templateClass)
-         {
-            DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
-            classSym.declaring--;
-         }
-         return;
+            external = _DeclareStruct(neededBy, classSym.registered.templateClass.fullName, skipNoHead, needDereference, fwdDecl);
+         classSym.declaring--;
+         return external;
       }
 
-      //if(!skipNoHead)
-         DeclareMembers(classSym.registered, false);
-
       structName[0] = 0;
       FullClassNameCat(structName, name, false);
 
-      /*if(!external)
-         external = MkExternalDeclaration(null);*/
-
-      if(!skipNoHead)
+      classSym.declaredStructSym = true;
+      if(!external || (classSym.registered.type == noHeadClass && !skipNoHead && !curDeclarations))
       {
-         bool addedPadding = false;
-         classSym.declaredStructSym = true;
+         bool add = false;
+         if(!external)
+         {
+            external = MkExternalDeclaration(null);
+            classSym.structExternal = external;
+            external.symbol = classSym;
 
-         declarations = MkList();
+            add = true;
+         }
 
-         AddMembers(declarations, classSym.registered, false, null, classSym.registered, &addedPadding);
+         if(!skipNoHead)
+         {
+            declarations = MkList();
+            AddMembers(external, declarations, classSym.registered, false, null, classSym.registered, &addedPadding);
+         }
 
-         //ListAdd(specifiers, MkSpecifier(TYPEDEF));
-         //ListAdd(specifiers, MkStructOrUnion(structSpecifier, null, declarations));
+         if(external.declaration)
+         {
+            Specifier spec;
+            for(spec = external.declaration.specifiers ? external.declaration.specifiers->first : null; spec; spec = spec.next)
+               if(spec.type == structSpecifier || spec.type == unionSpecifier)
+               {
+                  curSpec = spec;
+                  curDeclarations = spec.definitions;
+                  break;
+               }
+         }
 
-         if(!declarations->count || (declarations->count == 1 && addedPadding))
+         if(declarations && (!declarations->count || (declarations->count == 1 && addedPadding)))
          {
             FreeList(declarations, FreeClassDef);
             declarations = null;
          }
-      }
-      if(skipNoHead || declarations)
-      {
-         if(external && external.declaration)
-         {
-            ((Specifier)external.declaration.specifiers->first).definitions = declarations;
-
-            if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
-            {
-               // TODO: Fix this
-               //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
-
-               // DANGER
-               if(classSym.structExternal)
-                  ast->Move(classSym.structExternal, curExternal.prev);
-               ast->Move(classSym.pointerExternal, curExternal.prev);
 
-               classSym.id = curExternal.symbol.idCode;
-               classSym.idCode = curExternal.symbol.idCode;
-               // external = classSym.pointerExternal;
-               //external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
-            }
+         if(classSym.registered.type != noHeadClass && !declarations)
+         {
+            FreeExternal(external);
+            external = null;
+            classSym.structExternal = null;
          }
          else
          {
-            if(!external)
-               external = MkExternalDeclaration(null);
-
-            specifiers = MkList();
-            declarators = MkList();
-            ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations));
-
-            /*
-            d = MkDeclaratorIdentifier(MkIdentifier(structName));
-            ListAdd(declarators, MkInitDeclarator(d, null));
-            */
-            external.declaration = decl = MkDeclaration(specifiers, declarators);
-            if(decl.symbol && !decl.symbol.pointerExternal)
-               decl.symbol.pointerExternal = external;
-
-            // For simple classes, keep the declaration as the external to move around
-            if(classSym.registered && classSym.registered.type == structClass)
-            {
-               char className[1024];
-               strcpy(className, "__ecereClass_");
-               FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
-
-               // Testing This
-               DeclareClass(classSym, className);
-
-               external.symbol = classSym;
-               classSym.pointerExternal = external;
-               classSym.id = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
-               classSym.idCode = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
-            }
+            if(curSpec)
+               curSpec.definitions = declarations;
             else
             {
-               char className[1024];
-               strcpy(className, "__ecereClass_");
-               FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
-
-               // TOFIX: TESTING THIS...
-               classSym.structExternal = external;
-               DeclareClass(classSym, className);
-               external.symbol = classSym;
+               specifiers = MkList();
+               declarators = MkList();
+               ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations));
+               external.declaration = MkDeclaration(specifiers, declarators);
             }
-
-            //if(curExternal)
-               ast->Insert(curExternal ? curExternal.prev : null, external);
+            if(add)
+               ast->Add(external);
          }
       }
-
       classSym.declaring--;
    }
-   else if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
+   else if(!classSym.declaredStructSym && classSym.structExternal)
    {
-      // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
-      // Moved this one up because DeclareClass done later will need it
+      classSym.declaredStructSym = true;
 
-      // TESTING THIS:
-      classSym.declaring++;
+      if(classSym.registered)
+         DeclareMembers(classSym.structExternal, classSym.registered, false);
 
-      //if(!skipNoHead)
+      if(classSym.structExternal.declaration && classSym.structExternal.declaration.specifiers)
       {
-         if(classSym.registered)
-            DeclareMembers(classSym.registered, false);
+         Specifier spec;
+         for(spec = classSym.structExternal.declaration.specifiers->first; spec; spec = spec.next)
+         {
+            if(spec.definitions)
+               IdentifyAnonStructs(spec.definitions);
+         }
       }
-
-      if(classSym.registered && (classSym.registered.type == structClass || classSym.registered.type == noHeadClass))
+   }
+   if(inCompiler && neededBy && (external || !classSym.imported))
+   {
+      if(!external)
       {
-         // TODO: Fix this
-         //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
-
-         // DANGER
-         if(classSym.structExternal)
-            ast->Move(classSym.structExternal, curExternal.prev);
-         ast->Move(classSym.pointerExternal, curExternal.prev);
-
-         classSym.id = curExternal.symbol.idCode;
-         classSym.idCode = curExternal.symbol.idCode;
-         // external = classSym.pointerExternal;
-         // external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
+         classSym.structExternal = external = MkExternalDeclaration(null);
+         external.symbol = classSym;
+         ast->Add(external);
       }
-
-      classSym.declaring--;
+      if(reachedPass15 && !external.declaration && classSym.registered && classSym.registered.type == noHeadClass)
+      {
+         // Declare nohead classes without definitions here (e.g. IteratorPointer)
+         char structName[1024];
+         OldList * specifiers, * declarators;
+         structName[0] = 0;
+         FullClassNameCat(structName, name, false);
+         specifiers = MkList();
+         declarators = MkList();
+         ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), null));
+         external.declaration = MkDeclaration(specifiers, declarators);
+      }
+      if(fwdDecl)
+      {
+         External e = external.fwdDecl ? external.fwdDecl : external;
+         if(e.incoming.count)
+            neededBy.CreateUniqueEdge(e, !needDereference && !external.fwdDecl);
+      }
+      else
+         neededBy.CreateUniqueEdge(external, !needDereference);
    }
-   //return external;
+   return external;
 }
 
-void DeclareProperty(Property prop, char * setName, char * getName)
+void DeclareProperty(External neededBy, Property prop, char * setName, char * getName)
 {
    Symbol symbol = prop.symbol;
-   char propName[1024];
+   bool imported = false;
+   bool dllImport = false;
+   External structExternal = null;
+   External instExternal = null;
 
    strcpy(setName, "__ecereProp_");
    FullClassNameCat(setName, prop._class.fullName, false);
    strcat(setName, "_Set_");
-   // strcat(setName, prop.name);
    FullClassNameCat(setName, prop.name, true);
 
    strcpy(getName, "__ecereProp_");
    FullClassNameCat(getName, prop._class.fullName, false);
    strcat(getName, "_Get_");
    FullClassNameCat(getName, prop.name, true);
-   // strcat(getName, prop.name);
 
-   strcpy(propName, "__ecereProp_");
-   FullClassNameCat(propName, prop._class.fullName, false);
-   strcat(propName, "_");
-   FullClassNameCat(propName, prop.name, true);
-   // strcat(propName, prop.name);
-
-   // To support "char *" property
-   MangleClassName(getName);
-   MangleClassName(setName);
-   MangleClassName(propName);
-
-   if(prop._class.type == structClass)
-      DeclareStruct(prop._class.fullName, false);
-
-   if(!symbol || curExternal.symbol.idCode < symbol.id)
+   if(!symbol || symbol._import)
    {
-      bool imported = false;
-      bool dllImport = false;
-      if(!symbol || symbol._import)
+      if(!symbol)
       {
-         if(!symbol)
+         Symbol classSym;
+
+         if(!prop._class.symbol)
+            prop._class.symbol = FindClass(prop._class.fullName);
+         classSym = prop._class.symbol;
+         if(classSym && !classSym._import)
          {
-            Symbol classSym;
-            if(!prop._class.symbol)
-               prop._class.symbol = FindClass(prop._class.fullName);
-            classSym = prop._class.symbol;
-            if(classSym && !classSym._import)
-            {
-               ModuleImport module;
+            ModuleImport module;
 
-               if(prop._class.module)
-                  module = FindModule(prop._class.module);
-               else
-                  module = mainModule;
+            if(prop._class.module)
+               module = FindModule(prop._class.module);
+            else
+               module = mainModule;
 
-               classSym._import = ClassImport
-               {
-                  name = CopyString(prop._class.fullName);
-                  isRemote = prop._class.isRemote;
-               };
-               module.classes.Add(classSym._import);
-            }
-            symbol = prop.symbol = Symbol { };
-            symbol._import = (ClassImport)PropertyImport
+            classSym._import = ClassImport
             {
-               name = CopyString(prop.name);
-               isVirtual = false; //prop.isVirtual;
-               hasSet = prop.Set ? true : false;
-               hasGet = prop.Get ? true : false;
+               name = CopyString(prop._class.fullName);
+               isRemote = prop._class.isRemote;
             };
-            if(classSym)
-               classSym._import.properties.Add(symbol._import);
+            module.classes.Add(classSym._import);
          }
-         imported = true;
-         if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
-            dllImport = true;
-      }
+         symbol = prop.symbol = Symbol { };
+         symbol._import = (ClassImport)PropertyImport
+         {
+            name = CopyString(prop.name);
+            isVirtual = false; //prop.isVirtual;
+            hasSet = prop.Set ? true : false;
+            hasGet = prop.Get ? true : false;
+         };
+         if(classSym)
+            classSym._import.properties.Add(symbol._import);
+      }
+      imported = true;
+      // Ugly work around for isNan properties declared within float/double classes which are initialized with ecereCOM
+      if((prop._class.module != privateModule || !strcmp(prop._class.name, "float") || !strcmp(prop._class.name, "double")) &&
+         prop._class.module.importType != staticImport)
+         dllImport = true;
+   }
+
+   if(!symbol.type)
+   {
+      Context context = SetupTemplatesContext(prop._class);
+      symbol.type = ProcessTypeString(prop.dataTypeString, false);
+      FinishTemplatesContext(context);
+   }
+
+   if((prop.Get && !symbol.externalGet) || (prop.Set && !symbol.externalSet))
+   {
+      if(prop._class.type == normalClass && prop._class.structSize)
+         instExternal = DeclareStruct(null, "ecere::com::Instance", false, true);
+      structExternal = DeclareStruct(null, prop._class.fullName, prop._class.type != structClass /*true*/, false);
+   }
+
+   // Get
+   if(prop.Get && !symbol.externalGet)
+   {
+      Declaration decl;
+      OldList * specifiers, * declarators;
+      Declarator d;
+      OldList * params;
+      Specifier spec = null;
+      External external;
+      Declarator typeDecl;
+      bool simple = false;
+      bool needReference;
+
+      specifiers = MkList();
+      declarators = MkList();
+      params = MkList();
+
+      ListAdd(params, MkTypeName(MkListOne(MkSpecifierName(prop._class.fullName)),
+         MkDeclaratorIdentifier(MkIdentifier("this"))));
+
+      d = MkDeclaratorIdentifier(MkIdentifier(getName));
+      //if(imported)
+      if(dllImport)
+         d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
 
-      if(!symbol.type)
       {
          Context context = SetupTemplatesContext(prop._class);
-         symbol.type = ProcessTypeString(prop.dataTypeString, false);
+         typeDecl = SpecDeclFromString(prop.dataTypeString, specifiers, null);
          FinishTemplatesContext(context);
       }
 
-      // Get
-      if(prop.Get)
+      // Make sure the simple _class's type is declared
+      needReference = !typeDecl || typeDecl.type == identifierDeclarator;
+      for(spec = specifiers->first; spec; spec = spec.next)
       {
-         if(!symbol.externalGet || symbol.externalGet.type == functionExternal)
+         if(spec.type == nameSpecifier)
          {
-            Declaration decl;
-            OldList * specifiers, * declarators;
-            Declarator d;
-            OldList * params;
-            Specifier spec;
-            External external;
-            Declarator typeDecl;
-            bool simple = false;
+            Symbol classSym = spec.symbol;
+            if(needReference)
+            {
+               symbol._class = classSym.registered;
+               if(classSym.registered && classSym.registered.type == structClass)
+                  simple = true;
+            }
+            break;
+         }
+      }
 
-            specifiers = MkList();
-            declarators = MkList();
-            params = MkList();
+      if(!simple)
+         d = PlugDeclarator(typeDecl, d);
+      else
+      {
+         ListAdd(params, MkTypeName(specifiers,
+            PlugDeclarator(typeDecl, MkDeclaratorIdentifier(MkIdentifier("value")))));
+         specifiers = MkList();
+      }
 
-            ListAdd(params, MkTypeName(MkListOne(MkSpecifierName /*MkClassName*/(prop._class.fullName)),
-               MkDeclaratorIdentifier(MkIdentifier("this"))));
+      d = MkDeclaratorFunction(d, params);
 
-            d = MkDeclaratorIdentifier(MkIdentifier(getName));
-            //if(imported)
-            if(dllImport)
-               d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
+      //if(imported)
+      if(dllImport)
+         specifiers->Insert(null, MkSpecifier(EXTERN));
+      else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
+         specifiers->Insert(null, MkSpecifier(STATIC));
+      if(simple)
+         ListAdd(specifiers, MkSpecifier(VOID));
 
-            {
-               Context context = SetupTemplatesContext(prop._class);
-               typeDecl = SpecDeclFromString(prop.dataTypeString, specifiers, null);
-               FinishTemplatesContext(context);
-            }
+      ListAdd(declarators, MkInitDeclarator(d, null));
 
-            // Make sure the simple _class's type is declared
-            for(spec = specifiers->first; spec; spec = spec.next)
-            {
-               if(spec.type == nameSpecifier /*SpecifierClass*/)
-               {
-                  if((!typeDecl || typeDecl.type == identifierDeclarator))
-                  {
-                     Symbol classSym = spec.symbol; // FindClass(spec.name);
-                     symbol._class = classSym.registered;
-                     if(classSym.registered && classSym.registered.type == structClass)
-                     {
-                        DeclareStruct(spec.name, false);
-                        simple = true;
-                     }
-                  }
-               }
-            }
+      decl = MkDeclaration(specifiers, declarators);
 
-            if(!simple)
-               d = PlugDeclarator(typeDecl, d);
-            else
-            {
-               ListAdd(params, MkTypeName(specifiers,
-                  PlugDeclarator(typeDecl, MkDeclaratorIdentifier(MkIdentifier("value")))));
-               specifiers = MkList();
-            }
+      external = MkExternalDeclaration(decl);
 
-            d = MkDeclaratorFunction(d, params);
+      if(structExternal)
+         external.CreateEdge(structExternal, false);
+      if(instExternal)
+         external.CreateEdge(instExternal, false);
 
-            //if(imported)
-            if(dllImport)
-               specifiers->Insert(null, MkSpecifier(EXTERN));
-            else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
-               specifiers->Insert(null, MkSpecifier(STATIC));
-            if(simple)
-               ListAdd(specifiers, MkSpecifier(VOID));
+      if(spec)
+         DeclareStruct(external, spec.name, false, needReference);
 
-            ListAdd(declarators, MkInitDeclarator(d, null));
+      ast->Add(external);
+      external.symbol = symbol;
+      symbol.externalGet = external;
 
-            decl = MkDeclaration(specifiers, declarators);
+      ReplaceThisClassSpecifiers(specifiers, prop._class);
 
-            external = MkExternalDeclaration(decl);
-            ast->Insert(curExternal.prev, external);
-            external.symbol = symbol;
-            symbol.externalGet = external;
+      if(typeDecl)
+         FreeDeclarator(typeDecl);
+   }
 
-            ReplaceThisClassSpecifiers(specifiers, prop._class);
+   // Set
+   if(prop.Set && !symbol.externalSet)
+   {
+      Declaration decl;
+      OldList * specifiers, * declarators;
+      Declarator d;
+      OldList * params;
+      Specifier spec = null;
+      External external;
+      Declarator typeDecl;
+      bool needReference;
 
-            if(typeDecl)
-               FreeDeclarator(typeDecl);
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.externalGet, curExternal.prev);
-         }
+      declarators = MkList();
+      params = MkList();
+
+      if(!prop.conversion || prop._class.type == structClass)
+      {
+         ListAdd(params, MkTypeName(MkListOne(MkSpecifierName(prop._class.fullName)),
+            MkDeclaratorIdentifier(MkIdentifier("this"))));
       }
 
-      // Set
-      if(prop.Set)
+      specifiers = MkList();
+
       {
-         if(!symbol.externalSet || symbol.externalSet.type == functionExternal)
-         {
-            Declaration decl;
-            OldList * specifiers, * declarators;
-            Declarator d;
-            OldList * params;
-            Specifier spec;
-            External external;
-            Declarator typeDecl;
+         Context context = SetupTemplatesContext(prop._class);
+         typeDecl = d = SpecDeclFromString(prop.dataTypeString, specifiers,
+            MkDeclaratorIdentifier(MkIdentifier("value")));
+         FinishTemplatesContext(context);
+      }
+      if(!strcmp(prop._class.base.fullName, "eda::Row") || !strcmp(prop._class.base.fullName, "eda::Id"))
+         specifiers->Insert(null, MkSpecifier(CONST));
 
-            declarators = MkList();
-            params = MkList();
+      ListAdd(params, MkTypeName(specifiers, d));
 
-            // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
-            if(!prop.conversion || prop._class.type == structClass)
-            {
-               ListAdd(params, MkTypeName(MkListOne(MkSpecifierName/*MkClassName*/(prop._class.fullName)),
-                  MkDeclaratorIdentifier(MkIdentifier("this"))));
-            }
+      d = MkDeclaratorIdentifier(MkIdentifier(setName));
+      if(dllImport)
+         d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
+      d = MkDeclaratorFunction(d, params);
 
-            specifiers = MkList();
+      // Make sure the simple _class's type is declared
+      needReference = !typeDecl || typeDecl.type == identifierDeclarator;
+      for(spec = specifiers->first; spec; spec = spec.next)
+      {
+         if(spec.type == nameSpecifier)
+         {
+            Symbol classSym = spec.symbol;
+            if(needReference)
+               symbol._class = classSym.registered;
+            break;
+         }
+      }
 
-            {
-               Context context = SetupTemplatesContext(prop._class);
-               typeDecl = d = SpecDeclFromString(prop.dataTypeString, specifiers,
-                  MkDeclaratorIdentifier(MkIdentifier("value")));
-               FinishTemplatesContext(context);
-            }
-            ListAdd(params, MkTypeName(specifiers, d));
+      ListAdd(declarators, MkInitDeclarator(d, null));
 
-            d = MkDeclaratorIdentifier(MkIdentifier(setName));
-            //if(imported)
-            if(dllImport)
-               d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
-            d = MkDeclaratorFunction(d, params);
+      specifiers = MkList();
+      if(dllImport)
+         specifiers->Insert(null, MkSpecifier(EXTERN));
+      else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
+         specifiers->Insert(null, MkSpecifier(STATIC));
 
-            // Make sure the simple _class's type is declared
-            for(spec = specifiers->first; spec; spec = spec.next)
-            {
-               if(spec.type == nameSpecifier /*SpecifierClass*/)
-               {
-                  if((!typeDecl || typeDecl.type == identifierDeclarator))
-                  {
-                     Symbol classSym = spec.symbol; // FindClass(spec.name);
-                     symbol._class = classSym.registered;
-                     if(classSym.registered && classSym.registered.type == structClass)
-                        DeclareStruct(spec.name, false);
-                  }
-               }
-            }
+      if(!prop.conversion || prop._class.type == structClass)
+         ListAdd(specifiers, MkSpecifier(VOID));
+      else
+         ListAdd(specifiers, MkSpecifierName(prop._class.fullName));
 
-            ListAdd(declarators, MkInitDeclarator(d, null));
+      decl = MkDeclaration(specifiers, declarators);
 
-            specifiers = MkList();
-            //if(imported)
-            if(dllImport)
-               specifiers->Insert(null, MkSpecifier(EXTERN));
-            else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
-               specifiers->Insert(null, MkSpecifier(STATIC));
+      external = MkExternalDeclaration(decl);
 
-            // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
-            if(!prop.conversion || prop._class.type == structClass)
-               ListAdd(specifiers, MkSpecifier(VOID));
-            else
-               ListAdd(specifiers, MkSpecifierName/*MkClassName*/(prop._class.fullName));
+      if(structExternal)
+         external.CreateEdge(structExternal, false);
+      if(instExternal)
+         external.CreateEdge(instExternal, false);
 
-            decl = MkDeclaration(specifiers, declarators);
+      if(spec)
+         DeclareStruct(external, spec.name, false, needReference);
 
-            external = MkExternalDeclaration(decl);
-            ast->Insert(curExternal.prev, external);
-            external.symbol = symbol;
-            symbol.externalSet = external;
+      ast->Add(external);
+      external.symbol = symbol;
+      symbol.externalSet = external;
 
-            ReplaceThisClassSpecifiers(specifiers, prop._class);
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.externalSet, curExternal.prev);
-         }
-      }
+      ReplaceThisClassSpecifiers(specifiers, prop._class);
+   }
+
+   // Property (for Watchers)
+   if(!symbol.externalPtr)
+   {
+      Declaration decl;
+      External external;
+      OldList * specifiers = MkList();
+      char propName[1024];
 
-      // Property (for Watchers)
-      if(!symbol.externalPtr)
+      if(imported)
+         specifiers->Insert(null, MkSpecifier(EXTERN));
+      else
       {
-         Declaration decl;
-         External external;
-         OldList * specifiers = MkList();
+         specifiers->Insert(null, MkSpecifier(STATIC));
+         specifiers->Add(MkSpecifierExtended(MkExtDeclAttrib(MkAttrib(ATTRIB, MkListOne(MkAttribute(CopyString("unused"), null))))));
+      }
 
-         if(imported)
-            specifiers->Insert(null, MkSpecifier(EXTERN));
-         else
-            specifiers->Insert(null, MkSpecifier(STATIC));
+      ListAdd(specifiers, MkSpecifierName("Property"));
 
-         ListAdd(specifiers, MkSpecifierName("Property"));
+      strcpy(propName, "__ecereProp_");
+      FullClassNameCat(propName, prop._class.fullName, false);
+      strcat(propName, "_");
+      FullClassNameCat(propName, prop.name, true);
 
+      {
+         OldList * list = MkList();
+         ListAdd(list, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(propName)), null));
+
+         if(!imported)
          {
-            OldList * list = MkList();
-            ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null),
-                  MkDeclaratorIdentifier(MkIdentifier(propName))), null));
+            strcpy(propName, "__ecerePropM_");
+            FullClassNameCat(propName, prop._class.fullName, false);
+            strcat(propName, "_");
+            FullClassNameCat(propName, prop.name, true);
 
-            if(!imported)
-            {
-               strcpy(propName, "__ecerePropM_");
-               FullClassNameCat(propName, prop._class.fullName, false);
-               strcat(propName, "_");
-               // strcat(propName, prop.name);
-               FullClassNameCat(propName, prop.name, true);
+            ListAdd(list, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(propName)), null));
+         }
+         decl = MkDeclaration(specifiers, list);
+      }
 
-               MangleClassName(propName);
+      external = MkExternalDeclaration(decl);
+      ast->Insert(curExternal.prev, external);
+      external.symbol = symbol;
+      symbol.externalPtr = external;
+   }
 
-               ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null),
-                     MkDeclaratorIdentifier(MkIdentifier(propName))), null));
-            }
-            decl = MkDeclaration(specifiers, list);
-         }
+   if(inCompiler && neededBy)
+   {
+      // Could improve this to create edge on only what is needed...
+      if(symbol.externalPtr)
+         neededBy.CreateUniqueEdge(symbol.externalPtr, false);
 
-         external = MkExternalDeclaration(decl);
-         ast->Insert(curExternal.prev, external);
-         external.symbol = symbol;
-         symbol.externalPtr = external;
-      }
-      else
-      {
-         // Move declaration higher...
-         ast->Move(symbol.externalPtr, curExternal.prev);
-      }
+      if(symbol.externalGet)
+         neededBy.CreateUniqueEdge(symbol.externalGet, symbol.externalGet.type == functionExternal);
+
+      if(symbol.externalSet)
+         neededBy.CreateUniqueEdge(symbol.externalSet, symbol.externalSet.type == functionExternal);
 
-      symbol.id = curExternal.symbol.idCode;
+      // IsSet ?
    }
 }
 
@@ -1673,8 +1806,16 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
             ClassTemplateArgument arg = _class.templateArgs[id];
             if(arg.dataTypeString)
             {
+               bool constant = type.constant;
                // FreeType(type);
                type = ProcessTypeString(arg.dataTypeString, false);
+               if(type.kind == classType && constant) type.constant = true;
+               else if(type.kind == pointerType)
+               {
+                  Type t = type.type;
+                  while(t.kind == pointerType) t = t.type;
+                  if(constant) t.constant = constant;
+               }
                freeType = true;
                if(type && _class.templateClass)
                   type.passAsTemplate = true;
@@ -1694,7 +1835,6 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
       {
          Class expClass = type._class.registered;
          Class cClass = null;
-         int c;
          int paramCount = 0;
          int lastParam = -1;
 
@@ -1839,7 +1979,7 @@ void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, Da
             }
          }
          //else if(!MatchTypes(member.exp.expType, type, null, _class, null, true, true, false, false))
-         else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false))
+         else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false, true))
          {
             Compiler_Error($"incompatible instance method %s\n", ident.string);
          }
@@ -1906,17 +2046,14 @@ void ProcessInstantiationType(Instantiation inst)
    if(inst._class)
    {
       MembersInit members;
-      Symbol classSym; // = inst._class.symbol; // FindClass(inst._class.name);
+      Symbol classSym;
       Class _class;
 
-      /*if(!inst._class.symbol)
-         inst._class.symbol = FindClass(inst._class.name);*/
       classSym = inst._class.symbol;
       _class = classSym ? classSym.registered : null;
 
-      // DANGER: Patch for mutex not declaring its struct when not needed
       if(!_class || _class.type != noHeadClass)
-         DeclareStruct(inst._class.name, false); //_class && _class.type == noHeadClass);
+         DeclareStruct(curExternal, inst._class.name, false, true);
 
       afterExternal = afterExternal ? afterExternal : curExternal;
 
@@ -1950,7 +2087,6 @@ void ProcessInstantiationType(Instantiation inst)
                   if(inCompiler)
                   {
                      char number[16];
-                     //members.function.dontMangle = true;
                      strcpy(name, "__ecereInstMeth_");
                      FullClassNameCat(name, _class ? _class.fullName : "_UNKNOWNCLASS", false);
                      strcat(name, "_");
@@ -1988,8 +2124,7 @@ void ProcessInstantiationType(Instantiation inst)
                               symbol.type.thisClass = _class.symbol;
                            }
                         }
-                        // TESTING THIS HERE:
-                        DeclareType(symbol.type, true, true);
+                        DeclareType(curExternal, symbol.type, true, true);
 
                      }
                      else if(classSym)
@@ -1997,99 +2132,21 @@ void ProcessInstantiationType(Instantiation inst)
                         Compiler_Error($"couldn't find virtual method %s in class %s\n",
                            unmangled, classSym.string);
                      }
-                  }
-
-                  //declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
-                  createdExternal = ProcessClassFunction(classSym ? classSym.registered : null, members.function, ast, afterExternal, true);
-
-                  if(nameID)
-                  {
-                     FreeSpecifier(nameID._class);
-                     nameID._class = null;
-                  }
-
-                  if(inCompiler)
-                  {
-
-                     Type type = declarator.symbol.type;
-                     External oldExternal = curExternal;
-
-                     // *** Commented this out... Any negative impact? Yes: makes double prototypes declarations... Why was it commented out?
-                     // *** It was commented out for problems such as
-                     /*
-                           class VirtualDesktop : Window
-                           {
-                              clientSize = Size { };
-                              Timer timer
-                              {
-                                 bool DelayExpired()
-                                 {
-                                    clientSize.w;
-                                    return true;
-                                 }
-                              };
-                           }
-                     */
-                     // Commented Out: Good for bet.ec in Poker (Otherwise: obj\bet.c:187: error: `currentBet' undeclared (first use in this function))
-
-                     declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
-
-                     /*
-                     if(strcmp(declarator.symbol.string, name))
-                     {
-                        printf("TOCHECK: Look out for this\n");
-                        delete declarator.symbol.string;
-                        declarator.symbol.string = CopyString(name);
-                     }
-
-                     if(!declarator.symbol.parent && globalContext.symbols.root != (BTNode)declarator.symbol)
-                     {
-                        printf("TOCHECK: Will this ever be in a list? Yes.\n");
-                        excludedSymbols->Remove(declarator.symbol);
-                        globalContext.symbols.Add((BTNode)declarator.symbol);
-                        if(strstr(declarator.symbol.string), "::")
-                           globalContext.hasNameSpace = true;
-
-                     }
-                     */
-
-                     //curExternal = curExternal.prev;
-                     //afterExternal = afterExternal->next;
-
-                     //ProcessFunction(afterExternal->function);
-
-                     //curExternal = afterExternal;
-                     {
-                        External externalDecl;
-                        externalDecl = MkExternalDeclaration(null);
-                        ast->Insert(oldExternal.prev, externalDecl);
-
-                        // Which function does this process?
-                        if(createdExternal.function)
-                        {
-                           ProcessFunction(createdExternal.function);
-
-                           //curExternal = oldExternal;
-
-                           {
-                              //Declaration decl = MkDeclaration(members.function.specifiers, MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
-
-                              Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier),
-                                 MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
+                  }
 
-                              //externalDecl = MkExternalDeclaration(decl);
+                  createdExternal = ProcessClassFunction(classSym ? classSym.registered : null, members.function, ast, afterExternal, true);
 
-                              //***** ast->Insert(external.prev, externalDecl);
-                              //ast->Insert(curExternal.prev, externalDecl);
-                              externalDecl.declaration = decl;
-                              if(decl.symbol && !decl.symbol.pointerExternal)
-                                 decl.symbol.pointerExternal = externalDecl;
+                  if(nameID)
+                  {
+                     FreeSpecifier(nameID._class);
+                     nameID._class = null;
+                  }
 
-                              // Trying this out...
-                              declarator.symbol.pointerExternal = externalDecl;
-                           }
-                        }
-                     }
+                  curExternal = createdExternal;
+                  if(inCompiler)
+                  {
+                     if(createdExternal.function)
+                        ProcessFunction(createdExternal.function);
                   }
                   else if(declarator)
                   {
@@ -2134,36 +2191,42 @@ void ProcessInstantiationType(Instantiation inst)
    }
 }
 
-static void DeclareType(Type type, bool declarePointers, bool declareParams)
+void DeclareType(External neededFor, Type type, bool needDereference, bool forFunctionDef)
+{
+   _DeclareType(neededFor, type, needDereference, forFunctionDef, false);
+}
+
+void DeclareTypeForwardDeclare(External neededFor, Type type, bool needDereference, bool forFunctionDef)
+{
+   _DeclareType(neededFor, type, needDereference, forFunctionDef, true);
+}
+
+static void _DeclareType(External neededFor, Type type, bool needDereference, bool forFunctionDef, bool fwdDecl)
 {
-   // OPTIMIZATIONS: TESTING THIS...
    if(inCompiler)
    {
       if(type.kind == functionType)
       {
          Type param;
-         if(declareParams)
-         {
-            for(param = type.params.first; param; param = param.next)
-               DeclareType(param, declarePointers, true);
-         }
-         DeclareType(type.returnType, declarePointers, true);
+         for(param = type.params.first; param; param = param.next)
+            _DeclareType(neededFor, param, forFunctionDef, false, fwdDecl);
+         _DeclareType(neededFor, type.returnType, forFunctionDef, false, fwdDecl);
       }
-      else if(type.kind == pointerType && declarePointers)
-         DeclareType(type.type, declarePointers, false);
+      else if(type.kind == pointerType)
+         _DeclareType(neededFor, type.type, false, false, fwdDecl);
       else if(type.kind == classType)
       {
-         if(type._class.registered && (type._class.registered.type == structClass || type._class.registered.type == noHeadClass) && !type._class.declaring)
-            DeclareStruct(type._class.registered.fullName, type._class.registered.type == noHeadClass);
+         Class c = type._class.registered;
+         _DeclareStruct(neededFor, c ? c.fullName : "ecere::com::Instance", c ? c.type == noHeadClass : false, needDereference && c && c.type == structClass, fwdDecl);
       }
       else if(type.kind == structType || type.kind == unionType)
       {
          Type member;
          for(member = type.members.first; member; member = member.next)
-            DeclareType(member, false, false);
+            _DeclareType(neededFor, member, needDereference, forFunctionDef, fwdDecl);
       }
       else if(type.kind == arrayType)
-         DeclareType(type.arrayType, declarePointers, false);
+         _DeclareType(neededFor, type.arrayType, true, false, fwdDecl);
    }
 }
 
@@ -2341,18 +2404,17 @@ public void ProcessPropertyType(Property prop)
    }
 }
 
-public void DeclareMethod(Method method, char * name)
+public void DeclareMethod(External neededFor, Method method, const char * name)
 {
    Symbol symbol = method.symbol;
-   if(!symbol || (!symbol.pointerExternal && method.type == virtualMethod) || symbol.id > (curExternal ? curExternal.symbol.idCode : -1))
+   if(!symbol || (!symbol.pointerExternal && (!symbol.methodCodeExternal || method.type == virtualMethod)))
    {
-      bool imported = false;
       bool dllImport = false;
 
       if(!method.dataType)
          method.dataType = ProcessTypeString(method.dataTypeString, false);
 
-      if(!symbol || symbol._import || method.type == virtualMethod)
+      //if(!symbol || symbol._import || method.type == virtualMethod)
       {
          if(!symbol || method.type == virtualMethod)
          {
@@ -2390,45 +2452,18 @@ public void DeclareMethod(Method method, char * name)
             }
             if(!symbol)
             {
-               // Set the symbol type
-               /*
-               if(!type.thisClass)
-               {
-                  type.thisClass = method._class.symbol; // FindClass(method._class.fullName);
-               }
-               else if(type.thisClass == (void *)-1)
-               {
-                  type.thisClass = null;
-               }
-               */
-               // symbol.type = ProcessTypeString(method.dataTypeString, false);
                symbol.type = method.dataType;
                if(symbol.type) symbol.type.refCount++;
             }
-            /*
-            if(!method.thisClass || strcmp(method.thisClass, "void"))
-               symbol.type.params.Insert(null,
-                  MkClassType(method.thisClass ? method.thisClass : method._class.fullName));
-            */
          }
          if(!method.dataType.dllExport)
          {
-            imported = true;
-            if(method._class.module != privateModule && method._class.module.importType != staticImport)
+            if((method._class.module != privateModule || !strcmp(method._class.name, "float") || !strcmp(method._class.name, "double")) && method._class.module.importType != staticImport)
                dllImport = true;
          }
       }
 
-      /* MOVING THIS UP
-      if(!method.dataType)
-         method.dataType = ((Symbol)method.symbol).type;
-         //ProcessMethodType(method);
-      */
-
-      if(method.type != virtualMethod && method.dataType)
-         DeclareType(method.dataType, true, true);
-
-      if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
+      if(inCompiler)
       {
          // We need a declaration here :)
          Declaration decl;
@@ -2440,7 +2475,6 @@ public void DeclareMethod(Method method, char * name)
          specifiers = MkList();
          declarators = MkList();
 
-         //if(imported)
          if(dllImport)
             ListAdd(specifiers, MkSpecifier(EXTERN));
          else if(method._class.symbol && ((Symbol)method._class.symbol).isStatic)
@@ -2454,7 +2488,6 @@ public void DeclareMethod(Method method, char * name)
          else
          {
             d = MkDeclaratorIdentifier(MkIdentifier(name));
-            //if(imported)
             if(dllImport)
                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
             {
@@ -2485,7 +2518,7 @@ public void DeclareMethod(Method method, char * name)
                {
                   Class _class = method.dataType.thisClass ? method.dataType.thisClass.registered : method._class;
                   TypeName thisParam = MkTypeName(MkListOne(
-                     MkSpecifierName/*MkClassName*/(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)),
+                     MkSpecifierName(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)),
                      (_class && _class.type == systemClass) ? MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("this"))) : MkDeclaratorIdentifier(MkIdentifier("this")));
                   TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
                   Specifier firstSpec = firstParam.qualifiers ? firstParam.qualifiers->first : null;
@@ -2502,17 +2535,8 @@ public void DeclareMethod(Method method, char * name)
                   funcDecl.function.parameters->Insert(null, thisParam);
                }
             }
-            // Make sure we don't have empty parameter declarations for static methods...
-            /*
-            else if(!funcDecl.function.parameters)
-            {
-               funcDecl.function.parameters = MkList();
-               funcDecl.function.parameters->Insert(null,
-                  MkTypeName(MkListOne(MkSpecifier(VOID)),null));
-            }*/
          }
-         // TESTING THIS:
-         ProcessDeclarator(d);
+         ProcessDeclarator(d, true);
 
          ListAdd(declarators, MkInitDeclarator(d, null));
 
@@ -2520,35 +2544,19 @@ public void DeclareMethod(Method method, char * name)
 
          ReplaceThisClassSpecifiers(specifiers, method._class);
 
-         // Keep a different symbol for the function definition than the declaration...
-         if(symbol.pointerExternal)
-         {
-            Symbol functionSymbol { };
-
-            // Copy symbol
-            {
-               *functionSymbol = *symbol;
-               functionSymbol.string = CopyString(symbol.string);
-               if(functionSymbol.type)
-                  functionSymbol.type.refCount++;
-            }
-
-            excludedSymbols->Add(functionSymbol);
-            symbol.pointerExternal.symbol = functionSymbol;
-         }
          external = MkExternalDeclaration(decl);
-         if(curExternal)
-            ast->Insert(curExternal ? curExternal.prev : null, external);
          external.symbol = symbol;
          symbol.pointerExternal = external;
+         ast->Add(external);
+         DeclareStruct(external, method._class.fullName, true, true);
+         if(method.dataType)
+            DeclareType(external, method.dataType, true, true);
       }
-      else if(ast)
-      {
-         // Move declaration higher...
-         ast->Move(symbol.pointerExternal, curExternal.prev);
-      }
-
-      symbol.id = curExternal ? curExternal.symbol.idCode : MAXINT;
+   }
+   if(inCompiler && neededFor)
+   {
+      External external = symbol.pointerExternal ? symbol.pointerExternal : symbol.methodCodeExternal;
+      neededFor.CreateUniqueEdge(external, external.type == functionExternal);
    }
 }
 
@@ -2595,6 +2603,7 @@ char * ReplaceThisClass(Class _class)
 
 Type ReplaceThisClassType(Class _class)
 {
+   Type type;
    if(thisClassParams && _class.templateParams.count && !_class.templateClass)
    {
       bool first = true;
@@ -2628,14 +2637,16 @@ Type ReplaceThisClassType(Class _class)
          className[len++] = '>';
          className[len++] = '\0';
       }
-      return MkClassType(className);
-      //return ProcessTypeString(className, false);
+      type = MkClassType(className);
+      //type = ProcessTypeString(className, false);
    }
    else
    {
-      return MkClassType(_class.fullName);
-      //return ProcessTypeString(_class.fullName, false);
+      type = MkClassType(_class.fullName);
+      //type = ProcessTypeString(_class.fullName, false);
    }
+   //type.wasThisClass = true;
+   return type;
 }
 
 void ReplaceThisClassSpecifiers(OldList specs, Class _class)
@@ -2656,10 +2667,11 @@ void ReplaceThisClassSpecifiers(OldList specs, Class _class)
 }
 
 // Returns imported or not
-bool DeclareFunction(GlobalFunction function, char * name)
+bool DeclareFunction(External neededFor, GlobalFunction function, char * name)
 {
    Symbol symbol = function.symbol;
-   if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
+   // TOCHECK: Might get rid of the pointerExternal check in favor of marking the edge as breakable
+   if(!symbol || !symbol.pointerExternal)
    {
       bool imported = false;
       bool dllImport = false;
@@ -2699,11 +2711,10 @@ bool DeclareFunction(GlobalFunction function, char * name)
             dllImport = true;
       }
 
-      DeclareType(function.dataType, true, true);
-
       if(inCompiler)
       {
-         if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
+         // TOCHECK: What's with the functionExternal check here? Is it Edge breaking / forward declaration?
+         //if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
          {
             // We need a declaration here :)
             Declaration decl;
@@ -2715,15 +2726,9 @@ bool DeclareFunction(GlobalFunction function, char * name)
             specifiers = MkList();
             declarators = MkList();
 
-            //if(imported)
-               ListAdd(specifiers, MkSpecifier(EXTERN));
-            /*
-            else
-               ListAdd(specifiers, MkSpecifier(STATIC));
-            */
+            ListAdd(specifiers, MkSpecifier(EXTERN));
 
             d = MkDeclaratorIdentifier(MkIdentifier(imported ? name : function.name));
-            //if(imported)
             if(dllImport)
                d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
 
@@ -2761,7 +2766,8 @@ bool DeclareFunction(GlobalFunction function, char * name)
             }
 
             // Keep a different symbol for the function definition than the declaration...
-            if(symbol.pointerExternal)
+            /* Note: This should be handled by the edge breaking...
+            if(symbol.pointerExternal && symbol.pointerExternal.type == functionExternal)
             {
                Symbol functionSymbol { };
                // Copy symbol
@@ -2776,29 +2782,26 @@ bool DeclareFunction(GlobalFunction function, char * name)
 
                symbol.pointerExternal.symbol = functionSymbol;
             }
+            */
             external = MkExternalDeclaration(decl);
-            if(curExternal)
-               ast->Insert(curExternal.prev, external);
+            ast->Add(external);
             external.symbol = symbol;
             symbol.pointerExternal = external;
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.pointerExternal, curExternal.prev);
-         }
 
-         if(curExternal)
-            symbol.id = curExternal.symbol.idCode;
+            DeclareType(external, function.dataType, true, true);
+         }
       }
    }
+   if(inCompiler && neededFor && symbol && symbol.pointerExternal)
+      neededFor.CreateUniqueEdge(symbol.pointerExternal, symbol.pointerExternal.type == functionExternal);
    return (symbol && symbol._import && function.module != privateModule && function.module.importType != staticImport) ? true : false;
 }
 
-void DeclareGlobalData(GlobalData data)
+void DeclareGlobalData(External neededFor, GlobalData data)
 {
    Symbol symbol = data.symbol;
-   if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
+   // TOCHECK: Might get rid of the pointerExternal check in favor of marking the edge as breakable
+   if(!symbol || !symbol.pointerExternal)
    {
       if(inCompiler)
       {
@@ -2807,43 +2810,36 @@ void DeclareGlobalData(GlobalData data)
       }
       if(!data.dataType)
          data.dataType = ProcessTypeString(data.dataTypeString, false);
-      DeclareType(data.dataType, true, true);
+
       if(inCompiler)
       {
-         if(!symbol.pointerExternal)
-         {
-            // We need a declaration here :)
-            Declaration decl;
-            OldList * specifiers, * declarators;
-            Declarator d;
-            External external;
-
-            specifiers = MkList();
-            declarators = MkList();
+         // We need a declaration here :)
+         Declaration decl;
+         OldList * specifiers, * declarators;
+         Declarator d;
+         External external;
 
-            ListAdd(specifiers, MkSpecifier(EXTERN));
-            d = MkDeclaratorIdentifier(MkIdentifier(data.fullName));
-            d = SpecDeclFromString(data.dataTypeString, specifiers, d);
+         specifiers = MkList();
+         declarators = MkList();
 
-            ListAdd(declarators, MkInitDeclarator(d, null));
+         ListAdd(specifiers, MkSpecifier(EXTERN));
+         d = MkDeclaratorIdentifier(MkIdentifier(data.fullName));
+         d = SpecDeclFromString(data.dataTypeString, specifiers, d);
 
-            decl = MkDeclaration(specifiers, declarators);
-            external = MkExternalDeclaration(decl);
-            if(curExternal)
-               ast->Insert(curExternal.prev, external);
-            external.symbol = symbol;
-            symbol.pointerExternal = external;
-         }
-         else
-         {
-            // Move declaration higher...
-            ast->Move(symbol.pointerExternal, curExternal.prev);
-         }
+         ListAdd(declarators, MkInitDeclarator(d, null));
 
+         decl = MkDeclaration(specifiers, declarators);
+         external = MkExternalDeclaration(decl);
          if(curExternal)
-            symbol.id = curExternal.symbol.idCode;
+            ast->Insert(curExternal.prev, external);
+         external.symbol = symbol;
+         symbol.pointerExternal = external;
+
+         DeclareType(external, data.dataType, true, true);
       }
    }
+   if(inCompiler && neededFor && symbol && symbol.pointerExternal)
+      neededFor.CreateUniqueEdge(symbol.pointerExternal, false);
 }
 
 class Conversion : struct
@@ -2854,10 +2850,38 @@ class Conversion : struct
    Type resultType;
 };
 
-public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams, bool isConversionExploration)
+static bool CheckConstCompatibility(Type source, Type dest, bool warn)
+{
+   bool status = true;
+   if(((source.kind == classType && source._class && source._class.registered) || source.kind == arrayType || source.kind == pointerType) &&
+      ((dest.kind == classType && dest._class && dest._class.registered) || /*dest.kind == arrayType || */dest.kind == pointerType))
+   {
+      Class sourceClass = source.kind == classType ? source._class.registered : null;
+      Class destClass = dest.kind == classType ? dest._class.registered : null;
+      if((!sourceClass || (sourceClass && sourceClass.type == normalClass && !sourceClass.structSize)) &&
+         (!destClass || (destClass && destClass.type == normalClass && !destClass.structSize)))
+      {
+         Type sourceType = source, destType = dest;
+         while((sourceType.kind == pointerType || sourceType.kind == arrayType) && sourceType.type) sourceType = sourceType.type;
+         while((destType.kind == pointerType || destType.kind == arrayType) && destType.type) destType = destType.type;
+         if(!destType.constant && sourceType.constant)
+         {
+            status = false;
+            if(warn)
+               Compiler_Warning($"discarding const qualifier\n");
+         }
+      }
+   }
+   return status;
+}
+
+public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams,
+                       bool isConversionExploration, bool warnConst)
 {
    if(source && dest)
    {
+      if(warnConst)
+         CheckConstCompatibility(source, dest, true);
       // Property convert;
 
       if(source.kind == templateType && dest.kind != templateType)
@@ -2872,7 +2896,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
          if(type) dest = type;
       }
 
-      if(dest.classObjectType == typedObject)
+      if(dest.classObjectType == typedObject && dest.kind != functionType)
       {
          if(source.classObjectType != anyObject)
             return true;
@@ -2887,9 +2911,9 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
       }
       else
       {
-         if(source.classObjectType == anyObject)
+         if(source.kind != functionType && source.classObjectType == anyObject)
             return true;
-         if(dest.classObjectType == anyObject && source.classObjectType != typedObject)
+         if(dest.kind != functionType && dest.classObjectType == anyObject && source.classObjectType != typedObject)
             return true;
       }
 
@@ -2915,7 +2939,6 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
       if(!isConversionExploration && source.kind == pointerType && source.type.kind == voidType &&
          ((dest.kind == classType && (!dest._class || !dest._class.registered || dest._class.registered.type == structClass || dest._class.registered.type == normalClass || dest._class.registered.type == noHeadClass || dest._class.registered.type == systemClass))
          || dest.kind == subClassType || dest.kind == pointerType || dest.kind == arrayType || dest.kind == functionType || dest.kind == thisClassType)
-
          /* dest.kind != voidType && dest.kind != structType && dest.kind != unionType  */
 
          /*&& (dest.kind != classType || dest._class.registered.type != structClass)*/)
@@ -2949,9 +2972,11 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
          else
          {
             // Added this so that DefinedColor = Color doesn't go through ColorRGB property
-            if(enumBaseType &&
-               dest._class && dest._class.registered && dest._class.registered.type == enumClass &&
-               ((source._class && source._class.registered && source._class.registered.type != enumClass) || source.kind == classType)) // Added this here for a base enum to be acceptable for a derived enum (#139)
+            if(dest._class && dest._class.registered && source._class && source._class.registered &&
+               (dest.casted || (enumBaseType && dest._class.registered.type == enumClass &&
+                  (source.kind == classType ||  // Added this here for a base enum to be acceptable for a derived enum (#139)
+                   source._class.registered.type != enumClass)
+                ) ) )
             {
                if(eClass_IsDerived(dest._class.registered, source._class.registered))
                {
@@ -2982,7 +3007,11 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
 
                      if(!convert.dataType)
                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
-                     if(MatchTypes(convert.dataType, dest, conversions, null, null, false, true, false, true))
+                     // Only go ahead with this conversion flow while processing an existing conversion if the conversion data type is a class
+                     if((!isConversionExploration || convert.dataType.kind == classType || !strcmp(_class.name, "String")) &&
+                        MatchTypes(convert.dataType, dest, conversions, null, null,
+                           (convert.dataType.kind == classType && !strcmp(convert.dataTypeString, "String")) ? true : false,
+                              convert.dataType.kind == classType, false, true, warnConst))
                      {
                         if(!conversions && !convert.Get)
                            return true;
@@ -2997,6 +3026,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                               Conversion conv { convert = convert, isGet = true };
                               // conversions.Add(conv);
                               conversions.Insert(after, conv);
+
                               return true;
                            }
                         }
@@ -3018,32 +3048,47 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                {
                   if(convert.memberAccess == publicAccess || _class.module == privateModule)
                   {
+                     Type constType = null;
+                     bool success = false;
                      // Conversion after = (conversions != null) ? conversions.last : null;
 
                      if(!convert.dataType)
                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
+
+                     if(warnConst && convert.dataType.kind == pointerType && convert.dataType.type && dest.constant)
+                     {
+                        Type ptrType { };
+                        constType = { kind = pointerType, refCount = 1, type = ptrType };
+                        CopyTypeInto(ptrType, convert.dataType.type);
+                        ptrType.constant = true;
+                     }
+
                      // Just added this equality check to prevent recursion.... Make it safer?
                      // Changed enumBaseType to false here to prevent all int-compatible enums to show up in AnchorValues
-                     if(convert.dataType != dest && MatchTypes(source, convert.dataType, conversions, null, null, true, false /*true*/, false, true))
+                     if((constType || convert.dataType != dest) && MatchTypes(source, constType ? constType : convert.dataType, conversions, null, null, true, false /*true*/, false, true, warnConst))
                      {
                         if(!conversions && !convert.Set)
-                           return true;
+                           success = true;
                         else if(conversions != null)
                         {
                            if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
                               convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
                               (source.kind != classType || source._class.registered != _class.base))
-                              return true;
+                              success = true;
                            else
                            {
                               // *** Testing this! ***
                               Conversion conv { convert = convert };
                               conversions.Add(conv);
                               //conversions.Insert(after, conv);
-                              return true;
+                              success = true;
                            }
                         }
                      }
+                     if(constType)
+                        FreeType(constType);
+                     if(success)
+                        return true;
                   }
                }
             }
@@ -3063,7 +3108,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                if(dest._class.registered.dataType.kind == classType || source.truth || dest.truth/* ||
                   !strcmp(dest._class.registered.name, "bool") || (source.kind == classType && !strcmp(source._class.string, "bool"))*/)
                {
-                  if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
+                  if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, dest._class.registered.dataType.kind == classType, false, false, warnConst))
                   {
                      return true;
                   }
@@ -3086,7 +3131,9 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
 
                      if(!convert.dataType)
                         convert.dataType = ProcessTypeString(convert.dataTypeString, false);
-                     if(convert.dataType != source && MatchTypes(convert.dataType, dest, conversions, null, null, true, true, false, true))
+                     if(convert.dataType != source &&
+                        (!isConversionExploration || convert.dataType.kind == classType || !strcmp(_class.name, "String")) &&
+                        MatchTypes(convert.dataType, dest, conversions, null, null, convert.dataType.kind == classType, convert.dataType.kind == classType, false, true, warnConst))
                      {
                         if(!conversions && !convert.Get)
                            return true;
@@ -3115,9 +3162,13 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
             {
                if(!source._class.registered.dataType)
                   source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
-               if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, true, false, false))
+               if(!isConversionExploration || source._class.registered.dataType.kind == classType || !strcmp(source._class.registered.name, "String"))
                {
-                  return true;
+                  if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, source._class.registered.dataType.kind == classType, source._class.registered.dataType.kind == classType, false, false, warnConst))
+                     return true;
+                  // For bool to be accepted by byte, short, etc.
+                  else if(MatchTypes(dest, source._class.registered.dataType, null, null, null, false, false, false, false, warnConst))
+                     return true;
                }
             }
          }
@@ -3145,7 +3196,7 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
       else if(source.kind == enumType &&
          (dest.kind == intType || dest.kind == shortType || dest.kind == charType || source.kind == _BoolType || dest.kind == longType || dest.kind == int64Type || dest.kind == intPtrType || dest.kind == intSizeType))
           return true;
-      else if(dest.kind == enumType &&
+      else if(dest.kind == enumType && !isConversionExploration &&
          (source.kind == intType || source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == longType || source.kind == int64Type || source.kind == intPtrType || source.kind == intSizeType))
           return true;
       else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) &&
@@ -3242,11 +3293,14 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
 
 
          // Source return type must be derived from destination return type
-         if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false))
+         if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false, warnConst))
          {
             Compiler_Warning($"incompatible return type for function\n");
             return false;
          }
+         // The const check is backwards from the MatchTypes above (for derivative classes checks)
+         else
+            CheckConstCompatibility(dest.returnType, source.returnType, true);
 
          // Check parameters
 
@@ -3298,8 +3352,8 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
                }
 
                // paramDest must be derived from paramSource
-               if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false) &&
-                  (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false)))
+               if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false, warnConst) &&
+                  (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false, warnConst)))
                {
                   char type[1024];
                   type[0] = 0;
@@ -3330,8 +3384,15 @@ public bool MatchTypes(Type source, Type dest, OldList conversions, Class owning
       else if((dest.kind == pointerType || dest.kind == arrayType) &&
          (source.kind == arrayType || source.kind == pointerType))
       {
-         if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false))
-            return true;
+         // Pointers to pointer is incompatible with non normal/nohead classes
+         if(!(dest.type && dest.type.kind == pointerType && source.type.kind == classType && source.type._class &&
+            source.type._class.registered && (source.type._class.registered.type != normalClass && source.type._class.registered.type != noHeadClass) && !source.type.byReference))
+         {
+            ComputeTypeSize(source.type);
+            ComputeTypeSize(dest.type);
+            if(source.type.size == dest.type.size && MatchTypes(source.type, dest.type, null, null, null, true, true, false, false, warnConst))
+               return true;
+         }
       }
    }
    return false;
@@ -3361,9 +3422,10 @@ bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type de
             _class.symbol = FindClass(_class.fullName);
          type._class = _class.symbol;
 
-         if(MatchTypes(type, dest, &converts, null, null, true, false, false, false))
+         if(MatchTypes(type, dest, &converts, null, null, dest.kind != classType || !dest._class || strcmp(dest._class.string, "bool"),
+               false, false, false, false))
          {
-            NamedLink value;
+            NamedLink64 value;
             Class enumClass = eSystem_FindClass(privateModule, "enum");
             if(enumClass)
             {
@@ -3378,19 +3440,20 @@ bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type de
                   }
                   if(value)
                   {
-                     FreeExpContents(sourceExp);
                      FreeType(sourceExp.expType);
 
                      sourceExp.isConstant = true;
                      sourceExp.expType = MkClassType(baseClass.fullName);
-                     //if(inCompiler)
+                     if(inCompiler || inPreCompiler || inDebugger)
                      {
                         char constant[256];
+                        FreeExpContents(sourceExp);
+
                         sourceExp.type = constantExp;
-                        if(!strcmp(baseClass.dataTypeString, "int"))
-                           sprintf(constant, "%d",(int)value.data);
+                        if(!strcmp(baseClass.dataTypeString, "int") || !strcmp(baseClass.dataTypeString, "int64") || !strcmp(baseClass.dataTypeString, "short") || !strcmp(baseClass.dataTypeString, "char"))
+                           sprintf(constant, FORMAT64D, value.data);
                         else
-                           sprintf(constant, "0x%X",(int)value.data);
+                           sprintf(constant, FORMAT64HEXLL, value.data);
                         sourceExp.constant = CopyString(constant);
                         //for(;baseClass.base && baseClass.base.type != systemClass; baseClass = baseClass.base);
                      }
@@ -3455,14 +3518,34 @@ bool MatchWithEnums_Module(Module mainModule, Expression sourceExp, Type dest, c
    return false;
 }
 
-bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla)
+bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla, bool warnConst)
 {
-   Type source = sourceExp.expType;
+   Type source;
    Type realDest = dest;
    Type backupSourceExpType = null;
+   Expression nbExp = GetNonBracketsExp(sourceExp);
+   Expression computedExp = nbExp;
+   dest.refCount++;
+
+   if(sourceExp.isConstant && sourceExp.type != constantExp && sourceExp.type != identifierExp && sourceExp.type != castExp &&
+      dest.kind == classType && dest._class && dest._class.registered && dest._class.registered.type == enumClass)
+   {
+      computedExp = CopyExpression(nbExp);        // Keep the original expression, but compute for checking enum ranges
+      ComputeExpression(computedExp /*sourceExp*/);
+   }
+
+   source = sourceExp.expType;
 
    if(dest.kind == pointerType && sourceExp.type == constantExp && !strtoul(sourceExp.constant, null, 0))
+   {
+      if(computedExp != nbExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = nbExp;
+      }
+      FreeType(dest);
       return true;
+   }
 
    if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
    {
@@ -3477,8 +3560,16 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
               destBase = destBase.base);
           //if(source._class.registered == dest._class.registered)
           if(sourceBase == destBase)
-             return true;
-       }
+          {
+            if(computedExp != nbExp)
+            {
+               FreeExpression(computedExp);
+               computedExp = nbExp;
+            }
+            FreeType(dest);
+            return true;
+         }
+      }
    }
 
    if(source)
@@ -3488,25 +3579,29 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       int64 value = MAXINT;
 
       source.refCount++;
-      dest.refCount++;
 
-      if(sourceExp.type == constantExp)
+      if(computedExp.type == constantExp)
       {
          if(source.isSigned)
-            value = strtoll(sourceExp.constant, null, 0);
+            value = strtoll(computedExp.constant, null, 0);
          else
-            value = strtoull(sourceExp.constant, null, 0);
+            value = strtoull(computedExp.constant, null, 0);
       }
-      else if(sourceExp.type == opExp && sourceExp.op.op == '-' && !sourceExp.op.exp1 && sourceExp.op.exp2 && sourceExp.op.exp2.type == constantExp)
+      else if(computedExp.type == opExp && computedExp.op.op == '-' && !computedExp.op.exp1 && computedExp.op.exp2 && computedExp.op.exp2.type == constantExp)
       {
          if(source.isSigned)
-            value = -strtoll(sourceExp.op.exp2.constant, null, 0);
+            value = -strtoll(computedExp.op.exp2.constant, null, 0);
          else
-            value = -strtoull(sourceExp.op.exp2.constant, null, 0);
+            value = -strtoull(computedExp.op.exp2.constant, null, 0);
+      }
+      if(computedExp != nbExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = nbExp;
       }
 
       if(dest.kind != classType && source.kind == classType && source._class && source._class.registered &&
-         !strcmp(source._class.registered.fullName, "ecere::com::unichar"))
+         !strcmp(source._class.registered.fullName, "unichar" /*"ecere::com::unichar"*/))
       {
          FreeType(source);
          source = Type { kind = intType, isSigned = false, refCount = 1 };
@@ -3534,11 +3629,22 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                tempType._class = _class.symbol;
                tempType.truth = dest.truth;
                if(tempType._class)
-                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
+                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false, warnConst);
 
                // NOTE: To handle bad warnings on int64 vs 32 bit eda::Id incompatibilities
                backupSourceExpType = sourceExp.expType;
-               sourceExp.expType = dest; dest.refCount++;
+               if(dest.passAsTemplate)
+               {
+                  // Don't carry passAsTemplate
+                  sourceExp.expType = { };
+                  CopyTypeInto(sourceExp.expType, dest);
+                  sourceExp.expType.passAsTemplate = false;
+               }
+               else
+               {
+                  sourceExp.expType = dest;
+                  dest.refCount++;
+               }
                //sourceExp.expType = MkClassType(_class.fullName);
                flag = true;
 
@@ -3552,7 +3658,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          {
             if(!dest._class.registered.dataType)
                dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
-            if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
+            if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false, warnConst))
             {
                FreeType(source);
                FreeType(sourceExp.expType);
@@ -3612,7 +3718,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       {
          Class _class = source._class ? source._class.registered : null;
 
-         if(_class && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass ))  // TOCHECK: enumClass, bitClass is new here...
+         if(_class && (_class.type == unitClass || /*!strcmp(_class.fullName, "bool") || _class.type == enumClass || */_class.type == bitClass ))  // TOCHECK: enumClass, bitClass is new here...
          {
             /*
             if(dest.kind != classType)
@@ -3645,10 +3751,10 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                tempType.classObjectType = source.classObjectType;
 
                if(tempType._class)
-                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
+                  MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false, warnConst);
 
                // PUT THIS BACK TESTING UNITS?
-               if(conversions.last)
+               if(conversions && conversions.last)
                {
                   ((Conversion)(conversions.last)).resultType = dest;
                   dest.refCount++;
@@ -3691,7 +3797,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 
       if(!flag)
       {
-         if(MatchTypes(source, dest, conversions, null, null, true, true, false, false))
+         if(MatchTypes(source, dest, conversions, null, null, true, true, false, false, warnConst))
          {
             FreeType(source);
             FreeType(dest);
@@ -3715,7 +3821,16 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       if(dest.kind == classType)
       {
          Class _class = dest._class ? dest._class.registered : null;
-         if(_class && !dest.truth && (_class.type == unitClass || !strcmp(_class.fullName, "bool") ||
+         bool fittingValue = false;
+         if(_class && _class.type == enumClass)
+         {
+            Class enumClass = eSystem_FindClass(privateModule, "enum");
+            EnumClassData c = ACCESS_CLASSDATA(_class, enumClass);
+            if(c && value >= 0 && value <= c.largest)
+               fittingValue = true;
+         }
+
+         if(_class && !dest.truth && (_class.type == unitClass || fittingValue ||
             (/*_class.type == enumClass*/_class.type != structClass && !value && source.kind == intType) || _class.type == bitClass))   // TOCHECK: enumClass, bitClass is new here...
          {
             if(_class.type == normalClass || _class.type == noHeadClass)
@@ -3826,16 +3941,36 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       else if(dest.kind == charType && (source.kind == _BoolType || source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) &&
          (dest.isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
       {
-         specs = MkList();
-         if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
-         ListAdd(specs, MkSpecifier(CHAR));
+         if(source.kind == intType)
+         {
+            FreeType(dest);
+            FreeType(source);
+            if(backupSourceExpType) FreeType(backupSourceExpType);
+            return true;
+         }
+         else
+         {
+            specs = MkList();
+            if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
+            ListAdd(specs, MkSpecifier(CHAR));
+         }
       }
       else if(dest.kind == shortType && (source.kind == enumType || source.kind == _BoolType || source.kind == charType || source.kind == shortType ||
          (source.kind == intType && (dest.isSigned ? (value >= -32768 && value <= 32767) : (value >= 0 && value <= 65535)))))
       {
-         specs = MkList();
-         if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
-         ListAdd(specs, MkSpecifier(SHORT));
+         if(source.kind == intType)
+         {
+            FreeType(dest);
+            FreeType(source);
+            if(backupSourceExpType) FreeType(backupSourceExpType);
+            return true;
+         }
+         else
+         {
+            specs = MkList();
+            if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
+            ListAdd(specs, MkSpecifier(SHORT));
+         }
       }
       else if(dest.kind == intType && (source.kind == enumType || source.kind == shortType || source.kind == _BoolType || source.kind == charType || source.kind == intType))
       {
@@ -3867,7 +4002,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          return false;
       }
 
-      if(!flag)
+      if(!flag && !sourceExp.opDestType)
       {
          Expression newExp { };
          *newExp = *sourceExp;
@@ -3906,6 +4041,12 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
    }
    else
    {
+      if(computedExp != nbExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = nbExp;
+      }
+
       while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
       if(sourceExp.type == identifierExp)
       {
@@ -3920,7 +4061,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                {
                   for( ; _class && _class.type == ClassType::enumClass; _class = _class.base)
                   {
-                     NamedLink value;
+                     NamedLink64 value;
                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
                      for(value = e.values.first; value; value = value.next)
                      {
@@ -3929,22 +4070,22 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                      }
                      if(value)
                      {
-                        FreeExpContents(sourceExp);
                         FreeType(sourceExp.expType);
 
                         sourceExp.isConstant = true;
                         sourceExp.expType = MkClassType(_class.fullName);
-                        //if(inCompiler)
+                        if(inCompiler || inPreCompiler || inDebugger)
                         {
-                           char constant[256];
+                           FreeExpContents(sourceExp);
+
                            sourceExp.type = constantExp;
-                           if(/*_class && */_class.dataTypeString && !strcmp(_class.dataTypeString, "int")) // _class cannot be null here!
-                              sprintf(constant, "%d", (int) value.data);
+                           if(_class.dataTypeString && (!strcmp(_class.dataTypeString, "int") || !strcmp(_class.dataTypeString, "int64") || !strcmp(_class.dataTypeString, "short") || !strcmp(_class.dataTypeString, "char"))) // _class cannot be null here!
+                              sourceExp.constant = PrintInt64(value.data);
                            else
-                              sprintf(constant, "0x%X", (int) value.data);
-                           sourceExp.constant = CopyString(constant);
+                              sourceExp.constant = PrintUInt64(value.data);
                            //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
                         }
+                        FreeType(dest);
                         return true;
                      }
                   }
@@ -3954,8 +4095,12 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 
          // Loop through all enum classes
          if(dest.classObjectType != typedObject && dest.kind == classType /*!= ellipsisType */&& MatchWithEnums_Module(privateModule, sourceExp, dest, id.string, conversions))
+         {
+            FreeType(dest);
             return true;
+         }
       }
+      FreeType(dest);
    }
    return false;
 }
@@ -3975,18 +4120,29 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
    {                                                              \
       t value2 = op2.m;                                           \
       exp.type = constantExp;                                    \
-      exp.string = p(op1.m o value2);                     \
+      exp.string = p((t)(op1.m o value2));                     \
+      if(!exp.expType) \
+         { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
+      return true;                                                \
+   }
+
+#define BINARY_DIVIDEINT(o, name, m, t, p) \
+   static bool name(Expression exp, Operand op1, Operand op2)   \
+   {                                                              \
+      t value2 = op2.m;                                           \
+      exp.type = constantExp;                                    \
+      exp.string = p(value2 ? ((t)(op1.m o value2)) : 0);             \
       if(!exp.expType) \
          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
       return true;                                                \
    }
 
-#define BINARY_DIVIDE(o, name, m, t, p) \
+#define BINARY_DIVIDEREAL(o, name, m, t, p) \
    static bool name(Expression exp, Operand op1, Operand op2)   \
    {                                                              \
       t value2 = op2.m;                                           \
       exp.type = constantExp;                                    \
-      exp.string = p(value2 ? (op1.m o value2) : 0);             \
+      exp.string = p((t)(op1.m o value2));             \
       if(!exp.expType) \
          { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
       return true;                                                \
@@ -4005,8 +4161,8 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 #define OPERATOR_ALL(macro, o, name) \
    macro(o, Int##name, i, int, PrintInt) \
    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
-   macro(o, Int64##name, i, int, PrintInt64) \
-   macro(o, UInt64##name, ui, unsigned int, PrintUInt64) \
+   macro(o, Int64##name, i64, int64, PrintInt64) \
+   macro(o, UInt64##name, ui64, uint64, PrintUInt64) \
    macro(o, Short##name, s, short, PrintShort) \
    macro(o, UShort##name, us, unsigned short, PrintUShort) \
    macro(o, Char##name, c, char, PrintChar) \
@@ -4017,20 +4173,24 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
 #define OPERATOR_INTTYPES(macro, o, name) \
    macro(o, Int##name, i, int, PrintInt) \
    macro(o, UInt##name, ui, unsigned int, PrintUInt) \
-   macro(o, Int64##name, i, int, PrintInt64) \
-   macro(o, UInt64##name, ui, unsigned int, PrintUInt64) \
+   macro(o, Int64##name, i64, int64, PrintInt64) \
+   macro(o, UInt64##name, ui64, uint64, PrintUInt64) \
    macro(o, Short##name, s, short, PrintShort) \
    macro(o, UShort##name, us, unsigned short, PrintUShort) \
    macro(o, Char##name, c, char, PrintChar) \
    macro(o, UChar##name, uc, unsigned char, PrintUChar)
 
+#define OPERATOR_REALTYPES(macro, o, name) \
+   macro(o, Float##name, f, float, PrintFloat) \
+   macro(o, Double##name, d, double, PrintDouble)
 
 // binary arithmetic
 OPERATOR_ALL(BINARY, +, Add)
 OPERATOR_ALL(BINARY, -, Sub)
 OPERATOR_ALL(BINARY, *, Mul)
-OPERATOR_ALL(BINARY_DIVIDE, /, Div)
-OPERATOR_INTTYPES(BINARY_DIVIDE, %, Mod)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, /, Div)
+OPERATOR_REALTYPES(BINARY_DIVIDEREAL, /, Div)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, %, Mod)
 
 // unary arithmetic
 OPERATOR_ALL(UNARY, -, Neg)
@@ -4044,8 +4204,9 @@ OPERATOR_ALL(BINARY, =, Asign)
 OPERATOR_ALL(BINARY, +=, AddAsign)
 OPERATOR_ALL(BINARY, -=, SubAsign)
 OPERATOR_ALL(BINARY, *=, MulAsign)
-OPERATOR_ALL(BINARY_DIVIDE, /=, DivAsign)
-OPERATOR_INTTYPES(BINARY_DIVIDE, %=, ModAsign)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, /=, DivAsign)
+OPERATOR_REALTYPES(BINARY_DIVIDEREAL, /=, DivAsign)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, %=, ModAsign)
 
 // binary bitwise
 OPERATOR_INTTYPES(BINARY, &, BitAnd)
@@ -4082,7 +4243,7 @@ OPERATOR_ALL(BINARY, >=, GrtEqu)
 OPERATOR_ALL(BINARY, <=, SmaEqu)
 
 // tertiary condition operator
-OPERATOR_ALL(TERTIARY, ?, Cond)
+OPERATOR_INTTYPES(TERTIARY, ?, Cond)
 
 //Add, Sub, Mul, Div, Mod,     , Neg,     Inc, Dec,    Asign, AddAsign, SubAsign, MulAsign, DivAsign, ModAsign,     BitAnd, BitOr, BitXor, LShift, RShift, BitNot,     AndAsign, OrAsign, XorAsign, LShiftAsign, RShiftAsign,     Not,     Equ, Nqu,     And, Or,     Grt, Sma, GrtEqu, SmaEqu
 #define OPERATOR_TABLE_ALL(name, type) \
@@ -4154,8 +4315,8 @@ public void ReadString(char * output,  char * string)
             case 'v': output[d] = '\v'; break;
             case '\\': output[d] = '\\'; break;
             case '\"': output[d] = '\"'; break;
-            default: output[d++] = '\\'; output[d] = ch;
-            //default: output[d] = ch;
+            case '\'': output[d] = '\''; break;
+            default: output[d] = ch;
          }
          d++;
          escaped = false;
@@ -4176,13 +4337,62 @@ public void ReadString(char * output,  char * string)
    output[d] = '\0';
 }
 
+// String Unescape Copy
+
+// TOFIX: THIS DOESN'T HANDLE NUMERIC ESCAPE CODES (OCTAL/HEXADECIMAL...)?
+// This is the same as ReadString above (which also misses numeric escape codes) except it doesn't handle external quotes
+public int UnescapeString(char * d, char * s, int len)
+{
+   int j = 0, k = 0;
+   char ch;
+   while(j < len && (ch = s[j]))
+   {
+      switch(ch)
+      {
+         case '\\':
+            switch((ch = s[++j]))
+            {
+               case 'n': d[k] = '\n'; break;
+               case 't': d[k] = '\t'; break;
+               case 'a': d[k] = '\a'; break;
+               case 'b': d[k] = '\b'; break;
+               case 'f': d[k] = '\f'; break;
+               case 'r': d[k] = '\r'; break;
+               case 'v': d[k] = '\v'; break;
+               case '\\': d[k] = '\\'; break;
+               case '\"': d[k] = '\"'; break;
+               case '\'': d[k] = '\''; break;
+               default: d[k] = '\\'; d[k] = ch;
+            }
+            break;
+         default:
+            d[k] = ch;
+      }
+      j++, k++;
+   }
+   d[k] = '\0';
+   return k;
+}
+
+public char * OffsetEscapedString(char * s, int len, int offset)
+{
+   char ch;
+   int j = 0, k = 0;
+   while(j < len && k < offset && (ch = s[j]))
+   {
+      if(ch == '\\') ++j;
+      j++, k++;
+   }
+   return (k == offset) ? s + j : null;
+}
+
 public Operand GetOperand(Expression exp)
 {
    Operand op { };
    Type type = exp.expType;
    if(type)
    {
-      while(type.kind == classType &&
+      while(type.kind == classType && type._class &&
          type._class.registered && (type._class.registered.type == bitClass || type._class.registered.type == unitClass || type._class.registered.type == enumClass))
       {
          if(!type._class.registered.dataType)
@@ -4190,17 +4400,27 @@ public Operand GetOperand(Expression exp)
          type = type._class.registered.dataType;
 
       }
-      op.kind = type.kind;
-      op.type = exp.expType;
-      if(exp.isConstant && exp.type == constantExp)
+      if(exp.type == stringExp && op.kind == pointerType)
+      {
+         op.ui64 = (uint64)(uintptr)exp.string;
+         op.kind = pointerType;
+         op.ops = uint64Ops;
+      }
+      else if(exp.isConstant && exp.type == constantExp)
       {
+         op.kind = type.kind;
+         op.type = type;
+
          switch(op.kind)
          {
             case _BoolType:
             case charType:
             {
                if(exp.constant[0] == '\'')
+               {
                   op.c = exp.constant[1];
+                  op.ops = charOps;
+               }
                else if(type.isSigned)
                {
                   op.c = (char)strtol(exp.constant, null, 0);
@@ -4214,7 +4434,12 @@ public Operand GetOperand(Expression exp)
                break;
             }
             case shortType:
-               if(type.isSigned)
+               if(exp.constant[0] == '\'')
+               {
+                  op.s = exp.constant[1];
+                  op.ops = shortOps;
+               }
+               else if(type.isSigned)
                {
                   op.s = (short)strtol(exp.constant, null, 0);
                   op.ops = shortOps;
@@ -4227,7 +4452,12 @@ public Operand GetOperand(Expression exp)
                break;
             case intType:
             case longType:
-               if(type.isSigned)
+               if(exp.constant[0] == '\'')
+               {
+                  op.i = exp.constant[1];
+                  op.ops = intOps;
+               }
+               else if(type.isSigned)
                {
                   op.i = (int)strtol(exp.constant, null, 0);
                   op.ops = intOps;
@@ -4243,12 +4473,12 @@ public Operand GetOperand(Expression exp)
                if(type.isSigned)
                {
                   op.i64 = (int64)_strtoi64(exp.constant, null, 0);
-                  op.ops = intOps;
+                  op.ops = int64Ops;
                }
                else
                {
                   op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
-                  op.ops = uintOps;
+                  op.ops = uint64Ops;
                }
                op.kind = int64Type;
                break;
@@ -4279,11 +4509,21 @@ public Operand GetOperand(Expression exp)
                op.kind = int64Type;
                break;
             case floatType:
-               op.f = (float)strtod(exp.constant, null);
+               if(!strcmp(exp.constant, "inf")) op.f = float::inf();
+               else if(!strcmp(exp.constant, "-inf")) op.f = -float::inf();
+               else if(!strcmp(exp.constant, "nan")) op.f = float::nan();
+               else if(!strcmp(exp.constant, "-nan")) op.f = -float::nan();
+               else
+                  op.f = (float)strtod(exp.constant, null);
                op.ops = floatOps;
                break;
             case doubleType:
-               op.d = (double)strtod(exp.constant, null);
+               if(!strcmp(exp.constant, "inf")) op.d = double::inf();
+               else if(!strcmp(exp.constant, "-inf")) op.d = -double::inf();
+               else if(!strcmp(exp.constant, "nan")) op.d = double::nan();
+               else if(!strcmp(exp.constant, "-nan")) op.d = -double::nan();
+               else
+                  op.d = (double)strtod(exp.constant, null);
                op.ops = doubleOps;
                break;
             //case classType:    For when we have operator overloading...
@@ -4294,16 +4534,49 @@ public Operand GetOperand(Expression exp)
             case classType:
                op.ui64 = _strtoui64(exp.constant, null, 0);
                op.kind = pointerType;
-               op.ops = uintOps;
+               op.ops = uint64Ops;
                // op.ptrSize =
                break;
          }
       }
    }
-   return op;
+   return op;
+}
+
+static int64 GetEnumValue(Class _class, void * ptr)
+{
+   int64 v = 0;
+   switch(_class.typeSize)
+   {
+      case 8:
+         if(!strcmp(_class.dataTypeString, "uint64"))
+            v = (int64)*(uint64 *)ptr;
+         else
+            v = (int64)*(int64 *)ptr;
+         break;
+      case 4:
+         if(!strcmp(_class.dataTypeString, "uint"))
+            v = (int64)*(uint *)ptr;
+         else
+            v = (int64)*(int *)ptr;
+         break;
+      case 2:
+         if(!strcmp(_class.dataTypeString, "uint16"))
+            v = (int64)*(uint16 *)ptr;
+         else
+            v = (int64)*(short *)ptr;
+         break;
+      case 1:
+         if(!strcmp(_class.dataTypeString, "byte"))
+            v = (int64)*(byte *)ptr;
+         else
+            v = (int64)*(char *)ptr;
+         break;
+   }
+   return v;
 }
 
-static void UnusedFunction()
+static __attribute__((unused)) void UnusedFunction()
 {
    int a;
    a.OnGetString(0,0,0);
@@ -4341,10 +4614,10 @@ static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberLi
                if(enumClass)
                {
                   EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
-                  NamedLink item;
+                  NamedLink64 item;
                   for(item = e.values.first; item; item = item.next)
                   {
-                     if((int)item.data == *(int *)ptr)
+                     if(item.data == GetEnumValue(_class, ptr))
                      {
                         result = item.name;
                         break;
@@ -4414,7 +4687,7 @@ static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberLi
                {
                   FreeExpContents(exp);
                   // TODO: This should probably use proper type
-                  exp.constant = PrintInt64((int64)*(intptr*)ptr);
+                  exp.constant = PrintInt64((int64)*(intsize*)ptr);
                   exp.type = constantExp;
                   break;
                }
@@ -4470,10 +4743,10 @@ void PopulateInstance(Instantiation inst)
                   if(enumClass)
                   {
                      EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
-                     NamedLink item;
+                     NamedLink64 item;
                      for(item = e.values.first; item; item = item.next)
                      {
-                        if((int)item.data == *(int *)ptr)
+                        if(item.data == GetEnumValue(_class, ptr))
                         {
                            result = item.name;
                            break;
@@ -4586,7 +4859,6 @@ void ComputeInstantiation(Expression exp)
 
                      Property prop = null;
                      DataMember dataMember = null;
-                     Method method = null;
                      uint dataMemberOffset;
 
                      if(!ident)
@@ -4709,8 +4981,7 @@ void ComputeInstantiation(Expression exp)
                            if(type.kind == classType)
                            {
                               Class _class = type._class.registered;
-                              if(_class.type == bitClass || _class.type == unitClass ||
-                                 _class.type == enumClass)
+                              if(_class && (_class.type == bitClass || _class.type == unitClass || _class.type == enumClass))
                               {
                                  if(!_class.dataType)
                                     _class.dataType = ProcessTypeString(_class.dataTypeString, false);
@@ -4772,7 +5043,7 @@ void ComputeInstantiation(Expression exp)
                                  }
                               }
                            }
-                           else if(prop)
+                           else if(prop && prop.Set != (void *)(intptr)1)
                            {
                               if(value.type == instanceExp && value.instance.data)
                               {
@@ -4896,70 +5167,29 @@ void ComputeInstantiation(Expression exp)
                            {
                               BitMember bitMember = (BitMember) dataMember;
                               Type type;
-                              int part = 0;
-                              GetInt(value, &part);
+                              uint64 part = 0;
                               bits = (bits & ~bitMember.mask);
                               if(!bitMember.dataType)
                                  bitMember.dataType = ProcessTypeString(bitMember.dataTypeString, false);
-
                               type = bitMember.dataType;
-
                               if(type.kind == classType && type._class && type._class.registered)
                               {
                                  if(!type._class.registered.dataType)
                                     type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
                                  type = type._class.registered.dataType;
                               }
-
                               switch(type.kind)
                               {
                                  case _BoolType:
-                                 case charType:
-                                    if(type.isSigned)
-                                       bits |= ((char)part << bitMember.pos);
-                                    else
-                                       bits |= ((unsigned char)part << bitMember.pos);
-                                    break;
-                                 case shortType:
-                                    if(type.isSigned)
-                                       bits |= ((short)part << bitMember.pos);
-                                    else
-                                       bits |= ((unsigned short)part << bitMember.pos);
-                                    break;
+                                 case charType:       { byte v; type.isSigned ? GetChar(value, (char *)&v) : GetUChar(value, &v); part = (uint64)v; break; }
+                                 case shortType:      { uint16 v; type.isSigned ? GetShort(value, (short *)&v) : GetUShort(value, &v); part = (uint64)v; break; }
                                  case intType:
-                                 case longType:
-                                    if(type.isSigned)
-                                       bits |= ((int)part << bitMember.pos);
-                                    else
-                                       bits |= ((unsigned int)part << bitMember.pos);
-                                    break;
-                                 case int64Type:
-                                    if(type.isSigned)
-                                       bits |= ((int64)part << bitMember.pos);
-                                    else
-                                       bits |= ((uint64)part << bitMember.pos);
-                                    break;
-                                 case intPtrType:
-                                    if(type.isSigned)
-                                    {
-                                       bits |= ((intptr)part << bitMember.pos);
-                                    }
-                                    else
-                                    {
-                                       bits |= ((uintptr)part << bitMember.pos);
-                                    }
-                                    break;
-                                 case intSizeType:
-                                    if(type.isSigned)
-                                    {
-                                       bits |= ((ssize_t)(intsize)part << bitMember.pos);
-                                    }
-                                    else
-                                    {
-                                       bits |= ((size_t) (uintsize)part << bitMember.pos);
-                                    }
-                                    break;
+                                 case longType:       { uint v; type.isSigned ? GetInt(value, (int *)&v) : GetUInt(value, &v); part = (uint64)v; break; }
+                                 case int64Type:      { uint64 v; type.isSigned ? GetInt64(value, (int64 *)&v) : GetUInt64(value, &v); part = (uint64)v; break; }
+                                 case intPtrType:     { uintptr v; type.isSigned ? GetIntPtr(value, (intptr *)&v) : GetUIntPtr(value, &v); part = (uint64)v; break; }
+                                 case intSizeType:    { uintsize v; type.isSigned ? GetIntSize(value, (intsize *)&v) : GetUIntSize(value, &v); part = (uint64)v; break; }
                               }
+                              bits |= part << bitMember.pos;
                            }
                         }
                      }
@@ -4992,6 +5222,57 @@ void ComputeInstantiation(Expression exp)
    }
 }
 
+static bool Promote(Operand op, TypeKind kind, bool isSigned)
+{
+   bool result = false;
+   switch(kind)
+   {
+      case shortType:
+         if(op.kind == charType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpShort(op, &op.s) : GetOpUShort(op, &op.us);
+         break;
+      case intType:
+      case longType:
+         if(op.kind == charType || op.kind == shortType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt(op, &op.i) : GetOpUInt(op, &op.ui);
+         break;
+      case int64Type:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+            op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt64(op, &op.i64) : GetOpUInt64(op, &op.ui64);
+         break;
+      case floatType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType ||
+            op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = GetOpFloat(op, &op.f);
+         break;
+      case doubleType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType ||
+            op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = GetOpDouble(op, &op.d);
+         break;
+      case pointerType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+            op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = GetOpUInt64 /*GetOpUIntPtr*/(op, &op.ui64);
+         break;
+      case enumType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+            op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt(op, &op.i) : GetOpUInt(op, &op.ui);
+         break;
+      case intPtrType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt64 /*GetOpIntPtr*/(op, &op.i64) : GetOpUInt64 /*GetOpUIntPtr*/(op, &op.ui64);
+         break;
+      case intSizeType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpInt64 /*GetOpIntSize*/(op, &op.i64) : GetOpUInt64 /*GetOpUIntSize*/(op, &op.ui64);
+         break;
+   }
+   return result;
+}
+
 void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
 {
    if(exp.op.op == SIZEOF)
@@ -5037,6 +5318,13 @@ void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1,
       }
       else
       {
+         if(op1 && op2 && op1.type && op2.type && op1.kind != op2.kind)
+         {
+            if(Promote(op2, op1.kind, op1.type.isSigned))
+               op2.kind = op1.kind, op2.ops = op1.ops;
+            else if(Promote(op1, op2.kind, op2.type.isSigned))
+               op1.kind = op2.kind, op1.ops = op2.ops;
+         }
          switch(exp.op.op)
          {
             // binary arithmetic
@@ -5121,14 +5409,44 @@ void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1,
 
 void ComputeExpression(Expression exp)
 {
+#ifdef _DEBUG
    char expString[10240];
    expString[0] = '\0';
-#ifdef _DEBUG
    PrintExpression(exp, expString);
 #endif
 
    switch(exp.type)
    {
+      case identifierExp:
+      {
+         Identifier id = exp.identifier;
+         if(id && exp.isConstant && !inCompiler && !inPreCompiler && !inDebugger)
+         {
+            Class c = (exp.expType && exp.expType.kind == classType && exp.expType._class) ? exp.expType._class.registered : null;
+            if(c && c.type == enumClass)
+            {
+               Class enumClass = eSystem_FindClass(privateModule, "enum");
+               if(enumClass)
+               {
+                  NamedLink64 value;
+                  EnumClassData e = ACCESS_CLASSDATA(c, enumClass);
+                  for(value = e.values.first; value; value = value.next)
+                  {
+                     if(!strcmp(value.name, id.string))
+                        break;
+                  }
+                  if(value)
+                  {
+                     const String dts = c.dataTypeString;
+                     FreeExpContents(exp);
+                     exp.type = constantExp;
+                     exp.constant = (dts && (!strcmp(dts, "int") || !strcmp(dts, "int64") || !strcmp(dts, "short") || !strcmp(dts, "char"))) ? PrintInt64(value.data) : PrintUInt64(value.data);
+                  }
+               }
+            }
+         }
+         break;
+      }
       case instanceExp:
       {
          ComputeInstantiation(exp);
@@ -5146,7 +5464,46 @@ void ComputeExpression(Expression exp)
 
          // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
          if(exp.op.exp2)
-            ComputeExpression(exp.op.exp2);
+         {
+            Expression e = exp.op.exp2;
+
+            while((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list)
+            {
+               if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
+               {
+                  if(e.type == extensionCompoundExp)
+                     e = ((Statement)e.compound.compound.statements->last).expressions->last;
+                  else
+                     e = e.list->last;
+               }
+            }
+            if(exp.op.op == TokenType::sizeOf && e && e.expType)
+            {
+               if(e.type == stringExp && e.string)
+               {
+                  char * string = e.string;
+                  int len = strlen(string);
+                  char * tmp = new char[len-2+1];
+                  len = UnescapeString(tmp, string + 1, len - 2);
+                  delete tmp;
+                  FreeExpContents(exp);
+                  exp.type = constantExp;
+                  exp.constant = PrintUInt(len + 1);
+               }
+               else
+               {
+                  Type type = e.expType;
+                  type.refCount++;
+                  FreeExpContents(exp);
+                  exp.type = constantExp;
+                  exp.constant = PrintUInt(ComputeTypeSize(type));
+                  FreeType(type);
+               }
+               break;
+            }
+            else
+               ComputeExpression(exp.op.exp2);
+         }
          if(exp.op.exp1)
          {
             ComputeExpression(exp.op.exp1);
@@ -5366,11 +5723,23 @@ void ComputeExpression(Expression exp)
             if(!n)
             {
                OldList * list = exp.list;
+               Expression prev = exp.prev;
+               Expression next = exp.next;
+
+               // For operations which set the exp type on brackets exp after the inner exp was processed...
+               if(exp.expType && exp.expType.kind == classType && (!e.expType || e.expType.kind != classType))
+               {
+                  FreeType(e.expType);
+                  e.expType = exp.expType;
+                  e.expType.refCount++;
+               }
                ComputeExpression(e);
                //FreeExpContents(exp);
                FreeType(exp.expType);
                FreeType(exp.destType);
                *exp = *e;
+               exp.prev = prev;
+               exp.next = next;
                delete e;
                delete list;
             }
@@ -5518,7 +5887,7 @@ void ComputeExpression(Expression exp)
                                     void (*Set)(void *, void *) = (void *)prop.Set;
                                     exp.instance = Instantiation { };
                                     exp.instance.data = new0 byte[_class.structSize];
-                                    exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                    exp.instance._class = MkSpecifierName(_class.fullName);
                                     exp.instance.loc = exp.loc;
                                     exp.type = instanceExp;
                                     Set(exp.instance.data, value.instance.data);
@@ -5533,7 +5902,7 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
 
@@ -5568,7 +5937,7 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
 
@@ -5586,7 +5955,7 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
 
@@ -5596,6 +5965,23 @@ void ComputeExpression(Expression exp)
                                  PopulateInstance(exp.instance);
                                  break;
                               }
+                              case floatType:
+                              {
+                                 float floatValue;
+                                 void (*Set)(void *, float) = (void *)prop.Set;
+
+                                 exp.instance = Instantiation { };
+                                 exp.instance.data = new0 byte[_class.structSize];
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
+                                 exp.instance.loc = exp.loc;
+                                 exp.type = instanceExp;
+
+                                 GetFloat(value, &floatValue);
+
+                                 Set(exp.instance.data, floatValue);
+                                 PopulateInstance(exp.instance);
+                                 break;
+                              }
                               case doubleType:
                               {
                                  double doubleValue;
@@ -5603,7 +5989,7 @@ void ComputeExpression(Expression exp)
 
                                  exp.instance = Instantiation { };
                                  exp.instance.data = new0 byte[_class.structSize];
-                                 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                 exp.instance._class = MkSpecifierName(_class.fullName);
                                  exp.instance.loc = exp.loc;
                                  exp.type = instanceExp;
 
@@ -5663,7 +6049,7 @@ void ComputeExpression(Expression exp)
 
                                     exp.instance = Instantiation { };
                                     exp.instance.data = new0 byte[_class.structSize];
-                                    exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                    exp.instance._class = MkSpecifierName(_class.fullName);
                                     exp.instance.loc = exp.loc;
                                     //exp.instance.fullSet = true;
                                     exp.type = instanceExp;
@@ -5683,7 +6069,7 @@ void ComputeExpression(Expression exp)
                         }
                         else if(_class.type == structClass)
                         {
-                           char * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
+                           byte * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
                            switch(type.kind)
                            {
                               case classType:
@@ -5695,7 +6081,7 @@ void ComputeExpression(Expression exp)
 
                                     exp.instance = Instantiation { };
                                     exp.instance.data = new0 byte[_class.structSize];
-                                    exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+                                    exp.instance._class = MkSpecifierName(_class.fullName);
                                     exp.instance.loc = exp.loc;
                                     //exp.instance.fullSet = true;
                                     exp.type = instanceExp;
@@ -5773,9 +6159,8 @@ void ComputeExpression(Expression exp)
                char className[1024];
                strcpy(className, "__ecereClass_");
                FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
 
-               DeclareClass(classSym, className);
+               DeclareClass(curExternal, classSym, className);
 
                FreeExpContents(exp);
                exp.type = pointerExp;
@@ -5819,127 +6204,155 @@ void ComputeExpression(Expression exp)
                case charType:
                   if(type.isSigned)
                   {
-                     char value;
-                     GetChar(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintChar(value);
-                     exp.type = constantExp;
+                     char value = 0;
+                     if(GetChar(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintChar(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     unsigned char value;
-                     GetUChar(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUChar(value);
-                     exp.type = constantExp;
+                     unsigned char value = 0;
+                     if(GetUChar(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUChar(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case shortType:
                   if(type.isSigned)
                   {
-                     short value;
-                     GetShort(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintShort(value);
-                     exp.type = constantExp;
+                     short value = 0;
+                     if(GetShort(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintShort(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     unsigned short value;
-                     GetUShort(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUShort(value);
-                     exp.type = constantExp;
+                     unsigned short value = 0;
+                     if(GetUShort(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUShort(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case intType:
                   if(type.isSigned)
                   {
-                     int value;
-                     GetInt(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt(value);
-                     exp.type = constantExp;
+                     int value = 0;
+                     if(GetInt(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     unsigned int value;
-                     GetUInt(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt(value);
-                     exp.type = constantExp;
+                     unsigned int value = 0;
+                     if(GetUInt(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case int64Type:
                   if(type.isSigned)
                   {
-                     int64 value;
-                     GetInt64(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt64(value);
-                     exp.type = constantExp;
+                     int64 value = 0;
+                     if(GetInt64(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt64(value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     uint64 value;
-                     GetUInt64(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt64(value);
-                     exp.type = constantExp;
+                     uint64 value = 0;
+                     if(GetUInt64(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt64(value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case intPtrType:
                   if(type.isSigned)
                   {
-                     intptr value;
-                     GetIntPtr(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt64((int64)value);
-                     exp.type = constantExp;
+                     intptr value = 0;
+                     if(GetIntPtr(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt64((int64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     uintptr value;
-                     GetUIntPtr(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt64((uint64)value);
-                     exp.type = constantExp;
+                     uintptr value = 0;
+                     if(GetUIntPtr(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt64((uint64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case intSizeType:
                   if(type.isSigned)
                   {
-                     intsize value;
-                     GetIntSize(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintInt64((int64)value);
-                     exp.type = constantExp;
+                     intsize value = 0;
+                     if(GetIntSize(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintInt64((int64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   else
                   {
-                     uintsize value;
-                     GetUIntSize(e, &value);
-                     FreeExpContents(exp);
-                     exp.constant = PrintUInt64((uint64)value);
-                     exp.type = constantExp;
+                     uintsize value = 0;
+                     if(GetUIntSize(e, &value))
+                     {
+                        FreeExpContents(exp);
+                        exp.constant = PrintUInt64((uint64)value);
+                        exp.type = constantExp;
+                     }
                   }
                   break;
                case floatType:
                {
-                  float value;
-                  GetFloat(e, &value);
-                  FreeExpContents(exp);
-                  exp.constant = PrintFloat(value);
-                  exp.type = constantExp;
+                  float value = 0;
+                  if(GetFloat(e, &value))
+                  {
+                     FreeExpContents(exp);
+                     exp.constant = PrintFloat(value);
+                     exp.type = constantExp;
+                  }
                   break;
                }
                case doubleType:
                {
-                  double value;
-                  GetDouble(e, &value);
-                  FreeExpContents(exp);
-                  exp.constant = PrintDouble(value);
-                  exp.type = constantExp;
+                  double value = 0;
+                  if(GetDouble(e, &value))
+                  {
+                     FreeExpContents(exp);
+                     exp.constant = PrintDouble(value);
+                     exp.type = constantExp;
+                  }
                   break;
                }
             }
@@ -5976,7 +6389,7 @@ void ComputeExpression(Expression exp)
    }
 }
 
-static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
+static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla, bool warnConst)
 {
    bool result = true;
    if(destType)
@@ -5987,7 +6400,7 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
       if(destType.kind == voidType)
          return false;
 
-      if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla))
+      if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla, warnConst))
          result = false;
       if(converts.count)
       {
@@ -6002,6 +6415,8 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
 
                // TODO: Check this...
                *newExp = *exp;
+               newExp.prev = null;
+               newExp.next = null;
                newExp.destType = null;
 
                if(convert.isGet)
@@ -6076,13 +6491,15 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
                if(convert.isGet)
                {
                   exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
-                  exp.needCast = true;
+                  if(exp.destType.casted)
+                     exp.needCast = true;
                   if(exp.expType) exp.expType.refCount++;
                }
                else
                {
                   exp.expType = convert.resultType ? convert.resultType : MkClassType(convert.convert._class.fullName);
-                  exp.needCast = true;
+                  if(exp.destType.casted)
+                     exp.needCast = true;
                   if(convert.resultType)
                      convert.resultType.refCount++;
                }
@@ -6096,7 +6513,7 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
 
       if(!result && exp.expType && converts.count)      // TO TEST: Added converts.count here to avoid a double warning with function type
       {
-         result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false);
+         result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false, warnConst);
       }
       if(!result && exp.expType && exp.destType)
       {
@@ -6113,18 +6530,35 @@ static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
 
 void CheckTemplateTypes(Expression exp)
 {
-   if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
+   /*
+   bool et = exp.expType ? exp.expType.passAsTemplate : false;
+   bool dt = exp.destType ? exp.destType.passAsTemplate : false;
+   */
+   Expression nbExp = GetNonBracketsExp(exp);
+   if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate &&
+      (nbExp == exp || nbExp.type != castExp))
    {
       Expression newExp { };
-      Statement compound;
       Context context;
+      TypeKind kind = exp.expType.kind;
       *newExp = *exp;
       if(exp.destType) exp.destType.refCount++;
       if(exp.expType)  exp.expType.refCount++;
       newExp.prev = null;
       newExp.next = null;
 
-      switch(exp.expType.kind)
+      if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered)
+      {
+         Class c = exp.expType._class.registered;
+         if(c.type == bitClass || c.type == enumClass || c.type == unitClass)
+         {
+            if(!c.dataType)
+               c.dataType = ProcessTypeString(c.dataTypeString, false);
+            kind = c.dataType.kind;
+         }
+      }
+
+      switch(kind)
       {
          case doubleType:
             if(exp.destType.classObjectType)
@@ -6156,22 +6590,37 @@ void CheckTemplateTypes(Expression exp)
          default:
             exp.type = castExp;
             exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
-            exp.cast.exp = MkExpBrackets(MkListOne(newExp));
+            if((exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass) || exp.expType.isPointerType)
+               exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), MkExpBrackets(MkListOne(newExp)));
+            else
+               exp.cast.exp = MkExpBrackets(MkListOne(newExp));
+            exp.needCast = true;
             break;
       }
    }
    else if(exp.expType && exp.expType.passAsTemplate && exp.destType && exp.usage.usageGet && exp.destType.kind != templateType && !exp.destType.passAsTemplate)
    {
       Expression newExp { };
-      Statement compound;
       Context context;
+      TypeKind kind = exp.expType.kind;
       *newExp = *exp;
       if(exp.destType) exp.destType.refCount++;
       if(exp.expType)  exp.expType.refCount++;
       newExp.prev = null;
       newExp.next = null;
 
-      switch(exp.expType.kind)
+      if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered)
+      {
+         Class c = exp.expType._class.registered;
+         if(c.type == bitClass || c.type == enumClass || c.type == unitClass)
+         {
+            if(!c.dataType)
+               c.dataType = ProcessTypeString(c.dataTypeString, false);
+            kind = c.dataType.kind;
+         }
+      }
+
+      switch(kind)
       {
          case doubleType:
             if(exp.destType.classObjectType)
@@ -6205,6 +6654,8 @@ void CheckTemplateTypes(Expression exp)
             if(exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass)
             {
                exp.type = bracketsExp;
+
+               newExp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), newExp);
                exp.list = MkListOne(MkExpOp(null, '*', MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)),
                   MkDeclaratorPointer(MkPointer(null, null), null)), newExp)));
                ProcessExpressionType(exp.list->first);
@@ -6213,8 +6664,18 @@ void CheckTemplateTypes(Expression exp)
             else
             {
                exp.type = bracketsExp;
+               if(exp.expType.isPointerType)
+               {
+                  exp.needTemplateCast = 2;
+                  newExp.needCast = true;
+                  newExp.needTemplateCast = 2;
+                  newExp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), newExp);
+               }
+
                exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)), null), newExp));
+               exp.needTemplateCast = 2;
                newExp.needCast = true;
+               newExp.needTemplateCast = 2;
                ProcessExpressionType(exp.list->first);
                break;
             }
@@ -6232,15 +6693,16 @@ void CheckTemplateTypes(Expression exp)
                   break;
                }
             }
-            if(newExp.type == memberExp && newExp.member.memberType == dataMember)
+            /*if(newExp.type == memberExp && newExp.member.memberType == dataMember)
             {
+               // When was this required?    Removed to address using templated values to pass to printf()
                exp.type = opExp;
                exp.op.op = '*';
                exp.op.exp1 = null;
                exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
                   MkExpBrackets(MkListOne(MkExpOp(null, '&', newExp))));
             }
-            else
+            else*/
             {
                char typeString[1024];
                Declarator decl;
@@ -6254,6 +6716,8 @@ void CheckTemplateTypes(Expression exp)
                exp.cast.typeName = MkTypeName(specs, decl);
                exp.cast.exp = MkExpBrackets(MkListOne(newExp));
                exp.cast.exp.needCast = true;
+               exp.needTemplateCast = 2;
+               newExp.needTemplateCast = 2;
             }
             break;
          }
@@ -6265,7 +6729,7 @@ void CheckTemplateTypes(Expression exp)
 //    - Tree of all symbols within (stored without namespace)
 //    - Tree of sub-namespaces
 
-static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
+static Symbol ScanWithNameSpace(BinaryTree tree, const char * nameSpace, const char * name)
 {
    int nsLen = strlen(nameSpace);
    Symbol symbol;
@@ -6295,11 +6759,11 @@ static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
    return null;
 }
 
-static Symbol FindWithNameSpace(BinaryTree tree, char * name)
+static Symbol FindWithNameSpace(BinaryTree tree, const char * name)
 {
    int c;
    char nameSpace[1024];
-   char * namePart;
+   const char * namePart;
    bool gotColon = false;
 
    nameSpace[0] = '\0';
@@ -6342,9 +6806,7 @@ static Symbol FindWithNameSpace(BinaryTree tree, char * name)
    return null;
 }
 
-static void ProcessDeclaration(Declaration decl);
-
-/*static */Symbol FindSymbol(char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
+/*static */Symbol FindSymbol(const char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
 {
 #ifdef _DEBUG
    //Time startTime = GetTime();
@@ -6352,6 +6814,7 @@ static void ProcessDeclaration(Declaration decl);
    // Optimize this later? Do this before/less?
    Context ctx;
    Symbol symbol = null;
+
    // First, check if the identifier is declared inside the function
    //for(ctx = curContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
 
@@ -6377,34 +6840,8 @@ static void ProcessDeclaration(Declaration decl);
 
       if(symbol || ctx == endContext) break;
    }
-   if(inCompiler && curExternal && symbol && ctx == globalContext && curExternal.symbol && symbol.id > curExternal.symbol.idCode && symbol.pointerExternal)
-   {
-      if(symbol.pointerExternal.type == functionExternal)
-      {
-         FunctionDefinition function = symbol.pointerExternal.function;
-
-         // Modified this recently...
-         Context tmpContext = curContext;
-         curContext = null;
-         symbol.pointerExternal = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
-         curContext = tmpContext;
-
-         symbol.pointerExternal.symbol = symbol;
-
-         // TESTING THIS:
-         DeclareType(symbol.type, true, true);
-
-         ast->Insert(curExternal.prev, symbol.pointerExternal);
-
-         symbol.id = curExternal.symbol.idCode;
-
-      }
-      else if(symbol.pointerExternal.type == declarationExternal && curExternal.symbol.idCode < symbol.pointerExternal.symbol.id) // Added id comparison because Global Function prototypes were broken
-      {
-         ast->Move(symbol.pointerExternal, curExternal.prev);
-         symbol.id = curExternal.symbol.idCode;
-      }
-   }
+   if(inCompiler && symbol && ctx == globalContext && symbol.pointerExternal && curExternal && symbol.pointerExternal != curExternal)
+      curExternal.CreateUniqueEdge(symbol.pointerExternal, symbol.pointerExternal.type == functionExternal);
 #ifdef _DEBUG
    //findSymbolTotalTime += GetTime() - startTime;
 #endif
@@ -6465,11 +6902,12 @@ static void PrintTypeSpecs(Type type, char * string, bool fullName, bool printCo
          case classType:
          {
             Symbol c = type._class;
+            bool isObjectBaseClass = !c || !c.string || !strcmp(c.string, "class");
             // TODO: typed_object does not fully qualify the type, as it may have taken up an actual class (Stored in _class) from overriding
             //       look into merging with thisclass ?
-            if(type.classObjectType == typedObject)
+            if(type.classObjectType == typedObject && isObjectBaseClass)
                strcat(string, "typed_object");
-            else if(type.classObjectType == anyObject)
+            else if(type.classObjectType == anyObject && isObjectBaseClass)
                strcat(string, "any_object");
             else
             {
@@ -6584,7 +7022,6 @@ static void PrePrintType(Type type, char * string, bool fullName, Type parentTyp
 {
    if(type.kind == arrayType || type.kind == pointerType || type.kind == functionType || type.kind == methodType)
    {
-      Type attrType = null;
       if((type.kind == functionType || type.kind == methodType) && (!parentType || parentType.kind != pointerType))
          PrintAttribs(type, string);
       if(printConst && type.constant && (type.kind == functionType || type.kind == methodType))
@@ -6756,7 +7193,7 @@ static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassChe
 
    if(_class && _class.type == enumClass)
    {
-      NamedLink value = null;
+      NamedLink64 value = null;
       Class enumClass = eSystem_FindClass(privateModule, "enum");
       if(enumClass)
       {
@@ -6771,17 +7208,19 @@ static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassChe
             }
             if(value)
             {
-               char constant[256];
-
-               FreeExpContents(exp);
-
-               exp.type = constantExp;
                exp.isConstant = true;
-               if(!strcmp(baseClass.dataTypeString, "int"))
-                  sprintf(constant, "%d",(int)value.data);
-               else
-                  sprintf(constant, "0x%X",(int)value.data);
-               exp.constant = CopyString(constant);
+               if(inCompiler || inPreCompiler || inDebugger)
+               {
+                  char constant[256];
+                  FreeExpContents(exp);
+
+                  exp.type = constantExp;
+                  if(!strcmp(baseClass.dataTypeString, "int") || !strcmp(baseClass.dataTypeString, "int64") || !strcmp(baseClass.dataTypeString, "char") || !strcmp(baseClass.dataTypeString, "short"))
+                     sprintf(constant, FORMAT64D, value.data);
+                  else
+                     sprintf(constant, FORMAT64HEX, value.data);
+                  exp.constant = CopyString(constant);
+               }
                //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
                exp.expType = MkClassType(baseClass.fullName);
                break;
@@ -6837,7 +7276,7 @@ static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassChe
          {
             //char constant[256];
             exp.type = stringExp;
-            exp.constant = QMkString((char *)classProp.Get(_class));
+            exp.constant = QMkString((char *)(uintptr)classProp.Get(_class));
          }
          else
          {
@@ -6995,7 +7434,7 @@ void ApplyAnyObjectLogic(Expression e)
                   {
                      char size[100];
                      ComputeTypeSize(e.expType);
-                     sprintf(size, "%d", e.expType.size);
+                     sprintf(size, "%d", e.expType.size);   // Potential 32/64 Bootstrap issue
                      newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
                         MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
                            MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
@@ -7006,7 +7445,7 @@ void ApplyAnyObjectLogic(Expression e)
                }
                else if(!e.byReference || (_class && _class.type == noHeadClass))     // TESTING THIS HERE...
                {
-                  Expression checkedExp, newExp;
+                  Expression checkedExp; //, newExp;
 
                   {
                      // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
@@ -7099,9 +7538,11 @@ void ApplyAnyObjectLogic(Expression e)
                   {
                      Expression operand { };
                      operand = *checkedExp;
-                     checkedExp.destType = null;
-                     checkedExp.expType = null;
                      checkedExp.Clear();
+                     checkedExp.destType = ProcessTypeString("void *", false);
+                     checkedExp.expType = checkedExp.destType;
+                     checkedExp.destType.refCount++;
+
                      checkedExp.type = opExp;
                      checkedExp.op.op = '&';
                      checkedExp.op.exp1 = null;
@@ -7216,31 +7657,132 @@ void ApplyAnyObjectLogic(Expression e)
              (type.kind != pointerType && type.kind != intPtrType && type.kind != arrayType && type.kind != classType) ||
              (!destType.byReference && byReference && (destType.kind != pointerType || type.kind != pointerType)))
          {
+            bool passAsTemplate = thisExp.destType.passAsTemplate;
+            Type t;
+
+            destType.refCount++;
+
             e.type = opExp;
             e.op.op = '*';
             e.op.exp1 = null;
             e.op.exp2 = MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), thisExp);
 
+            t = { };
+            CopyTypeInto(t, thisExp.destType);
+            t.passAsTemplate = false;
+            FreeType(thisExp.destType);
+            thisExp.destType = t;
+
+            t = { };
+            CopyTypeInto(t, destType);
+            t.passAsTemplate = passAsTemplate;
+            FreeType(destType);
+            destType = t;
+            destType.refCount = 0;
+
             e.expType = { };
             CopyTypeInto(e.expType, type);
+            if(type.passAsTemplate)
+            {
+               e.expType.classObjectType = none;
+               e.expType.passAsTemplate = false;
+            }
             e.expType.byReference = false;
             e.expType.refCount = 1;
          }
-         else
+         else
+         {
+            e.type = castExp;
+            e.cast.typeName = MkTypeName(specs, decl);
+            e.cast.exp = thisExp;
+            e.byReference = true;
+            e.expType = type;
+            type.refCount++;
+         }
+
+         if(e.destType)
+            FreeType(e.destType);
+
+         e.destType = destType;
+         destType.refCount++;
+      }
+   }
+}
+
+void ApplyLocation(Expression exp, Location loc)
+{
+   exp.loc = loc;
+   switch(exp.type)
+   {
+      case opExp:
+         if(exp.op.exp1) ApplyLocation(exp.op.exp1, loc);
+         if(exp.op.exp2) ApplyLocation(exp.op.exp2, loc);
+         break;
+      case bracketsExp:
+         if(exp.list)
+         {
+            Expression e;
+            for(e = exp.list->first; e; e = e.next)
+               ApplyLocation(e, loc);
+         }
+         break;
+      case indexExp:
+         if(exp.index.index)
+         {
+            Expression e;
+            for(e = exp.index.index->first; e; e = e.next)
+               ApplyLocation(e, loc);
+         }
+         if(exp.index.exp)
+            ApplyLocation(exp.index.exp, loc);
+         break;
+      case callExp:
+         if(exp.call.arguments)
          {
-            e.type = castExp;
-            e.cast.typeName = MkTypeName(specs, decl);
-            e.cast.exp = thisExp;
-            e.byReference = true;
-            e.expType = type;
-            type.refCount++;
+            Expression arg;
+            for(arg = exp.call.arguments->first; arg; arg = arg.next)
+               ApplyLocation(arg, loc);
          }
-         e.destType = destType;
-         destType.refCount++;
-      }
+         if(exp.call.exp)
+            ApplyLocation(exp.call.exp, loc);
+         break;
+      case memberExp:
+      case pointerExp:
+         if(exp.member.exp)
+            ApplyLocation(exp.member.exp, loc);
+         break;
+      case castExp:
+         if(exp.cast.exp)
+            ApplyLocation(exp.cast.exp, loc);
+         break;
+      case conditionExp:
+         if(exp.cond.exp)
+         {
+            Expression e;
+            for(e = exp.cond.exp->first; e; e = e.next)
+               ApplyLocation(e, loc);
+         }
+         if(exp.cond.cond)
+            ApplyLocation(exp.cond.cond, loc);
+         if(exp.cond.elseExp)
+            ApplyLocation(exp.cond.elseExp, loc);
+         break;
+      case vaArgExp:
+         if(exp.vaArg.exp)
+            ApplyLocation(exp.vaArg.exp, loc);
+         break;
+      default:
+         break;
    }
 }
 
+bool RelatedUnits(Class c1, Class c2)
+{
+   if(c1.base.type == unitClass) c1 = c1.base;
+   if(c2.base.type == unitClass) c2 = c2.base;
+   return c1 == c2;
+}
+
 void ProcessExpressionType(Expression exp)
 {
    bool unresolved = false;
@@ -7263,7 +7805,7 @@ void ProcessExpressionType(Expression exp)
       case identifierExp:
       {
          Identifier id = exp.identifier;
-         if(!id) return;
+         if(!id || !topContext) return;
 
          // DOING THIS LATER NOW...
          if(id._class && id._class.name)
@@ -7280,7 +7822,13 @@ void ProcessExpressionType(Expression exp)
             exp.expType = ProcessTypeString("Module", true);
             break;
          }
-         else */if(strstr(id.string, "__ecereClass") == id.string)
+         else */
+         if(!strcmp(id.string, "__runtimePlatform"))
+         {
+            exp.expType = ProcessTypeString("ecere::com::Platform", true);
+            break;
+         }
+         else if(strstr(id.string, "__ecereClass") == id.string)
          {
             exp.expType = ProcessTypeString("ecere::com::Class", true);
             break;
@@ -7300,11 +7848,17 @@ void ProcessExpressionType(Expression exp)
          }
          else
          {
-            Symbol symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
+            Symbol symbol = null;
+            bool findInGlobal = false;
+            if(!topContext.parent && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered && exp.destType._class.registered.type == enumClass)
+               findInGlobal = true;  // In global context, look at enum values first
+            else
+               symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
+
             // Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
             if(!symbol/* && exp.destType*/)
             {
-               if(exp.destType && CheckExpressionType(exp, exp.destType, false))
+               if(exp.destType && CheckExpressionType(exp, exp.destType, false, false))
                   break;
                else
                {
@@ -7326,6 +7880,8 @@ void ProcessExpressionType(Expression exp)
                   symbol = FindSymbol(id.string, topContext.parent, globalContext, false, id._class && id._class.name == null);
                }
             }
+            if(findInGlobal)
+               symbol = FindSymbol(id.string, curContext, topContext, false, id._class && id._class.name == null);
 
             // If we manage to resolve this symbol
             if(symbol)
@@ -7350,7 +7906,10 @@ void ProcessExpressionType(Expression exp)
                exp.expType = type;
                if(type)
                   type.refCount++;
-               if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
+
+                                                // Commented this out, it was making non-constant enum parameters seen as constant
+                                                // enums should have been resolved by ResolveIdWithClass, changed to constantExp and marked as constant
+               if(type && (type.kind == enumType /*|| (_class && _class.type == enumClass)*/))
                   // Add missing cases here... enum Classes...
                   exp.isConstant = true;
 
@@ -7418,7 +7977,9 @@ void ProcessExpressionType(Expression exp)
                   if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
                   {
                      Location backupYylloc = yylloc;
+                     File backInput = fileInput;
                      definedExpStack[definedExpStackPos++] = definedExp;
+
                      fileInput = TempFile { };
                      fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
                      fileInput.Seek(0, start);
@@ -7428,6 +7989,8 @@ void ProcessExpressionType(Expression exp)
                      resetScanner();
                      expression_yyparse();
                      delete fileInput;
+                     if(backInput)
+                        fileInput = backInput;
 
                      yylloc = backupYylloc;
 
@@ -7436,7 +7999,7 @@ void ProcessExpressionType(Expression exp)
                         FreeIdentifier(id);
                         exp.type = bracketsExp;
                         exp.list = MkListOne(parsedExpression);
-                        parsedExpression.loc = yylloc;
+                        ApplyLocation(parsedExpression, yylloc);
                         ProcessExpressionType(exp);
                         definedExpStackPos--;
                         return;
@@ -7466,7 +8029,7 @@ void ProcessExpressionType(Expression exp)
                      data = FindGlobalData(id.string);
                   if(data)
                   {
-                     DeclareGlobalData(data);
+                     DeclareGlobalData(curExternal, data);
                      exp.expType = data.dataType;
                      if(data.dataType) data.dataType.refCount++;
 
@@ -7500,7 +8063,7 @@ void ProcessExpressionType(Expression exp)
                         if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
                            strcpy(name, "__ecereFunction_");
                         FullClassNameCat(name, id.string, false); // Why is this using FullClassNameCat ?
-                        if(DeclareFunction(function, name))
+                        if(DeclareFunction(curExternal, function, name))
                         {
                            delete id.string;
                            id.string = CopyString(name);
@@ -7522,7 +8085,7 @@ void ProcessExpressionType(Expression exp)
       }
       case instanceExp:
       {
-         Class _class;
+         // Class _class;
          // Symbol classSym;
 
          if(!exp.instance._class)
@@ -7537,6 +8100,7 @@ void ProcessExpressionType(Expression exp)
          //_class = classSym ? classSym.registered : null;
 
          ProcessInstantiationType(exp.instance);
+
          exp.isConstant = exp.instance.isConstant;
 
          /*
@@ -7623,9 +8187,11 @@ void ProcessExpressionType(Expression exp)
                else
                {
                   bool isSigned = constant[0] == '-';
-                  int64 i64 = strtoll(constant, null, 0);
-                  uint64 ui64 = strtoull(constant, null, 0);
-                  bool is64Bit = false;
+                  char * endP = null;
+                  int64 i64 = strtoll(constant, &endP, 0);
+                  uint64 ui64 = strtoull(constant, &endP, 0);
+                  bool is64Bit = endP && (!strcmp(endP, "LL") || !strcmp(endP, "ll") || !strcmp(endP, "LLU") || !strcmp(endP, "llu") || !strcmp(endP, "ull") || !strcmp(endP, "ULL"));
+                  bool forceUnsigned = endP && (!strcmp(endP, "U") || !strcmp(endP, "u") || !strcmp(endP, "LLU") || !strcmp(endP, "llu") || !strcmp(endP, "ull") || !strcmp(endP, "ULL"));
                   if(isSigned)
                   {
                      if(i64 < MININT)
@@ -7645,6 +8211,8 @@ void ProcessExpressionType(Expression exp)
                      else if(constant[0] != '0' || !constant[1])
                         isSigned = true;
                   }
+                  if(forceUnsigned)
+                     isSigned = false;
                   type.kind = is64Bit ? int64Type : intType;
                   type.isSigned = isSigned;
                }
@@ -7669,9 +8237,9 @@ void ProcessExpressionType(Expression exp)
             type = Type
             {
                refCount = 1;
-               kind = charType;
+               kind = exp.wideString ? shortType : charType;
                constant = true;
-               isSigned = true;
+               isSigned = exp.wideString ? false : true;
             }
          };
          break;
@@ -7685,7 +8253,7 @@ void ProcessExpressionType(Expression exp)
             kind = pointerType;
             type = ProcessType(exp._new.typeName.qualifiers, exp._new.typeName.declarator);
          };
-         DeclareType(exp.expType.type, false, false);
+         DeclareType(curExternal, exp.expType.type, true, false);
          break;
       case renewExp:
       case renew0Exp:
@@ -7697,7 +8265,7 @@ void ProcessExpressionType(Expression exp)
             kind = pointerType;
             type = ProcessType(exp._renew.typeName.qualifiers, exp._renew.typeName.declarator);
          };
-         DeclareType(exp.expType.type, false, false);
+         DeclareType(curExternal, exp.expType.type, true, false);
          break;
       case opExp:
       {
@@ -7706,6 +8274,9 @@ void ProcessExpressionType(Expression exp)
          bool useDestType = false, useSideType = false;
          Location oldyylloc = yylloc;
          bool useSideUnit = false;
+         Class destClass = (exp.destType && exp.destType.kind == classType && exp.destType._class) ? exp.destType._class.registered : null;
+         bool powerOp = false, relationOp = false;
+         Class c1 = null, c2 = null;
 
          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
          Type dummy
@@ -7752,25 +8323,41 @@ void ProcessExpressionType(Expression exp)
                // Gives boolean result
                boolResult = true;
                useSideType = true;
+               relationOp = true;
                break;
             case '+':
             case '-':
                useSideUnit = true;
+               useSideType = true;
+               useDestType = true;
+               break;
+
+            case LEFT_OP:
+            case RIGHT_OP:
+               // useSideType = true;
+               // useDestType = true;
+               break;
 
-               // Just added these... testing
             case '|':
-            case '&':
             case '^':
+               useSideType = true;
+               useDestType = true;
+               break;
 
-            // DANGER: Verify units
             case '/':
             case '%':
+               useSideType = true;
+               useDestType = true;
+               if(exp.op.op == '/') powerOp = true;
+               break;
+            case '&':
             case '*':
-
-               if(exp.op.op != '*' || exp.op.exp1)
+               if(exp.op.exp1)
                {
+                  // For & operator, useDestType nicely ensures the result will fit in a bool (TODO: Fix for generic enum)
                   useSideType = true;
                   useDestType = true;
+                  if(exp.op.op == '*') powerOp = true;
                }
                break;
 
@@ -7804,21 +8391,22 @@ void ProcessExpressionType(Expression exp)
          }
 
          //dummy.kind = TypeDummy;
-
          if(exp.op.exp1)
          {
-            if(exp.destType && exp.destType.kind == classType &&
-               exp.destType._class && exp.destType._class.registered && useDestType &&
+            // Added this check here to use the dest type only for units derived from the base unit
+            // So that untyped units will use the side unit as opposed to the untyped destination unit
+            // This fixes (#771) sin(Degrees { 5 } + 5) to be equivalent to sin(Degrees { 10 }), since sin expects a generic Angle
+            if(exp.op.exp2 && useSideUnit && useDestType && destClass && destClass.type == unitClass && destClass.base.type != unitClass)
+               useDestType = false;
 
-              ((exp.destType._class.registered.type == unitClass && useSideUnit) ||
-               exp.destType._class.registered.type == enumClass ||
-               exp.destType._class.registered.type == bitClass
-               ))
+            if(destClass && useDestType &&
+              ((destClass.type == unitClass && useSideUnit) || destClass.type == enumClass || destClass.type == bitClass))
 
               //(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
             {
                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                exp.op.exp1.destType = exp.destType;
+               exp.op.exp1.opDestType = true;
                if(exp.destType)
                   exp.destType.refCount++;
             }
@@ -7827,18 +8415,52 @@ void ProcessExpressionType(Expression exp)
                if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                exp.op.exp1.destType = dummy;
                dummy.refCount++;
+               if(powerOp)
+                  exp.op.exp1.opDestType = true;
+               if(relationOp)
+                  exp.op.exp1.usedInComparison = true;
+            }
+            if(exp.op.op == '+' || exp.op.op == '-')
+            {
+               if(exp.opDestType)
+                  exp.op.exp1.parentOpDestType = true;
+               if(exp.usedInComparison)
+                  exp.op.exp1.usedInComparison = true;
             }
 
             // TESTING THIS HERE...
             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
-            ProcessExpressionType(exp.op.exp1);
+               ProcessExpressionType(exp.op.exp1);
             if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
 
+            exp.op.exp1.opDestType = false;
+            exp.op.exp1.usedInComparison = false;
+
+            // Fix for unit and ++ / --
+            if(!exp.op.exp2 && (exp.op.op == INC_OP || exp.op.op == DEC_OP) && exp.op.exp1.expType && exp.op.exp1.expType.kind == classType &&
+               exp.op.exp1.expType._class && exp.op.exp1.expType._class.registered && exp.op.exp1.expType._class.registered.type == unitClass)
+            {
+               exp.op.exp2 = MkExpConstant("1");
+               exp.op.op = exp.op.op == INC_OP ? ADD_ASSIGN : SUB_ASSIGN;
+               assign = true;
+            }
+
             if(exp.op.exp1.destType == dummy)
             {
                FreeType(dummy);
                exp.op.exp1.destType = null;
             }
+
+            if(exp.op.exp2)
+            {
+               if(!assign && exp.op.exp1.expType && (exp.op.exp1.expType.kind == charType || exp.op.exp1.expType.kind == shortType))
+               {
+                  Type type { kind = intType, isSigned = true, refCount = 1, signedBeforePromotion = exp.op.exp1.expType.isSigned, bitMemberSize = exp.op.exp1.expType.bitMemberSize, promotedFrom = exp.op.exp1.expType.kind };
+                  FreeType(exp.op.exp1.expType);
+                  exp.op.exp1.expType = type;
+               }
+            }
+
             type1 = exp.op.exp1.expType;
          }
 
@@ -7857,6 +8479,8 @@ void ProcessExpressionType(Expression exp)
                else
                {
                   exp.op.exp2.destType = exp.destType;
+                  if(!exp.op.exp1 || (exp.op.op != '&' && exp.op.op != '^'))
+                     exp.op.exp2.opDestType = true;
                   if(exp.destType)
                      exp.destType.refCount++;
                }
@@ -7898,15 +8522,14 @@ void ProcessExpressionType(Expression exp)
                if(type1) type1.refCount++;
                exp.expType = type1;
             }
-            else if(exp.destType && exp.destType.kind == classType &&
-               exp.destType._class && exp.destType._class.registered &&
-
-                  ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) ||
-                  (exp.destType._class.registered.type == enumClass && useDestType))
-                  )
+            else if(destClass &&
+                  ((destClass.type == unitClass && useDestType && useSideUnit) ||
+                  (destClass.type == enumClass && useDestType)))
             {
                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                exp.op.exp2.destType = exp.destType;
+               if(exp.op.op != '&' && exp.op.op != '^')
+                  exp.op.exp2.opDestType = true;
                if(exp.destType)
                   exp.destType.refCount++;
             }
@@ -7915,6 +8538,10 @@ void ProcessExpressionType(Expression exp)
                if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                exp.op.exp2.destType = dummy;
                dummy.refCount++;
+               if(powerOp)
+                  exp.op.exp2.opDestType = true;
+               if(relationOp)
+                  exp.op.exp2.usedInComparison = true;
             }
 
             // TESTING THIS HERE... (DANGEROUS)
@@ -7926,9 +8553,45 @@ void ProcessExpressionType(Expression exp)
                type1.refCount++;
             }
             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
+            // Cannot lose the cast on a sizeof
+            if(exp.op.op == SIZEOF)
+            {
+               Expression e = exp.op.exp2;
+               while((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list)
+               {
+                  if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
+                  {
+                     if(e.type == extensionCompoundExp)
+                        e = ((Statement)e.compound.compound.statements->last).expressions->last;
+                     else
+                        e = e.list->last;
+                  }
+               }
+               if(e.type == castExp && e.cast.exp)
+                  e.cast.exp.needCast = true;
+            }
+            if(exp.op.op == '+' || exp.op.op == '-')
+            {
+               if(exp.opDestType)
+                  exp.op.exp2.parentOpDestType = true;
+               if(exp.usedInComparison)
+                  exp.op.exp2.usedInComparison = true;
+            }
             ProcessExpressionType(exp.op.exp2);
+            exp.op.exp2.opDestType = false;
+            exp.op.exp2.usedInComparison = false;
             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
 
+            if(!assign && (exp.op.exp1 || exp.op.op == '~'))
+            {
+               if(exp.op.exp2.expType && (exp.op.exp2.expType.kind == charType || exp.op.exp2.expType.kind == shortType))
+               {
+                  Type type { kind = intType, isSigned = true, refCount = 1, signedBeforePromotion = exp.op.exp2.expType.isSigned, bitMemberSize = exp.op.exp2.expType.bitMemberSize, promotedFrom = exp.op.exp2.expType.kind };
+                  FreeType(exp.op.exp2.expType);
+                  exp.op.exp2.expType = type;
+               }
+            }
+
             if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
             {
                if(exp.op.exp2.expType.kind == intSizeType || exp.op.exp2.expType.kind == intPtrType || exp.op.exp2.expType.kind == int64Type || exp.op.exp2.expType.kind == intType || exp.op.exp2.expType.kind == shortType || exp.op.exp2.expType.kind == charType)
@@ -7990,6 +8653,24 @@ void ProcessExpressionType(Expression exp)
                if(type2) type2.refCount++;
             }
          }
+         c1 = type1 && type1.kind == classType && type1._class ? type1._class.registered : null;
+         c2 = type2 && type2.kind == classType && type2._class ? type2._class.registered : null;
+
+         if(relationOp &&
+            ( (exp.op.exp1 && exp.op.exp1.ambiguousUnits && (!c2 || c2.type != unitClass)) ||
+               (exp.op.exp2 && exp.op.exp2.ambiguousUnits && (!c1 || c1.type != unitClass))) )
+            Compiler_Warning($"ambiguous units in relational operation\n");
+
+         if(!relationOp &&
+            ((exp.op.exp1 && exp.op.exp1.ambiguousUnits) ||
+             (exp.op.exp2 && exp.op.exp2.ambiguousUnits)) &&
+             (!powerOp || !c1 || c1.type != unitClass || !c2 || c2.type != unitClass || !RelatedUnits(c1, c2)))
+         {
+            if(exp.opDestType || exp.usedInComparison)
+               exp.ambiguousUnits = true;
+            else
+               Compiler_Warning($"ambiguous units\n");
+         }
 
          dummy.kind = voidType;
 
@@ -7998,7 +8679,7 @@ void ProcessExpressionType(Expression exp)
             exp.expType = Type
             {
                refCount = 1;
-               kind = intType;
+               kind = intSizeType;
             };
             exp.isConstant = true;
          }
@@ -8011,8 +8692,21 @@ void ProcessExpressionType(Expression exp)
          }
          else if(exp.op.op == '&' && !exp.op.exp1)
             exp.expType = Reference(type2);
+         else if(exp.op.op == LEFT_OP || exp.op.op == RIGHT_OP)
+         {
+            if(exp.op.exp1.expType)
+            {
+               exp.expType = exp.op.exp1.expType;
+               exp.expType.refCount++;
+            }
+         }
          else if(!assign)
          {
+            if(c1 && !c1.dataType)
+               c1.dataType = ProcessTypeString(c1.dataTypeString, false);
+            if(c2 && !c2.dataType)
+               c2.dataType = ProcessTypeString(c2.dataTypeString, false);
+
             if(boolOps)
             {
                if(exp.op.exp1)
@@ -8023,7 +8717,7 @@ void ProcessExpressionType(Expression exp)
                   if(!exp.op.exp1.expType)
                      ProcessExpressionType(exp.op.exp1);
                   else
-                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                   FreeType(exp.op.exp1.expType);
                   exp.op.exp1.expType = MkClassType("bool");
                   exp.op.exp1.expType.truth = true;
@@ -8036,17 +8730,39 @@ void ProcessExpressionType(Expression exp)
                   if(!exp.op.exp2.expType)
                      ProcessExpressionType(exp.op.exp2);
                   else
-                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                   FreeType(exp.op.exp2.expType);
                   exp.op.exp2.expType = MkClassType("bool");
                   exp.op.exp2.expType.truth = true;
                }
             }
+            else if(powerOp && exp.op.exp1 && exp.op.exp2 && ((c1 && c1.type == unitClass) || (c2 && c2.type == unitClass)))
+            {
+               // * or / with at least one unit operand
+               if(c1 && c1.type == unitClass && c2 && c2.type == unitClass)
+               {
+                  // This is where we'd handle unit powers e.g. square meters or meters/seconds
+                  // For now using base types
+                  if(c1.dataType.kind == doubleType)        exp.expType = c1.dataType;
+                  else if(c2.dataType.kind == doubleType)   exp.expType = c2.dataType;
+                  else if(c1.dataType.kind == floatType)    exp.expType = c1.dataType;
+                  else if(c2.dataType.kind == floatType)    exp.expType = c2.dataType;
+                  else
+                     exp.expType = c1.dataType;
+               }
+               else if((c1 && c1.type == unitClass) || exp.op.op == '/')   // 1/units should not be typed with unit
+                  exp.expType = type1;
+               else
+                  exp.expType = type2;
+
+               if(exp.expType)
+                  exp.expType.refCount++;
+            }
             else if(exp.op.exp1 && exp.op.exp2 &&
                ((useSideType /*&&
                      (useSideUnit ||
-                        ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
-                         (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
+                        ((!c1 || c1.type != unitClass) &&
+                         (!c2 || c2.type != unitClass)))*/) ||
                   ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) &&
                   (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
             {
@@ -8054,19 +8770,39 @@ void ProcessExpressionType(Expression exp)
                   // If either both are class or both are not class
                   ((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String"))))
                {
-                  if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
-                  exp.op.exp2.destType = type1;
-                  type1.refCount++;
-                  if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
-                  exp.op.exp1.destType = type2;
-                  type2.refCount++;
+                  // Added this check for enum subtraction to result in an int type:
+                  if(exp.op.op == '-' && ((c1 && c1.type == enumClass) || (c2 && c2.type == enumClass)) )
+                  {
+                     Type intType = ProcessTypeString((c1 && c1.dataType.kind == int64Type) || (c2 && c2.dataType.kind == int64Type) ? "int64" : "int", false);
+
+                     if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+                     if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+                     exp.op.exp1.destType = intType;
+                     exp.op.exp2.destType = intType;
+                     intType.refCount++;
+                  }
+                  else
+                  {
+                     if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+                     exp.op.exp2.destType = type1;
+                     type1.refCount++;
+                     if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+                     exp.op.exp1.destType = type2;
+                     type2.refCount++;
+                  }
+
                   // Warning here for adding Radians + Degrees with no destination type
-                  if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) &&
-                     type1._class.registered && type1._class.registered.type == unitClass &&
-                     type2._class.registered && type2._class.registered.type == unitClass &&
-                     type1._class.registered != type2._class.registered)
-                     Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
-                        type1._class.string, type2._class.string, type1._class.string);
+                  if(!boolResult && !exp.opDestType && (!exp.destType || exp.destType.kind != classType) &&
+                     c1 && c1.type == unitClass &&
+                     c2 && c2.type == unitClass &&
+                     c1 != c2)
+                  {
+                     if(exp.usedInComparison || exp.parentOpDestType)
+                        exp.ambiguousUnits = true;
+                     else
+                        Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
+                           type1._class.string, type2._class.string, type1._class.string);
+                  }
 
                   if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
                   {
@@ -8085,23 +8821,13 @@ void ProcessExpressionType(Expression exp)
                         {
                            ProcessExpressionType(classExp);
 
-                           exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*',
-                              // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
-                              MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
-                                 // noHeadClass
-                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("5")),
-                                    OR_OP,
-                                 // normalClass
-                                 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("0"))))),
-                                    MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
-                                       MkPointer(null, null), null)))),
-                                       MkExpMember(classExp, MkIdentifier("typeSize"))))))));
+                           exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*', MkExpMember(classExp, MkIdentifier("typeSize")) )));
 
                            if(!exp.op.exp2.expType)
                            {
                               if(type2)
                                  FreeType(type2);
-                              type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
+                              type2 = exp.op.exp2.expType = ProcessTypeString("int", false); c2 = null;
                               type2.refCount++;
                            }
 
@@ -8139,7 +8865,7 @@ void ProcessExpressionType(Expression exp)
                         else if(exp.op.op == '-')
                         {
                            // Pointer Subtraction gives integer
-                           if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
+                           if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false, false))
                            {
                               exp.expType = Type
                               {
@@ -8163,22 +8889,7 @@ void ProcessExpressionType(Expression exp)
                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp1)))
                                              , exp.op.op,
                                              MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/',
-
-                                             //MkExpMember(classExp, MkIdentifier("typeSize"))
-
-                                             // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
-                                             MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
-                                                // noHeadClass
-                                                MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))),
-                                                   OR_OP,
-                                                // normalClass
-                                                MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))))),
-                                                   MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
-                                                      MkPointer(null, null), null)))),
-                                                      MkExpMember(classExp, MkIdentifier("typeSize")))))
-
-
-                                             ));
+                                             MkExpMember(classExp, MkIdentifier("typeSize"))));
 
                                     ProcessExpressionType(((Expression)exp.list->first).op.exp2);
                                     FreeType(dummy);
@@ -8192,14 +8903,14 @@ void ProcessExpressionType(Expression exp)
                      if(!success && exp.op.exp1.type == constantExp)
                      {
                         // If first expression is constant, try to match that first
-                        if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                        if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp1.destType;
                            if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
                            success = true;
                         }
-                        else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
+                        else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp2.destType;
@@ -8209,14 +8920,14 @@ void ProcessExpressionType(Expression exp)
                      }
                      else if(!success)
                      {
-                        if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
+                        if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp2.destType;
                            if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
                            success = true;
                         }
-                        else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                        else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                         {
                            if(exp.expType) FreeType(exp.expType);
                            exp.expType = exp.op.exp1.destType;
@@ -8249,25 +8960,25 @@ void ProcessExpressionType(Expression exp)
                   }
                }
                // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
-               else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
+               else if(!boolResult && !useSideUnit && c2 && c2.type == unitClass && type1 && type1.kind != classType)
                {
                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp1.destType = type2._class.registered.dataType;
                   if(type2._class.registered.dataType)
                      type2._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                   exp.expType = type2;
                   if(type2) type2.refCount++;
                }
-               else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
+               else if(!boolResult && !useSideUnit && c1 && c1.type == unitClass && type2 && type2.kind != classType)
                {
                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp2.destType = type1._class.registered.dataType;
                   if(type1._class.registered.dataType)
                      type1._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                   exp.expType = type1;
                   if(type1) type1.refCount++;
                }
@@ -8275,71 +8986,113 @@ void ProcessExpressionType(Expression exp)
                {
                   bool valid = false;
 
-                  if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
+                  if(!boolResult && useSideUnit && c1 && c1.type == unitClass && type2 && type2.kind != classType)
                   {
                      if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
 
-                     if(!type1._class.registered.dataType)
-                        type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
-                     exp.op.exp2.destType = type1._class.registered.dataType;
+                     exp.op.exp2.destType = c1.dataType;
                      exp.op.exp2.destType.refCount++;
 
-                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                     CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                      if(type2)
                         FreeType(type2);
                      type2 = exp.op.exp2.destType;
+                     c2 = type2 && type2.kind == classType && type2._class ? type2._class.registered : null;
                      if(type2) type2.refCount++;
 
                      exp.expType = type2;
                      type2.refCount++;
                   }
 
-                  if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
+                  if(!boolResult && useSideUnit && c2 && c2.type == unitClass && type1 && type1.kind != classType)
                   {
                      if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
 
-                     if(!type2._class.registered.dataType)
-                        type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
-                     exp.op.exp1.destType = type2._class.registered.dataType;
+                     exp.op.exp1.destType = c2.dataType;
                      exp.op.exp1.destType.refCount++;
 
-                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                     CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                      type1 = exp.op.exp1.destType;
+                     c1 = type1 && type1.kind == classType && type1._class ? type1._class.registered : null;
                      exp.expType = type1;
                      type1.refCount++;
                   }
 
                   // TESTING THIS NEW CODE
-                  if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
+                  if(!boolResult || exp.op.op == '>' || exp.op.op == '<' || exp.op.op == GE_OP || exp.op.op == LE_OP)
                   {
-                     if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
+                     bool op1IsEnum = c1 && c1.type == enumClass;
+                     bool op2IsEnum = c2 && c2.type == enumClass;
+                     if(exp.op.op == '*' || exp.op.op == '/' || exp.op.op == '-' || exp.op.op == '|' || exp.op.op == '^')
                      {
-                        if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
+                        // Convert the enum to an int instead for these operators
+                        if(op1IsEnum && exp.op.exp2.expType)
                         {
-                           if(exp.expType) FreeType(exp.expType);
-                           exp.expType = exp.op.exp1.expType;
-                           if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
-                           valid = true;
+                           if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp2.expType;
+                              if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                              valid = true;
+                           }
+                        }
+                        else if(op2IsEnum && exp.op.exp1.expType)
+                        {
+                           if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp1.expType;
+                              if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+                              valid = true;
+                           }
                         }
                      }
-
-                     else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
+                     else
                      {
-                        if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
+                        if(op1IsEnum && exp.op.exp2.expType)
                         {
-                           if(exp.expType) FreeType(exp.expType);
-                           exp.expType = exp.op.exp2.expType;
-                           if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
-                           valid = true;
+                           if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp1.expType;
+                              if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+                              valid = true;
+                           }
+                        }
+                        else if(op2IsEnum && exp.op.exp1.expType)
+                        {
+                           if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false, false))
+                           {
+                              if(exp.expType) FreeType(exp.expType);
+                              exp.expType = exp.op.exp2.expType;
+                              if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                              valid = true;
+                           }
                         }
                      }
                   }
 
                   if(!valid)
                   {
-                     if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
-                     exp.op.exp2.destType = type1;
-                     type1.refCount++;
+                     // Added this first part of the if here to handle  5 + Degrees { 5 } with either a base unit dest or not a unit dest type
+                     if(c2 && c2.type == unitClass && (!c1 || c1.type != unitClass))
+                     {
+                        if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+                        exp.op.exp1.destType = type2;
+                        type2.refCount++;
+
+                        if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
+                        {
+                           if(exp.expType) FreeType(exp.expType);
+                           exp.expType = exp.op.exp1.destType;
+                           if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
+                        }
+                     }
+                     else
+                     {
+                        if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+                        exp.op.exp2.destType = type1;
+                        type1.refCount++;
 
                      /*
                      // Maybe this was meant to be an enum...
@@ -8381,43 +9134,44 @@ void ProcessExpressionType(Expression exp)
                      }
                      */
 
-                     if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
-                     {
-                        if(exp.expType) FreeType(exp.expType);
-                        exp.expType = exp.op.exp2.destType;
-                        if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
-                     }
-                     else if(type1 && type2)
-                     {
-                        char expString1[10240];
-                        char expString2[10240];
-                        char type1String[1024];
-                        char type2String[1024];
-                        expString1[0] = '\0';
-                        expString2[0] = '\0';
-                        type1String[0] = '\0';
-                        type2String[0] = '\0';
-                        if(inCompiler)
+                        if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
                         {
-                           PrintExpression(exp.op.exp1, expString1);
-                           ChangeCh(expString1, '\n', ' ');
-                           PrintExpression(exp.op.exp2, expString2);
-                           ChangeCh(expString2, '\n', ' ');
-                           PrintType(exp.op.exp1.expType, type1String, false, true);
-                           PrintType(exp.op.exp2.expType, type2String, false, true);
+                           if(exp.expType) FreeType(exp.expType);
+                           exp.expType = exp.op.exp2.destType;
+                           if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
                         }
+                        else if(type1 && type2)
+                        {
+                           char expString1[10240];
+                           char expString2[10240];
+                           char type1String[1024];
+                           char type2String[1024];
+                           expString1[0] = '\0';
+                           expString2[0] = '\0';
+                           type1String[0] = '\0';
+                           type2String[0] = '\0';
+                           if(inCompiler)
+                           {
+                              PrintExpression(exp.op.exp1, expString1);
+                              ChangeCh(expString1, '\n', ' ');
+                              PrintExpression(exp.op.exp2, expString2);
+                              ChangeCh(expString2, '\n', ' ');
+                              PrintType(exp.op.exp1.expType, type1String, false, true);
+                              PrintType(exp.op.exp2.expType, type2String, false, true);
+                           }
 
-                        Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
+                           Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
 
-                        if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
-                        {
-                           exp.expType = exp.op.exp1.expType;
-                           if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
-                        }
-                        else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
-                        {
-                           exp.expType = exp.op.exp2.expType;
-                           if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                           if(c1 && c1.type == enumClass)
+                           {
+                              exp.expType = exp.op.exp1.expType;
+                              if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+                           }
+                           else if(c2 && c2.type == enumClass)
+                           {
+                              exp.expType = exp.op.exp2.expType;
+                              if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+                           }
                         }
                      }
                   }
@@ -8425,11 +9179,11 @@ void ProcessExpressionType(Expression exp)
                else if(type2)
                {
                   // Maybe this was meant to be an enum...
-                  if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
+                  if(c2 && c2.type == enumClass)
                   {
                      Type oldType = exp.op.exp1.expType;
                      exp.op.exp1.expType = null;
-                     if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                     if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                         FreeType(oldType);
                      else
                         exp.op.exp1.expType = oldType;
@@ -8458,7 +9212,7 @@ void ProcessExpressionType(Expression exp)
                   }
                   */
 
-                  if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+                  if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
                   {
                      if(exp.expType) FreeType(exp.expType);
                      exp.expType = exp.op.exp1.destType;
@@ -8468,14 +9222,14 @@ void ProcessExpressionType(Expression exp)
             }
             else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
             {
-               if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
+               if(type1 && c2 && c2.type == unitClass)
                {
                   if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp1.destType = type2._class.registered.dataType;
                   if(type2._class.registered.dataType)
                      type2._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+                  CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
                }
                if(exp.op.op == '!')
                {
@@ -8490,14 +9244,14 @@ void ProcessExpressionType(Expression exp)
             }
             else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
             {
-               if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
+               if(c2 && c2.type == unitClass)
                {
                   if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
                   // Convert e.g. / 4 into / 4.0
                   exp.op.exp2.destType = type1._class.registered.dataType;
                   if(type1._class.registered.dataType)
                      type1._class.registered.dataType.refCount++;
-                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+                  CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
                }
                exp.expType = type1;
                if(type1) type1.refCount++;
@@ -8543,9 +9297,12 @@ void ProcessExpressionType(Expression exp)
 
          if(exp.op.op == SIZEOF && exp.op.exp2.expType)
          {
-            DeclareType(exp.op.exp2.expType, false, false);
+            DeclareType(curExternal, exp.op.exp2.expType, true, false);
          }
 
+         if(exp.op.op == DELETE && exp.op.exp2 && exp.op.exp2.expType && exp.op.exp2.expType.specConst)
+            Compiler_Warning($"deleting const qualified object\n");
+
          yylloc = oldyylloc;
 
          FreeType(dummy);
@@ -8560,20 +9317,26 @@ void ProcessExpressionType(Expression exp)
          exp.isConstant = true;
          for(e = exp.list->first; e; e = e.next)
          {
-            bool inced = false;
+            //bool inced = false;
             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) { exp.destType.refCount++; e.destType.count++; inced = true; }
+               if(e.destType) { exp.destType.refCount++; /*e.destType.count++; inced = true;*/ }
             }
             ProcessExpressionType(e);
-            if(inced)
-               exp.destType.count--;
+            if(e.ambiguousUnits)
+               exp.ambiguousUnits = true;
+            /*if(inced)
+               exp.destType.count--;*/
             if(!exp.expType && !e.next)
             {
                exp.expType = e.expType;
                if(e.expType) e.expType.refCount++;
+               exp.needCast = e.needCast;
             }
             if(!e.isConstant)
                exp.isConstant = false;
@@ -8624,7 +9387,17 @@ void ProcessExpressionType(Expression exp)
 
                   if(exp.index.index && exp.index.index->last)
                   {
-                     ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
+                     Type type = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
+
+                     if(type.kind == classType) type.constant = true;
+                     else if(type.kind == pointerType)
+                     {
+                        Type t = type;
+                        while(t.kind == pointerType) t = t.type;
+                        t.constant = true;
+                     }
+
+                     ((Expression)exp.index.index->last).destType = type;
                   }
                }
             }
@@ -8649,7 +9422,7 @@ void ProcessExpressionType(Expression exp)
          if(!exp.expType)
             exp.expType = Dereference(exp.index.exp.expType);
          if(exp.expType)
-            DeclareType(exp.expType, false, false);
+            DeclareType(curExternal, exp.expType, true, false);
          break;
       }
       case callExp:
@@ -8867,7 +9640,7 @@ void ProcessExpressionType(Expression exp)
                      {
                         Class backupThisClass = thisClass;
                         thisClass = exp.call.exp.expType.usedClass;
-                        ProcessDeclarator(decl);
+                        ProcessDeclarator(decl, true);
                         thisClass = backupThisClass;
                      }
 
@@ -8876,6 +9649,22 @@ void ProcessExpressionType(Expression exp)
                      functionType = ProcessType(specs, decl);
                      functionType.refCount = 0;
                      FinishTemplatesContext(context);
+
+                     // Mark parameters that were 'thisclass'
+                     {
+                        Type p, op;
+                        for(p = functionType.params.first, op = methodType.method.dataType.params.first; p && op; p = p.next, op = op.next)
+                        {
+                           //p.wasThisClass = op.kind == thisClassType;
+                           if(op.kind == thisClassType)
+                              p.thisClassFrom = methodType.method._class;
+                        }
+                     }
+                     if(methodType.method.dataType.returnType.kind == thisClassType)
+                     {
+                        // functionType.returnType.wasThisClass = true;
+                        functionType.returnType.thisClassFrom = methodType.method._class;
+                     }
                   }
 
                   FreeList(specs, FreeSpecifier);
@@ -9008,6 +9797,7 @@ void ProcessExpressionType(Expression exp)
                   }
                   if(curParam && _class.templateArgs[id].dataTypeString)
                   {
+                     bool constant = type.constant;
                      ClassTemplateArgument arg = _class.templateArgs[id];
                      {
                         Context context = SetupTemplatesContext(_class);
@@ -9017,6 +9807,15 @@ void ProcessExpressionType(Expression exp)
                         templatedType = ProcessTypeString(arg.dataTypeString, false);
                         FinishTemplatesContext(context);
                      }
+
+                     if(templatedType.kind == classType && constant) templatedType.constant = true;
+                     else if(templatedType.kind == pointerType)
+                     {
+                        Type t = templatedType.type;
+                        while(t.kind == pointerType) t = t.type;
+                        if(constant) t.constant = constant;
+                     }
+
                      e.destType = templatedType;
                      if(templatedType)
                      {
@@ -9132,10 +9931,7 @@ void ProcessExpressionType(Expression exp)
          if(exp.call.arguments)
          {
             for(e = exp.call.arguments->first; e; e = e.next)
-            {
-               Type destType = e.destType;
                ProcessExpressionType(e);
-            }
          }
          break;
       }
@@ -9210,9 +10006,6 @@ void ProcessExpressionType(Expression exp)
                      char * colon = strstr(param.defaultArg.memberString, "::");
                      if(colon)
                      {
-                        char className[1024];
-                        Class sClass;
-
                         memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
                         thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
                      }
@@ -9227,7 +10020,6 @@ void ProcessExpressionType(Expression exp)
                   {
                      Class expClass = exp.expType._class.registered;
                      Class cClass = null;
-                     int c;
                      int paramCount = 0;
                      int lastParam = -1;
 
@@ -9344,7 +10136,9 @@ void ProcessExpressionType(Expression exp)
                      }
                   }
 
-                  // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
+                  if(!expMember.expType.isPointerType)
+                     expMember = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), expMember);
+                  // *([expType] *)(((byte *)(uintptr)[exp.member.exp]) + [argExp].member.offset)
                   exp.type = bracketsExp;
                   exp.list = MkListOne(MkExpOp(null, '*',
                   /*opExp;
@@ -9353,11 +10147,12 @@ void ProcessExpressionType(Expression exp)
                   exp.op.exp2 = */
                   MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
                      MkExpBrackets(MkListOne(
-                        MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
-                           '+',
-                           MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")),
-                           '+',
-                           MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
+                        MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
+                           expMember))),
+                              '+',
+                              MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")),
+                              '+',
+                              MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
 
                            ));
                }
@@ -9454,28 +10249,39 @@ void ProcessExpressionType(Expression exp)
                   // Prioritize properties over data members otherwise
                   else
                   {
+                     bool useMemberForNonConst = false;
                      // First look for Public Members (Unless class specifier is provided, which skips public priority)
                      if(!id.classSym)
                      {
                         prop = eClass_FindProperty(_class, id.string, null);
-                        if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
+
+                        useMemberForNonConst = prop && exp.destType &&
+                           ( (exp.destType.kind == classType && !exp.destType.constant) || ((exp.destType.kind == pointerType || exp.destType.kind == arrayType) && exp.destType.type && !exp.destType.type.constant) ) &&
+                              !strncmp(prop.dataTypeString, "const ", 6);
+
+                        if(useMemberForNonConst || !id._class || !id._class.name || strcmp(id._class.name, "property"))
                            member = eClass_FindDataMember(_class, id.string, null, null, null);
                      }
 
-                     if(!prop && !member)
+                     if((!prop || useMemberForNonConst) && !member)
                      {
-                        method = eClass_FindMethod(_class, id.string, null);
+                        method = useMemberForNonConst ? null : eClass_FindMethod(_class, id.string, null);
                         if(!method)
                         {
                            prop = eClass_FindProperty(_class, id.string, privateModule);
-                           if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
+
+                           useMemberForNonConst |= prop && exp.destType &&
+                              ( (exp.destType.kind == classType && !exp.destType.constant) || ((exp.destType.kind == pointerType || exp.destType.kind == arrayType) && exp.destType.type && !exp.destType.type.constant) ) &&
+                                 !strncmp(prop.dataTypeString, "const ", 6);
+
+                           if(useMemberForNonConst || !id._class || !id._class.name || strcmp(id._class.name, "property"))
                               member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
                         }
                      }
 
                      if(member && prop)
                      {
-                        if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
+                        if(useMemberForNonConst || (member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class)))
                            prop = null;
                         else
                            member = null;
@@ -9539,13 +10345,41 @@ void ProcessExpressionType(Expression exp)
                   }
                }
 
+               //if(!exp.member.exp.destType)
+               if(exp.member.exp.destType)
+                  FreeType(exp.member.exp.destType);
+               {
+                  if(method && !method._class.symbol)
+                     method._class.symbol = FindClass(method._class.fullName);
+                  if(prop && !prop._class.symbol)
+                     prop._class.symbol = FindClass(prop._class.fullName);
+
+                  exp.member.exp.destType = Type
+                  {
+                     refCount = 1;
+                     kind = classType;
+                     _class = prop ? prop._class.symbol : method ? method._class.symbol : _class.symbol;
+                     // wasThisClass = type ? type.wasThisClass : false;
+                     thisClassFrom = type ? type.thisClassFrom : null;
+                  };
+               }
+
                if(prop)
                {
                   exp.member.memberType = propertyMember;
                   if(!prop.dataType)
                      ProcessPropertyType(prop);
                   exp.expType = prop.dataType;
-                  if(prop.dataType) prop.dataType.refCount++;
+                  if(!strcmp(_class.base.fullName, "eda::Row") && !exp.expType.constant && !exp.destType)
+                  {
+                     Type type { };
+                     CopyTypeInto(type, exp.expType);
+                     type.refCount = 1;
+                     type.constant = true;
+                     exp.expType = type;
+                  }
+                  else if(prop.dataType)
+                     prop.dataType.refCount++;
                }
                else if(member)
                {
@@ -9559,13 +10393,18 @@ void ProcessExpressionType(Expression exp)
                   }
 
                   exp.member.memberType = dataMember;
-                  DeclareStruct(_class.fullName, false);
+                  DeclareStruct(curExternal, _class.fullName, false, true);
+                  if(member._class != _class)
+                     DeclareStruct(curExternal, member._class.fullName, false, true);
+
                   if(!member.dataType)
                   {
                      Context context = SetupTemplatesContext(_class);
                      member.dataType = ProcessTypeString(member.dataTypeString, false);
                      FinishTemplatesContext(context);
                   }
+                  if(exp.member.exp.expType.kind == classType && exp.member.exp.expType._class && exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == bitClass)
+                     member.dataType.bitMemberSize = ((BitMember)member).size;
                   exp.expType = member.dataType;
                   if(member.dataType) member.dataType.refCount++;
                }
@@ -9613,7 +10452,8 @@ void ProcessExpressionType(Expression exp)
                      FreeExpContents(exp);
                      exp.type = identifierExp;
                      exp.identifier = MkIdentifier("class");
-                     ProcessExpressionType(exp);
+                     FreeType(exp.expType);
+                     exp.expType = MkClassType("ecere::com::Class");
                      return;
                   }
                   yylloc = exp.member.member.loc;
@@ -9626,7 +10466,7 @@ void ProcessExpressionType(Expression exp)
                {
                   Class tClass;
 
-                  tClass = _class;
+                  tClass = type._class && type._class.registered ? type._class.registered : _class;
                   while(tClass && !tClass.templateClass) tClass = tClass.base;
 
                   if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
@@ -9656,10 +10496,34 @@ void ProcessExpressionType(Expression exp)
                      {
                         ClassTemplateArgument arg = tClass.templateArgs[id];
                         Context context = SetupTemplatesContext(tClass);
+                        bool constant = exp.expType.constant;
+                        bool passAsTemplate = false;
+                        Class thisClassFrom = null;
+                        Type t = ProcessTypeString(exp.expType.templateParameter.dataTypeString, false);
+                        if(t && t.kind == classType && t._class)
+                           thisClassFrom = t._class.registered;
+                        else
+                           // Mark that 'thisClassFrom' was set to something
+                           thisClassFrom = eSystem_FindClass(GetPrivateModule(), "class");
+
+                        FreeType(t);
+
+                        passAsTemplate = tClass.templateClass && (exp.expType.kind != templateType ||
+                           (!exp.expType.templateParameter || (!exp.expType.templateParameter.dataTypeString && !exp.expType.templateParameter.dataType)));
+
                         /*if(!arg.dataType)
                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
                         FreeType(exp.expType);
+
                         exp.expType = ProcessTypeString(arg.dataTypeString, false);
+                        exp.expType.thisClassFrom = thisClassFrom;
+                        if(exp.expType.kind == classType && constant) exp.expType.constant = true;
+                        else if(exp.expType.kind == pointerType)
+                        {
+                           Type t = exp.expType.type;
+                           while(t.kind == pointerType) t = t.type;
+                           if(constant) t.constant = constant;
+                        }
                         if(exp.expType)
                         {
                            if(exp.expType.kind == thisClassType)
@@ -9668,12 +10532,20 @@ void ProcessExpressionType(Expression exp)
                               exp.expType = ReplaceThisClassType(_class);
                            }
 
-                           if(tClass.templateClass)
+                           if(passAsTemplate)
                               exp.expType.passAsTemplate = true;
                            //exp.expType.refCount++;
                            if(!exp.destType)
                            {
                               exp.destType = ProcessTypeString(arg.dataTypeString, false);
+                              if(exp.destType.kind == classType && constant) exp.destType.constant = true;
+                              else if(exp.destType.kind == pointerType)
+                              {
+                                 Type t = exp.destType.type;
+                                 while(t.kind == pointerType) t = t.type;
+                                 if(constant) t.constant = constant;
+                              }
+
                               //exp.destType.refCount++;
 
                               if(exp.destType.kind == thisClassType)
@@ -9768,7 +10640,6 @@ void ProcessExpressionType(Expression exp)
                      if(expClass)
                      {
                         Class cClass = null;
-                        int c;
                         int p = 0;
                         int paramCount = 0;
                         int lastParam = -1;
@@ -9784,7 +10655,6 @@ void ProcessExpressionType(Expression exp)
                            for(param = cClass.templateParams.first; param; param = param.next)
                            {
                               Class cClassCur = null;
-                              int c;
                               int cp = 0;
                               ClassTemplateParameter paramCur = null;
                               ClassTemplateArgument arg;
@@ -9952,19 +10822,54 @@ void ProcessExpressionType(Expression exp)
          Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
          if(classSym && classSym.registered)
          {
-            if(classSym.registered.type == noHeadClass)
+            if(classSym.registered.type == noHeadClass || (classSym.registered.fixed && classSym.registered.structSize))
             {
                char name[1024];
+               Class b = classSym.registered;
                name[0] = '\0';
-               DeclareStruct(classSym.string, false);
+               DeclareStruct(curExternal, classSym.string, false, true);
                FreeSpecifier(exp._class);
-               exp.type = typeSizeExp;
                FullClassNameCat(name, classSym.string, false);
-               exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
+
+               if(b.offset == 0)
+               {
+                  exp.type = typeSizeExp;
+                  exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
+               }
+               else
+               {
+                  Expression e;
+                  exp.type = opExp;
+                  if(b.structSize == b.offset)
+                     exp.op.exp1 = MkExpConstant("0");
+                  else
+                     exp.op.exp1 = MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null));
+                  exp.op.op = '+';
+                  e = exp;
+                  while(b.offset != 0)
+                  {
+                     Symbol sym;
+                     Expression typeSize;
+
+                     b = b.base;
+                     sym = FindClass(b.fullName);
+
+                     name[0] = '\0';
+                     DeclareStruct(curExternal, sym.string, false, true);
+                     FullClassNameCat(name, sym.string, false);
+
+                     if(b.structSize == b.offset)
+                        typeSize = MkExpConstant("0");
+                     else
+                        typeSize = MkExpTypeSize(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null));
+                     e.op.exp2 = b.offset ? MkExpOp(typeSize, '+', null) : typeSize;
+                     e = e.op.exp2;
+                  }
+               }
             }
             else
             {
-               if(classSym.registered.fixed)
+               if(classSym.registered.fixed && !classSym.registered.structSize)
                {
                   FreeSpecifier(exp._class);
                   exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
@@ -9975,9 +10880,8 @@ void ProcessExpressionType(Expression exp)
                   char className[1024];
                   strcpy(className, "__ecereClass_");
                   FullClassNameCat(className, classSym.string, true);
-                  MangleClassName(className);
 
-                  DeclareClass(classSym, className);
+                  DeclareClass(curExternal, classSym, className);
 
                   FreeExpContents(exp);
                   exp.type = pointerExp;
@@ -9990,7 +10894,7 @@ void ProcessExpressionType(Expression exp)
          exp.expType = Type
          {
             refCount = 1;
-            kind = intType;
+            kind = intSizeType;
          };
          // exp.isConstant = true;
          break;
@@ -10002,11 +10906,11 @@ void ProcessExpressionType(Expression exp)
          exp.expType = Type
          {
             refCount = 1;
-            kind = intType;
+            kind = intSizeType;
          };
          exp.isConstant = true;
 
-         DeclareType(type, false, false);
+         DeclareType(curExternal, type, true, false);
          FreeType(type);
          break;
       }
@@ -10017,7 +10921,9 @@ void ProcessExpressionType(Expression exp)
          FreeType(exp.cast.exp.destType);
          exp.cast.exp.destType = type;
          type.refCount++;
+         type.casted = true;
          ProcessExpressionType(exp.cast.exp);
+         type.casted = false;
          type.count = 0;
          exp.expType = type;
          //type.refCount++;
@@ -10074,6 +10980,16 @@ void ProcessExpressionType(Expression exp)
       case conditionExp:
       {
          Expression e;
+         Type t = exp.destType;
+         if(t && !exp.destType.casted)
+         {
+            t = { };
+            CopyTypeInto(t, exp.destType);
+            t.count = 0;
+         }
+         else if(t)
+            t.refCount++;
+
          exp.isConstant = true;
 
          FreeType(exp.cond.cond.destType);
@@ -10087,7 +11003,7 @@ void ProcessExpressionType(Expression exp)
             if(!e.next)
             {
                FreeType(e.destType);
-               e.destType = exp.destType;
+               e.destType = t;
                if(e.destType) e.destType.refCount++;
             }
             ProcessExpressionType(e);
@@ -10105,7 +11021,7 @@ void ProcessExpressionType(Expression exp)
          // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
 
          // Reversed it...
-         exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
+         exp.cond.elseExp.destType = t ? t : exp.expType;
 
          if(exp.cond.elseExp.destType)
             exp.cond.elseExp.destType.refCount++;
@@ -10114,6 +11030,8 @@ void ProcessExpressionType(Expression exp)
          // FIXED THIS: Was done before calling process on elseExp
          if(!exp.cond.elseExp.isConstant)
             exp.isConstant = false;
+
+         FreeType(t);
          break;
       }
       case extensionCompoundExp:
@@ -10183,7 +11101,7 @@ void ProcessExpressionType(Expression exp)
       case arrayExp:
       {
          Type type = null;
-         char * typeString = null;
+         const char * typeString = null;
          char typeStringBuf[1024];
          if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
             exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
@@ -10204,7 +11122,7 @@ void ProcessExpressionType(Expression exp)
                   else
                   {
                      // if(!MatchType(e.expType, type, null, null, null, false, false, false))
-                     if(!MatchTypeExpression(e, type, null, false))
+                     if(!MatchTypeExpression(e, type, null, false, true))
                      {
                         FreeType(type);
                         type = e.expType;
@@ -10215,7 +11133,7 @@ void ProcessExpressionType(Expression exp)
                         if(e.expType)
                         {
                            //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
-                           if(!MatchTypeExpression(e, type, null, false))
+                           if(!MatchTypeExpression(e, type, null, false, true))
                            {
                               FreeType(e.expType);
                               e.expType = null;
@@ -10267,7 +11185,7 @@ void ProcessExpressionType(Expression exp)
             {
                Expression e;
                type = ProcessTypeString(typeString, false);
-               while(e = exp.list->first)
+               while((e = exp.list->first))
                {
                   exp.list->Remove(e);
                   e.destType = type;
@@ -10279,7 +11197,7 @@ void ProcessExpressionType(Expression exp)
                delete exp.list;
             }
 
-            DeclareStruct("ecere::com::BuiltInContainer", false);
+            DeclareStruct(curExternal, "ecere::com::BuiltInContainer", false, true);
 
             ListAdd(structInitializers, /*MkIdentifier("_vTbl")*/    MkInitializerAssignment(MkExpMember(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl"))));
                ProcessExpressionType(((Initializer)structInitializers->last).exp);
@@ -10345,23 +11263,48 @@ void ProcessExpressionType(Expression exp)
          }
          else
          {
-            NamedLink member;
+            NamedLink64 member;
             for(member = symbol.type.members.first; member; member = member.next)
             {
-               NamedLink value { name = CopyString(member.name) };
+               NamedLink64 value { name = CopyString(member.name) };
                exp.expType.members.Add(value);
             }
          }
       }
    }
 
+   // Trying to do this here before conversion properties kick in and this becomes a new expression... (Fixing Class c; const char * a = c;)
+   // Mark nohead classes as by reference, unless we're casting them to an integral type
+   if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
+      exp.expType._class.registered.type == noHeadClass && (!exp.destType ||
+         (exp.destType.kind != intType && exp.destType.kind != int64Type && exp.destType.kind != intPtrType && exp.destType.kind != intSizeType &&
+          exp.destType.kind != longType && exp.destType.kind != shortType && exp.destType.kind != charType && exp.destType.kind != _BoolType)))
+   {
+      exp.byReference = true;
+   }
+
    yylloc = exp.loc;
-   if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
+   if(exp.destType && (/*exp.destType.kind == voidType || */exp.destType.kind == dummyType) );
    else if(exp.destType && !exp.destType.keepCast)
    {
-      if(!CheckExpressionType(exp, exp.destType, false))
+      if(!exp.needTemplateCast && exp.expType && (exp.expType.kind == templateType || exp.expType.passAsTemplate)) // && exp.destType && !exp.destType.passAsTemplate)
+         exp.needTemplateCast = 1;
+
+      if(exp.destType.kind == voidType);
+      else if(!CheckExpressionType(exp, exp.destType, false, !exp.destType.casted))
       {
-         if(!exp.destType.count || unresolved)
+         // Warn for casting unrelated types to/from struct classes
+         bool invalidCast = false;
+         if(inCompiler && exp.destType.count && exp.expType)
+         {
+            Class c1 = (exp.expType.kind == classType && exp.expType._class) ? exp.expType._class.registered : null;
+            Class c2 = (exp.destType.kind == classType && exp.destType._class) ? exp.destType._class.registered : null;
+            if(c1 && c1.type != structClass) c1 = null;
+            if(c2 && c2.type != structClass) c2 = null;
+            if((c1 && !exp.expType.byReference && !c2 && !exp.destType.isPointerType) || (c2 && !exp.destType.byReference && !c1 && !exp.expType.isPointerType))
+               invalidCast = true;
+         }
+         if(!exp.destType.count || unresolved || invalidCast)
          {
             if(!exp.expType)
             {
@@ -10415,46 +11358,142 @@ void ProcessExpressionType(Expression exp)
                   (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
                else
                {
-                  char expString[10240];
-                  expString[0] = '\0';
-                  if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
+                  Expression nbExp = GetNonBracketsExp(exp);
+                  bool skipWarning = false;
+                  TypeKind kind = exp.destType.kind;
+                  if(nbExp.type == conditionExp && nbExp.destType && !nbExp.destType.casted && nbExp.destType.kind == exp.destType.kind)
+                     // The if/else operands have already been checked / warned about
+                     skipWarning = true;
+                  if((kind == charType || kind == shortType) && exp.destType.isSigned == exp.expType.signedBeforePromotion && nbExp.type == opExp && nbExp.op.exp1 && nbExp.op.exp2)
+                  {
+                     int op = nbExp.op.op;
+                     Expression nbExp1, nbExp2;
+                     TypeKind from;
+
+                     switch(op)
+                     {
+                        case '%': case '/':
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           from = nbExp1.expType.promotedFrom;
+                           // Division and Modulo will not take more room than type before promotion
+                           if(from == charType || (kind == shortType && from == shortType))
+                              skipWarning = true;
+                           break;
+                        // Left shift
+                        case LEFT_OP: case RIGHT_OP:
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                           from = nbExp1.expType.promotedFrom;
+                           // Right shift will not take more room than type before promotion
+                           if(op == RIGHT_OP && (from == charType || (kind == shortType && from == shortType)))
+                              skipWarning = true;
+                           else if(nbExp2.isConstant && nbExp2.type == constantExp && (nbExp.op.op == RIGHT_OP || nbExp1.expType.bitMemberSize))
+                           {
+                              int n = (int)strtol(nbExp2.constant, null, 0);
+                              int s = from == charType ? 8 : 16;
+                              // Left shifting a bit member constrained in size may still fit in type before promotion
+                              if(nbExp1.expType.bitMemberSize && nbExp1.expType.bitMemberSize < s)
+                                 s = nbExp1.expType.bitMemberSize;
+
+                              // If right shifted enough things will fit in smaller type
+                              if(nbExp.op.op == RIGHT_OP)
+                                 s -= n;
+                              else
+                                 s += n;
+                              if(s <= (kind == charType ? 8 : 16))
+                                 skipWarning = true;
+                           }
+                           break;
+                        case '-':
+                           if(!exp.destType.isSigned)
+                           {
+                              nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                              nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                              from = nbExp2.expType.promotedFrom;
+                              // Max value of unsigned type before promotion minus the same will always fit
+                              if((from == charType || from == shortType) && nbExp1.isConstant && nbExp1.type == constantExp)
+                              {
+                                 int n = (int)strtol(nbExp1.constant, null, 0);
+                                 if(n == (from == charType ? 255 : 65535))
+                                    skipWarning = true;
+                              }
+                           }
+                           break;
+                        case '|':
+                        {
+                           TypeKind kind1, kind2;
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                           kind1 = nbExp1.expType.promotedFrom ? nbExp1.expType.promotedFrom : nbExp1.expType.kind;
+                           kind2 = nbExp2.expType.promotedFrom ? nbExp2.expType.promotedFrom : nbExp2.expType.kind;
+                           if(((kind1 == charType || (kind1 == shortType && kind == shortType)) || MatchTypeExpression(nbExp1, exp.destType, null, false, false)) &&
+                              ((kind2 == charType || (kind2 == shortType && kind == shortType)) || MatchTypeExpression(nbExp2, exp.destType, null, false, false)))
+                              skipWarning = true;
+                           break;
+                        }
+                        case '&':
+                        {
+                           TypeKind kind1, kind2;
+                           nbExp1 = GetNonBracketsExp(nbExp.op.exp1);
+                           nbExp2 = GetNonBracketsExp(nbExp.op.exp2);
+                           kind1 = nbExp1.expType.promotedFrom ? nbExp1.expType.promotedFrom : nbExp1.expType.kind;
+                           kind2 = nbExp2.expType.promotedFrom ? nbExp2.expType.promotedFrom : nbExp2.expType.kind;
+                           if(((kind1 == charType || (kind1 == shortType && kind == shortType)) || MatchTypeExpression(nbExp1, exp.destType, null, false, false)) ||
+                              ((kind2 == charType || (kind2 == shortType && kind == shortType)) || MatchTypeExpression(nbExp2, exp.destType, null, false, false)))
+                              skipWarning = true;
+                           break;
+                        }
+                     }
+                  }
+
+                  if(!skipWarning)
+                  {
+                     char expString[10240];
+                     expString[0] = '\0';
+                     if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
 
 #ifdef _DEBUG
-                  CheckExpressionType(exp, exp.destType, false);
+                     CheckExpressionType(exp, exp.destType, false, true);
 #endif
-                  // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
-                  if(!sourceFile || (strcmp(sourceFile, "src\\lexer.ec") && strcmp(sourceFile, "src/lexer.ec") && strcmp(sourceFile, "src\\grammar.ec") && strcmp(sourceFile, "src/grammar.ec")))
-                     Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
+
+                     // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
+                     if(!sourceFile || (!strstr(sourceFile, "src\\lexer.ec") && !strstr(sourceFile, "src/lexer.ec") &&
+                                        !strstr(sourceFile, "src\\grammar.ec") && !strstr(sourceFile, "src/grammar.ec") &&
+                                        !strstr(sourceFile, "src\\type.ec") && !strstr(sourceFile, "src/type.ec") &&
+                                        !strstr(sourceFile, "src\\expression.ec") && !strstr(sourceFile, "src/expression.ec")))
+                     {
+                        if(invalidCast)
+                           Compiler_Error($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
+                        else
+                           Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
+                     }
+                  }
 
                   // TO CHECK: FORCING HERE TO HELP DEBUGGER
-                  FreeType(exp.expType);
-                  exp.destType.refCount++;
-                  exp.expType = exp.destType;
+                  if(!inCompiler)
+                  {
+                     FreeType(exp.expType);
+                     exp.destType.refCount++;
+                     exp.expType = exp.destType;
+                  }
                }
             }
          }
       }
-      else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
+      // Cast function pointers to void * as eC already checked compatibility
+      else if(exp.destType && exp.destType.kind == pointerType && exp.destType.type && exp.destType.type.kind == functionType &&
+              exp.expType && (exp.expType.kind == functionType || exp.expType.kind == methodType))
       {
-         Expression newExp { };
-         char typeString[1024];
-         OldList * specs = MkList();
-         Declarator decl;
-
-         typeString[0] = '\0';
-
-         *newExp = *exp;
-
-         if(exp.expType)  exp.expType.refCount++;
-         if(exp.expType)  exp.expType.refCount++;
-         exp.type = castExp;
-         newExp.destType = exp.expType;
-
-         PrintType(exp.expType, typeString, false, false);
-         decl = SpecDeclFromString(typeString, specs, null);
-
-         exp.cast.typeName = MkTypeName(specs, decl);
-         exp.cast.exp = newExp;
+         Expression nbExp = GetNonBracketsExp(exp);
+         if(nbExp.type != castExp || !IsVoidPtrCast(nbExp.cast.typeName))
+         {
+            Expression e = MoveExpContents(exp);
+            exp.cast.exp = MkExpBrackets(MkListOne(e));
+            exp.type = castExp;
+            exp.cast.exp.destType = exp.destType;
+            if(exp.destType) exp.destType.refCount++;
+            exp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null));
+         }
       }
    }
    else if(unresolved)
@@ -10648,7 +11687,7 @@ static void ProcessInitializer(Initializer init, Type type)
    }
 }
 
-static void ProcessSpecifier(Specifier spec, bool declareStruct)
+static void ProcessSpecifier(Specifier spec, bool declareStruct, bool warnClasses)
 {
    switch(spec.type)
    {
@@ -10661,7 +11700,7 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
                spec.type = nameSpecifier;
                spec.name = ReplaceThisClass(thisClass);
                spec.symbol = FindClass(spec.name);
-               ProcessSpecifier(spec, declareStruct);
+               ProcessSpecifier(spec, declareStruct, false);
             }
          }
          break;
@@ -10670,9 +11709,14 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
       {
          Symbol symbol = FindType(curContext, spec.name);
          if(symbol)
-            DeclareType(symbol.type, true, true);
-         else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
-            DeclareStruct(spec.name, false);
+            DeclareType(curExternal, symbol.type, true, true);
+         else if(spec.symbol /*&& declareStruct*/)
+         {
+            Class c = spec.symbol.registered;
+            if(warnClasses && !c)
+               Compiler_Warning("Undeclared class %s\n", spec.name);
+            DeclareStruct(curExternal, spec.name, c && c.type == noHeadClass, declareStruct && c && c.type == structClass);
+         }
          break;
       }
       case enumSpecifier:
@@ -10686,14 +11730,16 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
                   ProcessExpressionType(e.exp);
             }
          }
-         break;
+         // Fall through for IDE type processing
+         if(inCompiler)
+            break;
       }
       case structSpecifier:
       case unionSpecifier:
       {
          if(spec.definitions)
          {
-            ClassDef def;
+            //ClassDef def;
             Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
             //if(symbol)
                ProcessClass(spec.definitions, symbol);
@@ -10713,7 +11759,7 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
       {
          Symbol classSym = FindClass(spec.name);
          if(classSym && classSym.registered && classSym.registered.type == structClass)
-            DeclareStruct(spec.name, false);
+            DeclareStruct(spec.name, false, true);
          break;
       }
       */
@@ -10721,7 +11767,7 @@ static void ProcessSpecifier(Specifier spec, bool declareStruct)
 }
 
 
-static void ProcessDeclarator(Declarator decl)
+static void ProcessDeclarator(Declarator decl, bool isFunction)
 {
    switch(decl.type)
    {
@@ -10741,22 +11787,32 @@ static void ProcessDeclarator(Declarator decl)
       case pointerDeclarator:
       case extendedDeclarator:
       case extendedDeclaratorEnd:
-         if(decl.declarator)
-            ProcessDeclarator(decl.declarator);
+      {
+         Identifier id = null;
+         Specifier classSpec = null;
          if(decl.type == functionDeclarator)
          {
-            Identifier id = GetDeclId(decl);
+            id = GetDeclId(decl);
             if(id && id._class)
             {
+               classSpec = id._class;
+               id._class = null;
+            }
+         }
+         if(decl.declarator)
+            ProcessDeclarator(decl.declarator, isFunction);
+         if(decl.type == functionDeclarator)
+         {
+            if(classSpec)
+            {
                TypeName param
                {
-                  qualifiers = MkListOne(id._class);
+                  qualifiers = MkListOne(classSpec);
                   declarator = null;
                };
                if(!decl.function.parameters)
                   decl.function.parameters = MkList();
                decl.function.parameters->Insert(null, param);
-               id._class = null;
             }
             if(decl.function.parameters)
             {
@@ -10764,57 +11820,83 @@ static void ProcessDeclarator(Declarator decl)
 
                for(param = decl.function.parameters->first; param; param = param.next)
                {
-                  if(param.qualifiers && param.qualifiers->first)
+                  if(param.qualifiers)
                   {
-                     Specifier spec = param.qualifiers->first;
-                     if(spec && spec.specifier == TYPED_OBJECT)
+                     Specifier spec;
+                     for(spec = param.qualifiers->first; spec; spec = spec.next)
                      {
-                        Declarator d = param.declarator;
-                        TypeName newParam
+                        if(spec.type == baseSpecifier)
                         {
-                           qualifiers = MkListOne(MkSpecifier(VOID));
-                           declarator = MkDeclaratorPointer(MkPointer(null,null), d);
-                        };
+                           if(spec.specifier == TYPED_OBJECT)
+                           {
+                              Declarator d = param.declarator;
+                              TypeName newParam
+                              {
+                                 qualifiers = MkListOne(MkSpecifier(VOID));
+                                 declarator = MkDeclaratorPointer(MkPointer(null,null), d);
+                              };
+                              if(!d || d.type != pointerDeclarator)
+                                 newParam.qualifiers->Insert(null, MkSpecifier(CONST));
 
-                        FreeList(param.qualifiers, FreeSpecifier);
+                              FreeList(param.qualifiers, FreeSpecifier);
 
-                        param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
-                        param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
+                              param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
+                              param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
 
-                        decl.function.parameters->Insert(param, newParam);
-                        param = newParam;
-                     }
-                     else if(spec && spec.specifier == ANY_OBJECT)
-                     {
-                        Declarator d = param.declarator;
+                              DeclareStruct(curExternal, "ecere::com::Class", false, true);
+
+                              decl.function.parameters->Insert(param, newParam);
+                              param = newParam;
+                              break;
+                           }
+                           else if(spec.specifier == ANY_OBJECT)
+                           {
+                              Declarator d = param.declarator;
 
-                        FreeList(param.qualifiers, FreeSpecifier);
+                              FreeList(param.qualifiers, FreeSpecifier);
 
-                        param.qualifiers = MkListOne(MkSpecifier(VOID));
-                        param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);
-                     }
-                     else if(spec.specifier == THISCLASS)
-                     {
-                        if(thisClass)
+                              param.qualifiers = MkListOne(MkSpecifier(VOID));
+                              if(!d || d.type != pointerDeclarator)
+                                 param.qualifiers->Insert(null, MkSpecifier(CONST));
+                              param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);
+                              break;
+                           }
+                           else if(spec.specifier == THISCLASS)
+                           {
+                              if(thisClass)
+                              {
+                                 spec.type = nameSpecifier;
+                                 spec.name = ReplaceThisClass(thisClass);
+                                 spec.symbol = FindClass(spec.name);
+                                 ProcessSpecifier(spec, false, false);
+                              }
+                              break;
+                           }
+                        }
+                        else if(spec.type == nameSpecifier)
                         {
-                           spec.type = nameSpecifier;
-                           spec.name = ReplaceThisClass(thisClass);
-                           spec.symbol = FindClass(spec.name);
-                           ProcessSpecifier(spec, false);
+                           ProcessSpecifier(spec, isFunction, true);
+                        }
+                        else if((spec.type == structSpecifier || spec.type == unionSpecifier) && !spec.definitions && spec.id && spec.id.string)
+                        {
+                           Declarator d = param.declarator;
+                           if(!d || d.type != pointerDeclarator)
+                              DeclareStruct(curExternal, spec.id.string, false, true);
                         }
                      }
                   }
 
                   if(param.declarator)
-                     ProcessDeclarator(param.declarator);
+                     ProcessDeclarator(param.declarator, false);
                }
             }
          }
          break;
+      }
    }
 }
 
-static void ProcessDeclaration(Declaration decl)
+static void ProcessDeclaration(Declaration decl, bool warnClasses)
 {
    yylloc = decl.loc;
    switch(decl.type)
@@ -10834,7 +11916,7 @@ static void ProcessDeclaration(Declaration decl)
             for(d = decl.declarators->first; d; d = d.next)
             {
                Type type, subType;
-               ProcessDeclarator(d.declarator);
+               ProcessDeclarator(d.declarator, false);
 
                type = ProcessType(decl.specifiers, d.declarator);
 
@@ -10890,7 +11972,7 @@ static void ProcessDeclaration(Declaration decl)
             Specifier s;
             for(s = decl.specifiers->first; s; s = s.next)
             {
-               ProcessSpecifier(s, declareStruct);
+               ProcessSpecifier(s, declareStruct, true);
             }
          }
          break;
@@ -10912,7 +11994,7 @@ static void ProcessDeclaration(Declaration decl)
             {
                Type type = ProcessType(decl.specifiers, d.declarator);
                Type subType;
-               ProcessDeclarator(d);
+               ProcessDeclarator(d, false);
                for(subType = type; subType;)
                {
                   if(subType.kind == classType)
@@ -10933,7 +12015,7 @@ static void ProcessDeclaration(Declaration decl)
          if(decl.specifiers)
          {
             for(spec = decl.specifiers->first; spec; spec = spec.next)
-               ProcessSpecifier(spec, declareStruct);
+               ProcessSpecifier(spec, declareStruct, warnClasses);
          }
          break;
       }
@@ -10948,22 +12030,18 @@ static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
    char getName[1024], setName[1024];
    OldList * args;
 
-   DeclareProperty(prop, setName, getName);
+   DeclareProperty(curExternal, prop, setName, getName);
 
    // eInstance_FireWatchers(object, prop);
    strcpy(propName, "__ecereProp_");
    FullClassNameCat(propName, prop._class.fullName, false);
    strcat(propName, "_");
-   // strcat(propName, prop.name);
    FullClassNameCat(propName, prop.name, true);
-   MangleClassName(propName);
 
    strcpy(propNameM, "__ecerePropM_");
    FullClassNameCat(propNameM, prop._class.fullName, false);
    strcat(propNameM, "_");
-   // strcat(propNameM, prop.name);
    FullClassNameCat(propNameM, prop.name, true);
-   MangleClassName(propNameM);
 
    if(prop.isWatchable)
    {
@@ -10976,8 +12054,9 @@ static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
-   }
 
+      DeclareFunctionUtil(curExternal, "eInstance_FireWatchers");
+   }
 
    {
       args = MkList();
@@ -10989,6 +12068,8 @@ static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
       ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
       ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
       ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
+
+      DeclareFunctionUtil(curExternal, "eInstance_FireSelfWatchers");
    }
 
    if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) &&
@@ -11038,7 +12119,7 @@ static void ProcessStatement(Statement stmt)
             if(stmt.compound.declarations)
             {
                for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
-                  ProcessDeclaration(decl);
+                  ProcessDeclaration(decl, true);
             }
             if(stmt.compound.statements)
             {
@@ -11184,7 +12265,7 @@ static void ProcessStatement(Statement stmt)
             (((Expression)exp->last).type == ExpressionType::arrayExp ||
               (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
          Expression arrayExp;
-         char * typeString = null;
+         const char * typeString = null;
          int builtinCount = 0;
 
          for(e = exp ? exp->first : null; e; e = e.next)
@@ -11205,24 +12286,28 @@ static void ProcessStatement(Statement stmt)
             Class _class = source ? source._class.registered : null;
             Symbol symbol;
             Expression expIt = null;
-            bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
+            bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false; //, isAVLTree = false;
             Class arrayClass = eSystem_FindClass(privateModule, "Array");
             Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
             Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
-            stmt.type = compoundStmt;
 
-            stmt.compound.context = Context { };
-            stmt.compound.context.parent = curContext;
-            curContext = stmt.compound.context;
+            if(inCompiler)
+            {
+               stmt.type = compoundStmt;
+
+               stmt.compound.context = Context { };
+               stmt.compound.context.parent = curContext;
+               curContext = stmt.compound.context;
+            }
 
             if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
             {
                Class mapClass = eSystem_FindClass(privateModule, "Map");
-               Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
+               //Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
                isCustomAVLTree = true;
-               if(eClass_IsDerived(source._class.registered, avlTreeClass))
+               /*if(eClass_IsDerived(source._class.registered, avlTreeClass))
                   isAVLTree = true;
-               else if(eClass_IsDerived(source._class.registered, mapClass))
+               else */if(eClass_IsDerived(source._class.registered, mapClass))
                   isMap = true;
             }
             else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
@@ -11233,7 +12318,7 @@ static void ProcessStatement(Statement stmt)
                isList = eClass_IsDerived(source._class.registered, listClass);
             }
 
-            if(isArray)
+            if(inCompiler && isArray)
             {
                Declarator decl;
                OldList * specs = MkList();
@@ -11279,7 +12364,7 @@ static void ProcessStatement(Statement stmt)
                         else
                         {
                            // if(!MatchType(e.expType, type, null, null, null, false, false, false))
-                           if(!MatchTypeExpression(e, type, null, false))
+                           if(!MatchTypeExpression(e, type, null, false, true))
                            {
                               FreeType(type);
                               type = e.expType;
@@ -11290,7 +12375,7 @@ static void ProcessStatement(Statement stmt)
                               if(e.expType)
                               {
                                  //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
-                                 if(!MatchTypeExpression(e, type, null, false))
+                                 if(!MatchTypeExpression(e, type, null, false, true))
                                  {
                                     FreeType(e.expType);
                                     e.expType = null;
@@ -11318,35 +12403,52 @@ static void ProcessStatement(Statement stmt)
                }
                if(typeString)
                {
-                  OldList * initializers = MkList();
-                  Declarator decl;
-                  OldList * specs = MkList();
-                  if(arrayExp.list)
+                  if(inCompiler)
                   {
-                     Expression e;
+                     OldList * initializers = MkList();
+                     Declarator decl;
+                     OldList * specs = MkList();
+                     if(arrayExp.list)
+                     {
+                        Expression e;
+
+                        builtinCount = arrayExp.list->count;
+                        type = ProcessTypeString(typeString, false);
+                        while((e = arrayExp.list->first))
+                        {
+                           arrayExp.list->Remove(e);
+                           e.destType = type;
+                           type.refCount++;
+                           ProcessExpressionType(e);
+                           if(inCompiler)
+                              ListAdd(initializers, MkInitializerAssignment(e));
+                        }
+                        FreeType(type);
+                        delete arrayExp.list;
+                     }
+                     decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
+
+                     stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier),
+                        MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
 
-                     builtinCount = arrayExp.list->count;
+                     ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(
+                        PlugDeclarator(
+                           /*CopyDeclarator(*/decl/*)*/, MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), null)
+                           ), MkInitializerList(initializers)))));
+                     FreeList(exp, FreeExpression);
+                  }
+                  else if(arrayExp.list)
+                  {
+                     Expression e;
                      type = ProcessTypeString(typeString, false);
-                     while(e = arrayExp.list->first)
+                     for(e = arrayExp.list->first; e; e = e.next)
                      {
-                        arrayExp.list->Remove(e);
                         e.destType = type;
                         type.refCount++;
                         ProcessExpressionType(e);
-                        ListAdd(initializers, MkInitializerAssignment(e));
                      }
                      FreeType(type);
-                     delete arrayExp.list;
                   }
-                  decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
-                  stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier),
-                     MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
-
-                  ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(
-                     PlugDeclarator(
-                        /*CopyDeclarator(*/decl/*)*/, MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__internalArray")), null)
-                        ), MkInitializerList(initializers)))));
-                  FreeList(exp, FreeExpression);
                }
                else
                {
@@ -11367,7 +12469,7 @@ static void ProcessStatement(Statement stmt)
                      MkInitializerAssignment(MkExpBrackets(exp))))));
                */
             }
-            else if(isLinkList && !isList)
+            else if(inCompiler && isLinkList && !isList)
             {
                Declarator decl;
                OldList * specs = MkList();
@@ -11387,7 +12489,7 @@ static void ProcessStatement(Statement stmt)
                   MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")),
                      MkInitializerAssignment(MkExpBrackets(exp))))));
             }*/
-            else if(_class.templateArgs)
+            else if(inCompiler && _class.templateArgs)
             {
                if(isMap)
                   sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
@@ -11399,159 +12501,166 @@ static void ProcessStatement(Statement stmt)
                   MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null,
                   MkInitializerAssignment(MkExpBrackets(exp)))))))));
             }
-            symbol = FindSymbol(id.string, curContext, curContext, false, false);
-
-            if(block)
+            if(inCompiler)
             {
-               // Reparent sub-contexts in this statement
-               switch(block.type)
+               symbol = FindSymbol(id.string, curContext, curContext, false, false);
+
+               if(block)
                {
-                  case compoundStmt:
-                     if(block.compound.context)
-                        block.compound.context.parent = stmt.compound.context;
-                     break;
-                  case ifStmt:
-                     if(block.ifStmt.stmt && block.ifStmt.stmt.type == compoundStmt && block.ifStmt.stmt.compound.context)
-                        block.ifStmt.stmt.compound.context.parent = stmt.compound.context;
-                     if(block.ifStmt.elseStmt && block.ifStmt.elseStmt.type == compoundStmt && block.ifStmt.elseStmt.compound.context)
-                        block.ifStmt.elseStmt.compound.context.parent = stmt.compound.context;
-                     break;
-                  case switchStmt:
-                     if(block.switchStmt.stmt && block.switchStmt.stmt.type == compoundStmt && block.switchStmt.stmt.compound.context)
-                        block.switchStmt.stmt.compound.context.parent = stmt.compound.context;
-                     break;
-                  case whileStmt:
-                     if(block.whileStmt.stmt && block.whileStmt.stmt.type == compoundStmt && block.whileStmt.stmt.compound.context)
-                        block.whileStmt.stmt.compound.context.parent = stmt.compound.context;
-                     break;
-                  case doWhileStmt:
-                     if(block.doWhile.stmt && block.doWhile.stmt.type == compoundStmt && block.doWhile.stmt.compound.context)
-                        block.doWhile.stmt.compound.context.parent = stmt.compound.context;
-                     break;
-                  case forStmt:
-                     if(block.forStmt.stmt && block.forStmt.stmt.type == compoundStmt && block.forStmt.stmt.compound.context)
-                        block.forStmt.stmt.compound.context.parent = stmt.compound.context;
-                     break;
-                  case forEachStmt:
-                     if(block.forEachStmt.stmt && block.forEachStmt.stmt.type == compoundStmt && block.forEachStmt.stmt.compound.context)
-                        block.forEachStmt.stmt.compound.context.parent = stmt.compound.context;
-                     break;
-                  /* Only handle those with compound blocks for now... (Potential limitation on compound statements within expressions)
-                  case labeledStmt:
-                  case caseStmt
-                  case expressionStmt:
-                  case gotoStmt:
-                  case continueStmt:
-                  case breakStmt
-                  case returnStmt:
-                  case asmStmt:
-                  case badDeclarationStmt:
-                  case fireWatchersStmt:
-                  case stopWatchingStmt:
-                  case watchStmt:
-                  */
+                  // Reparent sub-contexts in this statement
+                  switch(block.type)
+                  {
+                     case compoundStmt:
+                        if(block.compound.context)
+                           block.compound.context.parent = stmt.compound.context;
+                        break;
+                     case ifStmt:
+                        if(block.ifStmt.stmt && block.ifStmt.stmt.type == compoundStmt && block.ifStmt.stmt.compound.context)
+                           block.ifStmt.stmt.compound.context.parent = stmt.compound.context;
+                        if(block.ifStmt.elseStmt && block.ifStmt.elseStmt.type == compoundStmt && block.ifStmt.elseStmt.compound.context)
+                           block.ifStmt.elseStmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case switchStmt:
+                        if(block.switchStmt.stmt && block.switchStmt.stmt.type == compoundStmt && block.switchStmt.stmt.compound.context)
+                           block.switchStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case whileStmt:
+                        if(block.whileStmt.stmt && block.whileStmt.stmt.type == compoundStmt && block.whileStmt.stmt.compound.context)
+                           block.whileStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case doWhileStmt:
+                        if(block.doWhile.stmt && block.doWhile.stmt.type == compoundStmt && block.doWhile.stmt.compound.context)
+                           block.doWhile.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case forStmt:
+                        if(block.forStmt.stmt && block.forStmt.stmt.type == compoundStmt && block.forStmt.stmt.compound.context)
+                           block.forStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     case forEachStmt:
+                        if(block.forEachStmt.stmt && block.forEachStmt.stmt.type == compoundStmt && block.forEachStmt.stmt.compound.context)
+                           block.forEachStmt.stmt.compound.context.parent = stmt.compound.context;
+                        break;
+                     /* Only handle those with compound blocks for now... (Potential limitation on compound statements within expressions)
+                     case labeledStmt:
+                     case caseStmt
+                     case expressionStmt:
+                     case gotoStmt:
+                     case continueStmt:
+                     case breakStmt
+                     case returnStmt:
+                     case asmStmt:
+                     case badDeclarationStmt:
+                     case fireWatchersStmt:
+                     case stopWatchingStmt:
+                     case watchStmt:
+                     */
+                  }
                }
-            }
-            if(filter)
-            {
-               block = MkIfStmt(filter, block, null);
-            }
-            if(isArray)
-            {
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
-                     MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
-                  block));
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-              ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }
-            else if(isBuiltin)
-            {
-               char count[128];
-               //OldList * specs = MkList();
-               // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
 
-               sprintf(count, "%d", builtinCount);
+               if(filter)
+               {
+                  block = MkIfStmt(filter, block, null);
+               }
+               if(isArray)
+               {
+                  stmt.compound.statements = MkListOne(MkForStmt(
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
+                        MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
+                     block));
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
+               }
+               else if(isBuiltin)
+               {
+                  char count[128];
+                  //OldList * specs = MkList();
+                  // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
+
+                  sprintf(count, "%d", builtinCount);
 
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
-                     MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
-                  block));
+                  stmt.compound.statements = MkListOne(MkForStmt(
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
+                        MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
+                     block));
 
-               /*
-               Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
-                     MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
-                  block));
-              */
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-              ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-              ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }
-            else if(isLinkList && !isList)
-            {
-               Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
-               Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
-               if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString &&
-                  !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
-               {
+                  /*
+                  Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
                   stmt.compound.statements = MkListOne(MkForStmt(
-                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
-                     MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
-                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
+                        MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
                      block));
+                 */
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
                }
-               else
+               else if(isLinkList && !isList)
+               {
+                  Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
+                  Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
+                  if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString &&
+                     !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
+                  {
+                     stmt.compound.statements = MkListOne(MkForStmt(
+                        MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
+                        MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
+                        MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
+                        block));
+                  }
+                  else
+                  {
+                     OldList * specs = MkList();
+                     Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
+                     stmt.compound.statements = MkListOne(MkForStmt(
+                        MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
+                        MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
+                        MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
+                           MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
+                              MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
+                        block));
+                  }
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                  ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
+               }
+               /*else if(isCustomAVLTree)
                {
-                  OldList * specs = MkList();
-                  Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
                   stmt.compound.statements = MkListOne(MkForStmt(
-                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
+                     MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
+                        MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
                      MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
-                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
-                        MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
-                           MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
+                     MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
                      block));
-               }
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }
-            /*else if(isCustomAVLTree)
-            {
-               stmt.compound.statements = MkListOne(MkForStmt(
-                  MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
-                     MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
-                  MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
-                  MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
-                  block));
 
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
-               ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
-               ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
-            }*/
-            else
-            {
-               stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
-                  MkIdentifier("Next")), null)), block));
-            }
-            ProcessExpressionType(expIt);
-            if(stmt.compound.declarations->first)
-               ProcessDeclaration(stmt.compound.declarations->first);
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
+                  ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
+                  ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
+               }*/
+               else
+               {
+                  stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
+                     MkIdentifier("Next")), null)), block));
+               }
+               ProcessExpressionType(expIt);
+               if(stmt.compound.declarations->first)
+                  ProcessDeclaration(stmt.compound.declarations->first, true);
 
-            if(symbol)
-               symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
+               if(symbol)
+                  symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
 
-            ProcessStatement(stmt);
-            curContext = stmt.compound.context.parent;
+               ProcessStatement(stmt);
+            }
+            else
+               ProcessStatement(stmt.forEachStmt.stmt);
+            if(inCompiler)
+               curContext = stmt.compound.context.parent;
             break;
          }
          else
@@ -11579,6 +12688,7 @@ static void ProcessStatement(Statement stmt)
                      curFunction.type = ProcessType(
                         curFunction.specifiers, curFunction.declarator);
                   FreeType(exp.destType);
+                  // TODO: current property if not compiling
                   exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
                   if(exp.destType) exp.destType.refCount++;
                }
@@ -11589,7 +12699,7 @@ static void ProcessStatement(Statement stmt)
       }
       case badDeclarationStmt:
       {
-         ProcessDeclaration(stmt.decl);
+         ProcessDeclaration(stmt.decl, true);
          break;
       }
       case asmStmt:
@@ -11638,8 +12748,6 @@ static void ProcessStatement(Statement stmt)
                stmt.type = expressionStmt;
                stmt.expressions = MkList();
 
-               curExternal = external.prev;
-
                for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
                {
                   ClassFunction func;
@@ -11648,10 +12756,6 @@ static void ProcessStatement(Statement stmt)
                      ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
                   External createdExternal;
 
-                  // Create a declaration above
-                  External externalDecl = MkExternalDeclaration(null);
-                  ast->Insert(curExternal.prev, externalDecl);
-
                   sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
                   if(propWatch.deleteWatch)
                      strcat(watcherName, "_delete");
@@ -11667,33 +12771,18 @@ static void ProcessStatement(Statement stmt)
 
                   if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
                   {
-                     // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
                      func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
-                        //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
                         MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
                      ProcessClassFunctionBody(func, propWatch.compound);
                      propWatch.compound = null;
 
-                     //afterExternal = afterExternal ? afterExternal : curExternal;
-
-                     //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
                      createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
-                     // TESTING THIS...
-                     createdExternal.symbol.idCode = external.symbol.idCode;
+
+                     FreeClassFunction(func);
 
                      curExternal = createdExternal;
                      ProcessFunction(createdExternal.function);
 
-
-                     // Create a declaration above
-                     {
-                        Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier),
-                           MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
-                        externalDecl.declaration = decl;
-                        if(decl.symbol && !decl.symbol.pointerExternal)
-                           decl.symbol.pointerExternal = externalDecl;
-                     }
-
                      if(propWatch.deleteWatch)
                      {
                         OldList * args = MkList();
@@ -11716,24 +12805,25 @@ static void ProcessStatement(Statement stmt)
                               char getName[1024], setName[1024];
                               OldList * args = MkList();
 
-                              DeclareProperty(prop, setName, getName);
+                              DeclareProperty(createdExternal, prop, setName, getName);
 
                               // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
                               strcpy(propName, "__ecereProp_");
                               FullClassNameCat(propName, prop._class.fullName, false);
                               strcat(propName, "_");
-                              // strcat(propName, prop.name);
                               FullClassNameCat(propName, prop.name, true);
 
                               ListAdd(args, CopyExpression(object));
                               ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
                               ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
-                              ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
+                              ListAdd(args, MkExpCast(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpIdentifier(MkIdentifier(watcherName))));
 
                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
+
+                              external.CreateUniqueEdge(createdExternal, true);
                            }
                            else
-                              Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
+                              Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
                         }
                      }
                   }
@@ -11751,7 +12841,7 @@ static void ProcessStatement(Statement stmt)
                FreeList(watches, FreePropertyWatch);
             }
             else
-               Compiler_Error($"No observer specified and not inside a _class\n");
+               Compiler_Error($"No observer specified and not inside a class\n");
          }
          else
          {
@@ -11878,15 +12968,13 @@ static void ProcessStatement(Statement stmt)
                            char getName[1024], setName[1024];
                            OldList * args = MkList();
 
-                           DeclareProperty(prop, setName, getName);
+                           DeclareProperty(curExternal, prop, setName, getName);
 
                            // eInstance_StopWatching(object, prop, watcher);
                            strcpy(propName, "__ecereProp_");
                            FullClassNameCat(propName, prop._class.fullName, false);
                            strcat(propName, "_");
-                           // strcat(propName, prop.name);
                            FullClassNameCat(propName, prop.name, true);
-                           MangleClassName(propName);
 
                            ListAdd(args, CopyExpression(object));
                            ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
@@ -11894,7 +12982,7 @@ static void ProcessStatement(Statement stmt)
                            ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
                         }
                         else
-                           Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
+                           Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
                      }
                   }
 
@@ -11974,14 +13062,10 @@ static void ProcessFunction(FunctionDefinition function)
          strcpy(className, "__ecereClass_");
          FullClassNameCat(className, _class.fullName, true);
 
-         MangleClassName(className);
-
          structName[0] = 0;
          FullClassNameCat(structName, _class.fullName, false);
 
          // [class] this
-
-
          funcDecl = GetFuncDecl(function.declarator);
          if(funcDecl)
          {
@@ -11995,13 +13079,9 @@ static void ProcessFunction(FunctionDefinition function)
                }
             }
 
-            // DANGER: Watch for this... Check if it's a Conversion?
-            // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
-
-            // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
             if(!function.propertyNoThis)
             {
-               TypeName thisParam;
+               TypeName thisParam = null;
 
                if(type.classObjectType != classPointer)
                {
@@ -12024,6 +13104,7 @@ static void ProcessFunction(FunctionDefinition function)
                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
                   };
+                  DeclareStruct(curExternal, "ecere::com::Class", false, true);
                   funcDecl.function.parameters->Insert(null, thisParam);
                }
             }
@@ -12047,7 +13128,6 @@ static void ProcessFunction(FunctionDefinition function)
 
                if(type.classObjectType != classPointer)
                {
-                  // DANGER: Watch for this... Check if it's a Conversion?
                   if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
                   {
                      TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
@@ -12069,7 +13149,7 @@ static void ProcessFunction(FunctionDefinition function)
             thisSymbol = Symbol
             {
                string = CopyString("this");
-               type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
+               type = classSym ? MkClassType(classSym.string) : null;
             };
             function.body.compound.context.symbols.Add((BTNode)thisSymbol);
 
@@ -12078,17 +13158,12 @@ static void ProcessFunction(FunctionDefinition function)
                thisSymbol.type.classObjectType = ClassObjectType::typedObject;
                thisSymbol.type.byReference = type.byReference;
                thisSymbol.type.typedByReference = type.byReference;
-               /*
-               thisSymbol = Symbol { string = CopyString("class") };
-               function.body.compound.context.symbols.Add(thisSymbol);
-               */
             }
          }
       }
 
       // Pointer to class data
-
-      if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
+      if(inCompiler && _class && _class.type == normalClass && type.classObjectType != classPointer)
       {
          DataMember member = null;
          {
@@ -12119,10 +13194,8 @@ static void ProcessFunction(FunctionDefinition function)
                char className[1024];
                strcpy(className, "__ecereClass_");
                FullClassNameCat(className, classSym.string, true);
-               MangleClassName(className);
 
-               // Testing This
-               DeclareClass(classSym, className);
+               DeclareClass(curExternal, classSym, className);
             }
 
             // ((byte *) this)
@@ -12130,9 +13203,19 @@ static void ProcessFunction(FunctionDefinition function)
 
             if(_class.fixed)
             {
-               char string[256];
-               sprintf(string, "%d", _class.offset);
-               exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
+               Expression e;
+               if(_class.offset && _class.offset == (_class.base.type == noHeadClass ? _class.base.memberOffset : _class.base.structSize))
+               {
+                  e = MkExpClassSize(MkSpecifierName(_class.base.fullName));
+                  ProcessExpressionType(e);
+               }
+               else
+               {
+                  char string[256];
+                  sprintf(string, "%d", _class.offset);  // Need Bootstrap Fix
+                  e = MkExpConstant(string);
+               }
+               exp = QBrackets(MkExpOp(bytePtr, '+', e));
             }
             else
             {
@@ -12163,10 +13246,12 @@ static void ProcessFunction(FunctionDefinition function)
 
                {
                   Context prevContext = curContext;
+                  OldList * list;
                   curContext = function.body.compound.context;
 
-                  decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
+                  decl = MkDeclaration((list = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null))),
                      MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
+                  list->Insert(null, MkSpecifierExtended(MkExtDeclAttrib(MkAttrib(ATTRIB, MkListOne(MkAttribute(CopyString("unused"), null))))));
 
                   curContext = prevContext;
                }
@@ -12236,7 +13321,7 @@ static void ProcessFunction(FunctionDefinition function)
 
    if(function.declarator)
    {
-      ProcessDeclarator(function.declarator);
+      ProcessDeclarator(function.declarator, true);
    }
 
    topContext = oldTopContext;
@@ -12275,7 +13360,7 @@ static void ProcessClass(OldList definitions, Symbol symbol)
          {
             Class backThisClass = thisClass;
             if(regClass) thisClass = regClass;
-            ProcessDeclaration(def.decl);
+            ProcessDeclaration(def.decl, symbol ? true : false);
             thisClass = backThisClass;
          }
       }
@@ -12306,11 +13391,6 @@ static void ProcessClass(OldList definitions, Symbol symbol)
          PropertyDef prop = def.propertyDef;
 
          // Add this to the context
-         /*
-         Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
-         globalContext.symbols.Add(thisSymbol);
-         */
-
          thisClass = regClass;
          if(prop.setStmt)
          {
@@ -12359,11 +13439,6 @@ static void ProcessClass(OldList definitions, Symbol symbol)
          }
 
          thisClass = null;
-
-         /*
-         globalContext.symbols.Remove(thisSymbol);
-         FreeSymbol(thisSymbol);
-         */
       }
       else if(def.type == propertyWatchClassDef && def.propertyWatch)
       {
@@ -12388,7 +13463,7 @@ static void ProcessClass(OldList definitions, Symbol symbol)
    }
 }
 
-void DeclareFunctionUtil(String s)
+void DeclareFunctionUtil(External neededBy, const String s)
 {
    GlobalFunction function = eSystem_FindFunction(privateModule, s);
    if(function)
@@ -12398,92 +13473,81 @@ void DeclareFunctionUtil(String s)
       if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
          strcpy(name, "__ecereFunction_");
       FullClassNameCat(name, s, false); // Why is this using FullClassNameCat ?
-      DeclareFunction(function, name);
+      DeclareFunction(neededBy, function, name);
    }
+   else if(neededBy)
+      FindSymbol(s, globalContext, globalContext, false, false);
 }
 
+bool reachedPass15;
+
 void ComputeDataTypes()
 {
    External external;
-   External temp { };
-   External after = null;
 
    currentClass = null;
 
    containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
 
-   for(external = ast->first; external; external = external.next)
-   {
-      if(external.type == declarationExternal)
-      {
-         Declaration decl = external.declaration;
-         if(decl)
-         {
-            OldList * decls = decl.declarators;
-            if(decls)
-            {
-               InitDeclarator initDecl = decls->first;
-               if(initDecl)
-               {
-                  Declarator declarator = initDecl.declarator;
-                  if(declarator && declarator.type == identifierDeclarator)
-                  {
-                     Identifier id = declarator.identifier;
-                     if(id && id.string)
-                     {
-                        if(!strcmp(id.string, "uintptr_t") || !strcmp(id.string, "intptr_t") || !strcmp(id.string, "size_t") || !strcmp(id.string, "ssize_t"))
-                        {
-                           external.symbol.id = -1001, external.symbol.idCode = -1001;
-                           after = external;
-                        }
-                     }
-                  }
-               }
-            }
-         }
-       }
-   }
-
-   temp.symbol = Symbol { id = -1000, idCode = -1000 };
-   ast->Insert(after, temp);
-   curExternal = temp;
-
-   DeclareFunctionUtil("eSystem_New");
-   DeclareFunctionUtil("eSystem_New0");
-   DeclareFunctionUtil("eSystem_Renew");
-   DeclareFunctionUtil("eSystem_Renew0");
-   DeclareFunctionUtil("eSystem_Delete");
-   DeclareFunctionUtil("eClass_GetProperty");
-   DeclareFunctionUtil("eInstance_FireSelfWatchers");
-
-   DeclareStruct("ecere::com::Class", false);
-   DeclareStruct("ecere::com::Instance", false);
-   DeclareStruct("ecere::com::Property", false);
-   DeclareStruct("ecere::com::DataMember", false);
-   DeclareStruct("ecere::com::Method", false);
-   DeclareStruct("ecere::com::SerialBuffer", false);
-   DeclareStruct("ecere::com::ClassTemplateArgument", false);
-
-   ast->Remove(temp);
+   DeclareStruct(null, "ecere::com::Class", false, true);
+   DeclareStruct(null, "ecere::com::Instance", false, true);
+   DeclareStruct(null, "ecere::com::Property", false, true);
+   DeclareStruct(null, "ecere::com::DataMember", false, true);
+   DeclareStruct(null, "ecere::com::Method", false, true);
+   DeclareStruct(null, "ecere::com::SerialBuffer", false, true);
+   DeclareStruct(null, "ecere::com::ClassTemplateArgument", false, true);
+
+   DeclareFunctionUtil(null, "eSystem_New");
+   DeclareFunctionUtil(null, "eSystem_New0");
+   DeclareFunctionUtil(null, "eSystem_Renew");
+   DeclareFunctionUtil(null, "eSystem_Renew0");
+   DeclareFunctionUtil(null, "eSystem_Delete");
+   DeclareFunctionUtil(null, "eClass_GetProperty");
+   DeclareFunctionUtil(null, "eClass_SetProperty");
+   DeclareFunctionUtil(null, "eInstance_FireSelfWatchers");
+   DeclareFunctionUtil(null, "eInstance_SetMethod");
+   DeclareFunctionUtil(null, "eInstance_IncRef");
+   DeclareFunctionUtil(null, "eInstance_StopWatching");
+   DeclareFunctionUtil(null, "eInstance_Watch");
+   DeclareFunctionUtil(null, "eInstance_FireWatchers");
+   reachedPass15 = true;
 
    for(external = ast->first; external; external = external.next)
    {
       afterExternal = curExternal = external;
       if(external.type == functionExternal)
       {
+         if(memoryGuard)
+         {
+            DeclareFunctionUtil(external, "MemoryGuard_PushLoc");
+            DeclareFunctionUtil(external, "MemoryGuard_PopLoc");
+         }
+
          currentClass = external.function._class;
          ProcessFunction(external.function);
       }
       // There shouldn't be any _class member access here anyways...
       else if(external.type == declarationExternal)
       {
+         if(memoryGuard && external.declaration && external.declaration.type == instDeclaration)
+         {
+            DeclareFunctionUtil(external, "MemoryGuard_PushLoc");
+            DeclareFunctionUtil(external, "MemoryGuard_PopLoc");
+         }
+
          currentClass = null;
-         ProcessDeclaration(external.declaration);
+         if(external.declaration)
+            ProcessDeclaration(external.declaration, true);
       }
       else if(external.type == classExternal)
       {
          ClassDefinition _class = external._class;
          currentClass = external.symbol.registered;
+         if(memoryGuard)
+         {
+            DeclareFunctionUtil(external, "MemoryGuard_PushLoc");
+            DeclareFunctionUtil(external, "MemoryGuard_PopLoc");
+         }
          if(_class.definitions)
          {
             ProcessClass(_class.definitions, _class.symbol);
@@ -12502,7 +13566,5 @@ void ComputeDataTypes()
    }
    currentClass = null;
    thisNameSpace = null;
-
-   delete temp.symbol;
-   delete temp;
+   curExternal = null;
 }