fixed a compiler crash
[fw/sdcc] / src / SDCCicode.c
index c5bc3f15eb8a77665fb0ac47d42c1598531d7ad5..3968b3ea3302b07300dd5abbe717a535137d3928 100644 (file)
@@ -40,6 +40,13 @@ int scopeLevel;
 
 symbol *returnLabel;           /* function return label */
 symbol *entryLabel;            /* function entry  label */
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define LONG_LONG __int64
+#else
+#define LONG_LONG long long
+#endif
+
 /*-----------------------------------------------------------------*/
 /* forward definition of some functions */
 operand *geniCodeDivision (operand *, operand *);
@@ -113,6 +120,62 @@ iCodeTable codeTable[] =
   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
 };
 
+/*-----------------------------------------------------------------*/
+/* checkConstantRange: check a constant against the type           */
+/*-----------------------------------------------------------------*/
+
+/*   pedantic=0: allmost anything is allowed as long as the absolute
+       value is within the bit range of the type, and -1 is treated as
+       0xf..f for unsigned types (e.g. in assign)
+     pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
+     pedantic>1: "char c=200" is not allowed (evaluates to -56)
+*/
+
+void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
+  LONG_LONG max = (LONG_LONG) 1 << bitsForType(ltype);
+  char message[132]="";
+  int warnings=0;
+  int negative=0;
+  long v=SPEC_CVAL(val->type).v_long;
+
+#if 0
+  // this could be a good idea
+  if (options.pedantic)
+    pedantic=2;
+#endif
+
+  if (SPEC_NOUN(ltype)==FLOAT) {
+    // anything will do
+    return;
+  }
+
+  if (!SPEC_USIGN(val->type) && v<0) {
+    negative=1;
+    if (SPEC_USIGN(ltype) && (pedantic>1)) {
+      warnings++;
+    }
+    v=-v;
+  }
+
+  // if very pedantic: "char c=200" is not allowed
+  if (pedantic>1 && !SPEC_USIGN(ltype)) {
+    max = max/2 + negative;
+  }
+
+  if (v >= max) {
+    warnings++;
+  }
+
+  if (warnings) {
+    sprintf (message, "for %s %s in %s", 
+            SPEC_USIGN(ltype) ? "unsigned" : "signed",
+            nounName(ltype), msg);
+    werror (W_CONST_RANGE, message);
+
+    if (pedantic>1)
+      fatalError++;
+  }
+}
 
 /*-----------------------------------------------------------------*/
 /* operandName - returns the name of the operand                   */
@@ -1038,9 +1101,9 @@ isOperandEqual (operand * left, operand * right)
   return 0;
 }
 
-/*-----------------------------------------------------------------*/
-/* isiCodeEqual - comapres two iCodes are returns true if yes      */
-/*-----------------------------------------------------------------*/
+/*-------------------------------------------------------------------*/
+/* isiCodeEqual - compares two iCodes are equal, returns true if yes */
+/*-------------------------------------------------------------------*/
 int 
 isiCodeEqual (iCode * left, iCode * right)
 {
@@ -1074,6 +1137,7 @@ isiCodeEqual (iCode * left, iCode * right)
          if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
            return 0;
        }
+      
       return 1;
     }
   return 0;
@@ -1515,6 +1579,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
   sym_link *optype;
   sym_link *opetype = getSpec (optype = operandType (op));
   sym_link *restype;
+  int errors=0;
 
   /* one of them has size zero then error */
   if (IS_VOID (optype))
@@ -1532,20 +1597,69 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
     return operandFromValue (valCastLiteral (type,
                                             operandLitValue (op)));
 
