c-typeck.c (build_offsetof): Remove.
authorRichard Henderson <rth@redhat.com>
Fri, 27 Aug 2004 00:37:48 +0000 (17:37 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 27 Aug 2004 00:37:48 +0000 (17:37 -0700)
        * c-typeck.c (build_offsetof): Remove.
        * c-tree.h (build_offsetof): Remove.
        * c-common.c (fold_offsetof_1, fold_offsetof): New.
        * c-common.h (fold_offsetof): Declare.
        * c-parse.in (offsetof_base): New.
        (offsetof_member_designator): Use it.  Build references, not just
        a tree list.
        (primary): Use fold_offsetof, not build_offsetof.

From-SVN: r86651

gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-parse.in
gcc/c-tree.h
gcc/c-typeck.c

index cf1dc09c719cee9e6410c9258c1118ca4982e5f9..84af91f9e9e3d7d98a39926ba6acd474c49f3fa0 100644 (file)
@@ -1,3 +1,14 @@
+2004-08-26  Richard Henderson  <rth@redhat.com>
+
+       * c-typeck.c (build_offsetof): Remove.
+       * c-tree.h (build_offsetof): Remove.
+       * c-common.c (fold_offsetof_1, fold_offsetof): New.
+       * c-common.h (fold_offsetof): Declare.
+       * c-parse.in (offsetof_base): New.
+       (offsetof_member_designator): Use it.  Build references, not just
+       a tree list.
+       (primary): Use fold_offsetof, not build_offsetof.
+
 2004-08-26  Richard Henderson  <rth@redhat.com>
 
        * tree.c (staticp): Return the static object.
index 8b7ee2c94eac2e55b44f94d787eb1df985f7e54e..03531d3ca035787bbfc96f8b8dc2a861eb00e640 100644 (file)
@@ -5436,4 +5436,69 @@ c_warn_unused_result (tree *top_p)
     }
 }
 
+/* Build the result of __builtin_offsetof.  EXPR is a nested sequence of
+   component references, with an INDIRECT_REF at the bottom; much like
+   the traditional rendering of offsetof as a macro.  Returns the folded
+   and properly cast result.  */
+
+static tree
+fold_offsetof_1 (tree expr)
+{
+  enum tree_code code = PLUS_EXPR;
+  tree base, off, t;
+
+  switch (TREE_CODE (expr))
+    {
+    case ERROR_MARK:
+      return expr;
+
+    case INDIRECT_REF:
+      return size_zero_node;
+
+    case COMPONENT_REF:
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+      if (base == error_mark_node)
+       return base;
+
+      t = TREE_OPERAND (expr, 1);
+      if (DECL_C_BIT_FIELD (t))
+       {
+         error ("attempt to take address of bit-field structure "
+                "member `%s'", IDENTIFIER_POINTER (DECL_NAME (t)));
+         return error_mark_node;
+       }
+      off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
+                       size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
+                                 / BITS_PER_UNIT));
+      break;
+
+    case ARRAY_REF:
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+      if (base == error_mark_node)
+       return base;
+
+      t = TREE_OPERAND (expr, 1);
+      if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
+       {
+         code = MINUS_EXPR;
+         t = fold (build1 (NEGATE_EXPR, TREE_TYPE (t), t));
+       }
+      t = convert (sizetype, t);
+      off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+      break;
+
+    default:
+      abort ();
+    }
+
+  return size_binop (code, base, off);
+}
+
+tree
+fold_offsetof (tree expr)
+{
+  /* Convert back from the internal sizetype to size_t.  */
+  return convert (size_type_node, fold_offsetof_1 (expr));
+}
+
 #include "gt-c-common.h"
index 94f3249b21bc69a869d239369b6086eef38df5cd..e9a91d50fdd7ec57134a2c7e8e6f358f550ea885 100644 (file)
@@ -870,6 +870,8 @@ extern void c_warn_unused_result (tree *);
 
 extern void verify_sequence_points (tree);
 
+extern tree fold_offsetof (tree);
+
 /* In c-gimplify.c  */
 extern void c_genericize (tree);
 extern int c_gimplify_expr (tree *, tree *, tree *);
