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 *);
/* 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;
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) {
/* 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;
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);
}
/* 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 */
/* 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))
{
// 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);
}
/* 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;
/* 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);
/* 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;
/* 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))
/* 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);
}
/*-----------------------------------------------------------------*/
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 */
}
/*------------------------------------------------------------------*/
-/* getSize - returns size of a type chain in bits */
+/* getSize - returns size of a type chain in bytes */
/*------------------------------------------------------------------*/
unsigned int
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;
}
/*------------------------------------------------------------------*/
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;
{
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;