@@ -8538,41 +8538,7 @@ grokfield (location_t loc,
static bool
is_duplicate_field (tree x, tree y)
{
- if (DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y))
- return true;
-
- /* When using -fplan9-extensions, an anonymous field whose name is a
- typedef can duplicate a field name. */
- if (flag_plan9_extensions
- && (DECL_NAME (x) == NULL_TREE || DECL_NAME (y) == NULL_TREE))
- {
- tree xt, xn, yt, yn;
-
- xt = TREE_TYPE (x);
- if (DECL_NAME (x) != NULL_TREE)
- xn = DECL_NAME (x);
- else if (RECORD_OR_UNION_TYPE_P (xt)
- && TYPE_NAME (xt) != NULL_TREE
- && TREE_CODE (TYPE_NAME (xt)) == TYPE_DECL)
- xn = DECL_NAME (TYPE_NAME (xt));
- else
- xn = NULL_TREE;
-
- yt = TREE_TYPE (y);
- if (DECL_NAME (y) != NULL_TREE)
- yn = DECL_NAME (y);
- else if (RECORD_OR_UNION_TYPE_P (yt)
- && TYPE_NAME (yt) != NULL_TREE
- && TREE_CODE (TYPE_NAME (yt)) == TYPE_DECL)
- yn = DECL_NAME (TYPE_NAME (yt));
- else
- yn = NULL_TREE;
-
- if (xn != NULL_TREE && xn == yn)
- return true;
- }
-
- return false;
+ return DECL_NAME (x) != NULL_TREE && DECL_NAME (x) == DECL_NAME (y);
}
/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
@@ -8599,19 +8565,6 @@ detect_field_duplicates_hash (tree fieldlist,
else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
{
detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
-
- /* When using -fplan9-extensions, an anonymous field whose
- name is a typedef can duplicate a field name. */
- if (flag_plan9_extensions
- && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
- && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL)
- {
- tree xn = DECL_NAME (TYPE_NAME (TREE_TYPE (x)));
- slot = htab->find_slot (xn, INSERT);
- if (*slot)
- error ("duplicate member %q+D", TYPE_NAME (TREE_TYPE (x)));
- *slot = xn;
- }
}
}
@@ -8639,6 +8592,11 @@ detect_field_duplicates (tree fieldlist)
if (objc_detect_field_duplicates (false))
return;
+ /* When using -fplan9-extensions, do not perform duplicate field
+ checks until a field look up is performed. */
+ if (flag_plan9_extensions)
+ return;
+
/* First, see if there are more than "a few" fields.
This is trivially true if there are zero or one fields. */
if (!fieldlist || !DECL_CHAIN (fieldlist))
@@ -8658,14 +8616,7 @@ detect_field_duplicates (tree fieldlist)
if (timeout > 0)
{
for (x = DECL_CHAIN (fieldlist); x; x = DECL_CHAIN (x))
- /* When using -fplan9-extensions, we can have duplicates
- between typedef names and fields. */
- if (DECL_NAME (x)
- || (flag_plan9_extensions
- && DECL_NAME (x) == NULL_TREE
- && RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))
- && TYPE_NAME (TREE_TYPE (x)) != NULL_TREE
- && TREE_CODE (TYPE_NAME (TREE_TYPE (x))) == TYPE_DECL))
+ if (DECL_NAME (x))
{
for (y = fieldlist; y != x; y = TREE_CHAIN (y))
if (is_duplicate_field (y, x))
@@ -95,6 +95,7 @@ static int comp_target_types (location_t, tree, tree);
static int function_types_compatible_p (const_tree, const_tree, bool *,
bool *);
static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
+static tree lookup_field_plan9 (tree, tree);
static tree lookup_field (tree, tree);
static int convert_arguments (location_t, vec<location_t>, tree,
vec<tree, va_gc> *, vec<tree, va_gc> *, tree,
@@ -2280,6 +2281,81 @@ default_conversion (tree exp)
return exp;
}
+/* Look up COMPONENT in a structure or union TYPE like a Plan 9 C compiler.
+
+ Look up is performed in 3 passes:
+ 1. Look for field names that match the look up name.
+ 2. Look for anonymous records who's typedef name matches the look up name.
+ 3. Look for fields in embedded anonymous records.
+
+ If the component name is not found, returns NULL_TREE. If the component
+ name references multiple fields, issue an error. */
+
+static tree
+lookup_field_plan9 (tree type, tree component)
+{
+ tree field;
+ tree found = NULL_TREE;
+
+ /* Passes 1 & 2 are fused: conflicts are an error. */
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ /* Pass 1. */
+ if (DECL_NAME (field) == component)
+ {
+ if (found != NULL_TREE)
+ {
+ error ("duplicate member %q+D", found);
+ return NULL_TREE;
+ }
+ found = field;
+ }
+
+ /* Pass 2. */
+ if (DECL_NAME (field) == NULL_TREE
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
+ {
+ if (TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+ && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
+ && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+ == component))
+ {
+ if (found != NULL_TREE)
+ {
+ error ("duplicate member %q+D", found);
+ return NULL_TREE;
+ }
+ found = field;
+ }
+ }
+ }
+
+ if (found != NULL_TREE)
+ return tree_cons (NULL_TREE, found, NULL_TREE);
+
+ /* Pass 3. */
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (DECL_NAME (field) == NULL_TREE
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
+ {
+ tree anon = lookup_field_plan9 (TREE_TYPE (field), component);
+
+ if (anon != NULL_TREE)
+ {
+ if (found != NULL_TREE)
+ {
+ error ("duplicate member %q+D", TREE_VALUE (nreverse (anon)));
+ return NULL_TREE;
+ }
+ found = tree_cons (NULL_TREE, field, anon);
+ }
+ }
+ }
+
+ return found;
+}
+
/* Look up COMPONENT in a structure or union TYPE.
If the component name is not found, returns NULL_TREE. Otherwise,
@@ -2294,6 +2370,10 @@ lookup_field (tree type, tree component)
{
tree field;
+ /* The Plan 9 compiler has a different field resolution scheme. */
+ if (flag_plan9_extensions)
+ return lookup_field_plan9 (type, component);
+
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
to the field elements. Use a binary search on this array to quickly
find the element. Otherwise, do a linear search. TYPE_LANG_SPECIFIC
@@ -2329,17 +2409,6 @@ lookup_field (tree type, tree component)
if (anon)
return tree_cons (NULL_TREE, field, anon);
-
- /* The Plan 9 compiler permits referring
- directly to an anonymous struct/union field
- using a typedef name. */
- if (flag_plan9_extensions
- && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
- && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
- == TYPE_DECL)
- && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
- == component))
- break;
}
}
@@ -2375,16 +2444,6 @@ lookup_field (tree type, tree component)
if (anon)
return tree_cons (NULL_TREE, field, anon);
-
- /* The Plan 9 compiler permits referring directly to an
- anonymous struct/union field using a typedef
- name. */
- if (flag_plan9_extensions
- && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
- && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
- && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
- == component))
- break;
}
if (DECL_NAME (field) == component)
@@ -5,6 +5,8 @@
struct A {
char a; /* { dg-error "duplicate member" } */
+ char b;
+ char b;
};
struct B
@@ -46,6 +48,13 @@ struct E
struct D;
};
+struct F
+{
+ char a;
+ char a;
+ char a;
+};
+
char
f4 (struct E *p)
{