* support/regression/tests/bug-478094.c: Added.
[fw/sdcc] / src / SDCCast.c
index ffa15d16f959fe8a19b45f6901b761c3a96ceb3e..441bedc9105bed4feccc0f20c93d5192574fbd07 100644 (file)
@@ -23,7 +23,6 @@
 -------------------------------------------------------------------------*/
 
 #include "common.h"
-#include "newalloc.h"
 
 int currLineno = 0;
 set *astList = NULL;
@@ -46,7 +45,6 @@ int labelKey = 1;
 #define ALLOCATE 1
 #define DEALLOCATE 2
 
-char buffer[1024];
 int noLineno = 0;
 int noAlloc = 0;
 symbol *currFunc;
@@ -55,6 +53,7 @@ ast *createIvalCharPtr (ast *, sym_link *, ast *);
 ast *optimizeRRCRLC (ast *);
 ast *optimizeGetHbit (ast *);
 ast *backPatchLabels (ast *, symbol *, symbol *);
+void PA(ast *t);
 int inInitMode = 0;
 memmap *GcurMemmap=NULL;  /* points to the memmap that's currently active */
 FILE *codeOutFile;
@@ -76,7 +75,7 @@ newAst (int type, void *op)
   ast *ex;
   static int oldLineno = 0;
 
-  Safe_calloc (1, ex, sizeof (ast));
+  ex = Safe_alloc ( sizeof (ast));
 
   ex->type = type;
   ex->lineno = (noLineno ? oldLineno : yylineno);
@@ -111,7 +110,7 @@ newAst_ (unsigned type)
   ast *ex;
   static int oldLineno = 0;
 
-  ex = Safe_calloc (1, sizeof (ast));
+  ex = Safe_alloc ( sizeof (ast));
 
   ex->type = type;
   ex->lineno = (noLineno ? oldLineno : yylineno);
@@ -222,7 +221,7 @@ copyAstValues (ast * dest, ast * src)
       break;
 
     case INLINEASM:
-      dest->values.inlineasm = Safe_calloc (1, strlen (src->values.inlineasm) + 1);
+      dest->values.inlineasm = Safe_alloc (strlen (src->values.inlineasm) + 1);
       strcpy (dest->values.inlineasm, src->values.inlineasm);
       break;
 
@@ -253,13 +252,15 @@ copyAst (ast * src)
   if (!src)
     return NULL;
 
-  dest = Safe_calloc (1, sizeof (ast));
+  dest = Safe_alloc ( sizeof (ast));
 
   dest->type = src->type;
   dest->lineno = src->lineno;
   dest->level = src->level;
   dest->funcName = src->funcName;
-  dest->argSym = src->argSym;
+
+  if (src->ftype)
+    dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
 
   /* if this is a leaf */
   /* if value */
@@ -281,9 +282,6 @@ copyAst (ast * src)
   /* if this is a node that has special values */
   copyAstValues (dest, src);
 
-  if (src->ftype)
-    dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
-
   dest->trueLabel = copySymbol (src->trueLabel);
   dest->falseLabel = copySymbol (src->falseLabel);
   dest->left = copyAst (src->left);
