* src/SDCCsymt.c (addDecl): fixed bug 1609244
[fw/sdcc] / src / SDCCsymt.c
index 8031d9fce9013670b908847798febf6a74f6f26d..c65c3e2f965da328d1853bce5a27131d975d9ff4 100644 (file)
@@ -438,6 +438,7 @@ pointerTypes (sym_link * ptr, sym_link * type)
 void 
 addDecl (symbol * sym, int type, sym_link * p)
 {
+  static sym_link *empty = NULL;
   sym_link *head;
   sym_link *tail;
   sym_link *t;
@@ -445,6 +446,9 @@ addDecl (symbol * sym, int type, sym_link * p)
   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
     fprintf (stderr, "SDCCsymt.c:addDecl(%s,%d,%p)\n", sym->name, type, p);
 
+  if (empty == NULL)
+    empty = newLink(SPECIFIER);
+
   /* if we are passed a link then set head & tail */
   if (p)
     {
@@ -464,28 +468,28 @@ addDecl (symbol * sym, int type, sym_link * p)
       sym->type = head;
       sym->etype = tail;
     }
+  else if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail)
+    {
+      sym->etype = mergeSpec (sym->etype, head, sym->name);
+    }
+  else if (IS_SPEC (sym->etype) && !IS_SPEC (head) && head == tail)
+    {
+      t = sym->type;
+      while (t->next != sym->etype)
+        t = t->next;
+      t->next = head;
+      tail->next = sym->etype;
+    }
+  else if (IS_FUNC (sym->type) && IS_SPEC (sym->type->next) &&
+           !memcmp(sym->type->next, empty, sizeof(sym_link)))
+    {
+      sym->type->next = head;
+      sym->etype = tail;
+    }
   else
     {
-      if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail)
-        {
-          sym->etype = mergeSpec (sym->etype, head, sym->name);
-        }
-      else
-        {
-          if (IS_SPEC (sym->etype) && !IS_SPEC (head) && head == tail)
-            {
-              t = sym->type;
-              while (t->next != sym->etype)
-                t = t->next;
-              t->next = head;
-              tail->next = sym->etype;
-            }
-          else
-            {
-              sym->etype->next = head;
-              sym->etype = tail;
-            }
-        }
+      sym->etype->next = head;
+      sym->etype = tail;
     }
 
   /* if the type is an unknown pointer and has
@@ -1587,6 +1591,7 @@ checkSClass (symbol * sym, int isProto)
         //!sym->level &&
         port->mem.code_ro &&
         !IS_EXTERN (sym->etype) &&
+        !SPEC_ABSA (sym->etype) &&
         !funcInChain (sym->type))
       werror (E_CODE_NO_INIT, sym->name);
   }
@@ -3125,7 +3130,7 @@ printTypeChainRaw (sym_link * start, FILE * of)
 /* powof2 - returns power of two for the number if number is pow 2 */
 /*-----------------------------------------------------------------*/
 int
-powof2 (TYPE_UDWORD num)
+powof2 (TYPE_TARGET_ULONG num)
 {
   int nshifts = 0;
   int n1s = 0;
@@ -3456,17 +3461,50 @@ initCSupport ()
         {
           for (muldivmod = 1; muldivmod < 3; muldivmod++)
             {
-              /* div and mod */
-              SNPRINTF (buffer, sizeof(buffer),
-                        "_%s%s%s",
-                       smuldivmod[muldivmod],
-                       ssu[su],
-                       sbwd[bwd]);
-              __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
-              FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+              /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */
+             if (!TARGET_IS_PIC16 || muldivmod != 1 || bwd != 0 || su != 0)
+             {
+               SNPRINTF (buffer, sizeof(buffer),
+                   "_%s%s%s",
+                   smuldivmod[muldivmod],
+                   ssu[su],
+                   sbwd[bwd]);
+               __muldiv[muldivmod][bwd][su] = funcOfType (
+                   _mangleFunctionName(buffer),
+                   __multypes[bwd][su],
+                   __multypes[bwd][su],
+                   2,
+                   options.intlong_rent);
+               FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+             }
             }
         }
     }
+
+  if (TARGET_IS_PIC16)
+  {
+    /* PIC16 port wants __divschar/__modschar to return an int, so that both
+     * 100 / -4 = -25 and -128 / -1 = 128 can be handled correctly
+     * (first one would have to be sign extended, second one must not be).
+     * Similarly, modschar should be handled, but the iCode introduces cast
+     * here and forces '% : s8 x s8 -> s8' ... */
+    su = 0; bwd = 0;
+    for (muldivmod = 1; muldivmod < 2; muldivmod++) {
+      SNPRINTF (buffer, sizeof(buffer),
+         "_%s%s%s",
+         smuldivmod[muldivmod],
+         ssu[su],
+         sbwd[bwd]);
+      __muldiv[muldivmod][bwd][su] = funcOfType (
+         _mangleFunctionName(buffer),
+         __multypes[1][su],
+         __multypes[bwd][su],
+         2,
+         options.intlong_rent);
+      FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+    }
+  }
+
   /* mul only */
   muldivmod = 0;
   /* byte */