* src/SDCCast.c (backPatchLabels): fixed bug #1408066: made it inifinitely recurseabl...
[fw/sdcc] / src / SDCCast.c
index 7f94a70067448bedbe5942d2928187fd42d6075c..285bf5e9b8d5d76f15fbe8474eacdd16cc60820d 100644 (file)
@@ -50,8 +50,8 @@ int labelKey = 1;
 int noLineno = 0;
 int noAlloc = 0;
 symbol *currFunc=NULL;
-static ast *createIval (ast *, sym_link *, initList *, ast *);
-static ast *createIvalCharPtr (ast *, sym_link *, ast *);
+static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
+static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
 static ast *optimizeCompare (ast *);
 ast *optimizeRRCRLC (ast *);
 ast *optimizeSWAP (ast *);
@@ -59,12 +59,12 @@ ast *optimizeGetHbit (ast *, RESULT_TYPE);
 ast *optimizeGetAbit (ast *, RESULT_TYPE);
 ast *optimizeGetByte (ast *, RESULT_TYPE);
 ast *optimizeGetWord (ast *, RESULT_TYPE);
-ast *backPatchLabels (ast *, symbol *, symbol *);
+static ast *backPatchLabels (ast *, symbol *, symbol *);
 void PA(ast *t);
 int inInitMode = 0;
 memmap *GcurMemmap=NULL;  /* points to the memmap that's currently active */
 FILE *codeOutFile;