@@ -544,12 +542,18 @@ funcOfType (char *name, sym_link * type, sym_link * argType,
   /* create the symbol */
   sym = newSymbol (name, 0);
 
+  /* setup return value */
+  sym->type = newLink ();
+  DCL_TYPE (sym->type) = FUNCTION;
+  sym->type->next = copyLinkChain (type);
+  sym->etype = getSpec (sym->type);
+  FUNC_ISREENT(sym->type) = rent;
+
   /* if arguments required */
   if (nArgs)
     {
-
       value *args;
-      args = sym->args = newValue ();
+      args = FUNC_ARGS(sym->type) = newValue ();
 
       while (nArgs--)
        {
@@ -561,13 +565,6 @@ funcOfType (char *name, sym_link * type, sym_link * argType,
        }
     }
 
-  /* setup return value */
-  sym->type = newLink ();
-  DCL_TYPE (sym->type) = FUNCTION;
-  sym->type->next = copyLinkChain (type);
-  sym->etype = getSpec (sym->type);
-  SPEC_RENT (sym->etype) = rent;
-
   /* save it */
   addSymChain (sym);
   sym->cdef = 1;
@@ -605,20 +602,18 @@ reverseParms (ast * ptree)
 /*-----------------------------------------------------------------*/
 int 
 processParms (ast * func,
-             value * defParm,
+             value *defParm,
              ast * actParm,
-             int *parmNumber,
+             int *parmNumber, // unused, although updated
              bool rightmost)
 {
-  sym_link *fetype = func->etype;
-
   /* if none of them exist */
   if (!defParm && !actParm)
     return 0;
 
   if (defParm) {
     if (getenv("DEBUG_SANITY")) {
-      fprintf (stderr, "addSym: %s ", defParm->name);
+      fprintf (stderr, "processParms: %s ", defParm->name);
     }
     /* make sure the type is complete and sane */
     checkTypeSanity(defParm->etype, defParm->name);
@@ -627,17 +622,15 @@ processParms (ast * func,
   /* 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 && !IS_RENT (fetype) && !options.stackAuto)
+  if (func->type != EX_VALUE && !IFFUNC_ISREENT (func->ftype) && !options.stackAuto)
     {
-      werror (E_NONRENT_ARGS);
+      werror (W_NONRENT_ARGS);
       return 1;
     }
 
   /* if defined parameters ended but actual parameters */
   /* exist and this is not defined as a variable arg   */
-  /* also check if statckAuto option is specified      */
-  if ((!defParm) && actParm && (!func->hasVargs) &&
-      !options.stackAuto && !IS_RENT (fetype))
+  if (!defParm && actParm && !IFFUNC_HASVARARGS(func->ftype))
     {
       werror (E_TOO_MANY_PARMS);
       return 1;
@@ -650,8 +643,13 @@ processParms (ast * func,
       return 1;
     }
 
+  if (IS_VOID(actParm->ftype)) {
+    werror (E_VOID_VALUE_USED);
+    return 1;
+  }
+
   /* If this is a varargs function... */
-  if (!defParm && actParm && func->hasVargs)
+  if (!defParm && actParm && IFFUNC_HASVARARGS(func->ftype))
     {
       ast *newType = NULL;
       sym_link *ftype;
@@ -699,7 +697,7 @@ processParms (ast * func,
       if (newType)
        {
          /* cast required; change this op to a cast. */
-         ast *parmCopy = resolveSymbols (copyAst (actParm));
+         ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)));
 
          actParm->type = EX_OP;
          actParm->opval.op = CAST;
@@ -716,9 +714,9 @@ processParms (ast * func,
     }
 
   /* if defined parameters ended but actual has not & */
-  /* stackAuto                */
+  /* reentrant */
   if (!defParm && actParm &&
-      (options.stackAuto || IS_RENT (fetype)))
+      (options.stackAuto || IFFUNC_ISREENT (func->ftype)))
     return 0;
 
   resolveSymbols (actParm);
@@ -744,21 +742,16 @@ processParms (ast * func,
     }
 
   /* the parameter type must be at least castable */
-  if (compareType (defParm->type, actParm->ftype) == 0)
-    {
-      werror (E_TYPE_MISMATCH_PARM, *parmNumber);
-      werror (E_CONTINUE, "defined type ");
-      printTypeChain (defParm->type, stderr);
-      fprintf (stderr, "\n");
-      werror (E_CONTINUE, "actual type ");
-      printTypeChain (actParm->ftype, stderr);
-      fprintf (stderr, "\n");
-    }
+  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 = resolveSymbols (copyAst (actParm));
+      ast *pTree = decorateType(resolveSymbols (copyAst (actParm)));
 
       /* now change the current one to a cast */
       actParm->type = EX_OP;
@@ -767,11 +760,10 @@ processParms (ast * func,
       actParm->right = pTree;
       actParm->etype = defParm->etype;
       actParm->ftype = defParm->type;
+      actParm->decorated=0; /* force typechecking */
+      decorateType (actParm);
     }
 
-/*    actParm->argSym = resolveFromTable(defParm)->sym ; */
-
-  actParm->argSym = defParm->sym;
   /* make a copy and change the regparm type to the defined parm */
   actParm->etype = getSpec (actParm->ftype = copyLinkChain (actParm->ftype));
   SPEC_REGPARM (actParm->etype) = SPEC_REGPARM (defParm->etype);
@@ -801,6 +793,7 @@ ast *
 createIvalStruct (ast * sym, sym_link * type, initList * ilist)
 {
   ast *rast = NULL;
+  ast *lAst;
   symbol *sflds;
   initList *iloop;
 
@@ -815,8 +808,6 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
 
   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
     {
-      ast *lAst;
-
       /* if we have come to end */
       if (!iloop)
        break;
@@ -1036,6 +1027,8 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
 /* this has to go */ void printIval (symbol *, sym_link *, initList *, FILE *);
 
 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
+  ast *ast;
+  symbol *newSym;
 
   if (getenv("TRY_THE_NEW_INITIALIZER")) {
 
@@ -1045,58 +1038,24 @@ ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
       exit(404);
     }
 
-    if (SPEC_OCLS(sym->type->next)!=xdata) {
-      fprintf (stderr, "Can't \"TRY_THE_NEW_INITALIZER\" unless in xdata\n");
-      exit (405);
-    }
-    
-    if (getSize(sym->type) > 64) { // else it is'n worth it: do it the old way
-      // emit the inital values in cseg, then copy it to where it belongs
-      initList *iLoop;
-      int count, size=getSize(sym->type->next);
-      
-      if (ival->type != INIT_DEEP) {
-       werror (E_INIT_STRUCT, sym->name);
-       return NULL;
-      }
-      
-      tfprintf (code->oFile, "; initial data for %s\n", sym->name);
-      // TODO: this has to be a unique name
-      tfprintf (code->oFile, "_init_%s:", sym->name);
-      
-      for (count=0, iLoop=ival->init.deep; iLoop; iLoop=iLoop->next) {
-       count += size;
-       printIval (sym, sym->type->next, iLoop, code->oFile);
-      }
-      
-      // Now we only have to copy <count> bytes from cseg.
-      // This is VERY -mmcs51 --model-large specific for now, 
-      // in fact we should generate
-      // some icodes here that does the trick. But ok: experimental
-      // Trick: memcpy (sym->name, _init_(sym->name), count)
-      fprintf (statsg->oFile, ";       %s      %d\n", filename, sym->lineDef);
-      fprintf (statsg->oFile, ";       copy initial data from cseg _init_%s to %s\n", 
-              sym->name, sym->name);
-      fprintf (statsg->oFile, "        mov dptr,#_memcpy_PARM_2\n");
-      fprintf (statsg->oFile, "        mov a,#_init_%s\n", sym->name);
-      fprintf (statsg->oFile, "        movx @dptr,a\n");
-      fprintf (statsg->oFile, "        inc dptr\n");
-      fprintf (statsg->oFile, "        mov a,#(_init_%s>>8)\n", sym->name);
-      fprintf (statsg->oFile, "        movx @dptr,a\n");
-      fprintf (statsg->oFile, "        inc dptr\n");
-      fprintf (statsg->oFile, "        mov a,#%02x;    from cseg\n", 1);
-      fprintf (statsg->oFile, "        movx @dptr,a\n");
-      fprintf (statsg->oFile, "        mov dptr,#_memcpy_PARM_3\n");
-      fprintf (statsg->oFile, "        mov a,#(%d>>0); number of bytes\n", count);
-      fprintf (statsg->oFile, "        movx @dptr,a\n");
-      fprintf (statsg->oFile, "        inc dptr\n");
-      fprintf (statsg->oFile, "        mov a,#(%d>>8)\n", count);
-      fprintf (statsg->oFile, "        movx @dptr,a\n");
-      fprintf (statsg->oFile, "        mov dptr,#_%s\n", sym->name);
-      fprintf (statsg->oFile, "        mov b,#%02x;    only to xseg for now\n", 2);
-      fprintf (statsg->oFile, "        lcall _memcpy\n");
-      
-      return NULL;
+    if (SPEC_OCLS(sym->etype)==xdata &&
+       getSize(sym->type) > 16) { // else it isn't worth it: do it the old way
+
+      // copy this symbol
+      newSym=copySymbol (sym);
+      SPEC_OCLS(newSym->etype)=code;
+      sprintf (newSym->name, "%s_init__", sym->name);
+      sprintf (newSym->rname,"%s_init__", sym->rname);
+      addSym (SymbolTab, newSym, newSym->name, 0, 0, 1);
+
+      // emit it in the static segment
+      addSet(&statsg->syms, newSym);
+
+      // now memcpy() the entire array from cseg
+      ast=newNode (ARRAYINIT, // ASSIGN_AGGREGATE
+                  newAst_VALUE (symbolVal (sym)), 
+                  newAst_VALUE (symbolVal (newSym)));
+      return decorateType(resolveSymbols(ast));
     }
   }
   
@@ -1139,7 +1098,7 @@ gatherAutoInit (symbol * autoChain)
          /* insert the symbol into the symbol table */
          /* with level = 0 & name = rname       */
          newSym = copySymbol (sym);
-         addSym (SymbolTab, newSym, newSym->name, 0, 0, 1);
+         addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
 
          /* now lift the code to main */
          if (IS_AGGREGATE (sym->type))
@@ -1235,8 +1194,8 @@ processBlockVars (ast * tree, int *stack, int action)
 
       if (action == ALLOCATE)
        {
-         autoInit = gatherAutoInit (tree->values.sym);
          *stack += allocVariables (tree->values.sym);
+         autoInit = gatherAutoInit (tree->values.sym);
 
          /* if there are auto inits then do them */
          if (autoInit)
@@ -1253,6 +1212,7 @@ processBlockVars (ast * tree, int *stack, int action)
 
 /*-----------------------------------------------------------------*/
 /* constExprValue - returns the value of a constant expression     */
+/*                  or NULL if it is not a constant expression     */
 /*-----------------------------------------------------------------*/
 value *
 constExprValue (ast * cexpr, int check)
@@ -1868,31 +1828,6 @@ pushTypeCastToLeaves (sym_link * type, ast * node, ast ** parentPtr)
 
 #endif
 
-/*-----------------------------------------------------------------*/
-/* Given an assignment operation in a tree, determine if the LHS   */
-/* (the result) has a different (integer) type than the RHS.     */
-/* If so, walk the RHS and add a typecast to the type of the LHS   */
-/* to all leaf nodes.              */
-/*-----------------------------------------------------------------*/
-void 
-propAsgType (ast * tree)
-{
-#ifdef DEMAND_INTEGER_PROMOTION
-  if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
-    {
-      /* Nothing to do here... */
-      return;
-    }
-
-  if (getSize (LTYPE (tree)) > getSize (RTYPE (tree)))
-    {
-      pushTypeCastToLeaves (LTYPE (tree), tree->right, &(tree->right));
-    }
-#else
-  (void) tree;
-#endif
-}
-
 /*-----------------------------------------------------------------*/
 /* decorateType - compute type for this tree also does type cheking */
 /*          this is done bottom up, since type have to flow upwards */
@@ -1948,11 +1883,6 @@ decorateType (ast * tree)
 
          /* otherwise just copy the type information */
          COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
-         if (funcInChain (tree->opval.val->type))
-           {
-             tree->hasVargs = tree->opval.val->sym->hasVargs;
-             tree->args = copyValueChain (tree->opval.val->sym->args);
-           }
          return tree;
        }
 
@@ -1983,13 +1913,6 @@ decorateType (ast * tree)
 
                  /* and mark it as referenced */
                  tree->opval.val->sym->isref = 1;
-                 /* if this is of type function or function pointer */
-                 if (funcInChain (tree->opval.val->type))
-                   {
-                     tree->hasVargs = tree->opval.val->sym->hasVargs;
-                     tree->args = copyValueChain (tree->opval.val->sym->args);
-
-                   }
                }
            }
        }
@@ -2022,10 +1945,10 @@ decorateType (ast * tree)
 
   switch (tree->opval.op)
     {
-/*------------------------------------------------------------------*/
-/*----------------------------*/
-      /*        array node          */
-/*----------------------------*/
+           /*------------------------------------------------------------------*/
+           /*----------------------------*/
+           /*        array node          */
+           /*----------------------------*/
     case '[':
 
       /* determine which is the array & which the index */
@@ -2064,10 +1987,10 @@ decorateType (ast * tree)
       }
       return tree;
 
-/*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
       /*      struct/union          */
-/*----------------------------*/
+      /*----------------------------*/
     case '.':
       /* if this is not a structure */
       if (!IS_STRUCT (LTYPE (tree)))
@@ -2077,14 +2000,14 @@ decorateType (ast * tree)
        }
       TTYPE (tree) = structElemType (LTYPE (tree),
                                     (tree->right->type == EX_VALUE ?
-                              tree->right->opval.val : NULL), &tree->args);
+                              tree->right->opval.val : NULL));
       TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
-/*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
       /*    struct/union pointer    */
-/*----------------------------*/
+      /*----------------------------*/
     case PTR_OP:
       /* if not pointer to a structure */
       if (!IS_PTR (LTYPE (tree)))
@@ -2101,7 +2024,7 @@ decorateType (ast * tree)
 
       TTYPE (tree) = structElemType (LTYPE (tree)->next,
                                     (tree->right->type == EX_VALUE ?
-                              tree->right->opval.val : NULL), &tree->args);
+                              tree->right->opval.val : NULL));
       TETYPE (tree) = getSpec (TTYPE (tree));
       return tree;
 
