Fixed promotion, it should be done on AST level:
[fw/sdcc] / src / SDCCast.c
index fcf18e220e2559e82f311c62bf240018ce02f156..979dcfe225868fb1da8d4f06c920330caf1c503f 100644 (file)
@@ -84,6 +84,7 @@ newAst_ (unsigned type)
   ex->level = NestLevel;
   ex->block = currBlockno;
   ex->initMode = inInitMode;
+  ex->seqPoint = seqPointNo;
   return ex;
 }
 
@@ -343,7 +344,7 @@ hasSEFcalls (ast * tree)
 /*-----------------------------------------------------------------*/
 /* isAstEqual - compares two asts & returns 1 if they are equal    */
 /*-----------------------------------------------------------------*/
-int 
+static int
 isAstEqual (ast * t1, ast * t2)
 {
   if (!t1 && !t2)
@@ -429,7 +430,8 @@ resolveSymbols (ast * tree)
                               tree->trueLabel->name)))
            tree->trueLabel = csym;
          else
-           werror (E_LABEL_UNDEF, tree->trueLabel->name);
+           werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                     tree->trueLabel->name);
        }
 
       if (tree->falseLabel)
@@ -439,7 +441,8 @@ resolveSymbols (ast * tree)
                               tree->falseLabel->name)))
            tree->falseLabel = csym;
          else
-           werror (E_LABEL_UNDEF, tree->falseLabel->name);
+           werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                     tree->falseLabel->name);
        }
 
     }
@@ -454,7 +457,8 @@ resolveSymbols (ast * tree)
                              tree->opval.val->sym->name);
 
       if (!csym)
-       werror (E_LABEL_UNDEF, tree->opval.val->sym->name);
+       werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
+                 tree->opval.val->sym->name);
       else
        tree->opval.val->sym = csym;
 
@@ -493,7 +497,9 @@ resolveSymbols (ast * tree)
                tree->opval.val->sym->etype = newIntLink ();
              tree->opval.val->etype = tree->opval.val->etype;
              tree->opval.val->type = tree->opval.val->sym->type;
-             werror (W_IMPLICIT_FUNC, tree->opval.val->sym->name);
+             werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
+                       tree->opval.val->sym->name);
+             //tree->opval.val->sym->undefined = 1;
              allocVariables (tree->opval.val->sym);
            }
          else
@@ -670,6 +676,8 @@ processParms (ast * func,
   /* exist and this is not defined as a variable arg   */
   if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
     {
+      //if (func->type==EX_VALUE && func->opval.val->sym->undefined)
+      //  return 1; /* Already gave them an undefined function error */
       werror (E_TOO_MANY_PARMS);
       return 1;
     }
@@ -715,7 +723,7 @@ processParms (ast * func,
            actParm->decorated = 0;
            actParm->left = newNode( CAST, newAst_LINK(newIntLink()),
                                         actParm->left);
-           actParm = decorateType(actParm);
+           actParm = decorateType(actParm, RESULT_CHECK);
          } else {
            newType = newAst_LINK(INTTYPE);
          }
@@ -735,13 +743,13 @@ processParms (ast * func,
       if (newType)
        {
          /* cast required; change this op to a cast. */
-         ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)));
+         ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)), RESULT_CHECK);
 
          actParm->type = EX_OP;
          actParm->opval.op = CAST;
          actParm->left = newType;
          actParm->right = parmCopy;
-         decorateType (actParm);
+         decorateType (actParm, RESULT_CHECK);
        }
       else if (actParm->type == EX_OP && actParm->opval.op == PARAM)
        {
@@ -789,7 +797,7 @@ processParms (ast * func,
   /* if the parameter is castable then add the cast */
   if (compareType (defParm->type, actParm->ftype) < 0)
     {
-      ast *pTree = decorateType(resolveSymbols (copyAst (actParm)));
+      ast *pTree = decorateType(resolveSymbols (copyAst (actParm)), RESULT_CHECK);
 
       /* now change the current one to a cast */
       actParm->type = EX_OP;
@@ -799,7 +807,7 @@ processParms (ast * func,
       actParm->etype = defParm->etype;
       actParm->ftype = defParm->type;
       actParm->decorated=0; /* force typechecking */
-      decorateType (actParm);
+      decorateType (actParm, RESULT_CHECK);
     }
 
   /* make a copy and change the regparm type to the defined parm */
@@ -821,8 +829,8 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
   if (ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
-  iExpr = decorateType (resolveSymbols (list2expr (ilist)));
-  return decorateType (newNode ('=', sym, iExpr));
+  iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
+  return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
 }
 
 /*-----------------------------------------------------------------*/
@@ -852,13 +860,14 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
        break;
       sflds->implicit = 1;
       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
-      lAst = decorateType (resolveSymbols (lAst));
-      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)));
+      lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK);
+      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK);
     }
 
   if (iloop) {
-    werror (W_EXCESS_INITIALIZERS, "struct", 
-           sym->opval.val->sym->name, sym->opval.val->sym->lineDef);
+    werrorfl (filename, sym->opval.val->sym->lineDef,
+             W_EXCESS_INITIALIZERS, "struct", 
+             sym->opval.val->sym->name);
   }
 
   return rast;
@@ -882,9 +891,9 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
   if (IS_CHAR (type->next))
     if ((rast = createIvalCharPtr (sym,
                                   type,
-                       decorateType (resolveSymbols (list2expr (ilist))))))
+                       decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK))))
 
