diff mbox

[tree-type] Split decl_attribute into type and decl specific versions.

Message ID 54766978.2070908@redhat.com
State New
Headers show

Commit Message

Andrew MacLeod Nov. 26, 2014, 11:59 p.m. UTC
First independent  infrastructure patch for the branch.   These sort of 
patches I will commit to the branch without any tree-type specific 
changes so I can maintain it as a patch to submit in stage 1 independent 
of the overall larger change.  I'll make the tree-type specific changes 
last.

decl_attribute can be applied to either a type or a decl. This separates 
that function into decl_attributes() and type_attributes() (adding 
checking asserts for good measure), and changes the calling locations. 
It was not an enjoyable function to split. ugg. Hope the rest aren't 
like this :-)

Bootstraps, passes regression testing and build all targets.    The next 
part will change the attribute_spec structure to have a separate handler 
for types and for decls and change all the locations as handlers as need 
be.  Easier to test by keeping these changes apart from each other.

checked into tree-type branch as revision 218105

Andrew
diff mbox

Patch


	* attribs.c (process_attribute_spec): New.  Factored from
	decl_attribute to return a valid attribute spec.
	(finalize_type_attribute): New.  Factored from decl_attribute to process
	attributes for types after error checking.
	(type_attributes): New.  Factored type specific portions of
	decl_attributes.
	(decl_attributes): Moved all type processing to other functions.
	* attribs.h (type_attributes): Export.
	* c/c-decl.c (groktypename, grokdeclarator, finish_struct,
	finish_enum): Call type_attributes.
	* c-family/c-common.c (handle_tm_attribute): Call type_attributes.
	* cp/decl.c (grokdeclarator): Call type_attributes.
	* cp/decl2.c (cplus_decl_attributes): Call type_attributes when node is
	a type.
	* ada/gcc-interface/utils.c (finish_record_type): Call type_attribute.
	(process_attributes): Call type_attribute or decl_attribute as needed.
	* config/i386/i386.c (ix86_handle_tm_regparm_attribute): Call
	type_attribute or decl_attribute as required.
	(ix86_init_tm_builtins ): Call type_attributes.