@@ -2114,7 +2037,7 @@ decorateType (ast * tree)
       {
        sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
        COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
-       if (!tree->initMode && IS_CONSTANT (TETYPE (tree)))
+       if (!tree->initMode && IS_CONSTANT(TETYPE(tree)))
          werror (E_CODE_WRITE, "++/--");
 
        if (tree->right)
@@ -2136,7 +2059,7 @@ decorateType (ast * tree)
          if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
            {
              werror (E_BITWISE_OP);
-             werror (E_CONTINUE, "left & right types are ");
+             werror (W_CONTINUE, "left & right types are ");
              printTypeChain (LTYPE (tree), stderr);
              fprintf (stderr, ",");
              printTypeChain (RTYPE (tree), stderr);
@@ -2211,7 +2134,7 @@ decorateType (ast * tree)
       /* if bit field then error */
       if (IS_BITVAR (tree->left->etype))
        {
-         werror (E_ILLEGAL_ADDR, "addrress of bit variable");
+         werror (E_ILLEGAL_ADDR, "address of bit variable");
          goto errorTreeReturn;
        }
 
@@ -2227,7 +2150,13 @@ decorateType (ast * tree)
          goto errorTreeReturn;
        }
 
-      if (LRVAL (tree))
+      if (IS_LITERAL(LTYPE(tree)))
+       {
+         werror (E_ILLEGAL_ADDR, "address of literal");
+         goto errorTreeReturn;
+       }
+
+     if (LRVAL (tree))
        {
          werror (E_LVALUE_REQUIRED, "address of");
          goto errorTreeReturn;
@@ -2282,7 +2211,7 @@ decorateType (ast * tree)
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
        {
          werror (E_BITWISE_OP);
-         werror (E_CONTINUE, "left & right types are ");
+         werror (W_CONTINUE, "left & right types are ");
          printTypeChain (LTYPE (tree), stderr);
          fprintf (stderr, ",");
          printTypeChain (RTYPE (tree), stderr);
@@ -2344,7 +2273,7 @@ decorateType (ast * tree)
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
        {
          werror (E_BITWISE_OP);
-         werror (E_CONTINUE, "left & right types are ");
+         werror (W_CONTINUE, "left & right types are ");
          printTypeChain (LTYPE (tree), stderr);
          fprintf (stderr, ",");
          printTypeChain (RTYPE (tree), stderr);
@@ -2389,9 +2318,7 @@ decorateType (ast * tree)
            }
          TTYPE (tree) = copyLinkChain ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) ?
                                        LTYPE (tree)->next : NULL);
-         TETYPE (tree) = getSpec (TTYPE (tree));
-         tree->args = tree->left->args;
-         tree->hasVargs = tree->left->hasVargs;
+         TETYPE (tree) = getSpec (TTYPE (tree));
          SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree));
          return tree;
        }