-      return decorateType (resolveSymbols (rast));
+      return decorateType (resolveSymbols (rast), RESULT_CHECK);
 
     /* not the special case             */
     if (ilist->type != INIT_DEEP)
@@ -900,7 +909,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
     {
        ast *aSym;
 
-       aSym = decorateType (resolveSymbols(sym));
+       aSym = decorateType (resolveSymbols(sym), RESULT_CHECK);
        
        rast = newNode(ARRAYINIT, aSym, NULL);
        rast->values.constlist = literalL;
@@ -918,7 +927,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
            char *name=sym->opval.val->sym->name;
            int lineno=sym->opval.val->sym->lineDef;
            
-           werror (W_EXCESS_INITIALIZERS, "array", name, lineno);
+           werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
        }
     }
     else
@@ -928,7 +937,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
            ast *aSym;
            
            aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
-           aSym = decorateType (resolveSymbols (aSym));
+           aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK);
            rast = createIval (aSym, type->next, iloop, rast);
            iloop = (iloop ? iloop->next : NULL);
            if (!iloop)
@@ -943,7 +952,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
                // there has to be a better way
                char *name=sym->opval.val->sym->name;
                int lineno=sym->opval.val->sym->lineDef;
-               werror (W_EXCESS_INITIALIZERS, "array", name, lineno);
+               werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
                
                break;
            }
@@ -956,7 +965,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
        DCL_ELEM (type) = size;
     }
 
-    return decorateType (resolveSymbols (rast));
+    return decorateType (resolveSymbols (rast), RESULT_CHECK);
 }
 
 
@@ -985,8 +994,18 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       /* 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)
+        {
+         if (size>(symsize+1))
+           werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+                     "string", sym->opval.val->sym->name);
+         size = symsize;
+       }
 
-      while (*s)
+      for (i=0;i<size;i++)
        {
          rast = newNode (NULLOP,
                          rast,
@@ -994,20 +1013,13 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
                                   newNode ('[', sym,
                                   newAst_VALUE (valueFromLit ((float) i))),
                                   newAst_VALUE (valueFromLit (*s))));
-         i++;
          s++;
        }
-      rast = newNode (NULLOP,
-                     rast,
-                     newNode ('=',
-                              newNode ('[', sym,
-                                  newAst_VALUE (valueFromLit ((float) i))),
-                              newAst_VALUE (valueFromLit (*s))));
 
       // now WE don't need iexpr's symbol anymore
       freeStringSymbol(AST_SYMBOL(iexpr));
 
-      return decorateType (resolveSymbols (rast));
+      return decorateType (resolveSymbols (rast), RESULT_CHECK);
     }
 
   return NULL;
@@ -1026,7 +1038,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist)
   if (ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
-  iexpr = decorateType (resolveSymbols (list2expr (ilist)));
+  iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
 
   /* if character pointer */
   if (IS_CHAR (type->next))
@@ -1064,9 +1076,9 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
     rast = createIvalType (sym, type, ilist);
 
   if (wid)
-    return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)));
+    return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK);
   else
-    return decorateType (resolveSymbols (rast));
+    return decorateType (resolveSymbols (rast), RESULT_CHECK);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1114,8 +1126,9 @@ gatherAutoInit (symbol * autoChain)
            work = initAggregates (sym, sym->ival, NULL);
          } else {
            if (getNelements(sym->type, sym->ival)>1) {
-             werror (W_EXCESS_INITIALIZERS, "scalar", 
-                     sym->name, sym->lineDef);
+             werrorfl (filename, sym->lineDef,
+                       W_EXCESS_INITIALIZERS, "scalar", 
+                       sym->name);
            }
            work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
                            list2expr (sym->ival));
@@ -1149,8 +1162,9 @@ gatherAutoInit (symbol * autoChain)
            work = initAggregates (sym, sym->ival, NULL);
          } else {
            if (getNelements(sym->type, sym->ival)>1) {
-             werror (W_EXCESS_INITIALIZERS, "scalar", 
-                     sym->name, sym->lineDef);
+             werrorfl (filename, sym->lineDef,
+                       W_EXCESS_INITIALIZERS, "scalar", 
+                       sym->name);
            }
            work = newNode ('=', newAst_VALUE (symbolVal (sym)),
                            list2expr (sym->ival));
@@ -1194,12 +1208,14 @@ stringToSymbol (value * val)
   static int charLbl = 0;
   symbol *sym;
   set *sp;
+  int size;
 
   // have we heard this before?
   for (sp=statsg->syms; sp; sp=sp->next) {
     sym=sp->item;
-    if (sym->isstrlit && 
-       !strcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char)) {
+    size = getSize (sym->type);
+    if (sym->isstrlit && size == getSize (val->type) &&
+       !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
       // yes, this is old news. Don't publish it again.
       sym->isstrlit++; // but raise the usage count
       return symbolVal(sym);
@@ -1278,7 +1294,7 @@ bool constExprTree (ast *cexpr) {
     return TRUE;
   }
 
-  cexpr = decorateType (resolveSymbols (cexpr));
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
 
   switch (cexpr->type) 
     {
@@ -1342,7 +1358,7 @@ bool constExprTree (ast *cexpr) {
 value *
 constExprValue (ast * cexpr, int check)
 {
-  cexpr = decorateType (resolveSymbols (cexpr));
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
 
   /* if this is not a constant then */
   if (!IS_LITERAL (cexpr->ftype))
@@ -1578,7 +1594,7 @@ astHasSymbol (ast * tree, symbol * sym)
       else
        return FALSE;
     }
-  
+
   return astHasSymbol (tree->left, sym) ||
     astHasSymbol (tree->right, sym);
 }
@@ -1730,7 +1746,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
     case '?':
     case ':':
     case SIZEOF:               /* evaluate wihout code generation */
-      
+
       if (IS_AST_SYM_VALUE (pbody->left) &&
          isSymbolEqual (AST_SYMBOL (pbody->left), sym))
        return FALSE;
@@ -1766,7 +1782,7 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 
       if (astHasVolatile (pbody->left))
        return FALSE;
-      
+
       if (astHasDeref(pbody->right)) return FALSE;
 
       return isConformingBody (pbody->left, sym, body) &&
@@ -1935,7 +1951,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
                                                  rloop))));
 
   rloop->lineno=init->lineno;
