* src/SDCCast.c (decorateType): fix promotion of unary minus
[fw/sdcc] / src / SDCCsymt.c
index a34b6bb736d602c8ddbc209803c53f2cbbffef60..5cb19d06a213d70c525258c6a943beac6e07f439 100644 (file)
@@ -796,7 +796,7 @@ newBoolLink ()
 }
 
 /*------------------------------------------------------------------*/
-/* getSize - returns size of a type chain in bits                   */
+/* getSize - returns size of a type chain in bytes                  */
 /*------------------------------------------------------------------*/
 unsigned int 
 getSize (sym_link * p)
@@ -860,29 +860,41 @@ getSize (sym_link * p)
     }
 }
 
-/*---------------------------------------------------------------------*/
-/* getAllocSize - returns size of a type chain in bytes for allocation */
-/*---------------------------------------------------------------------*/
-unsigned int
-getAllocSize (sym_link *p)
+/*------------------------------------------------------------------*/
+/* checkStructFlexArray - check tree behind a struct                */
+/*------------------------------------------------------------------*/
+static bool
+checkStructFlexArray (symbol *sym, sym_link *p)
 {
-  if (IS_STRUCT (p) && SPEC_STRUCT (p)->type == STRUCT)
-    {
-      /* if this is a struct specifier then  */
-      /* calculate the size as it could end  */
-      /* with an array of unspecified length */
-      symbol *sflds = SPEC_STRUCT (p)->fields;
+  /* if nothing return FALSE */
+  if (!p)
+    return FALSE;
 
-      while (sflds && sflds->next)
-        sflds = sflds->next;
+  if (IS_SPEC (p))
+    {
+      /* (nested) struct with flexible array member? */
+      if (IS_STRUCT (p) && SPEC_STRUCT (p)->b_flexArrayMember)
+        {
+          werror (W_INVALID_FLEXARRAY);
+          return FALSE;
+        }
+      return FALSE;
+    }
 
-      if (sflds && !IS_BITFIELD (sflds->type))
-        return sflds->offset + getAllocSize (sflds->type);
-      else
-        return SPEC_STRUCT (p)->size;
+  /* this is a declarator */
+  if (IS_ARRAY (p))
+    {
+      /* flexible array member? */
+      if (!DCL_ELEM(p))
+        {
+          if (!options.std_c99)
+            werror (W_C89_NO_FLEXARRAY);
+          return TRUE;
+        }
+      /* walk tree */
+      return checkStructFlexArray (sym, p->next);
     }
-  else
-    return getSize (p);
+  return FALSE;
 }
 
 /*------------------------------------------------------------------*/
@@ -1233,7 +1245,11 @@ compStructSize (int su, structdef * sdef)
 
             /* change it to a unsigned bit */
             SPEC_NOUN (loop->etype) = V_BITFIELD;
-            SPEC_USIGN (loop->etype) = 1;
+            /* ISO/IEC 9899 J.3.9 implementation defined behaviour: */
+            /* a "plain" int bitfield is unsigned */
+            if (!loop->etype->select.s.b_signed)
+              SPEC_USIGN(loop->etype) = 1;
+
             SPEC_BLEN (loop->etype) = loop->bitVar;
 
             if (loop->bitVar == BITVAR_PAD) {
@@ -1288,6 +1304,21 @@ compStructSize (int su, structdef * sdef)
             loop->offset = sum;
             checkDecl (loop, 1);
             sum += getSize (loop->type);
+
+            /* search for "flexibel array members" */
+            /* and do some syntax checks */
+            if (   su == STRUCT
+                && checkStructFlexArray (loop, loop->type))
+              {
+                /* found a "flexible array member" */
+                sdef->b_flexArrayMember = TRUE;
+                /* is another struct-member following? */
+                if (loop->next)
+                  werror (E_FLEXARRAY_NOTATEND);
+                /* is it the first struct-member? */
+                else if (loop == sdef->fields)
+                  werror (E_FLEXARRAY_INEMPTYSTRCT);
+              }
         }
 
         loop = loop->next;
@@ -1621,6 +1652,7 @@ copyLinkChain (sym_link * p)
 {
   sym_link *head, *curr, *loop;
 
+  /* note: v_struct and v_struct->fields are not copied! */
   curr = p;
   head = loop = (curr ? newLink (p->class) : (void *) NULL);
   while (curr)
@@ -1768,24 +1800,20 @@ computeType (sym_link * type1, sym_link * type2,
   /* which ever is greater in size */
   if (IS_FLOAT (etype1) || IS_FLOAT (etype2))
     rType = newFloatLink ();
-  else
-    /* if both are fixed16x16 then result is float */
-  if (IS_FIXED16X16(etype1) && IS_FIXED16X16(etype2))
+  /* if both are fixed16x16 then result is float */
+  else if (IS_FIXED16X16(etype1) && IS_FIXED16X16(etype2))
     rType = newFixed16x16Link();
-  else
-  if (IS_FIXED16X16(etype1) && IS_FLOAT (etype2))
+  else if (IS_FIXED16X16(etype1) && IS_FLOAT (etype2))
     rType = newFloatLink ();
-  if (IS_FLOAT (etype1) && IS_FIXED16X16 (etype2) )
+  else if (IS_FLOAT (etype1) && IS_FIXED16X16 (etype2) )
     rType = newFloatLink ();
-  else
-    /* if both are bitvars choose the larger one */
-  if (IS_BITVAR (etype1) && IS_BITVAR (etype2))
-    {
-      rType = SPEC_BLEN (etype1) >= SPEC_BLEN (etype2) ?
-                copyLinkChain (type1) : copyLinkChain (type1);
-    }
-    /* if only one of them is a bit variable
-       then the other one prevails */
+            
+  /* if both are bitvars choose the larger one */
+  else if (IS_BITVAR (etype1) && IS_BITVAR (etype2))
+    rType = SPEC_BLEN (etype1) >= SPEC_BLEN (etype2) ?
+            copyLinkChain (type1) : copyLinkChain (type1);
+                          
+  /* if only one of them is a bit variable then the other one prevails */
   else if (IS_BITVAR (etype1) && !IS_BITVAR (etype2))
     {
       rType = copyLinkChain (type2);
@@ -1800,10 +1828,9 @@ computeType (sym_link * type1, sym_link * type2,
       if (getSize (etype2) > 1)
         SPEC_NOUN (getSpec (rType)) = V_INT;
     }
-  else
-    /* if one of them is a pointer or array then that
-       prevails */
-  if (IS_PTR (type1) || IS_ARRAY (type1))
+  /* if one of them is a pointer or array then that
+     prevails */
+  else if (IS_PTR (type1) || IS_ARRAY (type1))
     rType = copyLinkChain (type1);
   else if (IS_PTR (type2) || IS_ARRAY (type2))
     rType = copyLinkChain (type2);
@@ -1853,28 +1880,34 @@ computeType (sym_link * type1, sym_link * type2,
           }
         else if (IS_CHAR (reType))
           {
-            if (op == '|' || op == '^')
-              return computeTypeOr (etype1, etype2, reType);
-            else if (   op == '&'
-                     && SPEC_USIGN (etype1) != SPEC_USIGN (etype2))
-              {
-                SPEC_USIGN (reType) = 1;
-                return rType;
-              }
-            else if (op == '*')
+            /* promotion of some special cases */
+            switch (op)
               {
-                SPEC_NOUN (reType) = V_INT;
-                SPEC_USIGN (reType) = 0;
-                return rType;
-              }
-            /* TODO: should be in SDCCast.c */
-            else if (   op == '/'
-                     && (   !SPEC_USIGN (etype1)
-                         || !SPEC_USIGN (etype2)))
-              {
-                SPEC_NOUN (reType) = V_INT;
-                SPEC_USIGN (reType) = 0;
-                return rType;
+                case '|':
+                case '^':
+                  return computeTypeOr (etype1, etype2, reType);
+                case '&':
+                  if (SPEC_USIGN (etype1) != SPEC_USIGN (etype2))
+                    {
+                      SPEC_USIGN (reType) = 1;
+                      return rType;
+                    }
+                  break;
+                case '*':
+                  SPEC_NOUN (reType) = V_INT;
+                  SPEC_USIGN (reType) = 0;
+                  return rType;
+                case '/':
+                  /* if both are unsigned char then no promotion required */
+                  if (!(SPEC_USIGN (etype1) && SPEC_USIGN (etype2)))
+                    {
+                      SPEC_NOUN (reType) = V_INT;
+                      SPEC_USIGN (reType) = 0;
+                      return rType;
+                    }
+                  break;
+                default:
+                  break;
               }
           }
         break;
@@ -2659,7 +2692,7 @@ processFuncArgs (symbol * func)
             SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = bit;
           else
             SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
-              (options.model != MODEL_SMALL ? xdata : data);
+              port->mem.default_local_map;
           
           #if 0
           /* ?? static functions shouldn't imply static parameters - EEP */
@@ -2669,6 +2702,8 @@ processFuncArgs (symbol * func)
           }
           #endif
         }
+      if (SPEC_OCLS (val->sym->etype) == pdata)
+        val->sym->iaccess = 1;
       if (!isinSet(operKeyReset, val->sym)) {
         addSet (&operKeyReset, val->sym);
         applyToSet (operKeyReset, resetParmKey);
@@ -3077,7 +3112,7 @@ powof2 (TYPE_UDWORD num)
     }
 
   if (n1s > 1 || nshifts == 0)
-    return 0;
+    return -1;
   return nshifts - 1;
 }