X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=compiler%2Flibec%2Fsrc%2Fpass15.ec;h=4d4d489e0c9bea0e9c6f452a1daa5ea817fde1b3;hb=a5e9fe141ccca04d9c83c20f71d20e0663b62802;hp=090ac7ab3b8581e6e08b7e7a6fe51ccf27b7557e;hpb=3f3c5e72d6b5e4bcd1f6e5a57ce2a5e18bb30663;p=sdk diff --git a/compiler/libec/src/pass15.ec b/compiler/libec/src/pass15.ec index 090ac7a..4d4d489 100644 --- a/compiler/libec/src/pass15.ec +++ b/compiler/libec/src/pass15.ec @@ -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; } @@ -666,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; @@ -690,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; // ---------------------- @@ -1155,7 +1158,6 @@ External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, b External external = null; Symbol classSym = FindClass(name); OldList * curDeclarations = null; - Specifier curSpec = null; if(!inCompiler || !classSym) return null; @@ -1175,7 +1177,6 @@ External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, b 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; } @@ -1187,16 +1188,15 @@ External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, b OldList * declarations = null; char structName[1024]; bool addedPadding = false; + Specifier curSpec = null; classSym.declaring++; if(strchr(classSym.string, '<')) { if(classSym.registered.templateClass) - { external = _DeclareStruct(neededBy, classSym.registered.templateClass.fullName, skipNoHead, needDereference, fwdDecl); - classSym.declaring--; - } + classSym.declaring--; return external; } @@ -1222,6 +1222,18 @@ External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, b AddMembers(external, declarations, classSym.registered, false, null, classSym.registered, &addedPadding); } + 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 && (!declarations->count || (declarations->count == 1 && addedPadding))) { FreeList(declarations, FreeClassDef); @@ -1240,10 +1252,6 @@ External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, b curSpec.definitions = declarations; else { - char className[1024]; - strcpy(className, "__ecereClass_"); - FullClassNameCat(className, classSym.string, true); - specifiers = MkList(); declarators = MkList(); ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations)); @@ -1280,6 +1288,18 @@ External _DeclareStruct(External neededBy, const char * name, bool skipNoHead, b external.symbol = classSym; ast->Add(external); } + 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; @@ -2952,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)) { @@ -3501,13 +3523,14 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b Type source; Type realDest = dest; Type backupSourceExpType = null; - Expression computedExp = sourceExp; + 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(sourceExp); // Keep the original expression, but compute for checking enum ranges + computedExp = CopyExpression(nbExp); // Keep the original expression, but compute for checking enum ranges ComputeExpression(computedExp /*sourceExp*/); } @@ -3515,10 +3538,10 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b if(dest.kind == pointerType && sourceExp.type == constantExp && !strtoul(sourceExp.constant, null, 0)) { - if(computedExp != sourceExp) + if(computedExp != nbExp) { FreeExpression(computedExp); - computedExp = sourceExp; + computedExp = nbExp; } FreeType(dest); return true; @@ -3538,10 +3561,10 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b //if(source._class.registered == dest._class.registered) if(sourceBase == destBase) { - if(computedExp != sourceExp) + if(computedExp != nbExp) { FreeExpression(computedExp); - computedExp = sourceExp; + computedExp = nbExp; } FreeType(dest); return true; @@ -3564,17 +3587,17 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b else value = strtoull(computedExp.constant, null, 0); } - else if(computedExp.type == opExp && sourceExp.op.op == '-' && !computedExp.op.exp1 && computedExp.op.exp2 && computedExp.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(computedExp.op.exp2.constant, null, 0); else value = -strtoull(computedExp.op.exp2.constant, null, 0); } - if(computedExp != sourceExp) + if(computedExp != nbExp) { FreeExpression(computedExp); - computedExp = sourceExp; + computedExp = nbExp; } if(dest.kind != classType && source.kind == classType && source._class && source._class.registered && @@ -3918,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)) { @@ -3998,10 +4041,10 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b } else { - if(computedExp != sourceExp) + if(computedExp != nbExp) { FreeExpression(computedExp); - computedExp = sourceExp; + computedExp = nbExp; } while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last; @@ -4349,7 +4392,7 @@ public Operand GetOperand(Expression exp) 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) @@ -5682,6 +5725,14 @@ void ComputeExpression(Expression exp) 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); @@ -7725,6 +7776,13 @@ void ApplyLocation(Expression exp, Location loc) } } +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; @@ -7790,7 +7848,13 @@ 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*/) { @@ -7816,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) @@ -8209,6 +8275,8 @@ void ProcessExpressionType(Expression exp) 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 @@ -8255,6 +8323,7 @@ void ProcessExpressionType(Expression exp) // Gives boolean result boolResult = true; useSideType = true; + relationOp = true; break; case '+': case '-': @@ -8279,6 +8348,7 @@ void ProcessExpressionType(Expression exp) case '%': useSideType = true; useDestType = true; + if(exp.op.op == '/') powerOp = true; break; case '&': case '*': @@ -8287,6 +8357,7 @@ void ProcessExpressionType(Expression exp) // 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; @@ -8344,6 +8415,17 @@ 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... @@ -8352,6 +8434,7 @@ void ProcessExpressionType(Expression exp) 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 && @@ -8370,7 +8453,7 @@ void ProcessExpressionType(Expression exp) if(exp.op.exp2) { - if(exp.op.exp1.expType && (exp.op.exp1.expType.kind == charType || exp.op.exp1.expType.kind == shortType)) + 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); @@ -8455,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) @@ -8483,11 +8570,19 @@ void ProcessExpressionType(Expression exp) 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(exp.op.exp1 || exp.op.op == '~') + 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)) { @@ -8558,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; @@ -8589,6 +8702,11 @@ void ProcessExpressionType(Expression exp) } 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) @@ -8618,11 +8736,33 @@ void ProcessExpressionType(Expression exp) 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"))))) { @@ -8631,18 +8771,9 @@ void ProcessExpressionType(Expression exp) ((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String")))) { // Added this check for enum subtraction to result in an int type: - if(exp.op.op == '-' && - ((type1.kind == classType && type1._class.registered && type1._class.registered.type == enumClass) || - (type2.kind == classType && type2._class.registered && type2._class.registered.type == enumClass)) ) + if(exp.op.op == '-' && ((c1 && c1.type == enumClass) || (c2 && c2.type == enumClass)) ) { - Type intType; - if(!type1._class.registered.dataType) - type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false); - if(!type2._class.registered.dataType) - type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false); - - intType = ProcessTypeString( - (type1._class.registered.dataType.kind == int64Type || type2._class.registered.dataType.kind == int64Type) ? "int64" : "int", false); + 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); @@ -8661,12 +8792,17 @@ void ProcessExpressionType(Expression exp) } // 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) { @@ -8691,7 +8827,7 @@ void ProcessExpressionType(Expression exp) { if(type2) FreeType(type2); - type2 = exp.op.exp2.expType = ProcessTypeString("int", false); + type2 = exp.op.exp2.expType = ProcessTypeString("int", false); c2 = null; type2.refCount++; } @@ -8824,7 +8960,7 @@ 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 @@ -8835,7 +8971,7 @@ void ProcessExpressionType(Expression exp) 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 @@ -8850,36 +8986,34 @@ 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, 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, false); type1 = exp.op.exp1.destType; + c1 = type1 && type1.kind == classType && type1._class ? type1._class.registered : null; exp.expType = type1; type1.refCount++; } @@ -8887,8 +9021,8 @@ void ProcessExpressionType(Expression exp) // TESTING THIS NEW CODE if(!boolResult || exp.op.op == '>' || exp.op.op == '<' || exp.op.op == GE_OP || exp.op.op == LE_OP) { - bool op1IsEnum = type1 && type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass; - bool op2IsEnum = type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass; + 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 == '^') { // Convert the enum to an int instead for these operators @@ -8941,8 +9075,7 @@ void ProcessExpressionType(Expression exp) if(!valid) { // Added this first part of the if here to handle 5 + Degrees { 5 } with either a base unit dest or not a unit dest type - if(type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass && - (type1.kind != classType || !type1._class || !type1._class.registered || type1._class.registered.type != unitClass)) + if(c2 && c2.type == unitClass && (!c1 || c1.type != unitClass)) { if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType); exp.op.exp1.destType = type2; @@ -9029,12 +9162,12 @@ void ProcessExpressionType(Expression exp) 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) + if(c1 && c1.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) + else if(c2 && c2.type == enumClass) { exp.expType = exp.op.exp2.expType; if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++; @@ -9046,7 +9179,7 @@ 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; @@ -9089,7 +9222,7 @@ 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 @@ -9111,7 +9244,7 @@ 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 @@ -9189,16 +9322,21 @@ void ProcessExpressionType(Expression exp) { 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;*/ } } ProcessExpressionType(e); + 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; @@ -11135,6 +11273,16 @@ void ProcessExpressionType(Expression exp) } } + // 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) ); else if(exp.destType && !exp.destType.keepCast) @@ -11213,6 +11361,9 @@ void ProcessExpressionType(Expression exp) 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; @@ -11256,9 +11407,9 @@ void ProcessExpressionType(Expression exp) case '-': if(!exp.destType.isSigned) { - Expression nbExp1 = GetNonBracketsExp(nbExp.op.exp1); - Expression nbExp2 = GetNonBracketsExp(nbExp.op.exp2); - TypeKind from = nbExp2.expType.promotedFrom; + 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) { @@ -11268,6 +11419,30 @@ void ProcessExpressionType(Expression exp) } } 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; + } } } @@ -11660,7 +11835,7 @@ static void ProcessDeclarator(Declarator decl, bool isFunction) qualifiers = MkListOne(MkSpecifier(VOID)); declarator = MkDeclaratorPointer(MkPointer(null,null), d); }; - if(d.type != pointerDeclarator) + if(!d || d.type != pointerDeclarator) newParam.qualifiers->Insert(null, MkSpecifier(CONST)); FreeList(param.qualifiers, FreeSpecifier); @@ -11681,7 +11856,7 @@ static void ProcessDeclarator(Declarator decl, bool isFunction) FreeList(param.qualifiers, FreeSpecifier); param.qualifiers = MkListOne(MkSpecifier(VOID)); - if(d.type != pointerDeclarator) + if(!d || d.type != pointerDeclarator) param.qualifiers->Insert(null, MkSpecifier(CONST)); param.declarator = MkDeclaratorPointer(MkPointer(null,null), d); break; @@ -11702,6 +11877,12 @@ static void ProcessDeclarator(Declarator decl, bool isFunction) { 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); + } } } @@ -13023,7 +13204,7 @@ static void ProcessFunction(FunctionDefinition function) if(_class.fixed) { Expression e; - if(_class.offset && _class.offset == _class.base.structSize) + if(_class.offset && _class.offset == (_class.base.type == noHeadClass ? _class.base.memberOffset : _class.base.structSize)) { e = MkExpClassSize(MkSpecifierName(_class.base.fullName)); ProcessExpressionType(e); @@ -13298,6 +13479,8 @@ void DeclareFunctionUtil(External neededBy, const String s) FindSymbol(s, globalContext, globalContext, false, false); } +bool reachedPass15; + void ComputeDataTypes() { External external; @@ -13327,6 +13510,7 @@ void ComputeDataTypes() DeclareFunctionUtil(null, "eInstance_StopWatching"); DeclareFunctionUtil(null, "eInstance_Watch"); DeclareFunctionUtil(null, "eInstance_FireWatchers"); + reachedPass15 = true; for(external = ast->first; external; external = external.next) {