// 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;
}
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;
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;
// ----------------------
External external = null;
Symbol classSym = FindClass(name);
OldList * curDeclarations = null;
- Specifier curSpec = null;
if(!inCompiler || !classSym) return null;
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;
}
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;
}
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);
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));
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;
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))
{
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*/);
}
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;
//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;
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 &&
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))
{
}
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;
{ \
t value2 = op2.m; \
exp.type = constantExp; \
- exp.string = p(value2 ? (op1.m o value2) : 0); \
+ 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; \
{ \
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; \
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)
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;
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;
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);
}
}
+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;
}
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*/)
{
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)
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
// Gives boolean result
boolResult = true;
useSideType = true;
+ relationOp = true;
break;
case '+':
case '-':
case LEFT_OP:
case RIGHT_OP:
- useSideType = true;
- useDestType = true;
+ // useSideType = true;
+ // useDestType = true;
break;
case '|':
case '%':
useSideType = true;
useDestType = true;
+ if(exp.op.op == '/') powerOp = true;
break;
case '&':
case '*':
// 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;
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--;
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 &&
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;
}
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)
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)
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;
}
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)
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")))))
{
((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);
}
// 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)
{
{
if(type2)
FreeType(type2);
- type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
+ type2 = exp.op.exp2.expType = ProcessTypeString("int", false); c2 = null;
type2.refCount++;
}
}
}
// 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.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
{
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++;
}
// 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
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;
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++;
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;
}
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
}
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
{
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;
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++;
}
}
}
+ // 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)
(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, true);
+ 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 || (!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);
+
+ // 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
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);
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;
{
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(_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);
FindSymbol(s, globalContext, globalContext, false, false);
}
+bool reachedPass15;
+
void ComputeDataTypes()
{
External external;
DeclareFunctionUtil(null, "eInstance_StopWatching");
DeclareFunctionUtil(null, "eInstance_Watch");
DeclareFunctionUtil(null, "eInstance_FireWatchers");
+ reachedPass15 = true;
for(external = ast->first; external; external = external.next)
{