* src/pic16/device.c (pic16_dump_section): fixed a bug that allowed
[fw/sdcc] / src / SDCCsymt.c
index d3bfee79b661bfee51ab05509da4d5798c60753d..43996bf36bbbe4ad6a80995fd3cb5b77f4b3f952 100644 (file)
@@ -293,6 +293,7 @@ newSymbol (char *name, int scope)
   sym->level = scope;          /* set the level    */
   sym->block = currBlockno;
   sym->lineDef = mylineno;     /* set the line number */
+  sym->fileDef = currFname;
   return sym;
 }
 
@@ -1518,7 +1519,9 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
   sym_link *rType;
   sym_link *reType;
   sym_link *etype1 = getSpec (type1);
-  sym_link *etype2 = getSpec (type2);
+  sym_link *etype2;
+   
+  etype2 = type2 ? getSpec (type2) : type1;
 
   /* if one of them is a float then result is a float */
   /* here we assume that the types passed are okay */
@@ -1553,18 +1556,57 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
   if (IS_CHAR (reType) && promoteCharToInt)
     SPEC_NOUN (reType) = V_INT;
 
-  if (   (   (   SPEC_USIGN (etype1)
-              /* if this operand is promoted to a larger
-                type don't check it's signedness */
-             && (getSize (etype1) >= getSize (reType))
-             /* We store signed literals in the range 0...255 as
-                'unsigned char'. If there was no promotion to 'signed int'
-                they must not force an unsigned operation: */
-             && !(IS_CHAR (etype1) && IS_LITERAL (etype1)))
-         || (   SPEC_USIGN (etype2)
-             && (getSize (etype2) >= getSize (reType))
-             && !(IS_CHAR (etype2) && IS_LITERAL (etype2))))
-      && !IS_FLOAT (reType))
+  /* SDCC's sign promotion:
+     - if one or both operands are unsigned, the resultant type will be unsigned
+       (except char, see below)
+     - if an operand is promoted to a larger type (char -> int, int -> long),
+       the larger type will be signed
+
+     SDCC tries hard to avoid promotion to int and does 8 bit calculation as
+     much as possible. We're leaving ISO IEC 9899 here and have to extrapolate
+     the standard. The standard demands, that the result has to be the same
+     "as if" the promotion would have been performed:
+
+     - if the result of an operation with two char's is promoted to a
+       larger type, the result will be signed.
+
+     More sophisticated is the last one:
+     - if the result of an operation with two char's is a char again,
+       the result will only then be unsigned, if both operands are
+       unsigned. In all other cases the result will be signed.
+
+       This seems to be contradictionary to the first two rules, but it makes
+       real sense (all types are char's):
+
+       A signed char can be negative; this must be preserved in the result
+               -1 * 100 = -100;
+
+       Only if both operands are unsigned it's safe to make the result
+       unsigned; this helps to avoid overflow:
+               2 * 100 =  200;
+
+     Homework: - why is (200 * 200 < 0) true?
+              - why is { char l = 200, r = 200; (r * l > 0) } true?
+  */
+
+  if (!IS_FLOAT (reType)
+      && (   (SPEC_USIGN (etype1)
+              /* if this operand is promoted to a larger type,
+                then it will be promoted to a signed type */
+             && !(getSize (etype1) < getSize (reType))
+              /* char require special handling */
+             && !IS_CHAR (etype1))
+         || /* same for 2nd operand */  
+            (SPEC_USIGN (etype2)
+             && !(getSize (etype2) < getSize (reType))
+             && !IS_CHAR (etype2))
+         || /* if both are 'unsigned char' and not promoted
+               let the result be unsigned too */
+            (   SPEC_USIGN (etype1)
+             && SPEC_USIGN (etype2)
+             && IS_CHAR (etype1)
+             && IS_CHAR (etype2)
+             && IS_CHAR (reType))))
     SPEC_USIGN (reType) = 1;
   else
     SPEC_USIGN (reType) = 0;
@@ -2151,10 +2193,9 @@ processFuncArgs (symbol * func)
   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
     fprintf (stderr, "SDCCsymt.c:processFuncArgs(%s)\n", func->name);
 
-  // if this is a pointer to a function
-  if (IS_PTR(funcType)) {
+  /* find the function declaration within the type */
+  while (funcType && !IS_FUNC(funcType))
     funcType=funcType->next;
-  }
 
   /* if this function has variable argument list */
   /* then make the function a reentrant one    */