sdk: const correctness
[sdk] / compiler / libec / src / pass15.ec
index 576dc78..95ced2a 100644 (file)
@@ -47,6 +47,8 @@ Time findSymbolTotalTime;
    {
       TempFile f { };
       int count;
+      bool backOutputLineNumbers = outputLineNumbers;
+      outputLineNumbers = false;
 
       if(exp)
          OutputExpression(exp, f);
@@ -55,6 +57,8 @@ Time findSymbolTotalTime;
       count += f.Read(string + count, 1, 1023);
       string[count] = '\0';
       delete f;
+
+      outputLineNumbers = backOutputLineNumbers;
    }
 }
 
@@ -101,7 +105,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; ????
       }
@@ -201,10 +205,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);
 }
 
@@ -241,9 +247,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 +305,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 +352,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,6 +372,11 @@ 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...
@@ -364,7 +406,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;
 
@@ -727,7 +768,14 @@ public int ComputeTypeSize(Type type)
             {
                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;
@@ -838,7 +886,8 @@ public int ComputeTypeSize(Type type)
    DataMember topMember = isMember ? (DataMember) _class : null;
    uint totalSize = 0;
    uint maxSize = 0;
-   int alignment, size;
+   int alignment;
+   uint size;
    DataMember member;
    Context context = isMember ? null : SetupTemplatesContext(_class);
    if(addedPadding)
@@ -964,7 +1013,6 @@ public int ComputeTypeSize(Type type)
 static int DeclareMembers(Class _class, bool isMember)
 {
    DataMember topMember = isMember ? (DataMember) _class : null;
-   uint totalSize = 0;
    DataMember member;
    Context context = isMember ? null : SetupTemplatesContext(_class);
 
@@ -1005,7 +1053,7 @@ static int DeclareMembers(Class _class, bool isMember)
    return topMember ? topMember.memberID : _class.memberID;
 }
 
-void DeclareStruct(char * name, bool skipNoHead)
+void DeclareStruct(const char * name, bool skipNoHead)
 {
    External external = null;
    Symbol classSym = FindClass(name);
@@ -1028,6 +1076,7 @@ void DeclareStruct(char * name, bool skipNoHead)
       OldList * specifiers, * declarators;
       OldList * declarations = null;
       char structName[1024];
+      Specifier spec = null;
       external = (classSym.registered && classSym.registered.type == structClass) ?
          classSym.pointerExternal : classSym.structExternal;
 
@@ -1052,10 +1101,19 @@ void DeclareStruct(char * name, bool skipNoHead)
       structName[0] = 0;
       FullClassNameCat(structName, name, false);
 
+      if(external && external.declaration && external.declaration.specifiers)
+      {
+         for(spec = external.declaration.specifiers->first; spec; spec = spec.next)
+         {
+            if(spec.type == structSpecifier || spec.type == unionSpecifier)
+               break;
+         }
+      }
+
       /*if(!external)
          external = MkExternalDeclaration(null);*/
 
-      if(!skipNoHead)
+      if(!skipNoHead && (!spec || !spec.definitions))
       {
          bool addedPadding = false;
          classSym.declaredStructSym = true;
@@ -1075,9 +1133,10 @@ void DeclareStruct(char * name, bool skipNoHead)
       }
       if(skipNoHead || declarations)
       {
-         if(external && external.declaration)
+         if(spec)
          {
-            ((Specifier)external.declaration.specifiers->first).definitions = declarations;
+            if(declarations)
+               spec.definitions = declarations;
 
             if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
             {
@@ -1254,7 +1313,9 @@ void DeclareProperty(Property prop, char * setName, char * getName)
                classSym._import.properties.Add(symbol._import);
          }
          imported = true;
-         if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
+         // 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;
       }
 
@@ -1673,8 +1734,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;
@@ -1839,7 +1908,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);
          }
@@ -2010,8 +2079,7 @@ void ProcessInstantiationType(Instantiation inst)
 
                   if(inCompiler)
                   {
-
-                     Type type = declarator.symbol.type;
+                     //Type type = declarator.symbol.type;
                      External oldExternal = curExternal;
 
                      // *** Commented this out... Any negative impact? Yes: makes double prototypes declarations... Why was it commented out?
@@ -2341,7 +2409,7 @@ public void ProcessPropertyType(Property prop)
    }
 }
 
