* src/pic16/gen.c (pic16_emitpLabel,pic16_emitpLabelFORCE):
[fw/sdcc] / src / SDCCast.c
index 60f5a1d2ea3daf1c514abfb7500da30e8cbd3c21..a3cff8a4c5e5d5f77abd694c146614a2e3729eca 100644 (file)
@@ -84,12 +84,11 @@ static ast *
 newAst_ (unsigned type)
 {
   ast *ex;
-  static int oldLineno = 0;
 
   ex = Safe_alloc ( sizeof (ast));
 
   ex->type = type;
-  ex->lineno = (noLineno ? oldLineno : lexLineno);
+  ex->lineno = (noLineno ? 0 : lexLineno);
   ex->filename = lexFilename;
   ex->level = NestLevel;
   ex->block = currBlockno;
@@ -223,6 +222,7 @@ copyAst (ast * src)
   dest = Safe_alloc ( sizeof (ast));
 
   dest->type = src->type;
+  dest->filename = src->filename;
   dest->lineno = src->lineno;
   dest->level = src->level;
   dest->funcName = src->funcName;
@@ -616,17 +616,18 @@ resolveChildren:
   return tree;
 }
 
-/*-----------------------------------------------------------------*/
-/* setAstLineno - walks a ast tree & sets the line number          */
-/*-----------------------------------------------------------------*/
-int setAstLineno (ast * tree, int lineno)
+/*------------------------------------------------------------------------*/
+/* setAstFileLine - walks a ast tree & sets the file name and line number */
+/*------------------------------------------------------------------------*/
+int setAstFileLine (ast * tree, char *filename, int lineno)
 {
   if (!tree)
     return 0;
 
+  tree->filename = filename;
   tree->lineno = lineno;
-  setAstLineno (tree->left, lineno);
-  setAstLineno (tree->right, lineno);
+  setAstFileLine (tree->left, filename, lineno);
+  setAstFileLine (tree->right, filename, lineno);
   return 0;
 }
 
@@ -853,8 +854,12 @@ processParms (ast *func,
       ast *newType = NULL;
       sym_link *ftype;
 
-      if (IS_CAST_OP (*actParm)
-          || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
+      /* don't perform integer promotion of explicitly typecasted variable arguments
+       * if sdcc extensions are enabled */
+      if (options.std_sdcc && 
+        (IS_CAST_OP (*actParm) ||
+        (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
+        (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
         {
           /* Parameter was explicitly typecast; don't touch it. */
           return 0;
@@ -886,6 +891,7 @@ processParms (ast *func,
           /* cast required; change this op to a cast. */
           (*actParm)->decorated = 0;
            *actParm = newNode (CAST, newType, *actParm);
+          (*actParm)->filename = (*actParm)->right->filename;
           (*actParm)->lineno = (*actParm)->right->lineno;
 
           decorateType (*actParm, RESULT_TYPE_NONE);
@@ -996,10 +1002,14 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
 
     }
 
-  if (iloop) {
-    werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
-              W_EXCESS_INITIALIZERS, "struct",
-              sym->opval.val->sym->name);
+  if (iloop)
+    {
+      if (IS_AST_VALUE (sym))
+        werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
+                  W_EXCESS_INITIALIZERS, "struct",
+                  sym->opval.val->sym->name);
+      else
+        werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
   }
 
   return rast;
@@ -1298,7 +1308,7 @@ gatherAutoInit (symbol * autoChain)
                             list2expr (sym->ival));
           }
 
-          setAstLineno (work, sym->lineDef);
+          setAstFileLine (work, sym->fileDef, sym->lineDef);
 
           sym->ival = NULL;
           if (staticAutos)
@@ -1319,8 +1329,9 @@ gatherAutoInit (symbol * autoChain)
           }
 
           /* update lineno for error msg */
+          filename = sym->fileDef;
           lineno = sym->lineDef;
-          setAstLineno (ilist->init.node, sym->lineDef);
+          setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
 
           if (IS_AGGREGATE (sym->type)) {
             work = initAggregates (sym, sym->ival, NULL);
@@ -1335,7 +1346,7 @@ gatherAutoInit (symbol * autoChain)
           }
 
           // just to be sure
-          setAstLineno (work, sym->lineDef);
+          setAstFileLine (work, sym->fileDef, sym->lineDef);
 
           sym->ival = NULL;
           if (init)
@@ -1375,16 +1386,18 @@ stringToSymbol (value * val)
   unsigned int size;
 
   // have we heard this before?
-  for (sp=statsg->syms; sp; sp=sp->next) {
-    sym=sp->item;
-    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);
+  for (sp = statsg->syms; sp; sp = sp->next)
+    {
+      sym = sp->item;
+      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);
+        }
     }
-  }
 
   SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
   sym = newSymbol (name, 0);    /* make it @ level 0 */
