Skip to content

Commit

Permalink
Support unnamed/anonymous structs and unions (#5)
Browse files Browse the repository at this point in the history
* Regenerate c-parse.c with Andrew Bison

* Add unnamed struct/union members to C grammar

Based on gcc-mirror/gcc@ffc3b0f

* Handle nested unnamed structs/unions

Based on gcc-mirror/gcc@e9b2c82

* Check that only unnamed structs and unions are allowed

Based on gcc-mirror/gcc@3e96a2f
and gcc-mirror/gcc@85d4905
  • Loading branch information
cadmic authored Dec 30, 2024
1 parent 372a443 commit 78b40f3
Show file tree
Hide file tree
Showing 5 changed files with 872 additions and 896 deletions.
72 changes: 15 additions & 57 deletions gcc/c-decl.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,6 @@ static tree lookup_tag_reverse PROTO((tree));
static tree grokdeclarator PROTO((tree, tree, enum decl_context,
int));
static tree grokparms PROTO((tree, int));
static int field_decl_cmp PROTO((const GENERIC_PTR, const GENERIC_PTR));
static void layout_array_type PROTO((tree));

/* C-specific option variables. */
Expand Down Expand Up @@ -5691,6 +5690,21 @@ grokfield (filename, line, declarator, declspecs, width)
{
tree value;

if (declarator == NULL_TREE && width == NULL_TREE)
{
/* This is an unnamed decl. We only support unnamed
structs/unions, so check for other things and refuse them. */
tree type = TREE_VALUE (declspecs);

if (TREE_CODE (type) == TYPE_DECL)
type = TREE_TYPE (type);
if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE)
{
error ("unnamed fields of type other than struct or union are not allowed");
return NULL_TREE;
}
}

/* The corresponding pop_obstacks is in finish_decl. */
push_obstacks_nochange ();

Expand All @@ -5703,25 +5717,6 @@ grokfield (filename, line, declarator, declspecs, width)
return value;
}

/* Function to help qsort sort FIELD_DECLs by name order. */

static int
field_decl_cmp (xp, yp)
const GENERIC_PTR xp;
const GENERIC_PTR yp;
{
tree *x = (tree *)xp, *y = (tree *)yp;

if (DECL_NAME (*x) == DECL_NAME (*y))
return 0;
if (DECL_NAME (*x) == NULL)
return -1;
if (DECL_NAME (*y) == NULL)
return 1;
if (DECL_NAME (*x) < DECL_NAME (*y))
return -1;
return 1;
}

/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
FIELDLIST is a chain of FIELD_DECL nodes for the fields.
Expand Down Expand Up @@ -5958,43 +5953,6 @@ finish_struct (t, fieldlist, attributes)

TYPE_FIELDS (t) = fieldlist;

/* If there are lots of fields, sort so we can look through them fast.
We arbitrarily consider 16 or more elts to be "a lot". */
{
int len = 0;

for (x = fieldlist; x; x = TREE_CHAIN (x))
{
if (len > 15)
break;
len += 1;
}
if (len > 15)
{
tree *field_array;
char *space;

len += list_length (x);
/* Use the same allocation policy here that make_node uses, to
ensure that this lives as long as the rest of the struct decl.
All decls in an inline function need to be saved. */
if (allocation_temporary_p ())
space = savealloc (sizeof (struct lang_type) + len * sizeof (tree));
else
space = oballoc (sizeof (struct lang_type) + len * sizeof (tree));

TYPE_LANG_SPECIFIC (t) = (struct lang_type *) space;
TYPE_LANG_SPECIFIC (t)->len = len;

field_array = &TYPE_LANG_SPECIFIC (t)->elts[0];
len = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
field_array[len++] = x;

qsort (field_array, len, sizeof (tree), field_decl_cmp);
}
}

for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
{
TYPE_FIELDS (x) = TYPE_FIELDS (t);
Expand Down
Loading

0 comments on commit 78b40f3

Please sign in to comment.