-public void DeclareMethod(Method method, char * name)
+public void DeclareMethod(Method method, const char * name)
 {
    Symbol symbol = method.symbol;
    if(!symbol || (!symbol.pointerExternal && method.type == virtualMethod) || symbol.id > (curExternal ? curExternal.symbol.idCode : -1))
@@ -2414,7 +2482,7 @@ public void DeclareMethod(Method method, char * name)
          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;
          }
       }
@@ -2854,10 +2922,27 @@ 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)
+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 &&
+         ((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.type && (sourceType.kind == pointerType || sourceType.kind == arrayType)) sourceType = sourceType.type;
+            while(destType.type && (destType.kind == pointerType || destType.kind == arrayType)) destType = destType.type;
+            if(!destType.constant && sourceType.constant)
+               Compiler_Warning($"discarding const qualifier\n");
+         }
+      }
       // Property convert;
 
       if(source.kind == templateType && dest.kind != templateType)
@@ -2915,7 +3000,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)*/)
@@ -2982,7 +3066,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 +3085,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 +3107,48 @@ 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.refCount++;
+                        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(success)
+                        return true;
+                     if(constType)
+                        FreeType(constType);
                   }
                }
             }
@@ -3063,7 +3168,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 +3191,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 +3222,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 +3256,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,7 +3353,7 @@ 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;
@@ -3298,8 +3409,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,7 +3441,7 @@ 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))
+         if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false, warnConst))
             return true;
       }
    }
@@ -3361,7 +3472,7 @@ 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, true, false, false, false, false))
          {
             NamedLink value;
             Class enumClass = eSystem_FindClass(privateModule, "enum");
@@ -3455,14 +3566,33 @@ 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 computedExp = sourceExp;
+   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(sourceExp);        // 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 != sourceExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = sourceExp;
+      }
+      FreeType(dest);
       return true;
+   }
 
    if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
    {
@@ -3477,8 +3607,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 != sourceExp)
+            {
+               FreeExpression(computedExp);
+               computedExp = sourceExp;
+            }
+            FreeType(dest);
+            return true;
+         }
+      }
    }
 
    if(source)
@@ -3488,21 +3626,25 @@ 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 && sourceExp.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 != sourceExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = sourceExp;
       }
 
       if(dest.kind != classType && source.kind == classType && source._class && source._class.registered &&
@@ -3534,7 +3676,7 @@ 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;
@@ -3552,7 +3694,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 +3754,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,7 +3787,7 @@ 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)
@@ -3691,7 +3833,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 +3857,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)
@@ -3867,7 +4018,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          return false;
       }
 
-      if(!flag)
+      if(!flag && !sourceExp.opDestType)
       {
          Expression newExp { };
          *newExp = *sourceExp;
@@ -3906,6 +4057,12 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
    }
    else
    {
+      if(computedExp != sourceExp)
+      {
+         FreeExpression(computedExp);
+         computedExp = sourceExp;
+      }
+
       while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
       if(sourceExp.type == identifierExp)
       {
@@ -3945,6 +4102,7 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
                            sourceExp.constant = CopyString(constant);
                            //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
                         }
+                        FreeType(dest);
                         return true;
                      }
                   }
@@ -3954,8 +4112,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,13 +4137,13 @@ 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_DIVIDE(o, name, m, t, p) \
+#define BINARY_DIVIDEINT(o, name, m, t, p) \
    static bool name(Expression exp, Operand op1, Operand op2)   \
    {                                                              \
       t value2 = op2.m;                                           \
@@ -3992,6 +4154,17 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
       return true;                                                \
    }
 
+#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(op1.m o value2);             \
+      if(!exp.expType) \
+         { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
+      return true;                                                \
+   }
+
 #define UNARY(o, name, m, t, p) \
    static bool name(Expression exp, Operand op1)                \
    {                                                              \
@@ -4024,13 +4197,17 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
    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 +4221,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 +4260,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 +4332,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,6 +4354,55 @@ 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 { };
@@ -4190,17 +4417,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)exp.string;
+         op.kind = pointerType;
+         op.ops = uint64Ops;
+      }
+      else if(exp.isConstant && exp.type == constantExp)
       {
+         op.kind = type.kind;
+         op.type = exp.expType;
+
          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);