@@ -2703,7 +2630,7 @@ decorateType (ast * tree)
       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
        {
          werror (E_SHIFT_OP_INVALID);
-         werror (E_CONTINUE, "left & right types are ");
+         werror (W_CONTINUE, "left & right types are ");
          printTypeChain (LTYPE (tree), stderr);
          fprintf (stderr, ",");
          printTypeChain (RTYPE (tree), stderr);
@@ -2749,10 +2676,10 @@ decorateType (ast * tree)
        }
       return tree;
 
-/*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
       /*         casting            */
-/*----------------------------*/
+      /*----------------------------*/
     case CAST:                 /* change the type   */
       /* cannot cast to an aggregate type */
       if (IS_AGGREGATE (LTYPE (tree)))
@@ -2764,24 +2691,57 @@ decorateType (ast * tree)
       /* make sure the type is complete and sane */
       checkTypeSanity(LETYPE(tree), "(cast)");
 
+#if 0
       /* if the right is a literal replace the tree */
-      if (IS_LITERAL (RETYPE (tree)) && !IS_PTR (LTYPE (tree)))
-       {
-         tree->type = EX_VALUE;
-         tree->opval.val =
-           valCastLiteral (LTYPE (tree),
-                           floatFromVal (valFromType (RETYPE (tree))));
-         tree->left = NULL;
-         tree->right = NULL;
-         TTYPE (tree) = tree->opval.val->type;
-         tree->values.literalFromCast = 1;
-       }
-      else
-       {
-         TTYPE (tree) = LTYPE (tree);
-         LRVAL (tree) = 1;
-       }
-
+      if (IS_LITERAL (RETYPE (tree))) {
+             if (!IS_PTR (LTYPE (tree))) {
+                     tree->type = EX_VALUE;
+                     tree->opval.val =
+                             valCastLiteral (LTYPE (tree),
+                                             floatFromVal (valFromType (RETYPE (tree))));
+                     tree->left = NULL;
+                     tree->right = NULL;
+                     TTYPE (tree) = tree->opval.val->type;
+                     tree->values.literalFromCast = 1;
+             } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) && 
+                        ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
+                     sym_link *rest = LTYPE(tree)->next;
+                     werror(W_LITERAL_GENERIC);                      
+                     TTYPE(tree) = newLink();
+                     DCL_TYPE(TTYPE(tree)) = FPOINTER;
+                     TTYPE(tree)->next = rest;
+                     tree->left->opval.lnk = TTYPE(tree);
+                     LRVAL (tree) = 1;
+             } else {
+                     TTYPE (tree) = LTYPE (tree);
+                     LRVAL (tree) = 1;
+             }
+      } else {
+             TTYPE (tree) = LTYPE (tree);
+             LRVAL (tree) = 1;
+      }
+#else
+      /* if pointer to struct then check names */
+      if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
+         IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
+         strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag)) {
+             werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,SPEC_STRUCT(LETYPE(tree))->tag);
+      }
+      /* if the right is a literal replace the tree */
+      if (IS_LITERAL (RETYPE (tree)) && !IS_PTR (LTYPE (tree))) {
+       tree->type = EX_VALUE;
+       tree->opval.val =
+         valCastLiteral (LTYPE (tree),
+                         floatFromVal (valFromType (RETYPE (tree))));
+       tree->left = NULL;
+       tree->right = NULL;
+       TTYPE (tree) = tree->opval.val->type;
+       tree->values.literalFromCast = 1;
+      } else {
+       TTYPE (tree) = LTYPE (tree);
+       LRVAL (tree) = 1;
+      }
+#endif      
       TETYPE (tree) = getSpec (TTYPE (tree));
 
       return tree;
