From f8893e4723c8ce3462bfd1298afde78e5327c260 Mon Sep 17 00:00:00 2001
From: Joseph Myers <jsm@polyomino.org.uk>
Date: Thu, 9 Sep 2004 02:19:15 +0100
Subject: [PATCH] c-tree.h (enum c_declarator_kind, [...]): New.

	* c-tree.h (enum c_declarator_kind, struct c_arg_info, struct
	c_declarator, struct c_type_name, struct c_parm): New.
	(build_array_declarator, set_array_declarator_inner,
	get_parm_info, grokfield, groktypename, grokparm, push_parm_decl,
	start_function, start_decl, build_c_parm, build_attrs_declarator,
	build_function_declarator, make_pointer_declarator, c_cast_expr,
	store_parm_decls_newstyle, c_expr_sizeof_type): Update prototypes.
	(build_id_declarator): New.
	* c-typeck.c (c_cast_expr, c_expr_sizeof_type): Update to new
	structures.
	* c-decl.c (ARG_INFO_PARMS, ARG_INFO_TAGS, ARG_INFO_TYPES,
	ARG_INFO_OTHERS): Remove.
	(build_id_declarator): New.
	(build_array_declarator, set_array_declarator_inner, groktypename,
	start_decl, grokparm, push_parm_decl, grokparms, get_parm_info,
	grokfield, start_function, store_parm_decls_newstyle,
	store_parm_decls_oldstyle, store_parm_decls,
	build_c_parm, build_attrs_declarator, build_function_declarator,
	make_pointer_declarator, grokdeclarator): Update to new
	structures.
	* c-parse.in (%union): Add arginfotype, dtrtype, typenametype and
	parmtype.
	(declarator, notype_declarator, after_type_declarator,
	parm_declarator, parm_declarator_starttypename,
	parm_declarator_nostarttypename, array_declarator, typename,
	absdcl, absdcl1, absdcl1_ea, absdcl1_noea, direct_absdcl1,
	absdcl_maybe_attribute, parm, firstparm, parms, parmlist,
	parmlist_1, parmlist_2, parmlist_or_identifiers,
	parmlist_or_identifiers_1): Use these types.
	(primary, after_type_declarator, parm_declarator_starttypename,
	notype_declarator, component_decl, component_declarator,
	component_notype_declarator, typename, absdcl,
	absdcl_maybe_attribute, absdcl1_ea, direct_absdcl1, parmlist_1,
	parmlist_2, parmlist_or_identifiers_1): Update to new structures.

objc:
	* objc-act.c (objc_start_function, really_start_method,
	objc_get_parm_info, start_method_def): Update to new arg_info
	structures.

From-SVN: r87217
---
 gcc/ChangeLog       |  37 +++++
 gcc/c-decl.c        | 373 +++++++++++++++++++++++---------------------
 gcc/c-parse.in      |  88 +++++++----
 gcc/c-tree.h        | 115 ++++++++++++--
 gcc/c-typeck.c      |   7 +-
 gcc/objc/ChangeLog  |   6 +
 gcc/objc/objc-act.c |  58 +++++--
 7 files changed, 446 insertions(+), 238 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1ac41ec5b8e8..dd214e76ec85 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,40 @@
