* src/SDCC.y (enum_specifier, enumerator_list, opt_assign_expr),
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 6 Jan 2004 07:04:52 +0000 (07:04 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 6 Jan 2004 07:04:52 +0000 (07:04 +0000)
* src/SDCCsymt.c (newEnumType),
* src/SDCCsymt.h
* support/Util/SDCCerr.c,
* support/Util/SDCCerr.h: fixed bug #871258 and some other unreported
enum related bugs.
* support/regression/tests/enum.c: added test for enum values that
require at least 2 bytes of storage.

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3085 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/SDCC.y
src/SDCCsymt.c
src/SDCCsymt.h
support/Util/SDCCerr.c
support/Util/SDCCerr.h
support/regression/tests/enum.c

index 63f4d7a23a31afd106eb71ba8a545684646430a9..2189e0d349edc5c10c01a94f6f56250148e3d79d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2004-01-06 Erik Petrich <epetrich@ivorytower.norman.ok.us>
+
+       * src/SDCC.y (enum_specifier, enumerator_list, opt_assign_expr),
+       * src/SDCCsymt.c (newEnumType),
+       * src/SDCCsymt.h
+       * support/Util/SDCCerr.c,
+       * support/Util/SDCCerr.h: fixed bug #871258 and some other unreported
+       enum related bugs.
+       * support/regression/tests/enum.c: added test for enum values that
+       require at least 2 bytes of storage.
+
 2004-01-06 Vangelis Rokas <vrokas@otenet.gr>
 
        * src/common.h: added ifndef/define/endif macros
index 9c9eee76f7dd8da977476c3385f7b229da95e30b..a7cf2431586c0144bae478967fb04eab35fe0e5b 100644 (file)
@@ -753,6 +753,7 @@ struct_or_union_specifier
             }
             if (IS_SPEC(sym->etype) && SPEC_SCLS(sym->etype)) {
               werrorfl(filename, sym->lineDef, E_NOT_ALLOWED, "storage class");
+              printTypeChainRaw (sym->type,NULL);
               SPEC_SCLS(sym->etype) = 0;
             }
             for (dsym=sym->next; dsym; dsym=dsym->next) {
@@ -898,41 +899,26 @@ struct_declarator
 
 enum_specifier
    : ENUM            '{' enumerator_list '}' {
-           symbol *sym, *dsym;
-          char _error=0;
-
-          // check for duplicate enums
-          for (sym=$3; sym; sym=sym->next) {
-            for (dsym=sym->next; dsym; dsym=dsym->next) {
-              if (strcmp(sym->name, dsym->name)==0) {
-                werrorfl(filename, sym->lineDef, E_DUPLICATE_MEMBER, "enum", sym->name);
-                _error++;
-              }
-            }
-          }
-          if (_error==0) {
-            $$ = copyLinkChain(cenum->type);
-          } else {
-            $$ = newIntLink();
-            SPEC_NOUN($$)=0;
-          }
+          $$ = newEnumType ($3);       //copyLinkChain(cenum->type);
+          SPEC_SCLS(getSpec($$)) = 0;
          }
 
    | ENUM identifier '{' enumerator_list '}' {
      symbol *csym ;
+     sym_link *enumtype;
+
+     csym=findSym(enumTab,$2,$2->name);
+     if ((csym && csym->level == $2->level))
+       werrorfl(filename, $2->lineDef, E_DUPLICATE_TYPEDEF,csym->name);
      
-     $2->type = copyLinkChain(cenum->type);
-     $2->etype = getSpec($2->type);
-     /* add this to the enumerator table */
-     if (!(csym=findSym(enumTab,$2,$2->name)) && 
-        (csym && csym->level == $2->level))
-       werror(E_DUPLICATE_TYPEDEF,csym->name);
+     enumtype = newEnumType ($4);      //copyLinkChain(cenum->type);
+     SPEC_SCLS(getSpec(enumtype)) = 0;
+     $2->type = enumtype;
      
-     addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
-     //addSymChain ($4);
-     //allocVariables (reverseSyms($4));
-     $$ = copyLinkChain(cenum->type);
-     SPEC_SCLS(getSpec($$)) = 0 ;
+     /* add this to the enumerator table */
+     if (!csym)
+       addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
+     $$ = copyLinkChain(enumtype);
    }
    | ENUM identifier                         {
      symbol *csym ;
@@ -944,8 +930,6 @@ enum_specifier
        $$ = newLink(SPECIFIER) ;
        SPEC_NOUN($$) = V_INT   ;
      }
-     
-     SPEC_SCLS(getSpec($$)) = 0 ;
    }
    ;
 
@@ -953,10 +937,19 @@ enumerator_list
    : enumerator
    | enumerator_list ',' {
                          }
-   | enumerator_list ',' enumerator {
-                                       $3->next = $1 ;
-                                       $$ = $3  ;
-                                    }
+   | enumerator_list ',' enumerator
+     {
+       symbol *dsym;
+       
+       for (dsym=$1; dsym; dsym=dsym->next)
+         {
+          if (strcmp($3->name, dsym->name)==0)
+            werrorfl(filename, $3->lineDef, E_DUPLICATE_MEMBER, "enum", $3->name);
+        }
+       
+       $3->next = $1 ;
+       $$ = $3  ;
+     }
    ;
 
 enumerator