@@ -4243,12 +4480,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 +4516,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...
@@ -4303,7 +4550,7 @@ public Operand GetOperand(Expression exp)
    return op;
 }
 
-static void UnusedFunction()
+static __attribute__((unused)) void UnusedFunction()
 {
    int a;
    a.OnGetString(0,0,0);
@@ -4896,70 +5143,29 @@ void ComputeInstantiation(Expression exp)
                            {
                               BitMember bitMember = (BitMember) dataMember;
                               Type type;
-                              int part = 0;
-                              GetInt(value, &part);
+                              uint64 part;
                               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, (uint16 *)&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, (uint *)&v) : GetUInt(value, &v); part = (uint64)v; break; }
+                                 case int64Type:      { uint64 v; type.isSigned ? GetInt64(value, (uint64 *)&v) : GetUInt64(value, &v); part = (uint64)v; break; }
+                                 case intPtrType:     { uintptr v; type.isSigned ? GetIntPtr(value, (uintptr *)&v) : GetUIntPtr(value, &v); part = (uint64)v; break; }
+                                 case intSizeType:    { uintsize v; type.isSigned ? GetIntSize(value, (uintsize *)&v) : GetUIntSize(value, &v); part = (uint64)v; break; }
                               }
+                              bits |= part << bitMember.pos;
                            }
                         }
                      }
@@ -4992,6 +5198,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 = 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 ? GetOpIntPtr(op, &op.i64) : GetOpUIntPtr(op, &op.i64);
+         break;
+      case intSizeType:
+         if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+            result = isSigned ? GetOpIntSize(op, &op.ui64) : 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 +5294,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
@@ -5146,7 +5410,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 +5669,15 @@ void ComputeExpression(Expression exp)
             if(!n)
             {
                OldList * list = exp.list;
+               Expression prev = exp.prev;
+               Expression next = exp.next;
                ComputeExpression(e);
                //FreeExpContents(exp);
                FreeType(exp.expType);
                FreeType(exp.destType);
                *exp = *e;
+               exp.prev = prev;
+               exp.next = next;
                delete e;
                delete list;
             }
@@ -5518,7 +5825,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 +5840,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 +5875,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 +5893,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 +5903,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 +5927,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 +5987,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;
@@ -5695,7 +6019,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;
@@ -5819,127 +6143,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 +6328,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 +6339,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 +6354,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)
@@ -6096,7 +6450,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)
       {
@@ -6116,7 +6470,6 @@ void CheckTemplateTypes(Expression exp)
    if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
    {
       Expression newExp { };
-      Statement compound;
       Context context;
       *newExp = *exp;
       if(exp.destType) exp.destType.refCount++;
@@ -6265,7 +6618,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 +6648,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';
@@ -6344,7 +6697,7 @@ static Symbol FindWithNameSpace(BinaryTree tree, char * name)
 
 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();
@@ -7006,7 +7359,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
@@ -7241,6 +7594,73 @@ void ApplyAnyObjectLogic(Expression e)
    }
 }
 
