* sim/ucsim/configure.in,
[fw/sdcc] / src / SDCCast.c
index 9944eb407736217f94da4d98f6533c0c194cd5de..8e20910cf1c505dae56081cc9e485c210bbe0a52 100644 (file)
@@ -644,40 +644,49 @@ reverseParms (ast * ptree)
 /* processParms  - makes sure the parameters are okay and do some  */
 /*                 processing with them                            */
 /*-----------------------------------------------------------------*/
-int 
-processParms (ast * func,
+static int
+processParms (ast *func,
              value *defParm,
-             ast * actParm,
-             int *parmNumber, // unused, although updated
+             ast *actParm,
+             int *parmNumber, /* unused, although updated */
              bool rightmost)
 {
+  RESULT_TYPE resultType;
+  sym_link *functype;
+  
   /* if none of them exist */
   if (!defParm && !actParm)
     return 0;
 
-  if (defParm) {
-    if (getenv("DEBUG_SANITY")) {
-      fprintf (stderr, "processParms: %s ", defParm->name);
+  if (defParm)
+    {
+      if (getenv("DEBUG_SANITY"))
+        {
+          fprintf (stderr, "processParms: %s ", defParm->name);
+        }
+      /* make sure the type is complete and sane */
+      checkTypeSanity(defParm->etype, defParm->name);
     }
-    /* make sure the type is complete and sane */
-    checkTypeSanity(defParm->etype, defParm->name);
-  }
 
+  if (IS_CODEPTR (func->ftype))
+    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                                   */
-  if (func->type != EX_VALUE && !IFFUNC_ISREENT (func->ftype) && !options.stackAuto)
+  if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
     {
       werror (W_NONRENT_ARGS);
+      fatalError++;
       return 1;
     }
 
   /* if defined parameters ended but actual parameters */
   /* exist and this is not defined as a variable arg   */
-  if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
+  if (!defParm && actParm && !IFFUNC_HASVARARGS(functype))
     {
-      //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;
     }
@@ -689,13 +698,43 @@ processParms (ast * func,
       return 1;
     }
 
-  if (IS_VOID(actParm->ftype)) {
-    werror (E_VOID_VALUE_USED);
-    return 1;
-  }
+  /* if this is a PARAM node then match left & right */
+  if (actParm->type == EX_OP && actParm->opval.op == PARAM)
+    {
+      actParm->decorated = 1;
+      return (processParms (func, defParm,
+                           actParm->left,  parmNumber, FALSE) ||
+             processParms (func, defParm ? defParm->next : NULL,
+                           actParm->right, parmNumber, rightmost));
+    }
+  else if (defParm) /* not vararg */
+    {
+      /* If we have found a value node by following only right-hand links,
+       * then we know that there are no more values after us.
+       *
+       * Therefore, if there are more defined parameters, the caller didn't
+       * supply enough.
+       */
+      if (rightmost && defParm->next)
+       {
+         werror (E_TOO_FEW_PARMS);
+         return 1;
+       }
+    }
+
+  /* decorate parameter */
+  resultType = defParm ? getResultTypeFromType (defParm->etype) :
+                         RESULT_TYPE_NONE;
+  actParm = decorateType (actParm, resultType);
+
+  if (IS_VOID(actParm->ftype))
+    {
+      werror (E_VOID_VALUE_USED);
+      return 1;
+    }
 
   /* If this is a varargs function... */
-  if (!defParm && actParm && IFFUNC_HASVARARGS(func->ftype))
+  if (!defParm && actParm && IFFUNC_HASVARARGS(functype))
     {
       ast *newType = NULL;
       sym_link *ftype;
@@ -708,25 +747,12 @@ processParms (ast * func,
        }
 
       ftype = actParm->ftype;
-          
-      /* If it's a small integer, upcast to int. */
+
+      /* If it's a char, upcast to int. */
       if (IS_INTEGRAL (ftype)
          && (getSize (ftype) < (unsigned) INTSIZE))
        {
-         if (IS_AST_OP(actParm) &&
-             (actParm->opval.op == LEFT_OP ||
-              actParm->opval.op == '*' ||
-              actParm->opval.op == '+' ||
-              actParm->opval.op == '-') &&
-             actParm->right) {
-           // we should cast an operand instead of the result
-           actParm->decorated = 0;
-           actParm->left = newNode( CAST, newAst_LINK(newIntLink()),
-                                        actParm->left);
-           actParm = decorateType(actParm);
-         } else {
-           newType = newAst_LINK(INTTYPE);
-         }
+         newType = newAst_LINK(INTTYPE);  
        }
 
       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
@@ -740,74 +766,53 @@ 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. */
-         ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)));
+         ast *parmCopy = resolveSymbols (copyAst (actParm));
 
          actParm->type = EX_OP;
          actParm->opval.op = CAST;
          actParm->left = newType;
          actParm->right = parmCopy;
-         decorateType (actParm);
-       }
-      else if (actParm->type == EX_OP && actParm->opval.op == PARAM)
-       {
-         return (processParms (func, NULL, actParm->left, parmNumber, FALSE) ||
-         processParms (func, NULL, actParm->right, parmNumber, rightmost));
+         actParm->decorated = 0; /* force typechecking */
+         decorateType (actParm, RESULT_TYPE_NONE);
        }
       return 0;
