fixed bug#680076
[fw/sdcc] / src / SDCCast.c
index 2de2158f37dff16321db47cbab6970e3205e09df..4db1c15b6000e65ca99f3c446ae52214db7b6915 100644 (file)
@@ -186,8 +186,7 @@ copyAstValues (ast * dest, ast * src)
       break;
 
     case INLINEASM:
-      dest->values.inlineasm = Safe_alloc (strlen (src->values.inlineasm) + 1);
-      strcpy (dest->values.inlineasm, src->values.inlineasm);
+      dest->values.inlineasm =  Safe_strdup(src->values.inlineasm);
       break;
 
     case ARRAYINIT:
@@ -667,7 +666,20 @@ processParms (ast * func,
       if (IS_INTEGRAL (ftype)
          && (getSize (ftype) < (unsigned) INTSIZE))
        {
-         newType = newAst_LINK(INTTYPE);
+         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);
+         }
        }
 
       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
@@ -953,12 +965,9 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
                                   newAst_VALUE (valueFromLit ((float) i))),
                               newAst_VALUE (valueFromLit (*s))));
 
-      // now we don't need iexpr's symbol anymore
-      {
-       symbol *sym=AST_SYMBOL(iexpr);
-       memmap *segment=SPEC_OCLS(sym->etype);
-       deleteSetItem(&segment->syms, sym);
-      }
+      // now WE don't need iexpr's symbol anymore
+      freeStringSymbol(AST_SYMBOL(iexpr));
+
       return decorateType (resolveSymbols (rast));
     }
 
@@ -1122,6 +1131,20 @@ gatherAutoInit (symbol * autoChain)
   return init;
 }
 
+/*-----------------------------------------------------------------*/
+/* freeStringSymbol - delete a literal string if no more usage     */
+/*-----------------------------------------------------------------*/
+void freeStringSymbol(symbol *sym) {
+  /* make sure this is a literal string */
+  assert (sym->isstrlit);
+  if (--sym->isstrlit == 0) { // lower the usage count
+    memmap *segment=SPEC_OCLS(sym->etype);
+    if (segment) {
+      deleteSetItem(&segment->syms, sym);
+    }
+  }
+}
+  
 /*-----------------------------------------------------------------*/
 /* stringToSymbol - creates a symbol from a literal string         */
 /*-----------------------------------------------------------------*/
@@ -1131,10 +1154,22 @@ stringToSymbol (value * val)
   char name[SDCC_NAME_MAX + 1];
   static int charLbl = 0;
   symbol *sym;
+  set *sp;
+
+  // have we heard this before?
+  for (sp=statsg->syms; sp; sp=sp->next) {
+    sym=sp->item;
+    if (sym->isstrlit && 
+       !strcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char)) {
+      // yes, this is old news. Don't publish it again.
+      sym->isstrlit++; // but raise the usage count
+      return symbolVal(sym);
+    }
+  }
 
-  sprintf (name, "_str_%d", charLbl++);
+  SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
   sym = newSymbol (name, 0);   /* make it @ level 0 */
-  strcpy (sym->rname, name);
+  strncpyz (sym->rname, name, SDCC_NAME_MAX);
 
   /* copy the type from the value passed */
   sym->type = copyLinkChain (val->type);
@@ -1216,6 +1251,10 @@ bool constExprTree (ast *cexpr) {
        // a function's address will never change
        return TRUE;
       }
+      if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
+       // an array's address will never change
+       return TRUE;
+      }
       if (IS_AST_SYM_VALUE(cexpr) && 
          IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
        // a symbol in code space will never change
@@ -1275,7 +1314,7 @@ constExprValue (ast * cexpr, int check)
          val->sym = cexpr->opval.val->sym;
          val->sym->type = copyLinkChain (cexpr->ftype);
          val->sym->etype = getSpec (val->sym->type);
-         strcpy (val->name, cexpr->opval.val->sym->rname);
+         strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
          return val;
        }
 
@@ -1886,6 +1925,7 @@ decorateType (ast * tree)
 /*----------------------------*/
   /*   leaf has been reached    */
 /*----------------------------*/
+  lineno=tree->lineno;
   /* if this is of type value */
   /* just get the type        */
   if (tree->type == EX_VALUE)
@@ -1959,39 +1999,25 @@ decorateType (ast * tree)
     if (dtr != tree->right)
       tree->right = dtr;
 
-#if 0 // not sure yet if this covers all the cases
     if (IS_AST_OP(tree) &&
        (tree->opval.op == CAST || tree->opval.op == '=') &&
-       getSize(LTYPE(tree)) > getSize(RTYPE(tree))) {
+       (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) &&
+       (getSize(RTYPE(tree)) < INTSIZE)) {
       // this is a cast/assign to a bigger type
-      if (IS_AST_OP(tree->right) && tree->right->right &&
+      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 == '-')) {
-       // we should cast the operands instead of the result
-       fprintf (stderr, "*** we should promote operands instead of result\n");
-       fprintf (stderr, "(%d = %d op %d)\n", getSize(LTYPE(tree)),
-                getSize(LTYPE(tree->right)), getSize(RTYPE(tree->right)));
+          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);
       }
     }