Index: attribs.c
===================================================================
*** attribs.c	(revision 217787)
--- attribs.c	(working copy)
*************** get_attribute_namespace (const_tree attr
*** 354,368 ****
    return get_identifier ("gnu");
  }
  
  
  /* 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)
--- 354,622 ----
    return get_identifier ("gnu");
  }
  
+ /* Lookup the spec for attribute A using FLAGS, and issue any warnings or
+   errors as appropriate.   Return NULL or a valid spec.  */
+ 
+ static const struct attribute_spec *
+ process_attribute_spec (tree a, int flags)
+ {
+   tree name = get_attribute_name (a);
+   tree ns = get_attribute_namespace (a);
+   tree args = TREE_VALUE (a);
+   const struct attribute_spec *spec = lookup_scoped_attribute_spec (ns, name);
+ 
+   if (spec == NULL)
+     {
+       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
+ 	{
+ 	  if (ns == NULL_TREE || !cxx11_attribute_p (a))
+ 	    warning (OPT_Wattributes, "%qE attribute directive ignored",
+ 		     name);
+ 	  else
+ 	    warning (OPT_Wattributes,
+ 		     "%<%E::%E%> scoped attribute directive ignored",
+ 		     ns, name);
+ 	}
+       return NULL;
+     }
+   else if (list_length (args) < spec->min_length
+ 	   || (spec->max_length >= 0
+ 	       && list_length (args) > spec->max_length))
+     {
+       error ("wrong number of arguments specified for %qE attribute",
+ 	     name);
+       return NULL;
+     }
+   gcc_assert (is_attribute_p (spec->name, name));
+   return spec;
+ }
+ 
+ /* Perform the type specific processing of type_attribute.  This is factored
+    out to allow decl_attributes() to process underlying types when necessary.
+    In those cases, DECL_NODE is passed in so the decl can have re-layout
+    called.  SPEC is the already verified attribute spec structure.  Otherwise
+    the parameters match those of type_attribute.  */
+ 
+ static tree
+ finalize_type_attribute (tree *node, const struct attribute_spec *spec,
+ 			 tree a, tree returned_attrs, int flags,
+ 			 tree *decl_node = NULL)
+ {
+   bool no_add_attrs = 0;
+   int fn_ptr_quals = 0;
+   tree fn_ptr_tmp = NULL_TREE;
+   tree name = get_attribute_name (a);
+   tree args = TREE_VALUE (a);
+   tree *anode = node;
+ 
+   gcc_checking_assert (TYPE_P (*node));
+ 
+   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);
+ 	  fn_ptr_quals = TYPE_QUALS (*anode);
+ 	  anode = &fn_ptr_tmp;
+ 	  flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
+ 	}
+       else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
+ 	{
+ 	  /* Pass on this attribute to be tried again.  */
+ 	  returned_attrs = tree_cons (name, args, returned_attrs);
+ 	  return returned_attrs;
+ 	}
+ 
+       if (TREE_CODE (*anode) != FUNCTION_TYPE
+ 	  && TREE_CODE (*anode) != METHOD_TYPE)
+ 	{
+ 	  warning (OPT_Wattributes,
+ 		   "%qE attribute only applies to function types",
+ 		   name);
+ 	  return returned_attrs;
+ 	}
+     }
+ 
+   if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
+       && TYPE_SIZE (*anode) != NULL_TREE)
+     {
+       warning (OPT_Wattributes, "type attributes ignored after type is already defined");
+       return returned_attrs;
+     }
+ 
+   if (spec->handler != NULL)
+     {
+       int cxx11_flag =
+ 	cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
+ 
+       returned_attrs = chainon ((*spec->handler) (anode, name, args,
+ 						       flags|cxx11_flag,
+ 						       &no_add_attrs),
+ 				returned_attrs);
+     }
+ 
+   /* If there was a decl change the layout in case anything changed.  */
+   if (decl_node && spec->type_required
+       && (TREE_CODE (*decl_node) == VAR_DECL
+ 	  || TREE_CODE (*decl_node) == PARM_DECL
+ 	  || TREE_CODE (*decl_node) == RESULT_DECL))
+     relayout_decl (*decl_node);
+ 
+   if (!no_add_attrs)
+     {
+       tree old_attrs;
+       tree a;
+ 
+       old_attrs = TYPE_ATTRIBUTES (*anode);
+ 
+       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 (a == NULL_TREE)
+ 	{
+ 	  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));
+ 	}
+     }
+ 
+   if (fn_ptr_tmp)
+     {
+       /* Rebuild the function pointer type and put it in the
+ 	 appropriate place.  */
+       fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
+       if (fn_ptr_quals)
+ 	fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
+       if (decl_node)
+         TREE_TYPE (*decl_node) = fn_ptr_tmp;
+       else
+         {
+ 	  gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
+ 	  *node = fn_ptr_tmp;
+ 	}
+     }
+   return returned_attrs;
+ 
+ }
+ 
+ /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
+    which is 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
+ type_attributes (tree *node, tree attributes, int flags)
+ {
+   tree a;
+   tree returned_attrs = NULL_TREE;
+ 
+ 
+   if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
+     return NULL_TREE;
+ 
+   gcc_checking_assert (TYPE_P (*node));
+ 
+   if (!attributes_initialized)
+     init_attributes ();
+ 
+   targetm.insert_attributes (*node, &attributes);
+ 
+   for (a = attributes; a; a = TREE_CHAIN (a))
+     {
+       tree name = get_attribute_name (a);
+       tree args = TREE_VALUE (a);
+       const struct attribute_spec *spec = process_attribute_spec (a, flags);
+ 
+       if (!spec)
+ 	continue;
+ 
+       if (cxx11_attribute_p (a) && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
+ 	{
+ 	  /* This is a c++11 attribute that appertains to a
+ 	     type-specifier, outside of the definition of, a class
+ 	     type.  Ignore it.  */
+ 	  warning (OPT_Wattributes, "attribute ignored");
+ 	  inform (input_location,
+ 		  "an attribute that appertains to a type-specifier "
+ 		  "is ignored");
+ 	  continue;
+ 	}
+ 
+       if (spec->decl_required)
+ 	{
+ 	  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;
+ 	    }
+ 	  else
+ 	    {
+ 	      warning (OPT_Wattributes, "%qE attribute does not apply to types",
+ 		       name);
+ 	      continue;
+ 	    }
+ 	}
+ 
+       returned_attrs = finalize_type_attribute (node, spec, a, returned_attrs,
+ 						flags);
+     }
+ 
+   return returned_attrs;
+ }
+ 
+ 
+ 
  
  /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