-    }
+    } /* vararg */
 
   /* if defined parameters ended but actual has not & */
   /* reentrant */
   if (!defParm && actParm &&
-      (options.stackAuto || IFFUNC_ISREENT (func->ftype)))
+      (options.stackAuto || IFFUNC_ISREENT (functype)))
     return 0;
 
   resolveSymbols (actParm);
-  /* if this is a PARAM node then match left & right */
-  if (actParm->type == EX_OP && actParm->opval.op == PARAM)
-    {
-      return (processParms (func, defParm, actParm->left, parmNumber, FALSE) ||
-             processParms (func, defParm->next, actParm->right, parmNumber, rightmost));
-    }
-  else
+  
+  /* the parameter type must be at least castable */
+  if (compareType (defParm->type, actParm->ftype) == 0)
     {
-      /* If we have found a value node by following only right-hand links,
-       * then we know that there are no more values after us.
-       *
-       * Therefore, if there are more defined parameters, the caller didn't
-       * supply enough.
-       */
-      if (rightmost && defParm->next)
-       {
-         werror (E_TOO_FEW_PARMS);
-         return 1;
-       }
+      werror (E_INCOMPAT_TYPES);
+      printFromToType (actParm->ftype, defParm->type);
+      return 1;
     }
 
-  /* the parameter type must be at least castable */
-  if (compareType (defParm->type, actParm->ftype) == 0) {
-    werror (E_INCOMPAT_TYPES);
-    printFromToType (actParm->ftype, defParm->type);
-    return 1;
-  }
-
   /* if the parameter is castable then add the cast */
   if (compareType (defParm->type, actParm->ftype) < 0)
     {
-      ast *pTree = decorateType(resolveSymbols (copyAst (actParm)));
+      ast *pTree;
 
+      resultType = getResultTypeFromType (defParm->etype);
+      pTree = resolveSymbols (copyAst (actParm));
+      
       /* now change the current one to a cast */
       actParm->type = EX_OP;
       actParm->opval.op = CAST;
       actParm->left = newAst_LINK (defParm->type);
       actParm->right = pTree;
-      actParm->etype = defParm->etype;
-      actParm->ftype = defParm->type;
-      actParm->decorated=0; /* force typechecking */
-      decorateType (actParm);
+      actParm->decorated = 0; /* force typechecking */
+      decorateType (actParm, resultType);
     }
 
   /* make a copy and change the regparm type to the defined parm */
@@ -817,6 +822,7 @@ processParms (ast * func,
   (*parmNumber)++;
   return 0;
 }
+
 /*-----------------------------------------------------------------*/
 /* createIvalType - generates ival for basic types                 */
 /*-----------------------------------------------------------------*/
@@ -829,8 +835,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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -860,12 +866,12 @@ 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) {
-    werrorfl (filename, sym->opval.val->sym->lineDef,
+    werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
              W_EXCESS_INITIALIZERS, "struct", 
              sym->opval.val->sym->name);
   }
@@ -891,9 +897,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)
@@ -909,7 +915,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;
@@ -926,6 +932,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
            // 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);
        }
@@ -937,7 +944,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)
@@ -952,6 +959,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;
+               char *filename=sym->opval.val->sym->fileDef;
                werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
                
                break;
@@ -965,7 +973,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
        DCL_ELEM (type) = size;
     }
 
-    return decorateType (resolveSymbols (rast));
+    return decorateType (resolveSymbols (rast), RESULT_CHECK);
 }
 
 
