OSDN Git Service

PR c/2820
authorneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 4 Nov 2001 17:54:57 +0000 (17:54 +0000)
committerneil <neil@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 4 Nov 2001 17:54:57 +0000 (17:54 +0000)
* c-typeck.c (lookup_field): Rework to return a chain down to
the looked-up field.
(build_component_ref): Use the new lookup_field to handle
nested anonymous entities correctly.

* testsuite/gcc.c-torture/execute/anon-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46774 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/anon-1.c [new file with mode: 0644]

index fb19c7d..f580989 100644 (file)
@@ -1,3 +1,11 @@
+2001-11-04  Neil Booth  <neil@cat.daikokuya.demon.co.uk>
+
+       PR c/2820
+       * c-typeck.c (lookup_field): Rework to return a chain down to
+       the looked-up field.
+       (build_component_ref): Use the new lookup_field to handle
+       nested anonymous entities correctly.
+
 Sun Nov  4 11:53:31 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * config/sparc/sparc.c (sparc_emit_set_const32, GEN_HIGHINT64):
index 37810f6..34c7ba8 100644 (file)
@@ -55,7 +55,7 @@ static int comp_target_types          PARAMS ((tree, tree));
 static int function_types_compatible_p PARAMS ((tree, tree));
 static int type_lists_compatible_p     PARAMS ((tree, tree));
 static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
-static tree lookup_field               PARAMS ((tree, tree, tree *));
+static tree lookup_field               PARAMS ((tree, tree));
 static tree convert_arguments          PARAMS ((tree, tree, tree, tree));
 static tree pointer_int_sum            PARAMS ((enum tree_code, tree, tree));
 static tree pointer_diff               PARAMS ((tree, tree));
@@ -990,17 +990,20 @@ default_conversion (exp)
   return exp;
 }
 \f
-/* Look up component name in the structure type definition.
-
-   If this component name is found indirectly within an anonymous union,
-   store in *INDIRECT the component which directly contains
-   that anonymous union.  Otherwise, set *INDIRECT to 0.  */
+/* Look up COMPONENT in a structure or union DECL.
+
+   If the component name is not found, returns NULL_TREE.  Otherwise,
+   the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
+   stepping down the chain to the component, which is in the last
+   TREE_VALUE of the list.  Normally the list is of length one, but if
+   the component is embedded within (nested) anonymous structures or
+   unions, the list steps down the chain to the component.  */
      
 static tree
-lookup_field (type, component, indirect)
-     tree type, component;
-     tree *indirect;
+lookup_field (decl, component)
+     tree decl, component;
 {
+  tree type = TREE_TYPE (decl);
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@@ -1026,18 +1029,15 @@ lookup_field (type, component, indirect)
              /* Step through all anon unions in linear fashion.  */
              while (DECL_NAME (field_array[bot]) == NULL_TREE)
                {
-                 tree anon = 0, junk;
-
                  field = field_array[bot++];
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
-                   anon = lookup_field (TREE_TYPE (field), component, &junk);
-
-                 if (anon != NULL_TREE)
                    {
-                     *indirect = field;
-                     return anon;
-                   }
+                     tree anon = lookup_field (field, component);
+
+                     if (anon)
+                       return tree_cons (NULL_TREE, field, anon);
+                   } 
                }
 
              /* Entire record is only anon unions.  */
@@ -1059,35 +1059,31 @@ lookup_field (type, component, indirect)
       if (DECL_NAME (field_array[bot]) == component)
        field = field_array[bot];
       else if (DECL_NAME (field) != component)
