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