@@ -1019,7 +1027,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       // 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;
@@ -1038,7 +1046,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))
@@ -1076,9 +1084,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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1105,7 +1113,7 @@ gatherAutoInit (symbol * autoChain)
 
       /* resolve the symbols in the ival */
       if (sym->ival)
-       resolveIvalSym (sym->ival);
+       resolveIvalSym (sym->ival, sym->type);
 
       /* if this is a static variable & has an */
       /* initial value the code needs to be lifted */
@@ -1126,7 +1134,7 @@ gatherAutoInit (symbol * autoChain)
            work = initAggregates (sym, sym->ival, NULL);
          } else {
            if (getNelements(sym->type, sym->ival)>1) {
-             werrorfl (filename, sym->lineDef,
+             werrorfl (sym->fileDef, sym->lineDef,
                        W_EXCESS_INITIALIZERS, "scalar", 
                        sym->name);
            }
@@ -1162,7 +1170,7 @@ gatherAutoInit (symbol * autoChain)
            work = initAggregates (sym, sym->ival, NULL);
          } else {
            if (getNelements(sym->type, sym->ival)>1) {
-             werrorfl (filename, sym->lineDef,
+             werrorfl (sym->fileDef, sym->lineDef,
                        W_EXCESS_INITIALIZERS, "scalar", 
                        sym->name);
            }
@@ -1294,7 +1302,7 @@ bool constExprTree (ast *cexpr) {
     return TRUE;
   }
 
-  cexpr = decorateType (resolveSymbols (cexpr));
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
 
   switch (cexpr->type) 
     {
@@ -1358,7 +1366,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))
@@ -1746,7 +1754,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;
@@ -1782,7 +1790,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) &&
@@ -1951,7 +1959,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
                                                  rloop))));
 
   rloop->lineno=init->lineno;
-  return decorateType (rloop);
+  return decorateType (rloop, RESULT_CHECK);
 
 }
 
@@ -2005,15 +2013,167 @@ 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                                               */
+/*-----------------------------------------------------------------*/
+RESULT_TYPE
+getResultTypeFromType (sym_link *type)
+{
+  /* type = getSpec (type); */
+  if (IS_BIT (type))
+    return RESULT_TYPE_BIT;
+  if (IS_BITFIELD (type))
+    {
+      int blen = SPEC_BLEN (type);
+      
+      if (blen <= 1)
+        return RESULT_TYPE_BIT;
+      if (blen <= 8)
+        return RESULT_TYPE_CHAR;
+      return RESULT_TYPE_INT;
+    }
+  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 ast *
+addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
+{
+  sym_link *newLink;
+  bool upCasted = FALSE;
+  
+  switch (resultType)
+    {
+      case RESULT_TYPE_NONE:
+       /* char: promote to int */
+       if (!upcast ||
+           getSize (tree->etype) >= INTSIZE)
+         return tree;
+       newLink = newIntLink();
+       upCasted = TRUE;
+       break;
+      case RESULT_TYPE_CHAR:
+       if (getSize (tree->etype) <= 1)
+         return tree;
+       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 tree;
+       newLink = newIntLink();
+       upCasted = TRUE;
+       break;
+      case RESULT_TYPE_OTHER:
+       if (!upcast)
+         return tree;
+        /* return type is long, float: promote char to int */
+       if (getSize (tree->etype) >= INTSIZE)
+         return tree;
+       newLink = newIntLink();
+       upCasted = TRUE;
+       break;
+      default:
+       return tree;
+    }
+  tree->decorated = 0;
+  tree = newNode (CAST, newAst_LINK (newLink), tree);
+  tree->lineno = tree->right->lineno;
+  /* keep unsigned type during cast to smaller type,
+     but not when promoting from char to int */
+  if (!upCasted)
+    SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
+  return 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 '^':
+      case '*':
+      case '+':
+      case '-':
+      case LABEL:
+       return resultType;
+      case '&':
+       if (!tree->right)
+         /* can be unary */
+         return RESULT_TYPE_NONE;
+       else
+         return resultType;
+      case IFX:
+       return RESULT_TYPE_IFX;
+      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 (LTYPE (tree)))
+         return RESULT_TYPE_NONE;
+       else
+         return getResultTypeFromType (LETYPE (tree));
+      case RETURN:
+       if (IS_PTR (currFunc->type->next))
+         return RESULT_TYPE_NONE;
+       else
+         return getResultTypeFromType (currFunc->type->next);
+      case '[':
+       if (!IS_ARRAY (LTYPE (tree)))
+         return resultType;
+       if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
+         return RESULT_TYPE_CHAR;
+       return resultType;
+      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;
@@ -2045,7 +2205,7 @@ decorateType (ast * tree)
 
 /*------------------------------------------------------------------*/
 /*----------------------------*/
-  /*   leaf has been reached    */
+/*   leaf has been reached    */
 /*----------------------------*/
   lineno=tree->lineno;
   /* if this is of type value */
@@ -2130,11 +2290,50 @@ decorateType (ast * tree)
          }
       }
     #endif