-  /* if casting to some pointer type &&
-     the destination is not a generic pointer
-     then give a warning : (only for implicit casts) */
-  if (IS_PTR (optype) && implicit &&
-      (DCL_TYPE (optype) != DCL_TYPE (type)) &&
-      !IS_GENPTR (type))
-    {
-      werror (E_INCOMPAT_CAST);
-      fprintf (stderr, "from type '");
-      printTypeChain (optype, stderr);
-      fprintf (stderr, "' to type '");
-      printTypeChain (type, stderr);
-      fprintf (stderr, "'\n");
+  /* if casting to/from pointers, do some checking */
+  if (IS_PTR(type)) { // to a pointer
+    if (!IS_PTR(optype) && !IS_FUNC(optype)) { // from a non pointer
+      if (IS_INTEGRAL(optype)) { 
+       // maybe this is NULL, than it's ok.
+       if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
+         if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
+           // no way to set the storage
+           if (IS_LITERAL(optype)) {
+             werror(E_LITERAL_GENERIC);
+             errors++;
+           } else {
+             werror(E_NONPTR2_GENPTR);
+             errors++;
+           }
+         } else if (implicit) {
+           werror(W_INTEGRAL2PTR_NOCAST);
+           errors++;
+         }
+       }
+      }        else { 
+       // shouldn't do that with float, array or structure unless to void
+       if (!IS_VOID(getSpec(type)) && 
+           !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+         werror(E_INCOMPAT_TYPES);
+         errors++;
+       }
+      }
+    } else { // from a pointer to a pointer
+      if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
+       // if not a pointer to a function
+       if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+         if (implicit) { // if not to generic, they have to match 
+           if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
+             werror(E_INCOMPAT_PTYPES);
+             errors++;
+           }
+         }
+       }
+      }
+    }
+  } else { // to a non pointer
+    if (IS_PTR(optype)) { // from a pointer
+      if (implicit) { // sneaky
+       if (IS_INTEGRAL(type)) {
+         werror(W_PTR2INTEGRAL_NOCAST);
+         errors++;
+       } else { // shouldn't do that with float, array or structure
+         werror(E_INCOMPAT_TYPES);
+         errors++;
+       }
+      }
     }
+  }
+  if (errors) {
+    /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
+       implicit?"(implicit)":"", errors); */
+    fprintf (stderr, "from type '");
+    printTypeChain (optype, stderr);
+    fprintf (stderr, "' to type '");
+    printTypeChain (type, stderr);
+    fprintf (stderr, "'\n");
+  }
 
   /* if they are the same size create an assignment */
   if (getSize (type) == getSize (optype) &&
@@ -2381,12 +2495,6 @@ geniCodeRightShift (operand * left, operand * right)
   return IC_RESULT (ic);
 }
 
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define LONG_LONG __int64
-#else
-#define LONG_LONG long long
-#endif
-
 /*-----------------------------------------------------------------*/
 /* geniCodeLogic- logic code                                       */
 /*-----------------------------------------------------------------*/
@@ -2400,13 +2508,10 @@ geniCodeLogic (operand * left, operand * right, int op)
 
   /* left is integral type and right is literal then
      check if the literal value is within bounds */
-  if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
+  if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
     {
-      int nbits = bitsForType (ltype);
-      long v = (long) operandLitValue (right);
-
-      if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
-       werror (W_CONST_RANGE, " compare operation ");
+      checkConstantRange(ltype, 
+                        OP_VALUE(right), "compare operation", 1);
     }
 
   ctype = usualBinaryConversions (&left, &right);
@@ -2498,11 +2603,8 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
      check if the literal value is within bounds */
   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
     {
-      int nbits = bitsForType (ltype);
-      long v = (long) operandLitValue (right);
-
-      if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
-       werror (W_CONST_RANGE, " = operation");
+      checkConstantRange(ltype, 
+                        OP_VALUE(right), "= operation", 0);
     }
 
   /* if the left & right type don't exactly match */
@@ -2665,7 +2767,8 @@ geniCodeCall (operand * left, ast * parms,int lvl)
   sym_link *type, *etype;
   int stack = 0;
 
-  if (!IS_FUNC(OP_SYMBOL(left)->type)) {
+  if (!IS_FUNC(OP_SYMBOL(left)->type) && 
+      !IS_CODEPTR(OP_SYMBOL(left)->type)) {
     werror (E_FUNCTION_EXPECTED);
     return NULL;
   }
@@ -3034,8 +3137,16 @@ geniCodeArrayInit (ast * tree, operand *array)
 {
   iCode *ic;
 
-  ic = newiCode (ARRAYINIT, array, NULL);
-  IC_ARRAYILIST (ic) = tree->values.constlist;
+  if (!getenv("TRY_THE_NEW_INITIALIZER")) {
+    ic = newiCode (ARRAYINIT, array, NULL);
+    IC_ARRAYILIST (ic) = tree->values.constlist;
+  } else {
+    operand *left=newOperand(), *right=newOperand();
+    left->type=right->type=SYMBOL;
+    OP_SYMBOL(left)=AST_SYMBOL(tree->left);
+    OP_SYMBOL(right)=AST_SYMBOL(tree->right);
+    ic = newiCode (ARRAYINIT, left, right);
+  }
   ADDTOCHAIN (ic);
 }
 
@@ -3188,8 +3299,9 @@ ast2iCode (ast * tree,int lvl)
 
     case '[':                  /* array operation */
       {
-       sym_link *ltype = operandType (left);
-       left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+       //sym_link *ltype = operandType (left);
+       //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
+       left = geniCodeRValue (left, FALSE);
        right = geniCodeRValue (right, TRUE);
       }