-#else
-    /* special case for left shift operation : cast up right->left if type 
-       of left has greater size than right */
-    if (tree->left && tree->right && tree->right->opval.op == LEFT_OP) {
-       int lsize = getSize(LTYPE(tree));
-       int rsize = getSize(RTYPE(tree));
-
-       if (lsize > rsize) {
-           tree->right->decorated = 0;
-           tree->right->left = newNode( CAST, (lsize == 2 ? 
-                                              newAst_LINK(newIntLink()) : 
-                                              newAst_LINK(newLongLink())),
-                                       tree->right->left);
-           tree->right = decorateType(tree->right);
-       }
-      }
-#endif
   }
 
   /* depending on type of operator do */
@@ -2257,6 +2283,7 @@ decorateType (ast * tree)
        ast *wtree = optimizeRRCRLC (tree);
        if (wtree != tree)
          return decorateType (wtree);
+       // fall through
       }
       /*------------------------------------------------------------------*/
       /*----------------------------*/
@@ -2410,18 +2437,16 @@ decorateType (ast * tree)
        }
 
       LRVAL (tree) = RRVAL (tree) = 1;
+      TETYPE (tree) = getSpec (TTYPE (tree) =
+                              computeType (LTYPE (tree),
+                                           RTYPE (tree)));
+
       /* promote result to int if left & right are char
         this will facilitate hardware multiplies 8bit x 8bit = 16bit */
       if (IS_CHAR(LETYPE(tree)) && IS_CHAR(RETYPE(tree))) {
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree)));
        SPEC_NOUN(TETYPE(tree)) = V_INT;
-      } else {
-       TETYPE (tree) = getSpec (TTYPE (tree) =
-                                computeType (LTYPE (tree),
-                                             RTYPE (tree)));
       }
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2505,7 +2530,7 @@ decorateType (ast * tree)
 
       LRVAL (tree) = RRVAL (tree) = 1;
       /* if the left is a pointer */
-      if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
+      if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
        TETYPE (tree) = getSpec (TTYPE (tree) =
                                 LTYPE (tree));
       else
@@ -2706,46 +2731,24 @@ decorateType (ast * tree)
                                   tree->opval.val->type);
          return tree;
        }
-#if 0
-      /* a left shift must be done with at least 16bits */
-      if ((tree->opval.op==LEFT_OP) && (getSize(LTYPE(tree))<2)) {
-       // insert a cast
-       if (IS_AST_SYM_VALUE(tree->left) || IS_AST_OP(tree->left)) {
-         tree->left = 
-           decorateType (newNode (CAST,
-                                  newAst_LINK(copyLinkChain(LTYPE(tree))),
-                                  tree->left));
-         SPEC_NOUN(tree->left->left->ftype)=V_INT;
-       } else {
-         // must be a literal, we can do it right away
-         SPEC_NOUN(tree->left->opval.val->type)=V_INT;
-       }
-      }
-#endif
+
       /* if only the right side is a literal & we are
          shifting more than size of the left operand then zero */
       if (IS_LITERAL (RTYPE (tree)) &&
          ((unsigned) floatFromVal (valFromType (RETYPE (tree)))) >=
          (getSize (LTYPE (tree)) * 8))
        {
-           /* if left shift then cast up */
-           if (tree->opval.op==LEFT_OP) {
-               int size = getSize(LTYPE(tree));
-               tree->left = 
-                   decorateType (newNode (CAST,
-                                          (size == 1 ? newAst_LINK(newIntLink()) : 
-                                           (size == 2 ? newAst_LINK(newLongLink()) : 
-                                            newAst_LINK(newIntLink()))),
-                                          tree->left));
-           } else {
-               werror (W_SHIFT_CHANGED,
-                       (tree->opval.op == LEFT_OP ? "left" : "right"));
-               tree->type = EX_VALUE;
-               tree->left = tree->right = NULL;
-               tree->opval.val = constVal ("0");
-               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
-               return tree;
-           }
+         if (tree->opval.op==LEFT_OP ||
+             (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree)))) {
+           lineno=tree->lineno;
+           werror (W_SHIFT_CHANGED,
+                   (tree->opval.op == LEFT_OP ? "left" : "right"));
+           tree->type = EX_VALUE;
+           tree->left = tree->right = NULL;
+           tree->opval.val = constVal ("0");
+           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
+           return tree;
+         }
        }
       LRVAL (tree) = RRVAL (tree) = 1;
       if (IS_LITERAL (LTYPE (tree)) && !IS_LITERAL (RTYPE (tree)))