!    which is a DECL (including a TYPE_DECL) it should be modified in place; 
!    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.  */
  
  tree
  decl_attributes (tree *node, tree attributes, int flags)
*************** decl_attributes (tree *node, tree attrib
*** 370,378 ****
--- 624,635 ----
    tree a;
    tree returned_attrs = NULL_TREE;
  
+ 
    if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
      return NULL_TREE;
  
+   gcc_checking_assert (DECL_P (*node));
+ 
    if (!attributes_initialized)
      init_attributes ();
  
*************** decl_attributes (tree *node, tree attrib
*** 429,583 ****
  
    for (a = attributes; a; a = TREE_CHAIN (a))
      {
-       tree ns = get_attribute_namespace (a);
        tree name = get_attribute_name (a);
        tree args = TREE_VALUE (a);
        tree *anode = node;
-       const struct attribute_spec *spec =
- 	lookup_scoped_attribute_spec (ns, name);
        bool no_add_attrs = 0;
!       int fn_ptr_quals = 0;
!       tree fn_ptr_tmp = NULL_TREE;
  
!       if (spec == NULL)
! 	{
! 	  if (!(flags & (int) ATTR_FLAG_BUILT_IN))
! 	    {
! 	      if (ns == NULL_TREE || !cxx11_attribute_p (a))
! 		warning (OPT_Wattributes, "%qE attribute directive ignored",
! 			 name);
! 	      else
! 		warning (OPT_Wattributes,
! 			 "%<%E::%E%> scoped attribute directive ignored",
! 			 ns, name);
! 	    }
! 	  continue;
! 	}
!       else if (list_length (args) < spec->min_length
! 	       || (spec->max_length >= 0
! 		   && list_length (args) > spec->max_length))
! 	{
! 	  error ("wrong number of arguments specified for %qE attribute",
! 		 name);
! 	  continue;
! 	}
!       gcc_assert (is_attribute_p (spec->name, name));
  
!       if (TYPE_P (*node)
! 	  && cxx11_attribute_p (a)
! 	  && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
! 	{
! 	  /* This is a c++11 attribute that appertains to a
! 	     type-specifier, outside of the definition of, a class
! 	     type.  Ignore it.  */
! 	  warning (OPT_Wattributes, "attribute ignored");
! 	  inform (input_location,
! 		  "an attribute that appertains to a type-specifier "
! 		  "is ignored");
! 	  continue;
! 	}
! 
!       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;
! 	    }
! 	  else
! 	    {
! 	      warning (OPT_Wattributes, "%qE attribute does not apply to types",
! 		       name);
! 	      continue;
! 	    }
! 	}
  
        /* 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))
  	{
  	  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);
! 	      fn_ptr_quals = TYPE_QUALS (*anode);
! 	      anode = &fn_ptr_tmp;
! 	      flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
! 	    }
! 	  else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
! 	    {
! 	      /* Pass on this attribute to be tried again.  */
! 	      returned_attrs = tree_cons (name, args, returned_attrs);
! 	      continue;
! 	    }
! 
! 	  if (TREE_CODE (*anode) != FUNCTION_TYPE
! 	      && TREE_CODE (*anode) != METHOD_TYPE)
! 	    {
! 	      warning (OPT_Wattributes,
! 		       "%qE attribute only applies to function types",
! 		       name);
! 	      continue;
! 	    }
! 	}
! 
!       if (TYPE_P (*anode)
! 	  && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
! 	  && TYPE_SIZE (*anode) != NULL_TREE)
! 	{
! 	  warning (OPT_Wattributes, "type attributes ignored after type is already defined");
  	  continue;
  	}