+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)
+         {
+            Expression arg;
+            for(arg = exp.call.arguments->first; arg; arg = arg.next)
+               ApplyLocation(arg, loc);
+         }
+         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;
+   }
+}
+
 void ProcessExpressionType(Expression exp)
 {
    bool unresolved = false;
@@ -7304,7 +7724,7 @@ void ProcessExpressionType(Expression exp)
             // 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
                {
@@ -7350,7 +7770,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;
 
@@ -7440,7 +7863,7 @@ void ProcessExpressionType(Expression exp)
                         FreeIdentifier(id);
                         exp.type = bracketsExp;
                         exp.list = MkListOne(parsedExpression);
-                        parsedExpression.loc = yylloc;
+                        ApplyLocation(parsedExpression, yylloc);
                         ProcessExpressionType(exp);
                         definedExpStackPos--;
                         return;
@@ -7541,6 +7964,7 @@ void ProcessExpressionType(Expression exp)
          //_class = classSym ? classSym.registered : null;
 
          ProcessInstantiationType(exp.instance);
+
          exp.isConstant = exp.instance.isConstant;
 
          /*
@@ -7627,9 +8051,10 @@ 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"));
                   if(isSigned)
                   {
                      if(i64 < MININT)
@@ -7710,6 +8135,7 @@ 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;
 
          // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
          Type dummy
@@ -7760,19 +8186,32 @@ void ProcessExpressionType(Expression exp)
             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;
+               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;
                }
@@ -7808,21 +8247,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++;
             }
@@ -7835,9 +8275,20 @@ void ProcessExpressionType(Expression exp)
 
             // 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;
+
+            // 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);
@@ -7861,6 +8312,8 @@ void ProcessExpressionType(Expression exp)
                else
                {
                   exp.op.exp2.destType = exp.destType;
+                  if(!exp.op.exp1 || exp.op.op != '&')
+                     exp.op.exp2.opDestType = true;
                   if(exp.destType)
                      exp.destType.refCount++;
                }
@@ -7902,15 +8355,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.exp2.opDestType = true;
                if(exp.destType)
                   exp.destType.refCount++;
             }
@@ -7930,7 +8382,25 @@ 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;
+            }
             ProcessExpressionType(exp.op.exp2);
+            exp.op.exp2.opDestType = false;
             if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
 
             if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
@@ -8002,7 +8472,7 @@ void ProcessExpressionType(Expression exp)
             exp.expType = Type
             {
                refCount = 1;
-               kind = intType;
+               kind = intSizeType;
             };
             exp.isConstant = true;
          }
@@ -8027,7 +8497,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;
@@ -8040,7 +8510,7 @@ 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;
@@ -8058,12 +8528,36 @@ 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 == '-' &&
+                     ((type1.kind == classType && type1._class.registered && type1._class.registered.type == enumClass) ||
+                      (type2.kind == classType && type2._class.registered && type2._class.registered.type == enumClass)) )
+                  {
+                     Type intType;
+                     if(!type1._class.registered.dataType)
+                        type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
+                     if(!type2._class.registered.dataType)
+                        type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
+
+                     intType = ProcessTypeString(
+                        (type1._class.registered.dataType.kind == int64Type || type2._class.registered.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 &&
@@ -8143,7 +8637,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
                               {
@@ -8196,14 +8690,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;
@@ -8213,14 +8707,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;
@@ -8260,7 +8754,7 @@ void ProcessExpressionType(Expression exp)
                   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++;
                }
@@ -8271,7 +8765,7 @@ void ProcessExpressionType(Expression exp)
                   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++;
                }
@@ -8288,7 +8782,7 @@ void ProcessExpressionType(Expression exp)
                      exp.op.exp2.destType = type1._class.registered.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;
@@ -8307,43 +8801,88 @@ void ProcessExpressionType(Expression exp)
                      exp.op.exp1.destType = type2._class.registered.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;
                      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 = type1 && type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass;
+                     bool op2IsEnum = type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.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(type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass &&
+                        (type1.kind != classType || !type1._class || !type1._class.registered || type1._class.registered.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...
@@ -8385,43 +8924,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(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++;
+                           }
                         }
                      }
                   }
@@ -8433,7 +8973,7 @@ void ProcessExpressionType(Expression exp)
                   {
                      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;
@@ -8462,7 +9002,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;
@@ -8479,7 +9019,7 @@ void ProcessExpressionType(Expression exp)
                   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 == '!')
                {
@@ -8501,7 +9041,7 @@ void ProcessExpressionType(Expression exp)
                   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++;
@@ -8568,6 +9108,7 @@ void ProcessExpressionType(Expression exp)
             if(!e.next)
             {
                FreeType(e.destType);
+               e.opDestType = exp.opDestType;
                e.destType = exp.destType;
                if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
             }
@@ -8628,7 +9169,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;
                   }
                }
             }
@@ -9012,6 +9563,7 @@ void ProcessExpressionType(Expression exp)
                   }
                   if(curParam && _class.templateArgs[id].dataTypeString)
                   {
+                     bool constant = type.constant;
                      ClassTemplateArgument arg = _class.templateArgs[id];
                      {
                         Context context = SetupTemplatesContext(_class);
@@ -9021,6 +9573,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)
                      {
@@ -9458,28 +10019,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;
@@ -9617,7 +10189,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;
@@ -9660,10 +10233,19 @@ void ProcessExpressionType(Expression exp)
                      {
                         ClassTemplateArgument arg = tClass.templateArgs[id];
                         Context context = SetupTemplatesContext(tClass);
+                        bool constant = exp.expType.constant;
                         /*if(!arg.dataType)
                            arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
                         FreeType(exp.expType);
+
                         exp.expType = ProcessTypeString(arg.dataTypeString, false);
+                        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)
@@ -9678,6 +10260,14 @@ void ProcessExpressionType(Expression exp)
                            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)
@@ -9994,7 +10584,7 @@ void ProcessExpressionType(Expression exp)
          exp.expType = Type
          {
             refCount = 1;
-            kind = intType;
+            kind = intSizeType;
          };
          // exp.isConstant = true;
          break;
@@ -10006,7 +10596,7 @@ void ProcessExpressionType(Expression exp)
          exp.expType = Type
          {
             refCount = 1;
-            kind = intType;
+            kind = intSizeType;
          };
          exp.isConstant = true;
 
@@ -10021,7 +10611,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++;
@@ -10187,7 +10779,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))
@@ -10208,7 +10800,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;
@@ -10219,7 +10811,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;
@@ -10363,7 +10955,7 @@ void ProcessExpressionType(Expression exp)
    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(!CheckExpressionType(exp, exp.destType, false, !exp.destType.casted))
       {
          if(!exp.destType.count || unresolved)
          {
@@ -10424,7 +11016,7 @@ void ProcessExpressionType(Expression exp)
                   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")))
@@ -10779,6 +11371,8 @@ static void ProcessDeclarator(Declarator decl)
                            qualifiers = MkListOne(MkSpecifier(VOID));
                            declarator = MkDeclaratorPointer(MkPointer(null,null), d);
                         };
+                        if(d.type != pointerDeclarator)
+                           newParam.qualifiers->Insert(null, MkSpecifier(CONST));
 
                         FreeList(param.qualifiers, FreeSpecifier);
 
@@ -10795,6 +11389,8 @@ static void ProcessDeclarator(Declarator decl)
                         FreeList(param.qualifiers, FreeSpecifier);
 
                         param.qualifiers = MkListOne(MkSpecifier(VOID));
+                        if(d.type != pointerDeclarator)
+                           param.qualifiers->Insert(null, MkSpecifier(CONST));
                         param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);
                      }
                      else if(spec.specifier == THISCLASS)
@@ -11188,7 +11784,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)
@@ -11209,7 +11805,7 @@ 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");
@@ -11222,11 +11818,11 @@ static void ProcessStatement(Statement stmt)
             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;
@@ -11283,7 +11879,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;
@@ -11294,7 +11890,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;
@@ -11737,7 +12333,7 @@ static void ProcessStatement(Statement stmt)
                               ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), 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);
                         }
                      }
                   }
@@ -11898,7 +12494,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);
                      }
                   }
 
@@ -12392,7 +12988,7 @@ static void ProcessClass(OldList definitions, Symbol symbol)
    }
 }
 
-void DeclareFunctionUtil(String s)
+void DeclareFunctionUtil(const String s)
 {
    GlobalFunction function = eSystem_FindFunction(privateModule, s);
    if(function)
@@ -12458,7 +13054,13 @@ void ComputeDataTypes()
    DeclareFunctionUtil("eSystem_Renew0");
    DeclareFunctionUtil("eSystem_Delete");
    DeclareFunctionUtil("eClass_GetProperty");
+   DeclareFunctionUtil("eClass_SetProperty");
    DeclareFunctionUtil("eInstance_FireSelfWatchers");
+   DeclareFunctionUtil("eInstance_SetMethod");
+   DeclareFunctionUtil("eInstance_IncRef");
+   DeclareFunctionUtil("eInstance_StopWatching");
+   DeclareFunctionUtil("eInstance_Watch");
+   DeclareFunctionUtil("eInstance_FireWatchers");
 
    DeclareStruct("ecere::com::Class", false);
    DeclareStruct("ecere::com::Instance", false);
@@ -12482,7 +13084,8 @@ void ComputeDataTypes()
       else if(external.type == declarationExternal)
       {
          currentClass = null;
-         ProcessDeclaration(external.declaration);
+         if(external.declaration)
+            ProcessDeclaration(external.declaration);
       }
       else if(external.type == classExternal)
       {
@@ -12506,6 +13109,7 @@ void ComputeDataTypes()
    }
    currentClass = null;
    thisNameSpace = null;
+   curExternal = null;
 
    delete temp.symbol;
    delete temp;