From: bernhardheld Date: Tue, 29 Nov 2005 21:22:07 +0000 (+0000) Subject: * src/SDCCast.c (createIvalStruct, createIvalArray, createIvalPtr, createIval): imple... X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=b7d650f8fe1c5a42946ae9f0f6854978d510ed6f;p=fw%2Fsdcc * src/SDCCast.c (createIvalStruct, createIvalArray, createIvalPtr, createIval): implement symbol independant "flexible array member", (createIvalCharPtr): implemented flexible array initialisation with a string * src/SDCCsymt.c (copyStruct): removed, (getSize): fixed comment, (getAllocSize): removed, the additional allocation size is now in sym->flexArrayLength, (checkStructFlexArray): new, syntax checks for "flexible array members", (compStructSize): added syntax checks for "flexible array members" (copyStruct): removed, (copyLinkChain): removed inefficient fix for bug 770487 * src/SDCCglue.c (emitRegularMap): getAllocSize has been removed * src/SDCCsymt.h: added structdef.b_flexArrayMember and symbol->flexArrayLength * src/SDCCerr.c, * src/SDCCerr.h: added W_INVALID_FLEXARRAY, W_C89_NO_FLEXARRAY, E_FLEXARRAY_NOTATEND and E_FLEXARRAY_INEMPTYSTRCT * support/regression/tests/structflexarray.c: added * support/valdiag/tests/structflexiblearray.c: added git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3999 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index 4079dd17..ae35fe02 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2005-11-29 Bernhard Held + + * src/SDCCast.c (createIvalStruct, createIvalArray, createIvalPtr, + createIval): implement symbol independant "flexible array member", + (createIvalCharPtr): implemented flexible array initialisation with a + string + * src/SDCCsymt.c (copyStruct): removed, + (getSize): fixed misleading comment, + (getAllocSize): removed, the additional allocation size is now in + sym->flexArrayLength, + (checkStructFlexArray): new, syntax checks for flexible array members, + (compStructSize): added syntax checks for "flexible array members" + (copyStruct): removed, + (copyLinkChain): removed inefficient fix for bug 770487 + * src/SDCCglue.c (emitRegularMap): getAllocSize has been removed + * src/SDCCsymt.h: added structdef.b_flexArrayMember and + symbol->flexArrayLength + * src/SDCCerr.c, + * src/SDCCerr.h: added W_INVALID_FLEXARRAY, W_C89_NO_FLEXARRAY, + E_FLEXARRAY_NOTATEND and E_FLEXARRAY_INEMPTYSTRCT + * support/regression/tests/structflexarray.c: added + * support/valdiag/tests/structflexiblearray.c: added + 2005-11-29 Bernhard Held * src/SDCCast.c (decorateType): fixed bug 1368489 diff --git a/src/SDCCast.c b/src/SDCCast.c index 09b4a28c..2a0451b4 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -50,8 +50,8 @@ int labelKey = 1; int noLineno = 0; int noAlloc = 0; symbol *currFunc=NULL; -static ast *createIval (ast *, sym_link *, initList *, ast *); -static ast *createIvalCharPtr (ast *, sym_link *, ast *); +static ast *createIval (ast *, sym_link *, initList *, ast *, ast *); +static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *); static ast *optimizeCompare (ast *); ast *optimizeRRCRLC (ast *); ast *optimizeSWAP (ast *); @@ -864,7 +864,7 @@ createIvalType (ast * sym, sym_link * type, initList * ilist) /* createIvalStruct - generates initial value for structures */ /*-----------------------------------------------------------------*/ static ast * -createIvalStruct (ast * sym, sym_link * type, initList * ilist) +createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue) { ast *rast = NULL; ast *lAst; @@ -888,7 +888,10 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist) sflds->implicit = 1; lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds))); lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE); - rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_TYPE_NONE); + rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, + iloop, rast, rootValue)), + RESULT_TYPE_NONE); + } if (iloop) { @@ -905,7 +908,7 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist) /* createIvalArray - generates code for array initialization */ /*-----------------------------------------------------------------*/ static ast * -createIvalArray (ast * sym, sym_link * type, initList * ilist) +createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue) { ast *rast = NULL; initList *iloop; @@ -918,83 +921,88 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) if (IS_CHAR (type->next)) if ((rast = createIvalCharPtr (sym, type, - decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE)))) + decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE), + rootValue))) return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); - /* not the special case */ - if (ilist->type != INIT_DEEP) - { - werror (E_INIT_STRUCT, ""); - return NULL; - } + /* not the special case */ + if (ilist->type != INIT_DEEP) + { + werror (E_INIT_STRUCT, ""); + return NULL; + } - iloop = ilist->init.deep; - lcnt = DCL_ELEM (type); + iloop = ilist->init.deep; + lcnt = DCL_ELEM (type); - if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL)) - { - ast *aSym; + if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL)) + { + ast *aSym; - aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE); - - rast = newNode(ARRAYINIT, aSym, NULL); - rast->values.constlist = literalL; - - // Make sure size is set to length of initializer list. - while (iloop) - { - size++; - iloop = iloop->next; - } - - if (lcnt && size > lcnt) - { - // Array size was specified, and we have more initializers than needed. - char *name=sym->opval.val->sym->name; - int lineno=sym->opval.val->sym->lineDef; - char *filename=sym->opval.val->sym->fileDef; - - werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); - } - } - else - { - for (;;) - { - ast *aSym; - - aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++)))); - aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE); - rast = createIval (aSym, type->next, iloop, rast); - iloop = (iloop ? iloop->next : NULL); - if (!iloop) - { - break; - } - - /* no of elements given and we */ - /* have generated for all of them */ - if (!--lcnt) - { - // is this a better way? at least it won't crash - char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : ""; - int lineno = iloop->lineno; - char *filename = iloop->filename; - werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); - - break; - } - } - } + aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE); + + rast = newNode(ARRAYINIT, aSym, NULL); + rast->values.constlist = literalL; + + // Make sure size is set to length of initializer list. + while (iloop) + { + size++; + iloop = iloop->next; + } + + if (lcnt && size > lcnt) + { + // Array size was specified, and we have more initializers than needed. + char *name=sym->opval.val->sym->name; + int lineno=sym->opval.val->sym->lineDef; + char *filename=sym->opval.val->sym->fileDef; + + werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); + } + } + else + { + for (;;) + { + ast *aSym; + + aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++)))); + aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE); + rast = createIval (aSym, type->next, iloop, rast, rootValue); + iloop = (iloop ? iloop->next : NULL); + if (!iloop) + { + break; + } + + /* no of elements given and we */ + /* have generated for all of them */ + if (!--lcnt) + { + // is this a better way? at least it won't crash + char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : ""; + int lineno = iloop->lineno; + char *filename = iloop->filename; + werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name); + + break; + } + } + } - /* if we have not been given a size */ - if (!DCL_ELEM (type)) + /* if we have not been given a size */ + if (!DCL_ELEM (type)) { + /* check, if it's a flexible array */ + if (IS_STRUCT (AST_VALUE (rootValue)->type)) + AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next); + else DCL_ELEM (type) = size; } - return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); + return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); } @@ -1002,9 +1010,10 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) /* createIvalCharPtr - generates initial values for char pointers */ /*-----------------------------------------------------------------*/ static ast * -createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) +createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal) { ast *rast = NULL; + unsigned size = 0; /* if this is a pointer & right is a literal array then */ /* just assignment will do */ @@ -1023,10 +1032,10 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) /* to the array element */ char *s = SPEC_CVAL (iexpr->etype).v_char; int i = 0; - int size = getSize (iexpr->ftype); int symsize = getSize (type); - - if (size>symsize) + + size = getSize (iexpr->ftype); + if (symsize && size>symsize) { if (size>(symsize+1)) { @@ -1052,6 +1061,16 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) // now WE don't need iexpr's symbol anymore freeStringSymbol(AST_SYMBOL(iexpr)); + /* if we have not been given a size */ + if (!DCL_ELEM (type)) + { + /* check, if it's a flexible array */ + if (IS_STRUCT (AST_VALUE (rootVal)->type)) + AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next); + else + DCL_ELEM (type) = size; + } + return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE); } @@ -1062,7 +1081,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) /* createIvalPtr - generates initial value for pointers */ /*-----------------------------------------------------------------*/ static ast * -createIvalPtr (ast * sym, sym_link * type, initList * ilist) +createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal) { ast *rast; ast *iexpr; @@ -1075,7 +1094,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist) /* if character pointer */ if (IS_CHAR (type->next)) - if ((rast = createIvalCharPtr (sym, type, iexpr))) + if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal))) return rast; return newNode ('=', sym, iexpr); @@ -1085,7 +1104,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist) /* createIval - generates code for initial value */ /*-----------------------------------------------------------------*/ static ast * -createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) +createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue) { ast *rast = NULL; @@ -1094,15 +1113,15 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /* if structure then */ if (IS_STRUCT (type)) - rast = createIvalStruct (sym, type, ilist); + rast = createIvalStruct (sym, type, ilist, rootValue); else /* if this is a pointer */ if (IS_PTR (type)) - rast = createIvalPtr (sym, type, ilist); + rast = createIvalPtr (sym, type, ilist, rootValue); else /* if this is an array */ if (IS_ARRAY (type)) - rast = createIvalArray (sym, type, ilist); + rast = createIvalArray (sym, type, ilist, rootValue); else /* if type is SPECIFIER */ if (IS_SPEC (type)) @@ -1118,7 +1137,8 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) /* initAggregates - initialises aggregate variables with initv */ /*-----------------------------------------------------------------*/ ast * initAggregates (symbol * sym, initList * ival, ast * wid) { - return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid); + ast *newAst = newAst_VALUE (symbolVal (sym)); + return createIval (newAst, sym->type, ival, wid, newAst); } /*-----------------------------------------------------------------*/ diff --git a/src/SDCCglue.c b/src/SDCCglue.c index 199a7c06..78da0177 100644 --- a/src/SDCCglue.c +++ b/src/SDCCglue.c @@ -361,7 +361,7 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag) SPEC_ADDR (sym->etype)); } else { - int size = getAllocSize (sym->type); + int size = getSize (sym->type) + sym->flexArrayLength; if (size==0) { werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name); } diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index de557529..172acf80 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -328,20 +328,6 @@ newStruct (char *tag) return s; } -/*------------------------------------------------------------------*/ -/* copyStruct - copies a structdef including the fields-list */ -/*------------------------------------------------------------------*/ -static structdef * -copyStruct (structdef *src) -{ - structdef *dest; - - dest = newStruct (""); - memcpy (dest, src, sizeof (structdef)); - dest->fields = copySymbolChain (src->fields); - return dest; -} - /*------------------------------------------------------------------*/ /* sclsFromPtr - Return the storage class a pointer points into. */ /* S_FIXED is returned for generic pointers or other */ @@ -810,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) @@ -874,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; } /*------------------------------------------------------------------*/ @@ -1306,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; @@ -1639,14 +1652,12 @@ 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) { memcpy (loop, curr, sizeof (sym_link)); /* copy it */ -if (getenv ("SDCCCOPYSTRUCT")) // this breaks regression test bug-221220?? - if (IS_STRUCT (loop)) - SPEC_STRUCT (loop) = copyStruct (SPEC_STRUCT (loop)); loop->next = (curr->next ? newLink (curr->next->class) : (void *) NULL); loop = loop->next; curr = curr->next; diff --git a/src/SDCCsymt.h b/src/SDCCsymt.h index c9668d2d..3699759a 100644 --- a/src/SDCCsymt.h +++ b/src/SDCCsymt.h @@ -86,6 +86,8 @@ typedef struct structdef struct symbol *fields; /* pointer to fields */ unsigned size; /* sizeof the table in bytes */ int type; /* STRUCT or UNION */ + bool b_flexArrayMember; /* has got an flexible array member, + only needed for syntax checks */ } structdef; @@ -185,7 +187,8 @@ DECLARATOR_TYPE; typedef struct declarator { DECLARATOR_TYPE dcl_type; /* POINTER,ARRAY or FUNCTION */ - unsigned int num_elem; /* # of elems if type==array */ + unsigned int num_elem; /* # of elems if type==array, */ + /* always 0 for flexible arrays */ unsigned ptr_const:1; /* pointer is constant */ unsigned ptr_volatile:1; /* pointer is volatile */ struct sym_link *tspec; /* pointer type specifier */ @@ -246,6 +249,11 @@ typedef struct symbol short level; /* declration lev,fld offset */ short block; /* sequential block # of defintion */ int key; + unsigned flexArrayLength; /* if the symbol specifies a struct + with a "flexible array member", then the additional length in bytes for + the "fam" is stored here. Because the lenght can be different from symbol + to symbol AND v_struct isn't copied in copyLinkChain(), it's located here + in the symbol and not in v_struct or the declarator */ unsigned implicit:1; /* implicit flag */ unsigned undefined:1; /* undefined variable */ unsigned _isparm:1; /* is a parameter */ @@ -568,7 +576,6 @@ value *checkStructIval (symbol *, value *); value *checkArrayIval (sym_link *, value *); value *checkIval (sym_link *, value *); unsigned int getSize (sym_link *); -unsigned int getAllocSize (sym_link *); unsigned int bitsForType (sym_link *); sym_link *newIntLink (); sym_link *newCharLink (); diff --git a/support/Util/SDCCerr.c b/support/Util/SDCCerr.c index ea38e287..aa804d64 100644 --- a/support/Util/SDCCerr.c +++ b/support/Util/SDCCerr.c @@ -424,6 +424,14 @@ struct "integer constant '%s' out of range, truncated to %.0lf." }, { W_CMP_SU_CHAR, ERROR_LEVEL_PEDANTIC, "comparison of 'signed char' with 'unsigned char' requires promotion to int" }, +{ W_INVALID_FLEXARRAY, ERROR_LEVEL_WARNING, + "invalid use of structure with flexible array member" }, +{ W_C89_NO_FLEXARRAY, ERROR_LEVEL_PEDANTIC, + "ISO C90 does not support flexible array members" }, +{ E_FLEXARRAY_NOTATEND, ERROR_LEVEL_ERROR, + "flexible array member not at end of struct" }, +{ E_FLEXARRAY_INEMPTYSTRCT, ERROR_LEVEL_ERROR, + "flexible array in otherwise empty struct" }, }; /* diff --git a/support/Util/SDCCerr.h b/support/Util/SDCCerr.h index b48e0b62..64d1bb6b 100644 --- a/support/Util/SDCCerr.h +++ b/support/Util/SDCCerr.h @@ -201,6 +201,10 @@ SDCCERR - SDCC Standard error handler #define E_BANKED_WITH_CALLEESAVES 183 /* banked and callee-saves mixed */ #define W_INVALID_INT_CONST 184 /* invalid integer literal string */ #define W_CMP_SU_CHAR 185 /* comparison of 'signed char' with 'unsigned char' requires promotion to int */ +#define W_INVALID_FLEXARRAY 186 /* invalid use of structure with flexible array member */ +#define W_C89_NO_FLEXARRAY 187 /* ISO C90 does not support flexible array members */ +#define E_FLEXARRAY_NOTATEND 188 /* flexible array member not at end of struct */ +#define E_FLEXARRAY_INEMPTYSTRCT 189 /* flexible array in otherwise empty struct */ #define MAX_ERROR_WARNING 256 /* size of disable warnings array */ diff --git a/support/regression/tests/structflexarray.c b/support/regression/tests/structflexarray.c new file mode 100644 index 00000000..0c3bea24 --- /dev/null +++ b/support/regression/tests/structflexarray.c @@ -0,0 +1,46 @@ +/* Check basic behaviour of "flexible array members" + */ +#include + +struct str1 +{ + char c; + short i[]; +}; + +struct str1 s11 = { 1, {2, 3} }; +struct str1 s12 = { 4, {5, 6, 7} }; /* different size */ + +static void +testFlexibleArray1(void) +{ + /* test sizeof */ + ASSERT(sizeof(s11) == 1); + /* test allocation size */ +#if ! defined(PORT_HOST) + ASSERT((char *) &s12 - (char *) &s11 == 1 + 4); +#endif +} + + +/* test initialisation with string */ + +struct str2 +{ + short s; + char str2[]; +}; + +struct str2 s21 = { 1, "sdcc" }; +struct str2 s22 = { 2, "sdcc is great" }; /* different size */ + +static void +testFlexibleArray2(void) +{ + /* test sizeof */ + ASSERT(sizeof(s21) == 2); + /* test allocation size */ +#if ! defined(PORT_HOST) + ASSERT((char *) &s22 - (char *) &s21 == 2 + 5); +#endif +} diff --git a/support/valdiag/tests/structflexiblearray.c b/support/valdiag/tests/structflexiblearray.c new file mode 100644 index 00000000..e3a7eccc --- /dev/null +++ b/support/valdiag/tests/structflexiblearray.c @@ -0,0 +1,24 @@ + +#ifdef TEST1 +struct tag { + int good1; + int flex[]; /* ERROR(GCC) */ + int good2; +} badstruct; /* ERROR(SDCC) */ +#endif + +#ifdef TEST2 +struct tag { + int flex[]; /* ERROR(GCC) */ +} badstruct; /* ERROR(SDCC) */ +#endif + +#ifdef TEST3 +struct tag { + int good1; + struct tag2 { + int good2; + int flex[]; + } nestedstruct; /* IGNORE(SDCC) */ +} badstruct; /* ERROR(SDCC) */ +#endif