- 
        if (spec->handler != NULL)
  	{
  	  int cxx11_flag =
  	    cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
- 
  	  returned_attrs = chainon ((*spec->handler) (anode, name, args,
! 						      flags|cxx11_flag,
! 						      &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))
- 	relayout_decl (*node);
- 
        if (!no_add_attrs)
  	{
  	  tree old_attrs;
  	  tree a;
  
! 	  if (DECL_P (*anode))
! 	    old_attrs = DECL_ATTRIBUTES (*anode);
! 	  else
! 	    old_attrs = TYPE_ATTRIBUTES (*anode);
  
  	  for (a = lookup_attribute (spec->name, old_attrs);
  	       a != NULL_TREE;
--- 686,731 ----
  
    for (a = attributes; a; a = TREE_CHAIN (a))
      {
        tree name = get_attribute_name (a);
        tree args = TREE_VALUE (a);
        tree *anode = node;
        bool no_add_attrs = 0;
!       const struct attribute_spec *spec = process_attribute_spec (a, flags);
  
!       gcc_assert (DECL_P (*node));
  
!       if (!spec)
! 	continue;
  
        /* 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)
  	{
  	  anode = &TREE_TYPE (*anode);
  	  flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
! 	  returned_attrs = finalize_type_attribute (anode, spec, a,
! 						    returned_attrs, flags,
! 						    node);
  	  continue;
  	}
        if (spec->handler != NULL)
  	{
  	  int cxx11_flag =
  	    cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
  	  returned_attrs = chainon ((*spec->handler) (anode, name, args,
! 							   flags|cxx11_flag,
! 							   &no_add_attrs),
  				    returned_attrs);
  	}
  
        if (!no_add_attrs)
  	{
  	  tree old_attrs;
  	  tree a;
  
! 	  old_attrs = DECL_ATTRIBUTES (*anode);
  
  	  for (a = lookup_attribute (spec->name, old_attrs);
  	       a != NULL_TREE;
*************** decl_attributes (tree *node, tree attrib
*** 588,642 ****
  	    }
  
  	  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));
! 	    }
  	}
  
-       if (fn_ptr_tmp)
- 	{
- 	  /* Rebuild the function pointer type and put it in the
- 	     appropriate place.  */
- 	  fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
- 	  if (fn_ptr_quals)
- 	    fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
- 	  if (DECL_P (*node))
- 	    TREE_TYPE (*node) = fn_ptr_tmp;
- 	  else
- 	    {
- 	      gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
- 	      *node = fn_ptr_tmp;
- 	    }
- 	}
      }
- 
    return returned_attrs;
  }
  
--- 736,746 ----
  	    }
  
  	  if (a == NULL_TREE)
! 	    /* This attribute isn't already in the list.  */
! 	    DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
  	}
  
      }
    return returned_attrs;
  }
  
*************** get_attribute_name (const_tree attr)
*** 681,685 ****
  void
  apply_tm_attr (tree fndecl, tree attr)
  {
!   decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
  }
--- 785,789 ----
  void
  apply_tm_attr (tree fndecl, tree attr)
  {
!   type_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
  }
Index: attribs.h
===================================================================
*** attribs.h	(revision 217787)
--- attribs.h	(working copy)
*************** extern void init_attributes (void);
*** 31,36 ****
--- 31,37 ----
     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 type_attributes (tree *, tree, int);
  extern tree decl_attributes (tree *, tree, int);
  
  extern bool cxx11_attribute_p (const_tree);
Index: c/c-decl.c
===================================================================
*** c/c-decl.c	(revision 217787)
--- c/c-decl.c	(working copy)
*************** groktypename (struct c_type_name *type_n
*** 4383,4389 ****
  			 DEPRECATED_NORMAL);
  
    /* Apply attributes.  */
!   decl_attributes (&type, attrs, 0);
  
    return type;
  }
--- 4383,4389 ----
  			 DEPRECATED_NORMAL);
  
    /* Apply attributes.  */
!   type_attributes (&type, attrs, 0);
  
    return type;
  }