-  return decorateType (rloop);
+  return decorateType (rloop, RESULT_CHECK);
 
 }
 
@@ -1989,15 +2005,133 @@ searchLitOp (ast *tree, ast **parent, const char *ops)
 }
 
 /*-----------------------------------------------------------------*/
-/* decorateType - compute type for this tree also does type checking */
-/*          this is done bottom up, since type have to flow upwards */
-/*          it also does constant folding, and paramater checking  */
+/* getResultFromType                                               */
+/*-----------------------------------------------------------------*/
+static RESULT_TYPE
+getResultTypeFromType (sym_link *type)
+{
+  /* type = getSpec (type); */
+  if (IS_BITVAR (type))
+    return RESULT_TYPE_BIT;
+  if (IS_BITFIELD (type))
+    return RESULT_TYPE_CHAR;
+  if (IS_CHAR (type))
+    return RESULT_TYPE_CHAR;
+  if (   IS_INT (type)
+      && !IS_LONG (type))
+    return RESULT_TYPE_INT;
+  return RESULT_TYPE_OTHER;
+}
+
+/*-----------------------------------------------------------------*/
+/* addCast - adds casts to a type specified by RESULT_TYPE         */
+/*-----------------------------------------------------------------*/
+static void
+addCast (ast **tree, RESULT_TYPE resultType, bool upcast)
+{
+  sym_link *newLink;
+  
+  switch (resultType)
+    {
+      case RESULT_TYPE_CHAR:
+       if (getSize ((*tree)->etype) <= 1)
+         return;
+       newLink = newCharLink();
+       break;
+      case RESULT_TYPE_INT:
+#if 0
+       if (getSize ((*tree)->etype) > INTSIZE)
+          {
+            /* warn ("Loosing significant digits"); */
+           return;
+         }
+#endif
+       /* char: promote to int */
+       if (!upcast ||
+           getSize ((*tree)->etype) >= INTSIZE)
+         return;
+       newLink = newIntLink();
+       break;
+      case RESULT_TYPE_OTHER:
+       if (!upcast)
+         return;
+        /* long, float: promote to int */
+       if (getSize ((*tree)->etype) >= INTSIZE)
+         return;
+       newLink = newIntLink();
+       break;
+      default:
+       return;
+    }
+  (*tree)->decorated = 0;
+  *tree = newNode (CAST, newAst_LINK (newLink), *tree);
+  /* keep unsigned type */
+  SPEC_USIGN ((*tree)->left->opval.lnk) = IS_UNSIGNED ((*tree)->right->etype) ? 1 : 0;
+  *tree = decorateType (*tree, resultType);
+}
+
+/*-----------------------------------------------------------------*/
+/* resultTypePropagate - decides if resultType can be propagated   */
 /*-----------------------------------------------------------------*/