@@ -1786,8 +1799,8 @@ astHasDeref (ast * tree)
 }
 
 /*-----------------------------------------------------------------*/
-/* isConformingBody - the loop body has to conform to a set of rules */
-/* for the loop to be considered reversible read on for rules      */
+/* isConformingBody - the loop body has to conform to a set of     */
+/* rules for the loop to be considered reversible read on for rules*/
 /*-----------------------------------------------------------------*/
 bool
 isConformingBody (ast * pbody, symbol * sym, ast * body)
@@ -1796,14 +1809,13 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
   /* we are going to do a pre-order traversal of the
      tree && check for the following conditions. (essentially
      a set of very shallow tests )
-     a) the sym passed does not participate in
-     any arithmetic operation
+     a) the sym passed does not participate in any arithmetic operation
      b) There are no function calls
      c) all jumps are within the body
      d) address of loop control variable not taken
-     e) if an assignment has a pointer on the
-     left hand side make sure right does not have
-     loop control variable */
+     e) if an assignment has a pointer on the left hand side make sure
+        right does not have loop control variable
+  */
 
   /* if we reach the end or a leaf then true */
   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
@@ -1858,9 +1870,9 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 
       /* if right is NULL then unary operation  */
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*  address of                */
-/*----------------------------*/
+      /*----------------------------*/
       if (!pbody->right)
         {
           if (IS_AST_SYM_VALUE (pbody->left) &&
@@ -1960,7 +1972,8 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       if (astHasVolatile (pbody->left))
         return FALSE;
 
-      if (astHasDeref(pbody->right)) return FALSE;
+      if (astHasDeref(pbody->right))
+        return FALSE;
 
       return isConformingBody (pbody->left, sym, body) &&
         isConformingBody (pbody->right, sym, body);
@@ -1977,27 +1990,31 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       assert ("Parser should not have generated this\n");
 
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*      comma operator        */
-/*----------------------------*/
+      /*----------------------------*/
     case ',':
       return isConformingBody (pbody->left, sym, body) &&
         isConformingBody (pbody->right, sym, body);
 
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*       function call        */
-/*----------------------------*/
+      /*----------------------------*/
     case CALL:
-        /* if local & not passed as paramater then ok */
-        if (sym->level && !astHasSymbol(pbody->right,sym))
+        /* if local & not passed as parameter &
+           not used to find the function then ok */
+        if (sym->level && !astHasSymbol (pbody->right, sym) &&
+            !astHasSymbol (pbody->left, sym))
+          {
             return TRUE;
+          }
       return FALSE;
 
 /*------------------------------------------------------------------*/
-/*----------------------------*/
+      /*----------------------------*/
       /*     return statement       */
-/*----------------------------*/
+      /*----------------------------*/
     case RETURN:
       return FALSE;
 
@@ -2016,9 +2033,6 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
 
   return isConformingBody (pbody->left, sym, body) &&
     isConformingBody (pbody->right, sym, body);
-
-
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -2112,7 +2126,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
                             end));
 
   replLoopSym (loop->left, sym);