@@ -976,8 +969,15 @@ enumerator
 opt_assign_expr
    :  '='   constant_expr  {
                               value *val ;
-                                                       
-                              val = constExprValue($2,TRUE);                         
+
+                              val = constExprValue($2,TRUE);
+                             if (!IS_INT(val->type) && !IS_CHAR(val->type))
+                               {
+                                 werror(E_ENUM_NON_INTEGER);
+                                 SNPRINTF(lbuff, sizeof(lbuff), 
+                                         "%d",(int) floatFromVal(val));
+                                 val = constVal(lbuff);
+                               }
                               $$ = cenum = val ;
                            }                           
    |                       {                              
index 78d03f4ff85f258ae6e4040f926f1bc17acd6790..eafcb45d86d75b468225e3683a16e53cc991f4a3 100644 (file)
@@ -3000,3 +3000,63 @@ sym_link *validateLink(sym_link  *l,
     exit(-1);
     return l; // never reached, makes compiler happy.
 }
+
+/*--------------------------------------------------------------------*/
+/* newEnumType - create an integer type compatible with enumerations  */
+/*--------------------------------------------------------------------*/
+sym_link *
+newEnumType (symbol *enumlist)
+{
+  int min, max, v;
+  symbol *sym;
+  sym_link *type;
+
+  if (!enumlist)
+    {
+      type = newLink (SPECIFIER);
+      SPEC_NOUN (type) = V_INT;
+      return type;
+    }
+      
+  /* Determine the range of the enumerated values */
+  sym = enumlist;
+  min = max = (int) floatFromVal (valFromType (sym->type));
+  for (sym = sym->next; sym; sym = sym->next)
+    {
+      v = (int) floatFromVal (valFromType (sym->type));
+      if (v<min)
+        min = v;
+      if (v>max)
+        max = v;
+    }
+
+  /* Determine the smallest integer type that is compatible with this range */
+  type = newLink (SPECIFIER);
+  if (min>=0 && max<=255)
+    {
+      SPEC_NOUN (type) = V_CHAR;
+      SPEC_USIGN (type) = 1;
+    }
+  else if (min>=-128 && max<=127)
+    {
+      SPEC_NOUN (type) = V_CHAR;
+    }
+  else if (min>=0 && max<=65535)
+    {
+      SPEC_NOUN (type) = V_INT;
+      SPEC_USIGN (type) = 1;
+    }
+  else if (min>=-32768 && max<=32767)
+    {
+      SPEC_NOUN (type) = V_INT;
+    }
+  else
+    {
+      SPEC_NOUN (type) = V_INT;
+      SPEC_LONG (type) = 1;
+      if (min>=0)
+        SPEC_USIGN (type) = 1;
+    }
+  
+  return type;    
+}
index f79b049322de30f01738d081eb6b4dd91341e24a..9a4860b82487dbab851e281cc4820713242dadb4 100644 (file)
@@ -560,6 +560,7 @@ void changePointer (symbol * sym);
 void checkTypeSanity(sym_link *etype, char *name);
 sym_link *typeFromStr (char *) ;
 STORAGE_CLASS sclsFromPtr(sym_link *ptr);
+sym_link *newEnumType (symbol *);
 
 
 extern char *nounName(sym_link *); /* noun strings */
index e3f5981525302ca911aa66cfcb2cec47091e42d3..374c383b58fa0632d71e6fc2fe37c7cbb35b539d 100644 (file)
@@ -403,6 +403,8 @@ struct
     "%s not allowed here" },
 { E_BAD_TAG, ERROR_LEVEL_ERROR,
     "'%s' is not a %s tag" },
+{ E_ENUM_NON_INTEGER, ERROR_LEVEL_ERROR,
+   "enumeration constant not an integer" },
 };
 
 /*
index dca6e2ab803b9131efb5345b93e228ffefd6a37e..a81361b25902f2fb9a8541ae443817125410bf98 100644 (file)
@@ -189,6 +189,7 @@ SDCCERR - SDCC Standard error handler
 #define E_INVALID_CRITICAL 171     /* operation invalid in critical sequence */
 #define E_NOT_ALLOWED 172          /* %s not allowed here */
 #define E_BAD_TAG 173               /* '%s' is not a %s tag */
+#define E_ENUM_NON_INTEGER 174      /* enumeration constant not an integer */
 
 /** Describes the maximum error level that will be logged.  Any level
  *  includes all of the levels listed after it.
index 49ef416bb7961052fdb9868db84e620a05c50841..8dd23623aa5b0ec7576a1641e2621cb844ad125e 100644 (file)
@@ -26,6 +26,11 @@ enum _IndexedEnum {
 
 };
 
+volatile enum _IntEnum {
+  INT_256 = 256,
+  INT_ZERO = 0
+} ie;
+
 void
 testSimpleEnum(void)
 {
@@ -53,3 +58,15 @@ testIndexedEnum(void)
   ASSERT(INDEXED_TWO == 2);
   ASSERT(INDEXED_MATH == 7);
 }
+
+void
+testIntEnum(void)
+{
+  ASSERT(INT_ZERO == 0);
+  ASSERT(INT_256 == 256);
+
+  ie = INT_ZERO;
+  ASSERT(ie == INT_ZERO);
+  ie = INT_256;
+  ASSERT(ie == INT_256);
+}