+static RESULT_TYPE
+resultTypePropagate (ast *tree, RESULT_TYPE resultType)
+{
+  switch (tree->opval.op)
+    {
+      case '=':
+      case '?':
+      case ':':
+      case '|':
+      case '^':
+       return resultType;
+      case '&':
+       if (!tree->right)
+         /* can be unary */
+         return RESULT_TYPE_NONE;
+       else
+         return resultType;
+      default:
+       return RESULT_TYPE_NONE;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* getLeftResultType - gets type from left branch for propagation  */
+/*-----------------------------------------------------------------*/
+static RESULT_TYPE
+getLeftResultType (ast *tree, RESULT_TYPE resultType)
+{
+  switch (tree->opval.op)
+    {
+      case '=':
+      case CAST:
+       if (IS_PTR (tree->left->ftype))
+         return RESULT_TYPE_NONE;
+       else
+         return getResultTypeFromType (tree->left->etype);
+      case RETURN:
+       if (IS_PTR (currFunc->type->next))
+         return RESULT_TYPE_NONE;
+       else
+         return getResultTypeFromType (currFunc->type->next);
+      default:
+       return resultType;
+    }
+}
+
+/*--------------------------------------------------------------------*/
+/* decorateType - compute type for this tree, also does type checking.*/
+/* This is done bottom up, since type has to flow upwards.            */
+/* resultType flows top-down and forces e.g. char-arithmetik, if the  */
+/* result is a char and the operand(s) are int's.                     */
+/* It also does constant folding, and parameter checking.             */
+/*--------------------------------------------------------------------*/
 ast *
-decorateType (ast * tree)
+decorateType (ast * tree, RESULT_TYPE resultType)
 {
   int parmNumber;
   sym_link *p;
+  RESULT_TYPE resultTypeProp;
 
   if (!tree)
     return tree;
@@ -2029,7 +2163,7 @@ decorateType (ast * tree)
 
 /*------------------------------------------------------------------*/
 /*----------------------------*/
-  /*   leaf has been reached    */
+/*   leaf has been reached    */
 /*----------------------------*/
   lineno=tree->lineno;
   /* if this is of type value */
@@ -2093,10 +2227,47 @@ decorateType (ast * tree)
   {
     ast *dtl, *dtr;
 
-    dtl = decorateType (tree->left);
-    /* delay right side for '?' operator since conditional macro expansions might
-       rely on this */
-    dtr = (tree->opval.op == '?' ? tree->right : decorateType (tree->right));
+    #if 0
+    if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
+      {
+        if (tree->left && tree->left->type == EX_OPERAND
+           && (tree->left->opval.op == INC_OP
+               || tree->left->opval.op == DEC_OP)
+           && tree->left->left)
+         {
+           tree->left->right = tree->left->left;
+           tree->left->left = NULL;
+         }
+        if (tree->right && tree->right->type == EX_OPERAND
+           && (tree->right->opval.op == INC_OP
+               || tree->right->opval.op == DEC_OP)
+           && tree->right->left)
+         {
+           tree->right->right = tree->right->left;
+           tree->right->left = NULL;
+         }
+      }
+    #endif
+
+    /* Before decorating the left branch we've to decide in dependence
+       upon tree->opval.op, if resultType can be propagated */
+    if (getenv ("SDCC_NEWTYPEFLOW"))
+      resultTypeProp = resultTypePropagate (tree, resultType);
+    else
+      resultTypeProp = RESULT_TYPE_NONE; /* provide initialization */
+
+    dtl = decorateType (tree->left, resultTypeProp);
+
+    /* After decorating the left branch there's type information available
+       in tree->left->?type. If the op is e.g. '=' we extract the type
+       information from there and propagate it to the right branch. */
+    if (getenv ("SDCC_NEWTYPEFLOW"))
+      resultTypeProp = getLeftResultType (tree, resultTypeProp);
+    
+    /* delay right side for '?' operator since conditional macro expansions
+       might rely on this */
+    dtr = tree->opval.op == '?' ? tree->right :
+                                  decorateType (tree->right, resultTypeProp);
 
     /* this is to take care of situations
        when the tree gets rewritten */
@@ -2107,25 +2278,28 @@ decorateType (ast * tree)
     if ((dtl && dtl->isError) || (dtr && dtr->isError))
       return tree;
 
-    if (IS_AST_OP(tree) &&
-       (tree->opval.op == CAST || tree->opval.op == '=') &&
-       (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) &&
-       (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) {
-      // this is a cast/assign to a bigger type
-      if (IS_AST_OP(tree->right) &&
-         IS_INTEGRAL(tree->right->ftype) &&
-         (tree->right->opval.op == LEFT_OP ||
-          tree->right->opval.op == '*' ||
-          tree->right->opval.op == '+' ||
-          tree->right->opval.op == '-') &&
-         tree->right->right) {
-       // we should cast an operand instead of the result
-       tree->right->decorated = 0;
-       tree->right->left = newNode( CAST, newAst_LINK(newIntLink()),
-                                    tree->right->left);
-       tree->right = decorateType(tree->right);
+    if (!getenv ("SDCC_NEWTYPEFLOW"))
+      {
+        if (IS_AST_OP(tree) &&
+           (tree->opval.op == CAST || tree->opval.op == '=') &&
+           (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) &&
+           (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) {
+          /* this is a cast/assign to a bigger type */
+         if (IS_AST_OP(tree->right) &&
+             IS_INTEGRAL(tree->right->ftype) &&
+             (tree->right->opval.op == LEFT_OP ||
+              tree->right->opval.op == '*' ||
+              tree->right->opval.op == '+' ||
+              tree->right->opval.op == '-') &&
+              tree->right->right) {
+           /* we should cast an operand instead of the result */
+           tree->right->decorated = 0;
+           tree->right->left = newNode( CAST, newAst_LINK(newIntLink()),
+                                        tree->right->left);
+           tree->right = decorateType(tree->right, RESULT_CHECK);
+          }
+        }
       }
-    }
   }
 
   /* depending on type of operator do */
@@ -2242,6 +2416,10 @@ decorateType (ast * tree)
        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                    */
+      #if 0
       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
         {
@@ -2274,7 +2452,8 @@ decorateType (ast * tree)
             tree->left = NULL;
             tree->right = NULL;
         }
-
+      #endif
+      
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2335,11 +2514,15 @@ decorateType (ast * tree)
            ast *otree = optimizeGetHbit (tree);
 
            if (otree != tree)
-             return decorateType (otree);
+             return decorateType (otree, RESULT_CHECK);
          }
 
-         TTYPE (tree) =
-           computeType (LTYPE (tree), RTYPE (tree));
+         if (getenv ("SDCC_NEWTYPEFLOW"))
+           {
+             addCast (&tree->left,  resultType, FALSE);
+             addCast (&tree->right, resultType, FALSE);
+           }
+         TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
          TETYPE (tree) = getSpec (TTYPE (tree));
 
           /* if left is a literal exchange left & right */
@@ -2363,11 +2546,12 @@ decorateType (ast * tree)
                  litTree->left = tree->right;
                  tree->right = tTree;
                  /* both operands in tTree are literal now */
-                 decorateType (parent);
+                 decorateType (parent, RESULT_CHECK);
                }
            }
 
          LRVAL (tree) = RRVAL (tree) = 1;
+         
          return tree;
        }
 
@@ -2461,13 +2645,11 @@ decorateType (ast * tree)
       {
        ast *wtree = optimizeRRCRLC (tree);
        if (wtree != tree)
-         return decorateType (wtree);
+         return decorateType (wtree, RESULT_CHECK);
        
        wtree = optimizeSWAP (tree);
        if (wtree != tree)
-         return decorateType (wtree);
-        
-       // fall through
+         return decorateType (wtree, RESULT_CHECK);
       }
 
       /* if left is a literal exchange left & right */
@@ -2491,9 +2673,11 @@ decorateType (ast * tree)
              litTree->left = tree->right;
              tree->right = tTree;
              /* both operands in tTree are literal now */
-             decorateType (parent);
+             decorateType (parent, RESULT_CHECK);
            }
         }
