This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[static-tree] attributes


The attached patch is the attribute list rewrite I foreshadowed on
gcc-devel.  It removes the use of TREE_LIST for attributes, using
a new attribute_list_s structure (which is not actually a list datatype
at all).

It is a largeish patch that touches every frontend and most backends.
I have tested it by bootstrap & dejagnu on powerpc-darwin, plus
building the default languages' compilers on *-elf where '*' is each
CPU that I changed.  I also did this for sparc-solaris.  In each case,
I checked that the CPU file *.c built with no added warnings;
generally I checked that cc1 and cc1plus linked, but for sh-elf the
build failed for reasons unrelated to this patch.

I will commit it to a new 'static-tree-branch' that I will be creating
to hold it and subsequent work.

I would appreciate it if anyone changing or adding attributes or
attribute handling could make the corresponding change on
static-tree-branch.  Otherwise your code will probably quietly break
when I merge the branch.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/gcc-attrlist-2.patch======================
Index: gcc/ChangeLog
2004-09-30  Geoffrey Keating  <geoffk@apple.com>

	General changes that apply to every file listed:
	Update parameters and return value of attribute handlers.  Replace
	'tree' with 'attribute_list' in many places.  Replace
	'lookup_attribute' with 'has_attribute_p' or 'get_attribute'.
	Replace NULL_TREE with NULL when referring to an attribute list.
	Use 'merge_attributes' instead of 'chainon'.  Change each
	machine-specific insert_attribute function into an add_attribute
	function.  Replace each copy of handle_fndecl_attribute in the
	backends with either a call to the generic routine or NULL.
	
	* attribs.c (enum attribute_disposition): New.
	(determine_dispositions): New.
	(decl_attributes): Support new attribute representation.
	* builtin-attrs.def: Use new DEF_ATTR and DEF_ATTR_NULL macros.
	* c-common.c: (c_init_attributes): Use DEF_ATTR and DEF_ATTR_NULL
	macros.
	(check_function_nonnull): Update for new attribute list format.
	(check_function_sentinel): Likewise.
	(check_function_arguments): Do nothing if no attributes.
	(check_function_arguments_recurse): Update for new attribute list
	format.
	* c-common.h: General changes only.
	* c-decl.c: General changes only.
	* c-format.c (check_function_format): Update for new attribute format.
	* c-objc-common.c: General changes only.
	* c-parse.in: Update rules to return an attribute_list when
	appropriate.
	(attribute_list): Ignore one_attribute structures with NULL names.
	Use merge_attributes_1 to create attribute lists.
	(attrib): Return a struct one_attribute.
	* c-pragma.c (apply_pragma_weak): Use merge_attributes_1 to create
	attribute list.
	* c-tree.h: General changes only.
	* c-typeck.c: General changes only.
	* cgraphunit.c: General changes only.
	* coretypes.h: Declare struct one_attribute, struct
	attribute_list_s, attribute_list, attribute_count.
	* fold-const.c: General changes only.
	* integrate.c (function_attribute_inlinable_p): Update for new
	attribute list format.
	* langhooks.c: General changes only.
	* langhooks.h (builtin_function): General changes.
	* passes.c (rest_of_decl_compilation): General changes.
	* print-tree.c (print_attributes): New.
	(print_node): Use print_attributes.
	* system.h: Poison TARGET_INSERT_ATTRIBUTES.
	* target-def.h (TARGET_ADD_ATTRIBUTES): Rename from
	TARGET_INSERT_ATTRIBUTES.
	* target.h (merge_decl_attributes): General changes.
	(merge_type_attributes): General changes.
	(add_attributes): Rename from insert_attributes, change parameters.
	* targhooks.h (default_add_attributes): New.
	* tree-browser.c: Add comment asking for documentation.  Fudge
	enough so that it keeps compiling.
	* tree-inline.c: General changes.
	* tree.c (lookup_attribute): Rewrite.
	(has_attribute_p): New.
	(get_attribute): New.
	(merge_attributes_1): New.
	(merge_attributes): Rewrite.
	(handle_fndecl_attribute): New.
	(merge_dllimport_decl_attributes): Use merge_attributes_1 to delete
	attributes.
	(attribute_hash_list): Update for new attribute list format.
	(attribute_list_equal): Rewrite.
	(attribute_list_contained): Rewrite.
	* tree.h: Add names to arguments of some prototypes when referenced
	by their comments.
	(struct one_attribute): Define.
	(struct attribute_list_s): Define.
	(ATTRIBUTE_COUNT): New.
	(struct attribute_spec): Change parameters and return value of
	field 'handler'.
	(has_attribute_p): Prototype.
	(get_attribute): Prototype.
	(merge_attributes_1): Prototype.
	(handle_fndecl_attribute): Prototype.
	(lookup_attribute): Change parameters.
	(print_attributes): Prototype.
	* varasm.c (decl_tls_model): General changes.
	* config/sol2.h: General changes only.
	* config/sol2.c: General changes only.
	* config/alpha/alpha.c: General changes only.
	* config/arc/arc.c: General changes only.
	* config/arm/arm.c (arm_handle_fndecl_attribute): Replace with generic
	routine.
	(arm_handle_isr_attribute): Greatly simplify.
	(arm_comp_type_attributes): Boolify.  Use merge_attributes_1.
	* config/arm/pe.c: General changes only.
	* config/avr/avr-protos.h (avr_progmem_p): Delete prototype.
	* config/avr/avr.c: General changes only.
	* config/c4x/c4x.c: Remove use of loop.h, and general changes.
	* config/frv/frv.c: General changes only.
	* config/h8300/h8300.c: General changes only.
	* config/i386/i386-protos.h: General changes only.
	* config/i386/i386.c: General changes only.
	* config/i386/netware.c: General changes only.
	* config/i386/sol2.h: General changes only.
	* config/i386/winnt.h: General changes only.
	* config/ia64/ia64.c: General changes only.
	* config/ip2k/ip2k.c (ip2k_handle_progmem_attribute): Use
	merge_attributes_1.
	* config/iq2000/iq2000.c: General changes only.
	* config/m32r/m32r.c: General changes only.
	* config/m68hc11/m68hc11.c: General changes only.
	* config/m68k/m68k.c: General changes only.
	* config/mcore/mcore.c: General changes only.
	* config/ns32k/ns32k.c: General changes only.
	* config/rs6000/rs6000.c (rs6000_set_default_type_attributes): Use
	merge_attributes_1.
	* config/s390/s390.c: General changes only.
	* config/sh/sh-protos.h: General changes only.
	* config/sh/sh.c (sh_handle_renesas_attribute): Delete.
	* config/sh/symbian.c: General changes only.
	* config/sparc/sol2.h: General changes only.
	* config/sparc/sparc.c: General changes only.
	* config/stormy16/stormy16.c: General changes only.
	* config/v850/v850.c (v850_set_data_area_1): New function.
	(v850_set_data_area): Call v850_set_data_area_1,
	then call merge_attributes_1.
	(v850_add_attributes): Call v850_set_data_area_1.

Index: gcc/ada/ChangeLog
2004-09-30  Geoffrey Keating  <geoffk@apple.com>

	* gigi.h (builtin_function): Update parameters.
	* utils.c (builtin_function): Update parameters.

Index: gcc/cp/ChangeLog
2004-09-30  Geoffrey Keating  <geoffk@apple.com>

	General changes that apply to every file listed:
	Update parameters and return value of attribute handlers.  Replace
	'tree' with 'attribute_list' in many places.  Replace
	'lookup_attribute' with 'has_attribute_p' or 'get_attribute'.
	Replace NULL_TREE with NULL when referring to an attribute list.
	Use 'merge_attributes' instead of 'chainon'.

  	* call.c (build_java_interface_fn_ref): General changes.
	* class.c: General changes only.
	* cp-tree.h: General changes only.
	* decl.c: General changes only.
	* decl.h: General changes only.
	* decl2.c: General changes only.
	* method.c: General changes only.
	* name-lookup.c: General changes only.
	* name-lookup.h: General changes only.
	* optimize.c: General changes only.
	* parser.c (cp_parser_member_declaration): Delete first_attribute.
	(struct attribute_builder_data): New.
	(cp_parser_attributes_opt): Rewrite.
	(cp_parser_attribute_list): Rewrite.
	* pt.c: General changes only.
	* tree.c: General changes only.
	* typeck.c: General changes only.

Index: gcc/java/ChangeLog
2004-09-30  Geoffrey Keating  <geoffk@apple.com>

	* decl.c (builtin_function): Use attribute_list instead of tree.
	(java_init_decl_processing): Use NULL for attributes not NULL_TREE.
	* java-tree.h (builtin_function): Use attribute_list instead of tree.
	* jcf-reader.c: Rename get_attribute to jcf_get_attribute.

Index: gcc/objc/ChangeLog
2004-09-30  Geoffrey Keating  <geoffk@apple.com>

	* objc-act.c: Replace 'tree' with 'attribute_list' where appropriate.
	Use NULL not NULL_TREE for attributes.
	(build_objc_exception_stuff): Use merge_attributes_1 to build
	attribute lists.

Index: gcc/treelang/ChangeLog
2004-09-30  Geoffrey Keating  <geoffk@apple.com>

	* treetree.c (builtin_function): Replace 'tree' with 'attribute_list'
	for last parameter.  Use NULL not NULL_TREE for attributes.

Index: gcc/attribs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/attribs.c,v
retrieving revision 1.34
diff -u -p -u -p -r1.34 attribs.c
--- gcc/attribs.c	15 Sep 2004 20:47:35 -0000	1.34
+++ gcc/attribs.c	1 Oct 2004 00:57:13 -0000
@@ -124,34 +124,45 @@ init_attributes (void)
   attributes_initialized = true;
 }
 
-/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
-   which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
-   it should be modified in place; if a TYPE, a copy should be created
-   unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
-   information, in the form of a bitwise OR of flags in enum attribute_flags
-   from tree.h.  Depending on these flags, some attributes may be
-   returned to be applied at a later stage (for example, to apply
-   a decl attribute to the declaration rather than to its type).  */
-
-tree
-decl_attributes (tree *node, tree attributes, int flags)
+/* When adding an attribute, there are a bunch of possibilities for what
+   might need to be done with it.  */
+enum attribute_disposition {
+  /* It might be ignored, typically after printing an error message.  */
+  IGNORE,
+  /* It might need to be applied to a later stage, for example if we're
+     given a type and the attribute applies to declarations.  */
+  DEFER,
+  /* It might be added to this type or decl.  */
+  ADD,
+  /* It might need to be added to the type of this decl, by creating
+     a new type that includes this attribute and making it the type of
+     this decl.  */
+  ADD_TYPE,
+  /* It might need to be a function type, not a pointer-to-function type.
+     This will involve creating a new function type and a new type to
+     point to it.  */
+  ADD_FN_TYPE,
+  NUM_DISPOSITIONS
+};
+
+/* Fill in DISP with the disposition of each attribute listed in
+   ATTRIBUTES when adding them to NODE.  FLAGS is a bitwise OR of
+   flags in enum attribute_flags.  Some attributes might be processed
+   here, modifying 'node'.  */
+
+static void
+determine_dispositions (tree *node, attribute_count num_attributes,
+			const struct one_attribute * attributes, int flags,
+			char * disp)
 {
-  tree a;
-  tree returned_attrs = NULL_TREE;
-
-  if (!attributes_initialized)
-    init_attributes ();
-
-  targetm.insert_attributes (*node, &attributes);
-
-  for (a = attributes; a; a = TREE_CHAIN (a))
+  attribute_count ac;
+  
+  for (ac = 0; ac < num_attributes; ac++)
     {
-      tree name = TREE_PURPOSE (a);
-      tree args = TREE_VALUE (a);
+      tree name = attributes[ac].name;
+      tree args = attributes[ac].value;
       tree *anode = node;
       const struct attribute_spec *spec = NULL;
-      bool no_add_attrs = 0;
-      tree fn_ptr_tmp = NULL_TREE;
       size_t i;
 
       for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
@@ -170,11 +181,13 @@ decl_attributes (tree *node, tree attrib
 	    break;
 	}
 
+      disp[ac] = ADD;
+
       if (spec == NULL)
 	{
 	  warning ("%qs attribute directive ignored",
 		   IDENTIFIER_POINTER (name));
-	  continue;
+	  disp[ac] = IGNORE;
 	}
       else if (list_length (args) < spec->min_length
 	       || (spec->max_length >= 0
@@ -182,156 +195,199 @@ decl_attributes (tree *node, tree attrib
 	{
 	  error ("wrong number of arguments specified for %qs attribute",
 		 IDENTIFIER_POINTER (name));
-	  continue;
+	  disp[ac] = IGNORE;
 	}
-
-      if (spec->decl_required && !DECL_P (*anode))
+      else if (spec->decl_required && !DECL_P (*anode))
 	{
 	  if (flags & ((int) ATTR_FLAG_DECL_NEXT
 		       | (int) ATTR_FLAG_FUNCTION_NEXT
 		       | (int) ATTR_FLAG_ARRAY_NEXT))
-	    {
-	      /* Pass on this attribute to be tried again.  */
-	      returned_attrs = tree_cons (name, args, returned_attrs);
-	      continue;
-	    }
+	    disp[ac] = DEFER;
 	  else
 	    {
 	      warning ("%qs attribute does not apply to types",
 		       IDENTIFIER_POINTER (name));
-	      continue;
+	      disp[ac] = IGNORE;
 	    }
 	}
 
       /* If we require a type, but were passed a decl, set up to make a
-	 new type and update the one in the decl.  ATTR_FLAG_TYPE_IN_PLACE
-	 would have applied if we'd been passed a type, but we cannot modify
-	 the decl's type in place here.  */
-      if (spec->type_required && DECL_P (*anode))
+	 new type and update the one in the decl.  If a function type
+         is required, find one.  */
+      else if (spec->type_required)
 	{
-	  anode = &TREE_TYPE (*anode);
-	  flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
-	}
-
-      if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
-	  && TREE_CODE (*anode) != METHOD_TYPE)
-	{
-	  if (TREE_CODE (*anode) == POINTER_TYPE
-	      && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
-		  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
-	    {
-	      /* OK, this is a bit convoluted.  We can't just make a copy
-		 of the pointer type and modify its TREE_TYPE, because if
-		 we change the attributes of the target type the pointer
-		 type needs to have a different TYPE_MAIN_VARIANT.  So we
-		 pull out the target type now, frob it as appropriate, and
-		 rebuild the pointer type later.
-
-	         This would all be simpler if attributes were part of the
-	         declarator, grumble grumble.  */
-	      fn_ptr_tmp = TREE_TYPE (*anode);
-	      anode = &fn_ptr_tmp;
-	      flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
-	    }
-	  else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+	  if (DECL_P (*anode))
 	    {
-	      /* Pass on this attribute to be tried again.  */
-	      returned_attrs = tree_cons (name, args, returned_attrs);
-	      continue;
+	      anode = &TREE_TYPE (*anode);
+	      disp[ac] = ADD_TYPE;
 	    }
 
-	  if (TREE_CODE (*anode) != FUNCTION_TYPE
+	  if (spec->function_type_required 
+	      && TREE_CODE (*anode) != FUNCTION_TYPE
 	      && TREE_CODE (*anode) != METHOD_TYPE)
 	    {
-	      warning ("%qs attribute only applies to function types",
-		       IDENTIFIER_POINTER (name));
-	      continue;
+	      if (TREE_CODE (*anode) == POINTER_TYPE
+		  && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
+		      || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
+		{
+		  anode = &TREE_TYPE (*anode);
+		  disp[ac]++;
+		}
+	      else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+		disp[ac] = DEFER;
+	      else if (TREE_CODE (*anode) != FUNCTION_TYPE
+		       && TREE_CODE (*anode) != METHOD_TYPE)
+		{
+		  warning ("%qs attribute only applies to function types",
+			   IDENTIFIER_POINTER (name));
+		  disp[ac] = IGNORE;
+		}
 	    }
 	}
-
-      if (spec->handler != NULL)
-	returned_attrs = chainon ((*spec->handler) (anode, name, args,
-						    flags, &no_add_attrs),
-				  returned_attrs);
-
-      /* Layout the decl in case anything changed.  */
-      if (spec->type_required && DECL_P (*node)
-	  && (TREE_CODE (*node) == VAR_DECL
-	      || TREE_CODE (*node) == PARM_DECL
-	      || TREE_CODE (*node) == RESULT_DECL))
+      
+      if (disp[ac] != IGNORE && disp[ac] != DEFER && spec->handler)
 	{
-	  /* Force a recalculation of mode and size.  */
-	  DECL_MODE (*node) = VOIDmode;
-	  DECL_SIZE (*node) = 0;
-
-	  layout_decl (*node, 0);
+	  bool ignore = false;
+	  bool defer = false;
+	  (*spec->handler) (anode, name, args, flags, &ignore, &defer);
+	  if (ignore)
+	    disp[ac] = IGNORE;
+	  else if (defer)
+	    disp[ac] = DEFER;
 	}
+    }
+}
 
-      if (!no_add_attrs)
-	{
-	  tree old_attrs;
-	  tree a;
+/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
+   which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
+   it should be modified in place; if a TYPE, a copy should be created
+   unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
+   information, in the form of a bitwise OR of flags in enum attribute_flags
+   from tree.h.  Depending on these flags, some attributes may be
+   returned to be applied at a later stage (for example, to apply
+   a decl attribute to the declaration rather than to its type).  */
 
-	  if (DECL_P (*anode))
-	    old_attrs = DECL_ATTRIBUTES (*anode);
-	  else
-	    old_attrs = TYPE_ATTRIBUTES (*anode);
+attribute_list
+decl_attributes (tree *node, attribute_list attributes, int flags)
+{
+  char * disp;
+  attribute_count num_machine_attribs;
+  const struct one_attribute * machine_attribs = NULL;
+  attribute_count num_attributes;
+  attribute_count i;
+  attribute_count total_attributes;
+  struct one_attribute * all_attribs;
+  attribute_count num_per_disp[NUM_DISPOSITIONS];
+  tree old_type;
 
-	  for (a = lookup_attribute (spec->name, old_attrs);
-	       a != NULL_TREE;
-	       a = lookup_attribute (spec->name, TREE_CHAIN (a)))
-	    {
-	      if (simple_cst_equal (TREE_VALUE (a), args) == 1)
-		break;
-	    }
+  if (!attributes_initialized)
+    init_attributes ();
 
-	  if (a == NULL_TREE)
-	    {
-	      /* This attribute isn't already in the list.  */
-	      if (DECL_P (*anode))
-		DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
-	      else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
-		{
-		  TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
-		  /* If this is the main variant, also push the attributes
-		     out to the other variants.  */
-		  if (*anode == TYPE_MAIN_VARIANT (*anode))
-		    {
-		      tree variant;
-		      for (variant = *anode; variant;
-			   variant = TYPE_NEXT_VARIANT (variant))
-			{
-			  if (TYPE_ATTRIBUTES (variant) == old_attrs)
-			    TYPE_ATTRIBUTES (variant)
-			      = TYPE_ATTRIBUTES (*anode);
-			  else if (!lookup_attribute
-				   (spec->name, TYPE_ATTRIBUTES (variant)))
-			    TYPE_ATTRIBUTES (variant) = tree_cons
-			      (name, args, TYPE_ATTRIBUTES (variant));
-			}
-		    }
-		}
-	      else
-		*anode = build_type_attribute_variant (*anode,
-						       tree_cons (name, args,
-								  old_attrs));
-	    }
-	}
+  num_machine_attribs = targetm.add_attributes (*node, attributes,
+						&machine_attribs);
+
+  num_attributes = ATTRIBUTE_COUNT (attributes);
+  total_attributes = num_machine_attribs + num_attributes;
 
-      if (fn_ptr_tmp)
+  /* Check for overflow.  */
+  if (total_attributes < num_attributes)
+    {
+      error ("too many attributes");
+      return NULL;
+    }
+
+  /* Early exit.  */
+  if (total_attributes == 0)
+    return NULL;
+
+  /* Put all the attributes into one list for convenience, so that
+     it's easier to add them all to a type or decl at once.  */
+  disp = alloca (sizeof (*disp) * total_attributes);
+  all_attribs = alloca (sizeof (*all_attribs) * total_attributes);
+  if (num_machine_attribs != 0)
+    memcpy (all_attribs, machine_attribs,
+	    sizeof (*all_attribs) * num_machine_attribs);
+  if (attributes)
+    memcpy (all_attribs + num_machine_attribs, attributes->attribs,
+	    sizeof (*all_attribs) * num_attributes);
+
+  /* Save away the old type, so that we know whether or not we need to
+     re-layout a DECL.  */
+  old_type = TREE_TYPE (*node);
+  
+  determine_dispositions (node, total_attributes, all_attribs, flags, disp);
+  
+  /* Count the dispositions.  */
+  memset (num_per_disp, 0, sizeof (num_per_disp));
+  for (i = 0; i < total_attributes; i++)
+    num_per_disp[(int) disp[i]]++;
+  
+  /* Process the possible destinations from the simplest type outwards.  */
+  if (num_per_disp[ADD_FN_TYPE] != 0)
+    {
+      tree old_type, new_type;
+      attribute_list new_attribs;
+      
+      old_type = TREE_TYPE (TREE_TYPE (*node));
+      new_attribs = merge_attributes_1 (TYPE_ATTRIBUTES (old_type),
+					total_attributes, all_attribs,
+					disp, ADD_FN_TYPE);
+      new_type = build_type_attribute_variant (old_type, new_attribs);
+      gcc_assert (DECL_P (*node));
+      TREE_TYPE (*node) = build_pointer_type (new_type);
+    }
+  if (num_per_disp[ADD_TYPE] != 0)
+    {
+      tree old_type, new_type;
+      attribute_list new_attribs;
+      
+      old_type = TREE_TYPE (*node);
+      new_attribs = merge_attributes_1 (TYPE_ATTRIBUTES (old_type),
+					total_attributes, all_attribs,
+					disp, ADD_TYPE);
+      new_type = build_type_attribute_variant (old_type, new_attribs);
+
+      if (DECL_P (*node))
+	TREE_TYPE (*node) = new_type;
+      else
 	{
-	  /* Rebuild the function pointer type and put it in the
-	     appropriate place.  */
-	  fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
-	  if (DECL_P (*node))
-	    TREE_TYPE (*node) = fn_ptr_tmp;
-	  else
-	    {
-	      gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
-	      *node = fn_ptr_tmp;
-	    }
+	  gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
+	  *node = build_pointer_type (new_type);
 	}
     }
-
-  return returned_attrs;
+  /* If the above changed the type, layout the decl again.  */
+  if (DECL_P (*node) && TREE_TYPE (*node) != old_type
+      && TREE_CODE (*node) != LABEL_DECL
+      && TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      /* Force a recalculation of mode and size.  */
+      DECL_MODE (*node) = VOIDmode;
+      DECL_SIZE (*node) = 0;
+      
+      layout_decl (*node, 0);
+    }
+  if (num_per_disp[ADD] != 0)
+    {
+      attribute_list old_attribs, new_attribs;
+      
+      if (DECL_P (*node))
+	old_attribs = DECL_ATTRIBUTES (*node);
+      else
+	old_attribs = TYPE_ATTRIBUTES (*node);
+      
+      new_attribs = merge_attributes_1 (old_attribs,
+					total_attributes, all_attribs,
+					disp, ADD);
+      if (DECL_P (*node))
+	DECL_ATTRIBUTES (*node) = new_attribs;
+      else if (flags & ATTR_FLAG_TYPE_IN_PLACE)
+	TYPE_ATTRIBUTES (*node) = new_attribs;
+      else
+	*node = build_type_attribute_variant (*node, new_attribs);
+    }
+  if (num_per_disp[DEFER] != 0)
+    return merge_attributes_1 (NULL, total_attributes, all_attribs,
+			       disp, DEFER);
+  else
+    return NULL;
 }
Index: gcc/builtin-attrs.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtin-attrs.def,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 builtin-attrs.def
--- gcc/builtin-attrs.def	29 Sep 2004 09:06:49 -0000	1.15
+++ gcc/builtin-attrs.def	1 Oct 2004 00:57:13 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
    Contributed by Joseph Myers <jsm28@cam.ac.uk>.
 
 This file is part of GCC.
@@ -43,13 +43,13 @@ Software Foundation, 59 Temple Place - S
      Constructs a TREE_LIST with given PURPOSE, VALUE and CHAIN (given
      as previous ENUM names).  */
 
-DEF_ATTR_NULL_TREE (ATTR_NULL)
+DEF_ATTR_NULL_TREE (ATTR_NULL_TREE)
 
 /* Construct a tree for a given integer and a list containing it.  */
 #define DEF_ATTR_FOR_INT(VALUE)					\
   DEF_ATTR_INT (ATTR_##VALUE, VALUE)			\
-  DEF_ATTR_TREE_LIST (ATTR_LIST_##VALUE, ATTR_NULL,	\
-		      ATTR_##VALUE, ATTR_NULL)
+  DEF_ATTR_TREE_LIST (ATTR_LIST_##VALUE, ATTR_NULL_TREE,	\
+		      ATTR_##VALUE, ATTR_NULL_TREE)
 DEF_ATTR_FOR_INT (0)
 DEF_ATTR_FOR_INT (1)
 DEF_ATTR_FOR_INT (2)
@@ -59,7 +59,7 @@ DEF_ATTR_FOR_INT (4)
 
 /* Construct a tree for a list of two integers.  */
 #define DEF_LIST_INT_INT(VALUE1, VALUE2)				 \
-  DEF_ATTR_TREE_LIST (ATTR_LIST_##VALUE1##_##VALUE2, ATTR_NULL,		 \
+  DEF_ATTR_TREE_LIST (ATTR_LIST_##VALUE1##_##VALUE2, ATTR_NULL_TREE,		 \
 		      ATTR_##VALUE1, ATTR_LIST_##VALUE2)
 DEF_LIST_INT_INT (1,0)
 DEF_LIST_INT_INT (1,2)
@@ -78,69 +78,66 @@ DEF_ATTR_IDENT (ATTR_NONNULL, "nonnull")
 DEF_ATTR_IDENT (ATTR_NORETURN, "noreturn")
 DEF_ATTR_IDENT (ATTR_NOTHROW, "nothrow")
 DEF_ATTR_IDENT (ATTR_PRINTF, "printf")
-DEF_ATTR_IDENT (ATTR_ASM_FPRINTF, "asm_fprintf")
-DEF_ATTR_IDENT (ATTR_GCC_DIAG, "gcc_diag")
-DEF_ATTR_IDENT (ATTR_GCC_CDIAG, "gcc_cdiag")
-DEF_ATTR_IDENT (ATTR_GCC_CXXDIAG, "gcc_cxxdiag")
 DEF_ATTR_IDENT (ATTR_PURE, "pure")
 DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
 DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel")
 DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
 DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
 
-DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL, ATTR_NULL)
+DEF_ATTR_NULL (ATTR_NULL)
 
-DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST,	\
-			ATTR_NULL, ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LIST, ATTR_PURE,		\
-			ATTR_NULL, ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_NORETURN_NOTHROW_LIST, ATTR_NORETURN,	\
-			ATTR_NULL, ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_LIST, ATTR_MALLOC,	\
-			ATTR_NULL, ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LIST, ATTR_SENTINEL,	\
-			ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL_TREE, ATTR_NULL)
 
-DEF_ATTR_TREE_LIST (ATTR_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, ATTR_NULL)
-DEF_ATTR_TREE_LIST (ATTR_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, ATTR_NULL)
+DEF_ATTR (ATTR_CONST_NOTHROW_LIST, ATTR_CONST,	\
+			ATTR_NULL_TREE, ATTR_NOTHROW_LIST)
+DEF_ATTR (ATTR_PURE_NOTHROW_LIST, ATTR_PURE,		\
+			ATTR_NULL_TREE, ATTR_NOTHROW_LIST)
+DEF_ATTR (ATTR_NORETURN_NOTHROW_LIST, ATTR_NORETURN,	\
+			ATTR_NULL_TREE, ATTR_NOTHROW_LIST)
+DEF_ATTR (ATTR_MALLOC_NOTHROW_LIST, ATTR_MALLOC,	\
+			ATTR_NULL_TREE, ATTR_NOTHROW_LIST)
+DEF_ATTR (ATTR_SENTINEL_NOTHROW_LIST, ATTR_SENTINEL,	\
+			ATTR_NULL_TREE, ATTR_NOTHROW_LIST)
+
+DEF_ATTR (ATTR_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, ATTR_NULL)
+DEF_ATTR (ATTR_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, ATTR_NULL)
 /* Functions whose first and second parameters are nonnull pointers.  */
-DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_2, ATTR_NONNULL, ATTR_LIST_2, \
-			ATTR_NONNULL_1)
+DEF_ATTR (ATTR_NONNULL_1_2, ATTR_NONNULL, ATTR_LIST_2, ATTR_NONNULL_1)
 /* Functions whose first and fourth parameters are nonnull pointers.  */
-DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_4, ATTR_NONNULL, ATTR_LIST_4, \
-			ATTR_NONNULL_1)
-DEF_ATTR_TREE_LIST (ATTR_NOTHROW_SENTINEL_1, ATTR_SENTINEL, ATTR_LIST_1, \
+DEF_ATTR (ATTR_NONNULL_1_4, ATTR_NONNULL, ATTR_LIST_4, ATTR_NONNULL_1)
+
+DEF_ATTR (ATTR_NOTHROW_SENTINEL_1, ATTR_SENTINEL, ATTR_LIST_1, \
 			ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, \
+DEF_ATTR (ATTR_NOTHROW_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, \
 			ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, \
+DEF_ATTR (ATTR_NOTHROW_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, \
 			ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, \
+DEF_ATTR (ATTR_NOTHROW_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, \
 			ATTR_NOTHROW_LIST)
 /* Nothrow functions whose first and second parameters are nonnull pointers.  */
-DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_2, ATTR_NONNULL, ATTR_LIST_2, \
+DEF_ATTR (ATTR_NOTHROW_NONNULL_1_2, ATTR_NONNULL, ATTR_LIST_2, \
 			ATTR_NOTHROW_NONNULL_1)
 /* Nothrow functions whose first and fourth parameters are nonnull pointers.  */
-DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_4, ATTR_NONNULL, ATTR_LIST_4, \
+DEF_ATTR (ATTR_NOTHROW_NONNULL_1_4, ATTR_NONNULL, ATTR_LIST_4, \
 			ATTR_NOTHROW_NONNULL_1)
 /* Nothrow const functions whose first parameter is a nonnull pointer.  */
-DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL_1, ATTR_CONST, ATTR_NULL, \
+DEF_ATTR (ATTR_CONST_NOTHROW_NONNULL_1, ATTR_CONST, ATTR_NULL_TREE, \
 			ATTR_NOTHROW_NONNULL_1)
 /* Nothrow pure functions whose first parameter is a nonnull pointer.  */
-DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_1, ATTR_PURE, ATTR_NULL, \
+DEF_ATTR (ATTR_PURE_NOTHROW_NONNULL_1, ATTR_PURE, ATTR_NULL_TREE, \
 			ATTR_NOTHROW_NONNULL_1)
 /* Nothrow pure functions whose first and second parameters are nonnull pointers.  */
-DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_1_2, ATTR_PURE, ATTR_NULL, \
+DEF_ATTR (ATTR_PURE_NOTHROW_NONNULL_1_2, ATTR_PURE, ATTR_NULL_TREE, \
 			ATTR_NOTHROW_NONNULL_1_2)
 /* Nothrow malloc functions whose first parameter is a nonnull pointer.  */
-DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_NONNULL_1, ATTR_MALLOC, ATTR_NULL, \
+DEF_ATTR (ATTR_MALLOC_NOTHROW_NONNULL_1, ATTR_MALLOC, ATTR_NULL_TREE, \
 			ATTR_NOTHROW_NONNULL_1)
 
 /* Construct a tree for a format attribute.  */
 #define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES)				 \
-  DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL,		 \
+  DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL_TREE,		 \
 		      ATTR_##TYPE, ATTR_LIST_##VALUES)			 \
-  DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_##VALUES, ATTR_FORMAT,	 \
+  DEF_ATTR (ATTR_FORMAT_##TYPE##_##VALUES, ATTR_FORMAT,	 \
 		      ATTR_##TYPE##_##VALUES, ATTR_NOTHROW_NONNULL_##FA)
 DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_0)
 DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_2)
@@ -158,7 +155,7 @@ DEF_FORMAT_ATTRIBUTE(STRFMON,3,3_4)
 
 /* Construct a tree for a format_arg attribute.  */
 #define DEF_FORMAT_ARG_ATTRIBUTE(FA)					\
-  DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG,		\
+  DEF_ATTR (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG,		\
 		      ATTR_LIST_##FA, ATTR_NOTHROW_NONNULL_##FA)
 DEF_FORMAT_ARG_ATTRIBUTE(1)
 DEF_FORMAT_ARG_ATTRIBUTE(2)
Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.575
diff -u -p -u -p -r1.575 c-common.c
--- gcc/c-common.c	21 Sep 2004 02:22:35 -0000	1.575
+++ gcc/c-common.c	1 Oct 2004 00:57:14 -0000
@@ -519,47 +519,53 @@ static int constant_fits_type_p (tree, t
 static tree check_case_value (tree);
 static bool check_case_bounds (tree, tree, tree *, tree *);
 
-static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
-static tree handle_common_attribute (tree *, tree, tree, int, bool *);
-static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
-static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
-static tree handle_always_inline_attribute (tree *, tree, tree, int,
-					    bool *);
-static tree handle_used_attribute (tree *, tree, tree, int, bool *);
-static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
-static tree handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree handle_transparent_union_attribute (tree *, tree, tree,
-						int, bool *);
-static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
-static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
-static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
-static tree handle_section_attribute (tree *, tree, tree, int, bool *);
-static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
-static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
-static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
-static tree handle_visibility_attribute (tree *, tree, tree, int,
-					 bool *);
-static tree handle_tls_model_attribute (tree *, tree, tree, int,
-					bool *);
-static tree handle_no_instrument_function_attribute (tree *, tree,
-						     tree, int, bool *);
-static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
-static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
-					     bool *);
-static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_deprecated_attribute (tree *, tree, tree, int,
-					 bool *);
-static tree handle_vector_size_attribute (tree *, tree, tree, int,
+static void handle_packed_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_nocommon_attribute (tree *, tree, tree, int, bool *, 
+				       bool *);
+static void handle_common_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_noreturn_attribute (tree *, tree, tree, int, bool *, 
+				       bool *);
+static void handle_noinline_attribute (tree *, tree, tree, int, bool *, 
+				       bool *);
+static void handle_always_inline_attribute (tree *, tree, tree, int,
+					    bool *, bool *);
+static void handle_used_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_unused_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_const_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_transparent_union_attribute (tree *, tree, tree,
+						int, bool *, bool *);
+static void handle_constructor_attribute (tree *, tree, tree, int, bool *,
 					  bool *);
-static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
-static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
-static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
-						 bool *);
-static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+static void handle_destructor_attribute (tree *, tree, tree, int, bool *,
+					 bool *);
+static void handle_mode_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_section_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_aligned_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_weak_attribute (tree *, tree, tree, int, bool *, bool *) ;
+static void handle_alias_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_visibility_attribute (tree *, tree, tree, int,
+					 bool *, bool *);
+static void handle_tls_model_attribute (tree *, tree, tree, int,
+					bool *, bool *);
+static void handle_no_instrument_function_attribute (tree *, tree, tree, int,
+						     bool *, bool *);
+static void handle_malloc_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_no_limit_stack_attribute (tree *, tree, tree, int,
+					     bool *, bool *);
+static void handle_pure_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_deprecated_attribute (tree *, tree, tree, int,
+					 bool *, bool *);
+static void handle_vector_size_attribute (tree *, tree, tree, int,
+					  bool *, bool *);
+static void handle_nonnull_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_nothrow_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_cleanup_attribute (tree *, tree, tree, int, bool *, bool *);
+static void handle_warn_unused_result_attribute (tree *, tree, tree, int,
+						 bool *, bool *);
+static void handle_sentinel_attribute (tree *, tree, tree, int, bool *, 
+				       bool *);
 
-static void check_function_nonnull (tree, tree);
+static void check_function_nonnull (attribute_list, tree);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
 static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
 static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
@@ -2477,7 +2483,7 @@ static tree builtin_function_2 (const ch
 				enum built_in_function function_code,
 				enum built_in_class cl, int library_name_p,
 				bool nonansi_p,
-				tree attrs);
+				attribute_list attrs);
 
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */
@@ -2627,7 +2633,7 @@ c_common_get_alias_set (tree t)
     return 0;
 
   /* If it has the may_alias attribute, it can alias anything.  */
-  if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t)))
+  if (has_attribute_p ("may_alias", TYPE_ATTRIBUTES (t)))
     return 0;
 
   /* The C standard specifically allows aliasing between signed and
@@ -2847,19 +2853,23 @@ c_alignof_expr (tree expr)
 
 enum built_in_attribute
 {
-#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
-#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
-#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
-#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+#define DEF_ATTR_NULL_TREE(NAME) /* nothing */
+#define DEF_ATTR_INT(NAME, VALUE) /* nothing */
+#define DEF_ATTR_IDENT(NAME, STRING) /* nothing */
+#define DEF_ATTR_TREE_LIST(NAME, PURPOSE, VALUE, CHAIN) /* nothing */
+#define DEF_ATTR_NULL(NAME) NAME,
+#define DEF_ATTR(NAME, IDENT, VALUE, CHAIN) NAME,
 #include "builtin-attrs.def"
 #undef DEF_ATTR_NULL_TREE
 #undef DEF_ATTR_INT
 #undef DEF_ATTR_IDENT
 #undef DEF_ATTR_TREE_LIST
+#undef DEF_ATTR_NULL
+#undef DEF_ATTR
   ATTR_LAST
 };
 
-static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
+static GTY(()) attribute_list built_in_attributes[(int) ATTR_LAST];
 
 static void c_init_attributes (void);
 
@@ -3302,7 +3312,7 @@ builtin_function_2 (const char *builtin_
 		    tree builtin_type, tree type,
 		    enum built_in_function function_code,
 		    enum built_in_class cl, int library_name_p,
-		    bool nonansi_p, tree attrs)
+		    bool nonansi_p, attribute_list attrs)
 {
   tree bdecl = NULL_TREE;
   tree decl = NULL_TREE;
@@ -3907,22 +3917,43 @@ static void
 c_init_attributes (void)
 {
   /* Fill in the built_in_attributes array.  */
-#define DEF_ATTR_NULL_TREE(ENUM)				\
-  built_in_attributes[(int) ENUM] = NULL_TREE;
-#define DEF_ATTR_INT(ENUM, VALUE)				\
-  built_in_attributes[(int) ENUM] = build_int_cst (NULL_TREE, VALUE);
-#define DEF_ATTR_IDENT(ENUM, STRING)				\
-  built_in_attributes[(int) ENUM] = get_identifier (STRING);
-#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)	\
-  built_in_attributes[(int) ENUM]			\
-    = tree_cons (built_in_attributes[(int) PURPOSE],	\
-		 built_in_attributes[(int) VALUE],	\
-		 built_in_attributes[(int) CHAIN]);
+  struct one_attribute at;
+#define DEF_ATTR_NULL(NAME) /* nothing */
+#define DEF_ATTR(NAME, IDENT, VALUE, CHAIN) /* nothing */
+#define DEF_ATTR_NULL_TREE(NAME)				\
+  const tree NAME = NULL_TREE;
+#define DEF_ATTR_INT(NAME, VALUE)				\
+  const tree NAME = build_int_cst (NULL_TREE, VALUE);
+#define DEF_ATTR_IDENT(NAME, STRING)				\
+  const tree NAME = get_identifier (STRING);
+#define DEF_ATTR_TREE_LIST(NAME, PURPOSE, VALUE, CHAIN)		\
+  const tree NAME = tree_cons (PURPOSE, VALUE, CHAIN);
 #include "builtin-attrs.def"
+#undef DEF_ATTR_NULL
 #undef DEF_ATTR_NULL_TREE
 #undef DEF_ATTR_INT
 #undef DEF_ATTR_IDENT
 #undef DEF_ATTR_TREE_LIST
+#undef DEF_ATTR
+
+#define DEF_ATTR_NULL(NAME) 			\
+  built_in_attributes[NAME] = NULL;
+#define DEF_ATTR_NULL_TREE(NAME)  /* nothing */
+#define DEF_ATTR_INT(NAME, VALUE) /* nothing */
+#define DEF_ATTR_IDENT(NAME, STRING) /* nothing */
+#define DEF_ATTR_TREE_LIST(NAME, PURPOSE, VALUE, CHAIN) /* nothing */
+#define DEF_ATTR(NAME, IDENT, VALUE, CHAIN)				      \
+  at.name = IDENT;							      \
+  at.value = VALUE;							      \
+  built_in_attributes[NAME] = merge_attributes_1 (built_in_attributes[CHAIN], \
+						  1, &at, NULL, 0);
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+#undef DEF_ATTR
 }
 
 /* Attribute handlers common to C front ends.  */
@@ -3930,9 +3961,10 @@ c_init_attributes (void)
 /* Handle a "packed" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			 int flags, bool *no_add_attrs)
+			 int flags, bool *no_add_attrs,
+			 bool * ARG_UNUSED (defer))
 {
   if (TYPE_P (*node))
     {
@@ -3966,17 +3998,16 @@ handle_packed_attribute (tree *node, tre
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "nocommon" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_nocommon_attribute (tree *node, tree name,
 			   tree ARG_UNUSED (args),
-			   int ARG_UNUSED (flags), bool *no_add_attrs)
+			   int ARG_UNUSED (flags), bool *no_add_attrs,
+			   bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == VAR_DECL)
     DECL_COMMON (*node) = 0;
@@ -3985,16 +4016,15 @@ handle_nocommon_attribute (tree *node, t
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "common" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			 int ARG_UNUSED (flags), bool *no_add_attrs)
+			 int ARG_UNUSED (flags), bool *no_add_attrs,
+			   bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == VAR_DECL)
     DECL_COMMON (*node) = 1;
@@ -4003,16 +4033,15 @@ handle_common_attribute (tree *node, tre
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "noreturn" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			   int ARG_UNUSED (flags), bool *no_add_attrs)
+			   int ARG_UNUSED (flags), bool *no_add_attrs,
+			   bool * ARG_UNUSED (defer))
 {
   tree type = TREE_TYPE (*node);
 
@@ -4030,17 +4059,16 @@ handle_noreturn_attribute (tree *node, t
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "noinline" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_noinline_attribute (tree *node, tree name,
 			   tree ARG_UNUSED (args),
-			   int ARG_UNUSED (flags), bool *no_add_attrs)
+			   int ARG_UNUSED (flags), bool *no_add_attrs,
+			   bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     DECL_UNINLINABLE (*node) = 1;
@@ -4049,18 +4077,17 @@ handle_noinline_attribute (tree *node, t
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "always_inline" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_always_inline_attribute (tree *node, tree name,
 				tree ARG_UNUSED (args),
 				int ARG_UNUSED (flags),
-				bool *no_add_attrs)
+				bool *no_add_attrs,
+				bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     {
@@ -4072,16 +4099,15 @@ handle_always_inline_attribute (tree *no
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "used" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
-		       int ARG_UNUSED (flags), bool *no_add_attrs)
+		       int ARG_UNUSED (flags), bool *no_add_attrs,
+		       bool * ARG_UNUSED (defer))
 {
   tree node = *pnode;
 
@@ -4096,16 +4122,15 @@ handle_used_attribute (tree *pnode, tree
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "unused" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			 int flags, bool *no_add_attrs)
+			 int flags, bool *no_add_attrs,
+			 bool * ARG_UNUSED (defer))
 {
   if (DECL_P (*node))
     {
@@ -4129,16 +4154,15 @@ handle_unused_attribute (tree *node, tre
 	*node = build_variant_type_copy (*node);
       TREE_USED (*node) = 1;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "const" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			int ARG_UNUSED (flags), bool *no_add_attrs)
+			int ARG_UNUSED (flags), bool *no_add_attrs,
+			bool * ARG_UNUSED (defer))
 {
   tree type = TREE_TYPE (*node);
 
@@ -4156,17 +4180,16 @@ handle_const_attribute (tree *node, tree
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "transparent_union" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_transparent_union_attribute (tree *node, tree name,
 				    tree ARG_UNUSED (args), int flags,
-				    bool *no_add_attrs)
+				    bool *no_add_attrs,
+				    bool * ARG_UNUSED (defer))
 {
   tree decl = NULL_TREE;
   tree *type = NULL;
@@ -4200,18 +4223,17 @@ handle_transparent_union_attribute (tree
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "constructor" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_constructor_attribute (tree *node, tree name,
 			      tree ARG_UNUSED (args),
 			      int ARG_UNUSED (flags),
-			      bool *no_add_attrs)
+			      bool *no_add_attrs,
+			      bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
   tree type = TREE_TYPE (decl);
@@ -4228,18 +4250,17 @@ handle_constructor_attribute (tree *node
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "destructor" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_destructor_attribute (tree *node, tree name,
 			     tree ARG_UNUSED (args),
 			     int ARG_UNUSED (flags),
-			     bool *no_add_attrs)
+			     bool *no_add_attrs,
+			     bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
   tree type = TREE_TYPE (decl);
@@ -4256,16 +4277,15 @@ handle_destructor_attribute (tree *node,
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "mode" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_mode_attribute (tree *node, tree name, tree args,
-		       int ARG_UNUSED (flags), bool *no_add_attrs)
+		       int ARG_UNUSED (flags), bool *no_add_attrs,
+		       bool * ARG_UNUSED (defer))
 {
   tree type = *node;
 
@@ -4308,7 +4328,7 @@ handle_mode_attribute (tree *node, tree 
       if (mode == VOIDmode)
 	{
 	  error ("unknown machine mode %<%s%>", p);
-	  return NULL_TREE;
+	  return;
 	}
 
       valid_mode = false;
@@ -4339,7 +4359,7 @@ handle_mode_attribute (tree *node, tree 
       if (!valid_mode)
 	{
 	  error ("unable to emulate %<%s%>", p);
-	  return NULL_TREE;
+	  return;
 	}
 
       if (POINTER_TYPE_P (type))
@@ -4349,7 +4369,7 @@ handle_mode_attribute (tree *node, tree 
 	  if (!targetm.valid_pointer_mode (mode))
 	    {
 	      error ("invalid pointer mode %<%s%>", p);
-	      return NULL_TREE;
+	      return;
 	    }
 
           if (TREE_CODE (type) == POINTER_TYPE)
@@ -4364,7 +4384,7 @@ handle_mode_attribute (tree *node, tree 
       if (typefm == NULL_TREE)
 	{
 	  error ("no data type for mode %<%s%>", p);
-	  return NULL_TREE;
+	  return;
 	}
       else if (TREE_CODE (type) == ENUMERAL_TYPE)
 	{
@@ -4375,7 +4395,7 @@ handle_mode_attribute (tree *node, tree 
 	    {
 	      error ("cannot use mode %qs for enumeral types",
 		     GET_MODE_NAME (mode));
-	      return NULL_TREE;
+	      return;
 	    }
 
 	  if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
@@ -4387,16 +4407,15 @@ handle_mode_attribute (tree *node, tree 
 
       /* No need to layout the type here.  The caller should do this.  */
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "section" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
-			  int ARG_UNUSED (flags), bool *no_add_attrs)
+			  int ARG_UNUSED (flags), bool *no_add_attrs,
+			  bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -4441,16 +4460,15 @@ handle_section_attribute (tree *node, tr
       error ("%Jsection attributes are not supported for this target", *node);
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "aligned" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
-			  int flags, bool *no_add_attrs)
+			  int flags, bool *no_add_attrs,
+			  bool * ARG_UNUSED (defer))
 {
   tree decl = NULL_TREE;
   tree *type = NULL;
@@ -4520,30 +4538,28 @@ handle_aligned_attribute (tree *node, tr
       DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
       DECL_USER_ALIGN (decl) = 1;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "weak" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_weak_attribute (tree *node, tree ARG_UNUSED (name),
 		       tree ARG_UNUSED (args),
 		       int ARG_UNUSED (flags),
-		       bool * ARG_UNUSED (no_add_attrs))
+		       bool * ARG_UNUSED (no_add_attrs),
+		       bool * ARG_UNUSED (defer))
 {
   declare_weak (*node);
-
-  return NULL_TREE;
 }
 
 /* Handle an "alias" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_alias_attribute (tree *node, tree name, tree args,
-			int ARG_UNUSED (flags), bool *no_add_attrs)
+			int ARG_UNUSED (flags), bool *no_add_attrs,
+			bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -4568,7 +4584,7 @@ handle_alias_attribute (tree *node, tree
 	{
 	  error ("alias arg not a string");
 	  *no_add_attrs = true;
-	  return NULL_TREE;
+	  return;
 	}
       id = get_identifier (TREE_STRING_POINTER (id));
       /* This counts as a use of the object pointed to.  */
@@ -4587,17 +4603,16 @@ handle_alias_attribute (tree *node, tree
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle an "visibility" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_visibility_attribute (tree *node, tree name, tree args,
 			     int ARG_UNUSED (flags),
-			     bool *no_add_attrs)
+			     bool *no_add_attrs,
+			     bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
   tree id = TREE_VALUE (args);
@@ -4610,19 +4625,19 @@ handle_visibility_attribute (tree *node,
        {
          warning ("%qs attribute ignored on non-class types",
                   IDENTIFIER_POINTER (name));
-         return NULL_TREE;
+         return;
        }
     }
   else if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
     {
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
-      return NULL_TREE;
+      return;
     }
 
   if (TREE_CODE (id) != STRING_CST)
     {
       error ("visibility arg not a string");
-      return NULL_TREE;
+      return;
     }
 
   /*  If this is a type, set the visibility on the type decl.  */
@@ -4630,7 +4645,7 @@ handle_visibility_attribute (tree *node,
     {
       decl = TYPE_NAME (decl);
       if (! decl)
-        return NULL_TREE;
+        return;
     }
 
   if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
@@ -4651,8 +4666,6 @@ handle_visibility_attribute (tree *node,
      overridden from the class visibility.  */
   if (DECL_P (*node))
     *no_add_attrs = false;
-
-  return NULL_TREE;
 }
 
 /* Determine the ELF symbol visibility for DECL, which is either a
@@ -4675,12 +4688,12 @@ c_determine_visibility (tree decl)
      to distinguish the use of an attribute from the use of a "#pragma
      GCC visibility push(...)"; in the latter case we still want other
      considerations to be able to overrule the #pragma.  */
-  if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("visibility", DECL_ATTRIBUTES (decl)))
     return true;
 
   /* Anything that is exported must have default visibility.  */
   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
-      && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+      && has_attribute_p ("dllexport", DECL_ATTRIBUTES (decl)))
     {
       DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
       DECL_VISIBILITY_SPECIFIED (decl) = 1;
@@ -4693,9 +4706,10 @@ c_determine_visibility (tree decl)
 /* Handle an "tls_model" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_tls_model_attribute (tree *node, tree name, tree args,
-			    int ARG_UNUSED (flags), bool *no_add_attrs)
+			    int ARG_UNUSED (flags), bool *no_add_attrs,
+			    bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -4713,7 +4727,7 @@ handle_tls_model_attribute (tree *node, 
 	{
 	  error ("tls_model arg not a string");
 	  *no_add_attrs = true;
-	  return NULL_TREE;
+	  return;
 	}
       if (strcmp (TREE_STRING_POINTER (id), "local-exec")
 	  && strcmp (TREE_STRING_POINTER (id), "initial-exec")
@@ -4722,21 +4736,20 @@ handle_tls_model_attribute (tree *node, 
 	{
 	  error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
 	  *no_add_attrs = true;
-	  return NULL_TREE;
+	  return;
 	}
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "no_instrument_function" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_no_instrument_function_attribute (tree *node, tree name,
 					 tree ARG_UNUSED (args),
 					 int ARG_UNUSED (flags),
-					 bool *no_add_attrs)
+					 bool *no_add_attrs,
+					 bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -4752,16 +4765,15 @@ handle_no_instrument_function_attribute 
     }
   else
     DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
-
-  return NULL_TREE;
 }
 
 /* Handle a "malloc" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			 int ARG_UNUSED (flags), bool *no_add_attrs)
+			 int ARG_UNUSED (flags), bool *no_add_attrs,
+			 bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     DECL_IS_MALLOC (*node) = 1;
@@ -4771,18 +4783,17 @@ handle_malloc_attribute (tree *node, tre
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "no_limit_stack" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_no_limit_stack_attribute (tree *node, tree name,
 				 tree ARG_UNUSED (args),
 				 int ARG_UNUSED (flags),
-				 bool *no_add_attrs)
+				 bool *no_add_attrs,
+				 bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -4798,16 +4809,15 @@ handle_no_limit_stack_attribute (tree *n
     }
   else
     DECL_NO_LIMIT_STACK (decl) = 1;
-
-  return NULL_TREE;
 }
 
 /* Handle a "pure" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-		       int ARG_UNUSED (flags), bool *no_add_attrs)
+		       int ARG_UNUSED (flags), bool *no_add_attrs,
+		       bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     DECL_IS_PURE (*node) = 1;
@@ -4817,17 +4827,16 @@ handle_pure_attribute (tree *node, tree 
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "deprecated" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_deprecated_attribute (tree *node, tree name,
 			     tree ARG_UNUSED (args), int flags,
-			     bool *no_add_attrs)
+			     bool *no_add_attrs,
+			     bool * ARG_UNUSED (defer))
 {
   tree type = NULL_TREE;
   int warn = 0;
@@ -4875,17 +4884,16 @@ handle_deprecated_attribute (tree *node,
 	warning ("%qs attribute ignored",
 		      IDENTIFIER_POINTER (name));
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "vector_size" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_vector_size_attribute (tree *node, tree name, tree args,
 			      int ARG_UNUSED (flags),
-			      bool *no_add_attrs)
+			      bool *no_add_attrs,
+			      bool * ARG_UNUSED (defer))
 {
   unsigned HOST_WIDE_INT vecsize, nunits;
   enum machine_mode orig_mode;
@@ -4902,7 +4910,7 @@ handle_vector_size_attribute (tree *node
   if (! host_integerp (size, 1))
     {
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
-      return NULL_TREE;
+      return;
     }
 
   /* Get the vector size (in bytes).  */
@@ -4932,7 +4940,7 @@ handle_vector_size_attribute (tree *node
     {
       error ("invalid vector type for attribute %qs",
 	     IDENTIFIER_POINTER (name));
-      return NULL_TREE;
+      return;
     }
 
   /* Calculate how many units fit in the vector.  */
@@ -4940,22 +4948,21 @@ handle_vector_size_attribute (tree *node
   if (nunits & (nunits - 1))
     {
       error ("number of components of the vector not a power of two");
-      return NULL_TREE;
+      return;
     }
 
   new_type = build_vector_type (type, nunits);
 
   /* Build back pointers if needed.  */
   *node = reconstruct_complex_type (*node, new_type);
-
-  return NULL_TREE;
 }
 
 /* Handle the "nonnull" attribute.  */
-static tree
+static void
 handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
 			  tree args, int ARG_UNUSED (flags),
-			  bool *no_add_attrs)
+			  bool *no_add_attrs,
+			  bool * ARG_UNUSED (defer))
 {
   tree type = *node;
   unsigned HOST_WIDE_INT attr_arg_num;
@@ -4970,7 +4977,7 @@ handle_nonnull_attribute (tree *node, tr
 	  error ("nonnull attribute without arguments on a non-prototype");
 	  *no_add_attrs = true;
 	}
-      return NULL_TREE;
+      return;
     }
 
   /* Argument list specified.  Verify that each argument number references
@@ -4985,7 +4992,7 @@ handle_nonnull_attribute (tree *node, tr
 	  error ("nonnull argument has invalid operand number (arg %lu)",
 		 (unsigned long) attr_arg_num);
 	  *no_add_attrs = true;
-	  return NULL_TREE;
+	  return;
 	}
 
       argument = TYPE_ARG_TYPES (type);
@@ -5004,7 +5011,7 @@ handle_nonnull_attribute (tree *node, tr
 	      error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
 		     (unsigned long) attr_arg_num, (unsigned long) arg_num);
 	      *no_add_attrs = true;
-	      return NULL_TREE;
+	      return;
 	    }
 
 	  if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
@@ -5012,28 +5019,27 @@ handle_nonnull_attribute (tree *node, tr
 	      error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
 		   (unsigned long) attr_arg_num, (unsigned long) arg_num);
 	      *no_add_attrs = true;
-	      return NULL_TREE;
+	      return;
 	    }
 	}
     }
-
-  return NULL_TREE;
 }
 
 /* Check the argument list of a function call for null in argument slots
    that are marked as requiring a non-null pointer argument.  */
 
 static void
-check_function_nonnull (tree attrs, tree params)
+check_function_nonnull (attribute_list attrs, tree params)
 {
-  tree a, args, param;
+  tree args, param;
   int param_num;
+  attribute_count i;
 
-  for (a = attrs; a; a = TREE_CHAIN (a))
+  for (i = 0; i < attrs->n_attributes; i++)
     {
-      if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
+      if (is_attribute_p ("nonnull", attrs->attribs[i].name))
 	{
-	  args = TREE_VALUE (a);
+	  args = attrs->attribs[i].value;
 
 	  /* Walk the argument list.  If we encounter an argument number we
 	     should check for non-null, do it.  If the attribute has no args,
@@ -5043,11 +5049,11 @@ check_function_nonnull (tree attrs, tree
 	       param_num++, param = TREE_CHAIN (param))
 	    {
 	      if (! param)
-	break;
+		break;
 	      if (! args || nonnull_check_p (args, param_num))
-	check_function_arguments_recurse (check_nonnull_arg, NULL,
-					  TREE_VALUE (param),
-					  param_num);
+		check_function_arguments_recurse (check_nonnull_arg, NULL,
+						  TREE_VALUE (param),
+						  param_num);
 	    }
 	}
     }
@@ -5057,11 +5063,11 @@ check_function_nonnull (tree attrs, tree
    from the end) is a (pointer)0.  */
 
 static void
-check_function_sentinel (tree attrs, tree params)
+check_function_sentinel (attribute_list attrs, tree params)
 {
-  tree attr = lookup_attribute ("sentinel", attrs);
+  attribute_count i = lookup_attribute ("sentinel", attrs, 0);
 
-  if (attr)
+  if (i != attrs->n_attributes)
     {
       if (!params)
 	warning ("missing sentinel in function call");
@@ -5070,9 +5076,9 @@ check_function_sentinel (tree attrs, tre
 	  tree sentinel, end;
 	  unsigned pos = 0;
 	  
-	  if (TREE_VALUE (attr))
+	  if (attrs->attribs[i].value)
 	    {
-	      tree p = TREE_VALUE (TREE_VALUE (attr));
+	      tree p = TREE_VALUE (attrs->attribs[i].value);
 	      STRIP_NOPS (p);
 	      pos = TREE_INT_CST_LOW (p);
 	    }
@@ -5171,9 +5177,10 @@ get_nonnull_operand (tree arg_num_expr, 
 /* Handle a "nothrow" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			  int ARG_UNUSED (flags), bool *no_add_attrs)
+			  int ARG_UNUSED (flags), bool *no_add_attrs,
+			  bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     TREE_NOTHROW (*node) = 1;
@@ -5183,16 +5190,15 @@ handle_nothrow_attribute (tree *node, tr
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "cleanup" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
+static void
 handle_cleanup_attribute (tree *node, tree name, tree args,
-			  int ARG_UNUSED (flags), bool *no_add_attrs)
+			  int ARG_UNUSED (flags), bool *no_add_attrs,
+			  bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
   tree cleanup_id, cleanup_decl;
@@ -5205,7 +5211,7 @@ handle_cleanup_attribute (tree *node, tr
     {
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   /* Verify that the argument is a function in scope.  */
@@ -5216,28 +5222,28 @@ handle_cleanup_attribute (tree *node, tr
     {
       error ("cleanup arg not an identifier");
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
   cleanup_decl = lookup_name (cleanup_id);
   if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
     {
       error ("cleanup arg not a function");
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   /* That the function has proper type is checked with the
      eventual call to build_function_call.  */
-
-  return NULL_TREE;
 }
 
 /* Handle a "warn_unused_result" attribute.  No special handling.  */
 
-static tree
+static void
 handle_warn_unused_result_attribute (tree *node, tree name,
-			       tree ARG_UNUSED (args),
-			       int ARG_UNUSED (flags), bool *no_add_attrs)
+				     tree ARG_UNUSED (args),
+				     int ARG_UNUSED (flags), 
+				     bool *no_add_attrs,
+				     bool * ARG_UNUSED (defer))
 {
   /* Ignore the attribute for functions not returning any value.  */
   if (VOID_TYPE_P (TREE_TYPE (*node)))
@@ -5245,15 +5251,14 @@ handle_warn_unused_result_attribute (tre
       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "sentinel" attribute.  */
 
-static tree
+static void
 handle_sentinel_attribute (tree *node, tree name, tree args,
-			   int ARG_UNUSED (flags), bool *no_add_attrs)
+			   int ARG_UNUSED (flags), bool *no_add_attrs,
+			   bool * ARG_UNUSED (defer))
 {
   tree params = TYPE_ARG_TYPES (*node);
 
@@ -5295,14 +5300,15 @@ handle_sentinel_attribute (tree *node, t
 	    }
 	}
     }
-  
-  return NULL_TREE;
 }
 
 /* Check for valid arguments being passed to a function.  */
 void
-check_function_arguments (tree attrs, tree params)
+check_function_arguments (attribute_list attrs, tree params)
 {
+  if (!attrs)
+    return;
+  
   /* Check for null being passed in a pointer argument that must be
      non-null.  We also need to do this if format checking is enabled.  */
 
@@ -5338,17 +5344,16 @@ check_function_arguments_recurse (void (
   if (TREE_CODE (param) == CALL_EXPR)
     {
       tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0)));
-      tree attrs;
+      attribute_count ac;
       bool found_format_arg = false;
+      attribute_list attrs = TYPE_ATTRIBUTES (type);
 
       /* See if this is a call to a known internationalization function
 	 that modifies a format arg.  Such a function may have multiple
 	 format_arg attributes (for example, ngettext).  */
 
-      for (attrs = TYPE_ATTRIBUTES (type);
-	   attrs;
-	   attrs = TREE_CHAIN (attrs))
-	if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
+      for (ac = 0; ac < ATTRIBUTE_COUNT (attrs); ac++)
+	if (is_attribute_p ("format_arg", attrs->attribs[ac].name))
 	  {
 	    tree inner_args;
 	    tree format_num_expr;
@@ -5357,7 +5362,7 @@ check_function_arguments_recurse (void (
 
 	    /* Extract the argument number, which was previously checked
 	       to be valid.  */
-	    format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
+	    format_num_expr = TREE_VALUE (attrs->attribs[ac].value);
 	    while (TREE_CODE (format_num_expr) == NOP_EXPR
 		   || TREE_CODE (format_num_expr) == CONVERT_EXPR
 		   || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
@@ -5554,7 +5559,7 @@ c_warn_unused_result (tree *top_p)
 	  ftype = TREE_TYPE (ftype);
 	}
 
-      if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
+      if (has_attribute_p ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
 	{
 	  if (fdecl)
 	    warning ("%Hignoring return value of %qD, "
Index: gcc/c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.264
diff -u -p -u -p -r1.264 c-common.h
--- gcc/c-common.h	10 Sep 2004 23:56:18 -0000	1.264
+++ gcc/c-common.h	1 Oct 2004 00:57:14 -0000
@@ -626,16 +626,17 @@ extern void finish_fname_decls (void);
 extern const char *fname_as_string (int);
 extern tree fname_decl (unsigned, tree);
 
-extern void check_function_arguments (tree, tree);
+extern void check_function_arguments (attribute_list, tree);
 extern void check_function_arguments_recurse (void (*)
 					      (void *, tree,
 					       unsigned HOST_WIDE_INT),
 					      void *, tree,
 					      unsigned HOST_WIDE_INT);
-extern void check_function_format (tree, tree);
+extern void check_function_format (attribute_list, tree);
 extern void set_Wformat (int);
-extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
-extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
+extern void handle_format_attribute (tree *, tree, tree, int, bool *, bool *);
+extern void handle_format_arg_attribute (tree *, tree, tree, int, bool *,
+					 bool *);
 extern int c_common_handle_option (size_t code, const char *arg, int value);
 extern bool c_common_missing_argument (const char *opt, size_t code);
 extern tree c_common_type_for_mode (enum machine_mode, int);
Index: gcc/c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.592
diff -u -p -u -p -r1.592 c-decl.c
--- gcc/c-decl.c	30 Sep 2004 00:09:42 -0000	1.592
+++ gcc/c-decl.c	1 Oct 2004 00:57:14 -0000
@@ -1422,14 +1422,14 @@ diagnose_mismatched_decls (tree newdecl,
     {
       /* Diagnose inline __attribute__ ((noinline)) which is silly.  */
       if (DECL_DECLARED_INLINE_P (newdecl)
-	  && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+	  && has_attribute_p ("noinline", DECL_ATTRIBUTES (olddecl)))
 	{
 	  warning ("%Jinline declaration of %qD follows "
 		   "declaration with attribute noinline", newdecl, newdecl);
 	  warned = true;
 	}
       else if (DECL_DECLARED_INLINE_P (olddecl)
-	       && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+	       && has_attribute_p ("noinline", DECL_ATTRIBUTES (newdecl)))
 	{
 	  warning ("%Jdeclaration of %qD with attribute noinline follows "
 		   "inline declaration ", newdecl, newdecl);
@@ -2261,7 +2261,7 @@ implicitly_declare (tree functionid)
   gen_aux_info_record (decl, 0, 1, 0);
 
   /* Possibly apply some default attributes to this implicit declaration.  */
-  decl_attributes (&decl, NULL_TREE, 0);
+  decl_attributes (&decl, NULL, 0);
 
   return decl;
 }
@@ -2642,7 +2642,7 @@ c_make_fname_decl (tree id, int type_dep
 tree
 builtin_function (const char *name, tree type, int function_code,
 		  enum built_in_class cl, const char *library_name,
-		  tree attrs)
+		  attribute_list attrs)
 {
   tree id = get_identifier (name);
   tree decl = build_decl (FUNCTION_DECL, id, type);
@@ -2671,7 +2671,7 @@ builtin_function (const char *name, tree
   if (attrs)
     decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
   else
-    decl_attributes (&decl, NULL_TREE, 0);
+    decl_attributes (&decl, NULL, 0);
 
   return decl;
 }
@@ -2847,7 +2847,7 @@ build_array_declarator (tree expr, struc
     }
   else
     {
-      declarator->u.array.attrs = NULL_TREE;
+      declarator->u.array.attrs = NULL;
       declarator->u.array.quals = 0;
     }
   declarator->u.array.static_p = static_p;
@@ -2878,7 +2878,7 @@ set_array_declarator_inner (struct c_dec
 {
   decl->declarator = inner;
   if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED
-		     || decl->u.array.attrs != NULL_TREE
+		     || decl->u.array.attrs != NULL
 		     || decl->u.array.static_p))
     error ("static or type qualifiers in abstract declarator");
   return decl;
@@ -2890,9 +2890,9 @@ tree
 groktypename (struct c_type_name *type_name)
 {
   tree type;
-  tree attrs = type_name->specs->attrs;
+  attribute_list attrs = type_name->specs->attrs;
 
-  type_name->specs->attrs = NULL_TREE;
+  type_name->specs->attrs = NULL;
 
   type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
 			 false, NULL);
@@ -2920,14 +2920,14 @@ groktypename (struct c_type_name *type_n
 
 tree
 start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
-	    bool initialized, tree attributes)
+	    bool initialized, attribute_list attributes)
 {
   tree decl;
   tree tem;
 
   /* An object declared as __attribute__((deprecated)) suppresses
      warnings of uses of other deprecated items.  */
-  if (lookup_attribute ("deprecated", attributes))
+  if (has_attribute_p ("deprecated", attributes))
     deprecated_state = DEPRECATED_SUPPRESS;
 
   decl = grokdeclarator (declarator, declspecs,
@@ -3062,7 +3062,7 @@ start_decl (struct c_declarator *declara
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
-      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
+      && has_attribute_p ("noinline", DECL_ATTRIBUTES (decl)))
     warning ("%Jinline function %qD given attribute noinline", decl, decl);
 
   /* Add this decl to the current scope.
@@ -3315,7 +3315,7 @@ finish_decl (tree decl, tree init, tree 
     }
 
   /* If this was marked 'used', be sure it will be output.  */
-  if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("used", DECL_ATTRIBUTES (decl)))
     mark_decl_referenced (decl);
 
   if (TREE_CODE (decl) == TYPE_DECL)
@@ -3334,12 +3334,13 @@ finish_decl (tree decl, tree init, tree 
     get_pending_sizes ();
 
   /* Install a cleanup (aka destructor) if one was given.  */
-  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl) 
+      && DECL_ATTRIBUTES (decl))
     {
-      tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
-      if (attr)
+      tree value = get_attribute ("cleanup", DECL_ATTRIBUTES (decl));
+      if (value)
 	{
-	  tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
+	  tree cleanup_id = TREE_VALUE (value);
 	  tree cleanup_decl = lookup_name (cleanup_id);
 	  tree cleanup;
 
@@ -3704,11 +3705,11 @@ grokdeclarator (const struct c_declarato
   int funcdef_flag = 0;
   bool funcdef_syntax = false;
   int size_varies = 0;
-  tree decl_attr = declspecs->decl_attr;
+  attribute_list decl_attr = declspecs->decl_attr;
   int array_ptr_quals = TYPE_UNQUALIFIED;
-  tree array_ptr_attrs = NULL_TREE;
+  attribute_list array_ptr_attrs = NULL;
   int array_parm_static = 0;
-  tree returned_attrs = NULL_TREE;
+  attribute_list returned_attrs = NULL;
   bool bitfield = width != NULL;
   tree element_type;
   struct c_arg_info *arg_info = 0;
@@ -3928,7 +3929,7 @@ grokdeclarator (const struct c_declarato
 	 outermost layer removed.  */
 
       if (array_ptr_quals != TYPE_UNQUALIFIED
-	  || array_ptr_attrs != NULL_TREE
+	  || array_ptr_attrs != NULL
 	  || array_parm_static)
 	{
 	  /* Only the innermost declarator (making a parameter be of
@@ -3936,7 +3937,7 @@ grokdeclarator (const struct c_declarato
 	     may have static or type qualifiers.  */
 	  error ("static or type qualifiers in non-parameter array declarator");
 	  array_ptr_quals = TYPE_UNQUALIFIED;
-	  array_ptr_attrs = NULL_TREE;
+	  array_ptr_attrs = NULL;
 	  array_parm_static = 0;
 	}
 
@@ -3945,7 +3946,7 @@ grokdeclarator (const struct c_declarato
 	case cdk_attrs:
 	  {
 	    /* A declarator with embedded attributes.  */
-	    tree attrs = declarator->u.attrs;
+	    attribute_list attrs = declarator->u.attrs;
 	    const struct c_declarator *inner_decl;
 	    int attr_flags = 0;
 	    declarator = declarator->declarator;
@@ -3959,7 +3960,8 @@ grokdeclarator (const struct c_declarato
 	    else if (inner_decl->kind == cdk_array)
 	      attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
 	    returned_attrs = decl_attributes (&type,
-					      chainon (returned_attrs, attrs),
+					      merge_attributes (returned_attrs,
+								attrs),
 					      attr_flags);
 	    break;
 	  }
@@ -4125,12 +4127,12 @@ grokdeclarator (const struct c_declarato
 
 	    if (decl_context != PARM
 		&& (array_ptr_quals != TYPE_UNQUALIFIED
-		    || array_ptr_attrs != NULL_TREE
+		    || array_ptr_attrs != NULL
 		    || array_parm_static))
 	      {
 		error ("static or type qualifiers in non-parameter array declarator");
 		array_ptr_quals = TYPE_UNQUALIFIED;
-		array_ptr_attrs = NULL_TREE;
+		array_ptr_attrs = NULL;
 		array_parm_static = 0;
 	      }
 	    break;
@@ -4342,7 +4344,7 @@ grokdeclarator (const struct c_declarato
 	    type_quals = array_ptr_quals;
 
 	    /* We don't yet implement attributes in this context.  */
-	    if (array_ptr_attrs != NULL_TREE)
+	    if (array_ptr_attrs != NULL)
 	      warning ("attributes in parameter array declarator ignored");
 
 	    size_varies = 0;
@@ -5098,7 +5100,7 @@ detect_field_duplicates (tree fieldlist)
    ATTRIBUTES are attributes to be applied to the structure.  */
 
 tree
-finish_struct (tree t, tree fieldlist, tree attributes)
+finish_struct (tree t, tree fieldlist, attribute_list attributes)
 {
   tree x;
   bool toplevel = file_scope == current_scope;
@@ -5392,7 +5394,7 @@ start_enum (tree name)
    Returns ENUMTYPE.  */
 
 tree
-finish_enum (tree enumtype, tree values, tree attributes)
+finish_enum (tree enumtype, tree values, attribute_list attributes)
 {
   tree pair, tem;
   tree minnode = 0, maxnode = 0;
@@ -5611,7 +5613,7 @@ build_enumerator (tree name, tree value)
 
 int
 start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
-		tree attributes)
+		attribute_list attributes)
 {
   tree decl1, old_decl;
   tree restype, resdecl;
@@ -5639,7 +5641,7 @@ start_function (struct c_declspecs *decl
 
   if (DECL_DECLARED_INLINE_P (decl1)
       && DECL_UNINLINABLE (decl1)
-      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
+      && has_attribute_p ("noinline", DECL_ATTRIBUTES (decl1)))
     warning ("%Jinline function %qD given attribute noinline", decl1, decl1);
 
   announce_function (decl1);
@@ -6547,7 +6549,7 @@ build_void_list_node (void)
 /* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR.  */
 
 struct c_parm *
-build_c_parm (struct c_declspecs *specs, tree attrs,
+build_c_parm (struct c_declspecs *specs, attribute_list attrs,
 	      struct c_declarator *declarator)
 {
   struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
@@ -6562,7 +6564,7 @@ build_c_parm (struct c_declspecs *specs,
    attributes.  */
 
 struct c_declarator *
-build_attrs_declarator (tree attrs, struct c_declarator *target)
+build_attrs_declarator (attribute_list attrs, struct c_declarator *target)
 {
   struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
   ret->kind = cdk_attrs;
@@ -6607,7 +6609,7 @@ struct c_declarator *
 make_pointer_declarator (struct c_declspecs *type_quals_attrs,
 			 struct c_declarator *target)
 {
-  tree attrs;
+  attribute_list attrs;
   int quals = 0;
   struct c_declarator *itarget = target;
   struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
@@ -6615,7 +6617,7 @@ make_pointer_declarator (struct c_declsp
     {
       attrs = type_quals_attrs->attrs;
       quals = quals_from_declspecs (type_quals_attrs);
-      if (attrs != NULL_TREE)
+      if (attrs != NULL)
 	itarget = build_attrs_declarator (attrs, target);
     }
   ret->kind = cdk_pointer;
@@ -7063,9 +7065,9 @@ declspecs_add_scspec (struct c_declspecs
    returning SPECS.  */
 
 struct c_declspecs *
-declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
+declspecs_add_attrs (struct c_declspecs *specs, attribute_list attrs)
 {
-  specs->attrs = chainon (attrs, specs->attrs);
+  specs->attrs = merge_attributes (attrs, specs->attrs);
   return specs;
 }
 
Index: gcc/c-format.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-format.c,v
retrieving revision 1.65
diff -u -p -u -p -r1.65 c-format.c
--- gcc/c-format.c	17 Sep 2004 21:54:22 -0000	1.65
+++ gcc/c-format.c	1 Oct 2004 00:57:14 -0000
@@ -82,9 +82,10 @@ static bool get_constant (tree expr, uns
 
 /* Handle a "format_arg" attribute; arguments as in
    struct attribute_spec.handler.  */
-tree
+void
 handle_format_arg_attribute (tree *node, tree ARG_UNUSED (name),
-			     tree args, int flags, bool *no_add_attrs)
+			     tree args, int flags, bool *no_add_attrs,
+			     bool * ARG_UNUSED (defer))
 {
   tree type = *node;
   tree format_num_expr = TREE_VALUE (args);
@@ -95,14 +96,14 @@ handle_format_arg_attribute (tree *node,
     {
       error ("format string has invalid operand number");
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   argument = TYPE_ARG_TYPES (type);
   if (argument)
     {
       if (!check_format_string (argument, format_num, flags, no_add_attrs))
-	return NULL_TREE;
+	return;
     }
 
   if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
@@ -112,10 +113,8 @@ handle_format_arg_attribute (tree *node,
       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
 	error ("function does not return string type");
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
-
-  return NULL_TREE;
 }
 
 /* Verify that the format_num argument is actually a string, in case
@@ -788,39 +787,38 @@ decode_format_type (const char *s)
 
 
 /* Check the argument list of a call to printf, scanf, etc.
-   ATTRS are the attributes on the function type.
+   ATTRS are the attributes on the function type, guaranteed not NULL.
    PARAMS is the list of argument values.  Also, if -Wmissing-format-attribute,
    warn for calls to vprintf or vscanf in functions with no such format
    attribute themselves.  */
 
 void
-check_function_format (tree attrs, tree params)
+check_function_format (attribute_list attrs, tree params)
 {
-  tree a;
+  attribute_count i;
 
   /* See if this function has any format attributes.  */
-  for (a = attrs; a; a = TREE_CHAIN (a))
+  for (i = 0; i < attrs->n_attributes; i++)
     {
-      if (is_attribute_p ("format", TREE_PURPOSE (a)))
+      if (is_attribute_p ("format", attrs->attribs[i].name))
 	{
 	  /* Yup; check it.  */
 	  function_format_info info;
-	  decode_format_attr (TREE_VALUE (a), &info, 1);
+	  decode_format_attr (attrs->attribs[i].value, &info, 1);
 	  check_format_info (&info, params);
 	  if (warn_missing_format_attribute && info.first_arg_num == 0
 	      && (format_types[info.format_type].flags
 		  & (int) FMT_FLAG_ARG_CONVERT))
 	    {
-	      tree c;
-	      for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
-		   c;
-		   c = TREE_CHAIN (c))
-		if (is_attribute_p ("format", TREE_PURPOSE (c))
+	      attribute_count c;
+	      attribute_list a = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+	      for (c = 0; c < ATTRIBUTE_COUNT (a); c++)
+		if (is_attribute_p ("format", a->attribs[c].name)
 		    && (decode_format_type (IDENTIFIER_POINTER
-					    (TREE_VALUE (TREE_VALUE (c))))
+					    (TREE_VALUE (a->attribs[c].value)))
 			== info.format_type))
 		  break;
-	      if (c == NULL_TREE)
+	      if (c == ATTRIBUTE_COUNT (a))
 		{
 		  /* Check if the current function has a parameter to which
 		     the format attribute could be attached; if not, it
@@ -2446,9 +2444,10 @@ extern const format_kind_info TARGET_FOR
 
 /* Handle a "format" attribute; arguments as in
    struct attribute_spec.handler.  */
-tree
+void
 handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args,
-			 int flags, bool *no_add_attrs)
+			 int flags, bool *no_add_attrs,
+			 bool * ARG_UNUSED (defer))
 {
   tree type = *node;
   function_format_info info;
@@ -2474,7 +2473,7 @@ handle_format_attribute (tree *node, tre
   if (!decode_format_attr (args, &info, 0))
     {
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   argument = TYPE_ARG_TYPES (type);
@@ -2482,7 +2481,7 @@ handle_format_attribute (tree *node, tre
     {
       if (!check_format_string (argument, info.format_num, flags,
 				no_add_attrs))
-	return NULL_TREE;
+	return;
 
       if (info.first_arg_num != 0)
 	{
@@ -2498,7 +2497,7 @@ handle_format_attribute (tree *node, tre
 	      if (!(flags & (int) ATTR_FLAG_BUILT_IN))
 		error ("args to be formatted is not '...'");
 	      *no_add_attrs = true;
-	      return NULL_TREE;
+	      return;
 	    }
 	}
     }
@@ -2507,7 +2506,7 @@ handle_format_attribute (tree *node, tre
     {
       error ("strftime formats cannot format arguments");
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   /* If this is a custom GCC-internal format type, we have to
@@ -2537,6 +2536,4 @@ handle_format_attribute (tree *node, tre
       else
 	gcc_unreachable();
     }
-
-  return NULL_TREE;
 }
Index: gcc/c-objc-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-objc-common.c,v
retrieving revision 1.56
diff -u -p -u -p -r1.56 c-objc-common.c
--- gcc/c-objc-common.c	21 Sep 2004 15:42:43 -0000	1.56
+++ gcc/c-objc-common.c	1 Oct 2004 00:57:14 -0000
@@ -57,7 +57,7 @@ c_missing_noreturn_ok_p (tree decl)
 int
 c_disregard_inline_limits (tree fn)
 {
-  if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) != NULL)
+  if (has_attribute_p ("always_inline", DECL_ATTRIBUTES (fn)))
     return 1;
 
   return (!flag_really_no_inline && DECL_DECLARED_INLINE_P (fn)
@@ -75,7 +75,7 @@ c_cannot_inline_tree_fn (tree *fnp)
 		     && !DECL_IN_SYSTEM_HEADER (fn));
 
   if (flag_really_no_inline
-      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
+      && !has_attribute_p ("always_inline", DECL_ATTRIBUTES (fn)))
     {
       if (do_warning)
 	warning ("%Jfunction %qF can never be inlined because it "
Index: gcc/c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.243
diff -u -p -u -p -r1.243 c-parse.in
--- gcc/c-parse.in	28 Sep 2004 19:35:22 -0000	1.243
+++ gcc/c-parse.in	1 Oct 2004 00:57:15 -0000
@@ -103,7 +103,8 @@ do {									\
 	struct c_arg_info *arginfotype; struct c_declarator *dtrtype;
 	struct c_type_name *typenametype; struct c_parm *parmtype;
 	struct c_declspecs *dsptype; enum tree_code code;
-	location_t location; }
+	location_t location;
+        attribute_list attrs; struct one_attribute attrib; }
 
 /* All identifiers that are not reserved words
    and are not declared typedefs in the current block */
@@ -213,7 +214,8 @@ do {									\
 %type <exprtype> init
 %type <ttype> simple_asm_expr maybeasm asm_stmt asm_argument
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
-%type <ttype> maybe_attribute attributes attribute attribute_list attrib
+%type <attrib> attrib
+%type <attrs> maybe_attribute attributes attribute attribute_list
 %type <ttype> any_word
 
 %type <ttype> compstmt compstmt_start compstmt_primary_start
@@ -232,7 +234,7 @@ do {									\
 %type <ttype> component_decl components components_notype component_declarator
 %type <ttype> component_notype_declarator
 %type <ttype> enumlist enumerator
-%type <ttype> struct_head union_head enum_head
+%type <attrs> struct_head union_head enum_head
 %type <typenametype> typename
 %type <dtrtype> absdcl absdcl1 absdcl1_ea absdcl1_noea direct_absdcl1
 %type <parmtype> absdcl_maybe_attribute
@@ -270,21 +272,21 @@ do {									\
 %{
 /* Declaration specifiers of the current declaration.  */
 static struct c_declspecs *current_declspecs;
-static GTY(()) tree prefix_attributes;
+static GTY(()) attribute_list prefix_attributes;
 
 /* List of all the attributes applying to the identifier currently being
    declared; includes prefix_attributes and possibly some more attributes
    just after a comma.  */
-static GTY(()) tree all_prefix_attributes;
+static GTY(()) attribute_list all_prefix_attributes;
 
 /* Structure to save declaration specifiers.  */
 struct c_declspec_stack {
   /* Saved value of current_declspecs.  */
   struct c_declspecs *current_declspecs;
   /* Saved value of prefix_attributes.  */
-  tree prefix_attributes;
+  attribute_list prefix_attributes;
   /* Saved value of all_prefix_attributes.  */
-  tree all_prefix_attributes;
+  attribute_list all_prefix_attributes;
   /* Next level of stack.  */
   struct c_declspec_stack *next;
 };
@@ -865,12 +867,12 @@ setspecs: /* empty */
 		  if ($<dsptype>0)
 		    {
 		      prefix_attributes = $<dsptype>0->attrs;
-		      $<dsptype>0->attrs = NULL_TREE;
+		      $<dsptype>0->attrs = NULL;
 		      current_declspecs = $<dsptype>0;
 		    }
 		  else
 		    {
-		      prefix_attributes = NULL_TREE;
+		      prefix_attributes = NULL;
 		      current_declspecs = build_null_declspecs ();
 		    }
 		  current_declspecs = finish_declspecs (current_declspecs);
@@ -881,7 +883,7 @@ setspecs: /* empty */
    to prefix_attributes with these ones chained on the front.  */
 maybe_resetattrs:
 	  maybe_attribute
-		{ all_prefix_attributes = chainon ($1, prefix_attributes); }
+		{ all_prefix_attributes = merge_attributes ($1, prefix_attributes); }
 	;
 
 decl:
@@ -1315,7 +1317,7 @@ notype_initdecls:
 initdcl:
 	  declarator maybeasm maybe_attribute '='
 		{ $<ttype>$ = start_decl ($1, current_declspecs, true,
-					  chainon ($3, all_prefix_attributes));
+					  merge_attributes ($3, all_prefix_attributes));
 		  start_init ($<ttype>$, $2, global_bindings_p ()); }
 	  init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
@@ -1324,7 +1326,7 @@ initdcl:
 		  finish_decl ($<ttype>5, $6.value, $2); }
 	| declarator maybeasm maybe_attribute
 		{ tree d = start_decl ($1, current_declspecs, false,
-				       chainon ($3, all_prefix_attributes));
+				       merge_attributes ($3, all_prefix_attributes));
 		  finish_decl (d, NULL_TREE, $2);
                 }
 	;
@@ -1332,7 +1334,7 @@ initdcl:
 notype_initdcl:
 	  notype_declarator maybeasm maybe_attribute '='
 		{ $<ttype>$ = start_decl ($1, current_declspecs, true,
-					  chainon ($3, all_prefix_attributes));
+					  merge_attributes ($3, all_prefix_attributes));
 		  start_init ($<ttype>$, $2, global_bindings_p ()); }
 	  init
 /* Note how the declaration of the variable is in effect while its init is parsed! */
@@ -1341,14 +1343,14 @@ notype_initdcl:
 		  finish_decl ($<ttype>5, $6.value, $2); }
 	| notype_declarator maybeasm maybe_attribute
 		{ tree d = start_decl ($1, current_declspecs, false,
-				       chainon ($3, all_prefix_attributes));
+				       merge_attributes ($3, all_prefix_attributes));
 		  finish_decl (d, NULL_TREE, $2); }
 	;
 /* the * rules are dummies to accept the Apollo extended syntax
    so that the header files compile. */
 maybe_attribute:
       /* empty */
-		{ $$ = NULL_TREE; }
+		{ $$ = NULL; }
 	| attributes
 		{ $$ = $1; }
 	;
@@ -1357,7 +1359,7 @@ attributes:
       attribute
 		{ $$ = $1; }
 	| attributes attribute
-		{ $$ = chainon ($1, $2); }
+		{ $$ = merge_attributes ($1, $2); }
 	;
 
 attribute:
@@ -1365,27 +1367,29 @@ attribute:
                 '(' '(' attribute_list ')' ')' start_string_translation
 		{ $$ = $5; }
       | ATTRIBUTE error start_string_translation
-                { $$ = NULL_TREE; }
+                { $$ = NULL; }
 	;
 
 attribute_list:
       attrib
-		{ $$ = $1; }
+		{ $$ = ($1.name ? merge_attributes_1 (NULL, 1, &$1, NULL, 0) 
+			: 0); }
 	| attribute_list ',' attrib
-		{ $$ = chainon ($1, $3); }
+		{ $$ = ($3.name ? merge_attributes_1 ($1, 1, &$3, NULL, 0) 
+			: 0); }
 	;
 
 attrib:
     /* empty */
-		{ $$ = NULL_TREE; }
+		{ $$.name = NULL; }
 	| any_word
-		{ $$ = build_tree_list ($1, NULL_TREE); }
+		{ $$.name = $1; }
 	| any_word '(' IDENTIFIER ')'
-		{ $$ = build_tree_list ($1, build_tree_list (NULL_TREE, $3)); }
+		{ $$.name = $1, $$.value = build_tree_list (NULL_TREE, $3); }
 	| any_word '(' IDENTIFIER ',' nonnull_exprlist ')'
-		{ $$ = build_tree_list ($1, tree_cons (NULL_TREE, $3, $5)); }
+		{ $$.name = $1, $$.value = tree_cons (NULL_TREE, $3, $5); }
 	| any_word '(' exprlist ')'
-		{ $$ = build_tree_list ($1, $3); }
+		{ $$.name = $1, $$.value = $3; }
 	;
 
 /* This still leaves out most reserved keywords,
@@ -1613,21 +1617,21 @@ notype_declarator:
 
 struct_head:
 	  STRUCT
-		{ $$ = NULL_TREE; }
+		{ $$ = NULL; }
 	| STRUCT attributes
 		{ $$ = $2; }
 	;
 
 union_head:
 	  UNION
-		{ $$ = NULL_TREE; }
+		{ $$ = NULL; }
 	| UNION attributes
 		{ $$ = $2; }
 	;
 
 enum_head:
 	  ENUM
-		{ $$ = NULL_TREE; }
+		{ $$ = NULL; }
 	| ENUM attributes
 		{ $$ = $2; }
 	;
@@ -1645,30 +1649,30 @@ structsp_attr:
 		}
 	  component_decl_list '}' maybe_attribute
 		{ $$ = finish_struct ($<ttype>4, nreverse ($5),
-				      chainon ($1, $7)); }
+				      merge_attributes ($1, $7)); }
 	| struct_head '{' component_decl_list '}' maybe_attribute
 		{ $$ = finish_struct (start_struct (RECORD_TYPE, NULL_TREE),
-				      nreverse ($3), chainon ($1, $5));
+				      nreverse ($3), merge_attributes ($1, $5));
 		}
 	| union_head identifier '{'
 		{ $$ = start_struct (UNION_TYPE, $2); }
 	  component_decl_list '}' maybe_attribute
 		{ $$ = finish_struct ($<ttype>4, nreverse ($5),
-				      chainon ($1, $7)); }
+				      merge_attributes ($1, $7)); }
 	| union_head '{' component_decl_list '}' maybe_attribute
 		{ $$ = finish_struct (start_struct (UNION_TYPE, NULL_TREE),
-				      nreverse ($3), chainon ($1, $5));
+				      nreverse ($3), merge_attributes ($1, $5));
 		}
 	| enum_head identifier '{'
 		{ $$ = start_enum ($2); }
 	  enumlist maybecomma_warn '}' maybe_attribute
 		{ $$ = finish_enum ($<ttype>4, nreverse ($5),
-				    chainon ($1, $8)); }
+				    merge_attributes ($1, $8)); }
 	| enum_head '{'
 		{ $$ = start_enum (NULL_TREE); }
 	  enumlist maybecomma_warn '}' maybe_attribute
 		{ $$ = finish_enum ($<ttype>3, nreverse ($4),
-				    chainon ($1, $7)); }
+				    merge_attributes ($1, $7)); }
 	;
 
 structsp_nonattr:
@@ -1776,32 +1780,32 @@ component_declarator:
 	  declarator maybe_attribute
 		{ $$ = grokfield ($1, current_declspecs, NULL_TREE);
 		  decl_attributes (&$$,
-				   chainon ($2, all_prefix_attributes), 0); }
+				   merge_attributes ($2, all_prefix_attributes), 0); }
 	| declarator ':' expr_no_commas maybe_attribute
 		{ $$ = grokfield ($1, current_declspecs, $3.value);
 		  decl_attributes (&$$,
-				   chainon ($4, all_prefix_attributes), 0); }
+				   merge_attributes ($4, all_prefix_attributes), 0); }
 	| ':' expr_no_commas maybe_attribute
 		{ $$ = grokfield (build_id_declarator (NULL_TREE),
 				  current_declspecs, $2.value);
 		  decl_attributes (&$$,
-				   chainon ($3, all_prefix_attributes), 0); }
+				   merge_attributes ($3, all_prefix_attributes), 0); }
 	;
 
 component_notype_declarator:
 	  notype_declarator maybe_attribute
 		{ $$ = grokfield ($1, current_declspecs, NULL_TREE);
 		  decl_attributes (&$$,
-				   chainon ($2, all_prefix_attributes), 0); }
+				   merge_attributes ($2, all_prefix_attributes), 0); }
 	| notype_declarator ':' expr_no_commas maybe_attribute
 		{ $$ = grokfield ($1, current_declspecs, $3.value);
 		  decl_attributes (&$$,
-				   chainon ($4, all_prefix_attributes), 0); }
+				   merge_attributes ($4, all_prefix_attributes), 0); }
 	| ':' expr_no_commas maybe_attribute
 		{ $$ = grokfield (build_id_declarator (NULL_TREE),
 				  current_declspecs, $2.value);
 		  decl_attributes (&$$,
-				   chainon ($3, all_prefix_attributes), 0); }
+				   merge_attributes ($3, all_prefix_attributes), 0); }
 	;
 
 /* We chain the enumerators in reverse order.
@@ -1851,7 +1855,7 @@ absdcl_maybe_attribute:   /* absdcl mayb
 				     $1); }
 	| absdcl1_noea attributes
 		{ $$ = build_c_parm (current_declspecs,
-				     chainon ($2, all_prefix_attributes),
+				     merge_attributes ($2, all_prefix_attributes),
 				     $1); }
 	;
 
@@ -2474,18 +2478,18 @@ parms:
 parm:
 	  declspecs_ts setspecs parm_declarator maybe_attribute
 		{ $$ = build_c_parm (current_declspecs,
-				     chainon ($4, all_prefix_attributes), $3);
+				     merge_attributes ($4, all_prefix_attributes), $3);
 		  POP_DECLSPEC_STACK; }
 	| declspecs_ts setspecs notype_declarator maybe_attribute
 		{ $$ = build_c_parm (current_declspecs,
-				     chainon ($4, all_prefix_attributes), $3);
+				     merge_attributes ($4, all_prefix_attributes), $3);
 		  POP_DECLSPEC_STACK; }
 	| declspecs_ts setspecs absdcl_maybe_attribute
 		{ $$ = $3;
 		  POP_DECLSPEC_STACK; }
 	| declspecs_nots setspecs notype_declarator maybe_attribute
 		{ $$ = build_c_parm (current_declspecs,
-				     chainon ($4, all_prefix_attributes), $3);
+				     merge_attributes ($4, all_prefix_attributes), $3);
 		  POP_DECLSPEC_STACK; }
 
 	| declspecs_nots setspecs absdcl_maybe_attribute
@@ -2498,18 +2502,18 @@ parm:
 firstparm:
 	  declspecs_ts_nosa setspecs_fp parm_declarator maybe_attribute
 		{ $$ = build_c_parm (current_declspecs,
-				     chainon ($4, all_prefix_attributes), $3);
+				     merge_attributes ($4, all_prefix_attributes), $3);
 		  POP_DECLSPEC_STACK; }
 	| declspecs_ts_nosa setspecs_fp notype_declarator maybe_attribute
 		{ $$ = build_c_parm (current_declspecs,
-				     chainon ($4, all_prefix_attributes), $3);
+				     merge_attributes ($4, all_prefix_attributes), $3);
 		  POP_DECLSPEC_STACK; }
 	| declspecs_ts_nosa setspecs_fp absdcl_maybe_attribute
 		{ $$ = $3;
 		  POP_DECLSPEC_STACK; }
 	| declspecs_nots_nosa setspecs_fp notype_declarator maybe_attribute
 		{ $$ = build_c_parm (current_declspecs,
-				     chainon ($4, all_prefix_attributes), $3);
+				     merge_attributes ($4, all_prefix_attributes), $3);
 		  POP_DECLSPEC_STACK; }
 
 	| declspecs_nots_nosa setspecs_fp absdcl_maybe_attribute
@@ -2519,7 +2523,7 @@ firstparm:
 
 setspecs_fp:
 	  setspecs
-		{ prefix_attributes = chainon (prefix_attributes, $<ttype>-2);
+		{ prefix_attributes = merge_attributes (prefix_attributes, $<attrs>-2);
 		  all_prefix_attributes = prefix_attributes; }
 	;
 
Index: gcc/c-pragma.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-pragma.c,v
retrieving revision 1.78
diff -u -p -u -p -r1.78 c-pragma.c
--- gcc/c-pragma.c	17 Sep 2004 21:54:22 -0000	1.78
+++ gcc/c-pragma.c	1 Oct 2004 00:57:15 -0000
@@ -247,11 +247,15 @@ apply_pragma_weak (tree decl, tree value
 {
   if (value)
     {
+      struct one_attribute oa;
+      attribute_list al;
       value = build_string (IDENTIFIER_LENGTH (value),
 			    IDENTIFIER_POINTER (value));
-      decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
-					       build_tree_list (NULL, value)),
-		       0);
+
+      oa.name = get_identifier ("alias");
+      oa.value = build_tree_list (NULL, value);
+      al = merge_attributes_1 (NULL, 1, &oa, NULL, 0);
+      decl_attributes (&decl, al, 0);
     }
 
   if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
Index: gcc/c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.185
diff -u -p -u -p -r1.185 c-tree.h
--- gcc/c-tree.h	30 Sep 2004 22:52:05 -0000	1.185
+++ gcc/c-tree.h	1 Oct 2004 00:57:15 -0000
@@ -161,11 +161,11 @@ struct c_declspecs {
      "char" is used.  Does not include qualifiers.  */
   tree type;
   /* The attributes from a typedef decl.  */
-  tree decl_attr;
+  attribute_list decl_attr;
   /* When parsing, the attributes.  Outside the parser, this will be
      NULL; attributes (possibly from multiple lists) will be passed
      separately.  */
-  tree attrs;
+  attribute_list attrs;
   /* Any type specifier keyword used such as "int", not reflecting
      modifiers such as "short", or cts_none if none.  */
   enum c_typespec_keyword typespec_word;
@@ -258,7 +258,7 @@ struct c_declarator {
       /* The qualifiers inside [].  */
       int quals;
       /* The attributes (currently ignored) inside [].  */
-      tree attrs;
+      attribute_list attrs;
       /* Whether [static] was used.  */
       BOOL_BITFIELD static_p : 1;
       /* Whether [*] was used.  */
@@ -267,7 +267,7 @@ struct c_declarator {
     /* For pointers, the qualifiers on the pointer type.  */
     int pointer_quals;
     /* For attributes.  */
-    tree attrs;
+    attribute_list attrs;
   } u;
 };
 
@@ -284,7 +284,7 @@ struct c_parm {
   /* The declaration specifiers, minus any prefix attributes.  */
   struct c_declspecs *specs;
   /* The attributes.  */
-  tree attrs;
+  attribute_list attrs;
   /* The declarator.  */
   struct c_declarator *declarator;
 };
@@ -341,9 +341,9 @@ extern void undeclared_variable (tree);
 extern tree declare_label (tree);
 extern tree define_label (location_t, tree);
 extern void finish_decl (tree, tree, tree);
-extern tree finish_enum (tree, tree, tree);
+extern tree finish_enum (tree, tree, attribute_list);
 extern void finish_function (void);
-extern tree finish_struct (tree, tree, tree);
+extern tree finish_struct (tree, tree, attribute_list);
 extern struct c_arg_info *get_parm_info (bool);
 extern tree grokfield (struct c_declarator *, struct c_declspecs *, tree);
 extern tree groktypename (struct c_type_name *);
@@ -360,21 +360,22 @@ extern struct c_declarator *set_array_de
 							struct c_declarator *,
 							bool);
 extern tree builtin_function (const char *, tree, int, enum built_in_class,
-			      const char *, tree);
+			      const char *, attribute_list);
 extern void shadow_tag (const struct c_declspecs *);
 extern void shadow_tag_warned (const struct c_declspecs *, int);
 extern tree start_enum (tree);
-extern int  start_function (struct c_declspecs *, struct c_declarator *, tree);
+extern int  start_function (struct c_declspecs *, struct c_declarator *, 
+			    attribute_list);
 extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
-			tree);
+			attribute_list);
 extern tree start_struct (enum tree_code, tree);
 extern void store_parm_decls (void);
 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 struct c_parm *build_c_parm (struct c_declspecs *, tree,
+extern struct c_parm *build_c_parm (struct c_declspecs *, attribute_list,
 				    struct c_declarator *);
-extern struct c_declarator *build_attrs_declarator (tree,
+extern struct c_declarator *build_attrs_declarator (attribute_list,
 						    struct c_declarator *);
 extern struct c_declarator *build_function_declarator (struct c_arg_info *,
 						       struct c_declarator *);
@@ -385,7 +386,8 @@ extern struct c_declspecs *build_null_de
 extern struct c_declspecs *declspecs_add_qual (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_type (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
-extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *,
+						attribute_list);
 extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
 
 /* in c-objc-common.c */
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.383
diff -u -p -u -p -r1.383 c-typeck.c
--- gcc/c-typeck.c	30 Sep 2004 22:52:05 -0000	1.383
+++ gcc/c-typeck.c	1 Oct 2004 00:57:15 -0000
@@ -232,7 +232,7 @@ composite_type (tree t1, tree t2)
 {
   enum tree_code code1;
   enum tree_code code2;
-  tree attributes;
+  attribute_list attributes;
 
   /* Save time if the two types are the same.  */
 
@@ -415,7 +415,7 @@ composite_type (tree t1, tree t2)
 static tree
 common_pointer_type (tree t1, tree t2)
 {
-  tree attributes;
+  attribute_list attributes;
   tree pointed_to_1;
   tree pointed_to_2;
   tree target;
@@ -475,11 +475,11 @@ common_type (tree t1, tree t2)
   if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
     t2 = TYPE_MAIN_VARIANT (t2);
 
-  if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
-    t1 = build_type_attribute_variant (t1, NULL_TREE);
+  if (TYPE_ATTRIBUTES (t1) != NULL)
+    t1 = build_type_attribute_variant (t1, NULL);
 
-  if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
-    t2 = build_type_attribute_variant (t2, NULL_TREE);
+  if (TYPE_ATTRIBUTES (t2) != NULL)
+    t2 = build_type_attribute_variant (t2, NULL);
 
   /* Save time if the two types are the same.  */
 
Index: gcc/cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.85
diff -u -p -u -p -r1.85 cgraphunit.c
--- gcc/cgraphunit.c	26 Sep 2004 19:53:10 -0000	1.85
+++ gcc/cgraphunit.c	1 Oct 2004 00:57:15 -0000
@@ -282,7 +282,7 @@ decide_is_function_needed (struct cgraph
     return true;
 
   /* If the user told us it is used, then it must be so.  */
-  if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("used", DECL_ATTRIBUTES (decl)))
     return true;
 
   /* ??? If the assembler name is set by hand, it is possible to assemble
Index: gcc/coretypes.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/coretypes.h,v
retrieving revision 1.5
diff -u -p -u -p -r1.5 coretypes.h
--- gcc/coretypes.h	28 Jul 2004 23:36:41 -0000	1.5
+++ gcc/coretypes.h	1 Oct 2004 00:57:15 -0000
@@ -44,6 +44,12 @@ typedef struct rtvec_def *rtvec;
 union tree_node;
 typedef union tree_node *tree;
 
+struct one_attribute;
+struct attribute_list_s;
+typedef struct attribute_list_s * attribute_list;
+/* Assume never more than 64k attributes.  */
+typedef unsigned short attribute_count;
+
 /* Provide forward struct declaration so that we don't have to include
    all of cpplib.h whenever a random prototype includes a pointer.
    Note that the cpp_reader typedef remains part of cpplib.h.  */
Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.465
diff -u -p -u -p -r1.465 fold-const.c
--- gcc/fold-const.c	29 Sep 2004 19:44:53 -0000	1.465
+++ gcc/fold-const.c	1 Oct 2004 00:57:16 -0000
@@ -7922,13 +7922,13 @@ fold (tree expr)
 	  && TREE_CODE (arg0) == ADDR_EXPR
 	  && DECL_P (TREE_OPERAND (arg0, 0))
 	  && ! DECL_WEAK (TREE_OPERAND (arg0, 0))
-	  && ! lookup_attribute ("alias",
+	  && ! has_attribute_p ("alias",
 				 DECL_ATTRIBUTES (TREE_OPERAND (arg0, 0)))
 	  && ! DECL_EXTERNAL (TREE_OPERAND (arg0, 0))
 	  && TREE_CODE (arg1) == ADDR_EXPR
 	  && DECL_P (TREE_OPERAND (arg1, 0))
 	  && ! DECL_WEAK (TREE_OPERAND (arg1, 0))
-	  && ! lookup_attribute ("alias",
+	  && ! has_attribute_p ("alias",
 				 DECL_ATTRIBUTES (TREE_OPERAND (arg1, 0)))
 	  && ! DECL_EXTERNAL (TREE_OPERAND (arg1, 0)))
 	return constant_boolean_node (operand_equal_p (arg0, arg1, 0)
Index: gcc/integrate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.c,v
retrieving revision 1.270
diff -u -p -u -p -r1.270 integrate.c
--- gcc/integrate.c	18 Aug 2004 08:23:53 -0000	1.270
+++ gcc/integrate.c	1 Oct 2004 00:57:16 -0000
@@ -87,13 +87,14 @@ get_label_from_map (struct inline_remap 
 bool
 function_attribute_inlinable_p (tree fndecl)
 {
-  if (targetm.attribute_table)
+  if (targetm.attribute_table && DECL_ATTRIBUTES (fndecl))
     {
-      tree a;
+      attribute_list at = DECL_ATTRIBUTES (fndecl);
+      attribute_count ac;
 
-      for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
+      for (ac = 0; ac < at->n_attributes; ac++)
 	{
-	  tree name = TREE_PURPOSE (a);
+	  tree name = at->attribs[ac].name;
 	  int i;
 
 	  for (i = 0; targetm.attribute_table[i].name != NULL; i++)
Index: gcc/langhooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks.c,v
retrieving revision 1.78
diff -u -p -u -p -r1.78 langhooks.c
--- gcc/langhooks.c	17 Sep 2004 21:54:35 -0000	1.78
+++ gcc/langhooks.c	1 Oct 2004 00:57:16 -0000
@@ -311,7 +311,7 @@ int
 lhd_tree_inlining_cannot_inline_tree_fn (tree *fnp)
 {
   if (flag_really_no_inline
-      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (*fnp)) == NULL)
+      && !has_attribute_p ("always_inline", DECL_ATTRIBUTES (*fnp)))
     return 1;
 
   return 0;
@@ -324,7 +324,7 @@ lhd_tree_inlining_cannot_inline_tree_fn 
 int
 lhd_tree_inlining_disregard_inline_limits (tree fn)
 {
-  if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) != NULL)
+  if (has_attribute_p ("always_inline", DECL_ATTRIBUTES (fn)))
     return 1;
 
   return 0;
Index: gcc/langhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/langhooks.h,v
retrieving revision 1.101
diff -u -p -u -p -r1.101 langhooks.h
--- gcc/langhooks.h	17 Sep 2004 21:54:35 -0000	1.101
+++ gcc/langhooks.h	1 Oct 2004 00:57:16 -0000
@@ -414,7 +414,7 @@ struct lang_hooks
      ATTRS is nonzero, use that for the function's attribute list.  */
   tree (*builtin_function) (const char *name, tree type, int function_code,
 			    enum built_in_class bt_class,
-			    const char *library_name, tree attrs);
+			    const char *library_name, attribute_list attrs);
 
   /* Whenever you add entries here, make sure you adjust langhooks-def.h
      and langhooks.c accordingly.  */
Index: gcc/passes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/passes.c,v
retrieving revision 2.52
diff -u -p -u -p -r2.52 passes.c
--- gcc/passes.c	25 Sep 2004 10:05:09 -0000	2.52
+++ gcc/passes.c	1 Oct 2004 00:57:16 -0000
@@ -195,11 +195,10 @@ rest_of_decl_compilation (tree decl,
   /* We deferred calling assemble_alias so that we could collect
      other attributes such as visibility.  Emit the alias now.  */
   {
-    tree alias;
-    alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
+    tree alias = get_attribute ("alias", DECL_ATTRIBUTES (decl));
     if (alias)
       {
-	alias = TREE_VALUE (TREE_VALUE (alias));
+	alias = TREE_VALUE (alias);
 	alias = get_identifier (TREE_STRING_POINTER (alias));
 	assemble_alias (decl, alias);
       }
Index: gcc/print-tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/print-tree.c,v
retrieving revision 1.94
diff -u -p -u -p -r1.94 print-tree.c
--- gcc/print-tree.c	17 Sep 2004 21:54:36 -0000	1.94
+++ gcc/print-tree.c	1 Oct 2004 00:57:16 -0000
@@ -146,6 +146,24 @@ indent_to (FILE *file, int column)
   for (i = 0; i < column; i++)
     fprintf (file, " ");
 }
+
+/* Print some attributes of a node.  */
+void
+print_attributes (FILE *file, attribute_list al, int indent)
+{
+  attribute_count ac;
+  
+  if (! al)
+    return;
+  fprintf (file, " attributes <");
+  for (ac = 0; ac < al->n_attributes; ac++)
+    if (al->attribs[ac].value)
+      print_node (file, IDENTIFIER_POINTER (al->attribs[ac].name),
+		  al->attribs[ac].value, indent);
+    else
+      fprintf (file, " %s", IDENTIFIER_POINTER (al->attribs[ac].name));
+  fputc ('>', file);
+}
 
 /* Print the node NODE in full on file FILE, preceded by PREFIX,
    starting in column INDENT.  */
@@ -416,8 +434,7 @@ print_node (FILE *file, const char *pref
 	}
 
       print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);
-      print_node_brief (file, "attributes",
-			DECL_ATTRIBUTES (node), indent + 4);
+      print_attributes (file, DECL_ATTRIBUTES (node), indent + 4);
       print_node_brief (file, "abstract_origin",
 			DECL_ABSTRACT_ORIGIN (node), indent + 4);
 
@@ -527,7 +544,7 @@ print_node (FILE *file, const char *pref
 	       TYPE_ALIGN (node), TYPE_SYMTAB_ADDRESS (node),
 	       TYPE_ALIAS_SET (node));
 
-      print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4);
+      print_attributes (file, TYPE_ATTRIBUTES (node), indent + 4);
 
       if (INTEGRAL_TYPE_P (node) || TREE_CODE (node) == REAL_TYPE)
 	{
Index: gcc/system.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/system.h,v
retrieving revision 1.228
diff -u -p -u -p -r1.228 system.h
--- gcc/system.h	27 Sep 2004 22:38:08 -0000	1.228
+++ gcc/system.h	1 Oct 2004 00:57:16 -0000
@@ -660,7 +660,7 @@ extern void fancy_abort (const char *, i
 	LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS \
 	LANG_HOOKS_PUSHLEVEL LANG_HOOKS_SET_BLOCK \
 	LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \
-	LANG_HOOKS_POPLEVEL
+	LANG_HOOKS_POPLEVEL TARGET_INSERT_ATTRIBUTES
 
 /* Libiberty macros that are no longer used in GCC.  */
 #undef ANSI_PROTOTYPES
Index: gcc/target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.105
diff -u -p -u -p -r1.105 target-def.h
--- gcc/target-def.h	24 Sep 2004 15:13:53 -0000	1.105
+++ gcc/target-def.h	1 Oct 2004 00:57:16 -0000
@@ -343,7 +343,7 @@ Foundation, 59 Temple Place - Suite 330,
 #define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_false
 #define TARGET_COMP_TYPE_ATTRIBUTES hook_int_tree_tree_1
 #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES hook_void_tree
-#define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
+#define TARGET_ADD_ATTRIBUTES default_add_attributes
 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
 #define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
 #define TARGET_ALIGN_ANON_BITFIELD hook_bool_void_false
@@ -484,7 +484,7 @@ Foundation, 59 Temple Place - Suite 330,
   TARGET_ATTRIBUTE_TABLE,			\
   TARGET_COMP_TYPE_ATTRIBUTES,			\
   TARGET_SET_DEFAULT_TYPE_ATTRIBUTES,		\
-  TARGET_INSERT_ATTRIBUTES,			\
+  TARGET_ADD_ATTRIBUTES,			\
   TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P,	\
   TARGET_MS_BITFIELD_LAYOUT_P,			\
   TARGET_ALIGN_ANON_BITFIELD,			\
Index: gcc/target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.117
diff -u -p -u -p -r1.117 target.h
--- gcc/target.h	23 Sep 2004 14:34:19 -0000	1.117
+++ gcc/target.h	1 Oct 2004 00:57:16 -0000
@@ -303,10 +303,10 @@ struct gcc_target
   enum machine_mode (* eh_return_filter_mode) (void);
 
   /* Given two decls, merge their attributes and return the result.  */
-  tree (* merge_decl_attributes) (tree, tree);
+  attribute_list (* merge_decl_attributes) (tree, tree);
 
   /* Given two types, merge their attributes and return the result.  */
-  tree (* merge_type_attributes) (tree, tree);
+  attribute_list (* merge_type_attributes) (tree, tree);
 
   /* Table of machine attributes and functions to handle them.
      Ignored if NULL.  */
@@ -320,8 +320,10 @@ struct gcc_target
   /* Assign default attributes to the newly defined TYPE.  */
   void (* set_default_type_attributes) (tree type);
 
-  /* Insert attributes on the newly created DECL.  */
-  void (* insert_attributes) (tree decl, tree *attributes);
+  /* Possibly add some extra attributes to DECL, which is already
+     going to have ATTRIBUTES added.  */
+  attribute_count (* add_attributes) (tree decl, attribute_list attributes,
+				      const struct one_attribute * * to_add);
 
   /* Return true if FNDECL (which has at least one machine attribute)
      can be inlined despite its machine attributes, false otherwise.  */
Index: gcc/targhooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/targhooks.c,v
retrieving revision 2.33
diff -u -p -u -p -r2.33 targhooks.c
--- gcc/targhooks.c	24 Sep 2004 15:13:53 -0000	2.33
+++ gcc/targhooks.c	1 Oct 2004 00:57:16 -0000
@@ -285,3 +285,13 @@ hook_bool_CUMULATIVE_ARGS_mode_tree_bool
 {
   return true;
 }
+
+/* The default implementation of TARGET_ADD_ATTRIBUTES: don't add anything.  */
+
+attribute_count
+default_add_attributes (tree decl ATTRIBUTE_UNUSED,
+			attribute_list attributes ATTRIBUTE_UNUSED,
+			const struct one_attribute * * to_add ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
Index: gcc/targhooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/targhooks.h,v
retrieving revision 2.23
diff -u -p -u -p -r2.23 targhooks.h
--- gcc/targhooks.h	24 Sep 2004 15:13:53 -0000	2.23
+++ gcc/targhooks.h	1 Oct 2004 00:57:16 -0000
@@ -58,3 +58,7 @@ extern bool hook_bool_CUMULATIVE_ARGS_mo
   (CUMULATIVE_ARGS *, enum machine_mode, tree, bool);
 extern bool hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
   (CUMULATIVE_ARGS *, enum machine_mode, tree, bool);
+
+extern attribute_count default_add_attributes
+  (tree decl, attribute_list attributes,
+   const struct one_attribute * * to_add);
Index: gcc/tree-browser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-browser.c,v
retrieving revision 2.3
diff -u -p -u -p -r2.3 tree-browser.c
--- gcc/tree-browser.c	17 Sep 2004 21:54:37 -0000	2.3
+++ gcc/tree-browser.c	1 Oct 2004 00:57:16 -0000
@@ -19,6 +19,8 @@ along with GCC; see the file COPYING.  I
 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
+/* FIXME: what does this file do?  */
+
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -368,12 +370,7 @@ browse_tree (tree begin)
 	  break;
 
 	case TB_ATTRIBUTES:
-	  if (head && DECL_P (head))
-	    TB_SET_HEAD (DECL_ATTRIBUTES (head));
-	  else if (head && TYPE_P (head))
-	    TB_SET_HEAD (TYPE_ATTRIBUTES (head));
-	  else
-	    TB_WF;
+	  TB_WF;
 	  break;
 
 	case TB_CONTEXT:
Index: gcc/tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.144
diff -u -p -u -p -r1.144 tree-inline.c
--- gcc/tree-inline.c	25 Sep 2004 10:05:09 -0000	1.144
+++ gcc/tree-inline.c	1 Oct 2004 00:57:16 -0000
@@ -937,7 +937,7 @@ inline_forbidden_p_1 (tree *nodep, int *
 	 SPEC2000 inlining into schedule_block cause it to require 2GB of
 	 RAM instead of 256MB.  */
       if (alloca_call_p (node)
-	  && !lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
+	  && !has_attribute_p ("always_inline", DECL_ATTRIBUTES (fn)))
 	{
 	  inline_forbidden_reason
 	    = N_("%Jfunction '%F' can never be inlined because it uses "
@@ -1122,7 +1122,7 @@ inlinable_function_p (tree fn)
 			 && DECL_DECLARED_INLINE_P (fn)
 			 && !DECL_IN_SYSTEM_HEADER (fn));
 
-      if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
+      if (has_attribute_p ("always_inline", DECL_ATTRIBUTES (fn)))
 	sorry (inline_forbidden_reason, fn, fn);
       else if (do_warning)
 	warning (inline_forbidden_reason, fn, fn);
@@ -1468,7 +1468,7 @@ expand_call_inline (tree *tp, int *walk_
      inlining.  */
   if (!cgraph_inline_p (edge, &reason))
     {
-      if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)))
+      if (has_attribute_p ("always_inline", DECL_ATTRIBUTES (fn)))
 	{
 	  sorry ("%Jinlining failed in call to '%F': %s", fn, fn, reason);
 	  sorry ("called from here");
Index: gcc/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.437
diff -u -p -u -p -r1.437 tree.c
--- gcc/tree.c	29 Sep 2004 13:07:44 -0000	1.437
+++ gcc/tree.c	1 Oct 2004 00:57:16 -0000
@@ -132,7 +132,7 @@ static void print_type_hash_statistics (
 static tree make_vector_type (tree, int, enum machine_mode);
 static int type_hash_marked_p (const void *);
 static unsigned int type_hash_list (tree, hashval_t);
-static unsigned int attribute_hash_list (tree, hashval_t);
+static unsigned int attribute_hash_list (attribute_list, hashval_t);
 
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
@@ -362,7 +362,7 @@ make_node_stat (enum tree_code code MEM_
       TYPE_MAIN_VARIANT (t) = t;
 
       /* Default to no attributes for type, but let target change that.  */
-      TYPE_ATTRIBUTES (t) = NULL_TREE;
+      TYPE_ATTRIBUTES (t) = NULL;
       targetm.set_default_type_attributes (t);
 
       /* We have not yet computed the alias set for this type.  */
@@ -2791,7 +2791,7 @@ annotate_with_locus (tree node, location
    is ATTRIBUTE.  */
 
 tree
-build_decl_attribute_variant (tree ddecl, tree attribute)
+build_decl_attribute_variant (tree ddecl, attribute_list attribute)
 {
   DECL_ATTRIBUTES (ddecl) = attribute;
   return ddecl;
@@ -2871,7 +2871,7 @@ iterative_hash_host_wide_int (HOST_WIDE_
    Record such modified types already made so we don't make duplicates.  */
 
 tree
-build_type_attribute_variant (tree ttype, tree attribute)
+build_type_attribute_variant (tree ttype, attribute_list attribute)
 {
   if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
     {
@@ -2975,80 +2975,151 @@ is_attribute_p (const char *attr, tree i
   return 0;
 }
 
-/* Given an attribute name and a list of attributes, return a pointer to the
-   attribute's list element if the attribute is part of the list, or NULL_TREE
-   if not found.  If the attribute appears more than once, this only
-   returns the first occurrence; the TREE_CHAIN of the return value should
-   be passed back in if further occurrences are wanted.  */
+/* Return the index of the first attribute, starting with the
+   attribute indexed by START, named NAME in ATTRIBUTES.  If no such
+   attribute exists, return attributes->n_attributes.  ATTRIBUTES must
+   be non-NULL.  */
+
+attribute_count
+lookup_attribute (const char *name, 
+		  attribute_list attributes,
+		  attribute_count start)
+{
+  attribute_count result;
+  for (result = start; result < attributes->n_attributes; result++)
+    {
+      gcc_assert (TREE_CODE (attributes->attribs[result].name) 
+		  == IDENTIFIER_NODE);
+      if (is_attribute_p (name, attributes->attribs[result].name))
+	break;
+    }
+  return result;
+}
+
+/* Does ATTRIBUTES contain NAME?  */
+
+bool
+has_attribute_p (const char *name, attribute_list attributes)
+{
+  if (!attributes)
+    return false;
+  return lookup_attribute (name, attributes, 0) != attributes->n_attributes;
+}
+
+/* If ATTRIBUTES contains NAME, return the associated value, otherwise
+   NULL.  The attribute must not have a NULL value.  */
 
 tree
-lookup_attribute (const char *attr_name, tree list)
+get_attribute (const char *name, attribute_list attributes)
 {
-  tree l;
+  attribute_count i;
+  
+  if (!attributes)
+    return NULL_TREE;
+  i = lookup_attribute (name, attributes, 0);
+  if (i == attributes->n_attributes)
+    return NULL_TREE;
+  gcc_assert (attributes->attribs[i].value);
+  return attributes->attribs[i].value;
+}
+
+/* Given a list of attributes A and NUM extra attributes in EXTRA,
+   and an NUM-sized array of FLAGS, return a list of attributes that
+   contains every attribute in A plus each attribute in EXTRA for which
+   FLAGS is SELECT.  A may be NULL.  May return A.  FLAGS may be NULL,
+   in which case every element of EXTRA is selected.
+
+   Every attribute list is created using this routine.  */
+
+attribute_list
+merge_attributes_1 (attribute_list a, attribute_count num,
+		    const struct one_attribute *extra,
+		    const char * flags, char select)
+{
+  /* Number of attributes selected, in a, and in result, respectively.  */
+  attribute_count n_select, n_a, n_result;
+  attribute_count i, ir;
+  attribute_list result;
+
+  if (flags)
+    for (n_select = i = 0; i < num; i++)
+      n_select += flags[i] == select;
+  else
+    n_select = num;
+  
+  /* Don't allocate memory in trivial case.  */
+  if (n_select == 0)
+    return a;
 
-  for (l = list; l; l = TREE_CHAIN (l))
+  n_a = ATTRIBUTE_COUNT (a);
+  n_result = n_a + n_select;
+  if (n_result < n_a || n_result == (attribute_count)-1)
     {
-      gcc_assert (TREE_CODE (TREE_PURPOSE (l)) == IDENTIFIER_NODE);
-      if (is_attribute_p (attr_name, TREE_PURPOSE (l)))
-	return l;
+      error ("too many attributes");
+      return a;
     }
-
-  return NULL_TREE;
+  
+  /* Unfortunately we can't use ggc_realloc because attribute lists
+     can be shared.  */
+  result = ggc_alloc (sizeof (struct attribute_list_s)
+		      + (n_result - 1) * sizeof (struct one_attribute));
+  result->n_attributes = n_result;
+  if (n_a)
+    memcpy (result->attribs, a->attribs, sizeof (struct one_attribute) * n_a);
+  if (!flags)
+    memcpy (result->attribs + n_a, extra, sizeof (struct one_attribute) * num);
+  else
+    for (ir = n_a, i = 0; i < num; i++)
+      if (flags[i] == select)
+	result->attribs[ir++] = extra[i];
+  return result;
 }
 
 /* Return an attribute list that is the union of a1 and a2.  */
 
-tree
-merge_attributes (tree a1, tree a2)
+attribute_list
+merge_attributes (attribute_list a1, attribute_list a2)
 {
-  tree attributes;
-
-  /* Either one unset?  Take the set one.  */
-
-  if ((attributes = a1) == 0)
-    attributes = a2;
-
-  /* One that completely contains the other?  Take it.  */
+  char * add_from_2;
+  attribute_count i2;
 
-  else if (a2 != 0 && ! attribute_list_contained (a1, a2))
-    {
-      if (attribute_list_contained (a2, a1))
-	attributes = a2;
-      else
-	{
-	  /* Pick the longest list, and hang on the other list.  */
-
-	  if (list_length (a1) < list_length (a2))
-	    attributes = a2, a2 = a1;
-
-	  for (; a2 != 0; a2 = TREE_CHAIN (a2))
-	    {
-	      tree a;
-	      for (a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
-					 attributes);
-		   a != NULL_TREE;
-		   a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
-					 TREE_CHAIN (a)))
-		{
-		  if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1)
-		    break;
-		}
-	      if (a == NULL_TREE)
-		{
-		  a1 = copy_node (a2);
-		  TREE_CHAIN (a1) = attributes;
-		  attributes = a1;
-		}
-	    }
-	}
+  /* If one is NULL, take the other.  */
+  if (a2 == NULL)
+    return a1;
+  if (a1 == NULL)
+    return a2;
+
+  /* Save on temporaries: pick the shorter one as 'a2'.  */
+  if (a1->n_attributes < a2->n_attributes)
+    {
+      attribute_list tmp;
+      tmp = a1;
+      a1 = a2;
+      a2 = tmp;
+    }
+
+  /* Determine which elements of a2 need to be added to a1.  */
+  add_from_2 = alloca (sizeof (bool) * a2->n_attributes);
+  for (i2 = 0; i2 < a2->n_attributes; i2++)
+    {
+      attribute_count i1;
+      tree v2 = a2->attribs[i2].value;
+      tree n2 = a2->attribs[i2].name;
+      for (i1 = 0; i1 < a1->n_attributes; i1++)
+	if (is_attribute_p (IDENTIFIER_POINTER (n2), a1->attribs[i1].name)
+	    && simple_cst_equal (v2, a1->attribs[i1].value) == 1)
+	  break;
+      add_from_2[i2] = i1 == a1->n_attributes;
     }
-  return attributes;
+
+  return merge_attributes_1 (a1, a2->n_attributes, a2->attribs,
+			     add_from_2, true);
 }
 
 /* Given types T1 and T2, merge their attributes and return
   the result.  */
 
-tree
+attribute_list
 merge_type_attributes (tree t1, tree t2)
 {
   return merge_attributes (TYPE_ATTRIBUTES (t1),
@@ -3058,13 +3129,32 @@ merge_type_attributes (tree t1, tree t2)
 /* Given decls OLDDECL and NEWDECL, merge their attributes and return
    the result.  */
 
-tree
+attribute_list
 merge_decl_attributes (tree olddecl, tree newdecl)
 {
   return merge_attributes (DECL_ATTRIBUTES (olddecl),
 			   DECL_ATTRIBUTES (newdecl));
 }
 
+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+   struct attribute_spec.handler.  */
+
+void
+handle_fndecl_attribute (tree *node, tree name,
+			 tree ARG_UNUSED (args),
+			 int ARG_UNUSED (flags),
+			 bool *no_add_attrs,
+			 bool * ARG_UNUSED (defer))
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning ("`%s' attribute only applies to functions",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+}
+
+
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 
 /* Specialization of merge_decl_attributes for various Windows targets.
@@ -3076,54 +3166,39 @@ merge_decl_attributes (tree olddecl, tre
 
    The second instance of `foo' nullifies the dllimport.  */
 
-tree
-merge_dllimport_decl_attributes (tree old, tree new)
+attribute_list
+merge_dllimport_decl_attributes (tree old_p, tree new_p)
 {
-  tree a;
-  int delete_dllimport_p;
+  attribute_list old, new;
+  char *mask;
+  attribute_count oldc;
 
-  old = DECL_ATTRIBUTES (old);
-  new = DECL_ATTRIBUTES (new);
+  old = DECL_ATTRIBUTES (old_p);
+  new = DECL_ATTRIBUTES (new_p);
 
+  oldc = ATTRIBUTE_COUNT (old);
+  mask = alloca (oldc * sizeof (char));
+  
   /* What we need to do here is remove from `old' dllimport if it doesn't
      appear in `new'.  dllimport behaves like extern: if a declaration is
      marked dllimport and a definition appears later, then the object
      is not dllimport'd.  */
-  if (lookup_attribute ("dllimport", old) != NULL_TREE
-      && lookup_attribute ("dllimport", new) == NULL_TREE)
-    delete_dllimport_p = 1;
-  else
-    delete_dllimport_p = 0;
-
-  a = merge_attributes (old, new);
-
-  if (delete_dllimport_p)
+  if (!has_attribute_p ("dllimport", new))
     {
-      tree prev, t;
-
-      /* Scan the list for dllimport and delete it.  */
-      for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
-	{
-	  if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
-	    {
-	      if (prev == NULL_TREE)
-		a = TREE_CHAIN (a);
-	      else
-		TREE_CHAIN (prev) = TREE_CHAIN (t);
-	      break;
-	    }
-	}
+      attribute_count i;
+      for (i = 0; i < oldc; i++)
+	mask[i] = ! is_attribute_p ("dllimport", old->attribs[i].name);
     }
 
-  return a;
+  return merge_attributes_1 (new, oldc, old ? old->attribs : NULL, mask, true);
 }
 
 /* Handle a "dllimport" or "dllexport" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-tree
-handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
-		      bool *no_add_attrs)
+void
+handle_dll_attribute (tree * pnode, tree name, tree ARG_UNUSED (args),
+		      int flags, bool *no_add_attrs, bool *defer)
 {
   tree node = *pnode;
 
@@ -3133,17 +3208,15 @@ handle_dll_attribute (tree * pnode, tree
     {
       if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
 		   | (int) ATTR_FLAG_ARRAY_NEXT))
-	{
-	  *no_add_attrs = true;
-	  return tree_cons (name, args, NULL_TREE);
-	}
-      if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
+	*defer = true;
+      else if (TREE_CODE (node) != RECORD_TYPE 
+	       && TREE_CODE (node) != UNION_TYPE)
 	{
 	  warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
 	  *no_add_attrs = true;
 	}
 
-      return NULL_TREE;
+      return;
     }
 
   /* Report error on dllimport ambiguities seen now before they cause
@@ -3189,8 +3262,6 @@ handle_dll_attribute (tree * pnode, tree
 	     "%qs attribute.", node, node, IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES  */
@@ -3522,26 +3593,40 @@ print_type_hash_statistics (void)
    with names in the TREE_PURPOSE slots and args in the TREE_VALUE slots),
    by adding the hash codes of the individual attributes.  */
 
-unsigned int
-attribute_hash_list (tree list, hashval_t hashcode)
+static unsigned int
+attribute_hash_list (attribute_list list, hashval_t hashcode)
 {
-  tree tail;
+  attribute_count i;
 
-  for (tail = list; tail; tail = TREE_CHAIN (tail))
-    /* ??? Do we want to add in TREE_VALUE too? */
-    hashcode = iterative_hash_object
-      (IDENTIFIER_HASH_VALUE (TREE_PURPOSE (tail)), hashcode);
+  if (list != NULL)
+    for (i = 0; i < list->n_attributes; i++)
+      /* ??? Do we want to add in TREE_VALUE too? */
+      hashcode = iterative_hash_object
+	(IDENTIFIER_HASH_VALUE (list->attribs[i].name), hashcode);
   return hashcode;
 }
 
 /* Given two lists of attributes, return true if list l2 is
    equivalent to l1.  */
 
-int
-attribute_list_equal (tree l1, tree l2)
+bool
+attribute_list_equal (attribute_list l1, attribute_list l2)
 {
-  return attribute_list_contained (l1, l2)
-	 && attribute_list_contained (l2, l1);
+  bool result;
+  
+  result = l1 == l2;
+  if (l1 == NULL || l2 == NULL || result)
+    return result;
+
+  /* Attribute lists are supposed to contain only unique entries,
+     so if they're the same size then 'contained' should be equivalent
+     to 'equal'.  */
+  result = (l1->n_attributes == l2->n_attributes
+	    && attribute_list_contained (l1, l2));
+  gcc_assert (l1->n_attributes != l2->n_attributes 
+	      || result == attribute_list_contained (l2, l1));
+
+  return result;
 }
 
 /* Given two lists of attributes, return true if list L2 is
@@ -3552,46 +3637,47 @@ attribute_list_equal (tree l1, tree l2)
 /* ??? It's not clear that attributes with arguments will always be handled
    correctly.  */
 
-int
-attribute_list_contained (tree l1, tree l2)
+bool
+attribute_list_contained (attribute_list a1, attribute_list a2)
 {
-  tree t1, t2;
+  attribute_count i;
 
   /* First check the obvious, maybe the lists are identical.  */
-  if (l1 == l2)
-    return 1;
-
-  /* Maybe the lists are similar.  */
-  for (t1 = l1, t2 = l2;
-       t1 != 0 && t2 != 0
-        && TREE_PURPOSE (t1) == TREE_PURPOSE (t2)
-        && TREE_VALUE (t1) == TREE_VALUE (t2);
-       t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2));
-
-  /* Maybe the lists are equal.  */
-  if (t1 == 0 && t2 == 0)
-    return 1;
+  if (a1 == a2)
+    return true;
 
-  for (; t2 != 0; t2 = TREE_CHAIN (t2))
-    {
-      tree attr;
-      for (attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)), l1);
-	   attr != NULL_TREE;
-	   attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
-				    TREE_CHAIN (attr)))
-	{
-	  if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
-	    break;
-	}
+  /* Check for NULLs.  */
+  if (a1 == NULL)
+    return false;
+  if (a2 == NULL)
+    return true;
 
-      if (attr == 0)
-	return 0;
+  /* Maybe a2 is obviously not a subset because it's larger.  */
+  if (a1->n_attributes < a2->n_attributes)
+    return false;
 
-      if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) != 1)
-	return 0;
+  /* Compare a common initial part of the two lists.  */
+  i = 0;
+  while (i < a2->n_attributes
+	 && a1->attribs[i].name == a2->attribs[i].name
+	 && a1->attribs[i].value == a2->attribs[i].value)
+    i++;
+    
+  while (i < a2->n_attributes)
+    {
+      attribute_count i1;
+      tree v2 = a2->attribs[i].value;
+      tree n2 = a2->attribs[i].name;
+
+      for (i1 = 0; i1 < a1->n_attributes; i1++)
+	if (is_attribute_p (IDENTIFIER_POINTER (n2), a1->attribs[i1].name)
+	    && simple_cst_equal (v2, a1->attribs[i1].value) == 1)
+	  break;
+      if (i1 == a1->n_attributes)
+	return false;
+      i++;
     }
-
-  return 1;
+  return true;
 }
 
 /* Given two lists of types
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.634
diff -u -p -u -p -r1.634 tree.h
--- gcc/tree.h	30 Sep 2004 01:22:06 -0000	1.634
+++ gcc/tree.h	1 Oct 2004 00:57:17 -0000
@@ -215,6 +215,24 @@ extern const char *const built_in_names[
 extern GTY(()) tree built_in_decls[(int) END_BUILTINS];
 extern GTY(()) tree implicit_built_in_decls[(int) END_BUILTINS];
 
+/* A structure representing 'attributes' on a DECL or TYPE node.
+   Each attribute has a NAME (an IDENTIFIER_NODE) and possibly a VALUE.  */
+struct one_attribute GTY(())
+{
+  tree name;
+  tree value;
+};
+
+/* A counted list of attributes.  */
+struct attribute_list_s GTY(())
+{
+  attribute_count n_attributes;
+  /* There are 16 bits free here.  */
+  struct one_attribute GTY((length ("%h.n_attributes"))) attribs[1];
+};
+
+#define ATTRIBUTE_COUNT(a) ((a) ? (a)->n_attributes : 0)
+
 /* The definition of tree nodes fills the next several pages.  */
 
 /* A tree node can represent a data type, a variable, an expression
@@ -1670,7 +1688,7 @@ struct tree_type GTY(())
   tree values;
   tree size;
   tree size_unit;
-  tree attributes;
+  attribute_list attributes;
   unsigned int uid;
 
   unsigned int precision : 9;
@@ -2388,7 +2406,7 @@ struct tree_decl GTY(())
   tree abstract_origin;
   tree assembler_name;
   tree section_name;
-  tree attributes;
+  attribute_list attributes;
   rtx rtl;	/* RTL representation for object.  */
 
   /* In FUNCTION_DECL, if it is inline, holds the saved insn chain.
@@ -2739,12 +2757,12 @@ extern tree decl_assembler_name (tree);
 /* Compute the number of bytes occupied by 'node'.  This routine only
    looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH.  */
 
-extern size_t tree_size (tree);
+extern size_t tree_size (tree node);
 
 /* Compute the number of bytes occupied by a tree with code CODE.  This
    function cannot be used for TREE_VEC or PHI_NODE codes, which are of
    variable length.  */
-extern size_t tree_code_size (enum tree_code);
+extern size_t tree_code_size (enum tree_code code);
 
 /* Lowest level primitive for allocating a node.
    The TREE_CODE is the only argument.  Contents are initialized
@@ -2904,8 +2922,8 @@ extern bool in_array_bounds_p (tree);
 extern tree value_member (tree, tree);
 extern tree purpose_member (tree, tree);
 
-extern int attribute_list_equal (tree, tree);
-extern int attribute_list_contained (tree, tree);
+extern bool attribute_list_equal (attribute_list, attribute_list);
+extern bool attribute_list_contained (attribute_list, attribute_list);
 extern int tree_int_cst_equal (tree, tree);
 extern int tree_int_cst_lt (tree, tree);
 extern int tree_int_cst_compare (tree, tree);
@@ -2929,8 +2947,10 @@ extern tree make_tree (tree, rtx);
    Such modified types already made are recorded so that duplicates
    are not made.  */
 
-extern tree build_type_attribute_variant (tree, tree);
-extern tree build_decl_attribute_variant (tree, tree);
+extern tree build_type_attribute_variant (tree ttype,
+					  attribute_list attribute);
+extern tree build_decl_attribute_variant (tree ddecl,
+					  attribute_list attribute);
 
 /* Structure describing an attribute and a function to handle it.  */
 struct attribute_spec
@@ -2959,22 +2979,22 @@ struct attribute_spec
      and from a function return type (which is not itself a function
      pointer type) to the function type.  */
   const bool function_type_required;
-  /* Function to handle this attribute.  NODE points to the node to which
-     the attribute is to be applied.  If a DECL, it should be modified in
-     place; if a TYPE, a copy should be created.  NAME is the name of the
-     attribute (possibly with leading or trailing __).  ARGS is the TREE_LIST
-     of the arguments (which may be NULL).  FLAGS gives further information
-     about the context of the attribute.  Afterwards, the attributes will
-     be added to the DECL_ATTRIBUTES or TYPE_ATTRIBUTES, as appropriate,
-     unless *NO_ADD_ATTRS is set to true (which should be done on error,
-     as well as in any other cases when the attributes should not be added
-     to the DECL or TYPE).  Depending on FLAGS, any attributes to be
-     applied to another type or DECL later may be returned;
-     otherwise the return value should be NULL_TREE.  This pointer may be
-     NULL if no special handling is required beyond the checks implied
-     by the rest of this structure.  */
-  tree (*const handler) (tree *node, tree name, tree args,
-				 int flags, bool *no_add_attrs);
+  /* Function to handle this attribute.  NODE points to the node to
+     which the attribute is to be applied.  If a DECL, it should be
+     modified in place; if a TYPE, a copy should be created.  NAME is
+     the name of the attribute (possibly with leading or trailing __).
+     ARGS is the 'value' of the arguments (which may be NULL).  FLAGS
+     gives further information about the context of the attribute.
+     Afterwards, the attributes will be added to the DECL_ATTRIBUTES
+     or TYPE_ATTRIBUTES, as appropriate, unless *IGNORE or *DEFER are
+     set to true (which should be done on error, as well as in any
+     other cases when the attributes should not be added to the DECL
+     or TYPE).  If the attribute should be deferred to an enclosing
+     object (like a DECL if this is a TYPE), *DEFER should be set.
+     This pointer may be NULL if no special handling is required
+     beyond the checks implied by the rest of this structure.  */
+  void (*const handler) (tree *node, tree name, tree args,
+			 int flags, bool *ignore, bool *defer);
 };
 
 /* Flags that may be passed in the third argument of decl_attributes, and
@@ -3004,8 +3024,8 @@ enum attribute_flags
 
 /* Default versions of target-overridable functions.  */
 
-extern tree merge_decl_attributes (tree, tree);
-extern tree merge_type_attributes (tree, tree);
+extern attribute_list merge_decl_attributes (tree, tree);
+extern attribute_list merge_type_attributes (tree, tree);
 extern void default_register_cpp_builtins (struct cpp_reader *);
 
 /* Return 1 if an attribute and its arguments are valid for a decl or type.  */
@@ -3017,22 +3037,54 @@ extern int valid_machine_attribute (tree
 
 extern int is_attribute_p (const char *, tree);
 
-/* Given an attribute name and a list of attributes, return the list element
-   of the attribute or NULL_TREE if not found.  */
-
-extern tree lookup_attribute (const char *, tree);
+/* Return the index of the first attribute, starting with the
+   attribute indexed by START, named NAME in ATTRIBUTES.  If no such
+   attribute exists, return attributes->n_attributes.  */
+
+extern attribute_count lookup_attribute (const char *name, 
+					 attribute_list attributes,
+					 attribute_count start);
+
+/* Does ATTRIBUTES contain NAME?  */
+
+extern bool has_attribute_p (const char *name, attribute_list attributes);
+
+/* If ATTRIBUTES contains NAME, return the associated value, otherwise
+   NULL.  The attribute must not have a NULL value.  */
+
+extern tree get_attribute (const char *name, attribute_list attributes);
+
+/* Given a list of attributes A and NUM extra attributes in EXTRA,
+   and an NUM-sized array of FLAGS, return a list of attributes that
+   contains every attribute in A plus each attribute in EXTRA for which
+   FLAGS is SELECT.  A may be NULL.  May return A.  FLAGS may be NULL,
+   in which case every element of EXTRA is selected.
+
+   Every attribute list is created using this routine.  */
+extern attribute_list merge_attributes_1 (attribute_list a,
+					  attribute_count num,
+					  const struct one_attribute *extra,
+					  const char * flags,
+					  char select);
 
 /* Given two attributes lists, return a list of their union.  */
 
-extern tree merge_attributes (tree, tree);
+extern attribute_list merge_attributes (attribute_list, attribute_list);
+
+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+   struct attribute_spec.handler.  */
+
+void handle_fndecl_attribute (tree *node, tree name,
+			      tree args, int flags,
+			      bool *no_add_attrs, bool * defer);
 
 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
 /* Given two Windows decl attributes lists, possibly including
    dllimport, return a list of their union .  */
-extern tree merge_dllimport_decl_attributes (tree, tree);
+extern attribute_list merge_dllimport_decl_attributes (tree, tree);
 
 /* Handle a "dllimport" or "dllexport" attribute.  */
-extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
+extern void handle_dll_attribute (tree *, tree, tree, int, bool *, bool *);
 #endif
 
 /* Check whether CAND is suitable to be returned from get_qualified_type
@@ -3647,6 +3699,7 @@ extern void debug_tree (tree);
 #ifdef BUFSIZ
 extern void print_node (FILE *, const char *, tree, int);
 extern void print_node_brief (FILE *, const char *, tree, int);
+extern void print_attributes (FILE *, attribute_list, int);
 extern void indent_to (FILE *, int);
 #endif
 
@@ -3711,7 +3764,8 @@ extern bool must_pass_in_stack_var_size_
    from tree.h.  Depending on these flags, some attributes may be
    returned to be applied at a later stage (for example, to apply
    a decl attribute to the declaration rather than to its type).  */
-extern tree decl_attributes (tree *, tree, int);
+extern attribute_list decl_attributes (tree *node, attribute_list attributes,
+				       int flags);
 
 /* In integrate.c */
 extern void set_decl_abstract_flags (tree, int);
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.453
diff -u -p -u -p -r1.453 varasm.c
--- gcc/varasm.c	21 Sep 2004 23:40:21 -0000	1.453
+++ gcc/varasm.c	1 Oct 2004 00:57:17 -0000
@@ -4476,12 +4476,12 @@ enum tls_model
 decl_tls_model (tree decl)
 {
   enum tls_model kind;
-  tree attr = lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl));
+  tree at = get_attribute ("tls_model", DECL_ATTRIBUTES (decl));
   bool is_local;
 
-  if (attr)
+  if (at)
     {
-      attr = TREE_VALUE (TREE_VALUE (attr));
+      tree attr = TREE_VALUE (at);
       if (TREE_CODE (attr) != STRING_CST)
 	abort ();
       if (!strcmp (TREE_STRING_POINTER (attr), "local-exec"))
Index: gcc/ada/gigi.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/gigi.h,v
retrieving revision 1.31
diff -u -p -u -p -r1.31 gigi.h
--- gcc/ada/gigi.h	13 Sep 2004 10:18:39 -0000	1.31
+++ gcc/ada/gigi.h	1 Oct 2004 00:57:18 -0000
@@ -681,7 +681,7 @@ extern bool gnat_mark_addressable (tree)
 
 /* Implementation of the builtin_function langhook.  */
 extern tree builtin_function (const char *, tree, int, enum built_in_class,
-			      const char *, tree);
+			      const char *, attribute_list);
 
 /* This function is called by the front end to enumerate all the supported
    modes for the machine.  We pass a function which is called back with
Index: gcc/ada/utils.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/utils.c,v
retrieving revision 1.84
diff -u -p -u -p -r1.84 utils.c
--- gcc/ada/utils.c	21 Sep 2004 15:31:02 -0000	1.84
+++ gcc/ada/utils.c	1 Oct 2004 00:57:18 -0000
@@ -1831,7 +1831,7 @@ gnat_gimplify_function (tree fndecl)
 tree
 builtin_function (const char *name, tree type, int function_code,
                   enum built_in_class class, const char *library_name,
-                  tree attrs)
+                  attribute_list attrs)
 {
   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
 
Index: gcc/config/sol2-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sol2-protos.h,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 sol2-protos.h
--- gcc/config/sol2-protos.h	25 Jul 2004 18:10:02 -0000	1.1
+++ gcc/config/sol2-protos.h	1 Oct 2004 00:57:18 -0000
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING.  I
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-extern void solaris_insert_attributes (tree, tree *);
+extern attribute_count solaris_add_attributes (tree, attribute_list,
+					       const struct one_attribute **);
 extern void solaris_register_pragmas (void);
 extern void solaris_output_init_fini (FILE *, tree);
Index: gcc/config/sol2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sol2.c,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 sol2.c
--- gcc/config/sol2.c	25 Jul 2004 18:10:02 -0000	1.1
+++ gcc/config/sol2.c	1 Oct 2004 00:57:18 -0000
@@ -36,11 +36,16 @@ tree solaris_pending_aligns, solaris_pen
    all languages to avoid changing the target machine initializer
    depending on the language.  */
 
-void
-solaris_insert_attributes (tree decl, tree *attributes)
+attribute_count
+solaris_add_attributes (tree decl, attribute_list attributes,
+			const struct one_attribute **to_add)
 {
+  static struct one_attribute a[4];
+  attribute_count ac = 0;
   tree *x, next;
 
+  *to_add = a;
+
   if (solaris_pending_aligns != NULL && TREE_CODE (decl) == VAR_DECL)
     for (x = &solaris_pending_aligns; *x; x = &TREE_CHAIN (*x))
       {
@@ -48,13 +53,15 @@ solaris_insert_attributes (tree decl, tr
 	tree value = TREE_VALUE (*x);
 	if (DECL_NAME (decl) == name)
 	  {
-	    if (lookup_attribute ("aligned", DECL_ATTRIBUTES (decl))
-		|| lookup_attribute ("aligned", *attributes))
+	    if (has_attribute_p ("aligned", DECL_ATTRIBUTES (decl))
+		|| has_attribute_p ("aligned", attributes))
 	      warning ("%Jignoring %<#pragma align%> for explicitly "
 		       "aligned %<%D%>", decl, decl);
 	    else
-	      *attributes = tree_cons (get_identifier ("aligned"), value,
-				       *attributes);
+	      {
+		a[ac].name = get_identifier ("aligned");
+		a[ac++].value = value;
+	      }
 	    next = TREE_CHAIN (*x);
 	    ggc_free (*x);
 	    *x = next;
@@ -68,10 +75,10 @@ solaris_insert_attributes (tree decl, tr
 	tree name = TREE_PURPOSE (*x);
 	if (DECL_NAME (decl) == name)
 	  {
-	    *attributes = tree_cons (get_identifier ("init"), NULL,
-				     *attributes);
-	    *attributes = tree_cons (get_identifier ("used"), NULL,
-				     *attributes);
+	    a[ac].name = get_identifier ("init");
+	    a[ac++].value = NULL_TREE;
+	    a[ac].name = get_identifier ("used");
+	    a[ac++].value = NULL_TREE;
 	    next = TREE_CHAIN (*x);
 	    ggc_free (*x);
 	    *x = next;
@@ -85,16 +92,17 @@ solaris_insert_attributes (tree decl, tr
 	tree name = TREE_PURPOSE (*x);
 	if (DECL_NAME (decl) == name)
 	  {
-	    *attributes = tree_cons (get_identifier ("fini"), NULL,
-				     *attributes);
-	    *attributes = tree_cons (get_identifier ("used"), NULL,
-				     *attributes);
+	    a[ac].name = get_identifier ("fini");
+	    a[ac++].value = NULL_TREE;
+	    a[ac].name = get_identifier ("used");
+	    a[ac++].value = NULL_TREE;
 	    next = TREE_CHAIN (*x);
 	    ggc_free (*x);
 	    *x = next;
 	    break;
 	  }
       }
+  return ac;
 }
 
 /* Output initializer or finalizer entries for DECL to FILE.  */
@@ -102,14 +110,14 @@ solaris_insert_attributes (tree decl, tr
 void
 solaris_output_init_fini (FILE *file, tree decl)
 {
-  if (lookup_attribute ("init", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("init", DECL_ATTRIBUTES (decl)))
     {
       fprintf (file, "\t.pushsection\t\".init\"\n");
       ASM_OUTPUT_CALL (file, IDENTIFIER_POINTER (DECL_NAME (decl)));
       fprintf (file, "\t.popsection\n");
     }
 
-  if (lookup_attribute ("fini", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("fini", DECL_ATTRIBUTES (decl)))
     {
       fprintf (file, "\t.pushsection\t\".fini\"\n");
       ASM_OUTPUT_CALL (file, IDENTIFIER_POINTER (DECL_NAME (decl)));
Index: gcc/config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.397
diff -u -p -u -p -r1.397 alpha.c
--- gcc/config/alpha/alpha.c	30 Sep 2004 08:21:27 -0000	1.397
+++ gcc/config/alpha/alpha.c	1 Oct 2004 00:57:18 -0000
@@ -5737,36 +5737,36 @@ alpha_init_builtins (void)
   for (i = 0; i < ARRAY_SIZE (zero_arg_builtins); ++i, ++p)
     if ((target_flags & p->target_mask) == p->target_mask)
       lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
-				   NULL, NULL_TREE);
+				   NULL, NULL);
 
   ftype = build_function_type_list (long_integer_type_node,
-				    long_integer_type_node, NULL_TREE);
+				    long_integer_type_node, NULL);
 
   p = one_arg_builtins;
   for (i = 0; i < ARRAY_SIZE (one_arg_builtins); ++i, ++p)
     if ((target_flags & p->target_mask) == p->target_mask)
       lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
-				   NULL, NULL_TREE);
+				   NULL, NULL);
 
   ftype = build_function_type_list (long_integer_type_node,
 				    long_integer_type_node,
-				    long_integer_type_node, NULL_TREE);
+				    long_integer_type_node, NULL);
 
   p = two_arg_builtins;
   for (i = 0; i < ARRAY_SIZE (two_arg_builtins); ++i, ++p)
     if ((target_flags & p->target_mask) == p->target_mask)
       lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
-				   NULL, NULL_TREE);
+				   NULL, NULL);
 
   ftype = build_function_type (ptr_type_node, void_list_node);
   lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
 			       ALPHA_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
-			       NULL, NULL_TREE);
+			       NULL, NULL);
 
-  ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
+  ftype = build_function_type_list (void_type_node, ptr_type_node, NULL);
   lang_hooks.builtin_function ("__builtin_set_thread_pointer", ftype,
 			       ALPHA_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
-			       NULL, NULL_TREE);
+			       NULL, NULL);
 }
 
 /* Expand an expression EXP that calls a built-in function,
@@ -8427,14 +8427,14 @@ vms_section_type_flags (tree decl, const
 {
   unsigned int flags = default_section_type_flags (decl, name, reloc);
 
-  if (decl && DECL_ATTRIBUTES (decl)
-      && lookup_attribute ("overlaid", DECL_ATTRIBUTES (decl)))
+  if (!decl)
+    return flags;
+
+  if (has_attribute_p ("overlaid", DECL_ATTRIBUTES (decl)))
     flags |= SECTION_VMS_OVERLAY;
-  if (decl && DECL_ATTRIBUTES (decl)
-      && lookup_attribute ("global", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("global", DECL_ATTRIBUTES (decl)))
     flags |= SECTION_VMS_GLOBAL;
-  if (decl && DECL_ATTRIBUTES (decl)
-      && lookup_attribute ("initialize", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("initialize", DECL_ATTRIBUTES (decl)))
     flags |= SECTION_VMS_INITIALIZE;
 
   return flags;
@@ -8698,12 +8698,14 @@ unicosmk_asm_named_section (const char *
     fprintf (asm_out_file, "\t.psect\t%s,%s\n", name, kind);
 }
 
-static void
-unicosmk_insert_attributes (tree decl, tree *attr_ptr ATTRIBUTE_UNUSED)
+static attribute_count
+unicosmk_add_attributes (tree decl, attribute_list ARG_UNUSED (attrs),
+			 const struct one_attribute ** ARG_UNUSED (oa))
 {
   if (DECL_P (decl)
       && (TREE_PUBLIC (decl) || TREE_CODE (decl) == FUNCTION_DECL))
     unicosmk_unique_section (decl, 0);
+  return 0;
 }
 
 /* Output an alignment directive. We have to use the macro 'gcc@code@align'
@@ -9312,8 +9314,8 @@ alpha_init_libfuncs (void)
 #define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p
 
 #if TARGET_ABI_UNICOSMK
-# undef TARGET_INSERT_ATTRIBUTES
-# define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes
+# undef TARGET_ADD_ATTRIBUTES
+# define TARGET_ADD_ATTRIBUTES unicosmk_add_attributes
 # undef TARGET_SECTION_TYPE_FLAGS
 # define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
 # undef TARGET_ASM_UNIQUE_SECTION
Index: gcc/config/arc/arc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arc/arc.c,v
retrieving revision 1.62
diff -u -p -u -p -r1.62 arc.c
--- gcc/config/arc/arc.c	18 Sep 2004 19:19:30 -0000	1.62
+++ gcc/config/arc/arc.c	1 Oct 2004 00:57:18 -0000
@@ -90,7 +90,8 @@ static void record_cc_ref (rtx);
 static void arc_init_reg_tables (void);
 static int get_arc_condition_code (rtx);
 const struct attribute_spec arc_attribute_table[];
-static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
+static void arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *,
+					    bool *);
 static bool arc_assemble_integer (rtx, unsigned int, int);
 static void arc_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void arc_output_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -380,12 +381,13 @@ const struct attribute_spec arc_attribut
 
 /* Handle an "interrupt" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 arc_handle_interrupt_attribute (tree *node ATTRIBUTE_UNUSED,
                                 tree name,
                                 tree args,
                                 int flags ATTRIBUTE_UNUSED,
-                                bool *no_add_attrs)
+                                bool *no_add_attrs,
+				bool * ARG_UNUSED (defer))
 {
   tree value = TREE_VALUE (args);
 
@@ -402,8 +404,6 @@ arc_handle_interrupt_attribute (tree *no
 	       IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 
@@ -1004,7 +1004,6 @@ static struct arc_frame_info zero_frame_
 enum arc_function_type
 arc_compute_function_type (tree decl)
 {
-  tree a;
   /* Cached value.  */
   static enum arc_function_type fn_type = ARC_FUNCTION_UNKNOWN;
   /* Last function we were called for.  */
@@ -1025,27 +1024,22 @@ arc_compute_function_type (tree decl)
   fn_type = ARC_FUNCTION_NORMAL;
 
   /* Now see if this is an interrupt handler.  */
-  for (a = DECL_ATTRIBUTES (current_function_decl);
-       a;
-       a = TREE_CHAIN (a))
-    {
-      tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
-
-      if (name == get_identifier ("__interrupt__")
-	  && list_length (args) == 1
-	  && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
-	{
-	  tree value = TREE_VALUE (args);
-
-	  if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
-	    fn_type = ARC_FUNCTION_ILINK1;
-	  else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
-	    fn_type = ARC_FUNCTION_ILINK2;
-	  else
-	    abort ();
-	  break;
-	}
-    }
+  {
+    tree args = get_attribute ("interrupt",
+			       DECL_ATTRIBUTES (current_function_decl));
+
+    if (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+      {
+	tree value = TREE_VALUE (args);
+	
+	if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
+	  fn_type = ARC_FUNCTION_ILINK1;
+	else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
+	  fn_type = ARC_FUNCTION_ILINK2;
+	else
+	  abort ();
+      }
+  }
 
   last_fn = decl;
   return fn_type;
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.407
diff -u -p -u -p -r1.407 arm.c
--- gcc/config/arm/arm.c	18 Sep 2004 19:19:30 -0000	1.407
+++ gcc/config/arm/arm.c	1 Oct 2004 00:57:19 -0000
@@ -112,8 +112,7 @@ static unsigned long arm_compute_save_re
 static unsigned long arm_compute_save_reg_mask (void);
 static unsigned long arm_isr_value (tree);
 static unsigned long arm_compute_func_type (void);
-static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
-static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
+static void arm_handle_isr_attribute (tree *, tree, tree, int, bool *, bool *);
 static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);
 static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void thumb_output_function_prologue (FILE *, HOST_WIDE_INT);
@@ -1238,7 +1237,7 @@ arm_compute_func_type (void)
 {
   unsigned long type = ARM_FT_UNKNOWN;
   tree a;
-  tree attr;
+  attribute_list attr;
 
   if (TREE_CODE (current_function_decl) != FUNCTION_DECL)
     abort ();
@@ -1257,18 +1256,17 @@ arm_compute_func_type (void)
 
   attr = DECL_ATTRIBUTES (current_function_decl);
 
-  a = lookup_attribute ("naked", attr);
-  if (a != NULL_TREE)
+  if (has_attribute_p ("naked", attr))
     type |= ARM_FT_NAKED;
 
-  a = lookup_attribute ("isr", attr);
+  a = get_attribute ("isr", attr);
   if (a == NULL_TREE)
-    a = lookup_attribute ("interrupt", attr);
+    a = get_attribute ("interrupt", attr);
 
   if (a == NULL_TREE)
     type |= TARGET_INTERWORK ? ARM_FT_INTERWORKED : ARM_FT_NORMAL;
   else
-    type |= arm_isr_value (TREE_VALUE (a));
+    type |= arm_isr_value (a);
 
   return type;
 }
@@ -2420,9 +2418,9 @@ arm_init_cumulative_args (CUMULATIVE_ARG
      override any command line option.  */
   if (fntype)
     {
-      if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (fntype)))
+      if (has_attribute_p ("short_call", TYPE_ATTRIBUTES (fntype)))
 	pcum->call_cookie = CALL_SHORT;
-      else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (fntype)))
+      else if (has_attribute_p ("long_call", TYPE_ATTRIBUTES (fntype)))
 	pcum->call_cookie = CALL_LONG;
     }
 
@@ -2564,9 +2562,9 @@ const struct attribute_spec arm_attribut
      addressing range.  */
   { "short_call",   0, 0, false, true,  true,  NULL },
   /* Interrupt Service Routines have special prologue and epilogue requirements.  */
-  { "isr",          0, 1, false, false, false, arm_handle_isr_attribute },
-  { "interrupt",    0, 1, false, false, false, arm_handle_isr_attribute },
-  { "naked",        0, 0, true,  false, false, arm_handle_fndecl_attribute },
+  { "isr",          0, 1, false, true,  true,  arm_handle_isr_attribute },
+  { "interrupt",    0, 1, false, true,  true,  arm_handle_isr_attribute },
+  { "naked",        0, 0, true,  false, false, handle_fndecl_attribute },
 #ifdef ARM_PE
   /* ARM/PE has three new attributes:
      interfacearm - ?
@@ -2579,7 +2577,7 @@ const struct attribute_spec arm_attribut
   */
   { "dllimport",    0, 0, true,  false, false, NULL },
   { "dllexport",    0, 0, true,  false, false, NULL },
-  { "interfacearm", 0, 0, true,  false, false, arm_handle_fndecl_attribute },
+  { "interfacearm", 0, 0, true,  false, false, handle_fndecl_attribute },
 #elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
   { "dllimport",    0, 0, false, false, false, handle_dll_attribute },
   { "dllexport",    0, 0, false, false, false, handle_dll_attribute },
@@ -2587,79 +2585,18 @@ const struct attribute_spec arm_attribut
   { NULL,           0, 0, false, false, false, NULL }
 };
 
-/* Handle an attribute requiring a FUNCTION_DECL;
-   arguments as in struct attribute_spec.handler.  */
-static tree
-arm_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
-			     int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
 /* Handle an "interrupt" or "isr" attribute;
    arguments as in struct attribute_spec.handler.  */
-static tree
-arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
-			  bool *no_add_attrs)
+static void
+arm_handle_isr_attribute (tree * ARG_UNUSED (node), tree name, tree args,
+			  int ARG_UNUSED (flags),
+			  bool *no_add_attrs, bool * ARG_UNUSED (defer))
 {
-  if (DECL_P (*node))
-    {
-      if (TREE_CODE (*node) != FUNCTION_DECL)
-	{
-	  warning ("`%s' attribute only applies to functions",
-		   IDENTIFIER_POINTER (name));
-	  *no_add_attrs = true;
-	}
-      /* FIXME: the argument if any is checked for type attributes;
-	 should it be checked for decl ones?  */
-    }
-  else
+  if (arm_isr_value (args) == ARM_FT_UNKNOWN)
     {
-      if (TREE_CODE (*node) == FUNCTION_TYPE
-	  || TREE_CODE (*node) == METHOD_TYPE)
-	{
-	  if (arm_isr_value (args) == ARM_FT_UNKNOWN)
-	    {
-	      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-	      *no_add_attrs = true;
-	    }
-	}
-      else if (TREE_CODE (*node) == POINTER_TYPE
-	       && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
-		   || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
-	       && arm_isr_value (args) != ARM_FT_UNKNOWN)
-	{
-	  *node = build_variant_type_copy (*node);
-	  TREE_TYPE (*node) = build_type_attribute_variant
-	    (TREE_TYPE (*node),
-	     tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
-	  *no_add_attrs = true;
-	}
-      else
-	{
-	  /* Possibly pass this attribute on from the type to a decl.  */
-	  if (flags & ((int) ATTR_FLAG_DECL_NEXT
-		       | (int) ATTR_FLAG_FUNCTION_NEXT
-		       | (int) ATTR_FLAG_ARRAY_NEXT))
-	    {
-	      *no_add_attrs = true;
-	      return tree_cons (name, args, NULL_TREE);
-	    }
-	  else
-	    {
-	      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-	    }
-	}
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Return 0 if the attributes for two types are incompatible, 1 if they
@@ -2668,17 +2605,17 @@ arm_handle_isr_attribute (tree *node, tr
 static int
 arm_comp_type_attributes (tree type1, tree type2)
 {
-  int l1, l2, s1, s2;
+  bool l1, l2, s1, s2;
 
   /* Check for mismatch of non-default calling convention.  */
   if (TREE_CODE (type1) != FUNCTION_TYPE)
     return 1;
 
   /* Check for mismatched call attributes.  */
-  l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
-  l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
-  s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
-  s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
+  l1 = has_attribute_p ("long_call", TYPE_ATTRIBUTES (type1));
+  l2 = has_attribute_p ("long_call", TYPE_ATTRIBUTES (type2));
+  s1 = has_attribute_p ("short_call", TYPE_ATTRIBUTES (type1));
+  s2 = has_attribute_p ("short_call", TYPE_ATTRIBUTES (type2));
 
   /* Only bother to check if an attribute is defined.  */
   if (l1 | l2 | s1 | s2)
@@ -2693,12 +2630,12 @@ arm_comp_type_attributes (tree type1, tr
     }
 
   /* Check for mismatched ISR attribute.  */
-  l1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;
+  l1 = has_attribute_p ("isr", TYPE_ATTRIBUTES (type1));
   if (! l1)
-    l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL;
-  l2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL;
+    l1 = has_attribute_p ("interrupt", TYPE_ATTRIBUTES (type1));
+  l2 = has_attribute_p ("isr", TYPE_ATTRIBUTES (type2));
   if (! l2)
-    l1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL;
+    l1 = has_attribute_p ("interrupt", TYPE_ATTRIBUTES (type2));
   if (l1 != l2)
     return 0;
 
@@ -2737,18 +2674,18 @@ arm_set_default_type_attributes (tree ty
      when inside #pragma no_long_calls.  */
   if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
     {
-      tree type_attr_list, attr_name;
-      type_attr_list = TYPE_ATTRIBUTES (type);
+      struct one_attribute at;
 
       if (arm_pragma_long_calls == LONG)
- 	attr_name = get_identifier ("long_call");
+ 	at.name = get_identifier ("long_call");
       else if (arm_pragma_long_calls == SHORT)
- 	attr_name = get_identifier ("short_call");
+ 	at.name = get_identifier ("short_call");
       else
  	return;
-
-      type_attr_list = tree_cons (attr_name, NULL_TREE, type_attr_list);
-      TYPE_ATTRIBUTES (type) = type_attr_list;
+      at.value = NULL_TREE;
+      
+      TYPE_ATTRIBUTES (type) = merge_attributes_1 (TYPE_ATTRIBUTES (type),
+						   1, &at, NULL, 0);
     }
 }
 
@@ -2848,9 +2785,9 @@ arm_function_ok_for_sibcall (tree decl, 
     return false;
 
   /* Get the calling method.  */
-  if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
+  if (has_attribute_p ("short_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
     call_type = CALL_SHORT;
-  else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
+  else if (has_attribute_p ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
     call_type = CALL_LONG;
 
   /* Cannot tail-call to long calls, since these are out of range of
@@ -11298,7 +11235,7 @@ arm_debugger_arg_offset (int value, rtx 
     {									\
       if ((MASK) & insn_flags)						\
         lang_hooks.builtin_function ((NAME), (TYPE), (CODE),		\
-				     BUILT_IN_MD, NULL, NULL_TREE);	\
+				     BUILT_IN_MD, NULL, NULL);		\
     }									\
   while (0)
 
@@ -12611,7 +12548,7 @@ is_called_in_ARM_mode (tree func)
     return TRUE;
 
 #ifdef ARM_PE
-  return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
+  return has_attribute_p ("interfacearm", DECL_ATTRIBUTES (func));
 #else
   return FALSE;
 #endif
Index: gcc/config/arm/pe.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/pe.c,v
retrieving revision 1.26
diff -u -p -u -p -r1.26 pe.c
--- gcc/config/arm/pe.c	18 Sep 2004 19:19:31 -0000	1.26
+++ gcc/config/arm/pe.c	1 Oct 2004 00:57:19 -0000
@@ -48,11 +48,7 @@ arm_dllexport_p (decl)
   if (TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
-  exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
-  if (exp)
-    return 1;
-
-  return 0;
+  return has_attribute_p ("dllexport", DECL_ATTRIBUTES (decl));
 }
 
 /* Return nonzero if DECL is a dllimport'd object.  */
@@ -70,11 +66,7 @@ arm_dllimport_p (decl)
   if (TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
-  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
-  if (imp)
-    return 1;
-
-  return 0;
+  return has_attribute_p ("dllimport", DECL_ATTRIBUTES (decl));
 }
 
 /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
Index: gcc/config/avr/avr-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/avr-protos.h,v
retrieving revision 1.33
diff -u -p -u -p -r1.33 avr-protos.h
--- gcc/config/avr/avr-protos.h	15 Mar 2004 18:20:47 -0000	1.33
+++ gcc/config/avr/avr-protos.h	1 Oct 2004 00:57:19 -0000
@@ -42,7 +42,6 @@ extern void gas_output_ascii (FILE *file
 
 #ifdef TREE_CODE
 extern void asm_output_external (FILE *file, tree decl, char *name);
-extern int avr_progmem_p (tree decl, tree attributes);
 
 #ifdef RTX_CODE /* inside TREE_CODE */
 extern rtx avr_function_value (tree type, tree func);
Index: gcc/config/avr/avr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/avr.c,v
retrieving revision 1.121
diff -u -p -u -p -r1.121 avr.c
--- gcc/config/avr/avr.c	2 Sep 2004 01:04:22 -0000	1.121
+++ gcc/config/avr/avr.c	1 Oct 2004 00:57:19 -0000
@@ -60,15 +60,16 @@ static int out_adj_frame_ptr (FILE *, in
 static int out_set_stack_ptr (FILE *, int, int);
 static RTX_CODE compare_condition (rtx insn);
 static int compare_sign_p (rtx insn);
-static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
-static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+static void avr_handle_progmem_attribute (tree *, tree, tree, int, bool *,
+					  bool *);
 const struct attribute_spec avr_attribute_table[];
 static bool avr_assemble_integer (rtx, unsigned int, int);
 static void avr_file_start (void);
 static void avr_file_end (void);
 static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void avr_insert_attributes (tree, tree *);
+static attribute_count avr_add_attributes (tree, attribute_list,
+					   const struct one_attribute **);
 static unsigned int avr_section_type_flags (tree, const char *, int);
 
 static void avr_reorg (void);
@@ -232,8 +233,8 @@ int avr_case_values_threshold = 30000;
 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
+#undef TARGET_ADD_ATTRIBUTES
+#define TARGET_ADD_ATTRIBUTES avr_add_attributes
 #undef TARGET_SECTION_TYPE_FLAGS
 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
 #undef TARGET_RTX_COSTS
@@ -343,13 +344,10 @@ avr_reg_class_from_letter  (int c)
 static int
 avr_naked_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     abort ();
   
-  a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("naked", DECL_ATTRIBUTES (func));
 }
 
 /* Return nonzero if FUNC is an interrupt function as specified
@@ -358,13 +356,10 @@ avr_naked_function_p (tree func)
 static int
 interrupt_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("interrupt", DECL_ATTRIBUTES (func));
 }
 
 /* Return nonzero if FUNC is a signal function as specified
@@ -373,13 +368,10 @@ interrupt_function_p (tree func)
 static int
 signal_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("signal", DECL_ATTRIBUTES (func));
 }
 
 /* Return the number of hard registers to push/pop in the prologue/epilogue
@@ -4471,19 +4463,20 @@ const struct attribute_spec avr_attribut
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "progmem",   0, 0, false, false, false,  avr_handle_progmem_attribute },
-  { "signal",    0, 0, true,  false, false,  avr_handle_fndecl_attribute },
-  { "interrupt", 0, 0, true,  false, false,  avr_handle_fndecl_attribute },
-  { "naked",     0, 0, true,  false, false,  avr_handle_fndecl_attribute },
+  { "signal",    0, 0, true,  false, false,  handle_fndecl_attribute },
+  { "interrupt", 0, 0, true,  false, false,  handle_fndecl_attribute },
+  { "naked",     0, 0, true,  false, false,  handle_fndecl_attribute },
   { NULL,        0, 0, false, false, false, NULL }
 };
 
 /* Handle a "progmem" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 avr_handle_progmem_attribute (tree *node, tree name,
-			      tree args ATTRIBUTE_UNUSED,
+			      tree args,
 			      int flags ATTRIBUTE_UNUSED,
-			      bool *no_add_attrs)
+			      bool *no_add_attrs,
+			      bool * ARG_UNUSED (defer))
 {
   if (DECL_P (*node))
     {
@@ -4493,8 +4486,16 @@ avr_handle_progmem_attribute (tree *node
 	     but try to handle it for GCC 3.0 backwards compatibility.  */
 
 	  tree type = TREE_TYPE (*node);
-	  tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
-	  tree newtype = build_type_attribute_variant (type, attr);
+	  tree newtype;
+	  struct one_attribute attr;
+	  attribute_list new_type_at;
+
+	  attr.name = name;
+	  attr.value = args;
+	  
+	  new_type_at = merge_attributes_1 (TYPE_ATTRIBUTES (type),
+					    1, &attr, NULL, 0);
+	  newtype = build_type_attribute_variant (type, new_type_at);
 
 	  TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
 	  TREE_TYPE (*node) = newtype;
@@ -4515,42 +4516,20 @@ avr_handle_progmem_attribute (tree *node
 	  *no_add_attrs = true;
 	}
     }
-
-  return NULL_TREE;
-}
-
-/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-avr_handle_fndecl_attribute (tree *node, tree name,
-			     tree args ATTRIBUTE_UNUSED,
-			     int flags ATTRIBUTE_UNUSED,
-			     bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
 }
 
 /* Look for attribute `progmem' in DECL
    if found return 1, otherwise 0.  */
 
-int
-avr_progmem_p (tree decl, tree attributes)
+static int
+avr_progmem_p (tree decl, attribute_list attributes)
 {
   tree a;
 
   if (TREE_CODE (decl) != VAR_DECL)
     return 0;
 
-  if (NULL_TREE
-      != lookup_attribute ("progmem", attributes))
+  if (has_attribute_p ("progmem", attributes))
     return 1;
 
   a=decl;
@@ -4561,7 +4540,7 @@ avr_progmem_p (tree decl, tree attribute
   if (a == error_mark_node)
     return 0;
 
-  if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
+  if (has_attribute_p ("progmem", TYPE_ATTRIBUTES (a)))
     return 1;
   
   return 0;
@@ -4569,22 +4548,29 @@ avr_progmem_p (tree decl, tree attribute
 
 /* Add the section attribute if the variable is in progmem.  */
 
-static void
-avr_insert_attributes (tree node, tree *attributes)
+static attribute_count
+avr_add_attributes (tree node, attribute_list attributes,
+		    const struct one_attribute ** to_add)
 {
   if (TREE_CODE (node) == VAR_DECL
       && (TREE_STATIC (node) || DECL_EXTERNAL (node))
-      && avr_progmem_p (node, *attributes))
+      && avr_progmem_p (node, attributes))
     {
       static const char dsec[] = ".progmem.data";
-      *attributes = tree_cons (get_identifier ("section"),
-		build_tree_list (NULL, build_string (strlen (dsec), dsec)),
-		*attributes);
+      static struct one_attribute add;
 
       /* ??? This seems sketchy.  Why can't the user declare the
 	 thing const in the first place?  */
       TREE_READONLY (node) = 1;
+
+      *to_add = &add;
+      add.name = get_identifier ("section");
+      add.value = build_tree_list (NULL, build_string (strlen (dsec), dsec));
+
+      return 1;
     }
+  else
+    return 0;
 }
 
 static unsigned int
Index: gcc/config/c4x/c4x.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/c4x/c4x.c,v
retrieving revision 1.163
diff -u -p -u -p -r1.163 c4x.c
--- gcc/config/c4x/c4x.c	18 Sep 2004 19:19:31 -0000	1.163
+++ gcc/config/c4x/c4x.c	1 Oct 2004 00:57:19 -0000
@@ -42,7 +42,6 @@ Boston, MA 02111-1307, USA.  */
 #include "optabs.h"
 #include "libfuncs.h"
 #include "flags.h"
-#include "loop.h"
 #include "recog.h"
 #include "ggc.h"
 #include "cpplib.h"
@@ -187,14 +186,16 @@ static int c4x_arn_reg_operand (rtx, enu
 static int c4x_arn_mem_operand (rtx, enum machine_mode, unsigned int);
 static void c4x_file_start (void);
 static void c4x_file_end (void);
-static void c4x_check_attribute (const char *, tree, tree, tree *);
+static void c4x_check_attribute (const char *attrib, tree list, tree decl, 
+				 struct one_attribute * *addp);
 static int c4x_r11_set_p (rtx);
 static int c4x_rptb_valid_p (rtx, rtx);
 static void c4x_reorg (void);
 static int c4x_label_ref_used_p (rtx, rtx);
-static tree c4x_handle_fntype_attribute (tree *, tree, tree, int, bool *);
 const struct attribute_spec c4x_attribute_table[];
-static void c4x_insert_attributes (tree, tree *);
+static attribute_count c4x_add_attributes
+  (tree decl, attribute_list attributes,
+   const struct one_attribute * * to_add_p);
 static void c4x_asm_named_section (const char *, unsigned int, tree);
 static int c4x_adjust_cost (rtx, rtx, rtx, int);
 static void c4x_globalize_label (FILE *, const char *);
@@ -225,8 +226,8 @@ static tree c4x_gimplify_va_arg_expr (tr
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
 
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
+#undef TARGET_ADD_ATTRIBUTES
+#define TARGET_ADD_ATTRIBUTES c4x_add_attributes
 
 #undef TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS c4x_init_builtins
@@ -785,7 +786,7 @@ c4x_leaf_function_p (void)
      to define LEAF_REGISTERS and all that it entails.
      Let's check ourselves....  */
 
-  if (lookup_attribute ("leaf_pretend",
+  if (has_attribute_p ("leaf_pretend",
 			TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
     return 1;
 
@@ -809,7 +810,7 @@ c4x_naked_function_p (void)
   tree type;
 
   type = TREE_TYPE (current_function_decl);
-  return lookup_attribute ("naked", TYPE_ATTRIBUTES (type)) != NULL;
+  return has_attribute_p ("naked", TYPE_ATTRIBUTES (type));
 }
 
 
@@ -817,7 +818,7 @@ int
 c4x_interrupt_function_p (void)
 {
   const char *cfun_name;
-  if (lookup_attribute ("interrupt",
+  if (has_attribute_p ("interrupt",
 			TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
     return 1;
 
@@ -4443,69 +4444,61 @@ c4x_file_end (void)
 
 
 static void
-c4x_check_attribute (const char *attrib, tree list, tree decl, tree *attributes)
+c4x_check_attribute (const char *attrib, tree list, tree decl, 
+		     struct one_attribute * *addp)
 {
   while (list != NULL_TREE
          && IDENTIFIER_POINTER (TREE_PURPOSE (list))
 	 != IDENTIFIER_POINTER (DECL_NAME (decl)))
     list = TREE_CHAIN (list);
   if (list)
-    *attributes = tree_cons (get_identifier (attrib), TREE_VALUE (list),
-			     *attributes);
+    {
+      (*addp)->name = get_identifier (attrib);
+      (*addp)->value = TREE_VALUE (list);
+      (*addp)++;
+    }
 }
 
-
-static void
-c4x_insert_attributes (tree decl, tree *attributes)
+static attribute_count
+c4x_add_attributes (tree decl, attribute_list ARG_UNUSED (attributes),
+		    const struct one_attribute * * to_add_p)
 {
+  static struct one_attribute to_add[5];
+  struct one_attribute * addp = to_add;
+  
+  *to_add_p = to_add;
+  
   switch (TREE_CODE (decl))
     {
     case FUNCTION_DECL:
-      c4x_check_attribute ("section", code_tree, decl, attributes);
-      c4x_check_attribute ("const", pure_tree, decl, attributes);
-      c4x_check_attribute ("noreturn", noreturn_tree, decl, attributes);
-      c4x_check_attribute ("interrupt", interrupt_tree, decl, attributes);
-      c4x_check_attribute ("naked", naked_tree, decl, attributes);
+      c4x_check_attribute ("section", code_tree, decl, &addp);
+      c4x_check_attribute ("const", pure_tree, decl, &addp);
+      c4x_check_attribute ("noreturn", noreturn_tree, decl, &addp);
+      c4x_check_attribute ("interrupt", interrupt_tree, decl, &addp);
+      c4x_check_attribute ("naked", naked_tree, decl, &addp);
       break;
 
     case VAR_DECL:
-      c4x_check_attribute ("section", data_tree, decl, attributes);
+      c4x_check_attribute ("section", data_tree, decl, &addp);
       break;
 
     default:
       break;
     }
+
+  return addp - to_add;
 }
 
 /* Table of valid machine attributes.  */
 const struct attribute_spec c4x_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt",    0, 0, false, true,  true,  c4x_handle_fntype_attribute },
-  { "naked",    0, 0, false, true,  true,  c4x_handle_fntype_attribute },
-  { "leaf_pretend", 0, 0, false, true,  true,  c4x_handle_fntype_attribute },
+  { "interrupt",    0, 0, false, true,  true,  NULL },
+  { "naked",        0, 0, false, true,  true,  NULL },
+  { "leaf_pretend", 0, 0, false, true,  true,  NULL },
   { NULL,           0, 0, false, false, false, NULL }
 };
 
-/* Handle an attribute requiring a FUNCTION_TYPE;
-   arguments as in struct attribute_spec.handler.  */
-static tree
-c4x_handle_fntype_attribute (tree *node, tree name,
-			     tree args ATTRIBUTE_UNUSED,
-			     int flags ATTRIBUTE_UNUSED,
-			     bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_TYPE)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-
 /* !!! FIXME to emit RPTS correctly.  */
 
 int
@@ -4768,14 +4761,13 @@ c4x_init_builtins (void)
 			       (integer_type_node,
 				tree_cons (NULL_TREE, double_type_node,
 					   endlink)),
-			       C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL_TREE);
+			       C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL);
   lang_hooks.builtin_function ("ansi_ftoi",
 			       build_function_type 
 			       (integer_type_node, 
 				tree_cons (NULL_TREE, double_type_node,
 					   endlink)),
-			       C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL,
-			       NULL_TREE);
+			       C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL, NULL);
   if (TARGET_C3X)
     lang_hooks.builtin_function ("fast_imult",
 				 build_function_type
@@ -4784,8 +4776,7 @@ c4x_init_builtins (void)
 					     tree_cons (NULL_TREE,
 							integer_type_node,
 							endlink))),
-				 C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL,
-				 NULL_TREE);
+				 C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL, NULL);
   else
     {
       lang_hooks.builtin_function ("toieee",
@@ -4794,21 +4785,21 @@ c4x_init_builtins (void)
 				    tree_cons (NULL_TREE, double_type_node,
 					       endlink)),
 				   C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL,
-				   NULL_TREE);
+				   NULL);
       lang_hooks.builtin_function ("frieee",
 				   build_function_type
 				   (double_type_node, 
 				    tree_cons (NULL_TREE, double_type_node,
 					       endlink)),
 				   C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL,
-				   NULL_TREE);
+				   NULL);
       lang_hooks.builtin_function ("fast_invf",
 				   build_function_type 
 				   (double_type_node, 
 				    tree_cons (NULL_TREE, double_type_node,
 					       endlink)),
 				   C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL,
-				   NULL_TREE);
+				   NULL);
     }
 }
 
Index: gcc/config/frv/frv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/frv/frv.c,v
retrieving revision 1.71
diff -u -p -u -p -r1.71 frv.c
--- gcc/config/frv/frv.c	28 Sep 2004 07:59:52 -0000	1.71
+++ gcc/config/frv/frv.c	1 Oct 2004 00:57:20 -0000
@@ -5495,7 +5495,7 @@ frv_emit_movsi (rtx dest, rtx src)
 		    reloc = compute_reloc_for_constant (init);
 		  
 		  named_section = TREE_CODE (decl) == VAR_DECL
-		    && lookup_attribute ("section", DECL_ATTRIBUTES (decl));
+		    && has_attribute_p ("section", DECL_ATTRIBUTES (decl));
 		  readonly = decl_readonly_section (decl, reloc);
 		  
 		  if (named_section)
Index: gcc/config/h8300/h8300.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.c,v
retrieving revision 1.292
diff -u -p -u -p -r1.292 h8300.c
--- gcc/config/h8300/h8300.c	15 Sep 2004 17:03:03 -0000	1.292
+++ gcc/config/h8300/h8300.c	1 Oct 2004 00:57:20 -0000
@@ -110,9 +110,10 @@ static void push (int);
 static void pop (int);
 static const char *cond_string (enum rtx_code);
 static unsigned int h8300_asm_insn_count (const char *);
-static tree h8300_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
-static tree h8300_handle_eightbit_data_attribute (tree *, tree, tree, int, bool *);
-static tree h8300_handle_tiny_data_attribute (tree *, tree, tree, int, bool *);
+static void h8300_handle_eightbit_data_attribute (tree *, tree, tree, int,
+						  bool *, bool *);
+static void h8300_handle_tiny_data_attribute (tree *, tree, tree, int, bool *,
+					      bool *);
 #ifndef OBJECT_FORMAT_ELF
 static void h8300_asm_named_section (const char *, unsigned int, tree);
 #endif
@@ -5584,13 +5585,10 @@ fix_bit_operand (rtx *operands, enum rtx
 static int
 h8300_interrupt_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("interrupt_handler", DECL_ATTRIBUTES (func));
 }
 
 /* Return nonzero if FUNC is a saveall function as specified by the
@@ -5599,13 +5597,10 @@ h8300_interrupt_function_p (tree func)
 static int
 h8300_saveall_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("saveall", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("saveall", DECL_ATTRIBUTES (func));
 }
 
 /* Return nonzero if FUNC is an OS_Task function as specified
@@ -5614,13 +5609,10 @@ h8300_saveall_function_p (tree func)
 static int
 h8300_os_task_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("OS_Task", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("OS_Task", DECL_ATTRIBUTES (func));
 }
 
 /* Return nonzero if FUNC is a monitor function as specified
@@ -5629,13 +5621,10 @@ h8300_os_task_function_p (tree func)
 static int
 h8300_monitor_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("monitor", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("monitor", DECL_ATTRIBUTES (func));
 }
 
 /* Return nonzero if FUNC is a function that should be called
@@ -5644,13 +5633,10 @@ h8300_monitor_function_p (tree func)
 int
 h8300_funcvec_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("function_vector", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("function_vector", DECL_ATTRIBUTES (func));
 }
 
 /* Return nonzero if DECL is a variable that's in the eight bit
@@ -5659,13 +5645,10 @@ h8300_funcvec_function_p (tree func)
 int
 h8300_eightbit_data_p (tree decl)
 {
-  tree a;
-
   if (TREE_CODE (decl) != VAR_DECL)
     return 0;
 
-  a = lookup_attribute ("eightbit_data", DECL_ATTRIBUTES (decl));
-  return a != NULL_TREE;
+  return has_attribute_p ("eightbit_data", DECL_ATTRIBUTES (decl));
 }
 
 /* Return nonzero if DECL is a variable that's in the tiny
@@ -5674,21 +5657,22 @@ h8300_eightbit_data_p (tree decl)
 int
 h8300_tiny_data_p (tree decl)
 {
-  tree a;
-
   if (TREE_CODE (decl) != VAR_DECL)
     return 0;
 
-  a = lookup_attribute ("tiny_data", DECL_ATTRIBUTES (decl));
-  return a != NULL_TREE;
+  return has_attribute_p ("tiny_data", DECL_ATTRIBUTES (decl));
 }
 
 /* Generate an 'interrupt_handler' attribute for decls.  We convert
    all the pragmas to corresponding attributes.  */
 
-static void
-h8300_insert_attributes (tree node, tree *attributes)
+static attribute_count
+h8300_add_attributes (tree node, attribute_list ARG_UNUSED (attrs),
+		      const struct one_attribute **to_add)
 {
+  static struct one_attribute at[2];
+  attribute_count ac = 0;
+  
   if (TREE_CODE (node) == FUNCTION_DECL)
     {
       if (pragma_interrupt)
@@ -5696,8 +5680,7 @@ h8300_insert_attributes (tree node, tree
 	  pragma_interrupt = 0;
 
 	  /* Add an 'interrupt_handler' attribute.  */
-	  *attributes = tree_cons (get_identifier ("interrupt_handler"),
-				   NULL, *attributes);
+	  at[ac++].name = get_identifier ("interrupt_handler");
 	}
 
       if (pragma_saveall)
@@ -5705,10 +5688,12 @@ h8300_insert_attributes (tree node, tree
 	  pragma_saveall = 0;
 
 	  /* Add an 'saveall' attribute.  */
-	  *attributes = tree_cons (get_identifier ("saveall"),
-				   NULL, *attributes);
+	  at[ac++].name = get_identifier ("saveall");
 	}
     }
+  
+  *to_add = at;
+  return ac;
 }
 
 /* Supported attributes:
@@ -5731,42 +5716,25 @@ h8300_insert_attributes (tree node, tree
 const struct attribute_spec h8300_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt_handler", 0, 0, true,  false, false, h8300_handle_fndecl_attribute },
-  { "saveall",           0, 0, true,  false, false, h8300_handle_fndecl_attribute },
-  { "OS_Task",           0, 0, true,  false, false, h8300_handle_fndecl_attribute },
-  { "monitor",           0, 0, true,  false, false, h8300_handle_fndecl_attribute },
-  { "function_vector",   0, 0, true,  false, false, h8300_handle_fndecl_attribute },
+  { "interrupt_handler", 0, 0, true,  false, false, handle_fndecl_attribute },
+  { "saveall",           0, 0, true,  false, false, handle_fndecl_attribute },
+  { "OS_Task",           0, 0, true,  false, false, handle_fndecl_attribute },
+  { "monitor",           0, 0, true,  false, false, handle_fndecl_attribute },
+  { "function_vector",   0, 0, true,  false, false, handle_fndecl_attribute },
   { "eightbit_data",     0, 0, true,  false, false, h8300_handle_eightbit_data_attribute },
   { "tiny_data",         0, 0, true,  false, false, h8300_handle_tiny_data_attribute },
   { NULL,                0, 0, false, false, false, NULL }
 };
 
 
-/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
-   struct attribute_spec.handler.  */
-static tree
-h8300_handle_fndecl_attribute (tree *node, tree name,
-			       tree args ATTRIBUTE_UNUSED,
-			       int flags ATTRIBUTE_UNUSED,
-			       bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
 /* Handle an "eightbit_data" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 h8300_handle_eightbit_data_attribute (tree *node, tree name,
 				      tree args ATTRIBUTE_UNUSED,
 				      int flags ATTRIBUTE_UNUSED,
-				      bool *no_add_attrs)
+				      bool *no_add_attrs,
+				      bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -5779,17 +5747,16 @@ h8300_handle_eightbit_data_attribute (tr
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle an "tiny_data" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 h8300_handle_tiny_data_attribute (tree *node, tree name,
 				  tree args ATTRIBUTE_UNUSED,
 				  int flags ATTRIBUTE_UNUSED,
-				  bool *no_add_attrs)
+				  bool *no_add_attrs,
+				  bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -5802,8 +5769,6 @@ h8300_handle_tiny_data_attribute (tree *
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Mark function vectors, and various small data objects.  */
@@ -6226,8 +6191,8 @@ h8300_return_in_memory (tree type, tree 
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO h8300_encode_section_info
 
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES h8300_insert_attributes
+#undef TARGET_ADD_ATTRIBUTES
+#define TARGET_ADD_ATTRIBUTES h8300_add_attributes
 
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS h8300_rtx_costs
Index: gcc/config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.119
diff -u -p -u -p -r1.119 i386-protos.h
--- gcc/config/i386/i386-protos.h	15 Sep 2004 17:03:05 -0000	1.119
+++ gcc/config/i386/i386-protos.h	1 Oct 2004 00:57:20 -0000
@@ -203,7 +203,8 @@ extern int ix86_return_pops_args (tree, 
 extern int ix86_data_alignment (tree, int);
 extern int ix86_local_alignment (tree, int);
 extern int ix86_constant_alignment (tree, int);
-extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
+extern void ix86_handle_shared_attribute (tree *, tree, tree, int, bool *,
+					  bool *);
 
 extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
 extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
Index: gcc/config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.733
diff -u -p -u -p -r1.733 i386.c
--- gcc/config/i386/i386.c	29 Sep 2004 09:47:52 -0000	1.733
+++ gcc/config/i386/i386.c	1 Oct 2004 00:57:20 -0000
@@ -909,13 +909,16 @@ static int ix86_comp_type_attributes (tr
 static int ix86_function_regparm (tree, tree);
 const struct attribute_spec ix86_attribute_table[];
 static bool ix86_function_ok_for_sibcall (tree, tree);
-static tree ix86_handle_cdecl_attribute (tree *, tree, tree, int, bool *);
-static tree ix86_handle_regparm_attribute (tree *, tree, tree, int, bool *);
+static void ix86_handle_cdecl_attribute (tree *, tree, tree, int, bool *,
+					 bool *);
+static void ix86_handle_regparm_attribute (tree *, tree, tree, int, bool *,
+					   bool *);
 static int ix86_value_regno (enum machine_mode);
 static bool contains_128bit_aligned_vector_p (tree);
 static rtx ix86_struct_value_rtx (tree, int);
 static bool ix86_ms_bitfield_layout_p (tree);
-static tree ix86_handle_struct_attribute (tree *, tree, tree, int, bool *);
+static void ix86_handle_struct_attribute (tree *, tree, tree, int, bool *,
+					  bool *);
 static int extended_reg_mentioned_1 (rtx *, void *);
 static bool ix86_rtx_costs (rtx, int, int, int *);
 static int min_insn_size (rtx);
@@ -1078,9 +1081,9 @@ static void init_ext_80387_constants (vo
 #undef TARGET_VECTOR_MODE_SUPPORTED_P
 #define TARGET_VECTOR_MODE_SUPPORTED_P ix86_vector_mode_supported_p
 
-#ifdef SUBTARGET_INSERT_ATTRIBUTES
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
+#ifdef SUBTARGET_ADD_ATTRIBUTES
+#undef TARGET_ADD_ATTRIBUTES
+#define TARGET_ADD_ATTRIBUTES SUBTARGET_ADD_ATTRIBUTES
 #endif
 
 struct gcc_target targetm = TARGET_INITIALIZER;
@@ -1672,10 +1675,11 @@ ix86_function_ok_for_sibcall (tree decl,
 
 /* Handle a "cdecl", "stdcall", or "fastcall" attribute;
    arguments as in struct attribute_spec.handler.  */
-static tree
+static void
 ix86_handle_cdecl_attribute (tree *node, tree name,
 			     tree args ATTRIBUTE_UNUSED,
-			     int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+			     int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+			     bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) != FUNCTION_TYPE
       && TREE_CODE (*node) != METHOD_TYPE
@@ -1690,18 +1694,18 @@ ix86_handle_cdecl_attribute (tree *node,
     {
       if (is_attribute_p ("fastcall", name))
         {
-          if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (*node)))
+          if (has_attribute_p ("stdcall", TYPE_ATTRIBUTES (*node)))
             {
               error ("fastcall and stdcall attributes are not compatible");
             }
-           else if (lookup_attribute ("regparm", TYPE_ATTRIBUTES (*node)))
+           else if (has_attribute_p ("regparm", TYPE_ATTRIBUTES (*node)))
             {
               error ("fastcall and regparm attributes are not compatible");
             }
         }
       else if (is_attribute_p ("stdcall", name))
         {
-          if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
+          if (has_attribute_p ("fastcall", TYPE_ATTRIBUTES (*node)))
             {
               error ("fastcall and stdcall attributes are not compatible");
             }
@@ -1713,15 +1717,14 @@ ix86_handle_cdecl_attribute (tree *node,
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle a "regparm" attribute;
    arguments as in struct attribute_spec.handler.  */
-static tree
+static void
 ix86_handle_regparm_attribute (tree *node, tree name, tree args,
-			       int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+			       int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+			       bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) != FUNCTION_TYPE
       && TREE_CODE (*node) != METHOD_TYPE
@@ -1750,13 +1753,11 @@ ix86_handle_regparm_attribute (tree *nod
 	  *no_add_attrs = true;
 	}
 
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (*node)))
+      if (has_attribute_p ("fastcall", TYPE_ATTRIBUTES (*node)))
 	{
 	  error ("fastcall and regparm attributes are not compatible");
 	}
     }
-
-  return NULL_TREE;
 }
 
 /* Return 0 if the attributes for two types are incompatible, 1 if they
@@ -1773,13 +1774,13 @@ ix86_comp_type_attributes (tree type1, t
     return 1;
 
   /*  Check for mismatched fastcall types */
-  if (!lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type1))
-      != !lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type2)))
+  if (!has_attribute_p ("fastcall", TYPE_ATTRIBUTES (type1))
+      != !has_attribute_p ("fastcall", TYPE_ATTRIBUTES (type2)))
     return 0;
 
   /* Check for mismatched return types (cdecl vs stdcall).  */
-  if (!lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type1))
-      != !lookup_attribute (rtdstr, TYPE_ATTRIBUTES (type2)))
+  if (!has_attribute_p (rtdstr, TYPE_ATTRIBUTES (type1))
+      != !has_attribute_p (rtdstr, TYPE_ATTRIBUTES (type2)))
     return 0;
   if (ix86_function_regparm (type1, NULL)
       != ix86_function_regparm (type2, NULL))
@@ -1800,14 +1801,14 @@ ix86_function_regparm (tree type, tree d
 
   if (!TARGET_64BIT)
     {
-      attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+      attr = get_attribute ("regparm", TYPE_ATTRIBUTES (type));
       if (attr)
 	{
-	  regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+	  regparm = TREE_INT_CST_LOW (TREE_VALUE (attr));
 	  user_convention = true;
 	}
 
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+      if (has_attribute_p ("fastcall", TYPE_ATTRIBUTES (type)))
 	{
 	  regparm = 2;
 	  user_convention = true;
@@ -1871,12 +1872,12 @@ ix86_return_pops_args (tree fundecl, tre
   int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
 
   /* Cdecl functions override -mrtd, and never pop the stack.  */
-  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
+  if (! has_attribute_p ("cdecl", TYPE_ATTRIBUTES (funtype))) {
 
     /* Stdcall and fastcall functions will pop the stack if not
        variable args.  */
-    if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
-        || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
+    if (has_attribute_p ("stdcall", TYPE_ATTRIBUTES (funtype))
+        || has_attribute_p ("fastcall", TYPE_ATTRIBUTES (funtype)))
       rtd = 1;
 
     if (rtd
@@ -1976,7 +1977,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
   /* Use ecx and edx registers if function has fastcall attribute */
   if (fntype && !TARGET_64BIT)
     {
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
+      if (has_attribute_p ("fastcall", TYPE_ATTRIBUTES (fntype)))
 	{
 	  cum->nregs = 2;
 	  cum->fastcall = 1;
@@ -11860,7 +11861,7 @@ do {									\
   if ((MASK) & target_flags						\
       && (!((MASK) & MASK_64BIT) || TARGET_64BIT))			\
     lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,	\
-				 NULL, NULL_TREE);			\
+				 NULL, NULL);				\
 } while (0)
 
 struct builtin_description
@@ -14493,10 +14494,11 @@ x86_order_regs_for_local_alloc (void)
 
 /* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 ix86_handle_struct_attribute (tree *node, tree name,
 			      tree args ATTRIBUTE_UNUSED,
-			      int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+			      int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+			      bool * ARG_UNUSED (defer))
 {
   tree *type = NULL;
   if (DECL_P (*node))
@@ -14515,24 +14517,22 @@ ix86_handle_struct_attribute (tree *node
     }
 
   else if ((is_attribute_p ("ms_struct", name)
-	    && lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type)))
+	    && has_attribute_p ("gcc_struct", TYPE_ATTRIBUTES (*type)))
 	   || ((is_attribute_p ("gcc_struct", name)
-		&& lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type)))))
+		&& has_attribute_p ("ms_struct", TYPE_ATTRIBUTES (*type)))))
     {
       warning ("`%s' incompatible attribute ignored",
                IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 static bool
 ix86_ms_bitfield_layout_p (tree record_type)
 {
   return (TARGET_USE_MS_BITFIELD_LAYOUT &&
-	  !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))
-    || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));
+	  !has_attribute_p ("gcc_struct", TYPE_ATTRIBUTES (record_type)))
+    || has_attribute_p ("ms_struct", TYPE_ATTRIBUTES (record_type));
 }
 
 /* Returns an expression indicating where the this parameter is
@@ -14563,7 +14563,7 @@ x86_this_parameter (tree function)
       if (parm)
 	{
 	  int regno = 0;
-	  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+	  if (has_attribute_p ("fastcall", TYPE_ATTRIBUTES (type)))
 	    regno = 2;
 	  return gen_rtx_REG (SImode, regno);
 	}
@@ -14660,7 +14660,7 @@ x86_output_mi_thunk (FILE *file ATTRIBUT
       else
 	{
 	  int tmp_regno = 2 /* ECX */;
-	  if (lookup_attribute ("fastcall",
+	  if (has_attribute_p ("fastcall",
 	      TYPE_ATTRIBUTES (TREE_TYPE (function))))
 	    tmp_regno = 0 /* EAX */;
 	  tmp = gen_rtx_REG (SImode, tmp_regno);
Index: gcc/config/i386/netware.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/netware.c,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 netware.c
--- gcc/config/i386/netware.c	3 Sep 2004 18:09:26 -0000	1.1
+++ gcc/config/i386/netware.c	1 Oct 2004 00:57:20 -0000
@@ -169,18 +169,18 @@ i386_nlm_encode_section_info (tree decl,
       rtx rtlname = XEXP (rtl, 0);
       if (GET_CODE (rtlname) == MEM)
 	rtlname = XEXP (rtlname, 0);
-      if (lookup_attribute ("stdcall", type_attributes))
+      if (has_attribute_p ("stdcall", type_attributes))
 	XSTR (rtlname, 0) = gen_stdcall_decoration (decl);
-      else if (lookup_attribute ("fastcall", type_attributes))
+      else if (has_attribute_p ("fastcall", type_attributes))
 	XSTR (rtlname, 0) = gen_fastcall_decoration (decl);
       else
 	{
-	  tree attr = lookup_attribute ("regparm", type_attributes);
+	  tree attr = get_attribute ("regparm", type_attributes);
 
 	  if (attr)
 	    XSTR (rtlname, 0) =
 	      gen_regparm_prefix (decl,
-		      TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
+		      TREE_INT_CST_LOW (TREE_VALUE (attr)));
 	}
     }
 }
Index: gcc/config/i386/sol2.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/sol2.h,v
retrieving revision 1.30
diff -u -p -u -p -r1.30 sol2.h
--- gcc/config/i386/sol2.h	25 Jul 2004 18:10:03 -0000	1.30
+++ gcc/config/i386/sol2.h	1 Oct 2004 00:57:20 -0000
@@ -82,7 +82,7 @@ Boston, MA 02111-1307, USA.  */
 
 /* Solaris-specific #pragmas are implemented on top of attributes.  Hook in
    the bits from config/sol2.c.  */
-#define SUBTARGET_INSERT_ATTRIBUTES solaris_insert_attributes
+#define SUBTARGET_ADD_ATTRIBUTES solaris_add_attributes
 #define SUBTARGET_ATTRIBUTE_TABLE SOLARIS_ATTRIBUTE_TABLE
 
 /* Output a simple call for .init/.fini.  */
Index: gcc/config/i386/winnt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/winnt.c,v
retrieving revision 1.74
diff -u -p -u -p -r1.74 winnt.c
--- gcc/config/i386/winnt.c	18 Sep 2004 19:19:35 -0000	1.74
+++ gcc/config/i386/winnt.c	1 Oct 2004 00:57:20 -0000
@@ -64,10 +64,11 @@ static void i386_pe_mark_dllimport (tree
 
 /* Handle a "shared" attribute;
    arguments as in struct attribute_spec.handler.  */
-tree
+void
 ix86_handle_shared_attribute (tree *node, tree name,
 			      tree args ATTRIBUTE_UNUSED,
-			      int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+			      int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+			      bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) != VAR_DECL)
     {
@@ -75,8 +76,6 @@ ix86_handle_shared_attribute (tree *node
 	       IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Return the type that we should use to determine if DECL is
@@ -110,21 +109,17 @@ associated_type (tree decl)
 static int
 i386_pe_dllexport_p (tree decl)
 {
-  tree exp;
-
   if (TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
-  exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
-  if (exp)
+  if (has_attribute_p ("dllexport", DECL_ATTRIBUTES (decl)))
     return 1;
 
   /* Class members get the dllexport status of their class.  */
   if (associated_type (decl))
     {
-      exp = lookup_attribute ("dllexport",
-			      TYPE_ATTRIBUTES (associated_type (decl)));
-      if (exp)
+      if (has_attribute_p ("dllexport",
+			   TYPE_ATTRIBUTES (associated_type (decl)))
 	return 1;
     }
 
@@ -136,7 +131,7 @@ i386_pe_dllexport_p (tree decl)
 static int
 i386_pe_dllimport_p (tree decl)
 {
-  tree imp;
+  bool imp;
   int context_imp = 0;
 
   if (TREE_CODE (decl) == FUNCTION_DECL
@@ -147,12 +142,12 @@ i386_pe_dllimport_p (tree decl)
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
 
-  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
+  imp = has_attribute_p ("dllimport", DECL_ATTRIBUTES (decl));
 
   /* Class members get the dllimport status of their class.  */
   if (!imp && associated_type (decl))
     {
-      imp = lookup_attribute ("dllimport",
+      imp = has_attribute_p ("dllimport",
 			      TYPE_ATTRIBUTES (associated_type (decl)));
       if (imp)
 	context_imp = 1;
@@ -393,9 +388,9 @@ i386_pe_encode_section_info (tree decl, 
       tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
       tree newid = NULL_TREE;
 
-      if (lookup_attribute ("stdcall", type_attributes))
+      if (has_attribute_p ("stdcall", type_attributes))
 	newid = gen_stdcall_or_fastcall_suffix (decl, false);
-      else if (lookup_attribute ("fastcall", type_attributes))
+      else if (has_attribute_p ("fastcall", type_attributes))
 	newid = gen_stdcall_or_fastcall_suffix (decl, true);
       if (newid != NULL_TREE) 	
 	{
@@ -597,7 +592,7 @@ i386_pe_section_type_flags (tree decl, c
       flags = SECTION_WRITE;
 
       if (decl && TREE_CODE (decl) == VAR_DECL
-	  && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
+	  && has_attribute_p ("shared", DECL_ATTRIBUTES (decl)))
 	flags |= SECTION_PE_SHARED;
     }
 
Index: gcc/config/ia64/ia64.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.c,v
retrieving revision 1.326
diff -u -p -u -p -r1.326 ia64.c
--- gcc/config/ia64/ia64.c	28 Sep 2004 21:17:53 -0000	1.326
+++ gcc/config/ia64/ia64.c	1 Oct 2004 00:57:21 -0000
@@ -272,7 +272,8 @@ static void ia64_sysv4_init_libfuncs (vo
 static void ia64_vms_init_libfuncs (void)
      ATTRIBUTE_UNUSED;
 
-static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
+static void ia64_handle_model_attribute (tree *, tree, tree, int, bool *,
+					 bool *);
 static void ia64_encode_section_info (tree, rtx, int);
 static rtx ia64_struct_value_rtx (tree, int);
 static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
@@ -449,21 +450,23 @@ ia64_get_addr_area (tree decl)
 {
   tree model_attr;
 
-  model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
+  model_attr = get_attribute ("model", DECL_ATTRIBUTES (decl));
   if (model_attr)
     {
       tree id;
 
       init_idents ();
-      id = TREE_VALUE (TREE_VALUE (model_attr));
+      id = TREE_VALUE (model_attr);
       if (id == small_ident1 || id == small_ident2)
 	return ADDR_AREA_SMALL;
     }
   return ADDR_AREA_NORMAL;
 }
 
-static tree
-ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+static void
+ia64_handle_model_attribute (tree *node, tree name, tree args,
+			     int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+			     bool * ARG_UNUSED (defer))
 {
   ia64_addr_area addr_area = ADDR_AREA_NORMAL;
   ia64_addr_area area;
@@ -513,8 +516,6 @@ ia64_handle_model_attribute (tree *node,
       *no_add_attrs = true;
       break;
     }
-
-  return NULL_TREE;
 }
 
 static void
@@ -1482,7 +1483,7 @@ ia64_compute_frame_size (HOST_WIDE_INT s
      the caller.  */
 
   if (cfun->machine->n_varargs > 0
-      || lookup_attribute ("syscall_linkage",
+      || has_attribute_p ("syscall_linkage",
 			   TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
     current_frame_info.n_input_regs = 8;
   else
@@ -3370,7 +3371,7 @@ ia64_function_ok_for_sibcall (tree decl,
 {
   /* We can't perform a sibcall if the current function has the syscall_linkage
      attribute.  */
-  if (lookup_attribute ("syscall_linkage",
+  if (has_attribute_p ("syscall_linkage",
 			TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
     return false;
 
@@ -7135,7 +7136,7 @@ ia64_epilogue_uses (int regno)
 	 which in turn makes it possible to restart a system call after
 	 an interrupt without having to save/restore the input registers.
 	 This also prevents kernel data from leaking to application code.  */
-      return lookup_attribute ("syscall_linkage",
+      return has_attribute_p ("syscall_linkage",
 	   TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) != NULL;
 
     case R_BR (0):
@@ -7594,7 +7595,7 @@ ia64_init_builtins (void)
 
 #define def_builtin(name, type, code)					\
   lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD,	\
-			       NULL, NULL_TREE)
+			       NULL, NULL)
 
   def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
 	       IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
Index: gcc/config/ip2k/ip2k.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ip2k/ip2k.c,v
retrieving revision 1.40
diff -u -p -u -p -r1.40 ip2k.c
--- gcc/config/ip2k/ip2k.c	12 Aug 2004 13:56:51 -0000	1.40
+++ gcc/config/ip2k/ip2k.c	1 Oct 2004 00:57:21 -0000
@@ -76,8 +76,8 @@ static void ip2k_reorg (void);
 static int ip2k_check_can_adjust_stack_ref (rtx, int);
 static void ip2k_adjust_stack_ref (rtx *, int);
 static int ip2k_xexp_not_uses_reg_for_mem (rtx, unsigned int);
-static tree ip2k_handle_progmem_attribute (tree *, tree, tree, int, bool *);
-static tree ip2k_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+static void ip2k_handle_progmem_attribute (tree *, tree, tree, int, bool *,
+					   bool *);
 static bool ip2k_rtx_costs (rtx, int, int, int *);
 static int ip2k_address_cost (rtx);
 static void ip2k_init_libfuncs (void);
@@ -187,13 +187,10 @@ ip2k_return_pops_args (tree fundecl ATTR
 static int
 ip2k_naked_function_p (tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     abort ();
   
-  a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
-  return a != NULL_TREE;
+  return has_attribute_p ("naked", DECL_ATTRIBUTES (func));
 }
 
 /* Output function prologue.  */
@@ -3122,17 +3119,18 @@ const struct attribute_spec ip2k_attribu
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "progmem",   0, 0, false, false, false,  ip2k_handle_progmem_attribute },
-  { "naked",     0, 0, true,  false, false,  ip2k_handle_fndecl_attribute },
+  { "naked",     0, 0, true,  false, false,  handle_fndecl_attribute },
   { NULL,        0, 0, false, false, false, NULL }
 };
 
 /* Handle a "progmem" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 ip2k_handle_progmem_attribute (tree *node, tree name,
 			       tree args ATTRIBUTE_UNUSED,
 			       int flags ATTRIBUTE_UNUSED,
-			       bool *no_add_attrs)
+			       bool *no_add_attrs,
+			       bool * ARG_UNUSED (defer))
 {
   if (DECL_P (*node))
     {
@@ -3142,8 +3140,16 @@ ip2k_handle_progmem_attribute (tree *nod
 	     but try to handle it for GCC 3.0 backwards compatibility.  */
 
 	  tree type = TREE_TYPE (*node);
-	  tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
-	  tree newtype = build_type_attribute_variant (type, attr);
+	  tree newtype;
+	  struct one_attribute attr;
+	  attribute_list new_type_at;
+
+	  attr.name = name;
+	  attr.value = args;
+	  
+	  new_type_at = merge_attributes_1 (TYPE_ATTRIBUTES (type),
+					    1, &attr, NULL, 0);
+	  newtype = build_type_attribute_variant (type, new_type_at);
 
 	  TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
 	  TREE_TYPE (*node) = newtype;
@@ -3164,26 +3170,6 @@ ip2k_handle_progmem_attribute (tree *nod
 	  *no_add_attrs = true;
 	}
     }
-
-  return NULL_TREE;
-}
-
-/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
-   struct attribute_spec.handler.  */
-static tree
-ip2k_handle_fndecl_attribute (tree *node, tree name,
-			      tree args ATTRIBUTE_UNUSED,
-			      int flags ATTRIBUTE_UNUSED,
-			      bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
 }
 
 /* Cost functions.  */
Index: gcc/config/iq2000/iq2000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/iq2000/iq2000.c,v
retrieving revision 1.28
diff -u -p -u -p -r1.28 iq2000.c
--- gcc/config/iq2000/iq2000.c	18 Sep 2004 19:19:35 -0000	1.28
+++ gcc/config/iq2000/iq2000.c	1 Oct 2004 00:57:21 -0000
@@ -2689,7 +2689,7 @@ iq2000_output_conditional_branch (rtx in
 
 #define def_builtin(NAME, TYPE, CODE)					\
   lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,	\
-			       NULL, NULL_TREE)
+			       NULL, NULL)
 
 static void
 iq2000_init_builtins (void)
Index: gcc/config/m32r/m32r.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m32r/m32r.c,v
retrieving revision 1.106
diff -u -p -u -p -r1.106 m32r.c
--- gcc/config/m32r/m32r.c	26 Aug 2004 13:03:02 -0000	1.106
+++ gcc/config/m32r/m32r.c	1 Oct 2004 00:57:21 -0000
@@ -84,7 +84,8 @@ static void  init_reg_tables (void);
 static void  block_move_call (rtx, rtx, rtx);
 static int   m32r_is_insn (rtx);
 const struct attribute_spec m32r_attribute_table[];
-static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
+static void  m32r_handle_model_attribute (tree *, tree, tree, int, bool *,
+					  bool *);
 static void  m32r_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void  m32r_output_function_epilogue (FILE *, HOST_WIDE_INT);
 
@@ -336,10 +337,11 @@ const struct attribute_spec m32r_attribu
 
 /* Handle an "model" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 m32r_handle_model_attribute (tree *node ATTRIBUTE_UNUSED, tree name,
 			     tree args, int flags ATTRIBUTE_UNUSED,
-			     bool *no_add_attrs)
+			     bool *no_add_attrs,
+			     bool * ARG_UNUSED (defer))
 {
   tree arg;
 
@@ -357,8 +359,6 @@ m32r_handle_model_attribute (tree *node 
 	       IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Encode section information of DECL, which is either a VAR_DECL,
@@ -382,14 +382,14 @@ m32r_encode_section_info (tree decl, rtx
   if (!DECL_P (decl))
     return;
 
-  model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
+  model_attr = get_attribute ("model", DECL_ATTRIBUTES (decl));
   if (model_attr)
     {
       tree id;
 
       init_idents ();
 
-      id = TREE_VALUE (TREE_VALUE (model_attr));
+      id = TREE_VALUE (model_attr);
 
       if (id == small_ident1 || id == small_ident2)
 	model = M32R_MODEL_SMALL;
@@ -435,7 +435,7 @@ m32r_in_small_data_p (tree decl)
   if (TREE_CODE (decl) != VAR_DECL)
     return false;
 
-  if (lookup_attribute ("model", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("model", DECL_ATTRIBUTES (decl)))
     return false;
 
   section = DECL_SECTION_NAME (decl);
@@ -1506,7 +1506,7 @@ m32r_compute_function_type (tree decl)
     return fn_type;
 
   /* Compute function type.  */
-  fn_type = (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE
+  fn_type = (has_attribute_p ("interrupt", DECL_ATTRIBUTES (current_function_decl))
 	     ? M32R_FUNCTION_INTERRUPT
 	     : M32R_FUNCTION_NORMAL);
 
@@ -2846,7 +2846,7 @@ m32r_hard_regno_rename_ok (unsigned int 
 			   unsigned int new_reg)
 {
   /* Interrupt routines can't clobber any register that isn't already used.  */
-  if (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl))
+  if (has_attribute_p ("interrupt", DECL_ATTRIBUTES (current_function_decl))
       && !regs_ever_live[new_reg])
     return 0;
 
Index: gcc/config/m68hc11/m68hc11.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68hc11/m68hc11.c,v
retrieving revision 1.109
diff -u -p -u -p -r1.109 m68hc11.c
--- gcc/config/m68hc11/m68hc11.c	18 Sep 2004 19:19:36 -0000	1.109
+++ gcc/config/m68hc11/m68hc11.c	1 Oct 2004 00:57:21 -0000
@@ -73,7 +73,6 @@ static int m68hc11_shift_cost (enum mach
 static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
 static bool m68hc11_rtx_costs (rtx, int, int, int *);
 static int m68hc11_auto_inc_p (rtx);
-static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *);
 const struct attribute_spec m68hc11_attribute_table[];
 
 void create_regs_rtx (void);
@@ -1298,10 +1297,11 @@ m68hc11_initialize_trampoline (rtx tramp
 
 /* Handle an "tiny_data" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 m68hc11_handle_page0_attribute (tree *node, tree name,
                                 tree args ATTRIBUTE_UNUSED,
-                                int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+                                int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+				bool * ARG_UNUSED (defer))
 {
   tree decl = *node;
 
@@ -1314,17 +1314,15 @@ m68hc11_handle_page0_attribute (tree *no
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 const struct attribute_spec m68hc11_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt", 0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
-  { "trap",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
-  { "far",       0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
-  { "near",      0, 0, false, true,  true,  m68hc11_handle_fntype_attribute },
+  { "interrupt", 0, 0, false, true,  true,  handle_fndecl_attribute },
+  { "trap",      0, 0, false, true,  true,  handle_fndecl_attribute },
+  { "far",       0, 0, false, true,  true,  handle_fndecl_attribute },
+  { "near",      0, 0, false, true,  true,  handle_fndecl_attribute },
   { "page0",     0, 0, false, false, false, m68hc11_handle_page0_attribute },
   { NULL,        0, 0, false, false, false, NULL }
 };
@@ -1334,26 +1332,6 @@ const struct attribute_spec m68hc11_attr
    record one such symbol.  If there are several, a warning is reported.  */
 static rtx trap_handler_symbol = 0;
 
-/* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
-   arguments as in struct attribute_spec.handler.  */
-static tree
-m68hc11_handle_fntype_attribute (tree *node, tree name,
-                                 tree args ATTRIBUTE_UNUSED,
-                                 int flags ATTRIBUTE_UNUSED,
-                                 bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_TYPE
-      && TREE_CODE (*node) != METHOD_TYPE
-      && TREE_CODE (*node) != FIELD_DECL
-      && TREE_CODE (*node) != TYPE_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
 /* Undo the effects of the above.  */
 
 static const char *
@@ -1407,13 +1385,13 @@ m68hc11_page0_symbol_p (rtx x)
 static void
 m68hc11_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
 {
-  tree func_attr;
+  attribute_list func_attr;
   int trap_handler;
   int is_far = 0;
   
   if (TREE_CODE (decl) == VAR_DECL)
     {
-      if (lookup_attribute ("page0", DECL_ATTRIBUTES (decl)) != 0)
+      if (has_attribute_p ("page0", DECL_ATTRIBUTES (decl)))
         m68hc11_encode_label (decl);
       return;
     }
@@ -1423,13 +1401,12 @@ m68hc11_encode_section_info (tree decl, 
 
   func_attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));
 
-
-  if (lookup_attribute ("far", func_attr) != NULL_TREE)
+  if (has_attribute_p ("far", func_attr))
     is_far = 1;
-  else if (lookup_attribute ("near", func_attr) == NULL_TREE)
+  else if (!has_attribute_p ("near", func_attr))
     is_far = TARGET_LONG_CALLS != 0;
 
-  trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
+  trap_handler = has_attribute_p ("trap", func_attr);
   if (trap_handler && is_far)
     {
       warning ("`trap' and `far' attributes are not compatible, ignoring `far'");
@@ -1484,21 +1461,20 @@ m68hc11_is_trap_symbol (rtx sym)
 int
 m68hc11_initial_elimination_offset (int from, int to)
 {
-  int trap_handler;
-  tree func_attr;
+  bool trap_handler;
+  attribute_list func_attr;
   int size;
   int regno;
 
   /* For a trap handler, we must take into account the registers which
      are pushed on the stack during the trap (except the PC).  */
   func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
-  current_function_interrupt = lookup_attribute ("interrupt",
-						 func_attr) != NULL_TREE;
-  trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
+  current_function_interrupt = has_attribute_p ("interrupt", func_attr);
+  trap_handler = has_attribute_p ("trap", func_attr);
 
-  if (lookup_attribute ("far", func_attr) != 0)
+  if (has_attribute_p ("far", func_attr))
     current_function_far = 1;
-  else if (lookup_attribute ("near", func_attr) != 0)
+  else if (has_attribute_p ("near", func_attr))
     current_function_far = 0;
   else
     current_function_far = (TARGET_LONG_CALLS != 0
@@ -1762,7 +1738,7 @@ m68hc11_output_function_epilogue (FILE *
 void
 expand_prologue (void)
 {
-  tree func_attr;
+  attribute_list func_attr;
   int size;
   int regno;
   rtx scratch;
@@ -1776,12 +1752,11 @@ expand_prologue (void)
 
   /* Generate specific prologue for interrupt handlers.  */
   func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
-  current_function_interrupt = lookup_attribute ("interrupt",
-						 func_attr) != NULL_TREE;
-  current_function_trap = lookup_attribute ("trap", func_attr) != NULL_TREE;
-  if (lookup_attribute ("far", func_attr) != NULL_TREE)
+  current_function_interrupt = has_attribute_p ("interrupt", func_attr);
+  current_function_trap = has_attribute_p ("trap", func_attr);
+  if (has_attribute_p ("far", func_attr))
     current_function_far = 1;
-  else if (lookup_attribute ("near", func_attr) != NULL_TREE)
+  else if (has_attribute_p ("near", func_attr))
     current_function_far = 0;
   else
     current_function_far = (TARGET_LONG_CALLS != 0
Index: gcc/config/m68k/m68k.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68k/m68k.c,v
retrieving revision 1.141
diff -u -p -u -p -r1.141 m68k.c
--- gcc/config/m68k/m68k.c	18 Sep 2004 19:19:36 -0000	1.141
+++ gcc/config/m68k/m68k.c	1 Oct 2004 00:57:22 -0000
@@ -114,9 +114,6 @@ static void m68k_output_mi_thunk (FILE *
 					  HOST_WIDE_INT, tree);
 static rtx m68k_struct_value_rtx (tree, int);
 static bool m68k_interrupt_function_p (tree func);
-static tree m68k_handle_fndecl_attribute (tree *node, tree name,
-					  tree args, int flags,
-					  bool *no_add_attrs);
 static void m68k_compute_frame_layout (void);
 static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
 static int const_int_cost (rtx);
@@ -189,7 +186,7 @@ int m68k_last_compare_had_fp_operands;
 static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt_handler", 0, 0, true,  false, false, m68k_handle_fndecl_attribute },
+  { "interrupt_handler", 0, 0, true,  false, false, handle_fndecl_attribute },
   { NULL,                0, 0, false, false, false, NULL }
 };
 
@@ -266,31 +263,10 @@ override_options (void)
 static bool
 m68k_interrupt_function_p(tree func)
 {
-  tree a;
-
   if (TREE_CODE (func) != FUNCTION_DECL)
     return false;
 
-  a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
-  return (a != NULL_TREE);
-}
-
-/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
-   struct attribute_spec.handler.  */
-static tree
-m68k_handle_fndecl_attribute (tree *node, tree name,
-			      tree args ATTRIBUTE_UNUSED,
-			      int flags ATTRIBUTE_UNUSED,
-			      bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
+  return has_attribute_p ("interrupt_handler", DECL_ATTRIBUTES (func));
 }
 
 static void
Index: gcc/config/mcore/mcore.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mcore/mcore.c,v
retrieving revision 1.74
diff -u -p -u -p -r1.74 mcore.c
--- gcc/config/mcore/mcore.c	18 Sep 2004 19:19:36 -0000	1.74
+++ gcc/config/mcore/mcore.c	1 Oct 2004 00:57:22 -0000
@@ -135,7 +135,8 @@ static void       mcore_mark_dllimport  
 static int        mcore_dllexport_p             (tree);
 static int        mcore_dllimport_p             (tree);
 const struct attribute_spec mcore_attribute_table[];
-static tree       mcore_handle_naked_attribute  (tree *, tree, tree, int, bool *);
+static void       mcore_handle_naked_attribute  (tree *, tree, tree, int,
+						 bool *, bool *);
 #ifdef OBJECT_FORMAT_ELF
 static void	  mcore_asm_named_section       (const char *,
 						 unsigned int, tree);
@@ -3275,7 +3276,7 @@ mcore_dllexport_p (tree decl)
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
 
-  return lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)) != 0;
+  return has_attribute_p ("dllexport", DECL_ATTRIBUTES (decl));
 }
 
 static int
@@ -3285,7 +3286,7 @@ mcore_dllimport_p (tree decl)
       && TREE_CODE (decl) != FUNCTION_DECL)
     return 0;
 
-  return lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)) != 0;
+  return has_attribute_p ("dllimport", DECL_ATTRIBUTES (decl));
 }
 
 /* We must mark dll symbols specially.  Definitions of dllexport'd objects
@@ -3348,9 +3349,11 @@ const struct attribute_spec mcore_attrib
 /* Handle a "naked" attribute; arguments as in
    struct attribute_spec.handler.  */
 
-static tree
-mcore_handle_naked_attribute (tree * node, tree name, tree args ATTRIBUTE_UNUSED,
-			      int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
+static void
+mcore_handle_naked_attribute (tree * node, tree name, 
+			      tree args ATTRIBUTE_UNUSED,
+			      int flags ATTRIBUTE_UNUSED, bool * no_add_attrs,
+			      bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     {
@@ -3376,8 +3379,6 @@ mcore_handle_naked_attribute (tree * nod
 	       IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* ??? It looks like this is PE specific?  Oh well, this is what the
@@ -3419,7 +3420,7 @@ mcore_unique_section (tree decl, int rel
 int
 mcore_naked_function_p (void)
 {
-  return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
+  return has_attribute_p ("naked", DECL_ATTRIBUTES (current_function_decl));
 }
 
 #ifdef OBJECT_FORMAT_ELF
Index: gcc/config/ns32k/ns32k.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ns32k/ns32k.c,v
retrieving revision 1.48
diff -u -p -u -p -r1.48 ns32k.c
--- gcc/config/ns32k/ns32k.c	7 Jul 2004 19:24:33 -0000	1.48
+++ gcc/config/ns32k/ns32k.c	1 Oct 2004 00:57:22 -0000
@@ -67,7 +67,6 @@ static const char *const ns32k_out_reg_n
 static rtx gen_indexed_expr (rtx, rtx, rtx);
 static const char *singlemove_string (rtx *);
 static void move_tail (rtx[], int, int);
-static tree ns32k_handle_fntype_attribute (tree *, tree, tree, int, bool *);
 const struct attribute_spec ns32k_attribute_table[];
 static void ns32k_output_function_prologue (FILE *, HOST_WIDE_INT);
 static void ns32k_output_function_epilogue (FILE *, HOST_WIDE_INT);
@@ -1047,32 +1046,12 @@ const struct attribute_spec ns32k_attrib
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   /* Stdcall attribute says callee is responsible for popping arguments
      if they are not variable.  */
-  { "stdcall", 0, 0, false, true,  true,  ns32k_handle_fntype_attribute },
+  { "stdcall", 0, 0, false, true,  true,  NULL },
   /* Cdecl attribute says the callee is a normal C declaration */
-  { "cdecl",   0, 0, false, true,  true,  ns32k_handle_fntype_attribute },
+  { "cdecl",   0, 0, false, true,  true,  NULL },
   { NULL,      0, 0, false, false, false, NULL }
 };
 
-/* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
-   arguments as in struct attribute_spec.handler.  */
-static tree
-ns32k_handle_fntype_attribute (tree *node, tree name,
-			       tree args ATTRIBUTE_UNUSED,
-			       int flags ATTRIBUTE_UNUSED,
-			       bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_TYPE
-      && TREE_CODE (*node) != FIELD_DECL
-      && TREE_CODE (*node) != TYPE_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
 
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
@@ -1100,11 +1079,11 @@ ns32k_return_pops_args (tree fundecl ATT
     return rtd ? size : 0;
 
   /* Cdecl functions override -mrtd, and never pop the stack */
-  if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
+  if (has_attribute_p ("cdecl", TYPE_ATTRIBUTES (funtype)))
     return 0;
 
   /* Stdcall functions will pop the stack if not variable args */
-  if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
+  if (has_attribute_p ("stdcall", TYPE_ATTRIBUTES (funtype)))
     rtd = 1;
 
   if (rtd)
Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.718
diff -u -p -u -p -r1.718 rs6000.c
--- gcc/config/rs6000/rs6000.c	29 Sep 2004 09:47:48 -0000	1.718
+++ gcc/config/rs6000/rs6000.c	1 Oct 2004 00:57:23 -0000
@@ -628,8 +628,8 @@ static bool rs6000_assemble_integer (rtx
 static void rs6000_assemble_visibility (tree, int);
 #endif
 static int rs6000_ra_ever_killed (void);
-static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
-static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
+static void rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *,
+					     bool *);
 static void rs6000_eliminate_indexed_memrefs (rtx operands[2]);
 static const char *rs6000_mangle_fundamental_type (tree);
 extern const struct attribute_spec rs6000_attribute_table[];
@@ -4595,8 +4595,8 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 
   /* Check for a longcall attribute.  */
   if (fntype
-      && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))
-      && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
+      && has_attribute_p ("longcall", TYPE_ATTRIBUTES (fntype))
+      && !has_attribute_p ("shortcall", TYPE_ATTRIBUTES (fntype)))
     cum->call_cookie = CALL_LONG;
 
   if (TARGET_DEBUG_ARG)
@@ -5745,7 +5745,7 @@ rs6000_gimplify_va_arg (tree valist, tre
 do {									\
   if ((MASK) & target_flags)						\
     lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,	\
-				 NULL, NULL_TREE);			\
+				 NULL, NULL);				\
 } while (0)
 
 /* Simple ternary operations: VECd = foo (VECa, VECb, VECc).  */
@@ -12390,10 +12390,10 @@ rs6000_function_ok_for_sibcall (tree dec
       if (DEFAULT_ABI == ABI_DARWIN
 	  || (*targetm.binds_local_p) (decl))
 	{
-	  tree attr_list = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+	  attribute_list attr_list = TYPE_ATTRIBUTES (TREE_TYPE (decl));
 
-	  if (!lookup_attribute ("longcall", attr_list)
-	      || lookup_attribute ("shortcall", attr_list))
+	  if (!has_attribute_p ("longcall", attr_list)
+	      || has_attribute_p ("shortcall", attr_list))
 	    return true;
 	}
     }
@@ -16243,8 +16243,8 @@ const struct attribute_spec rs6000_attri
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "altivec",   1, 1, false, true,  false, rs6000_handle_altivec_attribute },
-  { "longcall",  0, 0, false, true,  true,  rs6000_handle_longcall_attribute },
-  { "shortcall", 0, 0, false, true,  true,  rs6000_handle_longcall_attribute },
+  { "longcall",  0, 0, false, true,  true,  NULL },
+  { "shortcall", 0, 0, false, true,  true,  NULL },
   { NULL,        0, 0, false, false, false, NULL }
 };
 
@@ -16258,10 +16258,11 @@ const struct attribute_spec rs6000_attri
   and may appear more than once (e.g., 'vector bool char') in a
   given declaration.  */
 
-static tree
+static void
 rs6000_handle_altivec_attribute (tree *node, tree name, tree args,
 				 int flags ATTRIBUTE_UNUSED,
-				 bool *no_add_attrs)
+				 bool *no_add_attrs,
+				 bool * ARG_UNUSED (defer))
 {
   tree type = *node, result = NULL_TREE;
   enum machine_mode mode;
@@ -16334,8 +16335,6 @@ rs6000_handle_altivec_attribute (tree *n
     warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
   else
     *node = reconstruct_complex_type (*node, result);
-
-  return NULL_TREE;
 }
 
 /* AltiVec defines four built-in scalar types that serve as vector
@@ -16353,27 +16352,6 @@ rs6000_mangle_fundamental_type (tree typ
   return NULL;
 }
 
-/* Handle a "longcall" or "shortcall" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-rs6000_handle_longcall_attribute (tree *node, tree name,
-				  tree args ATTRIBUTE_UNUSED,
-				  int flags ATTRIBUTE_UNUSED,
-				  bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_TYPE
-      && TREE_CODE (*node) != FIELD_DECL
-      && TREE_CODE (*node) != TYPE_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
 /* Set longcall attributes on all functions declared when
    rs6000_default_long_calls is true.  */
 static void
@@ -16382,9 +16360,13 @@ rs6000_set_default_type_attributes (tree
   if (rs6000_default_long_calls
       && (TREE_CODE (type) == FUNCTION_TYPE
 	  || TREE_CODE (type) == METHOD_TYPE))
-    TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"),
-					NULL_TREE,
-					TYPE_ATTRIBUTES (type));
+    {
+      struct one_attribute oa;
+      oa.name = get_identifier ("longcall");
+      oa.value = NULL_TREE;
+      TYPE_ATTRIBUTES (type) = merge_attributes_1 (TYPE_ATTRIBUTES (type),
+						   1, &oa, NULL, 0);
+    }
 }
 
 /* Return a reference suitable for calling a function with the
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.182
diff -u -p -u -p -r1.182 s390.c
--- gcc/config/s390/s390.c	30 Sep 2004 21:23:29 -0000	1.182
+++ gcc/config/s390/s390.c	1 Oct 2004 00:57:23 -0000
@@ -7375,12 +7375,12 @@ s390_init_builtins (void)
   ftype = build_function_type (ptr_type_node, void_list_node);
   lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
 			       S390_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
-			       NULL, NULL_TREE);
+			       NULL, NULL);
 
   ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
   lang_hooks.builtin_function ("__builtin_set_thread_pointer", ftype,
 			       S390_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
-			       NULL, NULL_TREE);
+			       NULL, NULL);
 }
 
 /* Expand an expression EXP that calls a built-in function,
Index: gcc/config/sh/sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.60
diff -u -p -u -p -r1.60 sh-protos.h
--- gcc/config/sh/sh-protos.h	28 Sep 2004 17:37:35 -0000	1.60
+++ gcc/config/sh/sh-protos.h	1 Oct 2004 00:57:23 -0000
@@ -156,7 +156,8 @@ extern bool         sh_symbian_dllexport
 extern int          symbian_import_export_class       (tree, int);
 #ifdef TREE_CODE
 extern bool         sh_symbian_dllexport_p            (tree);
-extern tree         sh_symbian_handle_dll_attribute   (tree *, tree, tree, int, bool *);
+extern void         sh_symbian_handle_dll_attribute   (tree *, tree, tree, int,
+						       bool *, bool *);
 #ifdef RTX_CODE
 extern void         sh_symbian_encode_section_info    (tree, rtx, int);
 #endif
Index: gcc/config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.303
diff -u -p -u -p -r1.303 sh.c
--- gcc/config/sh/sh.c	30 Sep 2004 12:25:34 -0000	1.303
+++ gcc/config/sh/sh.c	1 Oct 2004 00:57:23 -0000
@@ -220,12 +220,16 @@ static void mark_use (rtx, rtx *);
 static HOST_WIDE_INT rounded_frame_size (int);
 static rtx mark_constant_pool_use (rtx);
 const struct attribute_spec sh_attribute_table[];
-static tree sh_handle_interrupt_handler_attribute (tree *, tree, tree, int, bool *);
-static tree sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *);
-static tree sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *);
-static tree sh_handle_renesas_attribute (tree *, tree, tree, int, bool *);
+static void sh_handle_interrupt_handler_attribute (tree *, tree, tree, int,
+						   bool *, bool *);
+static void sh_handle_sp_switch_attribute (tree *, tree, tree, int, bool *,
+					   bool *);
+static void sh_handle_trap_exit_attribute (tree *, tree, tree, int, bool *,
+					   bool *);
 static void sh_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void sh_insert_attributes (tree, tree *);
+static attribute_count sh_add_attributes (tree node,
+					  attribute_list attrs,
+					  const struct one_attribute **to_add);
 static int sh_adjust_cost (rtx, rtx, rtx, int);
 static int sh_issue_rate (void);
 static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p);
@@ -317,8 +321,8 @@ static bool sh_callee_copies (CUMULATIVE
 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
 
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES sh_insert_attributes
+#undef TARGET_ADD_ATTRIBUTES
+#define TARGET_ADD_ATTRIBUTES sh_add_attributes
 
 #undef TARGET_SCHED_ADJUST_COST
 #define TARGET_SCHED_ADJUST_COST sh_adjust_cost
@@ -5263,7 +5267,7 @@ sh_media_register_for_return (void)
 
   if (! current_function_is_leaf)
     return -1;
-  if (lookup_attribute ("interrupt_handler",
+  if (has_attribute_p ("interrupt_handler",
 			DECL_ATTRIBUTES (current_function_decl)))
     return -1;
 
@@ -7075,21 +7079,24 @@ sh_pr_nosave_low_regs (struct cpp_reader
 
 /* Generate 'handle_interrupt' attribute for decls */
 
-static void
-sh_insert_attributes (tree node, tree *attributes)
+static attribute_count
+sh_add_attributes (tree node, attribute_list ARG_UNUSED (attrs),
+		   const struct one_attribute **to_add)
 {
+  static struct one_attribute oa;
+  
   if (! pragma_interrupt
       || TREE_CODE (node) != FUNCTION_DECL)
-    return;
+    return 0;
 
   /* We are only interested in fields.  */
   if (!DECL_P (node))
-    return;
+    return 0;
 
   /* Add a 'handle_interrupt' attribute.  */
-  * attributes = tree_cons (get_identifier ("interrupt_handler"), NULL, * attributes);
-
-  return;
+  oa.name = get_identifier ("interrupt_handler");
+  *to_add = &oa;
+  return 1;
 }
 
 /* Supported attributes:
@@ -7113,7 +7120,7 @@ const struct attribute_spec sh_attribute
   { "interrupt_handler", 0, 0, true,  false, false, sh_handle_interrupt_handler_attribute },
   { "sp_switch",         1, 1, true,  false, false, sh_handle_sp_switch_attribute },
   { "trap_exit",         1, 1, true,  false, false, sh_handle_trap_exit_attribute },
-  { "renesas",           0, 0, false, true, false, sh_handle_renesas_attribute },
+  { "renesas",           0, 0, false, true, false, NULL },
 #ifdef SYMBIAN
   /* Symbian support adds three new attributes:
      dllexport - for exporting a function/variable that will live in a dll
@@ -7130,11 +7137,12 @@ const struct attribute_spec sh_attribute
 
 /* Handle an "interrupt_handler" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 sh_handle_interrupt_handler_attribute (tree *node, tree name,
 				       tree args ATTRIBUTE_UNUSED,
 				       int flags ATTRIBUTE_UNUSED,
-				       bool *no_add_attrs)
+				       bool *no_add_attrs,
+				       bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
@@ -7147,15 +7155,14 @@ sh_handle_interrupt_handler_attribute (t
       error ("attribute interrupt_handler is not compatible with -m5-compact");
       *no_add_attrs = true;
     }
-
-  return NULL_TREE;
 }
 
 /* Handle an "sp_switch" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 sh_handle_sp_switch_attribute (tree *node, tree name, tree args,
-			       int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+			       int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+			       bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
@@ -7179,18 +7186,17 @@ sh_handle_sp_switch_attribute (tree *nod
     }
   else
     {
-      char *s = ggc_strdup (TREE_STRING_POINTER (TREE_VALUE (args)));
+      const char *s = ggc_strdup (TREE_STRING_POINTER (TREE_VALUE (args)));
       sp_switch = gen_rtx_SYMBOL_REF (VOIDmode, s);
     }
-
-  return NULL_TREE;
 }
 
 /* Handle an "trap_exit" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 sh_handle_trap_exit_attribute (tree *node, tree name, tree args,
-			       int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+			       int flags ATTRIBUTE_UNUSED, bool *no_add_attrs,
+			       bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
@@ -7216,18 +7222,6 @@ sh_handle_trap_exit_attribute (tree *nod
     {
       trap_exit = TREE_INT_CST_LOW (TREE_VALUE (args));
     }
-
-  return NULL_TREE;
-}
-
-static tree
-sh_handle_renesas_attribute (tree *node ATTRIBUTE_UNUSED,
-			     tree name ATTRIBUTE_UNUSED,
-			     tree args ATTRIBUTE_UNUSED,
-			     int flags ATTRIBUTE_UNUSED,
-			     bool *no_add_attrs ATTRIBUTE_UNUSED)
-{
-  return NULL_TREE;
 }
 
 /* True if __attribute__((renesas)) or -mrenesas.  */
@@ -7240,8 +7234,7 @@ sh_attr_renesas_p (tree td)
     return 0;
   if (DECL_P (td))
     td = TREE_TYPE (td);
-  return (lookup_attribute ("renesas", TYPE_ATTRIBUTES (td))
-	  != NULL_TREE);
+  return has_attribute_p ("renesas", TYPE_ATTRIBUTES (td));
 }
 
 /* True if __attribute__((renesas)) or -mrenesas, for the current
@@ -7255,9 +7248,8 @@ sh_cfun_attr_renesas_p (void)
 int
 sh_cfun_interrupt_handler_p (void)
 {
-  return (lookup_attribute ("interrupt_handler",
-			    DECL_ATTRIBUTES (current_function_decl))
-	  != NULL_TREE);
+  return has_attribute_p ("interrupt_handler",
+			  DECL_ATTRIBUTES (current_function_decl));
 }
 
 /* ??? target_switches in toplev.c is static, hence we have to duplicate it.  */
@@ -9378,7 +9370,7 @@ sh_media_init_builtins (void)
 	    shared[signature] = type;
 	}
       lang_hooks.builtin_function (d->name, type, d - bdesc, BUILT_IN_MD,
-				   NULL, NULL_TREE);
+				   NULL, NULL);
     }
 }
 
Index: gcc/config/sh/symbian.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/symbian.c,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 symbian.c
--- gcc/config/sh/symbian.c	18 Sep 2004 19:19:40 -0000	1.4
+++ gcc/config/sh/symbian.c	1 Oct 2004 00:57:23 -0000
@@ -76,21 +76,21 @@ sh_symbian_associated_type (tree decl)
 bool
 sh_symbian_dllexport_p (tree decl)
 {
-  tree exp;
+  bool exp;
 
   if (   TREE_CODE (decl) != VAR_DECL
       && TREE_CODE (decl) != FUNCTION_DECL)
     return false;
 
-  exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
+  exp = has_attribute_p ("dllexport", DECL_ATTRIBUTES (decl));
 
   /* Class members get the dllexport status of their class.  */
-  if (exp == NULL)
+  if (exp)
     {
       tree class = sh_symbian_associated_type (decl);
 
       if (class)
-	exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
+	exp = has_attribute_p ("dllexport", TYPE_ATTRIBUTES (class));
     }
 #if SYMBIAN_DEBUG
   if (exp)
@@ -107,7 +107,7 @@ sh_symbian_dllexport_p (tree decl)
       fprintf (stderr, "\n");
     }
 #endif
-  return exp ? true : false;
+  return exp;
 }
 
 /* Return nonzero if DECL is a dllimport'd object.  */
@@ -121,8 +121,7 @@ sh_symbian_dllimport_p (tree decl)
       && TREE_CODE (decl) != FUNCTION_DECL)
     return false;
 
-  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
-  if (imp)
+  if (has_attribute_p ("dllimport", DECL_ATTRIBUTES (decl)))
     return true;
 
   /* Class members get the dllimport status of their class.  */
@@ -130,8 +129,7 @@ sh_symbian_dllimport_p (tree decl)
   if (! imp)
     return false;
 
-  imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
-  if (!imp)
+  if (!has_attribute_p ("dllimport", TYPE_ATTRIBUTES (imp)))
     return false;
 
   /* Don't mark defined functions as dllimport.  If the definition itself
@@ -377,7 +375,7 @@ symbian_add_attribute (tree node, const 
 
   attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
 
-  if (lookup_attribute (attr_name, attrs) != NULL_TREE)
+  if (has_attribute_p (attr_name, attrs))
     return;
 
   attr = get_identifier (attr_name);
@@ -395,9 +393,10 @@ symbian_add_attribute (tree node, const 
 /* Handle a "dllimport" or "dllexport" attribute;
    arguments as in struct attribute_spec.handler.  */
 
-tree
+void
 sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
-				 int flags, bool *no_add_attrs)
+				 int flags, bool *no_add_attrs,
+				 bool * defer)
 {
   tree thunk;
   tree node = *pnode;
@@ -412,8 +411,8 @@ sh_symbian_handle_dll_attribute (tree *p
 		   | (int) ATTR_FLAG_ARRAY_NEXT))
 	{
 	  warning ("`%s' attribute ignored", attr);
-	  *no_add_attrs = true;
-	  return tree_cons (name, args, NULL_TREE);
+	  *defer = true;
+	  return;
 	}
 
       if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
@@ -422,7 +421,7 @@ sh_symbian_handle_dll_attribute (tree *p
 	  *no_add_attrs = true;
 	}
 
-      return NULL_TREE;
+      return;
     }
 
   /* Report error on dllimport ambiguities
@@ -517,8 +516,6 @@ sh_symbian_handle_dll_attribute (tree *p
   print_node_brief (stderr, "mark node", node, 0);
   fprintf (stderr, " as %s\n", attr);
 #endif
-
-  return NULL_TREE;
 }
 
 /* This code implements a specification for exporting the vtable and rtti of
@@ -684,7 +681,7 @@ symbian_export_vtable_and_rtti_p (tree c
 		      || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
 		inline_ctor_dtor = true;
 
-	      if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
+	      if (has_attribute_p ("dllimport", DECL_ATTRIBUTES (member)))
 		dllimport_ctor_dtor = true;
 	    }
 	  else
@@ -698,7 +695,7 @@ symbian_export_vtable_and_rtti_p (tree c
 	      if (DECL_INLINE (member))
 		continue;
 
-	      if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
+	      if (has_attribute_p ("dllimport", DECL_ATTRIBUTES (member)))
 		dllimport_member = true;
 	    }
 	}
@@ -765,7 +762,7 @@ symbian_class_needs_attribute_p (tree ct
   /* If the key function has the attribute then the class needs it too.  */
   if (TYPE_POLYMORPHIC_P (ctype)
       && CLASSTYPE_KEY_METHOD (ctype)
-      && lookup_attribute (attribute_name,
+      && has_attribute_p (attribute_name,
 			   DECL_ATTRIBUTES (CLASSTYPE_KEY_METHOD (ctype))))
     return true;
 
@@ -795,7 +792,7 @@ symbian_class_needs_attribute_p (tree ct
 	      if (! DECL_VIRTUAL_P (member))
 		continue;
 
-	      if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
+	      if (has_attribute_p (attribute_name, DECL_ATTRIBUTES (member)))
 		{
 #if SYMBIAN_DEBUG
 		  print_node_brief (stderr, "", ctype, 0);
@@ -832,7 +829,7 @@ symbian_import_export_class (tree ctype,
     }
 
   if (attr_name
-      && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
+      && ! has_attribute_p (attr_name, TYPE_ATTRIBUTES (ctype)))
     {
       if (symbian_class_needs_attribute_p (ctype, attr_name))
 	symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
Index: gcc/config/sparc/sol2.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sol2.h,v
retrieving revision 1.65
diff -u -p -u -p -r1.65 sol2.h
--- gcc/config/sparc/sol2.h	24 Sep 2004 06:17:07 -0000	1.65
+++ gcc/config/sparc/sol2.h	1 Oct 2004 00:57:23 -0000
@@ -162,7 +162,7 @@ Boston, MA 02111-1307, USA.  */
 
 /* Solaris-specific #pragmas are implemented on top of attributes.  Hook in
    the bits from config/sol2.c.  */
-#define SUBTARGET_INSERT_ATTRIBUTES solaris_insert_attributes
+#define SUBTARGET_ADD_ATTRIBUTES solaris_add_attributes
 #define SUBTARGET_ATTRIBUTE_TABLE SOLARIS_ATTRIBUTE_TABLE
 
 /* Output a simple call for .init/.fini.  */
Index: gcc/config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.336
diff -u -p -u -p -r1.336 sparc.c
--- gcc/config/sparc/sparc.c	28 Sep 2004 06:26:08 -0000	1.336
+++ gcc/config/sparc/sparc.c	1 Oct 2004 00:57:24 -0000
@@ -464,9 +464,9 @@ enum processor_type sparc_cpu;
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg
 
-#ifdef SUBTARGET_INSERT_ATTRIBUTES
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
+#ifdef SUBTARGET_ADD_ATTRIBUTES
+#undef TARGET_ADD_ATTRIBUTES
+#define TARGET_ADD_ATTRIBUTES SUBTARGET_ADD_ATTRIBUTES
 #endif
 
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
Index: gcc/config/stormy16/stormy16.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/stormy16/stormy16.c,v
retrieving revision 1.68
diff -u -p -u -p -r1.68 stormy16.c
--- gcc/config/stormy16/stormy16.c	27 Sep 2004 19:28:51 -0000	1.68
+++ gcc/config/stormy16/stormy16.c	1 Oct 2004 00:57:24 -0000
@@ -1750,8 +1750,8 @@ xstormy16_encode_section_info (tree decl
 			       int first ATTRIBUTE_UNUSED)
 {
   if (TREE_CODE (decl) == VAR_DECL
-      && (lookup_attribute ("below100", DECL_ATTRIBUTES (decl))
-	  || lookup_attribute ("BELOW100", DECL_ATTRIBUTES (decl))))
+      && (has_attribute_p ("below100", DECL_ATTRIBUTES (decl))
+	  || has_attribute_p ("BELOW100", DECL_ATTRIBUTES (decl))))
     {
       const char *newsection = 0;
       char *newname;
@@ -2372,7 +2372,7 @@ xstormy16_output_shift (enum machine_mod
 int
 xstormy16_interrupt_function_p (void)
 {
-  tree attributes;
+  attribute_list attributes;
   
   /* The dwarf2 mechanism asks for INCOMING_FRAME_SP_OFFSET before
      any functions are declared, which is demonstrably wrong, but
@@ -2381,51 +2381,32 @@ xstormy16_interrupt_function_p (void)
     return 0;
 
   attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
-  return lookup_attribute ("interrupt", attributes) != NULL_TREE;
+  return has_attribute_p ("interrupt", attributes);
 }
 
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE xstormy16_attribute_table
-static tree xstormy16_handle_interrupt_attribute
-  (tree *, tree, tree, int, bool *);
-static tree xstormy16_handle_below100_attribute
-  (tree *, tree, tree, int, bool *);
+static void xstormy16_handle_below100_attribute
+  (tree *, tree, tree, int, bool *, bool *);
 
 static const struct attribute_spec xstormy16_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt", 0, 0, false, true,  true,  xstormy16_handle_interrupt_attribute },
+  { "interrupt", 0, 0, false, true,  true,  NULL },
   { "BELOW100",  0, 0, false, false, false, xstormy16_handle_below100_attribute },
   { "below100",  0, 0, false, false, false, xstormy16_handle_below100_attribute },
   { NULL,        0, 0, false, false, false, NULL }
 };
 
-/* Handle an "interrupt" attribute;
-   arguments as in struct attribute_spec.handler.  */
-static tree
-xstormy16_handle_interrupt_attribute (tree *node, tree name,
-				      tree args ATTRIBUTE_UNUSED,
-				      int flags ATTRIBUTE_UNUSED,
-				      bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_TYPE)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
 /* Handle an "below" attribute;
    arguments as in struct attribute_spec.handler.  */
-static tree
+static void
 xstormy16_handle_below100_attribute (tree *node,
 				     tree name ATTRIBUTE_UNUSED,
 				     tree args ATTRIBUTE_UNUSED,
 				     int flags ATTRIBUTE_UNUSED,
-				     bool *no_add_attrs)
+				     bool *no_add_attrs,
+				     bool * ARG_UNUSED (defer))
 {
   if (TREE_CODE (*node) != VAR_DECL
       && TREE_CODE (*node) != POINTER_TYPE
@@ -2442,8 +2423,6 @@ xstormy16_handle_below100_attribute (tre
 	  *no_add_attrs = true;
 	}
     }
-  
-  return NULL_TREE;
 }
 
 #undef TARGET_INIT_BUILTINS
Index: gcc/config/v850/v850.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850.c,v
retrieving revision 1.95
diff -u -p -u -p -r1.95 v850.c
--- gcc/config/v850/v850.c	8 Sep 2004 18:45:20 -0000	1.95
+++ gcc/config/v850/v850.c	1 Oct 2004 00:57:24 -0000
@@ -58,9 +58,10 @@ static void v850_reorg		     (void);
 static int  ep_memory_offset         (enum machine_mode, int);
 static void v850_set_data_area       (tree, v850_data_area);
 const struct attribute_spec v850_attribute_table[];
-static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
-static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *);
-static void v850_insert_attributes   (tree, tree *);
+static void v850_handle_data_area_attribute (tree *, tree, tree, int, bool *,
+					     bool *);
+static attribute_count v850_add_attributes (tree, attribute_list,
+					    const struct one_attribute **);
 static void v850_select_section (tree, int, unsigned HOST_WIDE_INT);
 static void v850_encode_data_area    (tree, rtx);
 static void v850_encode_section_info (tree, rtx, int);
@@ -101,8 +102,8 @@ static int v850_interrupt_p = FALSE;
 #undef TARGET_ATTRIBUTE_TABLE
 #define TARGET_ATTRIBUTE_TABLE v850_attribute_table
 
-#undef TARGET_INSERT_ATTRIBUTES
-#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes
+#undef TARGET_ADD_ATTRIBUTES
+#define TARGET_ADD_ATTRIBUTES v850_add_attributes
 
 #undef  TARGET_ASM_SELECT_SECTION
 #define TARGET_ASM_SELECT_SECTION  v850_select_section
@@ -2150,76 +2151,73 @@ notice_update_cc (rtx body, rtx insn)
 v850_data_area
 v850_get_data_area (tree decl)
 {
-  if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+  if (has_attribute_p ("sda", DECL_ATTRIBUTES (decl)))
     return DATA_AREA_SDA;
   
-  if (lookup_attribute ("tda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+  if (has_attribute_p ("tda", DECL_ATTRIBUTES (decl)))
     return DATA_AREA_TDA;
   
-  if (lookup_attribute ("zda", DECL_ATTRIBUTES (decl)) != NULL_TREE)
+  if (has_attribute_p ("zda", DECL_ATTRIBUTES (decl)))
     return DATA_AREA_ZDA;
 
   return DATA_AREA_NORMAL;
 }
 
-/* Store the indicated data area in the decl's attributes.  */
+/* Return zero or one attributes to add to give effect to DATA_AREA.  */
 
-static void
-v850_set_data_area (tree decl, v850_data_area data_area)
+static attribute_count
+v850_set_data_area_1 (v850_data_area data_area,
+		      const struct one_attribute ** to_add)
 {
-  tree name;
+  static struct one_attribute at;
   
   switch (data_area)
     {
-    case DATA_AREA_SDA: name = get_identifier ("sda"); break;
-    case DATA_AREA_TDA: name = get_identifier ("tda"); break;
-    case DATA_AREA_ZDA: name = get_identifier ("zda"); break;
+    case DATA_AREA_SDA: at.name = get_identifier ("sda"); break;
+    case DATA_AREA_TDA: at.name = get_identifier ("tda"); break;
+    case DATA_AREA_ZDA: at.name = get_identifier ("zda"); break;
     default:
-      return;
+      return 0;
     }
+  at.value = NULL_TREE;
+  *to_add = &at;
+  return 1;
+}
+
+
+/* Store the indicated data area in the decl's attributes.  */
 
-  DECL_ATTRIBUTES (decl) = tree_cons
-    (name, NULL, DECL_ATTRIBUTES (decl));
+static void
+v850_set_data_area (tree decl, v850_data_area data_area)
+{
+  const struct one_attribute *oa;
+  attribute_count ac;
+
+  ac = v850_set_data_area_1 (data_area, &oa);
+  DECL_ATTRIBUTES (decl) = merge_attributes_1 (DECL_ATTRIBUTES (decl),
+					       ac, oa, NULL, 0);
 }
 
 const struct attribute_spec v850_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "interrupt_handler", 0, 0, true,  false, false, v850_handle_interrupt_attribute },
-  { "interrupt",         0, 0, true,  false, false, v850_handle_interrupt_attribute },
+  { "interrupt_handler", 0, 0, true,  false, false, handle_fndecl_attribute },
+  { "interrupt",         0, 0, true,  false, false, handle_fndecl_attribute },
   { "sda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
   { "tda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
   { "zda",               0, 0, true,  false, false, v850_handle_data_area_attribute },
   { NULL,                0, 0, false, false, false, NULL }
 };
 
-/* Handle an "interrupt" attribute; arguments as in
-   struct attribute_spec.handler.  */
-static tree
-v850_handle_interrupt_attribute (tree * node,
-                                 tree name,
-                                 tree args ATTRIBUTE_UNUSED,
-                                 int flags ATTRIBUTE_UNUSED,
-                                 bool * no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning ("`%s' attribute only applies to functions",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
 /* Handle a "sda", "tda" or "zda" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 v850_handle_data_area_attribute (tree* node,
                                  tree name,
                                  tree args ATTRIBUTE_UNUSED,
                                  int flags ATTRIBUTE_UNUSED,
-                                 bool * no_add_attrs)
+                                 bool * no_add_attrs,
+				 bool * ARG_UNUSED (defer))
 {
   v850_data_area data_area;
   v850_data_area area;
@@ -2260,8 +2258,6 @@ v850_handle_data_area_attribute (tree* n
     default:
       break;
     }
-
-  return NULL_TREE;
 }
 
 
@@ -2271,8 +2267,7 @@ v850_handle_data_area_attribute (tree* n
 int
 v850_interrupt_function_p (tree func)
 {
-  tree a;
-  int ret = 0;
+  bool ret;
 
   if (v850_interrupt_cache_p)
     return v850_interrupt_p;
@@ -2280,15 +2275,8 @@ v850_interrupt_function_p (tree func)
   if (TREE_CODE (func) != FUNCTION_DECL)
     return 0;
 
-  a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
-  if (a != NULL_TREE)
-    ret = 1;
-
-  else
-    {
-      a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
-      ret = a != NULL_TREE;
-    }
+  ret = (has_attribute_p ("interrupt_handler", DECL_ATTRIBUTES (func))
+	 || has_attribute_p ("interrupt", DECL_ATTRIBUTES (func)));
 
   /* Its not safe to trust global variables until after function inlining has
      been done.  */
@@ -2847,15 +2835,18 @@ v850_output_local (FILE * file,
 
 /* Add data area to the given declaration if a ghs data area pragma is
    currently in effect (#pragma ghs startXXX/endXXX).  */
-static void
-v850_insert_attributes (tree decl, tree * attr_ptr ATTRIBUTE_UNUSED )
+static attribute_count
+v850_add_attributes (tree decl, attribute_list attributes ATTRIBUTE_UNUSED,
+		     const struct one_attribute ** ats)
 {
+  attribute_count result = 0;
+  
   if (data_area_stack
       && data_area_stack->data_area
       && current_function_decl == NULL_TREE
       && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
       && v850_get_data_area (decl) == DATA_AREA_NORMAL)
-    v850_set_data_area (decl, data_area_stack->data_area);
+    result = v850_set_data_area_1 (data_area_stack->data_area, ats);
 
   /* Initialize the default names of the v850 specific sections,
      if this has not been done before.  */
@@ -2941,6 +2932,7 @@ v850_insert_attributes (tree decl, tree 
 	  DECL_SECTION_NAME (decl) = chosen_section;
 	}
     }
+  return result;
 }
 
 /* Return nonzero if the given RTX is suitable
Index: gcc/cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.510
diff -u -p -u -p -r1.510 call.c
--- gcc/cp/call.c	28 Sep 2004 02:56:06 -0000	1.510
+++ gcc/cp/call.c	1 Oct 2004 00:57:24 -0000
@@ -4907,7 +4907,7 @@ build_java_interface_fn_ref (tree fn, tr
       java_iface_lookup_fn 
 	= builtin_function ("_Jv_LookupInterfaceMethodIdx",
 			    build_function_type (ptr_type_node, t),
-			    0, NOT_BUILT_IN, NULL, NULL_TREE);
+			    0, NOT_BUILT_IN, NULL, NULL);
     }
 
   /* Look up the pointer to the runtime java.lang.Class object for `instance'. 
Index: gcc/cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.679
diff -u -p -u -p -r1.679 class.c
--- gcc/cp/class.c	29 Sep 2004 06:23:46 -0000	1.679
+++ gcc/cp/class.c	1 Oct 2004 00:57:25 -0000
@@ -5089,7 +5089,7 @@ unreverse_member_declarations (tree t)
 }
 
 tree
-finish_struct (tree t, tree attributes)
+finish_struct (tree t, attribute_list attributes)
 {
   location_t saved_loc = input_location;
 
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1056
diff -u -p -u -p -r1.1056 cp-tree.h
--- gcc/cp/cp-tree.h	30 Sep 2004 15:25:18 -0000	1.1056
+++ gcc/cp/cp-tree.h	1 Oct 2004 00:57:25 -0000
@@ -3434,7 +3434,7 @@ typedef struct cp_decl_specifier_seq {
      was used, in which case it will be a TYPE_DECL.  */
   tree type;
   /* The attributes, if any, provided with the specifier sequence.  */
-  tree attributes;
+  attribute_list attributes;
   /* If non-NULL, a built-in type that the user attempted to redefine
      to some other type.  */
   tree redefined_builtin_type;
@@ -3495,7 +3495,7 @@ struct cp_declarator {
   /* The kind of declarator.  */
   cp_declarator_kind kind;
   /* Attributes that apply to this declarator.  */
-  tree attributes;
+  attribute_list attributes;
   /* For all but cdk_id and cdk_error, the contained declarator.  For
      cdk_id and cdk_error, guaranteed to be NULL.  */
   cp_declarator *declarator;
@@ -3592,7 +3592,7 @@ extern void resort_type_method_vec
 extern void add_method				(tree, tree);
 extern int currently_open_class			(tree);
 extern tree currently_open_derived_class	(tree);
-extern tree finish_struct			(tree, tree);
+extern tree finish_struct			(tree, attribute_list);
 extern void finish_struct_1			(tree);
 extern int resolves_to_fixed_type_p		(tree, int *);
 extern void init_class_processing		(void);
@@ -3689,7 +3689,9 @@ extern int init_type_desc			(void);
 extern tree check_tag_decl			(cp_decl_specifier_seq *);
 extern tree shadow_tag				(cp_decl_specifier_seq *);
 extern tree groktypename			(cp_decl_specifier_seq *, const cp_declarator *);
-extern tree start_decl				(const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, bool *);
+extern tree start_decl
+  (const cp_declarator *, cp_decl_specifier_seq *, int, attribute_list,
+   attribute_list, bool *);
 extern void start_decl_1			(tree);
 extern void cp_finish_decl			(tree, tree, tree, int);
 extern void finish_decl				(tree, tree, tree);
@@ -3708,12 +3710,13 @@ extern void xref_basetypes			(tree, tree
 extern tree start_enum				(tree);
 extern void finish_enum				(tree);
 extern void build_enumerator			(tree, tree, tree);
-extern void start_preparsed_function            (tree, tree, int);
-extern int start_function			(cp_decl_specifier_seq *, const cp_declarator *, tree);
+extern void start_preparsed_function            (tree, attribute_list, int);
+extern int start_function			(cp_decl_specifier_seq *, const cp_declarator *, attribute_list);
 extern tree begin_function_body			(void);
 extern void finish_function_body		(tree);
 extern tree finish_function			(int);
-extern tree start_method			(cp_decl_specifier_seq *, const cp_declarator *, tree);
+extern tree start_method
+  (cp_decl_specifier_seq *, const cp_declarator *, attribute_list);
 extern tree finish_method			(tree);
 extern void maybe_register_incomplete_var       (tree);
 extern void complete_vars			(tree);
@@ -3748,7 +3751,7 @@ extern tree cp_fname_init			(const char 
 extern tree builtin_function (const char *name, tree type,
 			      int code,
 			      enum built_in_class cl,
-			      const char *libname, tree attrs);
+			      const char *libname, attribute_list attrs);
 extern tree check_elaborated_type_specifier     (enum tag_types, tree, bool);
 extern void warn_extern_redeclared_static (tree, tree);
 extern const char *cxx_comdat_group             (tree);
@@ -3767,10 +3770,11 @@ extern tree grok_array_decl (tree, tree)
 extern tree delete_sanity (tree, tree, bool, int);
 extern tree check_classfn (tree, tree, tree);
 extern void check_member_template (tree);
-extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree, tree, tree);
+extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree,
+		       tree, attribute_list);
 extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *, tree);
 extern tree groktypefield			(tree, tree);
-extern void cplus_decl_attributes (tree *, tree, int);
+extern void cplus_decl_attributes (tree *, attribute_list, int);
 extern void finish_anon_union (tree);
 extern tree finish_table (tree, tree, tree, int);
 extern void cp_finish_file (void);
@@ -3836,7 +3840,8 @@ extern tree cplus_expand_constant       
 extern int is_friend				(tree, tree);
 extern void make_friend_class			(tree, tree, bool);
 extern void add_friend                          (tree, tree, bool);
-extern tree do_friend				(tree, tree, tree, tree, enum overload_flags, cp_cv_quals, int);
+extern tree do_friend
+  (tree, tree, tree, attribute_list, enum overload_flags, cp_cv_quals, int);
 
 /* in init.c */
 extern tree expand_member_init			(tree);
@@ -4193,7 +4198,7 @@ extern int is_dummy_object			(tree);
 extern const struct attribute_spec cxx_attribute_table[];
 extern tree make_tinst_level                    (tree, location_t);
 extern tree make_ptrmem_cst                     (tree, tree);
-extern tree cp_build_type_attribute_variant     (tree, tree);
+extern tree cp_build_type_attribute_variant     (tree, attribute_list);
 extern tree cp_build_qualified_type_real        (tree, int, tsubst_flags_t);
 #define cp_build_qualified_type(TYPE, QUALS) \
   cp_build_qualified_type_real ((TYPE), (QUALS), tf_error | tf_warning)
Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1309
diff -u -p -u -p -r1.1309 decl.c
--- gcc/cp/decl.c	29 Sep 2004 20:27:21 -0000	1.1309
+++ gcc/cp/decl.c	1 Oct 2004 00:57:25 -0000
@@ -64,14 +64,14 @@ static tree grok_reference_init (tree, t
 static tree grokfndecl (tree, tree, tree, tree, tree, int,
 			enum overload_flags, cp_cv_quals,
 			tree, int, int, int, int, int, int, tree, 
-			tree *);
+			attribute_list *);
 static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
 			 int, int, tree);
 static void record_unknown_type (tree, const char *);
 static tree builtin_function_1 (const char *, tree, tree,
 				enum built_in_function code,
                                 enum built_in_class cl, const char *,
-				tree);
+				attribute_list);
 static tree build_library_fn_1 (tree, enum tree_code, tree);
 static int member_function_or_else (tree, tree, enum overload_flags);
 static void bad_specifiers (tree, const char *, int, int, int, int,
@@ -1173,15 +1173,15 @@ duplicate_decls (tree newdecl, tree oldd
     {
       if (DECL_DECLARED_INLINE_P (newdecl)
 	  && DECL_UNINLINABLE (newdecl)
-	  && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+	  && has_attribute_p ("noinline", DECL_ATTRIBUTES (newdecl)))
 	/* Already warned elsewhere.  */;
       else if (DECL_DECLARED_INLINE_P (olddecl)
 	       && DECL_UNINLINABLE (olddecl)
-	       && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+	       && has_attribute_p ("noinline", DECL_ATTRIBUTES (olddecl)))
 	/* Already warned.  */;
       else if (DECL_DECLARED_INLINE_P (newdecl)
 	       && DECL_UNINLINABLE (olddecl)
-	       && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+	       && has_attribute_p ("noinline", DECL_ATTRIBUTES (olddecl)))
 	{
 	  warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
 	  warning ("%Jprevious declaration of '%D' with attribute noinline",
@@ -1189,7 +1189,7 @@ duplicate_decls (tree newdecl, tree oldd
 	}
       else if (DECL_DECLARED_INLINE_P (olddecl)
 	       && DECL_UNINLINABLE (newdecl)
-	       && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+	       && has_attribute_p ("noinline", DECL_ATTRIBUTES (newdecl)))
 	{
 	  warning ("%Jfunction '%D' redeclared with attribute noinline",
 		   newdecl, newdecl);
@@ -1301,7 +1301,7 @@ duplicate_decls (tree newdecl, tree oldd
       else if (DECL_ANTICIPATED (olddecl))
 	{
 	  tree type = TREE_TYPE (newdecl);
-	  tree attribs = (*targetm.merge_type_attributes)
+	  attribute_list attribs = (*targetm.merge_type_attributes)
 	    (TREE_TYPE (olddecl), type);
 
 	  type = cp_build_type_attribute_variant (type, attribs);
@@ -3222,7 +3222,7 @@ builtin_function_1 (const char* name,
 		    enum built_in_function code,
                     enum built_in_class class,
                     const char* libname,
-                    tree attrs)
+                    attribute_list attrs)
 {
   tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
   DECL_BUILT_IN_CLASS (decl) = class;
@@ -3246,7 +3246,7 @@ builtin_function_1 (const char* name,
   if (attrs)
     decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
   else
-    decl_attributes (&decl, NULL_TREE, 0);
+    decl_attributes (&decl, NULL, 0);
 
   return decl;
 }
@@ -3273,7 +3273,7 @@ builtin_function (const char* name,
                   int code,
                   enum built_in_class cl,
                   const char* libname,
-                  tree attrs)
+                  attribute_list attrs)
 {
   /* All builtins that don't begin with an '_' should additionally
      go in the 'std' namespace.  */
@@ -3606,10 +3606,10 @@ tree
 groktypename (cp_decl_specifier_seq *type_specifiers,
 	      const cp_declarator *declarator)
 {
-  tree attrs;
+  attribute_list attrs;
   tree type;
   attrs = type_specifiers->attributes;
-  type_specifiers->attributes = NULL_TREE;
+  type_specifiers->attributes = NULL;
   type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
   if (attrs)
     cplus_decl_attributes (&type, attrs, 0);
@@ -3635,8 +3635,8 @@ tree
 start_decl (const cp_declarator *declarator,
 	    cp_decl_specifier_seq *declspecs,
             int initialized,
-            tree attributes,
-            tree prefix_attributes, 
+            attribute_list attributes,
+            attribute_list prefix_attributes, 
 	    bool *pop_scope_p)
 {
   tree decl;
@@ -3652,10 +3652,10 @@ start_decl (const cp_declarator *declara
 
   /* An object declared as __attribute__((deprecated)) suppresses
      warnings of uses of other deprecated items.  */
-  if (lookup_attribute ("deprecated", attributes))
+  if (has_attribute_p ("deprecated", attributes))
     deprecated_state = DEPRECATED_SUPPRESS;
 
-  attributes = chainon (attributes, prefix_attributes);
+  attributes = merge_attributes (attributes, prefix_attributes);
 
   decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
 			 &attributes);
@@ -3727,7 +3727,7 @@ start_decl (const cp_declarator *declara
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
-      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
+      && has_attribute_p ("noinline", DECL_ATTRIBUTES (decl)))
     warning ("%Jinline function '%D' given attribute noinline", decl, decl);
 
   if (context && COMPLETE_TYPE_P (complete_type (context)))
@@ -4982,7 +4982,7 @@ cp_finish_decl (tree decl, tree init, tr
     TREE_READONLY (decl) = 1;
 
   /* If this was marked 'used', be sure it will be output.  */
-  if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+  if (has_attribute_p ("used", DECL_ATTRIBUTES (decl)))
     mark_decl_referenced (decl);
 }
 
@@ -5153,7 +5153,7 @@ start_cleanup_fn (void)
     }
 
   pushdecl (fndecl);
-  start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
+  start_preparsed_function (fndecl, NULL, SF_PRE_PARSED);
 
   pop_lang_context ();
 
@@ -5542,7 +5542,7 @@ grokfndecl (tree ctype,
             int funcdef_flag,
             int template_count,
             tree in_namespace,
-	    tree* attrlist)
+	    attribute_list * attrlist)
 {
   tree decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -5766,7 +5766,7 @@ grokfndecl (tree ctype,
   if (attrlist)
     {
       cplus_decl_attributes (&decl, *attrlist, 0);
-      *attrlist = NULL_TREE;
+      *attrlist = NULL;
     }
 
   if (ctype != NULL_TREE
@@ -6430,7 +6430,7 @@ grokdeclarator (const cp_declarator *dec
 		const cp_decl_specifier_seq *declspecs,
                 enum decl_context decl_context,
                 int initialized,
-                tree* attrlist)
+                attribute_list* attrlist)
 {
   tree type = NULL_TREE;
   int longlong = 0;
@@ -6463,7 +6463,7 @@ grokdeclarator (const cp_declarator *dec
   cp_cv_quals quals = TYPE_UNQUALIFIED;
   tree raises = NULL_TREE;
   int template_count = 0;
-  tree returned_attrs = NULL_TREE;
+  attribute_list returned_attrs = NULL;
   tree parms = NULL_TREE;
   const cp_declarator *id_declarator;
   /* The unqualified name of the declarator; either an
@@ -7120,7 +7120,7 @@ grokdeclarator (const cp_declarator *dec
        declarator = declarator->declarator)
     {
       const cp_declarator *inner_declarator;
-      tree attrs;
+      attribute_list attrs;
 
       if (type == error_mark_node)
 	return error_mark_node;
@@ -7140,7 +7140,8 @@ grokdeclarator (const cp_declarator *dec
 	  if (declarator->kind == cdk_array)
 	    attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
 	  returned_attrs = decl_attributes (&type,
-					    chainon (returned_attrs, attrs),
+					    merge_attributes (returned_attrs,
+							      attrs),
 					    attr_flags);
 	}
 
@@ -7471,7 +7472,7 @@ grokdeclarator (const cp_declarator *dec
   if (returned_attrs)
     {
       if (attrlist)
-	*attrlist = chainon (returned_attrs, *attrlist);
+	*attrlist = merge_attributes (returned_attrs, *attrlist);
       else
 	attrlist = &returned_attrs;
     }
@@ -8350,14 +8351,14 @@ grokparms (cp_parameter_declarator *firs
     {
       tree type = NULL_TREE;
       tree init = parm->default_argument;
-      tree attrs;
+      attribute_list attrs;
       tree decl;
 
       if (parm == no_parameters)
         break;
 
       attrs = parm->decl_specifiers.attributes;
-      parm->decl_specifiers.attributes = NULL_TREE;
+      parm->decl_specifiers.attributes = NULL;
       decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
 			     PARM, init != NULL_TREE, &attrs);
       if (! decl || TREE_TYPE (decl) == error_mark_node)
@@ -9783,7 +9784,7 @@ check_function_type (tree decl, tree cur
    applied to it with the argument list [1, 2].  */
 
 void
-start_preparsed_function (tree decl1, tree attrs, int flags)
+start_preparsed_function (tree decl1, attribute_list attrs, int flags)
 {
   tree ctype = NULL_TREE;
   tree fntype;
@@ -9817,7 +9818,7 @@ start_preparsed_function (tree decl1, tr
     }
 
   if (DECL_DECLARED_INLINE_P (decl1)
-      && lookup_attribute ("noinline", attrs))
+      && has_attribute_p ("noinline", attrs))
     warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
 
   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
@@ -10102,7 +10103,7 @@ start_preparsed_function (tree decl1, tr
 int
 start_function (cp_decl_specifier_seq *declspecs,
 		const cp_declarator *declarator,
-		tree attrs)
+		attribute_list attrs)
 {
   tree decl1;
 
@@ -10651,7 +10652,7 @@ finish_function (int flags)
 
 tree
 start_method (cp_decl_specifier_seq *declspecs,
-              const cp_declarator *declarator, tree attrlist)
+              const cp_declarator *declarator, attribute_list attrlist)
 {
   tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
 				&attrlist);
Index: gcc/cp/decl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.h,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 decl.h
--- gcc/cp/decl.h	13 Jul 2004 21:11:50 -0000	1.16
+++ gcc/cp/decl.h	1 Oct 2004 00:57:25 -0000
@@ -33,7 +33,7 @@ enum decl_context
 /* We need this in here to get the decl_context definition.  */
 extern tree grokdeclarator (const cp_declarator *, 
 			    const cp_decl_specifier_seq *, 
-			    enum decl_context, int, tree*);
+			    enum decl_context, int, attribute_list*);
 
 #ifdef DEBUG_CP_BINDING_LEVELS
 /* Purely for debugging purposes.  */
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.749
diff -u -p -u -p -r1.749 decl2.c
--- gcc/cp/decl2.c	22 Sep 2004 18:12:05 -0000	1.749
+++ gcc/cp/decl2.c	1 Oct 2004 00:57:25 -0000
@@ -826,7 +826,7 @@ tree
 grokfield (const cp_declarator *declarator, 
 	   cp_decl_specifier_seq *declspecs, 
 	   tree init, tree asmspec_tree,
-           tree attrlist)
+           attribute_list attrlist)
 {
   tree value;
   const char *asmspec = 0;
@@ -1099,7 +1099,7 @@ grok_function_init (tree decl, tree init
 }
 
 void
-cplus_decl_attributes (tree *decl, tree attributes, int flags)
+cplus_decl_attributes (tree *decl, attribute_list attributes, int flags)
 {
   if (*decl == NULL_TREE || *decl == void_type_node)
     return;
@@ -1446,9 +1446,9 @@ import_export_class (tree ctype)
   if (CLASSTYPE_INTERFACE_ONLY (ctype))
     return;
 
-  if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
+  if (has_attribute_p ("dllimport", TYPE_ATTRIBUTES (ctype)))
     import_export = -1;
-  else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
+  else if (has_attribute_p ("dllexport", TYPE_ATTRIBUTES (ctype)))
     import_export = 1;
   else if (CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
 	   && !flag_implicit_templates)
@@ -1656,7 +1656,7 @@ determine_visibility (tree decl)
   if (class_type)
     {
       if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
-	  && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class_type)))
+	  && has_attribute_p ("dllexport", TYPE_ATTRIBUTES (class_type)))
 	{
 	  DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
 	  DECL_VISIBILITY_SPECIFIED (decl) = 1;
@@ -2088,7 +2088,7 @@ start_objects (int method_type, int init
 			    get_file_function_name_long (type),
 			    build_function_type (void_type_node,
 						 void_list_node));
-  start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
+  start_preparsed_function (fndecl, /*attrs=*/NULL, SF_PRE_PARSED);
 
   /* It can be a static function as long as collect2 does not have
      to scan the object file to find its ctor/dtor routine.  */
@@ -2256,7 +2256,7 @@ start_static_storage_duration_function (
      It is static because we only need to call this function from the
      various constructor and destructor functions for this module.  */
   start_preparsed_function (ssdf_decl,
-			    /*attrs=*/NULL_TREE,
+			    /*attrs=*/NULL,
 			    SF_PRE_PARSED);
 
   /* Set up the scope of the outermost block in the function.  */
Index: gcc/cp/friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.100
diff -u -p -u -p -r1.100 friend.c
--- gcc/cp/friend.c	30 Aug 2004 15:28:44 -0000	1.100
+++ gcc/cp/friend.c	1 Oct 2004 00:57:25 -0000
@@ -323,7 +323,7 @@ make_friend_class (tree type, tree frien
 
 tree
 do_friend (tree ctype, tree declarator, tree decl,
-	   tree attrlist, enum overload_flags flags, 
+	   attribute_list attrlist, enum overload_flags flags, 
 	   cp_cv_quals quals,
 	   int funcdef_flag)
 {
Index: gcc/cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.315
diff -u -p -u -p -r1.315 method.c
--- gcc/cp/method.c	10 Sep 2004 23:56:31 -0000	1.315
+++ gcc/cp/method.c	1 Oct 2004 00:57:26 -0000
@@ -445,7 +445,7 @@ use_thunk (tree thunk_fndecl, bool emit_
 
       DECL_RESULT (thunk_fndecl) = NULL_TREE;
 
-      start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
+      start_preparsed_function (thunk_fndecl, NULL, SF_PRE_PARSED);
       /* We don't bother with a body block for thunks.  */
 
       /* There's no need to check accessibility inside the thunk body.  */
@@ -725,7 +725,7 @@ synthesize_method (tree fndecl)
      function.  */
   DECL_SOURCE_LOCATION (fndecl) = input_location;
 
-  start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
+  start_preparsed_function (fndecl, NULL, SF_DEFAULT | SF_PRE_PARSED);
   stmt = begin_function_body ();
 
   if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
Index: gcc/cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.85
diff -u -p -u -p -r1.85 name-lookup.c
--- gcc/cp/name-lookup.c	30 Aug 2004 16:03:45 -0000	1.85
+++ gcc/cp/name-lookup.c	1 Oct 2004 00:57:26 -0000
@@ -3409,15 +3409,15 @@ do_using_directive (tree namespace)
    handle attributes here, since they cannot appear inside a template.  */
 
 void
-parse_using_directive (tree namespace, tree attribs)
+parse_using_directive (tree namespace, attribute_list attribs)
 {
-  tree a;
-
+  attribute_count ac;
+  
   do_using_directive (namespace);
 
-  for (a = attribs; a; a = TREE_CHAIN (a))
+  for (ac = 0; ac < ATTRIBUTE_COUNT (attribs); ac++)
     {
-      tree name = TREE_PURPOSE (a);
+      tree name = attribs->attribs[ac].name;
       if (is_attribute_p ("strong", name))
 	{
 	  if (!toplevel_bindings_p ())
Index: gcc/cp/name-lookup.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.h,v
retrieving revision 1.29
diff -u -p -u -p -r1.29 name-lookup.h
--- gcc/cp/name-lookup.h	10 Sep 2004 11:12:14 -0000	1.29
+++ gcc/cp/name-lookup.h	1 Oct 2004 00:57:26 -0000
@@ -327,7 +327,7 @@ extern tree do_class_using_decl (tree);
 extern void do_using_directive (tree);
 extern tree lookup_arg_dependent (tree, tree, tree);
 extern bool is_associated_namespace (tree, tree);
-extern void parse_using_directive (tree, tree);
+extern void parse_using_directive (tree, attribute_list);
 extern tree innermost_non_namespace_value (tree);
 extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
 
Index: gcc/cp/optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/optimize.c,v
retrieving revision 1.114
diff -u -p -u -p -r1.114 optimize.c
--- gcc/cp/optimize.c	4 Aug 2004 15:33:50 -0000	1.114
+++ gcc/cp/optimize.c	1 Oct 2004 00:57:26 -0000
@@ -132,7 +132,7 @@ maybe_clone_body (tree fn)
 	update_cloned_parm (parm, clone_parm);
 
       /* Start processing the function.  */
-      start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
+      start_preparsed_function (clone, NULL, SF_PRE_PARSED);
 
       /* Remap the parameters.  */
       decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
Index: gcc/cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.257
diff -u -p -u -p -r1.257 parser.c
--- gcc/cp/parser.c	27 Sep 2004 22:24:35 -0000	1.257
+++ gcc/cp/parser.c	1 Oct 2004 00:57:26 -0000
@@ -849,7 +849,7 @@ make_declarator (cp_declarator_kind kind
 
   declarator = (cp_declarator *) alloc_declarator (sizeof (cp_declarator));
   declarator->kind = kind;
-  declarator->attributes = NULL_TREE;
+  declarator->attributes = NULL;
   declarator->declarator = NULL;
 
   return declarator;
@@ -1581,7 +1581,7 @@ static tree cp_parser_class_name
 static tree cp_parser_class_specifier
   (cp_parser *);
 static tree cp_parser_class_head
-  (cp_parser *, bool *, tree *);
+  (cp_parser *, bool *, attribute_list *);
 static enum tag_types cp_parser_class_key
   (cp_parser *);
 static void cp_parser_member_specification_opt
@@ -1674,10 +1674,11 @@ static tree cp_parser_asm_operand_list
   (cp_parser *);
 static tree cp_parser_asm_clobber_list
   (cp_parser *);
-static tree cp_parser_attributes_opt
-  (cp_parser *);
-static tree cp_parser_attribute_list
+static attribute_list cp_parser_attributes_opt
   (cp_parser *);
+struct attribute_builder_data;
+static void cp_parser_attribute_list
+  (cp_parser *, struct attribute_builder_data *);
 static bool cp_parser_extension_opt
   (cp_parser *, int *);
 static void cp_parser_label_declaration
@@ -1702,7 +1703,8 @@ static tree cp_parser_global_scope_opt
 static bool cp_parser_constructor_declarator_p
   (cp_parser *, bool);
 static tree cp_parser_function_definition_from_specifiers_and_declarator
-  (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *);
+  (cp_parser *, cp_decl_specifier_seq *, attribute_list,
+   const cp_declarator *);
 static tree cp_parser_function_definition_after_declarator
   (cp_parser *, bool);
 static void cp_parser_template_declaration_after_export
@@ -1712,7 +1714,7 @@ static tree cp_parser_single_declaration
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
-  (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree);
+  (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, attribute_list);
 static tree cp_parser_enclosed_template_argument_list
   (cp_parser *);
 static void cp_parser_save_default_args
@@ -6240,7 +6242,7 @@ cp_parser_condition (cp_parser* parser)
     {
       tree decl;
       tree asm_specification;
-      tree attributes;
+      attribute_list attributes;
       cp_declarator *declarator;
       tree initializer = NULL_TREE;
 
@@ -6269,7 +6271,7 @@ cp_parser_condition (cp_parser* parser)
 	  /* Create the declaration.  */
 	  decl = start_decl (declarator, &type_specifiers,
 			     /*initialized_p=*/true,
-			     attributes, /*prefix_attributes=*/NULL_TREE,
+			     attributes, /*prefix_attributes=*/NULL,
 			     &pop_p);
 	  /* Parse the assignment-expression.  */
 	  initializer = cp_parser_assignment_expression (parser);
@@ -7091,8 +7093,8 @@ cp_parser_decl_specifier_seq (cp_parser*
 	{
 	  /* Parse the attributes.  */
 	  decl_specs->attributes
-	    = chainon (decl_specs->attributes,
-		       cp_parser_attributes_opt (parser));
+	    = merge_attributes (decl_specs->attributes,
+				cp_parser_attributes_opt (parser));
 	  continue;
 	}
       /* Assume we will find a decl-specifier keyword.  */
@@ -7481,7 +7483,7 @@ cp_parser_conversion_function_id (cp_par
 static tree
 cp_parser_conversion_type_id (cp_parser* parser)
 {
-  tree attributes;
+  attribute_list attributes;
   cp_decl_specifier_seq type_specifiers;
   cp_declarator *declarator;
   tree type_specified;
@@ -9603,7 +9605,7 @@ cp_parser_elaborated_type_specifier (cp_
   enum tag_types tag_type;
   tree identifier;
   tree type = NULL_TREE;
-  tree attributes = NULL_TREE;
+  attribute_list attributes = NULL;
 
   /* See if we're looking at the `enum' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
@@ -10220,7 +10222,7 @@ static void
 cp_parser_using_directive (cp_parser* parser)
 {
   tree namespace_decl;
-  tree attribs;
+  attribute_list attribs;
 
   /* Look for the `using' keyword.  */
   cp_parser_require_keyword (parser, RID_USING, "`using'");
@@ -10424,8 +10426,8 @@ cp_parser_init_declarator (cp_parser* pa
 {
   cp_token *token;
   cp_declarator *declarator;
-  tree prefix_attributes;
-  tree attributes;
+  attribute_list prefix_attributes;
+  attribute_list attributes;
   tree asm_specification;
   tree initializer;
   tree decl = NULL_TREE;
@@ -10484,7 +10486,7 @@ cp_parser_init_declarator (cp_parser* pa
   else
     {
       asm_specification = NULL_TREE;
-      attributes = NULL_TREE;
+      attributes = NULL;
     }
 
   /* Peek at the next token.  */
@@ -10649,7 +10651,7 @@ cp_parser_init_declarator (cp_parser* pa
 	pop_scope (scope);
       decl = grokfield (declarator, decl_specifiers,
 			initializer, /*asmspec=*/NULL_TREE,
-			/*attributes=*/NULL_TREE);
+			/*attributes=*/NULL);
       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
 	cp_parser_save_default_args (parser, decl);
     }
@@ -10728,7 +10730,7 @@ cp_parser_declarator (cp_parser* parser,
   enum tree_code code;
   cp_cv_quals cv_quals;
   tree class_type;
-  tree attributes = NULL_TREE;
+  attribute_list attributes = NULL;
 
   /* Assume this is not a constructor, destructor, or type-conversion
      operator.  */
@@ -11423,8 +11425,8 @@ cp_parser_type_specifier_seq (cp_parser*
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
 	{
 	  type_specifier_seq->attributes =
-	    chainon (type_specifier_seq->attributes,
-		     cp_parser_attributes_opt (parser));
+	    merge_attributes (type_specifier_seq->attributes,
+			      cp_parser_attributes_opt (parser));
 	  continue;
 	}
 
@@ -11743,8 +11745,8 @@ cp_parser_parameter_declaration (cp_pars
       parser->default_arg_ok_p = saved_default_arg_ok_p;
       /* After the declarator, allow more attributes.  */
       decl_specifiers.attributes
-	= chainon (decl_specifiers.attributes,
-		   cp_parser_attributes_opt (parser));
+	= merge_attributes (decl_specifiers.attributes,
+			    cp_parser_attributes_opt (parser));
     }
 
   /* The restriction on defining new types applies only to the type
@@ -12259,7 +12261,7 @@ cp_parser_class_specifier (cp_parser* pa
 {
   cp_token *token;
   tree type;
-  tree attributes = NULL_TREE;
+  attribute_list attributes = NULL;
   int has_trailing_semicolon;
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
@@ -12322,8 +12324,8 @@ cp_parser_class_specifier (cp_parser* pa
   /* Look for trailing attributes to apply to this class.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
-      tree sub_attr = cp_parser_attributes_opt (parser);
-      attributes = chainon (attributes, sub_attr);
+      attribute_list sub_attr = cp_parser_attributes_opt (parser);
+      attributes = merge_attributes (attributes, sub_attr);
     }
   if (type != error_mark_node)
     type = finish_struct (type, attributes);
@@ -12447,13 +12449,13 @@ cp_parser_class_specifier (cp_parser* pa
 static tree
 cp_parser_class_head (cp_parser* parser,
 		      bool* nested_name_specifier_p,
-		      tree *attributes_p)
+		      attribute_list *attributes_p)
 {
   tree nested_name_specifier;
   enum tag_types class_key;
   tree id = NULL_TREE;
   tree type = NULL_TREE;
-  tree attributes;
+  attribute_list attributes;
   bool template_id_p = false;
   bool qualified_p = false;
   bool invalid_nested_name_p = false;
@@ -12865,7 +12867,7 @@ static void
 cp_parser_member_declaration (cp_parser* parser)
 {
   cp_decl_specifier_seq decl_specifiers;
-  tree prefix_attributes;
+  attribute_list prefix_attributes;
   tree decl;
   int declares_class_or_enum;
   bool friend_p;
@@ -12907,7 +12909,7 @@ cp_parser_member_declaration (cp_parser*
 				&decl_specifiers,
 				&declares_class_or_enum);
   prefix_attributes = decl_specifiers.attributes;
-  decl_specifiers.attributes = NULL_TREE;
+  decl_specifiers.attributes = NULL;
   /* Check for an invalid type-name.  */
   if (cp_parser_parse_and_diagnose_invalid_type_name (parser))
     return;
@@ -12996,8 +12998,7 @@ cp_parser_member_declaration (cp_parser*
 	 declaration.  */
       while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
 	{
-	  tree attributes = NULL_TREE;
-	  tree first_attribute;
+	  attribute_list attributes = NULL;
 
 	  /* Peek at the next token.  */
 	  token = cp_lexer_peek_token (parser->lexer);
@@ -13029,11 +13030,8 @@ cp_parser_member_declaration (cp_parser*
 
 	      /* Look for attributes that apply to the bitfield.  */
 	      attributes = cp_parser_attributes_opt (parser);
-	      /* Remember which attributes are prefix attributes and
-		 which are not.  */
-	      first_attribute = attributes;
 	      /* Combine the attributes.  */
-	      attributes = chainon (prefix_attributes, attributes);
+	      attributes = merge_attributes (prefix_attributes, attributes);
 
 	      /* Create the bitfield declaration.  */
 	      decl = grokbitfield (identifier
@@ -13081,11 +13079,8 @@ cp_parser_member_declaration (cp_parser*
 	      asm_specification = cp_parser_asm_specification_opt (parser);
 	      /* Look for attributes that apply to the declaration.  */
 	      attributes = cp_parser_attributes_opt (parser);
-	      /* Remember which attributes are prefix attributes and
-		 which are not.  */
-	      first_attribute = attributes;
 	      /* Combine the attributes.  */
-	      attributes = chainon (prefix_attributes, attributes);
+	      attributes = merge_attributes (prefix_attributes, attributes);
 
 	      /* If it's an `=', then we have a constant-initializer or a
 		 pure-specifier.  It is not correct to parse the
@@ -13161,12 +13156,6 @@ cp_parser_member_declaration (cp_parser*
 		}
 	    }
 
-	  /* Reset PREFIX_ATTRIBUTES.  */
-	  while (attributes && TREE_CHAIN (attributes) != first_attribute)
-	    attributes = TREE_CHAIN (attributes);
-	  if (attributes)
-	    TREE_CHAIN (attributes) = NULL_TREE;
-
 	  /* If there is any qualification still in effect, clear it
 	     now; we will be starting fresh with the next declarator.  */
 	  parser->scope = NULL_TREE;
@@ -13864,17 +13853,34 @@ cp_parser_asm_clobber_list (cp_parser* p
    attribute:
      __attribute__ (( attribute-list [opt] ))
 
-   The return value is as for cp_parser_attribute_list.  */
+   The return value is an attribute list.  */
 
-static tree
+/* This is used to construct the array of attributes.  We expect that
+   most of the time, there will be less (much less!) than 10 attributes.
+   USED holds the number of entries in *ATTRS that have been used,
+   SIZE holds the maximum number of entries in *ATTRS.  If SIZE is
+   insufficient, ATTRS must be enlarged by using xrealloc, or using
+   xmemdup if ATTRS points to INIT_ATTRS.  */
+struct attribute_builder_data {
+  struct one_attribute *attrs;
+  attribute_count size;
+  attribute_count used;
+  struct one_attribute init_attrs[10];
+};
+
+static attribute_list
 cp_parser_attributes_opt (cp_parser* parser)
 {
-  tree attributes = NULL_TREE;
-
+  struct attribute_builder_data abd;
+  attribute_list attributes;
+  
+  abd.attrs = abd.init_attrs;
+  abd.size = ARRAY_SIZE (abd.init_attrs);
+  abd.used = 0;
+  
   while (true)
     {
       cp_token *token;
-      tree attribute_list;
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -13890,22 +13896,21 @@ cp_parser_attributes_opt (cp_parser* par
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
+      /* If the next token is a `)', then there is no attribute
+	 list.  */
       if (token->type != CPP_CLOSE_PAREN)
 	/* Parse the attribute-list.  */
-	attribute_list = cp_parser_attribute_list (parser);
-      else
-	/* If the next token is a `)', then there is no attribute
-	   list.  */
-	attribute_list = NULL;
+	cp_parser_attribute_list (parser, &abd);
 
       /* Look for the two `)' tokens.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-
-      /* Add these new attributes to the list.  */
-      attributes = chainon (attributes, attribute_list);
     }
 
+  attributes = merge_attributes_1 (NULL, abd.used, abd.attrs, NULL, 0);
+  if (abd.attrs != abd.init_attrs)
+    free (abd.attrs);
+
   return attributes;
 }
 
@@ -13921,36 +13926,43 @@ cp_parser_attributes_opt (cp_parser* par
      identifier ( identifier , expression-list )
      identifier ( expression-list )
 
-   Returns a TREE_LIST.  Each node corresponds to an attribute.  THe
-   TREE_PURPOSE of each node is the identifier indicating which
-   attribute is in use.  The TREE_VALUE represents the arguments, if
-   any.  */
+   Adds each attribute to ABD.  */
 
-static tree
-cp_parser_attribute_list (cp_parser* parser)
+static void
+cp_parser_attribute_list (cp_parser* parser,
+			  struct attribute_builder_data *abd)
 {
-  tree attribute_list = NULL_TREE;
   bool save_translate_strings_p = parser->translate_strings_p;
 
   parser->translate_strings_p = false;
   while (true)
     {
       cp_token *token;
-      tree identifier;
-      tree attribute;
 
       /* Look for the identifier.  We also allow keywords here; for
 	 example `__attribute__ ((const))' is legal.  */
       token = cp_lexer_peek_token (parser->lexer);
       if (token->type != CPP_NAME
 	  && token->type != CPP_KEYWORD)
-	return error_mark_node;
+	return;
       /* Consume the token.  */
       token = cp_lexer_consume_token (parser->lexer);
 
+      /* Make room for more attributes, if necessary.  */
+      if (abd->used == abd->size)
+	{
+	  abd->size *= 2;
+	  if (abd->attrs == abd->init_attrs)
+	    abd->attrs = xmemdup (abd->attrs,
+				  abd->used * sizeof (*abd->attrs),
+				  abd->size * sizeof (*abd->attrs));
+	  else
+	    abd->attrs = xrealloc (abd->attrs,
+				   abd->size * sizeof (*abd->attrs));
+	}
+
       /* Save away the identifier that indicates which attribute this is.  */
-      identifier = token->value;
-      attribute = build_tree_list (identifier, NULL_TREE);
+      abd->attrs[abd->used].name = token->value;
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -13962,13 +13974,16 @@ cp_parser_attribute_list (cp_parser* par
 	  arguments = (cp_parser_parenthesized_expression_list
 		       (parser, true, /*non_constant_p=*/NULL));
 	  /* Save the identifier and arguments away.  */
-	  TREE_VALUE (attribute) = arguments;
+	  abd->attrs[abd->used].value = arguments;
 	}
+      else
+	abd->attrs[abd->used].value = NULL_TREE;
 
-      /* Add this attribute to the list.  */
-      TREE_CHAIN (attribute) = attribute_list;
-      attribute_list = attribute;
-
+      /* Keep this attribute.  */
+      abd->used++;
+      if (abd->used == 0)
+	error ("too many attributes");
+      
       /* Now, look for more attributes.  */
       token = cp_lexer_peek_token (parser->lexer);
       /* If the next token isn't a `,', we're done.  */
@@ -13979,9 +13994,6 @@ cp_parser_attribute_list (cp_parser* par
       cp_lexer_consume_token (parser->lexer);
     }
   parser->translate_strings_p = save_translate_strings_p;
-
-  /* We built up the list in reverse order.  */
-  return nreverse (attribute_list);
 }
 
 /* Parse an optional `__extension__' keyword.  Returns TRUE if it is
@@ -14629,7 +14641,7 @@ static tree
 cp_parser_function_definition_from_specifiers_and_declarator
   (cp_parser* parser,
    cp_decl_specifier_seq *decl_specifiers,
-   tree attributes,
+   attribute_list attributes,
    const cp_declarator *declarator)
 {
   tree fn;
@@ -14939,7 +14951,7 @@ static tree
 cp_parser_save_member_function_body (cp_parser* parser,
 				     cp_decl_specifier_seq *decl_specifiers,
 				     cp_declarator *declarator,
-				     tree attributes)
+				     attribute_list attributes)
 {
   cp_token *first;
   cp_token *last;
@@ -15116,7 +15128,7 @@ cp_parser_late_parsing_for_member (cp_pa
 
       /* Let the front end know that we going to be defining this
 	 function.  */
-      start_preparsed_function (member_function, NULL_TREE,
+      start_preparsed_function (member_function, NULL,
 				SF_PRE_PARSED | SF_INCLASS_INLINE);
 
       /* Now, parse the body of the function.  */
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.929
diff -u -p -u -p -r1.929 pt.c
--- gcc/cp/pt.c	28 Sep 2004 08:50:56 -0000	1.929
+++ gcc/cp/pt.c	1 Oct 2004 00:57:27 -0000
@@ -11176,7 +11176,7 @@ instantiate_decl (tree d, int defer_ok, 
 					   NULL);
 
       /* Set up context.  */
-      start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+      start_preparsed_function (d, NULL, SF_PRE_PARSED);
 
       /* Create substitution entries for the parameters.  */
       subst_decl = DECL_TEMPLATE_RESULT (template_for_substitution (d));
Index: gcc/cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.413
diff -u -p -u -p -r1.413 tree.c
--- gcc/cp/tree.c	28 Sep 2004 11:55:45 -0000	1.413
+++ gcc/cp/tree.c	1 Oct 2004 00:57:27 -0000
@@ -48,9 +48,12 @@ static tree verify_stmt_tree_r (tree *, 
 static tree find_tree_r (tree *, int *, void *);
 static tree build_local_temp (tree);
 
-static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
-static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
-static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
+static void handle_java_interface_attribute (tree *, tree, tree, int, bool *,
+					     bool *);
+static void handle_com_interface_attribute (tree *, tree, tree, int, bool *,
+					    bool *);
+static void handle_init_priority_attribute (tree *, tree, tree, int, bool *,
+					    bool *);
 
 /* If REF is an lvalue, returns the kind of lvalue that REF is.
    Otherwise, returns clk_none.  If TREAT_CLASS_RVALUES_AS_LVALUES is
@@ -1754,12 +1757,13 @@ const struct attribute_spec cxx_attribut
 
 /* Handle a "java_interface" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 handle_java_interface_attribute (tree* node,
                                  tree name,
                                  tree args ATTRIBUTE_UNUSED ,
                                  int flags,
-                                 bool* no_add_attrs)
+                                 bool* no_add_attrs,
+				 bool * ARG_UNUSED (defer))
 {
   if (DECL_P (*node)
       || !CLASS_TYPE_P (*node)
@@ -1768,23 +1772,22 @@ handle_java_interface_attribute (tree* n
       error ("`%E' attribute can only be applied to Java class definitions",
 	     name);
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
   if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
     *node = build_variant_type_copy (*node);
   TYPE_JAVA_INTERFACE (*node) = 1;
-
-  return NULL_TREE;
 }
 
 /* Handle a "com_interface" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 handle_com_interface_attribute (tree* node,
                                 tree name,
                                 tree args ATTRIBUTE_UNUSED ,
                                 int flags ATTRIBUTE_UNUSED ,
-                                bool* no_add_attrs)
+                                bool* no_add_attrs,
+				bool * ARG_UNUSED (defer))
 {
   static int warned;
 
@@ -1796,24 +1799,23 @@ handle_com_interface_attribute (tree* no
     {
       warning ("`%E' attribute can only be applied to class definitions",
 	       name);
-      return NULL_TREE;
+      return;
     }
 
   if (!warned++)
     warning ("`%E' is obsolete; g++ vtables are now COM-compatible by default",
 	     name);
-
-  return NULL_TREE;
 }
 
 /* Handle an "init_priority" attribute; arguments as in
    struct attribute_spec.handler.  */
-static tree
+static void
 handle_init_priority_attribute (tree* node,
                                 tree name,
                                 tree args,
                                 int flags ATTRIBUTE_UNUSED ,
-                                bool* no_add_attrs)
+                                bool* no_add_attrs,
+				bool * ARG_UNUSED (defer))
 {
   tree initp_expr = TREE_VALUE (args);
   tree decl = *node;
@@ -1826,7 +1828,7 @@ handle_init_priority_attribute (tree* no
     {
       error ("requested init_priority is not an integer constant");
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   pri = TREE_INT_CST_LOW (initp_expr);
@@ -1848,14 +1850,14 @@ handle_init_priority_attribute (tree* no
       error ("can only use `%E' attribute on file-scope definitions "
              "of objects of class type", name);
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   if (pri > MAX_INIT_PRIORITY || pri <= 0)
     {
       error ("requested init_priority is out of range");
       *no_add_attrs = true;
-      return NULL_TREE;
+      return;
     }
 
   /* Check for init_priorities that are reserved for
@@ -1867,15 +1869,11 @@ handle_init_priority_attribute (tree* no
     }
 
   if (SUPPORTS_INIT_PRIORITY)
-    {
-      DECL_INIT_PRIORITY (decl) = pri;
-      return NULL_TREE;
-    }
+    DECL_INIT_PRIORITY (decl) = pri;
   else
     {
       error ("`%E' attribute is not supported on this platform", name);
       *no_add_attrs = true;
-      return NULL_TREE;
     }
 }
 
@@ -1906,7 +1904,7 @@ make_ptrmem_cst (tree type, tree member)
    return an existing type of an appropriate type already exists.  */
 
 tree
-cp_build_type_attribute_variant (tree type, tree attributes)
+cp_build_type_attribute_variant (tree type, attribute_list attributes)
 {
   tree new_type;
 
@@ -2027,7 +2025,7 @@ cp_cannot_inline_tree_fn (tree* fnp)
     }
 
   if (flag_really_no_inline
-      && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
+      && !has_attribute_p ("always_inline", DECL_ATTRIBUTES (fn)))
     return 1;
 
   /* Don't auto-inline anything that might not be bound within
Index: gcc/cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.579
diff -u -p -u -p -r1.579 typeck.c
--- gcc/cp/typeck.c	28 Sep 2004 02:56:07 -0000	1.579
+++ gcc/cp/typeck.c	1 Oct 2004 00:57:27 -0000
@@ -260,7 +260,7 @@ type_after_usual_arithmetic_conversions 
 {
   enum tree_code code1 = TREE_CODE (t1);
   enum tree_code code2 = TREE_CODE (t2);
-  tree attributes;
+  attribute_list attributes;
 
   /* FIXME: Attributes.  */
   gcc_assert (ARITHMETIC_TYPE_P (t1) 
@@ -401,7 +401,7 @@ composite_pointer_type_r (tree t1, tree 
   tree pointee1;
   tree pointee2;
   tree result_type;
-  tree attributes;
+  attribute_list attributes;
 
   /* Determine the types pointed to by T1 and T2.  */
   if (TREE_CODE (t1) == POINTER_TYPE)
@@ -503,7 +503,7 @@ composite_pointer_type (tree t1, tree t2
   /* Now, if T1 is a pointer to void, merge the qualifiers.  */
   if (TREE_CODE (t1) == POINTER_TYPE && VOID_TYPE_P (TREE_TYPE (t1)))
     {
-      tree attributes;
+      attribute_list attributes;
       tree result_type;
 
       if (pedantic && TYPE_PTRFN_P (t2))
@@ -578,7 +578,7 @@ merge_types (tree t1, tree t2)
 {
   enum tree_code code1;
   enum tree_code code2;
-  tree attributes;
+  attribute_list attributes;
 
   /* Save time if the two types are the same.  */
   if (t1 == t2)
Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.199
diff -u -p -u -p -r1.199 decl.c
--- gcc/java/decl.c	30 Sep 2004 02:16:45 -0000	1.199
+++ gcc/java/decl.c	1 Oct 2004 00:57:28 -0000
@@ -499,7 +499,7 @@ builtin_function (const char *name,
 		  int function_code,
 		  enum built_in_class cl,
 		  const char *library_name,
-		  tree ARG_UNUSED (attrs))
+		  attribute_list ARG_UNUSED (attrs))
 {
   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
   DECL_EXTERNAL (decl) = 1;
@@ -899,23 +899,23 @@ java_init_decl_processing (void)
 		 tree_cons (NULL_TREE, int_type_node, endlink));
   alloc_object_node = builtin_function ("_Jv_AllocObject",
 					build_function_type (ptr_type_node, t),
-					0, NOT_BUILT_IN, NULL, NULL_TREE);
+					0, NOT_BUILT_IN, NULL, NULL);
   DECL_IS_MALLOC (alloc_object_node) = 1;
   alloc_no_finalizer_node = 
     builtin_function ("_Jv_AllocObjectNoFinalizer",
 		      build_function_type (ptr_type_node, t),
-		      0, NOT_BUILT_IN, NULL, NULL_TREE);
+		      0, NOT_BUILT_IN, NULL, NULL);
   DECL_IS_MALLOC (alloc_no_finalizer_node) = 1;
 
   t = tree_cons (NULL_TREE, ptr_type_node, endlink);
   soft_initclass_node = builtin_function ("_Jv_InitClass",
 					  build_function_type (void_type_node,
 							       t),
-					  0, NOT_BUILT_IN, NULL, NULL_TREE);
+					  0, NOT_BUILT_IN, NULL, NULL);
 
   throw_node = builtin_function ("_Jv_Throw",
 				 build_function_type (ptr_type_node, t),
-				 0, NOT_BUILT_IN, NULL, NULL_TREE);
+				 0, NOT_BUILT_IN, NULL, NULL);
   /* Mark throw_nodes as `noreturn' functions with side effects.  */
   TREE_THIS_VOLATILE (throw_node) = 1;
   TREE_SIDE_EFFECTS (throw_node) = 1;
@@ -923,17 +923,17 @@ java_init_decl_processing (void)
   t = build_function_type (int_type_node, endlink);
   soft_monitorenter_node 
     = builtin_function ("_Jv_MonitorEnter", t, 0, NOT_BUILT_IN,
-			NULL, NULL_TREE);
+			NULL, NULL);
   soft_monitorexit_node 
     = builtin_function ("_Jv_MonitorExit", t, 0, NOT_BUILT_IN,
-			NULL, NULL_TREE);
+			NULL, NULL);
   
   t = tree_cons (NULL_TREE, int_type_node, 
 		 tree_cons (NULL_TREE, int_type_node, endlink));
   soft_newarray_node
       = builtin_function ("_Jv_NewPrimArray",
 			  build_function_type(ptr_type_node, t),
-			  0, NOT_BUILT_IN, NULL, NULL_TREE);
+			  0, NOT_BUILT_IN, NULL, NULL);
   DECL_IS_MALLOC (soft_newarray_node) = 1;
 
   t = tree_cons (NULL_TREE, int_type_node,
@@ -942,7 +942,7 @@ java_init_decl_processing (void)
   soft_anewarray_node
       = builtin_function ("_Jv_NewObjectArray",
 			  build_function_type (ptr_type_node, t),
-			  0, NOT_BUILT_IN, NULL, NULL_TREE);
+			  0, NOT_BUILT_IN, NULL, NULL);
   DECL_IS_MALLOC (soft_anewarray_node) = 1;
 
   /* There is no endlink here because _Jv_NewMultiArray is a varargs
@@ -952,14 +952,14 @@ java_init_decl_processing (void)
   soft_multianewarray_node
       = builtin_function ("_Jv_NewMultiArray",
 			  build_function_type (ptr_type_node, t),
-			  0, NOT_BUILT_IN, NULL, NULL_TREE);
+			  0, NOT_BUILT_IN, NULL, NULL);
   DECL_IS_MALLOC (soft_multianewarray_node) = 1;
 
   t = build_function_type (void_type_node, 
 			   tree_cons (NULL_TREE, int_type_node, endlink));
   soft_badarrayindex_node
       = builtin_function ("_Jv_ThrowBadArrayIndex", t, 
-			  0, NOT_BUILT_IN, NULL, NULL_TREE);
+			  0, NOT_BUILT_IN, NULL, NULL);
   /* Mark soft_badarrayindex_node as a `noreturn' function with side
      effects.  */
   TREE_THIS_VOLATILE (soft_badarrayindex_node) = 1;
@@ -968,7 +968,7 @@ java_init_decl_processing (void)
   soft_nullpointer_node
     = builtin_function ("_Jv_ThrowNullPointerException",
 			build_function_type (void_type_node, endlink),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
   /* Mark soft_nullpointer_node as a `noreturn' function with side
      effects.  */
   TREE_THIS_VOLATILE (soft_nullpointer_node) = 1;
@@ -979,27 +979,27 @@ java_init_decl_processing (void)
   soft_checkcast_node
     = builtin_function ("_Jv_CheckCast",
 			build_function_type (ptr_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
   t = tree_cons (NULL_TREE, object_ptr_type_node,
 		 tree_cons (NULL_TREE, class_ptr_type, endlink));
   soft_instanceof_node
     = builtin_function ("_Jv_IsInstanceOf",
 			build_function_type (boolean_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
   DECL_IS_PURE (soft_instanceof_node) = 1;
   t = tree_cons (NULL_TREE, object_ptr_type_node,
 		 tree_cons (NULL_TREE, object_ptr_type_node, endlink));
   soft_checkarraystore_node
     = builtin_function ("_Jv_CheckArrayStore",
 			build_function_type (void_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
   t = tree_cons (NULL_TREE, ptr_type_node,
 		 tree_cons (NULL_TREE, ptr_type_node,
 			    tree_cons (NULL_TREE, int_type_node, endlink)));
   soft_lookupinterfacemethod_node 
     = builtin_function ("_Jv_LookupInterfaceMethodIdx",
 			build_function_type (ptr_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
 
   DECL_IS_PURE (soft_lookupinterfacemethod_node) = 1;
   t = tree_cons (NULL_TREE, object_ptr_type_node,
@@ -1010,36 +1010,36 @@ java_init_decl_processing (void)
   soft_lookupjnimethod_node
     = builtin_function ("_Jv_LookupJNIMethod",
 			build_function_type (ptr_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
   t = tree_cons (NULL_TREE, ptr_type_node, endlink);
   soft_getjnienvnewframe_node
     = builtin_function ("_Jv_GetJNIEnvNewFrame",
 			build_function_type (ptr_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
   soft_jnipopsystemframe_node
     = builtin_function ("_Jv_JNI_PopSystemFrame",
 			build_function_type (ptr_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
 
   soft_idiv_node
     = builtin_function ("_Jv_divI",
 			build_function_type (int_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
 
   soft_irem_node
     = builtin_function ("_Jv_remI",
 			build_function_type (int_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
 
   soft_ldiv_node
     = builtin_function ("_Jv_divJ",
 			build_function_type (long_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
 
   soft_lrem_node
     = builtin_function ("_Jv_remJ",
 			build_function_type (long_type_node, t),
-			0, NOT_BUILT_IN, NULL, NULL_TREE);
+			0, NOT_BUILT_IN, NULL, NULL);
 
   /* Initialize variables for except.c.  */
   eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.218
diff -u -p -u -p -r1.218 java-tree.h
--- gcc/java/java-tree.h	30 Sep 2004 23:25:27 -0000	1.218
+++ gcc/java/java-tree.h	1 Oct 2004 00:57:28 -0000
@@ -1358,7 +1358,7 @@ extern int split_qualified_name (tree *l
 extern int in_same_package (tree, tree);
 
 extern tree builtin_function (const char *, tree, int, enum built_in_class,
-			      const char *, tree);
+			      const char *, attribute_list);
 
 #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
 
Index: gcc/java/jcf-reader.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-reader.c,v
retrieving revision 1.23
diff -u -p -u -p -r1.23 jcf-reader.c
--- gcc/java/jcf-reader.c	24 Feb 2003 02:14:49 -0000	1.23
+++ gcc/java/jcf-reader.c	1 Oct 2004 00:57:28 -0000
@@ -28,7 +28,7 @@ The Free Software Foundation is independ
 #include "jcf.h"
 #include "zipfile.h"
 
-static int get_attribute (JCF *);
+static int jcf_get_attribute (JCF *);
 static int jcf_parse_preamble (JCF *);
 static int jcf_parse_constant_pool (JCF *);
 static void jcf_parse_class (JCF *);
@@ -103,7 +103,7 @@ skip_attribute (JCF *jcf, int number_of_
 #endif
 
 static int
-get_attribute (JCF *jcf)
+jcf_get_attribute (JCF *jcf)
 {
   uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf));
   uint32 attribute_length = JCF_readu4 (jcf);
@@ -168,7 +168,7 @@ get_attribute (JCF *jcf)
       attributes_count = JCF_readu2 (jcf);
       for (j = 0; j < attributes_count; j++)
 	{
-	  int code = get_attribute (jcf);
+	  int code = jcf_get_attribute (jcf);
 	  if (code != 0)
 	    return code;
 	}
@@ -377,7 +377,7 @@ jcf_parse_fields (JCF* jcf)
 #endif
       for (j = 0; j < attribute_count; j++)
 	{
-	  int code = get_attribute (jcf);
+	  int code = jcf_get_attribute (jcf);
 	  if (code != 0)
 	    return code;
 	}
@@ -406,7 +406,7 @@ jcf_parse_one_method (JCF* jcf)
 #endif
   for (i = 0; i < attribute_count; i++)
     {
-      int code = get_attribute (jcf);
+      int code = jcf_get_attribute (jcf);
       if (code != 0)
 	return code;
     }
@@ -449,7 +449,7 @@ jcf_parse_final_attributes (JCF *jcf)
 #endif
   for (i = 0; i < attributes_count; i++)
     {
-      int code = get_attribute (jcf);
+      int code = jcf_get_attribute (jcf);
       if (code != 0)
 	return code;
     }
Index: gcc/objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.248
diff -u -p -u -p -r1.248 objc-act.c
--- gcc/objc/objc-act.c	24 Sep 2004 23:15:33 -0000	1.248
+++ gcc/objc/objc-act.c	1 Oct 2004 00:57:29 -0000
@@ -157,9 +157,10 @@ 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);
+static void objc_start_function (tree, tree, attribute_list, tree);
 #else
-static void objc_start_function (tree, tree, tree, struct c_arg_info *);
+static void objc_start_function (tree, tree, attribute_list,
+				 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);
@@ -496,7 +497,7 @@ generate_struct_by_value_array (void)
 					  buffer);
 	  chainon (field_decl_chain, field_decl);
 	}
-      finish_struct (type, field_decl_chain, NULL_TREE);
+      finish_struct (type, field_decl_chain, NULL);
 
       aggregate_in_mem[i] = aggregate_value_p (type, 0);
       if (!aggregate_in_mem[i])
@@ -1406,16 +1407,16 @@ synth_module_prologue (void)
 						     NULL_TREE)));
       umsg_decl = builtin_function (TAG_MSGSEND,
 				    type, 0, NOT_BUILT_IN,
-				    NULL, NULL_TREE);
+				    NULL, NULL);
       umsg_nonnil_decl = builtin_function (TAG_MSGSEND_NONNIL,
 					   type, 0, NOT_BUILT_IN,
-					   NULL, NULL_TREE);
+					   NULL, NULL);
       umsg_stret_decl = builtin_function (TAG_MSGSEND_STRET,
 					  type, 0, NOT_BUILT_IN,
-					  NULL, NULL_TREE);
+					  NULL, NULL);
       umsg_nonnil_stret_decl = builtin_function (TAG_MSGSEND_NONNIL_STRET,
 						 type, 0, NOT_BUILT_IN,
-						 NULL, NULL_TREE);
+						 NULL, NULL);
 
       /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
       /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
@@ -1426,10 +1427,10 @@ synth_module_prologue (void)
 						     NULL_TREE)));
       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
 					  type, 0, NOT_BUILT_IN,
-					  NULL, NULL_TREE);
+					  NULL, NULL);
       umsg_super_stret_decl = builtin_function (TAG_MSGSENDSUPER_STRET,
 						type, 0, NOT_BUILT_IN, 0,
-						NULL_TREE);
+						NULL);
     }
   else
     {
@@ -1451,7 +1452,7 @@ synth_module_prologue (void)
 						     OBJC_VOID_AT_END)));
       umsg_decl = builtin_function (TAG_MSGSEND,
 				    type, 0, NOT_BUILT_IN,
-				    NULL, NULL_TREE);
+				    NULL, NULL);
 
       /* IMP objc_msg_lookup_super (struct objc_super *, SEL); */
       type
@@ -1461,7 +1462,7 @@ synth_module_prologue (void)
 						     OBJC_VOID_AT_END)));
       umsg_super_decl = builtin_function (TAG_MSGSENDSUPER,
 					  type, 0, NOT_BUILT_IN,
-					  NULL, NULL_TREE);
+					  NULL, NULL);
 
       /* The following GNU runtime entry point is called to initialize
 	 each module:
@@ -1473,7 +1474,7 @@ synth_module_prologue (void)
 					  OBJC_VOID_AT_END));
       execclass_decl = builtin_function (TAG_EXECCLASS,
 					 type, 0, NOT_BUILT_IN,
-					 NULL, NULL_TREE);
+					 NULL, NULL);
     }
 
   /* id objc_getClass (const char *); */
@@ -1485,12 +1486,12 @@ synth_module_prologue (void)
 
   objc_get_class_decl
     = builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
-			NULL, NULL_TREE);
+			NULL, NULL);
 
   /* id objc_getMetaClass (const char *); */
 
   objc_get_meta_class_decl
-    = builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL);
 
   build_class_template ();
   build_super_template ();
@@ -1813,7 +1814,7 @@ build_objc_symtab_template (void)
       chainon (field_decl_chain, field_decl);
     }
 
-  finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_symtab_template, field_decl_chain, NULL);
 }
 
 /* Create the initial value for the `defs' field of _objc_symtab.
@@ -2031,7 +2032,7 @@ build_module_descriptor (void)
 			 "symtab");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_module_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_module_template, field_decl_chain, NULL);
 
   /* Create an instance of "_objc_module".  */
   UOBJC_MODULES_decl = start_var_decl (objc_module_template, "_OBJC_MODULES");
@@ -2063,7 +2064,7 @@ build_module_initializer_routine (void)
   objc_start_function (get_identifier (TAG_GNUINIT),
 		       build_function_type (void_type_node,
 					    OBJC_VOID_AT_END),
-		       NULL_TREE, objc_get_parm_info (0));
+		       NULL, objc_get_parm_info (0));
 
   body = c_begin_compound_stmt (true);
   add_stmt (build_function_call
@@ -3398,14 +3399,14 @@ build_next_objc_exception_stuff (void)
 				  "pointers");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_exception_data_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_exception_data_template, field_decl_chain, NULL);
 
   /* int _setjmp(...); */
   /* If the user includes <setjmp.h>, this shall be superseded by
      'int _setjmp(jmp_buf);' */
   temp_type = build_function_type (integer_type_node, NULL_TREE);
   objc_setjmp_decl
-    = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL);
 
   /* id objc_exception_extract(struct _objc_exception_data *); */
   temp_type
@@ -3414,7 +3415,7 @@ build_next_objc_exception_stuff (void)
 				      build_pointer_type (objc_exception_data_template),
 				      OBJC_VOID_AT_END));
   objc_exception_extract_decl
-    = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, NULL);
   /* void objc_exception_try_enter(struct _objc_exception_data *); */
   /* void objc_exception_try_exit(struct _objc_exception_data *); */
   temp_type
@@ -3423,9 +3424,9 @@ build_next_objc_exception_stuff (void)
 				      build_pointer_type (objc_exception_data_template),
 				      OBJC_VOID_AT_END));
   objc_exception_try_enter_decl
-    = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, NULL);
   objc_exception_try_exit_decl
-    = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, NULL);
 
   /* int objc_exception_match(id, id); */
   temp_type 
@@ -3434,16 +3435,21 @@ build_next_objc_exception_stuff (void)
 				      tree_cons (NULL_TREE, objc_object_type,
 						 OBJC_VOID_AT_END)));
   objc_exception_match_decl
-    = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
+    = builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, NULL);
 }
 
 static void
 build_objc_exception_stuff (void)
 {
-  tree noreturn_list, nothrow_list, temp_type;
-
-  noreturn_list = tree_cons (get_identifier ("noreturn"), NULL, NULL);
-  nothrow_list = tree_cons (get_identifier ("nothrow"), NULL, NULL);
+  attribute_list noreturn_list, nothrow_list;
+  tree temp_type;
+  struct one_attribute oa;
+
+  oa.value = NULL_TREE;
+  oa.name = get_identifier ("noreturn");
+  noreturn_list = merge_attributes_1 (NULL, 1, &oa, NULL, 0);
+  oa.name = get_identifier ("nothrow");
+  nothrow_list = merge_attributes_1 (NULL, 1, &oa, NULL, 0);
 
   /* void objc_exception_throw(id) __attribute__((noreturn)); */
   /* void objc_sync_enter(id); */
@@ -3483,7 +3489,7 @@ build_private_template (tree class)
       uprivate_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
       ivar_context = get_class_ivars (class);
 
-      finish_struct (uprivate_record, ivar_context, NULL_TREE);
+      finish_struct (uprivate_record, ivar_context, NULL);
 
       CLASS_STATIC_TEMPLATE (class) = uprivate_record;
 
@@ -3548,7 +3554,7 @@ build_protocol_template (void)
 				  "class_methods");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_protocol_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_protocol_template, field_decl_chain, NULL);
 }
 
 static tree
@@ -3612,7 +3618,7 @@ build_method_prototype_list_template (tr
 				  "method_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
+  finish_struct (objc_ivar_list_record, field_decl_chain, NULL);
 
   return objc_ivar_list_record;
 }
@@ -3634,7 +3640,7 @@ build_method_prototype_template (void)
   field_decl = create_field_decl (string_type_node, "method_types");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (proto_record, field_decl_chain, NULL_TREE);
+  finish_struct (proto_record, field_decl_chain, NULL);
 
   return proto_record;
 }
@@ -4023,7 +4029,7 @@ build_category_template (void)
 				  "protocol_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_category_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_category_template, field_decl_chain, NULL);
 }
 
 /* struct _objc_selector {
@@ -4048,7 +4054,7 @@ build_selector_template (void)
   field_decl = create_field_decl (string_type_node, "sel_type");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_selector_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_selector_template, field_decl_chain, NULL);
 }
 
 /* struct _objc_class {
@@ -4184,7 +4190,7 @@ build_class_template (void)
 				  "gc_object_type");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_class_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_class_template, field_decl_chain, NULL);
 }
 
 /* Generate appropriate forward declarations for an implementation.  */
@@ -4296,7 +4302,7 @@ build_super_template (void)
 				  "super_class");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_super_template, field_decl_chain, NULL_TREE);
+  finish_struct (objc_super_template, field_decl_chain, NULL);
 }
 
 /* struct _objc_ivar {
@@ -4326,7 +4332,7 @@ build_ivar_template (void)
   field_decl = create_field_decl (integer_type_node, "ivar_offset");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_record, field_decl_chain, NULL_TREE);
+  finish_struct (objc_ivar_record, field_decl_chain, NULL);
 
   return objc_ivar_record;
 }
@@ -4356,7 +4362,7 @@ build_ivar_list_template (tree list_type
 				  "ivar_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
+  finish_struct (objc_ivar_list_record, field_decl_chain, NULL);
 
   return objc_ivar_list_record;
 }
@@ -4395,7 +4401,7 @@ build_method_list_template (tree list_ty
 				  "method_list");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (objc_ivar_list_record, field_decl_chain, NULL_TREE);
+  finish_struct (objc_ivar_list_record, field_decl_chain, NULL);
 
   return objc_ivar_list_record;
 }
@@ -4601,7 +4607,7 @@ build_method_template (void)
 				  "_imp");
   chainon (field_decl_chain, field_decl);
 
-  finish_struct (_SLT_record, field_decl_chain, NULL_TREE);
+  finish_struct (_SLT_record, field_decl_chain, NULL);
 
   return _SLT_record;
 }
@@ -6782,7 +6788,7 @@ continue_class (tree class)
       if (!CLASS_STATIC_TEMPLATE (class))
 	{
 	  tree record = start_struct (RECORD_TYPE, CLASS_NAME (class));
-	  finish_struct (record, get_class_ivars (class), NULL_TREE);
+	  finish_struct (record, get_class_ivars (class), NULL);
 	  CLASS_STATIC_TEMPLATE (class) = record;
 
 	  /* Mark this record as a class template for static typing.  */
@@ -7559,7 +7565,7 @@ objc_fold_obj_type_ref (tree ref ATTRIBU
 }
 
 static void
-objc_start_function (tree name, tree type, tree attrs,
+objc_start_function (tree name, tree type, attribute_list attrs,
 #ifdef OBJCPLUS
 		     tree params
 #else
@@ -7645,7 +7651,7 @@ really_start_method (tree method,
   meth_type
     = build_function_type (ret_type,
 			   get_arg_type_list (method, METHOD_DEF, 0));
-  objc_start_function (method_id, meth_type, NULL_TREE, parmlist);
+  objc_start_function (method_id, meth_type, NULL, parmlist);
 
   /* Set self_decl from the first argument.  */
   self_decl = DECL_ARGUMENTS (current_function_decl);
Index: gcc/treelang/treetree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/treelang/treetree.c,v
retrieving revision 1.45
diff -u -p -u -p -r1.45 treetree.c
--- gcc/treelang/treetree.c	17 Sep 2004 21:55:02 -0000	1.45
+++ gcc/treelang/treetree.c	1 Oct 2004 00:57:37 -0000
@@ -146,7 +146,7 @@ static tree* getstmtlist (void);
 /* Langhooks.  */
 static tree builtin_function (const char *name, tree type, int function_code,
 		  enum built_in_class class, const char *library_name,
-		  tree attrs);
+		  attribute_list attrs);
 static tree getdecls (void);
 static int global_bindings_p (void);
 static void insert_block (tree);
@@ -1252,7 +1252,7 @@ treelang_init_decl_processing (void)
 static tree
 builtin_function (const char *name, tree type, int function_code,
 		  enum built_in_class class, const char *library_name,
-		  tree attrs)
+		  attribute_list attrs)
 {
   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
   DECL_EXTERNAL (decl) = 1;
@@ -1267,7 +1267,7 @@ builtin_function (const char *name, tree
   if (attrs)
     decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
   else
-    decl_attributes (&decl, NULL_TREE, 0);
+    decl_attributes (&decl, NULL, 0);
 
   return decl;
 }
============================================================


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]