compiler/libec: (#316) Added missing edge on opaque structs
[sdk] / compiler / libec / src / pass15.ec
index 090ac7a..6eaa2bb 100644 (file)
@@ -1155,7 +1155,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 +1174,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 +1185,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 +1219,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 +1249,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 +1285,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;
@@ -3501,13 +3518,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 +3533,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 +3556,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;
@@ -3571,10 +3589,10 @@ bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, b
          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 +3936,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 +4036,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;
@@ -8370,7 +8408,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);
@@ -8487,7 +8525,7 @@ void ProcessExpressionType(Expression exp)
             exp.op.exp2.opDestType = 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))
                {
@@ -11135,6 +11173,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 +11261,9 @@ void ProcessExpressionType(Expression exp)
                   Expression nbExp = GetNonBracketsExp(exp);
                   bool skipWarning = false;
                   TypeKind kind = exp.destType.kind;
+                  if(nbExp.type == conditionExp && !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 +11307,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 +11319,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 +11735,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 +11756,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 +11777,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);
+                        }
                      }
                   }
 
@@ -13298,6 +13379,8 @@ void DeclareFunctionUtil(External neededBy, const String s)
       FindSymbol(s, globalContext, globalContext, false, false);
 }
 
+bool reachedPass15;
+
 void ComputeDataTypes()
 {
    External external;
@@ -13327,6 +13410,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)
    {