+      /* fall through */
+
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*  bitwise xor               */
@@ -2535,7 +2719,8 @@ decorateType (ast * tree)
       /* if right is a literal and */
       /* we can find a 2nd literal in a xor-tree then */
       /* rearrange the tree */
-      if (IS_LITERAL (RTYPE (tree)))
+      if (IS_LITERAL (RTYPE (tree)) &&
+          tree->opval.op == '^') /* the same source is used by 'bitwise or' */
        {
          ast *parent;
          ast *litTree = searchLitOp (tree, &parent, "^");
@@ -2545,14 +2730,22 @@ decorateType (ast * tree)
              litTree->left = tree->right;
              tree->right = tTree;
              /* both operands in litTree are literal now */
-             decorateType (parent);
+             decorateType (parent, RESULT_CHECK);
            }
         }
 
       LRVAL (tree) = RRVAL (tree) = 1;
+      if (getenv ("SDCC_NEWTYPEFLOW"))
+        {
+          addCast (&tree->left,  resultType, FALSE);
+          addCast (&tree->right, resultType, FALSE);
+        }
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                                           RTYPE (tree),
+                                           FALSE));
+
+      return tree;
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
@@ -2580,7 +2773,8 @@ decorateType (ast * tree)
       LRVAL (tree) = RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                                           RTYPE (tree),
+               ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
 
       /* if right is a literal and */
       /* left is also a division by a literal then */
@@ -2600,15 +2794,15 @@ decorateType (ast * tree)
                  litTree->right->lineno = tree->lineno;
 
                  tree->right->opval.val = constVal ("1");
-                 decorateType (parent);
+                 decorateType (parent, RESULT_CHECK);
                }
              else
                {
                  /* litTree->left is literal: no gcse possible.
-                    We can't call decorateType(parent), because
+                    We can't call decorateType(parent, RESULT_CHECK), because
                     this would cause an infinit loop. */
                  parent->decorated = 1;
-                 decorateType (litTree);
+                 decorateType (litTree, RESULT_CHECK);
                }
            }
        }
@@ -2645,7 +2839,8 @@ decorateType (ast * tree)
       LRVAL (tree) = RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                                           RTYPE (tree),
+               ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2750,21 +2945,26 @@ decorateType (ast * tree)
              litTree->left = tree->right;
              tree->right = tTree;
              /* both operands in litTree are literal now */
-             decorateType (parent);
+             decorateType (parent, RESULT_CHECK);
            }
         }
 
       LRVAL (tree) = RRVAL (tree) = 1;
-      TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree)));
-
-      /* promote result to int if left & right are char
-        this will facilitate hardware multiplies 8bit x 8bit = 16bit */
-      if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) {
-       SPEC_NOUN(TETYPE(tree)) = V_INT;
-      }
-
+      if (!getenv ("SDCC_NEWTYPEFLOW"))
+        TETYPE (tree) = getSpec (TTYPE (tree) =
+                                computeType (LTYPE (tree),
+                                             RTYPE (tree),
+                                             TRUE));
+      else
+       {
+          addCast (&tree->left,  resultType, FALSE);
+          addCast (&tree->right, resultType, FALSE);
+         TETYPE (tree) = getSpec (TTYPE (tree) =
+                                  computeType (LTYPE (tree),
+                                               RTYPE (tree),
+                              resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+       }
+      
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2775,7 +2975,7 @@ decorateType (ast * tree)
       /* if unary plus */
       if (!tree->right)
        {
-         if (!IS_INTEGRAL (LTYPE (tree)))
+         if (!IS_ARITHMETIC (LTYPE (tree)))
            {
              werror (E_UNARY_OP, '+');
              goto errorTreeReturn;
@@ -2882,7 +3082,7 @@ decorateType (ast * tree)
                      tree->opval.op = '-';
                    }
                }
-             decorateType (parent);
+             decorateType (parent, RESULT_CHECK);
            }
        }
 