@@ -2892,10 +2895,17 @@ decorateType (ast * tree)
       /* if they are pointers they must be castable */
       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
        {
+         if (tree->opval.op==EQ_OP && 
+             !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
+           // we cannot cast a gptr to a !gptr: switch the leaves
+           struct ast *s=tree->left;
+           tree->left=tree->right;
+           tree->right=s;
+         }
          if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
            {
              werror (E_COMPARE_OP);
-             fprintf (stderr, "comparing type ");
+             fprintf (stderr, "comparring type ");
              printTypeChain (LTYPE (tree), stderr);
              fprintf (stderr, "to type ");
              printTypeChain (RTYPE (tree), stderr);
@@ -2957,7 +2967,7 @@ decorateType (ast * tree)
     case SIZEOF:               /* evaluate wihout code generation */
       /* change the type to a integer */
       tree->type = EX_VALUE;
-      sprintf (buffer, "%d", (getSize (tree->right->ftype)));
+      SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
       tree->opval.val = constVal (buffer);
       tree->right = tree->left = NULL;
       TETYPE (tree) = getSpec (TTYPE (tree) =
@@ -3030,7 +3040,7 @@ decorateType (ast * tree)
                    break;
                }
            }
-           sprintf (buffer, "%d", typeofv);
+           SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
            tree->opval.val = constVal (buffer);
            tree->right = tree->left = NULL;
            TETYPE (tree) = getSpec (TTYPE (tree) =
@@ -3410,7 +3420,7 @@ sizeofOp (sym_link * type)
   checkTypeSanity(type, "(sizeof)");
 
   /* get the size and convert it to character  */
-  sprintf (buff, "%d", getSize (type));
+  SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
 
   /* now convert into value  */
   return constVal (buff);
@@ -3444,7 +3454,7 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
       static int localLbl = 0;
       symbol *localLabel;
 
-      sprintf (buffer, "_and_%d", localLbl++);
+      SNPRINTF(buffer, sizeof(buffer), "_and_%d", localLbl++);
       localLabel = newSymbol (buffer, NestLevel);
 
       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
@@ -3470,7 +3480,7 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
       static int localLbl = 0;
       symbol *localLabel;
 
-      sprintf (buffer, "_or_%d", localLbl++);
+      SNPRINTF(buffer, sizeof(buffer), "_or_%d", localLbl++);
       localLabel = newSymbol (buffer, NestLevel);
 
       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
@@ -3562,7 +3572,7 @@ createLabel (symbol * label, ast * stmnt)
     label = newSymbol (label->name, label->level);
 
   /* change the name before putting it in add _ */
-  sprintf (name, "%s", label->name);
+  SNPRINTF(name, sizeof(name), "%s", label->name);
 
   /* put the label in the LabelSymbol table    */
   /* but first check if a label of the same    */
@@ -3650,7 +3660,8 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
     }
 
   /* create the case label   */
-  sprintf (caseLbl, "_case_%d_%d",
+  SNPRINTF(caseLbl, sizeof(caseLbl), 
+          "_case_%d_%d",
           swStat->values.switchVals.swNum,
           (int) floatFromVal (caseVal->opval.val));
 
@@ -3679,7 +3690,8 @@ createDefault (ast * swStat, ast * stmnt)
   swStat->values.switchVals.swDefault = 1;
 
   /* create the label  */
-  sprintf (defLbl, "_default_%d", swStat->values.switchVals.swNum);
+  SNPRINTF (defLbl, sizeof(defLbl),
+           "_default_%d", swStat->values.switchVals.swNum);
   return createLabel (newSymbol (defLbl, 0), stmnt);
 }
 
@@ -3702,18 +3714,18 @@ createIf (ast * condAst, ast * ifBody, ast * elseBody)
   }
 
   /* create the labels */
-  sprintf (buffer, "_iffalse_%d", Lblnum);
+  SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
   ifFalse = newSymbol (buffer, NestLevel);
   /* if no else body then end == false */
   if (!elseBody)
     ifEnd = ifFalse;
   else
     {
-      sprintf (buffer, "_ifend_%d", Lblnum);
+      SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
       ifEnd = newSymbol (buffer, NestLevel);
     }
 
-  sprintf (buffer, "_iftrue_%d", Lblnum);
+  SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
   ifTrue = newSymbol (buffer, NestLevel);
 
   Lblnum++;
@@ -4345,7 +4357,7 @@ createFunction (symbol * name, ast * body)
     name->stack = SPEC_STAK (fetype) = stack;
 
   /* name needs to be mangled */
-  sprintf (name->rname, "%s%s", port->fun_prefix, name->name);
+  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 */