From d3116fbcb26b6893466538702b9ad9d5819687a7 Mon Sep 17 00:00:00 2001 From: epetrich Date: Tue, 6 Jan 2004 07:04:52 +0000 Subject: [PATCH] * 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. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3085 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 11 +++++ src/SDCC.y | 74 ++++++++++++++++----------------- src/SDCCsymt.c | 60 ++++++++++++++++++++++++++ src/SDCCsymt.h | 1 + support/Util/SDCCerr.c | 2 + support/Util/SDCCerr.h | 1 + support/regression/tests/enum.c | 17 ++++++++ 7 files changed, 129 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index 63f4d7a2..2189e0d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2004-01-06 Erik Petrich + + * 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 * src/common.h: added ifndef/define/endif macros diff --git a/src/SDCC.y b/src/SDCC.y index 9c9eee76..a7cf2431 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -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 ; } | { diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index 78d03f4f..eafcb45d 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -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 (vmax) + 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; +} diff --git a/src/SDCCsymt.h b/src/SDCCsymt.h index f79b0493..9a4860b8 100644 --- a/src/SDCCsymt.h +++ b/src/SDCCsymt.h @@ -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 */ diff --git a/support/Util/SDCCerr.c b/support/Util/SDCCerr.c index e3f59815..374c383b 100644 --- a/support/Util/SDCCerr.c +++ b/support/Util/SDCCerr.c @@ -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" }, }; /* diff --git a/support/Util/SDCCerr.h b/support/Util/SDCCerr.h index dca6e2ab..a81361b2 100644 --- a/support/Util/SDCCerr.h +++ b/support/Util/SDCCerr.h @@ -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. diff --git a/support/regression/tests/enum.c b/support/regression/tests/enum.c index 49ef416b..8dd23623 100644 --- a/support/regression/tests/enum.c +++ b/support/regression/tests/enum.c @@ -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); +} -- 2.30.2