+2004-09-09  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+	* c-tree.h (enum c_declarator_kind, struct c_arg_info, struct
+	c_declarator, struct c_type_name, struct c_parm): New.
+	(build_array_declarator, set_array_declarator_inner,
+	get_parm_info, grokfield, groktypename, grokparm, push_parm_decl,
+	start_function, start_decl, build_c_parm, build_attrs_declarator,
+	build_function_declarator, make_pointer_declarator, c_cast_expr,
+	store_parm_decls_newstyle, c_expr_sizeof_type): Update prototypes.
+	(build_id_declarator): New.
+	* c-typeck.c (c_cast_expr, c_expr_sizeof_type): Update to new
+	structures.
+	* c-decl.c (ARG_INFO_PARMS, ARG_INFO_TAGS, ARG_INFO_TYPES,
+	ARG_INFO_OTHERS): Remove.
+	(build_id_declarator): New.
+	(build_array_declarator, set_array_declarator_inner, groktypename,
+	start_decl, grokparm, push_parm_decl, grokparms, get_parm_info,
+	grokfield, start_function, store_parm_decls_newstyle,
+	store_parm_decls_oldstyle, store_parm_decls,
+	build_c_parm, build_attrs_declarator, build_function_declarator,
+	make_pointer_declarator, grokdeclarator): Update to new
+	structures.
+	* c-parse.in (%union): Add arginfotype, dtrtype, typenametype and
+	parmtype.
+	(declarator, notype_declarator, after_type_declarator,
+	parm_declarator, parm_declarator_starttypename,
+	parm_declarator_nostarttypename, array_declarator, typename,
+	absdcl, absdcl1, absdcl1_ea, absdcl1_noea, direct_absdcl1,
+	absdcl_maybe_attribute, parm, firstparm, parms, parmlist,
+	parmlist_1, parmlist_2, parmlist_or_identifiers,
+	parmlist_or_identifiers_1): Use these types.
+	(primary, after_type_declarator, parm_declarator_starttypename,
+	notype_declarator, component_decl, component_declarator,
+	component_notype_declarator, typename, absdcl,
+	absdcl_maybe_attribute, absdcl1_ea, direct_absdcl1, parmlist_1,
+	parmlist_2, parmlist_or_identifiers_1): Update to new structures.
+
 2004-09-09  Joseph S. Myers  <jsm@polyomino.org.uk>
 
 	* c-tree.h (C_DECL_USED, parser_obstack, in_alignof, in_sizeof,
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 5399c175d829..2f0334414db5 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -91,13 +91,6 @@ static tree enum_next_value;
 
 static int enum_overflow;
 
-/* These #defines are for clarity in working with the information block
-   returned by get_parm_info.  */
-#define ARG_INFO_PARMS(args)  TREE_PURPOSE(args)
-#define ARG_INFO_TAGS(args)   TREE_VALUE(args)
-#define ARG_INFO_TYPES(args)  TREE_CHAIN(args)
-#define ARG_INFO_OTHERS(args) TREE_TYPE(args)
-
 /* The file and line that the prototype came from if this is an
    old-style definition; used for diagnostics in
    store_parm_decls_oldstyle.  */
@@ -107,7 +100,7 @@ static location_t current_function_prototype_locus;
 /* The argument information structure for the function currently being
    defined.  */
 
-static GTY(()) tree current_function_arg_info;
+static struct c_arg_info *current_function_arg_info;
 
 /* The obstack on which parser and related data structures, which are
    not live beyond their top-level declaration or definition, are
@@ -405,8 +398,9 @@ static GTY(()) tree static_dtors;
 /* Forward declarations.  */
 static tree lookup_name_in_scope (tree, struct c_scope *);
 static tree c_make_fname_decl (tree, int);
-static tree grokdeclarator (tree, tree, enum decl_context, bool, tree *);
-static tree grokparms (tree, bool);
+static tree grokdeclarator (const struct c_declarator *, tree,
+			    enum decl_context, bool, tree *);
+static tree grokparms (struct c_arg_info *, bool);
 static void layout_array_type (tree);
 
 /* States indicating how grokdeclarator() should handle declspecs marked
@@ -2752,20 +2746,21 @@ shadow_tag_warned (tree declspecs, int warned)
    true if "static" is inside the [], false otherwise.  VLA_UNSPEC_P
    is true if the array is [*], a VLA of unspecified length which is
    nevertheless a complete type (not currently implemented by GCC),
-   false otherwise.  The declarator is constructed as an ARRAY_REF
-   (to be decoded by grokdeclarator), whose operand 0 is what's on the
-   left of the [] (filled by in set_array_declarator_inner) and operand 1
-   is the expression inside; whose TREE_TYPE is the type qualifiers and
-   which has TREE_STATIC set if "static" is used.  */
+   false otherwise.  The field for the contained declarator is left to be
+   filled in by set_array_declarator_inner.  */
 
-tree
+struct c_declarator *
 build_array_declarator (tree expr, tree quals, bool static_p,
 			bool vla_unspec_p)
 {
-  tree decl;
-  decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
-  TREE_TYPE (decl) = quals;
-  TREE_STATIC (decl) = (static_p ? 1 : 0);
+  struct c_declarator *declarator = XOBNEW (&parser_obstack,
+					    struct c_declarator);
+  declarator->kind = cdk_array;
+  declarator->declarator = 0;
+  declarator->u.array.dimen = expr;
+  declarator->u.array.quals = quals;
+  declarator->u.array.static_p = static_p;
+  declarator->u.array.vla_unspec_p = vla_unspec_p;
   if (pedantic && !flag_isoc99)
     {
       if (static_p || quals != NULL_TREE)
@@ -2775,21 +2770,23 @@ build_array_declarator (tree expr, tree quals, bool static_p,
     }
   if (vla_unspec_p)
     warning ("GCC does not yet properly implement `[*]' array declarators");
-  return decl;
+  return declarator;
 }
 
-/* Set the type of an array declarator.  DECL is the declarator, as
-   constructed by build_array_declarator; TYPE is what appears on the left
-   of the [] and goes in operand 0.  ABSTRACT_P is true if it is an
-   abstract declarator, false otherwise; this is used to reject static and
-   type qualifiers in abstract declarators, where they are not in the
-   C99 grammar.  */
+/* Set the contained declarator of an array declarator.  DECL is the
+   declarator, as constructed by build_array_declarator; INNER is what
+   appears on the left of the [].  ABSTRACT_P is true if it is an
+   abstract declarator, false otherwise; this is used to reject static
+   and type qualifiers in abstract declarators, where they are not in
+   the C99 grammar (subject to possible change in DR#289).  */
 
-tree
-set_array_declarator_inner (tree decl, tree type, bool abstract_p)
+struct c_declarator *
+set_array_declarator_inner (struct c_declarator *decl,
+			    struct c_declarator *inner, bool abstract_p)
 {
-  TREE_OPERAND (decl, 0) = type;
-  if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+  decl->declarator = inner;
+  if (abstract_p && (decl->u.array.quals != NULL_TREE
+		     || decl->u.array.static_p))
     error ("static or type qualifiers in abstract declarator");
   return decl;
 }
@@ -2876,22 +2873,20 @@ split_specs_attrs (tree specs_attrs, tree *declspecs, tree *prefix_attributes)
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
-groktypename (tree type_name)
+groktypename (struct c_type_name *type_name)
 {
+  tree type;
   tree specs, attrs;
 
-  if (TREE_CODE (type_name) != TREE_LIST)
-    return type_name;
+  split_specs_attrs (type_name->specs, &specs, &attrs);
 
-  split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
-
-  type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, false,
-			     NULL);
+  type = grokdeclarator (type_name->declarator, specs, TYPENAME, false,
+			 NULL);
 
   /* Apply attributes.  */
-  decl_attributes (&type_name, attrs, 0);
+  decl_attributes (&type, attrs, 0);
 
-  return type_name;
+  return type;
 }
 
 /* Decode a declarator in an ordinary declaration or data definition.
@@ -2910,7 +2905,8 @@ groktypename (tree type_name)
    grokfield and not through here.  */
 
 tree
-start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
+start_decl (struct c_declarator *declarator, tree declspecs,
+	    bool initialized, tree attributes)
 {
   tree decl;
   tree tem;
@@ -3023,13 +3019,13 @@ start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
     {
-      tree ce = declarator;
+      struct c_declarator *ce = declarator;
 
-      if (TREE_CODE (ce) == INDIRECT_REF)
-	ce = TREE_OPERAND (declarator, 0);
-      if (TREE_CODE (ce) == CALL_EXPR)
+      if (ce->kind == cdk_pointer)
+	ce = declarator->declarator;
+      if (ce->kind == cdk_function)
 	{
-	  tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1));
+	  tree args = ce->u.arg_info->parms;
 	  for (; args; args = TREE_CHAIN (args))
 	    {
 	      tree type = TREE_TYPE (args);
@@ -3348,13 +3344,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
 /* Given a parsed parameter declaration, decode it into a PARM_DECL.  */
 
 tree
-grokparm (tree parm)
+grokparm (const struct c_parm *parm)
 {
-  tree decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
-			      TREE_PURPOSE (TREE_PURPOSE (parm)),
-			      PARM, false, NULL);
+  tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
+			      NULL);
 
-  decl_attributes (&decl, TREE_VALUE (parm), 0);
+  decl_attributes (&decl, parm->attrs, 0);
 
   return decl;
 }
@@ -3363,14 +3358,12 @@ grokparm (tree parm)
    and push that on the current scope.  */
 
 void
-push_parm_decl (tree parm)
+push_parm_decl (const struct c_parm *parm)
 {
   tree decl;
 
-  decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
-			 TREE_PURPOSE (TREE_PURPOSE (parm)),
-			 PARM, false, NULL);
-  decl_attributes (&decl, TREE_VALUE (parm), 0);
+  decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
+  decl_attributes (&decl, parm->attrs, 0);
 
   decl = pushdecl (decl);
 
@@ -3664,7 +3657,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
    and `extern' are interpreted.  */
 
 static tree
-grokdeclarator (tree declarator, tree declspecs,
+grokdeclarator (const struct c_declarator *declarator, tree declspecs,
 		enum decl_context decl_context, bool initialized, tree *width)
 {
   int specbits = 0;
@@ -3683,7 +3676,7 @@ grokdeclarator (tree declarator, tree declspecs,
   const char *name, *orig_name;
   tree typedef_type = 0;
   int funcdef_flag = 0;
-  enum tree_code innermost_code = ERROR_MARK;
+  bool funcdef_syntax = false;
   int size_varies = 0;
   tree decl_attr = NULL_TREE;
   tree array_ptr_quals = NULL_TREE;
@@ -3691,7 +3684,7 @@ grokdeclarator (tree declarator, tree declspecs,
   tree returned_attrs = NULL_TREE;
   bool bitfield = width != NULL;
   tree element_type;
-  tree arg_info = NULL_TREE;
+  struct c_arg_info *arg_info = 0;
 
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
@@ -3699,25 +3692,26 @@ grokdeclarator (tree declarator, tree declspecs,
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   {
-    tree decl = declarator;
+    const struct c_declarator *decl = declarator;
     name = 0;
 
     while (decl)
-      switch (TREE_CODE (decl))
+      switch (decl->kind)
 	{
-	case ARRAY_REF:
-	case INDIRECT_REF:
-	case CALL_EXPR:
-	  innermost_code = TREE_CODE (decl);
-	  decl = TREE_OPERAND (decl, 0);
+	case cdk_function:
+	case cdk_array:
+	case cdk_pointer:
+	  funcdef_syntax = (decl->kind == cdk_function);
+	  decl = decl->declarator;
 	  break;
 
-	case TREE_LIST:
-	  decl = TREE_VALUE (decl);
+	case cdk_attrs:
+	  decl = decl->declarator;
 	  break;
 
-	case IDENTIFIER_NODE:
-	  name = IDENTIFIER_POINTER (decl);
+	case cdk_id:
+	  if (decl->u.id)
+	    name = IDENTIFIER_POINTER (decl->u.id);
 	  decl = 0;
 	  break;
 
@@ -3732,7 +3726,7 @@ grokdeclarator (tree declarator, tree declspecs,
   /* A function definition's declarator must have the form of
      a function declarator.  */
 
-  if (funcdef_flag && innermost_code != CALL_EXPR)
+  if (funcdef_flag && !funcdef_syntax)
     return 0;
 
   /* If this looks like a function definition, make it one,
@@ -4163,22 +4157,22 @@ grokdeclarator (tree declarator, tree declspecs,
      Descend through it, creating more complex types, until we reach
      the declared identifier (or NULL_TREE, in an absolute declarator).  */
 
-  while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
+  while (declarator && declarator->kind != cdk_id)
     {
       if (type == error_mark_node)
 	{
-	  declarator = TREE_OPERAND (declarator, 0);
+	  declarator = declarator->declarator;
 	  continue;
 	}
 
-      /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
-	 an INDIRECT_REF (for *...),
-	 a CALL_EXPR (for ...(...)),
-	 a TREE_LIST (for nested attributes),
-	 an identifier (for the name being declared)
-	 or a null pointer (for the place in an absolute declarator
+      /* Each level of DECLARATOR is either a cdk_array (for ...[..]),
+	 a cdk_pointer (for *...),
+	 a cdk_function (for ...(...)),
+	 a cdk_attrs (for nested attributes),
+	 or a cdk_id (for the name being declared
+	 or the place in an absolute declarator
 	 where the name was omitted).
-	 For the last two cases, we have just exited the loop.
+	 For the last case, we have just exited the loop.
 
 	 At this point, TYPE is the type of elements of an array,
 	 or for a function to return, or for a pointer to point to.
@@ -4196,43 +4190,40 @@ grokdeclarator (tree declarator, tree declspecs,
 	  array_parm_static = 0;
 	}
 
-      switch (TREE_CODE (declarator))
+      switch (declarator->kind)
 	{
-	case TREE_LIST:
+	case cdk_attrs:
 	  {
-	    /* We encode a declarator with embedded attributes using a
-	       TREE_LIST.  */
-	    tree attrs = TREE_PURPOSE (declarator);
-	    tree inner_decl;
+	    /* A declarator with embedded attributes.  */
+	    tree attrs = declarator->u.attrs;
+	    const struct c_declarator *inner_decl;
 	    int attr_flags = 0;
-	    declarator = TREE_VALUE (declarator);
+	    declarator = declarator->declarator;
 	    inner_decl = declarator;
-	    while (inner_decl != NULL_TREE
-		   && TREE_CODE (inner_decl) == TREE_LIST)
-	      inner_decl = TREE_VALUE (inner_decl);
-	    if (inner_decl == NULL_TREE
-		|| TREE_CODE (inner_decl) == IDENTIFIER_NODE)
+	    while (inner_decl->kind == cdk_attrs)
+	      inner_decl = inner_decl->declarator;
+	    if (inner_decl->kind == cdk_id)
 	      attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
-	    else if (TREE_CODE (inner_decl) == CALL_EXPR)
+	    else if (inner_decl->kind == cdk_function)
 	      attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
-	    else if (TREE_CODE (inner_decl) == ARRAY_REF)
+	    else if (inner_decl->kind == cdk_array)
 	      attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
 	    returned_attrs = decl_attributes (&type,
 					      chainon (returned_attrs, attrs),
 					      attr_flags);
 	    break;
 	  }
-	case ARRAY_REF:
+	case cdk_array:
 	  {
 	    tree itype = NULL_TREE;
-	    tree size = TREE_OPERAND (declarator, 1);
+	    tree size = declarator->u.array.dimen;
 	    /* The index is a signed object `sizetype' bits wide.  */
 	    tree index_type = c_common_signed_type (sizetype);
 
-	    array_ptr_quals = TREE_TYPE (declarator);
-	    array_parm_static = TREE_STATIC (declarator);
+	    array_ptr_quals = declarator->u.array.quals;
+	    array_parm_static = declarator->u.array.static_p;
 	    
-	    declarator = TREE_OPERAND (declarator, 0);
+	    declarator = declarator->declarator;
 
 	    /* Check for some types that there cannot be arrays of.  */
 	    
@@ -4375,7 +4366,7 @@ grokdeclarator (tree declarator, tree declspecs,
 		TYPE_SIZE (type) = bitsize_zero_node;
 		TYPE_SIZE_UNIT (type) = size_zero_node;
 	      }
-	    else if (declarator && TREE_CODE (declarator) == INDIRECT_REF)
+	    else if (declarator->kind == cdk_pointer)
 	      /* We can never complete an array type which is the
 	         target of a pointer, so go ahead and lay it out.  */
 	      layout_type (type);
@@ -4389,7 +4380,7 @@ grokdeclarator (tree declarator, tree declspecs,
 	      }
 	    break;
 	  }