@@ -2892,9 +3092,21 @@ decorateType (ast * tree)
        TETYPE (tree) = getSpec (TTYPE (tree) =
                                 LTYPE (tree));
       else
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree)));
+        if (!getenv ("SDCC_NEWTYPEFLOW"))
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                  computeType (LTYPE (tree),
+                                               RTYPE (tree),
+                                               FALSE));
+       else
+          {
+           addCast (&tree->left,  resultType, TRUE);
+            addCast (&tree->right, resultType, TRUE);
+            TETYPE (tree) = getSpec (TTYPE (tree) =
+                                    computeType (LTYPE (tree),
+                                                 RTYPE (tree),
+                              resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+          }
+       
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2991,9 +3203,20 @@ decorateType (ast * tree)
        TETYPE (tree) = getSpec (TTYPE (tree) =
                                 LTYPE (tree));
       else
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree)));
+        if (!getenv ("SDCC_NEWTYPEFLOW"))
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                  computeType (LTYPE (tree),
+                                               RTYPE (tree),
+                                               FALSE));
+       else
+         {
+           addCast (&tree->left,  resultType, TRUE);
+           addCast (&tree->right, resultType, TRUE);
+           TETYPE (tree) = getSpec (TTYPE (tree) =
+                                    computeType (LTYPE (tree),
+                                                 RTYPE (tree),
+                              resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+         }
 
       LRVAL (tree) = RRVAL (tree) = 1;
 
@@ -3034,7 +3257,7 @@ decorateType (ast * tree)
                      tree->right = tTree;
                    }
                }
-             decorateType (litParent);
+             decorateType (litParent, RESULT_CHECK);
            }
        }
       return tree;
@@ -3133,28 +3356,52 @@ decorateType (ast * tree)
          return tree;
        }
 