+
+    /* Before decorating the left branch we've to decide in dependence
+       upon tree->opval.op, if resultType can be propagated */
+    resultTypeProp = resultTypePropagate (tree, resultType);
+
+    if (tree->opval.op == '?')
+      dtl = decorateType (tree->left, RESULT_TYPE_IFX);
+    else
+      dtl = decorateType (tree->left, resultTypeProp);
+
+    /* if an array node, we may need to swap branches */
+    if (tree->opval.op == '[')
+      {
+        /* determine which is the array & which the index */
+        if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
+           IS_INTEGRAL (LTYPE (tree)))
+         {
+           ast *tempTree = tree->left;
+           tree->left = tree->right;
+           tree->right = tempTree;
+         }
+      }
+
+    /* 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. */
+    resultTypeProp = getLeftResultType (tree, resultTypeProp);
     
-    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));
+    switch (tree->opval.op)
+      {
+        case '?':
+         /* delay right side for '?' operator since conditional macro
+            expansions might rely on this */
+         dtr = tree->right;
+         break;
+       case CALL: 
+         /* decorate right side for CALL (parameter list) in processParms();
+            there is resultType available */
+         dtr = tree->right;
+         break;
+       default:     
+         dtr = decorateType (tree->right, resultTypeProp);
+         break;
+      }
 
     /* this is to take care of situations
        when the tree gets rewritten */
@@ -2144,26 +2343,6 @@ decorateType (ast * tree)
       tree->right = dtr;
     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);
-      }
-    }
   }
 
   /* depending on type of operator do */
@@ -2176,15 +2355,6 @@ decorateType (ast * tree)
        /*----------------------------*/
     case '[':
 
-      /* determine which is the array & which the index */
-      if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) && IS_INTEGRAL (LTYPE (tree)))
-       {
-
-         ast *tempTree = tree->left;
-         tree->left = tree->right;
-         tree->right = tempTree;
-       }
-
       /* first check if this is a array or a pointer */
       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
        {
@@ -2205,6 +2375,17 @@ decorateType (ast * tree)
          werror (E_LVALUE_REQUIRED, "array access");
          goto errorTreeReturn;
        }
+
+      if (IS_LITERAL (RTYPE (tree)))
+       {
+         int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
+         int arraySize = DCL_ELEM (LTYPE (tree));
+         if (arraySize && arrayIndex >= arraySize)
+           {
+             werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
+           }
+       }
+
       RRVAL (tree) = 1;
       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
       return tree;
@@ -2378,11 +2559,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), FALSE);
+         tree->left  = addCast (tree->left,  resultType, FALSE);
+         tree->right = addCast (tree->right, resultType, FALSE);
+         TTYPE (tree) = computeType (LTYPE (tree),
+                                     RTYPE (tree),
+                                     resultType,
+                                     tree->opval.op);
          TETYPE (tree) = getSpec (TTYPE (tree));
 
           /* if left is a literal exchange left & right */
@@ -2406,11 +2591,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;
        }
 
@@ -2504,11 +2690,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);
+         return decorateType (wtree, RESULT_CHECK);
       }
 
       /* if left is a literal exchange left & right */
@@ -2532,7 +2718,7 @@ 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 */
@@ -2589,15 +2775,18 @@ 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;
+      tree->left  = addCast (tree->left,  resultType, FALSE);
+      tree->right = addCast (tree->right, resultType, FALSE);
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
                                            RTYPE (tree),
-                                           FALSE));
+                                           resultType,
+                                           tree->opval.op));
 
       return tree;
 
@@ -2625,10 +2814,12 @@ decorateType (ast * tree)
        }
 
       LRVAL (tree) = RRVAL (tree) = 1;
+
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
                                            RTYPE (tree),
-                                           TRUE));
+                                           resultType,
+                                           tree->opval.op));
 
       /* if right is a literal and */
       /* left is also a division by a literal then */
@@ -2648,15 +2839,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);
                }
            }
        }
@@ -2694,7 +2885,8 @@ decorateType (ast * tree)
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
                                            RTYPE (tree),