index 85927d4f359efb1ff78be0d8886b92156f3bbd6d..c28b1565c84222116653b2e72117fe2fcee4cd20 100644 (file)
@@ -275,6 +275,9 @@ static GTY(()) tree all_prefix_attributes;
    all_prefix_attributes.  */
 static GTY(()) tree declspec_stack;
 
+/* INDIRECT_REF with a TREE_TYPE of the type being queried for offsetof.  */
+static tree offsetof_base;
+
 /* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK
    should be called from the productions making use of setspecs.  */
 #define PUSH_DECLSPEC_STACK                                             \
@@ -681,8 +684,15 @@ primary:
                { $$.value = build_va_arg ($3.value, groktypename ($5));
                  $$.original_code = ERROR_MARK; }
 
-       | OFFSETOF '(' typename ',' offsetof_member_designator ')'
-               { $$.value = build_offsetof (groktypename ($3), $5);
+       | OFFSETOF '(' typename ','
+               { tree type = groktypename ($3);
+                 if (type == error_mark_node)
+                   offsetof_base = error_mark_node;
+                 else
+                   offsetof_base = build1 (INDIRECT_REF, type, NULL);
+               }
+         offsetof_member_designator ')'
+               { $$.value = fold_offsetof ($6);
                  $$.original_code = ERROR_MARK; }
        | OFFSETOF '(' error ')'
                { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
@@ -753,17 +763,15 @@ primary:
 
 /* This is the second argument to __builtin_offsetof.  We must have one
    identifier, and beyond that we want to accept sub structure and sub
-   array references.  We return tree list where each element has
-   PURPOSE set for component refs or VALUE set for array refs.  We'll
-   turn this into something real inside build_offsetof.  */
+   array references.  */
 
 offsetof_member_designator:
          identifier
-               { $$ = tree_cons ($1, NULL_TREE, NULL_TREE); }
+               { $$ = build_component_ref (offsetof_base, $1); }
        | offsetof_member_designator '.' identifier
-               { $$ = tree_cons ($3, NULL_TREE, $1); }
+               { $$ = build_component_ref ($1, $3); }
        | offsetof_member_designator '[' expr ']'
-               { $$ = tree_cons (NULL_TREE, $3.value, $1); }
+               { $$ = build_array_ref ($1, $3.value); }
        ;
 
 old_style_parm_decls:
index 5c99f47aa0ef773c250fa8c78b68a8af41ae8c2d..f9f06eb517c1469fba59f6cb460e34db687b76c9 100644 (file)
@@ -277,7 +277,6 @@ extern tree c_finish_return (tree);
 extern tree c_finish_bc_stmt (tree *, bool);
 extern tree c_finish_goto_label (tree);
 extern tree c_finish_goto_ptr (tree);
-extern tree build_offsetof (tree, tree);
 
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
index ca6e9f372a733ea2b2748d1059d7c409c25dbc41..aa04ac0d24a76b23f2f3125c7b3cbb853d151743 100644 (file)
@@ -7583,31 +7583,3 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     return result;
   }
 }
-
-/* Build the result of __builtin_offsetof.  TYPE is the first argument to
-   offsetof, i.e. a type.  LIST is a tree_list that encodes component and
-   array references; PURPOSE is set for the former and VALUE is set for
-   the later.  */
-
-tree
-build_offsetof (tree type, tree list)
-{
-  tree t;
-
-  /* Build "*(type *)0".  */
-  t = convert (build_pointer_type (type), null_pointer_node);
-  t = build_indirect_ref (t, "");
-
-  /* Build COMPONENT and ARRAY_REF expressions as needed.  */
-  for (list = nreverse (list); list ; list = TREE_CHAIN (list))
-    if (TREE_PURPOSE (list))
-      t = build_component_ref (t, TREE_PURPOSE (list));
-    else
-      t = build_array_ref (t, TREE_VALUE (list));
-
-  /* Finalize the offsetof expression.  For now all we need to do is take
-     the address of the expression we created, and cast that to an integer
-     type; this mirrors the traditional macro implementation of offsetof.  */
-  t = build_unary_op (ADDR_EXPR, t, 0);
-  return convert (size_type_node, t);
-}