-  setAstLineno (rloop, init->lineno);
+  setAstFileLine (rloop, init->filename, init->lineno);
 
   rloop = newNode (NULLOP,
                    newNode ('=',
@@ -2275,6 +2289,7 @@ addCast (ast *tree, RESULT_TYPE resultType, bool promote)
     }
   tree->decorated = 0;
   tree = newNode (CAST, newAst_LINK (newLink), tree);
+  tree->filename = tree->right->filename;
   tree->lineno = tree->right->lineno;
   /* keep unsigned type during cast to smaller type,
      but not when promoting from char to int */
@@ -2466,15 +2481,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 /*----------------------------*/
 /*   leaf has been reached    */
 /*----------------------------*/
+  filename = tree->filename;
   lineno = tree->lineno;
   /* if this is of type value */
   /* just get the type        */
   if (tree->type == EX_VALUE)
     {
-
       if (IS_LITERAL (tree->opval.val->etype))
         {
-
           /* if this is a character array then declare it */
           if (IS_ARRAY (tree->opval.val->type))
             tree->opval.val = stringToSymbol (tree->opval.val);
@@ -3129,6 +3143,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                   litTree->right = newNode ('*',
                                             litTree->right,
                                             copyAst (tree->right));
+                  litTree->right->filename = tree->filename;
                   litTree->right->lineno = tree->lineno;
 
                   tree->right->opval.val = constCharVal (1);
@@ -3676,6 +3691,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           tree->right = newNode (':',
                                   newAst_VALUE (constCharVal (1)),
                                   newAst_VALUE (constCharVal (0)));
+          tree->right->filename = tree->filename;
           tree->right->lineno = tree->lineno;
           tree->decorated = 0;
           return decorateType (tree, resultType);
@@ -3821,10 +3837,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       changePointer(LTYPE(tree));
       checkTypeSanity(LETYPE(tree), "(cast)");
 
-      /* if 'from' and 'to' are the same remove the superfluous cast, */
-      /* this helps other optimizations */
+
+      /* if 'from' and 'to' are the same remove the superfluous cast,
+       * this helps other optimizations */
       if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
         {
+          /* mark that the explicit cast has been removed,
+           * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
+          tree->right->values.removedCast = 1;
           return tree->right;
         }
 
@@ -3994,6 +4014,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           allocGlobal (sym);
 
           newTree->left = newAst_VALUE(symbolVal(sym));
+          newTree->left->filename = tree->filename;
           newTree->left->lineno = tree->lineno;
           LTYPE (newTree) = sym->type;
           LETYPE (newTree) = sym->etype;
@@ -4139,9 +4160,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                 if (!options.lessPedantic)
                   werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
                           ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
-                return decorateType (newAst_VALUE (constCharVal (
-                                   ccr_result == CCR_ALWAYS_TRUE ? 1 : 0)),
-                                                   resultType);
+                return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
               case CCR_OK:
               default:
                 break;
@@ -4166,7 +4185,9 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           tree->right = newNode (':',
                                   newAst_VALUE (constCharVal (1)),
                                   tree->right); /* val 0 */
+          tree->right->filename = tree->filename;
           tree->right->lineno = tree->lineno;
+          tree->right->left->filename = tree->filename;
           tree->right->left->lineno = tree->lineno;
           tree->decorated = 0;
           return decorateType (tree, resultType);
@@ -4271,6 +4292,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             tree->opval.op = transformedOp;
             tree->decorated = 0;
             tree = newNode ('!', tree, NULL);
+            tree->filename = tree->left->filename;
             tree->lineno = tree->left->lineno;
             return decorateType (tree, resultType);
           }
@@ -4965,6 +4987,7 @@ createBlock (symbol * decl, ast * body)
   ex->values.sym = decl;
 
   ex->level++;
+  ex->filename = NULL;
   ex->lineno = 0;
   return ex;
 }
@@ -5001,6 +5024,7 @@ createLabel (symbol * label, ast * stmnt)
   label->islbl = 1;
   label->key = labelKey++;
   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
+  rValue->filename = NULL;
   rValue->lineno = 0;
 
   return rValue;
@@ -5088,6 +5112,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
            (int) ulFromVal (caseVal->opval.val));
 
   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
+  rexpr->filename = 0;
   rexpr->lineno = 0;
   return rexpr;
 }