@@ -2907,15 +2867,25 @@ decorateType (ast * tree)
                               tree->opval.val->type);
       return tree;
 
-/*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*------------------------------------------------------------------*/
+      /*----------------------------*/
       /* conditional operator  '?'  */
-/*----------------------------*/
+      /*----------------------------*/
     case '?':
       /* the type is value of the colon operator (on the right) */
       assert(IS_COLON_OP(tree->right));
-      TTYPE (tree) = RTYPE(tree); // #HACK LTYPE(tree).
-      TETYPE (tree) = getSpec (TTYPE (tree));
+      /* 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 tree->right->left ;
+         } else {
+             return tree->right->right ;
+         }
+      } else {
+         TTYPE (tree) = RTYPE(tree); // #HACK LTYPE(tree).
+         TETYPE (tree) = getSpec (TTYPE (tree));
+      }
       return tree;
 
     case ':':
@@ -2957,8 +2927,6 @@ decorateType (ast * tree)
        }
       LLVAL (tree) = 1;
 
-      propAsgType (tree);
-
       return tree;
 
     case AND_ASSIGN:
@@ -2986,8 +2954,6 @@ decorateType (ast * tree)
        }
       LLVAL (tree) = 1;
 
-      propAsgType (tree);
-
       return tree;
 
 /*------------------------------------------------------------------*/