-int 
+int
 ptt (ast * tree)
 {
   printTypeChain (tree->ftype, stdout);
@@ -589,23 +589,23 @@ funcOfType (char *name, sym_link * type, sym_link * argType,
 symbol *
 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
 {
-  
+
     symbol *sym;
     int i ;
     /* create the symbol */
     sym = newSymbol (name, 0);
-    
+
     /* setup return value */
     sym->type = newLink (DECLARATOR);
     DCL_TYPE (sym->type) = FUNCTION;
     sym->type->next = typeFromStr(rtype);
     sym->etype = getSpec (sym->type);
-    
+
     /* if arguments required */
     if (nArgs) {
         value *args;
         args = FUNC_ARGS(sym->type) = newValue ();
-        
+
         for ( i = 0 ; i < nArgs ; i++ ) {
             args->type = typeFromStr(atypes[i]);
             args->etype = getSpec (args->type);
@@ -647,7 +647,7 @@ reverseParms (ast * ptree)
           ttree->left = ptree->left;
           ptree->left = ttree;
         }
-    
+
       /* Now reverse */
       ttree = ptree->left;
       ptree->left = ptree->right;
@@ -673,7 +673,7 @@ processParms (ast *func,
 {
   RESULT_TYPE resultType;
   sym_link *functype;
-  
+
   /* if none of them exist */
   if (!defParm && !*actParm)
     return 0;
@@ -692,7 +692,7 @@ processParms (ast *func,
     functype = func->ftype->next;
   else
     functype = func->ftype;
-    
+
   /* if the function is being called via a pointer &   */
   /* it has not been defined a reentrant then we cannot */
   /* have parameters                                   */
@@ -776,7 +776,7 @@ processParms (ast *func,
       if (IS_INTEGRAL (ftype)
           && (getSize (ftype) < (unsigned) INTSIZE))
         {
-          newType = newAst_LINK(INTTYPE);  
+          newType = newAst_LINK(INTTYPE);
         }
 
       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
@@ -790,14 +790,14 @@ processParms (ast *func,
           newType = newAst_LINK (copyLinkChain (ftype));
           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
         }
-      
+
       if (newType)
         {
           /* cast required; change this op to a cast. */
           (*actParm)->decorated = 0;
            *actParm = newNode (CAST, newType, *actParm);
           (*actParm)->lineno = (*actParm)->right->lineno;
-          
+
           decorateType (*actParm, RESULT_TYPE_NONE);
         }
       return 0;
@@ -810,7 +810,7 @@ processParms (ast *func,
     return 0;
 
   resolveSymbols (*actParm);
-  
+
   /* the parameter type must be at least castable */
   if (compareType (defParm->type, (*actParm)->ftype) == 0)
     {
@@ -826,7 +826,7 @@ processParms (ast *func,
 
       resultType = getResultTypeFromType (defParm->etype);
       pTree = resolveSymbols (copyAst (*actParm));
-      
+
       /* now change the current one to a cast */
       (*actParm)->type = EX_OP;
       (*actParm)->opval.op = CAST;
@@ -864,7 +864,7 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
 /* createIvalStruct - generates initial value for structures       */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalStruct (ast * sym, sym_link * type, initList * ilist)
+createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
 {
   ast *rast = NULL;
   ast *lAst;
@@ -888,12 +888,15 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
       sflds->implicit = 1;
       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
       lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
-      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_TYPE_NONE);
+      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
+                                                       iloop, rast, rootValue)),
+                           RESULT_TYPE_NONE);
+
     }
 
   if (iloop) {
     werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
-              W_EXCESS_INITIALIZERS, "struct", 
+              W_EXCESS_INITIALIZERS, "struct",
               sym->opval.val->sym->name);
   }
 
@@ -905,7 +908,7 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
 /* createIvalArray - generates code for array initialization       */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalArray (ast * sym, sym_link * type, initList * ilist)
+createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
 {
   ast *rast = NULL;
   initList *iloop;
@@ -918,84 +921,88 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
   if (IS_CHAR (type->next))
     if ((rast = createIvalCharPtr (sym,
                                    type,
-                        decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE))))
+                        decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+                                   rootValue)))
 
       return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 
-    /* not the special case             */
-    if (ilist->type != INIT_DEEP)
-    {
-        werror (E_INIT_STRUCT, "");
-        return NULL;
-    }
+  /* not the special case             */
+  if (ilist->type != INIT_DEEP)
+  {
+      werror (E_INIT_STRUCT, "");
+      return NULL;
+  }
+
+  iloop = ilist->init.deep;
+  lcnt = DCL_ELEM (type);
 
-    iloop = ilist->init.deep;
-    lcnt = DCL_ELEM (type);
+  if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
+  {
+      ast *aSym;
 
-    if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
-    {
-        ast *aSym;
+      aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
 
-        aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
-        
-        rast = newNode(ARRAYINIT, aSym, NULL);
-        rast->values.constlist = literalL;
-        
-        // Make sure size is set to length of initializer list.
-        while (iloop)
-        {
-            size++;
-            iloop = iloop->next;
-        }
-        
-        if (lcnt && size > lcnt)
-        {
-            // Array size was specified, and we have more initializers than needed.
-            char *name=sym->opval.val->sym->name;
-            int lineno=sym->opval.val->sym->lineDef;
-            char *filename=sym->opval.val->sym->fileDef;
-            
-            werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
-        }
-    }
-    else
-    {
-        for (;;)
-        {
-            ast *aSym;
-            
-            aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
-            aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
-            rast = createIval (aSym, type->next, iloop, rast);
-            iloop = (iloop ? iloop->next : NULL);
-            if (!iloop)
-            {
-                break;
-            }
-            
-            /* no of elements given and we    */
-            /* have generated for all of them */
-            if (!--lcnt) 
-            {
-                // is this a better way? at least it won't crash
-                char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
-                int lineno = iloop->lineno;
-                char *filename = iloop->filename;
-                werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
-                
-                break;
-            }
-        }
-    }
+      rast = newNode(ARRAYINIT, aSym, NULL);
+      rast->values.constlist = literalL;
 
-    /* if we have not been given a size  */
-    if (!DCL_ELEM (type))
+      // Make sure size is set to length of initializer list.
+      while (iloop)
+      {
+          size++;
+          iloop = iloop->next;
+      }
+
+      if (lcnt && size > lcnt)
+      {
+          // Array size was specified, and we have more initializers than needed.
+          char *name=sym->opval.val->sym->name;
+          int lineno=sym->opval.val->sym->lineDef;
+          char *filename=sym->opval.val->sym->fileDef;
+
+          werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
+      }
+  }
+  else
+  {
+      for (;;)
+      {
+          ast *aSym;
+
+          aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
+          aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
+          rast = createIval (aSym, type->next, iloop, rast, rootValue);
+          iloop = (iloop ? iloop->next : NULL);
+          if (!iloop)
+          {
+              break;
+          }
+
+          /* no of elements given and we    */
+          /* have generated for all of them */
+          if (!--lcnt)
+          {
+              // is this a better way? at least it won't crash
+              char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+              int lineno = iloop->lineno;
+              char *filename = iloop->filename;
+              werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
+
+              break;
+          }
+      }
+  }
+
+  /* if we have not been given a size  */
+  if (!DCL_ELEM (type))
     {
-        /* but this still updates the typedef instead of the instance ! see bug 770487 */
+      /* check, if it's a flexible array */
+      if (IS_STRUCT (AST_VALUE (rootValue)->type))
+        AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
+      else
         DCL_ELEM (type) = size;
     }
 
-    return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
+  return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 }
 
 
@@ -1003,9 +1010,10 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
 /* createIvalCharPtr - generates initial values for char pointers  */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
+createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
 {
   ast *rast = NULL;
+  unsigned size = 0;
 
   /* if this is a pointer & right is a literal array then */
   /* just assignment will do                              */
@@ -1023,15 +1031,19 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       /* for each character generate an assignment */
       /* to the array element */
       char *s = SPEC_CVAL (iexpr->etype).v_char;
-      int i = 0;
-      int size = getSize (iexpr->ftype);
-      int symsize = getSize (type);
-      
-      if (size>symsize)
+      unsigned int i = 0;
+      unsigned int symsize = getSize (type);
+
+      size = getSize (iexpr->ftype);
+      if (symsize && size>symsize)
         {
           if (size>(symsize+1))
-            werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
-                      "string", sym->opval.val->sym->name);
+            {
+              char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+
+              werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+                        "string", name);
+            }
           size = symsize;
         }
 
@@ -1049,6 +1061,16 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       // now WE don't need iexpr's symbol anymore
       freeStringSymbol(AST_SYMBOL(iexpr));
 
+      /* if we have not been given a size  */
+      if (!DCL_ELEM (type))
+        {
+          /* check, if it's a flexible array */
+          if (IS_STRUCT (AST_VALUE (rootVal)->type))
+            AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
+          else
+            DCL_ELEM (type) = size;
+        }
+
       return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
     }
 