-                                           TRUE));
+                                           resultType,
+                                           tree->opval.op));
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2799,15 +2991,18 @@ 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;
+      tree->left  = addCast (tree->left,  resultType, FALSE);
+      tree->right = addCast (tree->right, resultType, FALSE);
       TETYPE (tree) = getSpec (TTYPE (tree) =
-                              computeType (LTYPE (tree),
-                                           RTYPE (tree),
-                                           TRUE));
+                                  computeType (LTYPE (tree),
+                                               RTYPE (tree),
+                                               resultType,
+                                               tree->opval.op));
 
       return tree;
 
@@ -2926,7 +3121,7 @@ decorateType (ast * tree)
                      tree->opval.op = '-';
                    }
                }
-             decorateType (parent);
+             decorateType (parent, RESULT_CHECK);
            }
        }
 
@@ -2936,10 +3131,16 @@ decorateType (ast * tree)
        TETYPE (tree) = getSpec (TTYPE (tree) =
                                 LTYPE (tree));
       else
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree),
-                                             FALSE));
+       {
+         tree->left  = addCast (tree->left,  resultType, TRUE);
+          tree->right = addCast (tree->right, resultType, TRUE);
+          TETYPE (tree) = getSpec (TTYPE (tree) =
+                                    computeType (LTYPE (tree),
+                                                 RTYPE (tree),
+                                                 resultType,
+                                                 tree->opval.op));
+       }
+       
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3036,10 +3237,15 @@ decorateType (ast * tree)
        TETYPE (tree) = getSpec (TTYPE (tree) =
                                 LTYPE (tree));
       else
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree),
-                                             FALSE));
+       {
+         tree->left  = addCast (tree->left,  resultType, TRUE);
+         tree->right = addCast (tree->right, resultType, TRUE);
+         TETYPE (tree) = getSpec (TTYPE (tree) =
+                                    computeType (LTYPE (tree),
+                                                 RTYPE (tree),
+                                                 resultType,
+                                                 tree->opval.op));
+       }
 
       LRVAL (tree) = RRVAL (tree) = 1;
 
@@ -3080,7 +3286,7 @@ decorateType (ast * tree)
                      tree->right = tTree;
                    }
                }
-             decorateType (litParent);
+             decorateType (litParent, RESULT_CHECK);
            }
        }
       return tree;
@@ -3182,11 +3388,12 @@ decorateType (ast * tree)
       LRVAL (tree) = RRVAL (tree) = 1;
       if (tree->opval.op == LEFT_OP)
        {
-         /* promote char to int */
+         tree->left = addCast (tree->left, resultType, TRUE);
          TETYPE (tree) = getSpec (TTYPE (tree) =
-                                  computeType (LTYPE (tree),
-                                               LTYPE (tree), /* no, not RTYPE! */
-                                               TRUE));
+                                      computeType (LTYPE (tree),
+                                                   NULL,
+                                                   resultType,
+                                                   tree->opval.op));
        }
       else /* RIGHT_OP */
        {
@@ -3233,6 +3440,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))) {
@@ -3478,8 +3702,10 @@ 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))  &&
+      /* 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 == '<')
@@ -3488,7 +3714,21 @@ decorateType (ast * tree)
            }
          if (tree->opval.op == '>')
            {
-             return tree->left;
+             if (resultType == RESULT_TYPE_IFX)
+               {
+                 /* the parent is an ifx: */
+                 /* if (unsigned value) */
+                 return tree->left;
+               }
+             
+             /* (unsigned value) ? 1 : 0 */
+             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 */
@@ -3515,8 +3755,13 @@ decorateType (ast * tree)
       /*----------------------------*/
     case SIZEOF:               /* evaluate wihout code generation */
       /* change the type to a integer */
+      {
+       int size = getSize (tree->right->ftype);
+       SNPRINTF(buffer, sizeof(buffer), "%d", size);
+       if (!size && !IS_VOID(tree->right->ftype))
+         werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
+      }
       tree->type = EX_VALUE;
-      SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
       tree->opval.val = constVal (buffer);
       tree->right = tree->left = NULL;
       TETYPE (tree) = getSpec (TTYPE (tree) =
@@ -3605,20 +3850,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 ':':
@@ -3629,7 +3876,8 @@ decorateType (ast * tree)
          goto errorTreeReturn;
        }
 
-      TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
+      TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
+                                  resultType, tree->opval.op);
       TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
