Permalink
Browse files

Collapsed commit of cananian's designated initializer changes, patche…

…d to top of tree. Regressions have also been fixed.

See <https://sourceforge.net/tracker/index.php?func=detail&aid=2991122&group_id=599&atid=350599>
  • Loading branch information...
1 parent 27d2a2c commit a7dc1b8a8321059a8643ad43a47e66b76f414f51 @darconeous committed Mar 27, 2011
Showing with 616 additions and 35 deletions.
  1. +48 −2 src/SDCC.y
  2. +122 −28 src/SDCCast.c
  3. +4 −0 src/SDCCerr.c
  4. +2 −0 src/SDCCerr.h
  5. +40 −2 src/SDCCglue.c
  6. +320 −2 src/SDCCval.c
  7. +28 −0 src/SDCCval.h
  8. +24 −0 src/pic14/glue.c
  9. +28 −1 src/pic16/glue.c
View
@@ -75,6 +75,7 @@ bool uselessDecl = TRUE;
int yyint; /* integer value returned */
value *val ; /* for integer constant */
initList *ilist; /* initial list */
+ designation*dsgn; /* designator */
const char *yyinline; /* inlined assembler code */
ast *asts; /* expression tree */
}
@@ -125,6 +126,7 @@ bool uselessDecl = TRUE;
%type <asts> expression_statement selection_statement iteration_statement
%type <asts> jump_statement function_body else_statement string_literal
%type <asts> critical_statement
+%type <dsgn> designator designator_list designation designation_opt
%type <ilist> initializer initializer_list
%type <yyint> unary_operator assignment_operator struct_or_union
@@ -529,6 +531,45 @@ init_declarator
| declarator '=' initializer { $1->ival = $3 ; }
;
+designation_opt
+ : { $$ = NULL; }
+ | designation
+ ;
+
+designation
+ : designator_list '=' { $$ = revDesignation($1); }
+ ;
+
+designator_list
+ : designator
+ | designator_list designator { $2->next = $1; $$ = $2; }
+ ;
+
+designator
+ : '[' constant_expr ']'
+ {
+ value *tval;
+ int elemno;
+
+ tval = constExprValue($2, TRUE);
+ /* if it is not a constant then Error */
+ if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
+ {
+ werror (E_CONST_EXPECTED);
+ elemno = 0; /* arbitrary fixup */
+ }
+ else
+ {
+ if ((elemno = (int) ulFromVal(tval)) < 0)
+ {
+ werror (E_BAD_DESIGNATOR);
+ elemno = 0; /* arbitrary fixup */
+ }
+ }
+ $$ = newDesignation(DESIGNATOR_ARRAY, &elemno);
+ }
+ | '.' identifier { $$ = newDesignation(DESIGNATOR_STRUCT,$2); }
+ ;
storage_class_specifier
: TYPEDEF {
@@ -1408,8 +1449,13 @@ initializer
;
initializer_list
- : initializer
- | initializer_list ',' initializer { $3->next = $1; $$ = $3; }
+ : designation_opt initializer { $2->designation = $1; $$ = $2; }
+ | initializer_list ',' designation_opt initializer
+ {
+ $4->designation = $3;
+ $4->next = $1;
+ $$ = $4;
+ }
;
statement
View
@@ -966,6 +966,51 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
}
+/*------------------------------------------------------------------*/
+/* moveNestedInit - rewrites an initList node with a nested */
+/* designator to remove one level of nesting. */
+/*------------------------------------------------------------------*/
+static initList *
+moveNestedInit (initList *src)
+{
+ initList *dst;
+
+ /** Create new initList element */
+ switch (src->type)
+ {
+ case INIT_NODE:
+ dst = newiList(INIT_NODE, src->init.node);
+ break;
+ case INIT_DEEP:
+ dst = newiList(INIT_DEEP, src->init.deep);
+ break;
+ }
+ dst->filename = src->filename;
+ dst->lineno = src->lineno;
+ /* remove one level of nesting from the designation */
+ dst->designation = src->designation->next;
+
+ dst = newiList(INIT_DEEP, dst);
+ dst->filename = src->filename;
+ dst->lineno = src->lineno;
+ dst->next = src->next;
+ return dst;
+}
+
+/*-----------------------------------------------------------------*/
+/* findStructField - find a specific field in a struct definition */
+/*-----------------------------------------------------------------*/
+static symbol *
+findStructField (symbol *fields, symbol *target)
+{
+ for ( ; fields; fields = fields->next)
+ {
+ if (strcmp(fields->name, target->name) == 0)
+ return fields;
+ }
+ return NULL; /* not found */
+}
+
/*-----------------------------------------------------------------*/
/* createIvalStruct - generates initial value for structures */
/*-----------------------------------------------------------------*/
@@ -986,20 +1031,51 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast * rootValue)
iloop = ilist ? ilist->init.deep : NULL;
- for (sflds = SPEC_STRUCT (type)->fields; sflds; sflds = sflds->next)
+ for (sflds = SPEC_STRUCT (type)->fields; ; sflds = sflds->next)
{
+ /* skip past unnamed bitfields */
+ if (sflds && IS_BITFIELD (sflds->type) && SPEC_BUNNAMED (sflds->etype))
+ continue;
+
+ /* designated initializer? */
+ if (iloop && iloop->designation)
+ {
+ if (iloop->designation->type != DESIGNATOR_STRUCT)
+ {
+ werrorfl (iloop->filename, iloop->lineno, E_BAD_DESIGNATOR);
+ }
+ else /* find this designated element */
+ {
+ sflds = findStructField(SPEC_STRUCT (type)->fields,
+ iloop->designation->designator.tag);
+ if (sflds)
+ {
+ if (iloop->designation->next)
+ {
+ iloop = moveNestedInit(iloop);
+ }
+ }
+ else
+ {
+ werrorfl (iloop->filename, iloop->lineno, E_NOT_MEMBER,
+ iloop->designation->designator.tag->name);
+ sflds = SPEC_STRUCT (type)->fields; /* fixup */
+ }
+ }
+ }
+
/* if we have come to end */
+ if (!sflds)
+ break;
if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
break;
- if (!IS_BITFIELD (sflds->type) || !SPEC_BUNNAMED (sflds->etype))
- {
- 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, rootValue)), RESULT_TYPE_NONE);
- iloop = iloop ? iloop->next : NULL;
- }
+ /* initialize this field */
+ 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, rootValue)), RESULT_TYPE_NONE);
+ iloop = iloop ? iloop->next : NULL;
}
if (iloop)
@@ -1022,15 +1098,19 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist, ast * rootValue)
{
ast *rast = NULL;
initList *iloop;
- int lcnt = 0, size = 0;
+ int lcnt = 0, size = 0, idx = 0;
literalList *literalL;
sym_link *etype = getSpec (type);
/* take care of the special case */
/* array of characters can be init */
/* by a string */
- if (IS_CHAR (type->next))
- if ((rast = createIvalCharPtr (sym, type, decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE), rootValue)))
+ if (IS_CHAR (type->next) &&
+ ilist && ilist->type == INIT_NODE)
+ if ((rast = createIvalCharPtr (sym,
+ type,
+ decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
+ rootValue)))
return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
@@ -1049,7 +1129,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist, ast * rootValue)
return NULL;
}
- if (port->arrayInitializerSuppported && convertIListToConstList (ilist, &literalL, lcnt))
+ if (port->arrayInitializerSuppported && convertIListToConstList (reorderIlist(type,ilist), &literalL, lcnt))
{
ast *aSym;
@@ -1059,11 +1139,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist, ast * rootValue)
rast->values.constlist = literalL;
// Make sure size is set to length of initializer list.
- while (iloop)
- {
- size++;
- iloop = iloop->next;
- }
+ size = getNelements (type, ilist);
if (lcnt && size > lcnt)
{
@@ -1078,27 +1154,45 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist, ast * rootValue)
{
ast *aSym;
- if (!iloop && (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
+ if (!iloop && ((lcnt && size >= lcnt) || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
{
break;
}
- aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
- aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
- rast = createIval (aSym, type->next, iloop, rast, rootValue);
- lcnt--;
- iloop = (iloop ? iloop->next : NULL);
-
- /* no of elements given and we */
- /* have generated for all of them */
- if (!lcnt && iloop)
+ if (iloop && iloop->designation)
+ {
+ if (iloop->designation->type != DESIGNATOR_ARRAY)
+ {
+ werrorfl (iloop->filename, iloop->lineno, E_BAD_DESIGNATOR);
+ }
+ else {
+ idx = iloop->designation->designator.elemno;
+ if (iloop->designation->next)
+ {
+ iloop = moveNestedInit(iloop);
+ }
+ }
+ }
+ /* track array size based on the initializers seen */
+ if (size <= idx)
+ {
+ size = idx + 1;
+ }
+ /* too many initializers? */
+ if (iloop && (lcnt && size > lcnt))
{
// is this a better way? at least it won't crash
char *name = (IS_AST_SYM_VALUE (sym)) ? AST_SYMBOL (sym)->name : "";
werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
break;
}
+
+ aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (idx))));
+ aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
+ rast = createIval (aSym, type->next, iloop, rast, rootValue);
+ idx++;
+ iloop = (iloop ? iloop->next : NULL);
}
}
View
@@ -455,6 +455,10 @@ struct
"field '%s' has incomplete type" },
{ W_DEPRECATED_OPTION, ERROR_LEVEL_WARNING,
"deprecated compiler option '%s'" },
+{ E_BAD_DESIGNATOR, ERROR_LEVEL_ERROR,
+ "Invalid designator for designated initializer" },
+{ W_DUPLICATE_INIT, ERROR_LEVEL_WARNING,
+ "Duplicate initializer at position %d; ignoring previous." },
};
/*
View
@@ -227,6 +227,8 @@
#define E_OFFSETOF_TYPE 199 /* offsetof can only be applied to structs/unions */
#define E_INCOMPLETE_FIELD 200 /* struct field has incomplete type */
#define W_DEPRECATED_OPTION 201 /* deprecated compiler option '%s' */
+#define E_BAD_DESIGNATOR 202 /* Bad designated initializer */
+#define W_DUPLICATE_INIT 203 /* duplicate initializer */
#define MAX_ERROR_WARNING 256 /* size of disable warnings array */
View
@@ -851,8 +851,27 @@ printIvalStruct (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s
if (SPEC_STRUCT (type)->type == UNION)
{
+ int size;
+ /* skip past holes, print value */
+ while (iloop && iloop->type == INIT_HOLE)
+ {
+ iloop = iloop->next;
+ sflds = sflds->next;
+ }
printIval (sym, sflds->type, iloop, oBuf, 1);
- iloop = iloop ? iloop->next : NULL;
+ /* pad out with zeros if necessary */
+ size = getSize(type) - getSize(sflds->type);
+ for ( ; size > 0 ; size-- )
+ {
+ dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
+ }
+ /* advance past holes to find out if there were excess initializers */
+ do
+ {
+ iloop = iloop ? iloop->next : NULL;
+ sflds = sflds->next;
+ }
+ while (iloop && iloop->type == INIT_HOLE);
}
else
{
@@ -929,7 +948,7 @@ printIvalArray (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *
/* take care of the special case */
/* array of characters can be init */
/* by a string */
- if (IS_CHAR (type->next))
+ if (IS_CHAR (type->next) && ilist->type == INIT_NODE)
{
val = list2val (ilist);
if (!val)
@@ -1268,6 +1287,25 @@ printIval (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *oBuf,
{
sym_link *itype;
+ /* Handle designated initializers */
+ if (ilist && ilist->type==INIT_DEEP)
+ ilist = reorderIlist (type, ilist);
+
+ /* If this is a hole, substitute an appropriate initializer. */
+ if (ilist && ilist->type == INIT_HOLE)
+ {
+ if (IS_AGGREGATE (type))
+ {
+ ilist = newiList(INIT_DEEP, NULL); /* init w/ {} */
+ }
+ else
+ {
+ ast *ast = newAst_VALUE (constVal("0"));
+ ast = decorateType (ast, RESULT_TYPE_NONE);
+ ilist = newiList(INIT_NODE, ast);
+ }
+ }
+
/* if structure then */
if (IS_STRUCT (type))
{
Oops, something went wrong.

0 comments on commit a7dc1b8

Please sign in to comment.