@@ -1059,7 +1081,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
 /* createIvalPtr - generates initial value for pointers            */
 /*-----------------------------------------------------------------*/
 static ast *
-createIvalPtr (ast * sym, sym_link * type, initList * ilist)
+createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
 {
   ast *rast;
   ast *iexpr;
@@ -1072,7 +1094,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist)
 
   /* if character pointer */
   if (IS_CHAR (type->next))
-    if ((rast = createIvalCharPtr (sym, type, iexpr)))
+    if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
       return rast;
 
   return newNode ('=', sym, iexpr);
@@ -1082,7 +1104,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist)
 /* createIval - generates code for initial value                   */
 /*-----------------------------------------------------------------*/
 static ast *
-createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
+createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
 {
   ast *rast = NULL;
 
@@ -1091,15 +1113,15 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
 
   /* if structure then    */
   if (IS_STRUCT (type))
-    rast = createIvalStruct (sym, type, ilist);
+    rast = createIvalStruct (sym, type, ilist, rootValue);
   else
     /* if this is a pointer */
   if (IS_PTR (type))
-    rast = createIvalPtr (sym, type, ilist);
+    rast = createIvalPtr (sym, type, ilist, rootValue);
   else
     /* if this is an array   */
   if (IS_ARRAY (type))
-    rast = createIvalArray (sym, type, ilist);
+    rast = createIvalArray (sym, type, ilist, rootValue);
   else
     /* if type is SPECIFIER */
   if (IS_SPEC (type))
@@ -1115,7 +1137,8 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
 /* initAggregates - initialises aggregate variables with initv     */
 /*-----------------------------------------------------------------*/
 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
-  return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid);
+  ast *newAst = newAst_VALUE (symbolVal (sym));
+  return createIval (newAst, sym->type, ival, wid, newAst);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1160,7 +1183,7 @@ gatherAutoInit (symbol * autoChain)
           SPEC_SCLS (sym->etype) != S_CODE)
         {
           symbol *newSym;
-          
+
           /* insert the symbol into the symbol table */
           /* with level = 0 & name = rname       */
           newSym = copySymbol (sym);
@@ -1172,7 +1195,7 @@ gatherAutoInit (symbol * autoChain)
           } else {
             if (getNelements(sym->type, sym->ival)>1) {
               werrorfl (sym->fileDef, sym->lineDef,
-                        W_EXCESS_INITIALIZERS, "scalar", 
+                        W_EXCESS_INITIALIZERS, "scalar",
                         sym->name);
             }
             work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
@@ -1194,7 +1217,7 @@ gatherAutoInit (symbol * autoChain)
       if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
         {
           initList *ilist=sym->ival;
-          
+
           while (ilist->type == INIT_DEEP) {
             ilist = ilist->init.deep;
           }
@@ -1202,19 +1225,19 @@ gatherAutoInit (symbol * autoChain)
           /* update lineno for error msg */
           lineno=sym->lineDef;
           setAstLineno (ilist->init.node, lineno);
-          
+
           if (IS_AGGREGATE (sym->type)) {
             work = initAggregates (sym, sym->ival, NULL);
           } else {
             if (getNelements(sym->type, sym->ival)>1) {
               werrorfl (sym->fileDef, sym->lineDef,
-                        W_EXCESS_INITIALIZERS, "scalar", 
+                        W_EXCESS_INITIALIZERS, "scalar",
                         sym->name);
             }
             work = newNode ('=', newAst_VALUE (symbolVal (sym)),
                             list2expr (sym->ival));
           }
-          
+
           // just to be sure
           setAstLineno (work, sym->lineDef);
 
@@ -1242,7 +1265,7 @@ void freeStringSymbol(symbol *sym) {
     }
   }
 }