@@ -5323,10 +5348,12 @@ createWhile (symbol * trueLabel, symbol * continueLabel,
   /* put the continue label */
   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
   condExpr = createLabel (continueLabel, condExpr);
+  condExpr->filename = NULL;
   condExpr->lineno = 0;
 
   /* put the body label in front of the body */
   whileBody = createLabel (trueLabel, whileBody);
+  whileBody->filename = NULL;
   whileBody->lineno = 0;
   /* put a jump to continue at the end of the body */
   /* and put break label at the end of the body */
@@ -5963,8 +5990,8 @@ fixupInlineLabel (symbol * sym)
 static void
 copyAstLoc (ast * dest, ast * src)
 {
-  dest->lineno = src->lineno;
   dest->filename = src->filename;
+  dest->lineno = src->lineno;
   dest->level = src->level;
   dest->block = src->block;
   dest->seqPoint = src->seqPoint;
@@ -5980,13 +6007,13 @@ copyAstLoc (ast * dest, ast * src)
 static void
 fixupInline (ast * tree, int level)
 {
-  tree->block = currBlockno;
+  int savedBlockno = currBlockno;
 
   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
     {
       symbol * decls;
 
-      currBlockno++;
+      currBlockno = ++blockNo;
       level++;
 
       /* Add any declared variables back into the symbol table */
@@ -6001,6 +6028,7 @@ fixupInline (ast * tree, int level)
     }
 
   tree->level = level;
+  tree->block = currBlockno;
 
   /* Update symbols */
   if (IS_AST_VALUE (tree) &&
@@ -6073,6 +6101,7 @@ fixupInline (ast * tree, int level)
   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
     {
       level--;
+      currBlockno = savedBlockno;
     }
 }
 
@@ -6173,33 +6202,6 @@ inlineFindParm (ast * parms, int index)
   return inlineFindParmRecurse (parms, &index);
 }
 
-/*-----------------------------------------------------------------*/
-/* inlineFindMaxBlockno - find maximum block number in an ast tree */
-/*-----------------------------------------------------------------*/
-static int
-inlineFindMaxBlockno (ast * tree, int maxBlockno)
-{
-  int tempBlockno;
-
-  if (!tree)
-    return maxBlockno;
-
-  tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
-  if (tempBlockno > maxBlockno)
-    maxBlockno = tempBlockno;
-
-  tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
-  if (tempBlockno > maxBlockno)
-    maxBlockno = tempBlockno;
-
-  if (tree->block > maxBlockno)
-    maxBlockno = tree->block;
-  return maxBlockno;
-}
-
-
-
-
 /*-----------------------------------------------------------------*/
 /* expandInlineFuncs - replace calls to inline functions with the  */
 /*                     function itself                             */
@@ -6259,19 +6261,13 @@ expandInlineFuncs (ast * tree, ast * block)
           /* during the function call. For example, a function         */
           /* declared as func(int x, int y) but called as func(y,x).   */
           /* { //inlinetree block                                      */
-          /*   type1 temparg1;                                         */
+          /*   type1 temparg1 = argument1;                             */
           /*   ...                                                     */
-          /*   typen tempargn;                                         */
-          /*   temparg1 = argument1;                                   */
-          /*   ...                                                     */
-          /*   tempargn = argumentn;                                   */
+          /*   typen tempargn = argumentn;                             */
           /*   { //inlinetree2 block                                   */
-          /*     type1 param1;                                         */
-          /*     ...                                                   */
-          /*     typen paramn;                                         */
-          /*     param1 = temparg1;                                    */
+          /*     type1 param1 = temparg1;                              */
           /*     ...                                                   */
-          /*     paramn = tempargn;                                    */
+          /*     typen paramn = tempargn;                              */
           /*     inline_function_code;                                 */
           /*     retlab:                                               */
           /*   }                                                       */
@@ -6281,32 +6277,39 @@ expandInlineFuncs (ast * tree, ast * block)
           while (args)
             {
               symbol * temparg;
-              ast * passedarg;
               ast * assigntree;
-              symbol * parm = copySymbol (args->sym);
+              symbol * parm;
+              ast * passedarg = inlineFindParm (tree->right, argIndex);
+
+              if (!passedarg)
+                {
+                  werror(E_TOO_FEW_PARMS);
+                  break;
+                }
 
               temparg = inlineTempVar (args->sym->type, tree->level+1);
               inlineAddDecl (temparg, inlinetree, FALSE);
 
-              passedarg = inlineFindParm (tree->right, argIndex);
               assigntree = newNode ('=',
                                     newAst_VALUE (symbolVal (temparg)),
                                     passedarg);
+              assigntree->initMode=1; // tell that assignment is initializer
               inlinetree->right = newNode (NULLOP,
                                            assigntree,
                                            inlinetree->right);
 
+              parm = copySymbol (args->sym);
               inlineAddDecl (parm, inlinetree2, FALSE);
               parm->_isparm = 0;
 
               assigntree = newNode ('=',
                                     newAst_VALUE (symbolVal (parm)),
                                     newAst_VALUE (symbolVal (temparg)));
+              assigntree->initMode=1; // tell that assignment is initializer
               inlinetree2->right = newNode (NULLOP,
                                            assigntree,
                                            inlinetree2->right);
 
-
               args = args->next;
               argIndex++;
             }
@@ -6346,7 +6349,6 @@ expandInlineFuncs (ast * tree, ast * block)
           fixupInline (inlinetree, inlinetree->level);
           inlineState.count++;
         }
-
     }
 
   /* Recursively continue to search for functions to inline. */
@@ -6377,7 +6379,6 @@ createFunction (symbol * name, ast * body)
   int stack = 0;
   sym_link *fetype;
   iCode *piCode = NULL;
-  int savedBlockno;
 
   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
@@ -6434,10 +6435,7 @@ createFunction (symbol * name, ast * body)
     reentrant++;
 
   inlineState.count = 0;
-  savedBlockno = currBlockno;
-  currBlockno = inlineFindMaxBlockno (body, 0);
   expandInlineFuncs (body, NULL);
-  currBlockno = savedBlockno;
 
   if (FUNC_ISINLINE (name->type))
     name->funcTree = copyAst (body);