#include "c-common.h"
#include "c-pragma.h"
#include "cgraph.h"
+#include "hashtab.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
return value;
}
\f
+/* Generate an error for any duplicate field names in FIELDLIST. Munge
+ the list such that this does not present a problem later. */
+
+static void
+detect_field_duplicates (tree fieldlist)
+{
+ tree x, y;
+ int timeout = 10;
+
+ /* First, see if there are more than "a few" fields.
+ This is trivially true if there are zero or one fields. */
+ if (!fieldlist)
+ return;
+ x = TREE_CHAIN (fieldlist);
+ if (!x)
+ return;
+ do {
+ timeout--;
+ x = TREE_CHAIN (x);
+ } while (timeout > 0 && x);
+
+ /* If there were "few" fields, avoid the overhead of allocating
+ a hash table. Instead just do the nested traversal thing. */
+ if (timeout > 0)
+ {
+ for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x))
+ if (DECL_NAME (x))
+ {
+ for (y = fieldlist; y != x; y = TREE_CHAIN (y))
+ if (DECL_NAME (y) == DECL_NAME (x))
+ {
+ error_with_decl (x, "duplicate member `%s'");
+ DECL_NAME (x) = NULL_TREE;
+ }
+ }
+ }
+ else
+ {
+ htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
+ void **slot;
+
+ for (x = fieldlist; x ; x = TREE_CHAIN (x))
+ if ((y = DECL_NAME (x)) != 0)
+ {
+ slot = htab_find_slot (htab, y, INSERT);
+ if (*slot)
+ {
+ error_with_decl (x, "duplicate member `%s'");
+ DECL_NAME (x) = NULL_TREE;
+ }
+ *slot = y;
+ }
+
+ htab_delete (htab);
+ }
+}
+
/* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
FIELDLIST is a chain of FIELD_DECL nodes for the fields.
ATTRIBUTES are attributes to be applied to the structure. */
saw_named_field = 1;
}
- /* Delete all duplicate fields from the fieldlist */
- for (x = fieldlist; x && TREE_CHAIN (x);)
- /* Anonymous fields aren't duplicates. */
- if (DECL_NAME (TREE_CHAIN (x)) == 0)
- x = TREE_CHAIN (x);
- else
- {
- tree y = fieldlist;
-
- while (1)
- {
- if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
- break;
- if (y == x)
- break;
- y = TREE_CHAIN (y);
- }
- if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
- {
- error_with_decl (TREE_CHAIN (x), "duplicate member `%s'");
- TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
- }
- else
- x = TREE_CHAIN (x);
- }
+ detect_field_duplicates (fieldlist);
/* Now we have the nearly final fieldlist. Record it,
then lay out the structure or union (including the fields). */
- /* YACC parser for C syntax and for Objective C. -*-c-*-
+/* YACC parser for C syntax and for Objective C. -*-c-*-
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996,
1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
/* Start scope of tag before parsing components. */
}
component_decl_list '}' maybe_attribute
- { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+ { $$ = finish_struct ($<ttype>4, nreverse ($5),
+ chainon ($1, $7)); }
| struct_head '{' component_decl_list '}' maybe_attribute
{ $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
- $3, chainon ($1, $5));
+ nreverse ($3), chainon ($1, $5));
}
| union_head identifier '{'
{ $$ = start_struct (UNION_TYPE, $2); }
component_decl_list '}' maybe_attribute
- { $$ = finish_struct ($<ttype>4, $5, chainon ($1, $7)); }
+ { $$ = finish_struct ($<ttype>4, nreverse ($5),
+ chainon ($1, $7)); }
| union_head '{' component_decl_list '}' maybe_attribute
{ $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
- $3, chainon ($1, $5));
+ nreverse ($3), chainon ($1, $5));
}
| enum_head identifier '{'
{ $$ = start_enum ($2); }
pedwarn ("comma at end of enumerator list"); }
;
+/* We chain the components in reverse order. They are put in forward
+ order in structsp_attr.
+
+ Note that component_declarator returns single decls, so components
+ and components_notype can use TREE_CHAIN directly, wheras components
+ and components_notype return lists (of comma separated decls), so
+ component_decl_list and component_decl_list2 must use chainon.
+
+ The theory behind all this is that there will be more semicolon
+ separated fields than comma separated fields, and so we'll be
+ minimizing the number of node traversals required by chainon. */
+
component_decl_list:
component_decl_list2
{ $$ = $1; }
| component_decl_list2 component_decl
- { $$ = chainon ($1, $2);
+ { $$ = chainon ($2, $1);
pedwarn ("no semicolon at end of struct or union"); }
;
component_decl_list2: /* empty */
{ $$ = NULL_TREE; }
| component_decl_list2 component_decl ';'
- { $$ = chainon ($1, $2); }
+ { $$ = chainon ($2, $1); }
| component_decl_list2 ';'
{ if (pedantic)
pedwarn ("extra semicolon in struct or union specified"); }
tree interface = lookup_interface ($3);
if (interface)
- $$ = get_class_ivars (interface);
+ $$ = nreverse (get_class_ivars (interface));
else
{
error ("cannot find interface declaration for `%s'",
components:
component_declarator
| components ',' maybe_resetattrs component_declarator
- { $$ = chainon ($1, $4); }
+ { TREE_CHAIN ($4) = $1; $$ = $4; }
;
components_notype:
component_notype_declarator
| components_notype ',' maybe_resetattrs component_notype_declarator
- { $$ = chainon ($1, $4); }
+ { TREE_CHAIN ($4) = $1; $$ = $4; }
;
component_declarator:
;
/* We chain the enumerators in reverse order.
- They are put in forward order where enumlist is used.
- (The order used to be significant, but no longer is so.
- However, we still maintain the order, just to be clean.) */
+ They are put in forward order in structsp_attr. */
enumlist:
enumerator
{ if ($1 == error_mark_node)
$$ = $1;
else
- $$ = chainon ($3, $1); }
+ TREE_CHAIN ($3) = $1, $$ = $3; }
| error
{ $$ = error_mark_node; }
;