-  
+
 /*-----------------------------------------------------------------*/
 /* stringToSymbol - creates a symbol from a literal string         */
 /*-----------------------------------------------------------------*/
@@ -1314,7 +1337,7 @@ processBlockVars (ast * tree, int *stack, int action)
         {
           *stack += allocVariables (tree->values.sym);
           autoInit = gatherAutoInit (tree->values.sym);
-        
+
           /* if there are auto inits then do them */
           if (autoInit)
             tree->left = newNode (NULLOP, autoInit, tree->left);
@@ -1341,7 +1364,7 @@ bool constExprTree (ast *cexpr) {
 
   cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
 
-  switch (cexpr->type) 
+  switch (cexpr->type)
     {
     case EX_VALUE:
       if (IS_AST_LIT_VALUE(cexpr)) {
@@ -1356,7 +1379,7 @@ bool constExprTree (ast *cexpr) {
         // an array's address will never change
         return TRUE;
       }
-      if (IS_AST_SYM_VALUE(cexpr) && 
+      if (IS_AST_SYM_VALUE(cexpr) &&
           IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
         // a symbol in code space will never change
         // This is only for the 'char *s="hallo"' case and will have to leave
@@ -1380,7 +1403,7 @@ bool constExprTree (ast *cexpr) {
         // cast ignored, maybe we should throw a warning here?
         return constExprTree(cexpr->right);
       }
-      if (cexpr->opval.op=='&') { 
+      if (cexpr->opval.op=='&') {
         return TRUE;
       }
       if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
@@ -1395,7 +1418,7 @@ bool constExprTree (ast *cexpr) {
     }
   return FALSE;
 }
-    
+
 /*-----------------------------------------------------------------*/
 /* constExprValue - returns the value of a constant expression     */
 /*                  or NULL if it is not a constant expression     */
@@ -1451,7 +1474,7 @@ constExprValue (ast * cexpr, int check)
 /*-----------------------------------------------------------------*/
 /* isLabelInAst - will return true if a given label is found       */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isLabelInAst (symbol * label, ast * tree)
 {
   if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
@@ -1471,7 +1494,7 @@ isLabelInAst (symbol * label, ast * tree)
 /* isLoopCountable - return true if the loop count can be determi- */
 /* -ned at compile time .                                          */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
                  symbol ** sym, ast ** init, ast ** end)
 {
@@ -1584,7 +1607,7 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
 /*-----------------------------------------------------------------*/
 /* astHasVolatile - returns true if ast contains any volatile      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasVolatile (ast * tree)
 {
   if (!tree)
@@ -1603,7 +1626,7 @@ astHasVolatile (ast * tree)
 /*-----------------------------------------------------------------*/
 /* astHasPointer - return true if the ast contains any ptr variable */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasPointer (ast * tree)
 {
   if (!tree)
@@ -1628,7 +1651,7 @@ astHasPointer (ast * tree)
 /*-----------------------------------------------------------------*/
 /* astHasSymbol - return true if the ast has the given symbol      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 astHasSymbol (ast * tree, symbol * sym)
 {
   if (!tree || IS_AST_LINK (tree))
@@ -1649,14 +1672,14 @@ astHasSymbol (ast * tree, symbol * sym)
 /*-----------------------------------------------------------------*/
 /* astHasDeref - return true if the ast has an indirect access     */
 /*-----------------------------------------------------------------*/
-static bool 
+static bool
 astHasDeref (ast * tree)
 {
   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
     return FALSE;
 
   if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
-  
+
   return astHasDeref (tree->left) || astHasDeref (tree->right);
 }
 
@@ -1664,7 +1687,7 @@ astHasDeref (ast * tree)
 /* isConformingBody - the loop body has to conform to a set of rules */
 /* for the loop to be considered reversible read on for rules      */
 /*-----------------------------------------------------------------*/
-bool 
+bool
 isConformingBody (ast * pbody, symbol * sym, ast * body)
 {
 
@@ -1683,7 +1706,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
   /* if we reach the end or a leaf then true */
   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
     return TRUE;
-  
+
   /* if anything else is "volatile" */
   if (IS_VOLATILE (TETYPE (pbody)))
     return FALSE;
@@ -1865,7 +1888,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 /*----------------------------*/
     case CALL:
         /* if local & not passed as paramater then ok */
-        if (sym->level && !astHasSymbol(pbody->right,sym)) 
+        if (sym->level && !astHasSymbol(pbody->right,sym))
             return TRUE;
       return FALSE;
 
@@ -1931,7 +1954,7 @@ isLoopReversible (ast * loop, symbol ** loopCntrl,
 /*-----------------------------------------------------------------*/
 /* replLoopSym - replace the loop sym by loop sym -1               */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 replLoopSym (ast * body, symbol * sym)
 {
   /* reached end */
@@ -2068,7 +2091,7 @@ getResultTypeFromType (sym_link *type)
   if (IS_BITFIELD (type))
     {
       int blen = SPEC_BLEN (type);
-      
+
       if (blen <= 1)
         return RESULT_TYPE_BIT;
       if (blen <= 8)
@@ -2087,17 +2110,30 @@ getResultTypeFromType (sym_link *type)
 /* addCast - adds casts to a type specified by RESULT_TYPE         */
 /*-----------------------------------------------------------------*/
 static ast *
-addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
+addCast (ast *tree, RESULT_TYPE resultType, bool promote)
 {
   sym_link *newLink;
   bool upCasted = FALSE;
-  
+
   switch (resultType)
     {
       case RESULT_TYPE_NONE:
-        /* char: promote to int */
-        if (!upcast ||
+        /* if thing smaller than int must be promoted to int */
+        if (!promote ||
             getSize (tree->etype) >= INTSIZE)
+          /* promotion not necessary or already an int */
+          return tree;
+        /* char and bits: promote to int */
+        newLink = newIntLink();
+        upCasted = TRUE;
+        break;
+      case RESULT_TYPE_BIT:
+        if (!promote ||
+            /* already an int */
+            bitsForType (tree->etype) >= 16 ||
+            /* bit to bit operation: don't promote, the code generators
+               hopefully know everything about promotion rules */
+            bitsForType (tree->etype) == 1)
           return tree;
         newLink = newIntLink();
         upCasted = TRUE;
@@ -2118,14 +2154,14 @@ addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
           }
 #endif
         /* char: promote to int */
-        if (!upcast ||
+        if (!promote ||
             getSize (tree->etype) >= INTSIZE)
           return tree;
         newLink = newIntLink();
         upCasted = TRUE;
         break;
       case RESULT_TYPE_OTHER:
-        if (!upcast)
+        if (!promote)
           return tree;
         /* return type is long, float: promote char to int */
         if (getSize (tree->etype) >= INTSIZE)
@@ -2367,7 +2403,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
        in tree->left->?type. If the op is e.g. '=' we extract the type
        information from there and propagate it to the right branch. */
     resultTypeProp = getLeftResultType (tree, resultTypeProp);
-    
+
     switch (tree->opval.op)
       {
         case '?':
@@ -2375,12 +2411,12 @@ decorateType (ast * tree, RESULT_TYPE resultType)
              expansions might rely on this */
           dtr = tree->right;
           break;
-        case CALL: 
+        case CALL:
           /* decorate right side for CALL (parameter list) in processParms();
              there is resultType available */
           dtr = tree->right;
           break;
-        default:     
+        default:
           dtr = decorateType (tree->right, resultTypeProp);
           break;
       }
@@ -2438,6 +2474,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
       RRVAL (tree) = 1;
       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
+      SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2483,19 +2520,19 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* adjust the storage class */
       switch (DCL_TYPE(tree->left->ftype)) {
       case POINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_DATA; 
+        SPEC_SCLS(TETYPE(tree)) = S_DATA;
         break;
       case FPOINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
+        SPEC_SCLS(TETYPE(tree)) = S_XDATA;
         break;
       case CPOINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_CODE; 
+        SPEC_SCLS(TETYPE(tree)) = S_CODE;
         break;
       case GPOINTER:
         SPEC_SCLS (TETYPE (tree)) = 0;
         break;
       case PPOINTER:
-        SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
+        SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
         break;
       case IPOINTER:
         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
@@ -2510,7 +2547,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       case FUNCTION:
         break;
       }
-      
+
       /* This breaks with extern declarations, bitfields, and perhaps other */
       /* cases (gcse). Let's leave this optimization disabled for now and   */
       /* ponder if there's a safe way to do this. -- EEP                    */
@@ -2539,7 +2576,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             SPEC_ABSA(sym->etype) = 1;
             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
             allocGlobal (sym);
-            
+
             AST_VALUE (tree) = symbolVal(sym);
             TLVAL (tree) = 1;
             TRVAL (tree) = 0;
@@ -2548,7 +2585,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             tree->right = NULL;
         }
       #endif
-      
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2666,7 +2703,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             }
 
           LRVAL (tree) = RRVAL (tree) = 1;
-          
+
           TTYPE (tree) = computeType (LTYPE (tree),
                                       RTYPE (tree),
                                       resultType,
@@ -2762,12 +2799,12 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*  bitwise or                */
       /*----------------------------*/
     case '|':
-      /* if the rewrite succeeds then don't go any furthur */
+      /* if the rewrite succeeds then don't go any further */
       {
         ast *wtree = optimizeRRCRLC (tree);
         if (wtree != tree)
           return decorateType (wtree, RESULT_TYPE_NONE);
-        
+
         wtree = optimizeSWAP (tree);
         if (wtree != tree)
           return decorateType (wtree, RESULT_TYPE_NONE);
@@ -2999,16 +3036,16 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               SPEC_SCLS(TETYPE(tree)) = S_DATA;
               break;
             case FPOINTER:
-              SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
+              SPEC_SCLS(TETYPE(tree)) = S_XDATA;
               break;
             case CPOINTER:
-              SPEC_SCLS(TETYPE(tree)) = S_CODE; 
+              SPEC_SCLS(TETYPE(tree)) = S_CODE;
               break;
             case GPOINTER:
               SPEC_SCLS (TETYPE (tree)) = 0;
               break;
             case PPOINTER:
-              SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
+              SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
               break;
             case IPOINTER:
               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
@@ -3225,7 +3262,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                                   resultType,
                                                   tree->opval.op));
         }
-        
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3250,11 +3287,15 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
               tree->left = NULL;
               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-              SPEC_USIGN(TETYPE(tree)) = 0;
               return tree;
             }
+          tree->left  = addCast (tree->left, resultType, TRUE);
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                     computeType (LTYPE (tree),
+                                                  NULL,
+                                                  resultType,
+                                                  tree->opval.op));
           LRVAL (tree) = 1;
-          TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
           return tree;
         }
 
@@ -3370,7 +3411,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                       tree->right = litParent->left;
                       litParent->left = tTree;
                       litTree->opval.op = '+';
-                      
+
                       tree->decorated = 0;
                       decorateType (tree, resultType);
                     }
@@ -3409,7 +3450,23 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
           return addCast (tree, resultType, TRUE);
         }
-      tree->left = addCast (tree->left, resultType, TRUE);
+
+      if (resultType == RESULT_TYPE_BIT &&
+          IS_UNSIGNED (tree->left->etype) &&
+          getSize (tree->left->etype) < INTSIZE)
+        {
+          /* promotion rules are responsible for this strange result:
+             bit -> int -> ~int -> bit
+             uchar -> int -> ~int -> bit
+          */
+          werror(W_COMPLEMENT);
+
+          /* optimize bit-result, even if we optimize a buggy source */
+          tree->type = EX_VALUE;
+          tree->opval.val = constVal ("1");
+        }
+      else
+        tree->left = addCast (tree->left, resultType, TRUE);
       LRVAL (tree) = 1;
       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
       return tree;
@@ -3481,7 +3538,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /* make smaller type only if it's a LEFT_OP */
       if (tree->opval.op == LEFT_OP)
         tree->left = addCast (tree->left, resultType, TRUE);
-      
+
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
@@ -3629,7 +3686,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (IS_ADDRESS_OF_OP(tree->right)
           && IS_AST_SYM_VALUE (tree->right->left)
           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
-        
+
         symbol * sym = AST_SYMBOL (tree->right->left);
         unsigned int gptype = 0;
         unsigned int addr = SPEC_ADDR (sym->etype);
@@ -3656,7 +3713,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               }
             addr |= gptype << (8*(GPTRSIZE - 1));
           }
-        
+
         tree->type = EX_VALUE;
         tree->opval.val =
           valCastLiteral (LTYPE (tree), addr);
@@ -3875,7 +3932,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                   /* if (unsigned value) */
                   return tree->left;
                 }
-              
+
               /* (unsigned value) ? 1 : 0 */
               tree->opval.op = '?';
               tree->right = newNode (':',
@@ -3900,6 +3957,37 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                    tree->opval.val->type);
           return tree;
         }
+      /* if one is 'signed char ' and the other one is 'unsigned char' */
+      /* it's necessary to promote to int */
+      if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
+          (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
+        {
+          /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
+             if it's possible to use a 'signed char' */
+
+              /* is left a 'unsigned char'? */
+          if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
+              /* the value range of a 'unsigned char' is 0...255;
+                 if the actual value is < 128 it can be changed to signed */
+              (int) floatFromVal (valFromType (RETYPE (tree))) < 128)
+            {
+              /* now we've got 2 'signed char'! */
+              SPEC_USIGN (RETYPE (tree)) = 0;
+            }
+                   /* same test for the left operand: */
+          else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
+              (int) floatFromVal (valFromType (LETYPE (tree))) < 128)
+            {
+              SPEC_USIGN (LETYPE (tree)) = 0;
+            }
+          else
+            {
+              werror (W_CMP_SU_CHAR);
+              tree->left  = addCast (tree->left , RESULT_TYPE_INT, TRUE);
+              tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
+            }
+        }
+
       LRVAL (tree) = RRVAL (tree) = 1;
       TTYPE (tree) = TETYPE (tree) = newCharLink ();
       return tree;
@@ -4236,7 +4324,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*       function call        */
       /*----------------------------*/
     case CALL:
-      
+
       /* undo any explicit pointer derefernce; PCALL will handle it instead */
       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
         {
@@ -4256,7 +4344,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (!tree->right ||
           !tree->right->decorated)
         {
-          sym_link *functype;      
+          sym_link *functype;
           parmNumber = 1;
 
           if (IS_FUNCPTR (LTYPE (tree)))
@@ -4269,8 +4357,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             {
               goto errorTreeReturn;
             }
-        
-          if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
+
+          if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
              !IFFUNC_ISBUILTIN(functype))
             {
               reverseParms (tree->right);
@@ -4431,11 +4519,12 @@ sizeofOp (sym_link * type)
 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
+#define IS_NULLOP(ex) (ex->type == EX_OP && ex->opval.op == NULLOP)
 
 /*-----------------------------------------------------------------*/
 /* backPatchLabels - change and or not operators to flow control    */
 /*-----------------------------------------------------------------*/
-ast *
+static ast *
 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
 {
 
@@ -4500,25 +4589,18 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
   /* change not */
   if (IS_NOT (tree))
     {
-      int wasnot = IS_NOT (tree->left);
+      /* call with exchanged labels */
       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
 
-      /* if the left is already a IFX */
+      /* if left isn't already a IFX */
       if (!IS_IFX (tree->left))
-        tree->left = newNode (IFX, tree->left, NULL);
-
-      if (wasnot)
-        {
-          tree->left->trueLabel = trueLabel;
-          tree->left->falseLabel = falseLabel;
-        }
-      else
         {
+          tree->left = newNode (IFX, tree->left, NULL);
           tree->left->trueLabel = falseLabel;
           tree->left->falseLabel = trueLabel;
         }
       return tree->left;
-    }
+     }
 
   if (IS_IFX (tree))
     {
@@ -4544,7 +4626,7 @@ createBlock (symbol * decl, ast * body)
 
   ex = newNode (BLOCK, NULL, body);
   ex->values.sym = decl;
-  
+
   ex->level++;
   ex->lineno = 0;
   return ex;
@@ -4663,7 +4745,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
     }
 
   /* create the case label   */
-  SNPRINTF(caseLbl, sizeof(caseLbl), 
+  SNPRINTF(caseLbl, sizeof(caseLbl),
            "_case_%d_%d",
            swStat->values.switchVals.swNum,
            (int) floatFromVal (caseVal->opval.val));
@@ -4959,8 +5041,6 @@ isShiftRightLitVal_BitAndLitVal (ast * tree)
 static int
 isBitAndPow2 (ast * tree)
 {
-  int p2;
-
   /* if this is not a bit and */
   if (!IS_BITAND (tree))
     return -1;
@@ -4970,13 +5050,7 @@ isBitAndPow2 (ast * tree)
   if (!IS_AST_LIT_VALUE (tree->right))
     return -1;
 
-  if (AST_LIT_VALUE (tree->right) == 1)
-    return 0;
-  p2 = powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
-  if (!p2)
-    return -1;
-
-  return p2;
+  return powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
 }
 
 /*-----------------------------------------------------------------*/
@@ -4999,7 +5073,7 @@ optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
   if (!expr && (resultType == RESULT_TYPE_BIT))
     {
       expr = tree->left;
-      if (isBitAndPow2 (tree) != getSize (TTYPE (expr)) * 8 - 1)
+      if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
         expr = NULL;
     }
   if (!expr)
@@ -5080,7 +5154,7 @@ optimizeGetByte (ast * tree, RESULT_TYPE resultType)
     }
   if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
     return tree;
-      
+
   /* make sure the port supports GETBYTE */
   if (port->hasExtBitOp
       && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
@@ -5095,7 +5169,7 @@ optimizeGetByte (ast * tree, RESULT_TYPE resultType)
 ast *
 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
 {
-  unsigned int i;
+  unsigned int i = 0;
   ast * expr;
   ast * count = NULL;
 
@@ -5106,7 +5180,7 @@ optimizeGetWord (ast * tree, RESULT_TYPE resultType)
       count = tree->left->right;
       if (AST_LIT_VALUE (tree->right) != 0xFFFF)
         expr = NULL;
-    }      
+    }
   if (!expr && resultType == RESULT_TYPE_INT)
     {
       /* if this is a right shift over a multiple of 8 */
@@ -5119,7 +5193,7 @@ optimizeGetWord (ast * tree, RESULT_TYPE resultType)
     }
   if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
     return tree;
-      
+
   /* make sure the port supports GETWORD */
   if (port->hasExtBitOp
       && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
@@ -5474,7 +5548,7 @@ noOptimize:
 /*-----------------------------------------------------------------*/
 /* addSymToBlock : adds the symbol to the first block we find      */
 /*-----------------------------------------------------------------*/
-void 
+void
 addSymToBlock (symbol * sym, ast * tree)
 {
   /* reached end of tree or a leaf */
@@ -5500,7 +5574,7 @@ addSymToBlock (symbol * sym, ast * tree)
 /*-----------------------------------------------------------------*/
 /* processRegParms - do processing for register parameters         */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 processRegParms (value * args, ast * body)
 {
   while (args)
@@ -5617,7 +5691,6 @@ createFunction (symbol * name, ast * body)
 
   body = resolveSymbols (body); /* resolve the symbols */
   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
-                                        
 
   ex = newAst_VALUE (symbolVal (name)); /* create name */
   ex = newNode (FUNCTION, ex, body);
@@ -5945,11 +6018,11 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                         fprintf(outfile,")\n");
                         ast_print(tree->left,outfile,indent+2);
                         return ;
-                }                       
+                }
                 /*------------------------------------------------------------------*/
                 /*----------------------------*/
                 /*      multiplication        */
-                /*----------------------------*/                
+                /*----------------------------*/
                 fprintf(outfile,"MULT (%p) type (",tree);
                 printTypeChain(tree->ftype,outfile);
                 fprintf(outfile,")\n");
@@ -6005,7 +6078,7 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                 return;
                 /*------------------------------------------------------------------*/
                 /*----------------------------*/
-                /*    compliment              */
+                /*    complement              */
                 /*----------------------------*/
         case '~':
                 fprintf(outfile,"COMPL (%p) type (",tree);
@@ -6099,7 +6172,7 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                 fprintf(outfile,")\n");
                 ast_print(tree->right,outfile,indent+2);
                 return ;
-                
+
         case AND_OP:
                 fprintf(outfile,"ANDAND (%p) type (",tree);
                 printTypeChain(tree->ftype,outfile);
@@ -6114,7 +6187,7 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                 ast_print(tree->left,outfile,indent+2);
                 ast_print(tree->right,outfile,indent+2);
                 return ;
-                
+
                 /*------------------------------------------------------------------*/
                 /*----------------------------*/
                 /*     comparison operators   */
@@ -6273,7 +6346,7 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                 fprintf(outfile,")\n");
                 ast_print(tree->left,outfile,indent+2);
                 ast_print(tree->right,outfile,indent+2);
-                return;     
+                return;
                 /*------------------------------------------------------------------*/
                 /*----------------------------*/
                 /*      comma operator        */
@@ -6414,12 +6487,12 @@ void PA(ast *t)
 int astErrors(ast *t)
 {
   int errors=0;
-  
+
   if (t)
     {
       if (t->isError)
         errors++;
-  
+
       if (t->type == EX_VALUE
           && t->opval.val->sym
           && t->opval.val->sym->undefined)
@@ -6428,6 +6501,6 @@ int astErrors(ast *t)
       errors += astErrors(t->left);
       errors += astErrors(t->right);
     }
-    
+
   return errors;
 }