@@ -3712,7 +3960,8 @@ decorateType (ast * tree)
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
                                            RTYPE (tree),
-                                           FALSE));
+                                           RESULT_TYPE_NOPROM,
+                                           tree->opval.op));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
        werror (E_CODE_WRITE, "-=");
@@ -3754,7 +4003,8 @@ decorateType (ast * tree)
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
                                            RTYPE (tree),
-                                           FALSE));
+                                           RESULT_TYPE_NOPROM,
+                                           tree->opval.op));
 
       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
        werror (E_CODE_WRITE, "+=");
@@ -3765,7 +4015,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;
@@ -3827,26 +4077,45 @@ decorateType (ast * tree)
       /*       function call        */
       /*----------------------------*/
     case CALL:
-      parmNumber = 1;
-
-      if (processParms (tree->left,
-                       FUNC_ARGS(tree->left->ftype),
-                       tree->right, &parmNumber, TRUE)) {
-       goto errorTreeReturn;
-      }
+      
+      /* undo any explicit pointer derefernce; PCALL will handle it instead */
+      if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
+        {
+         if (tree->left->opval.op == '*' && !tree->left->right)
+           tree->left = tree->left->left;
+       }
 
-      if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) && 
-         !IFFUNC_ISBUILTIN(LTYPE(tree)))
+      /* require a function or pointer to function */
+      if (!IS_FUNC (LTYPE (tree))
+          && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
        {
-         reverseParms (tree->right);
+         werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
+         goto errorTreeReturn;
        }
 
-      if (IS_CODEPTR(LTYPE(tree))) {
-       TTYPE(tree) = LTYPE(tree)->next->next;
-      } else {
-       TTYPE(tree) = LTYPE(tree)->next;
+      {
+       sym_link *functype;      
+       parmNumber = 1;
+
+       if (IS_CODEPTR(LTYPE(tree)))
+         functype = LTYPE (tree)->next;
+       else
+         functype = LTYPE (tree);
+
+       if (processParms (tree->left, FUNC_ARGS(functype),
+                         tree->right, &parmNumber, TRUE)) {
+         goto errorTreeReturn;
+        }
+
+       if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
+           !IFFUNC_ISBUILTIN(functype))
+         {
+           reverseParms (tree->right);
+         }
+
+       TTYPE (tree) = functype->next;
+       TETYPE (tree) = getSpec (TTYPE (tree));
       }
-      TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3872,13 +4141,14 @@ decorateType (ast * tree)
          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;
@@ -3927,9 +4197,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
@@ -3948,8 +4218,13 @@ decorateType (ast * tree)
                                          AST_FOR (tree, initExpr),
                                          AST_FOR (tree, condExpr),
                                          AST_FOR (tree, loopExpr),
-                                         tree->left));
+                                         tree->left), RESULT_CHECK);
       }
+    case PARAM:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "node PARAM shouldn't be processed here");
+             /* but in processParams() */
+      return tree;
     default:
       TTYPE (tree) = TETYPE (tree) = NULL;
       return tree;
@@ -3971,12 +4246,15 @@ value *
 sizeofOp (sym_link * type)
 {
   char buff[10];
+  int size;
 
   /* make sure the type is complete and sane */
   checkTypeSanity(type, "(sizeof)");
 
   /* get the size and convert it to character  */
-  SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
+  SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
+  if (!size && !IS_VOID(type))
+    werror (E_SIZEOF_INCOMPLETE_TYPE);
 
   /* now convert into value  */
   return constVal (buff);
@@ -4164,7 +4442,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
       return NULL;
     }
 
-  caseVal = decorateType (resolveSymbols (caseVal));
+  caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
   /* if not a constant then error  */
   if (!IS_LITERAL (caseVal->ftype))
     {
@@ -4522,7 +4800,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);
 
 }
 
@@ -4789,7 +5067,7 @@ optimizeCompare (ast * root)
          break;
        }
 
-      return decorateType (optExpr);
+      return decorateType (optExpr, RESULT_CHECK);
     }
 
   vleft = (root->left->type == EX_VALUE ?
@@ -4863,7 +5141,7 @@ optimizeCompare (ast * root)
              break;
            }
        }
-      return decorateType (resolveSymbols (optExpr));
+      return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
     }                          /* end-of-if of BITVAR */
 
 noOptimize:
@@ -5009,7 +5287,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);
@@ -5040,7 +5319,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;
     }
 
@@ -5558,7 +5837,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    */