-       field = 0;
+       return NULL_TREE;
     }
   else
     {
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        {
-         if (DECL_NAME (field) == NULL_TREE)
+         if (DECL_NAME (field) == NULL_TREE
+             && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
            {
-             tree junk;
-             tree anon = 0;
-
-             if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
-                 || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
-               anon = lookup_field (TREE_TYPE (field), component, &junk);
+             tree anon = lookup_field (field, component);
 
-             if (anon != NULL_TREE)
-               {
-                 *indirect = field;
-                 return anon;
-               }
+             if (anon)
+               return tree_cons (NULL_TREE, field, anon);
            }
 
          if (DECL_NAME (field) == component)
            break;
        }
+
+      if (field == NULL_TREE)
+       return NULL_TREE;
     }
 
-  *indirect = NULL_TREE;
-  return field;
+  return tree_cons (NULL_TREE, field, NULL_TREE);
 }
 
 /* Make an expression to refer to the COMPONENT field of
@@ -1126,15 +1122,13 @@ build_component_ref (datum, component)
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
     {
-      tree indirect = 0;
-
       if (!COMPLETE_TYPE_P (type))
        {
          incomplete_type_error (NULL_TREE, type);
          return error_mark_node;
        }
 
-      field = lookup_field (type, component, &indirect);
+      field = lookup_field (datum, component);
 
       if (!field)
        {
@@ -1143,29 +1137,27 @@ build_component_ref (datum, component)
                 IDENTIFIER_POINTER (component));
          return error_mark_node;
        }
-      if (TREE_TYPE (field) == error_mark_node)
-       return error_mark_node;
 
-      /* If FIELD was found buried within an anonymous union,
-        make one COMPONENT_REF to get that anonymous union,
-        then fall thru to make a second COMPONENT_REF to get FIELD.  */
-      if (indirect != 0)
+      /* Chain the COMPONENT_REFs if necessary down to the FIELD.
+        This might be better solved in future the way the C++ front
+        end does it - by giving the anonymous entities each a
+        separate name and type, and then have build_component_ref
+        recursively call itself.  We can't do that here.  */
+      for (; field; field = TREE_CHAIN (field))
        {
-         ref = build (COMPONENT_REF, TREE_TYPE (indirect), datum, indirect);
-         if (TREE_READONLY (datum) || TREE_READONLY (indirect))
+         tree subdatum = TREE_VALUE (field);
+
+         if (TREE_TYPE (subdatum) == error_mark_node)
+           return error_mark_node;
+
+         ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum);
+         if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
-         if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (indirect))
+         if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
            TREE_THIS_VOLATILE (ref) = 1;
          datum = ref;
        }
 
-      ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
-
-      if (TREE_READONLY (datum) || TREE_READONLY (field))
-       TREE_READONLY (ref) = 1;
-      if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
-       TREE_THIS_VOLATILE (ref) = 1;
-
       return ref;
     }
   else if (code != ERROR_MARK)
index 572fb2a..985326e 100644 (file)
@@ -1,3 +1,7 @@
+2001-11-04  Neil Booth  <neil@cat.daikokuya.demon.co.uk>
+
+       * gcc.c-torture/execute/anon-1.c: New test.
+
 2001-11-03  Geoffrey Keating  <geoffk@redhat.com>
 
        * g++.old-deja/g++.bugs/900227_01.C: short and pointer are the
diff --git a/gcc/testsuite/gcc.c-torture/execute/anon-1.c b/gcc/testsuite/gcc.c-torture/execute/anon-1.c
new file mode 100644 (file)
index 0000000..98a9ed7
--- /dev/null
@@ -0,0 +1,29 @@
+/* Copyright (C) 2001 Free Software Foundation, Inc.  */
+
+/* Source: Neil Booth, 4 Nov 2001, derived from PR 2820 - field lookup in
+   nested anonymous entities was broken.  */
+
+struct
+{
+  int x;
+  struct
+  {
+    int a;
+    union
+    {
+      int b;
+    };
+  };
+} foo;
+
+int
+main(int argc, char *argv[])
+{
+  foo.b = 6;
+  foo.a = 5;
+
+  if (foo.b != 6)
+    abort ();
+
+  return 0;
+}