@@ -3023,8 +2989,6 @@ decorateType (ast * tree)
        }
       LLVAL (tree) = 1;
 
-      propAsgType (tree);
-
       return tree;
 
 /*------------------------------------------------------------------*/
@@ -3068,8 +3032,6 @@ decorateType (ast * tree)
       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right));
       tree->opval.op = '=';
 
-      propAsgType (tree);
-
       return tree;
 
 /*------------------------------------------------------------------*/
@@ -3102,20 +3064,7 @@ decorateType (ast * tree)
       if (IS_VOID (LTYPE (tree)))
        {
          werror (E_CAST_ZERO);
-         fprintf (stderr, "type --> '");
-         printTypeChain (RTYPE (tree), stderr);
-         fprintf (stderr, "' ");
-         fprintf (stderr, "assigned to type --> '");
-         printTypeChain (LTYPE (tree), stderr);
-         fprintf (stderr, "'\n");
-       }
-
-      /* extra checks for pointer types */
-      if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)) &&
-         !IS_GENPTR (LTYPE (tree)))
-       {
-         if (DCL_TYPE (LTYPE (tree)) != DCL_TYPE (RTYPE (tree)))
-           werror (W_PTR_ASSIGN);
+         printFromToType(RTYPE(tree), LTYPE(tree));
        }
 
       TETYPE (tree) = getSpec (TTYPE (tree) =
@@ -3123,9 +3072,8 @@ decorateType (ast * tree)
       RRVAL (tree) = 1;
       LLVAL (tree) = 1;
       if (!tree->initMode ) {
-             if (IS_CONSTANT (LETYPE (tree))) {
-                     werror (E_CODE_WRITE, " ");
-             } 
+       if ((IS_SPEC(LETYPE(tree)) && IS_CONSTANT (LETYPE (tree))))
+         werror (E_CODE_WRITE, " ");
       }
       if (LRVAL (tree))
        {
@@ -3133,8 +3081,6 @@ decorateType (ast * tree)
          goto errorTreeReturn;
        }
 
-      propAsgType (tree);
-
       return tree;
 
 /*------------------------------------------------------------------*/
@@ -3153,17 +3099,18 @@ decorateType (ast * tree)
       parmNumber = 1;
 
       if (processParms (tree->left,
-                       tree->left->args,
-                       tree->right, &parmNumber, TRUE))
+                       FUNC_ARGS(tree->left->ftype),
+                       tree->right, &parmNumber, TRUE)) {
        goto errorTreeReturn;
+      }
 
-      if (options.stackAuto || IS_RENT (LETYPE (tree)))
+      if (options.stackAuto || IFFUNC_ISREENT (LTYPE (tree)))
        {
-         tree->left->args = reverseVal (tree->left->args);
+         //FUNC_ARGS(tree->left->ftype) = 
+         //reverseVal (FUNC_ARGS(tree->left->ftype));
          reverseParms (tree->right);
        }
 