*************** grokdeclarator (const struct c_declarato
*** 5691,5697 ****
  	      attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
  	    else if (inner_decl->kind == cdk_array)
  	      attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
! 	    returned_attrs = decl_attributes (&type,
  					      chainon (returned_attrs, attrs),
  					      attr_flags);
  	    break;
--- 5691,5697 ----
  	      attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
  	    else if (inner_decl->kind == cdk_array)
  	      attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
! 	    returned_attrs = type_attributes (&type,
  					      chainon (returned_attrs, attrs),
  					      attr_flags);
  	    break;
*************** finish_struct (location_t loc, tree t, t
*** 7576,7582 ****
  
    TYPE_SIZE (t) = 0;
  
!   decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
  
    if (pedantic)
      {
--- 7576,7582 ----
  
    TYPE_SIZE (t) = 0;
  
!   type_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
  
    if (pedantic)
      {
*************** finish_enum (tree enumtype, tree values,
*** 7949,7955 ****
    bool toplevel = (file_scope == current_scope);
    struct lang_type *lt;
  
!   decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
  
    /* Calculate the maximum value of any enumerator in this type.  */
  
--- 7949,7955 ----
    bool toplevel = (file_scope == current_scope);
    struct lang_type *lt;
  
!   type_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
  
    /* Calculate the maximum value of any enumerator in this type.  */
  
Index: c-family/c-common.c
===================================================================
*** c-family/c-common.c	(revision 217787)
--- c-family/c-common.c	(working copy)
*************** handle_tm_attribute (tree *node, tree na
*** 8574,8580 ****
  	if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE)
  	  {
  	    tree fn_tmp = TREE_TYPE (*node);
! 	    decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
  	    *node = build_pointer_type (fn_tmp);
  	    break;
  	  }
--- 8574,8580 ----
  	if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE)
  	  {
  	    tree fn_tmp = TREE_TYPE (*node);
! 	    type_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
  	    *node = build_pointer_type (fn_tmp);
  	    break;
  	  }
Index: cp/decl.c
===================================================================
*** cp/decl.c	(revision 217787)
--- cp/decl.c	(working copy)
*************** grokdeclarator (const cp_declarator *dec
*** 9581,9587 ****
      {
        /* Apply the c++11 attributes to the type preceding them.  */
        input_location = declspecs->locations[ds_std_attribute];
!       decl_attributes (&type, declspecs->std_attributes, 0);
        input_location = saved_loc;
      }
  
--- 9581,9587 ----
      {
        /* Apply the c++11 attributes to the type preceding them.  */
        input_location = declspecs->locations[ds_std_attribute];
!       type_attributes (&type, declspecs->std_attributes, 0);
        input_location = saved_loc;
      }
  
*************** grokdeclarator (const cp_declarator *dec
*** 9607,9613 ****
  	    attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
  	  if (declarator->kind == cdk_array)
  	    attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
! 	  returned_attrs = decl_attributes (&type,
  					    chainon (returned_attrs, attrs),
  					    attr_flags);
  	}
--- 9607,9613 ----
  	    attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
  	  if (declarator->kind == cdk_array)
  	    attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
! 	  returned_attrs = type_attributes (&type,
  					    chainon (returned_attrs, attrs),
  					    attr_flags);
  	}
*************** grokdeclarator (const cp_declarator *dec
*** 9853,9859 ****
  
  		 The optional attribute-specifier-seq appertains to
  		 the function type.  */
! 	      decl_attributes (&type, declarator->std_attributes,
  			       0);
  	  }
  	  break;
--- 9853,9859 ----
  
  		 The optional attribute-specifier-seq appertains to
  		 the function type.  */
! 	      type_attributes (&type, declarator->std_attributes,
  			       0);
  	  }
  	  break;
*************** grokdeclarator (const cp_declarator *dec
*** 10034,10040 ****
  		 [the optional attribute-specifier-seq (7.6.1) appertains
  		  to the pointer and not to the object pointed to].  */
  	  if (declarator->std_attributes)
! 	    decl_attributes (&type, declarator->std_attributes,
  			     0);
  
  	  ctype = NULL_TREE;
--- 10034,10040 ----
  		 [the optional attribute-specifier-seq (7.6.1) appertains
  		  to the pointer and not to the object pointed to].  */
  	  if (declarator->std_attributes)
! 	    type_attributes (&type, declarator->std_attributes,
  			     0);
  
  	  ctype = NULL_TREE;
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 217787)
--- cp/decl2.c	(working copy)
*************** cplus_decl_attributes (tree *decl, tree
*** 1472,1484 ****
  
    if (TREE_TYPE (*decl) && TYPE_PTRMEMFUNC_P (TREE_TYPE (*decl)))
      {
!       attributes
! 	= decl_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT);
!       decl_attributes (&TYPE_PTRMEMFUNC_FN_TYPE_RAW (TREE_TYPE (*decl)),
  		       attributes, flags);
      }
    else
!     decl_attributes (decl, attributes, flags);
  
    if (TREE_CODE (*decl) == TYPE_DECL)
      SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
--- 1472,1491 ----
  
    if (TREE_TYPE (*decl) && TYPE_PTRMEMFUNC_P (TREE_TYPE (*decl)))
      {
!       if (TYPE_P (*decl))
! 	attributes
! 	  = type_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT);
!       else
! 	attributes
! 	  = decl_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT);
!       type_attributes (&TYPE_PTRMEMFUNC_FN_TYPE_RAW (TREE_TYPE (*decl)),
  		       attributes, flags);
      }
    else
!     if (TYPE_P (*decl))
!       type_attributes (decl, attributes, flags);
!     else
!       decl_attributes (decl, attributes, flags);
  
    if (TREE_CODE (*decl) == TYPE_DECL)
      SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
Index: ada/gcc-interface/utils.c
===================================================================
*** ada/gcc-interface/utils.c	(revision 217787)
--- ada/gcc-interface/utils.c	(working copy)
*************** finish_record_type (tree record_type, tr
*** 1629,1635 ****
  	 efficient packing in almost all cases.  */
  #ifdef TARGET_MS_BITFIELD_LAYOUT
        if (TARGET_MS_BITFIELD_LAYOUT && TYPE_PACKED (record_type))
! 	decl_attributes (&record_type,
  			 tree_cons (get_identifier ("gcc_struct"),
  				    NULL_TREE, NULL_TREE),
  			 ATTR_FLAG_TYPE_IN_PLACE);
--- 1629,1635 ----
  	 efficient packing in almost all cases.  */
  #ifdef TARGET_MS_BITFIELD_LAYOUT
        if (TARGET_MS_BITFIELD_LAYOUT && TYPE_PACKED (record_type))
! 	type_attributes (&record_type,
  			 tree_cons (get_identifier ("gcc_struct"),
  				    NULL_TREE, NULL_TREE),
  			 ATTR_FLAG_TYPE_IN_PLACE);
*************** process_attributes (tree *node, struct a
*** 2650,2657 ****
        {
        case ATTR_MACHINE_ATTRIBUTE:
  	Sloc_to_locus (Sloc (gnat_node), &input_location);
! 	decl_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE),
! 			 in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0);
  	break;
  
        case ATTR_LINK_ALIAS:
--- 2650,2661 ----
        {
        case ATTR_MACHINE_ATTRIBUTE:
  	Sloc_to_locus (Sloc (gnat_node), &input_location);
! 	if (TYPE_P (*node))
! 	  type_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE),
! 			   in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0);
! 	else
! 	  decl_attributes (node, tree_cons (attr->name, attr->args, NULL_TREE),
! 			   in_place ? ATTR_FLAG_TYPE_IN_PLACE : 0);
  	break;
  
        case ATTR_LINK_ALIAS:
Index: config/i386/i386.c
===================================================================
*** config/i386/i386.c	(revision 217787)
--- config/i386/i386.c	(working copy)
*************** ix86_handle_tm_regparm_attribute (tree *
*** 5614,5620 ****
        alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL);
        alt = tree_cons (get_identifier ("regparm"), alt, NULL);
      }
!   decl_attributes (node, alt, flags);
  
    return NULL_TREE;
  }
--- 5614,5623 ----
        alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL);
        alt = tree_cons (get_identifier ("regparm"), alt, NULL);
      }
!   if (TYPE_P (*node))
!     type_attributes (node, alt, flags);
!   else
!     decl_attributes (node, alt, flags);
  
    return NULL_TREE;
  }
*************** ix86_init_tm_builtins (void)
*** 33294,33300 ****
  				       attrs);
  	  /* add_builtin_function() will set the DECL_ATTRIBUTES, now
  	     set the TYPE_ATTRIBUTES.  */
! 	  decl_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN);
  
  	  set_builtin_decl (code, decl, false);
  	}
--- 33297,33303 ----
  				       attrs);
  	  /* add_builtin_function() will set the DECL_ATTRIBUTES, now
  	     set the TYPE_ATTRIBUTES.  */
! 	  type_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN);
  
  	  set_builtin_decl (code, decl, false);
  	}