+      LRVAL (tree) = RRVAL (tree) = 1;
+      if (tree->opval.op == LEFT_OP)
+       {
+         if (!getenv ("SDCC_NEWTYPEFLOW"))
+           /* promote char to int */
+           TETYPE (tree) = getSpec (TTYPE (tree) =
+                                    computeType (LTYPE (tree),
+                                                 LTYPE (tree), /* no, not RTYPE! */
+                                                 TRUE));
+         else
+           {
+             addCast (&tree->left,  resultType, TRUE);
+             TETYPE (tree) = getSpec (TTYPE (tree) =
+                                      computeType (LTYPE (tree),
+                                                   RTYPE (tree),
+                              resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
+           }
+       }
+      else /* RIGHT_OP */
+       {
+         /* no promotion necessary */
+         TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
+         if (IS_LITERAL (TTYPE (tree)))
+           SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
+       }
+
       /* if only the right side is a literal & we are
          shifting more than size of the left operand then zero */
       if (IS_LITERAL (RTYPE (tree)) &&
-         ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
-         (getSize (LTYPE (tree)) * 8))
+         ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
+         (getSize (TETYPE (tree)) * 8))
        {
          if (tree->opval.op==LEFT_OP ||
-             (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) {
-           lineno=tree->lineno;
-           werror (W_SHIFT_CHANGED,
-                   (tree->opval.op == LEFT_OP ? "left" : "right"));
-           tree->type = EX_VALUE;
-           tree->left = tree->right = NULL;
-           tree->opval.val = constVal ("0");
-           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-           return tree;
-         }
+             (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
+           {
+             lineno=tree->lineno;
+             werror (W_SHIFT_CHANGED,
+                     (tree->opval.op == LEFT_OP ? "left" : "right"));
+             tree->type = EX_VALUE;
+             tree->left = tree->right = NULL;
+             tree->opval.val = constVal ("0");
+             TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+             return tree;
+           }
        }
-      LRVAL (tree) = RRVAL (tree) = 1;
-      TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
-      if (IS_LITERAL (TTYPE (tree)))
-        SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3172,6 +3419,23 @@ decorateType (ast * tree)
       /* make sure the type is complete and sane */
       checkTypeSanity(LETYPE(tree), "(cast)");
 
+      /* If code memory is read only, then pointers to code memory */
+      /* implicitly point to constants -- make this explicit       */
+      {
+       sym_link *t = LTYPE(tree);
+       while (t && t->next)
+         {
+           if (IS_CODEPTR(t) && port->mem.code_ro)
+             {
+               if (IS_SPEC(t->next))
+                 SPEC_CONST (t->next) = 1;
+               else
+                 DCL_PTR_CONST (t->next) = 1;
+             }
+           t = t->next;
+          }
+      }
+
 #if 0
       /* if the right is a literal replace the tree */
       if (IS_LITERAL (RETYPE (tree))) {
@@ -3248,7 +3512,7 @@ decorateType (ast * tree)
          tree->opval.val = valCastLiteral (
            LTYPE (tree),
            element->offset
-            + floatFromVal (valFromType (RETYPE (tree->right->left->left)))
+            + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
           );
 
          TTYPE (tree) = tree->opval.val->type;
@@ -3261,7 +3525,8 @@ decorateType (ast * tree)
 
       /* if the right is a literal replace the tree */
       if (IS_LITERAL (RETYPE (tree))) {
-        if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
+        #if 0
+       if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
           /* rewrite      (type *)litaddr
              as           &temp
              and define   type at litaddr temp
@@ -3284,7 +3549,7 @@ decorateType (ast * tree)
           sym->cdef = 1;
           sym->isref = 1;
           SPEC_STAT (sym->etype) = 1;
-          SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RETYPE (tree)));
+          SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
           SPEC_ABSA(sym->etype) = 1;
           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
           allocGlobal (sym);
@@ -3298,11 +3563,12 @@ decorateType (ast * tree)
           TLVAL (newTree) = 1;
           return newTree;
         }
+       #endif
         if (!IS_PTR (LTYPE (tree))) {
          tree->type = EX_VALUE;
          tree->opval.val =
          valCastLiteral (LTYPE (tree),
-                         floatFromVal (valFromType (RETYPE (tree))));
+                         floatFromVal (valFromType (RTYPE (tree))));
          TTYPE (tree) = tree->opval.val->type;
          tree->left = NULL;
          tree->right = NULL;
@@ -3347,8 +3613,8 @@ decorateType (ast * tree)
          IS_LITERAL (LTYPE (tree)))
        {
          tree->type = EX_VALUE;
-         tree->opval.val = valLogicAndOr (valFromType (LETYPE (tree)),
-                                          valFromType (RETYPE (tree)),
+         tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
+                                          valFromType (RTYPE (tree)),
                                           tree->opval.op);
          tree->right = tree->left = NULL;
          TETYPE (tree) = getSpec (TTYPE (tree) =
@@ -3389,7 +3655,7 @@ decorateType (ast * tree)
          if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
            {
              werror (E_COMPARE_OP);
-             fprintf (stderr, "comparring type ");
+             fprintf (stderr, "comparing type ");
              printTypeChain (LTYPE (tree), stderr);
              fprintf (stderr, "to type ");
              printTypeChain (RTYPE (tree), stderr);
@@ -3415,17 +3681,29 @@ decorateType (ast * tree)
              }
        }
       /* if unsigned value < 0  then always false */
-      /* if (unsigned value) > 0 then (unsigned value) */
-      if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree))  && 
-         ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) {
-
-         if (tree->opval.op == '<') {
+      /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
+      if (SPEC_USIGN(LETYPE(tree)) &&
+          !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
+          IS_LITERAL(RTYPE(tree))  &&
+         ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
+       {
+         if (tree->opval.op == '<')
+           {
              return tree->right;
-         }
-         if (tree->opval.op == '>') {
-             return tree->left;
-         }
-      }
+           }
+         if (tree->opval.op == '>')
+           {
+             /* if the parent is an ifx, then we could do */
+             /* return tree->left; */
+             tree->opval.op = '?';
+             tree->right = newNode (':',
+                                    newAst_VALUE (constVal ("1")),
+                                    tree->right); /* val 0 */
+             tree->right->lineno = tree->lineno;
+             tree->right->left->lineno = tree->lineno;
+             decorateType (tree->right, RESULT_CHECK);
+           }
+        }
       /* if they are both literal then */
       /* rewrite the tree */
       if (IS_LITERAL (RTYPE (tree)) &&
@@ -3540,20 +3818,22 @@ decorateType (ast * tree)
       /*----------------------------*/
     case '?':
       /* the type is value of the colon operator (on the right) */
-      assert(IS_COLON_OP(tree->right));
+      assert (IS_COLON_OP (tree->right));
       /* if already known then replace the tree : optimizer will do it
         but faster to do it here */
-      if (IS_LITERAL (LTYPE(tree))) {    
-         if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) {
-             return decorateType(tree->right->left) ;
-         } else {
-             return decorateType(tree->right->right) ;
-         }
-      } else {
-         tree->right = decorateType(tree->right);
-         TTYPE (tree) = RTYPE(tree);
+      if (IS_LITERAL (LTYPE (tree)))
+       {
+         if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
+            return decorateType (tree->right->left, resultTypeProp);
+         else
+           return decorateType (tree->right->right, resultTypeProp);
+       }
+      else
+       {
+         tree->right = decorateType (tree->right, resultTypeProp);
+         TTYPE (tree) = RTYPE (tree);
          TETYPE (tree) = getSpec (TTYPE (tree));
-      }
+       }
       return tree;
 
     case ':':
@@ -3564,7 +3844,7 @@ decorateType (ast * tree)
          goto errorTreeReturn;
        }
 
-      TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree));
+      TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
       TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
@@ -3646,7 +3926,8 @@ decorateType (ast * tree)
       RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                                           RTYPE (tree),
+                                           FALSE));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
        werror (E_CODE_WRITE, "-=");
@@ -3687,7 +3968,8 @@ decorateType (ast * tree)
       RRVAL (tree) = 1;
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
-                                           RTYPE (tree)));
+                                           RTYPE (tree),
+                                           FALSE));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
        werror (E_CODE_WRITE, "+=");
@@ -3698,7 +3980,7 @@ decorateType (ast * tree)
          goto errorTreeReturn;
        }
 
-      tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right));
+      tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
       tree->opval.op = '=';
 
       return tree;
@@ -3792,7 +4074,7 @@ decorateType (ast * tree)
 
       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
        {
-         werror (W_RETURN_MISMATCH);
+         werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
          printFromToType (RTYPE(tree), currFunc->type->next);
          goto errorTreeReturn;
        }
@@ -3801,17 +4083,18 @@ decorateType (ast * tree)
          && tree->right &&
          !IS_VOID (RTYPE (tree)))
        {
-         werror (E_FUNC_VOID);
+         werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
          goto errorTreeReturn;
        }
 
-      /* if there is going to be a casing required then add it */
+      /* if there is going to be a casting required then add it */
       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
        {
          tree->right =
            decorateType (newNode (CAST,
-                          newAst_LINK (copyLinkChain (currFunc->type->next)),
-                                  tree->right));
+                         newAst_LINK (copyLinkChain (currFunc->type->next)),
+                                       tree->right),
+                         RESULT_CHECK);
        }
 
       RRVAL (tree) = 1;