-      tree->args = tree->left->args;
       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)->next);
       return tree;
 
@@ -3177,7 +3124,8 @@ decorateType (ast * tree)
 
       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
        {
-         werror (E_RETURN_MISMATCH);
+         werror (W_RETURN_MISMATCH);
+         printFromToType (RTYPE(tree), currFunc->type->next);
          goto errorTreeReturn;
        }
 
@@ -3192,19 +3140,10 @@ decorateType (ast * tree)
       /* if there is going to be a casing required then add it */
       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
        {
-#if 0 && defined DEMAND_INTEGER_PROMOTION
-         if (IS_INTEGRAL (currFunc->type->next))
-           {
-             pushTypeCastToLeaves (currFunc->type->next, tree->right, &(tree->right));
-           }
-         else
-#endif
-           {
-             tree->right =
-               decorateType (newNode (CAST,
-                        newAst_LINK (copyLinkChain (currFunc->type->next)),
-                                      tree->right));
-           }
+         tree->right =
+           decorateType (newNode (CAST,
+                          newAst_LINK (copyLinkChain (currFunc->type->next)),
+                                  tree->right));
        }
 
       RRVAL (tree) = 1;
@@ -3586,8 +3525,12 @@ createIf (ast * condAst, ast * ifBody, ast * elseBody)
   symbol *ifTrue, *ifFalse, *ifEnd;
 
   /* if neither exists */
-  if (!elseBody && !ifBody)
-    return condAst;
+  if (!elseBody && !ifBody) {
+    // if there are no side effects (i++, j() etc)
+    if (!hasSEFcalls(condAst)) {
+      return condAst;
+    }
+  }
 
   /* create the labels */
   sprintf (buffer, "_iffalse_%d", Lblnum);
@@ -4165,8 +4108,11 @@ createFunction (symbol * name, ast * body)
   sym_link *fetype;
   iCode *piCode = NULL;
 
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
+
   /* if check function return 0 then some problem */
-  if (checkFunction (name) == 0)
+  if (checkFunction (name, NULL) == 0)
     return NULL;
 
   /* create a dummy block if none exists */
@@ -4195,27 +4141,30 @@ createFunction (symbol * name, ast * body)
     }
   name->lastLine = yylineno;
   currFunc = name;
-  processFuncArgs (currFunc, 0);
+
+#if 0 // jwk: this is now done in addDecl()
+  processFuncArgs (currFunc);
+#endif
 
   /* set the stack pointer */
   /* PENDING: check this for the mcs51 */
   stackPtr = -port->stack.direction * port->stack.call_overhead;
-  if (IS_ISR (name->etype))
+  if (IFFUNC_ISISR (name->type))
     stackPtr -= port->stack.direction * port->stack.isr_overhead;
-  if (IS_RENT (name->etype) || options.stackAuto)
+  if (IFFUNC_ISREENT (name->type) || options.stackAuto)
     stackPtr -= port->stack.direction * port->stack.reent_overhead;
 
   xstackPtr = -port->stack.direction * port->stack.call_overhead;
 
   fetype = getSpec (name->type);       /* get the specifier for the function */
   /* if this is a reentrant function then */
-  if (IS_RENT (fetype))
+  if (IFFUNC_ISREENT (name->type))
     reentrant++;
 
-  allocParms (name->args);     /* allocate the parameters */
+  allocParms (FUNC_ARGS(name->type));  /* allocate the parameters */
 
   /* do processing for parameters that are passed in registers */
-  processRegParms (name->args, body);
+  processRegParms (FUNC_ARGS(name->type), body);
 
   /* set the stack pointer */
   stackPtr = 0;
@@ -4236,10 +4185,11 @@ createFunction (symbol * name, ast * body)
   body = resolveSymbols (body);        /* resolve the symbols */
   body = decorateType (body);  /* propagateType & do semantic checks */
 
-  ex = newAst_VALUE (symbolVal (name));                /* create name       */
+  ex = newAst_VALUE (symbolVal (name));        /* create name */
   ex = newNode (FUNCTION, ex, body);