-	case CALL_EXPR:
+	case cdk_function:
 	  {
 	    /* Say it's a definition only for the declarator closest
 	       to the identifier, apart possibly from some
@@ -4398,10 +4389,10 @@ grokdeclarator (tree declarator, tree declspecs,
 	    tree arg_types;
 	    if (funcdef_flag)
 	      {
-		tree t = TREE_OPERAND (declarator, 0);
-		while (TREE_CODE (t) == TREE_LIST)
-		  t = TREE_VALUE (t);
-		really_funcdef = (TREE_CODE (t) == IDENTIFIER_NODE);
+		const struct c_declarator *t = declarator->declarator;
+		while (t->kind == cdk_attrs)
+		  t = t->declarator;
+		really_funcdef = (t->kind == cdk_id);
 	      }
 
 	    /* Declaring a function type.  Make sure we have a valid
@@ -4425,7 +4416,7 @@ grokdeclarator (tree declarator, tree declspecs,
 
 	    /* Construct the function type and go to the next
 	       inner layer of declarator.  */
-	    arg_info = TREE_OPERAND (declarator, 1);
+	    arg_info = declarator->u.arg_info;
 	    arg_types = grokparms (arg_info, really_funcdef);
 
 	    /* Type qualifiers before the return type of the function
@@ -4448,7 +4439,7 @@ grokdeclarator (tree declarator, tree declspecs,
 	    type_quals = TYPE_UNQUALIFIED;
 	    
 	    type = build_function_type (type, arg_types);
-	    declarator = TREE_OPERAND (declarator, 0);
+	    declarator = declarator->declarator;
 	    
 	    /* Set the TYPE_CONTEXTs for each tagged type which is local to
 	       the formal parameter list of this FUNCTION_TYPE to point to
@@ -4456,14 +4447,14 @@ grokdeclarator (tree declarator, tree declspecs,
 	    {
 	      tree link;
 	      
-	      for (link = ARG_INFO_TAGS (arg_info);
+	      for (link = arg_info->tags;
 		   link;
 		   link = TREE_CHAIN (link))
 		TYPE_CONTEXT (TREE_VALUE (link)) = type;
 	    }
 	    break;
 	  }
-	case INDIRECT_REF:
+	case cdk_pointer:
 	  {
 	    /* Merge any constancy or volatility into the target type
 	       for the pointer.  */
@@ -4480,7 +4471,7 @@ grokdeclarator (tree declarator, tree declspecs,
 	    
 	    /* Process a list of type modifier keywords (such as const
 	       or volatile) that were given inside the `*'.  */
-	    if (TREE_TYPE (declarator))
+	    if (declarator->u.pointer_quals)
 	      {
 		tree typemodlist;
 		int erred = 0;
@@ -4488,7 +4479,7 @@ grokdeclarator (tree declarator, tree declspecs,
 		constp = 0;
 		volatilep = 0;
 		restrictp = 0;
-		for (typemodlist = TREE_TYPE (declarator); typemodlist;
+		for (typemodlist = declarator->u.pointer_quals; typemodlist;
 		     typemodlist = TREE_CHAIN (typemodlist))
 		  {
 		    tree qualifier = TREE_VALUE (typemodlist);
@@ -4525,7 +4516,7 @@ grokdeclarator (tree declarator, tree declspecs,
 			      | (volatilep ? TYPE_QUAL_VOLATILE : 0));
 	      }
 	    
-	    declarator = TREE_OPERAND (declarator, 0);
+	    declarator = declarator->declarator;
 	    break;
 	  }
 	default:
@@ -4559,7 +4550,7 @@ grokdeclarator (tree declarator, tree declspecs,
 	pedwarn ("ISO C forbids qualified function types");
       if (type_quals)
 	type = c_build_qualified_type (type, type_quals);
-      decl = build_decl (TYPE_DECL, declarator, type);
+      decl = build_decl (TYPE_DECL, declarator->u.id, type);
       if ((specbits & (1 << (int) RID_SIGNED))
 	  || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
 	C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
@@ -4691,7 +4682,7 @@ grokdeclarator (tree declarator, tree declspecs,
 
 	type_as_written = type;
 
-	decl = build_decl (PARM_DECL, declarator, type);
+	decl = build_decl (PARM_DECL, declarator->u.id, type);
 	if (size_varies)
 	  C_DECL_VARIABLE_SIZE (decl) = 1;
 
@@ -4728,7 +4719,7 @@ grokdeclarator (tree declarator, tree declspecs,
 	  type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
 							   type_quals),
 				   TYPE_DOMAIN (type));
-	decl = build_decl (FIELD_DECL, declarator, type);
+	decl = build_decl (FIELD_DECL, declarator->u.id, type);
 	DECL_NONADDRESSABLE_P (decl) = bitfield;
 
 	if (size_varies)
@@ -4755,7 +4746,7 @@ grokdeclarator (tree declarator, tree declspecs,
 	      error ("invalid storage class for function `%s'", name);
 	  }
 
-	decl = build_decl (FUNCTION_DECL, declarator, type);
+	decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
 	decl = build_decl_attribute_variant (decl, decl_attr);
 
 	DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
@@ -4792,7 +4783,7 @@ grokdeclarator (tree declarator, tree declspecs,
 	  C_FUNCTION_IMPLICIT_INT (decl) = 1;
 
 	/* Record presence of `inline', if it is reasonable.  */
-	if (MAIN_NAME_P (declarator))
+	if (MAIN_NAME_P (declarator->u.id))
 	  {
 	    if (inlinep)
 	      warning ("cannot inline function `main'");
@@ -4845,8 +4836,8 @@ grokdeclarator (tree declarator, tree declspecs,
 	   the 'extern' declaration is taken to refer to that decl.) */
 	if (extern_ref && current_scope != file_scope)
 	  {
-	    tree global_decl  = identifier_global_value (declarator);
-	    tree visible_decl = lookup_name (declarator);
+	    tree global_decl  = identifier_global_value (declarator->u.id);
+	    tree visible_decl = lookup_name (declarator->u.id);
 
 	    if (global_decl
 		&& global_decl != visible_decl
@@ -4856,7 +4847,7 @@ grokdeclarator (tree declarator, tree declspecs,
 		     "'extern'");
 	  }
 
-	decl = build_decl (VAR_DECL, declarator, type);
+	decl = build_decl (VAR_DECL, declarator->u.id, type);
 	if (size_varies)
 	  C_DECL_VARIABLE_SIZE (decl) = 1;
 
@@ -4948,9 +4939,9 @@ grokdeclarator (tree declarator, tree declspecs,
    when FUNCDEF_FLAG is false.  */
 
 static tree
-grokparms (tree arg_info, bool funcdef_flag)
+grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
 {
-  tree arg_types = ARG_INFO_TYPES (arg_info);
+  tree arg_types = arg_info->types;
 
   if (warn_strict_prototypes && arg_types == 0 && !funcdef_flag
       && !in_system_header)
@@ -4964,8 +4955,8 @@ grokparms (tree arg_info, bool funcdef_flag)
       if (! funcdef_flag)
 	pedwarn ("parameter names (without types) in function declaration");
 
-      ARG_INFO_PARMS (arg_info) = ARG_INFO_TYPES (arg_info);
-      ARG_INFO_TYPES (arg_info) = 0;
+      arg_info->parms = arg_info->types;
+      arg_info->types = 0;
       return 0;
     }
   else
@@ -4978,7 +4969,7 @@ grokparms (tree arg_info, bool funcdef_flag)
 	 the scope of the declaration, so the types can never be
 	 completed, and no call can be compiled successfully.  */
 
-      for (parm = ARG_INFO_PARMS (arg_info), typelt = arg_types, parmno = 1;
+      for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
 	   parm;
 	   parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
 	{
@@ -5015,26 +5006,20 @@ grokparms (tree arg_info, bool funcdef_flag)
     }
 }
 
-/* Take apart the current scope and return a tree_list node with info
-   on a parameter list just parsed.  This tree_list node should be
-   examined using the ARG_INFO_* macros, defined above:
-
-     ARG_INFO_PARMS:  a list of parameter decls.
-     ARG_INFO_TAGS:   a list of structure, union and enum tags defined.
-     ARG_INFO_TYPES:  a list of argument types to go in the FUNCTION_TYPE.
-     ARG_INFO_OTHERS: a list of non-parameter decls (notably enumeration
-                      constants) defined with the parameters.
+/* Take apart the current scope and return a c_arg_info structure with
+   info on a parameter list just parsed.
 
-   This tree_list node is later fed to 'grokparms' and 'store_parm_decls'.
+   This structure is later fed to 'grokparms' and 'store_parm_decls'.
 
    ELLIPSIS being true means the argument list ended in '...' so don't
    append a sentinel (void_list_node) to the end of the type-list.  */
 
-tree
+struct c_arg_info *
 get_parm_info (bool ellipsis)
 {
   struct c_binding *b = current_scope->bindings;
-  tree arg_info = make_node (TREE_LIST);
+  struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
+					struct c_arg_info);
   tree parms    = 0;
   tree tags     = 0;
   tree types    = 0;
@@ -5043,6 +5028,11 @@ get_parm_info (bool ellipsis)
   static bool explained_incomplete_types = false;
   bool gave_void_only_once_err = false;
 
+  arg_info->parms = 0;
+  arg_info->tags = 0;
+  arg_info->types = 0;
+  arg_info->others = 0;
+
   /* The bindings in this scope must not get put into a block.
      We will take care of deleting the binding nodes.  */
   current_scope->bindings = 0;
@@ -5070,7 +5060,7 @@ get_parm_info (bool ellipsis)
       if (ellipsis)
 	error ("'void' must be the only parameter");
 
-      ARG_INFO_TYPES (arg_info) = void_list_node;
+      arg_info->types = void_list_node;
       return arg_info;
     }
 
@@ -5191,10 +5181,10 @@ get_parm_info (bool ellipsis)
       b = free_binding_and_advance (b);
     }
 
-  ARG_INFO_PARMS  (arg_info) = parms;
-  ARG_INFO_TAGS   (arg_info) = tags;
-  ARG_INFO_TYPES  (arg_info) = types;
-  ARG_INFO_OTHERS (arg_info) = others;
+  arg_info->parms = parms;
+  arg_info->tags = tags;
+  arg_info->types = types;
+  arg_info->others = others;
   return arg_info;
 }
 
@@ -5283,7 +5273,7 @@ start_struct (enum tree_code code, tree name)
   return ref;
 }
 
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
+/* Process the specs, declarator and width (NULL if omitted)
    of a structure component, returning a FIELD_DECL node.
    WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
 
@@ -5292,11 +5282,12 @@ start_struct (enum tree_code code, tree name)
    are ultimately passed to `build_struct' to make the RECORD_TYPE node.  */
 
 tree
-grokfield (tree declarator, tree declspecs, tree width)
+grokfield (struct c_declarator *declarator, tree declspecs, tree width)
 {
   tree value;
 
-  if (declarator == NULL_TREE && width == NULL_TREE)
+  if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+      && width == NULL_TREE)
     {
       /* This is an unnamed decl.
 
@@ -5925,7 +5916,8 @@ build_enumerator (tree name, tree value)
    yyparse to report a parse error.  */
 
 int
-start_function (tree declspecs, tree declarator, tree attributes)
+start_function (tree declspecs, struct c_declarator *declarator,
+		tree attributes)
 {
   tree decl1, old_decl;
   tree restype, resdecl;
@@ -6137,12 +6129,9 @@ start_function (tree declspecs, tree declarator, tree attributes)
    need only record them as in effect and complain if any redundant
    old-style parm decls were written.  */
 static void
-store_parm_decls_newstyle (tree fndecl, tree arg_info)
+store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
 {
   tree decl;
-  tree parms  = ARG_INFO_PARMS  (arg_info);
-  tree tags   = ARG_INFO_TAGS   (arg_info);
-  tree others = ARG_INFO_OTHERS (arg_info);
 
   if (current_scope->bindings)
     {
@@ -6158,13 +6147,13 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
      (this happens when a function definition has just an ellipsis in
      its parameter list).  */
   else if (warn_traditional && !in_system_header && !current_function_scope
-	   && ARG_INFO_TYPES (arg_info) != error_mark_node)
+	   && arg_info->types != error_mark_node)
     warning ("%Jtraditional C rejects ISO C style function definitions",
 	     fndecl);
 
   /* Now make all the parameter declarations visible in the function body.
      We can bypass most of the grunt work of pushdecl.  */
-  for (decl = parms; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
@@ -6175,10 +6164,10 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
     }
 
   /* Record the parameter list in the function declaration.  */
-  DECL_ARGUMENTS (fndecl) = parms;
+  DECL_ARGUMENTS (fndecl) = arg_info->parms;
 
   /* Now make all the ancillary declarations visible, likewise.  */
-  for (decl = others; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
@@ -6187,7 +6176,7 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
     }
 
   /* And all the tag declarations.  */
-  for (decl = tags; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
     if (TREE_PURPOSE (decl))
       bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
 	    /*invisible=*/false, /*nested=*/false);
@@ -6197,11 +6186,11 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
    definitions (separate parameter list and declarations).  */
 
 static void
-store_parm_decls_oldstyle (tree fndecl, tree arg_info)
+store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
 {
   struct c_binding *b;
   tree parm, decl, last;
-  tree parmids = ARG_INFO_PARMS (arg_info);
+  tree parmids = arg_info->parms;
 
   /* We use DECL_WEAK as a flag to show which parameters have been
      seen already, since it is not used on PARM_DECL.  */
@@ -6419,7 +6408,7 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
    function declaration.  */
 
 void
-store_parm_decls_from (tree arg_info)
+store_parm_decls_from (struct c_arg_info *arg_info)
 {
   current_function_arg_info = arg_info;
   store_parm_decls ();
@@ -6439,7 +6428,7 @@ store_parm_decls (void)
   bool proto;
 
   /* The argument information block for FNDECL.  */
-  tree arg_info = current_function_arg_info;
+  struct c_arg_info *arg_info = current_function_arg_info;
   current_function_arg_info = 0;
 
   /* True if this definition is written with a prototype.  Note:
@@ -6447,7 +6436,7 @@ store_parm_decls (void)
      list in a function definition as equivalent to (void) -- an
      empty argument list specifies the function has no parameters,
      but only (void) sets up a prototype for future calls.  */
-  proto = ARG_INFO_TYPES (arg_info) != 0;
+  proto = arg_info->types != 0;
 
   if (proto)
     store_parm_decls_newstyle (fndecl, arg_info);
@@ -6865,52 +6854,78 @@ build_void_list_node (void)
   return t;
 }
 
-/* Return a structure for a parameter with the given SPECS, ATTRS and
-   DECLARATOR.  */
+/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR.  */
 
-tree
-build_c_parm (tree specs, tree attrs, tree declarator)
+struct c_parm *
+build_c_parm (tree specs, tree attrs, struct c_declarator *declarator)
 {
-  return build_tree_list (build_tree_list (specs, declarator), attrs);
+  struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
+  ret->specs = specs;
+  ret->attrs = attrs;
+  ret->declarator = declarator;
+  return ret;
 }
 
 /* Return a declarator with nested attributes.  TARGET is the inner
    declarator to which these attributes apply.  ATTRS are the
    attributes.  */
 
-tree
-build_attrs_declarator (tree attrs, tree target)
+struct c_declarator *
+build_attrs_declarator (tree attrs, struct c_declarator *target)
 {
-  return tree_cons (attrs, target, NULL_TREE);
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_attrs;
+  ret->declarator = target;
+  ret->u.attrs = attrs;
+  return ret;
 }
 
 /* Return a declarator for a function with arguments specified by ARGS
    and return type specified by TARGET.  */
 
-tree
-build_function_declarator (tree args, tree target)
+struct c_declarator *
+build_function_declarator (struct c_arg_info *args,
+			   struct c_declarator *target)
 {
-  return build_nt (CALL_EXPR, target, args, NULL_TREE);
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_function;
+  ret->declarator = target;
+  ret->u.arg_info = args;
+  return ret;
+}
+
+/* Return a declarator for the identifier IDENT (which may be
+   NULL_TREE for an abstract declarator).  */
+
+struct c_declarator *
+build_id_declarator (tree ident)
+{
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_id;
+  ret->declarator = 0;
+  ret->u.id = ident;
+  return ret;
 }
 
 /* Return something to represent absolute declarators containing a *.
    TARGET is the absolute declarator that the * contains.
    TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
    to apply to the pointer type, represented as identifiers, possible mixed
-   with attributes.
+   with attributes.  */
 
-   We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
-   if attributes are present) and whose type is the modifier list.  */
-
-tree
-make_pointer_declarator (tree type_quals_attrs, tree target)
+struct c_declarator *
+make_pointer_declarator (tree type_quals_attrs, struct c_declarator *target)
 {
   tree quals, attrs;
-  tree itarget = target;
+  struct c_declarator *itarget = target;
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
   split_specs_attrs (type_quals_attrs, &quals, &attrs);
   if (attrs != NULL_TREE)
     itarget = build_attrs_declarator (attrs, target);
-  return build1 (INDIRECT_REF, quals, itarget);
+  ret->kind = cdk_pointer;
+  ret->declarator = itarget;
+  ret->u.pointer_quals = quals;
+  return ret;
 }
 
 /* Synthesize a function which calls all the global ctors or global
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index fff001faa173..9a0b4d27e684 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -100,6 +100,8 @@ do {									\
 %start program
 
 %union {long itype; tree ttype; void *otype; struct c_expr exprtype;
+	struct c_arg_info *arginfotype; struct c_declarator *dtrtype;
+	struct c_type_name *typenametype; struct c_parm *parmtype;
 	enum tree_code code; location_t location; }
 
 /* All identifiers that are not reserved words
@@ -217,11 +219,11 @@ do {									\
 
 %type <ttype> c99_block_start c99_block_lineno_labeled_stmt
 %type <ttype> if_statement_1 if_statement_2
-%type <ttype> declarator
-%type <ttype> notype_declarator after_type_declarator
-%type <ttype> parm_declarator
-%type <ttype> parm_declarator_starttypename parm_declarator_nostarttypename
-%type <ttype> array_declarator
+%type <dtrtype> declarator
+%type <dtrtype> notype_declarator after_type_declarator
+%type <dtrtype> parm_declarator
+%type <dtrtype> parm_declarator_starttypename parm_declarator_nostarttypename
+%type <dtrtype> array_declarator
 
 %type <ttype> structsp_attr structsp_nonattr
 %type <ttype> component_decl_list component_decl_list2
@@ -229,13 +231,15 @@ do {									\
 %type <ttype> component_notype_declarator
 %type <ttype> enumlist enumerator
 %type <ttype> struct_head union_head enum_head
-%type <ttype> typename absdcl absdcl1 absdcl1_ea absdcl1_noea
-%type <ttype> direct_absdcl1 absdcl_maybe_attribute
+%type <typenametype> typename
+%type <dtrtype> absdcl absdcl1 absdcl1_ea absdcl1_noea direct_absdcl1
+%type <parmtype> absdcl_maybe_attribute
 %type <ttype> condition xexpr for_cond_expr for_incr_expr
-%type <ttype> parms parm firstparm identifiers
+%type <parmtype> parm firstparm
+%type <ttype> identifiers
 
-%type <ttype> parmlist parmlist_1 parmlist_2
-%type <ttype> parmlist_or_identifiers parmlist_or_identifiers_1
+%type <arginfotype> parms parmlist parmlist_1 parmlist_2
+%type <arginfotype> parmlist_or_identifiers parmlist_or_identifiers_1
 %type <ttype> identifiers_or_typenames
 
 %type <itype> setspecs setspecs_fp extension
@@ -655,12 +659,12 @@ primary:
 		  $$.original_code = ERROR_MARK; }
 	| '(' typename ')' '{'
 		{ start_init (NULL_TREE, NULL, 0);
-		  $2 = groktypename ($2);
-		  really_start_incremental_init ($2); }
+		  $<ttype>$ = groktypename ($2);
+		  really_start_incremental_init ($<ttype>$); }
 	  initlist_maybe_comma '}'  %prec UNARY
 		{ struct c_expr init = pop_init_level (0);
 		  tree constructor = init.value;
-		  tree type = $2;
+		  tree type = $<ttype>5;
 		  finish_init ();
 		  maybe_warn_string_init (type, init);
 
@@ -1653,8 +1657,10 @@ after_type_declarator:
 	| '*' maybe_type_quals_attrs after_type_declarator  %prec UNARY
 		{ $$ = make_pointer_declarator ($2, $3); }
 	| TYPENAME
+		{ $$ = build_id_declarator ($1); }
 @@ifobjc
 	| OBJECTNAME
+		{ $$ = build_id_declarator ($1); }
 @@end_ifobjc
 	;
 
@@ -1673,8 +1679,10 @@ parm_declarator_starttypename:
 	| parm_declarator_starttypename array_declarator  %prec '.'
 		{ $$ = set_array_declarator_inner ($2, $1, false); }
 	| TYPENAME
+		{ $$ = build_id_declarator ($1); }
 @@ifobjc
 	| OBJECTNAME
+		{ $$ = build_id_declarator ($1); }
 @@end_ifobjc
 	;
 
@@ -1704,6 +1712,7 @@ notype_declarator:
 	| notype_declarator array_declarator  %prec '.'
 		{ $$ = set_array_declarator_inner ($2, $1, false); }
 	| IDENTIFIER
+		{ $$ = build_id_declarator ($1); }
 	;
 
 struct_head:
@@ -1837,7 +1846,8 @@ component_decl:
 		  if (pedantic)
 		    pedwarn ("ISO C doesn't support unnamed structs/unions");
 
-		  $$ = grokfield(NULL, current_declspecs, NULL_TREE);
+		  $$ = grokfield (build_id_declarator (NULL_TREE),
+				  current_declspecs, NULL_TREE);
 		  POP_DECLSPEC_STACK; }
 	| declspecs_nosc_nots setspecs components_notype
 		{ $$ = $3;
@@ -1876,7 +1886,8 @@ component_declarator:
 		  decl_attributes (&$$,
 				   chainon ($4, all_prefix_attributes), 0); }
 	| ':' expr_no_commas maybe_attribute
-		{ $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+		{ $$ = grokfield (build_id_declarator (NULL_TREE),
+				  current_declspecs, $2.value);
 		  decl_attributes (&$$,
 				   chainon ($3, all_prefix_attributes), 0); }
 	;
@@ -1891,7 +1902,8 @@ component_notype_declarator:
 		  decl_attributes (&$$,
 				   chainon ($4, all_prefix_attributes), 0); }
 	| ':' expr_no_commas maybe_attribute
-		{ $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
+		{ $$ = grokfield (build_id_declarator (NULL_TREE),
+				  current_declspecs, $2.value);
 		  decl_attributes (&$$,
 				   chainon ($3, all_prefix_attributes), 0); }
 	;
@@ -1923,19 +1935,21 @@ typename:
 		{ pending_xref_error ();
 		  $<ttype>$ = $1; }
 	  absdcl
-		{ $$ = build_tree_list ($<ttype>2, $3); }
+		{ $$ = XOBNEW (&parser_obstack, struct c_type_name);
+		  $$->specs = $<ttype>2;
+		  $$->declarator = $3; }
 	;
 
 absdcl:   /* an absolute declarator */
 	/* empty */
-		{ $$ = NULL_TREE; }
+		{ $$ = build_id_declarator (NULL_TREE); }
 	| absdcl1
 	;
 
 absdcl_maybe_attribute:   /* absdcl maybe_attribute, but not just attributes */
 	/* empty */
 		{ $$ = build_c_parm (current_declspecs, all_prefix_attributes,
-				     NULL_TREE); }
+				     build_id_declarator (NULL_TREE)); }
 	| absdcl1
 		{ $$ = build_c_parm (current_declspecs, all_prefix_attributes,
 				     $1); }
@@ -1958,7 +1972,8 @@ absdcl1_noea:
 
 absdcl1_ea:
 	  '*' maybe_type_quals_attrs
-		{ $$ = make_pointer_declarator ($2, NULL_TREE); }
+		{ $$ = make_pointer_declarator
+		    ($2, build_id_declarator (NULL_TREE)); }
 	| '*' maybe_type_quals_attrs absdcl1_ea
 		{ $$ = make_pointer_declarator ($2, $3); }
 	;
@@ -1971,9 +1986,11 @@ direct_absdcl1:
 	| direct_absdcl1 array_declarator
 		{ $$ = set_array_declarator_inner ($2, $1, true); }
 	| '(' parmlist
-		{ $$ = build_function_declarator ($2, NULL_TREE); }
+		{ $$ = build_function_declarator
+		    ($2, build_id_declarator (NULL_TREE)); }
 	| array_declarator
-		{ $$ = set_array_declarator_inner ($1, NULL_TREE, true); }
+		{ $$ = set_array_declarator_inner
+		    ($1, build_id_declarator (NULL_TREE), true); }
 	;
 
 /* The [...] part of a declarator for an array type.  */
@@ -2519,17 +2536,28 @@ parmlist_1:
 	  parmlist_1
 		{ $$ = $6; }
 	| error ')'
-		{ $$ = make_node (TREE_LIST); }
+		{ $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+		  $$->parms = 0;
+		  $$->tags = 0;
+		  $$->types = 0;
+		  $$->others = 0; }
 	;
 
 /* This is what appears inside the parens in a function declarator.
-   Is value is represented in the format that grokdeclarator expects.  */
+   Its value is represented in the format that grokdeclarator expects.  */
 parmlist_2:  /* empty */
-		{ $$ = make_node (TREE_LIST); }
+		{ $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+		  $$->parms = 0;
+		  $$->tags = 0;
+		  $$->types = 0;
+		  $$->others = 0; }
 	| ELLIPSIS
-		{ $$ = make_node (TREE_LIST); 
+		{ $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+		  $$->parms = 0;
+		  $$->tags = 0;
+		  $$->others = 0;
 		  /* Suppress -Wold-style-definition for this case.  */
-		  TREE_CHAIN ($$) = error_mark_node;
+		  $$->types = error_mark_node;
 		  error ("ISO C requires a named argument before `...'");
 		}
 	| parms
@@ -2614,7 +2642,11 @@ parmlist_or_identifiers:
 parmlist_or_identifiers_1:
 	  parmlist_1
 	| identifiers ')'
-		{ $$ = tree_cons (NULL_TREE, NULL_TREE, $1);
+		{ $$ = XOBNEW (&parser_obstack, struct c_arg_info);
+		  $$->parms = 0;
+		  $$->tags = 0;
+		  $$->types = $1;
+		  $$->others = 0;
 
 		  /* Make sure we have a parmlist after attributes.  */
 		  if ($<ttype>-1 != 0)
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index e241d4bddeaa..09f679ef8b1e 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -131,6 +131,81 @@ struct c_expr
   enum tree_code original_code;
 };
 
+/* The various kinds of declarators in C.  */
+enum c_declarator_kind {
+  /* An identifier.  */
+  cdk_id,
+  /* A function.  */
+  cdk_function,
+  /* An array.  */
+  cdk_array,
+  /* A pointer.  */
+  cdk_pointer,
+  /* Parenthesized declarator with nested attributes.  */
+  cdk_attrs
+};
+
+/* Information about the parameters in a function declarator.  */
+struct c_arg_info {
+  /* A list of parameter decls.  */
+  tree parms;
+  /* A list of structure, union and enum tags defined.  */
+  tree tags;
+  /* A list of argument types to go in the FUNCTION_TYPE.  */
+  tree types;
+  /* A list of non-parameter decls (notably enumeration constants)
+     defined with the parameters.  */
+  tree others;
+};
+
+/* A declarator.  */
+struct c_declarator {
+  /* The kind of declarator.  */
+  enum c_declarator_kind kind;
+  /* Except for cdk_id, the contained declarator.  For cdk_id, NULL.  */
+  struct c_declarator *declarator;
+  union {
+    /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract
+       declarator.  */
+    tree id;
+    /* For functions.  */
+    struct c_arg_info *arg_info;
+    /* For arrays.  */
+    struct {
+      /* The array dimension, or NULL for [] and [*].  */
+      tree dimen;
+      /* The qualifiers (and attributes, currently ignored) inside [].  */
+      tree quals;
+      /* Whether [static] was used.  */
+      BOOL_BITFIELD static_p : 1;
+      /* Whether [*] was used.  */
+      BOOL_BITFIELD vla_unspec_p : 1;
+    } array;
+    /* For pointers, the qualifiers on the pointer type.  */
+    tree pointer_quals;
+    /* For attributes.  */
+    tree attrs;
+  } u;
+};
+
+/* A type name.  */
+struct c_type_name {
+  /* The declaration specifiers.  */
+  tree specs;
+  /* The declarator.  */
+  struct c_declarator *declarator;
+};
+
+/* A parameter.  */
+struct c_parm {
+  /* The declaration specifiers, minus any prefix attributes.  */
+  tree specs;
+  /* The attributes.  */
+  tree attrs;
+  /* The declarator.  */
+  struct c_declarator *declarator;
+};
+
 /* Save and restore the variables in this file and elsewhere
    that keep track of the progress of compilation of the current function.
    Used for nested functions.  */
@@ -141,7 +216,7 @@ struct language_function GTY(())
   tree x_break_label;
   tree x_cont_label;
   struct c_switch * GTY((skip)) x_switch_stack;
-  tree arg_info;
+  struct c_arg_info * GTY((skip)) arg_info;
   int returns_value;
   int returns_null;
   int returns_abnormally;
@@ -171,7 +246,7 @@ extern void c_expand_body (tree);
 extern void c_init_decl_processing (void);
 extern void c_dup_lang_specific_decl (tree);
 extern void c_print_identifier (FILE *, tree, int);
-extern tree build_array_declarator (tree, tree, bool, bool);
+extern struct c_declarator *build_array_declarator (tree, tree, bool, bool);
 extern tree build_enumerator (tree, tree);
 extern void check_for_loop_decls (void);
 extern void mark_forward_parm_decls (void);
@@ -184,36 +259,42 @@ extern void finish_decl (tree, tree, tree);
 extern tree finish_enum (tree, tree, tree);
 extern void finish_function (void);
 extern tree finish_struct (tree, tree, tree);
-extern tree get_parm_info (bool);
-extern tree grokfield (tree, tree, tree);
+extern struct c_arg_info *get_parm_info (bool);
+extern tree grokfield (struct c_declarator *, tree, tree);
 extern void split_specs_attrs (tree, tree *, tree *);
-extern tree groktypename (tree);
-extern tree grokparm (tree);
+extern tree groktypename (struct c_type_name *);
+extern tree grokparm (const struct c_parm *);
 extern tree implicitly_declare (tree);
 extern void keep_next_level (void);
 extern tree lookup_name (tree);
 extern void pending_xref_error (void);
 extern void c_push_function_context (struct function *);
 extern void c_pop_function_context (struct function *);
-extern void push_parm_decl (tree);
+extern void push_parm_decl (const struct c_parm *);
 extern tree pushdecl_top_level (tree);
-extern tree set_array_declarator_inner (tree, tree, bool);
+extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
+							struct c_declarator *,
+							bool);
 extern tree builtin_function (const char *, tree, int, enum built_in_class,
 			      const char *, tree);
 extern void shadow_tag (tree);
 extern void shadow_tag_warned (tree, int);
 extern tree start_enum (tree);
-extern int  start_function (tree, tree, tree);
-extern tree start_decl (tree, tree, bool, tree);
+extern int  start_function (tree, struct c_declarator *, tree);
+extern tree start_decl (struct c_declarator *, tree, bool, tree);
 extern tree start_struct (enum tree_code, tree);
 extern void store_parm_decls (void);
-extern void store_parm_decls_from (tree);
+extern void store_parm_decls_from (struct c_arg_info *);
 extern tree xref_tag (enum tree_code, tree);
 extern int c_expand_decl (tree);
-extern tree build_c_parm (tree, tree, tree);
-extern tree build_attrs_declarator (tree, tree);
-extern tree build_function_declarator (tree, tree);
-extern tree make_pointer_declarator (tree, tree);
+extern struct c_parm *build_c_parm (tree, tree, struct c_declarator *);
+extern struct c_declarator *build_attrs_declarator (tree,
+						    struct c_declarator *);
+extern struct c_declarator *build_function_declarator (struct c_arg_info *,
+						       struct c_declarator *);
+extern struct c_declarator *build_id_declarator (tree);
+extern struct c_declarator *make_pointer_declarator (tree,
+						     struct c_declarator *);
 
 /* in c-objc-common.c */
 extern int c_disregard_inline_limits (tree);
@@ -252,13 +333,13 @@ extern tree build_external_ref (tree, int);
 extern void record_maybe_used_decl (tree);
 extern void pop_maybe_used (bool);
 extern struct c_expr c_expr_sizeof_expr (struct c_expr);
-extern struct c_expr c_expr_sizeof_type (tree);
+extern struct c_expr c_expr_sizeof_type (struct c_type_name *);
 extern struct c_expr parser_build_binary_op (enum tree_code, struct c_expr,
 					     struct c_expr);
 extern void readonly_error (tree, const char *);
 extern tree build_conditional_expr (tree, tree, tree);
 extern tree build_compound_expr (tree, tree);
-extern tree c_cast_expr (tree, tree);
+extern tree c_cast_expr (struct c_type_name *, tree);
 extern tree build_c_cast (tree, tree);
 extern tree build_modify_expr (tree, enum tree_code, tree);
 extern void store_init_value (tree, tree);
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 9b20152cb5bf..1bab69565bb5 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -1859,7 +1859,7 @@ c_expr_sizeof_expr (struct c_expr expr)
    name passed to sizeof (rather than the type itself).  */
 
 struct c_expr
-c_expr_sizeof_type (tree t)
+c_expr_sizeof_type (struct c_type_name *t)
 {
   tree type;
   struct c_expr ret;
@@ -3217,15 +3217,16 @@ build_c_cast (tree type, tree expr)
 
 /* Interpret a cast of expression EXPR to type TYPE.  */
 tree
-c_cast_expr (tree type, tree expr)
+c_cast_expr (struct c_type_name *type_name, tree expr)
 {
+  tree type;
   int saved_wsp = warn_strict_prototypes;
 
   /* This avoids warnings about unprototyped casts on
      integers.  E.g. "#define SIG_DFL (void(*)())0".  */
   if (TREE_CODE (expr) == INTEGER_CST)
     warn_strict_prototypes = 0;
-  type = groktypename (type);
+  type = groktypename (type_name);
   warn_strict_prototypes = saved_wsp;
 
   return build_c_cast (type, expr);
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 53e6a280ba17..bfee61589e66 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,9 @@
+2004-09-09  Joseph S. Myers  <jsm@polyomino.org.uk>
+
+	* objc-act.c (objc_start_function, really_start_method,
+	objc_get_parm_info, start_method_def): Update to new arg_info
+	structures.
+
 2004-09-07  Ziemowit Laski  <zlaski@apple.com>
 
 	* Make-lang.in (objc/objc-parse.o): Depend on $(C_COMMON_H) instead of
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 00dd3dfe95d4..f115ba44fd1e 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -156,7 +156,11 @@ static tree start_class (enum tree_code, tree, tree, tree);
 static tree continue_class (tree);
 static void finish_class (tree);
 static void start_method_def (tree);
+#ifdef OBJCPLUS
 static void objc_start_function (tree, tree, tree, tree);
+#else
+static void objc_start_function (tree, tree, tree, struct c_arg_info *);
+#endif
 static tree start_protocol (enum tree_code, tree, tree);
 static tree build_method_decl (enum tree_code, tree, tree, tree);
 static tree objc_add_method (tree, tree, int);
@@ -244,12 +248,20 @@ static void encode_gnu_bitfield (int, tree, int);
 static void encode_type (tree, int, int);
 static void encode_field_decl (tree, int, int);
 
+#ifdef OBJCPLUS
 static void really_start_method (tree, tree);
+#else
+static void really_start_method (tree, struct c_arg_info *);
+#endif
 static int objc_types_are_equivalent (tree, tree);
 static int comp_proto_with_proto (tree, tree);
 static tree get_arg_type_list (tree, int, int);
 static void objc_push_parm (tree);
+#ifdef OBJCPLUS
 static tree objc_get_parm_info (int);
+#else
+static struct c_arg_info *objc_get_parm_info (int);
+#endif
 static void synth_self_and_ucmd_args (void);
 
 /* Utilities for debugging and error diagnostics.  */
@@ -7338,16 +7350,22 @@ objc_push_parm (tree parm)
 /* Retrieve the formal paramter list constructed via preceding calls to
    objc_push_parm().  */
 
-static tree
 #ifdef OBJCPLUS
+static tree
 objc_get_parm_info (int have_ellipsis ATTRIBUTE_UNUSED)
 #else
+static struct c_arg_info *
 objc_get_parm_info (int have_ellipsis)
 #endif
 {
+#ifdef OBJCPLUS
   tree parm_info = objc_parmlist;
+  objc_parmlist = NULL_TREE;
 
-#ifndef OBJCPLUS
+  return parm_info;
+#else
+  tree parm_info = objc_parmlist;
+  struct c_arg_info *arg_info;
   /* The C front-end requires an elaborate song and dance at
      this point.  */
   push_scope ();
@@ -7360,12 +7378,11 @@ objc_get_parm_info (int have_ellipsis)
       pushdecl (parm_info);
       parm_info = next;
     }
-  parm_info = get_parm_info (have_ellipsis);
+  arg_info = get_parm_info (have_ellipsis);
   pop_scope ();
-#endif
   objc_parmlist = NULL_TREE;
-
-  return parm_info;
+  return arg_info;
+#endif
 }
 
 /* Synthesize the formal parameters 'id self' and 'SEL _cmd' needed for ObjC
@@ -7400,6 +7417,11 @@ static void
 start_method_def (tree method)
 {
   tree parmlist;
+#ifdef OBJCPLUS
+  tree parm_info;
+#else
+  struct c_arg_info *parm_info;
+#endif
   int have_ellipsis = 0;
 
   /* Required to implement _msgSuper.  */
@@ -7434,9 +7456,9 @@ start_method_def (tree method)
 	have_ellipsis = 1;
     }
 
-  parmlist = objc_get_parm_info (have_ellipsis);
+  parm_info = objc_get_parm_info (have_ellipsis);
 
-  really_start_method (objc_method_context, parmlist);
+  really_start_method (objc_method_context, parm_info);
 }
 
 static void
@@ -7509,11 +7531,19 @@ comp_proto_with_proto (tree proto1, tree proto2)
 }
 
 static void
-objc_start_function (tree name, tree type, tree attrs, tree params)
+objc_start_function (tree name, tree type, tree attrs,
+#ifdef OBJCPLUS
+		     tree params
+#else
+		     struct c_arg_info *params
+#endif
+		     )
 {
   tree fndecl = build_decl (FUNCTION_DECL, name, type);
 
+#ifdef OBJCPLUS
   DECL_ARGUMENTS (fndecl) = params;
+#endif
   DECL_INITIAL (fndecl) = error_mark_node;
   DECL_EXTERNAL (fndecl) = 0;
   TREE_STATIC (fndecl) = 1;
@@ -7532,7 +7562,7 @@ objc_start_function (tree name, tree type, tree attrs, tree params)
     = build_decl (RESULT_DECL, NULL_TREE,
 		  TREE_TYPE (TREE_TYPE (current_function_decl)));
   start_fname_decls ();
-  store_parm_decls_from (DECL_ARGUMENTS (current_function_decl));
+  store_parm_decls_from (params);
 #endif
 
   TREE_USED (current_function_decl) = 1;
@@ -7545,7 +7575,13 @@ objc_start_function (tree name, tree type, tree attrs, tree params)
    - If we have a prototype, check for type consistency.  */
 
 static void
-really_start_method (tree method, tree parmlist)
+really_start_method (tree method,
+#ifdef OBJCPLUS
+		     tree parmlist
+#else
+		     struct c_arg_info *parmlist
+#endif
+		     )
 {
   tree ret_type, meth_type;
   tree method_id;
-- 
GitLab