@@ -3836,7 +4119,7 @@ decorateType (ast * tree)
       /* the switch value must be an integer */
       if (!IS_INTEGRAL (LTYPE (tree)))
        {
-         werror (E_SWITCH_NON_INTEGER);
+         werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
          goto errorTreeReturn;
        }
       LRVAL (tree) = 1;
@@ -3860,9 +4143,9 @@ decorateType (ast * tree)
       /*----------------------------*/
     case FOR:
 
-      decorateType (resolveSymbols (AST_FOR (tree, initExpr)));
-      decorateType (resolveSymbols (AST_FOR (tree, condExpr)));
-      decorateType (resolveSymbols (AST_FOR (tree, loopExpr)));
+      decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
+      decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
+      decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
 
       /* if the for loop is reversible then
          reverse it otherwise do what we normally
@@ -3881,7 +4164,7 @@ decorateType (ast * tree)
                                          AST_FOR (tree, initExpr),
                                          AST_FOR (tree, condExpr),
                                          AST_FOR (tree, loopExpr),
-                                         tree->left));
+                                         tree->left), RESULT_CHECK);
       }
     default:
       TTYPE (tree) = TETYPE (tree) = NULL;
@@ -4093,22 +4376,22 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
   /* then case is out of context            */
   if (!swStat)
     {
-      werror (E_CASE_CONTEXT);
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
       return NULL;
     }
 
-  caseVal = decorateType (resolveSymbols (caseVal));
+  caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
   /* if not a constant then error  */
   if (!IS_LITERAL (caseVal->ftype))
     {
-      werror (E_CASE_CONSTANT);
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
       return NULL;
     }
 
   /* if not a integer than error */
   if (!IS_INTEGRAL (caseVal->ftype))
     {
-      werror (E_CASE_NON_INTEGER);
+      werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
       return NULL;
     }
 
@@ -4131,6 +4414,12 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
        {
          pval->next = caseVal->opval.val;
        }
+      else if ((int) floatFromVal (val) == cVal)
+       {
+         werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
+                   "case");
+         return NULL;
+       }
       else
        {
          /* we found a value greater than */
@@ -4163,7 +4452,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
 /* createDefault - creates the parse tree for the default statement */
 /*-----------------------------------------------------------------*/
 ast *
-createDefault (ast * swStat, ast * stmnt)
+createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
 {
   char defLbl[SDCC_NAME_MAX + 1];
 
@@ -4171,7 +4460,14 @@ createDefault (ast * swStat, ast * stmnt)
   /* then case is out of context            */
   if (!swStat)
     {
-      werror (E_CASE_CONTEXT);
+      werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
+      return NULL;
+    }
+
+  if (swStat->values.switchVals.swDefault)
+    {
+      werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
+               "default");
       return NULL;
     }
 
@@ -4442,7 +4738,7 @@ optimizeGetHbit (ast * tree)
       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
     return tree;
 
-  return decorateType (newNode (GETHBIT, tree->left->left, NULL));
+  return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
 
 }
 
@@ -4709,7 +5005,7 @@ optimizeCompare (ast * root)
          break;
        }
 
-      return decorateType (optExpr);
+      return decorateType (optExpr, RESULT_CHECK);
     }
 
   vleft = (root->left->type == EX_VALUE ?
@@ -4783,7 +5079,7 @@ optimizeCompare (ast * root)
              break;
            }
        }
-      return decorateType (resolveSymbols (optExpr));
+      return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
     }                          /* end-of-if of BITVAR */
 
 noOptimize:
@@ -4929,7 +5225,8 @@ createFunction (symbol * name, ast * body)
   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
 
   body = resolveSymbols (body);        /* resolve the symbols */
-  body = decorateType (body);  /* propagateType & do semantic checks */
+  body = decorateType (body, RESULT_TYPE_NONE);        /* propagateType & do semantic checks */
+                                       
 
   ex = newAst_VALUE (symbolVal (name));        /* create name */
   ex = newNode (FUNCTION, ex, body);
@@ -4960,7 +5257,7 @@ createFunction (symbol * name, ast * body)
     {
       GcurMemmap = statsg;
       codeOutFile = statsg->oFile;
-      eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos))));
+      eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
       staticAutos = NULL;
     }
 
@@ -5084,7 +5381,7 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                                fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
                        else
                                fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
-                       fprintf(outfile,", 0x%x, %g", (TYPE_UDWORD) floatFromVal(tree->opval.val),
+                       fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
                                                      floatFromVal(tree->opval.val));
                } else if (tree->opval.val->sym) {
                        /* if the undefined flag is set then give error message */
@@ -5478,7 +5775,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 ;
-               
+
                /*------------------------------------------------------------------*/
                /*----------------------------*/
                /*    assignment operators    */
@@ -5696,3 +5993,29 @@ void PA(ast *t)
 {
        ast_print(t,stdout,0);
 }
+
+
+
+/*-----------------------------------------------------------------*/
+/* astErrors : returns non-zero if errors present in tree          */
+/*-----------------------------------------------------------------*/
+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)
+        errors++;
+
+      errors += astErrors(t->left);
+      errors += astErrors(t->right);
+    }
+    
+  return errors;
+}