-  ex->values.args = name->args;
-
+  ex->values.args = FUNC_ARGS(name->type);
+  ex->decorated=1;
+  if (options.dump_tree) PA(ex);
   if (fatalError)
     {
       werror (E_FUNC_NO_CODE, name->name);
@@ -4273,16 +4223,16 @@ skipall:
   /* dealloc the block variables */
   processBlockVars (body, &stack, DEALLOCATE);
   /* deallocate paramaters */
-  deallocParms (name->args);
+  deallocParms (FUNC_ARGS(name->type));
 
-  if (IS_RENT (fetype))
+  if (IFFUNC_ISREENT (name->type))
     reentrant--;
 
   /* we are done freeup memory & cleanup */
   noLineno--;
   labelKey = 1;
   name->key = 0;
-  name->fbody = 1;
+  FUNC_HASBODY(name->type) = 1;
   addSet (&operKeyReset, name);
   applyToSet (operKeyReset, resetParmKey);
 
@@ -4329,25 +4279,40 @@ void ast_print (ast * tree, FILE *outfile, int indent)
        }
        
        if (tree->opval.op == FUNCTION) {
-               fprintf(outfile,"FUNCTION (%p) type (",tree);
+               int arg=0;
+               value *args=FUNC_ARGS(tree->left->opval.val->type);
+               fprintf(outfile,"FUNCTION (%s=%p) type (", 
+                       tree->left->opval.val->name, tree);
                printTypeChain (tree->ftype,outfile);
+               fprintf(outfile,") args (");
+               do {
+                 if (arg) {
+                   fprintf (outfile, ", ");
+                 }
+                 printTypeChain (args ? args->type : NULL, outfile);
+                 arg++;
+                 args= args ? args->next : NULL;
+               } while (args);
                fprintf(outfile,")\n");
-               ast_print(tree->left,outfile,indent+4);
-               ast_print(tree->right,outfile,indent+4);
+               ast_print(tree->left,outfile,indent);
+               ast_print(tree->right,outfile,indent);
                return ;
        }
        if (tree->opval.op == BLOCK) {
                symbol *decls = tree->values.sym;
+               INDENT(indent,outfile);
                fprintf(outfile,"{\n");
                while (decls) {
                        INDENT(indent+4,outfile);
-                       fprintf(outfile,"DECLARE SYMBOL %s, type(",decls->name);
+                       fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
+                               decls->name, decls);
                        printTypeChain(decls->type,outfile);
                        fprintf(outfile,")\n");
                        
                        decls = decls->next;                    
                }
                ast_print(tree->right,outfile,indent+4);
+               INDENT(indent,outfile);
                fprintf(outfile,"}\n");
                return;
        }
@@ -4380,7 +4345,8 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                        } else {
                                fprintf(outfile,"SYMBOL ");
                        }
-                       fprintf(outfile,"(%p) name= %s ",tree,tree->opval.val->sym->name);
+                       fprintf(outfile,"(%s=%p)",
+                               tree->opval.val->sym->name,tree);
                }
                if (tree->ftype) {
                        fprintf(outfile," type (");
@@ -4653,7 +4619,9 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                /*         casting            */
                /*----------------------------*/
        case CAST:                      /* change the type   */
-               fprintf(outfile,"CAST (%p) type (",tree);
+               fprintf(outfile,"CAST (%p) from type (",tree);
+               printTypeChain(tree->right->ftype,outfile);
+               fprintf(outfile,") to type (");
                printTypeChain(tree->ftype,outfile);
                fprintf(outfile,")\n");
                ast_print(tree->right,outfile,indent+4);
@@ -4737,6 +4705,7 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                fprintf(outfile,")\n");
                ast_print(tree->left,outfile,indent+4);
                ast_print(tree->right,outfile,indent+4);
+               return;
 
        case ':':
                fprintf(outfile,"COLON(:) (%p) type (",tree);
@@ -4856,10 +4825,9 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                ast_print(tree->right,outfile,indent+4);
                return;
        case PARAM:
-               fprintf(outfile,"PARM ");
+               fprintf(outfile,"PARMS\n");
                ast_print(tree->left,outfile,indent+4);
                if (tree->right && !IS_AST_PARAM(tree->right)) {
-                       fprintf(outfile,"PARM ");
                        ast_print(tree->right,outfile,indent+4);
                }
                return ;
@@ -4906,18 +4874,17 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                /* ifx Statement              */
                /*----------------------------*/
        case IFX:
-               ast_print(tree->left,outfile,indent);
-               INDENT(indent,outfile);
                fprintf(outfile,"IF (%p) \n",tree);
+               ast_print(tree->left,outfile,indent+4);
                if (tree->trueLabel) {
                        INDENT(indent,outfile);
-                       fprintf(outfile,"NE(==) 0 goto %s\n",tree->trueLabel->name);
+                       fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
                }
                if (tree->falseLabel) {
                        INDENT(indent,outfile);
                        fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
                }
-               ast_print(tree->right,outfile,indent);
+               ast_print(tree->right,outfile,indent+4);
                return ;
                /*------------------------------------------------------------------*/
                /*----------------------------*/
@@ -4950,5 +4917,5 @@ void ast_print (ast * tree, FILE *outfile, int indent)
 
 void PA(ast *t)
 {
-       ast_print(t,stdout,1);
+       ast_print(t,stdout,0);
 }