diff mbox

Move shared attributes to common location

Message ID CABOHX+d50iLTqufcQvRzER3jeBCBkicbwTNi5TT2pqk9hcS35Q@mail.gmail.com
State New
Headers show

Commit Message

Iain Buclaw May 5, 2014, 10:23 p.m. UTC
Hi,

This patch (changelog entry needs to be written up) moves the minimal
set of attributes to accommodate the needs of builtins out of each
respective front-end and into a common area shared between each.

Defines lhd_common_attribute_table and lhd_format_attribute_table to
provide as defaults for the COMMON_ATTRIBUTE_TABLE and
FORMAT_ATTRIBUTE_TABLE langhooks respectively.  All attribute handlers
in LTO; Java, and most in Ada have been moved/merged together.
Attributes not required for builtins.def, but in use by Ada have been
left in their own language attribute table.  And C family languages
still override these two langhooks with their own common and format
attribute tables defined in c-common.c

langhooks.c seems the most appropriate place to put these, but they
could just as easily go in a new source file.

Regards
Iain.
diff mbox

Patch

diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index c81ab00..93e84e1 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -86,62 +86,20 @@  tree gnat_raise_decls[(int) LAST_REASON_CODE + 1];
 tree gnat_raise_decls_ext[(int) LAST_REASON_CODE + 1];
 
 /* Forward declarations for handlers of attributes.  */
-static tree handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
-static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
-static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
-static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
-static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
-static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
-static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
 static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *);
 static tree handle_vector_type_attribute (tree *, tree, tree, int, bool *);
 
-/* Fake handler for attributes we don't properly support, typically because
-   they'd require dragging a lot of the common-c front-end circuitry.  */
-static tree fake_attribute_handler      (tree *, tree, tree, int, bool *);
-
-/* Table of machine-independent internal attributes for Ada.  We support
-   this minimal set of attributes to accommodate the needs of builtins.  */
+/* Table of machine-independent internal attributes for Ada.  */
 const struct attribute_spec gnat_internal_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
        affects_type_identity } */
-  { "const",        0, 0,  true,  false, false, handle_const_attribute,
-    false },
-  { "nothrow",      0, 0,  true,  false, false, handle_nothrow_attribute,
-    false },
-  { "pure",         0, 0,  true,  false, false, handle_pure_attribute,
-    false },
-  { "no vops",      0, 0,  true,  false, false, handle_novops_attribute,
-    false },
-  { "nonnull",      0, -1, false, true,  true,  handle_nonnull_attribute,
-    false },
-  { "sentinel",     0, 1,  false, true,  true,  handle_sentinel_attribute,
-    false },
-  { "noreturn",     0, 0,  true,  false, false, handle_noreturn_attribute,
-    false },
-  { "leaf",         0, 0,  true,  false, false, handle_leaf_attribute,
-    false },
-  { "malloc",       0, 0,  true,  false, false, handle_malloc_attribute,
-    false },
-  { "type generic", 0, 0,  false, true, true, handle_type_generic_attribute,
-    false },
-
   { "vector_size",  1, 1,  false, true, false,  handle_vector_size_attribute,
     false },
   { "vector_type",  0, 0,  false, true, false,  handle_vector_type_attribute,
     false },
   { "may_alias",    0, 0, false, true, false, NULL, false },
 
-  /* ??? format and format_arg are heavy and not supported, which actually
-     prevents support for stdio builtins, which we however declare as part
-     of the common builtins.def contents.  */
-  { "format",     3, 3,  false, true,  true,  fake_attribute_handler, false },
-  { "format_arg", 1, 1,  false, true,  true,  fake_attribute_handler, false },
-
   { NULL,         0, 0, false, false, false, NULL, false }
 };
 
@@ -6115,303 +6073,6 @@  install_builtin_attributes (void)
 #undef DEF_ATTR_TREE_LIST
 }
 
-/* Handle a "const" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_const_attribute (tree *node, tree ARG_UNUSED (name),
-			tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_READONLY (*node) = 1;
-  else
-    *no_add_attrs = true;
-
-  return NULL_TREE;
-}
-
-/* Handle a "nothrow" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
-			  tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			  bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_NOTHROW (*node) = 1;
-  else
-    *no_add_attrs = true;
-
-  return NULL_TREE;
-}
-
-/* Handle a "pure" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-		       int ARG_UNUSED (flags), bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_PURE_P (*node) = 1;
-  /* ??? TODO: Support types.  */
-  else
-    {
-      warning (OPT_Wattributes, "%qs attribute ignored",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "no vops" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
-			 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			 bool *ARG_UNUSED (no_add_attrs))
-{
-  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
-  DECL_IS_NOVOPS (*node) = 1;
-  return NULL_TREE;
-}
-
-/* Helper for nonnull attribute handling; fetch the operand number
-   from the attribute argument list.  */
-
-static bool
-get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
-{
-  /* Verify the arg number is a constant.  */
-  if (TREE_CODE (arg_num_expr) != INTEGER_CST
-      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
-    return false;
-
-  *valp = TREE_INT_CST_LOW (arg_num_expr);
-  return true;
-}
-
-/* Handle the "nonnull" attribute.  */
-static tree
-handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
-			  tree args, int ARG_UNUSED (flags),
-			  bool *no_add_attrs)
-{
-  tree type = *node;
-  unsigned HOST_WIDE_INT attr_arg_num;
-
-  /* If no arguments are specified, all pointer arguments should be
-     non-null.  Verify a full prototype is given so that the arguments
-     will have the correct types when we actually check them later.  */
-  if (!args)
-    {
-      if (!prototype_p (type))
-	{
-	  error ("nonnull attribute without arguments on a non-prototype");
-	  *no_add_attrs = true;
-	}
-      return NULL_TREE;
-    }
-
-  /* Argument list specified.  Verify that each argument number references
-     a pointer argument.  */
-  for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
-    {
-      unsigned HOST_WIDE_INT arg_num = 0, ck_num;
-
-      if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
-	{
-	  error ("nonnull argument has invalid operand number (argument %lu)",
-		 (unsigned long) attr_arg_num);
-	  *no_add_attrs = true;
-	  return NULL_TREE;
-	}
-
-      if (prototype_p (type))
-	{
-	  function_args_iterator iter;
-	  tree argument;
-
-	  function_args_iter_init (&iter, type);
-	  for (ck_num = 1; ; ck_num++, function_args_iter_next (&iter))
-	    {
-	      argument = function_args_iter_cond (&iter);
-	      if (!argument || ck_num == arg_num)
-		break;
-	    }
-
-	  if (!argument
-	      || TREE_CODE (argument) == VOID_TYPE)
-	    {
-	      error ("nonnull argument with out-of-range operand number "
-		     "(argument %lu, operand %lu)",
-		     (unsigned long) attr_arg_num, (unsigned long) arg_num);
-	      *no_add_attrs = true;
-	      return NULL_TREE;
-	    }
-
-	  if (TREE_CODE (argument) != POINTER_TYPE)
-	    {
-	      error ("nonnull argument references non-pointer operand "
-		     "(argument %lu, operand %lu)",
-		   (unsigned long) attr_arg_num, (unsigned long) arg_num);
-	      *no_add_attrs = true;
-	      return NULL_TREE;
-	    }
-	}
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "sentinel" attribute.  */
-
-static tree
-handle_sentinel_attribute (tree *node, tree name, tree args,
-			   int ARG_UNUSED (flags), bool *no_add_attrs)
-{
-  if (!prototype_p (*node))
-    {
-      warning (OPT_Wattributes,
-	       "%qs attribute requires prototypes with named arguments",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-  else
-    {
-      if (!stdarg_p (*node))
-        {
-	  warning (OPT_Wattributes,
-		   "%qs attribute only applies to variadic functions",
-		   IDENTIFIER_POINTER (name));
-	  *no_add_attrs = true;
-	}
-    }
-
-  if (args)
-    {
-      tree position = TREE_VALUE (args);
-
-      if (TREE_CODE (position) != INTEGER_CST)
-        {
-	  warning (0, "requested position is not an integer constant");
-	  *no_add_attrs = true;
-	}
-      else
-        {
-	  if (tree_int_cst_lt (position, integer_zero_node))
-	    {
-	      warning (0, "requested position is less than zero");
-	      *no_add_attrs = true;
-	    }
-	}
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "noreturn" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			   int ARG_UNUSED (flags), bool *no_add_attrs)
-{
-  tree type = TREE_TYPE (*node);
-
-  /* See FIXME comment in c_common_attribute_table.  */
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_THIS_VOLATILE (*node) = 1;
-  else if (TREE_CODE (type) == POINTER_TYPE
-	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
-    TREE_TYPE (*node)
-      = build_pointer_type
-	(build_type_variant (TREE_TYPE (type),
-			     TYPE_READONLY (TREE_TYPE (type)), 1));
-  else
-    {
-      warning (OPT_Wattributes, "%qs attribute ignored",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "leaf" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_leaf_attribute (tree *node, tree name,
-		       tree ARG_UNUSED (args),
-		       int ARG_UNUSED (flags), bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning (OPT_Wattributes, "%qE attribute ignored", name);
-      *no_add_attrs = true;
-    }
-  if (!TREE_PUBLIC (*node))
-    {
-      warning (OPT_Wattributes, "%qE attribute has no effect", name);
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "malloc" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			 int ARG_UNUSED (flags), bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL
-      && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
-    DECL_IS_MALLOC (*node) = 1;
-  else
-    {
-      warning (OPT_Wattributes, "%qs attribute ignored",
-	       IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Fake handler for attributes we don't properly support.  */
-
-tree
-fake_attribute_handler (tree * ARG_UNUSED (node),
-			tree ARG_UNUSED (name),
-			tree ARG_UNUSED (args),
-			int  ARG_UNUSED (flags),
-			bool * ARG_UNUSED (no_add_attrs))
-{
-  return NULL_TREE;
-}
-
-/* Handle a "type_generic" attribute.  */
-
-static tree
-handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
-			       tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			       bool * ARG_UNUSED (no_add_attrs))
-{
-  /* Ensure we have a function type.  */
-  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
-  /* Ensure we have a variadic function.  */
-  gcc_assert (!prototype_p (*node) || stdarg_p (*node));
-
-  return NULL_TREE;
-}
-
 /* Handle a "vector_size" attribute; arguments as in
    struct attribute_spec.handler.  */
 
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index 8a68691..2a4c5d0 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -71,14 +71,6 @@  static tree java_eh_personality (void);
 # define TARGET_OBJECT_SUFFIX ".o"
 #endif
 
-/* Table of machine-independent attributes.  */
-const struct attribute_spec java_attribute_table[] =
-{
- { "nonnull",                0, -1, false, true, true,
-			      NULL, false },
-  { NULL,                     0, 0, false, false, false, NULL, false }
-};
-
 /* Used to avoid printing error messages with bogus function
    prototypes.  Starts out false.  */
 static bool inhibit_error_function_printing;
@@ -164,9 +156,6 @@  struct GTY(()) language_function {
 #undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME
 #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME java_mangle_decl
 
-#undef LANG_HOOKS_ATTRIBUTE_TABLE
-#define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table
-
 #undef LANG_HOOKS_EH_PERSONALITY
 #define LANG_HOOKS_EH_PERSONALITY java_eh_personality
 
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 95bd379..fb49e4d 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -61,6 +61,10 @@  extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
 extern tree lhd_expr_to_decl (tree, bool *, bool *);
 extern tree lhd_builtin_function (tree);
 
+/* Declarations of default attribute table hooks.  */
+extern const struct attribute_spec *lhd_common_attribute_table;
+extern const struct attribute_spec *lhd_format_attribute_table;
+
 /* Declarations of default tree inlining hooks.  */
 extern void lhd_initialize_diagnostics (diagnostic_context *);
 extern void lhd_init_options (unsigned int,
@@ -121,8 +125,8 @@  extern bool lhd_omp_mappable_type (tree);
 
 /* Attribute hooks.  */
 #define LANG_HOOKS_ATTRIBUTE_TABLE		NULL
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE	NULL
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE	NULL
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE	lhd_common_attribute_table
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE	lhd_format_attribute_table
 
 /* Tree inlining hooks.  */
 #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index d00ebd8..da8b782 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -41,6 +41,21 @@  along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "output.h"
 
+static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
+static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
+static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
+static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree ignore_attribute (tree *, tree, tree, int, bool *);
+
 /* Do nothing; in many cases the default hook.  */
 
 void
@@ -678,3 +693,420 @@  lhd_end_section (void)
       saved_section = NULL;
     }
 }
+
+
+/* Table of machine-independent attributes supported in GIMPLE.
+   We support this minimal set of attributes to accommodate the
+   needs of builtins.*/
+const struct attribute_spec lhd_common_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       do_diagnostic } */
+  /* See FIXME comment on noreturn in c_common_attribute_table.  */
+/*{ "noreturn",               0, 0, true,  false, false,
+			      handle_noreturn_attribute, false },*/
+/*{ "leaf",		      0, 0, true,  false, false,
+			      handle_leaf_attribute, false },*/
+  /* The same comments as for noreturn attributes apply to const ones.  */
+/*{ "const",                  0, 0, true,  false, false,
+			      handle_const_attribute, false },*/
+/*{ "malloc",                 0, 0, true,  false, false,
+			      handle_malloc_attribute, false },*/
+/*{ "pure",                   0, 0, true,  false, false,
+			      handle_pure_attribute, false },*/
+/*{ "no vops",                0, 0, true,  false, false,
+			      handle_novops_attribute, false },*/
+/*{ "nonnull",                0, -1, false, true, true,
+			      handle_nonnull_attribute, false },*/
+/*{ "nothrow",                0, 0, true,  false, false,
+			      handle_nothrow_attribute, false },*/
+  { "returns_twice",          0, 0, true,  false, false,
+			      handle_returns_twice_attribute, false },
+/*{ "sentinel",               0, 1, false, true, true,
+			      handle_sentinel_attribute, false },*/
+/*{ "type generic",           0, 0, false, true, true,
+			      handle_type_generic_attribute, false },*/
+  { "fn spec",	 	      1, 1, false, true, true,
+			      handle_fnspec_attribute, false },
+  { "transaction_pure",	      0, 0, false, true, true,
+			      handle_transaction_pure_attribute, false },
+  /* For internal use only.  The leading '*' both prevents its usage in
+     source code and signals that it may be overridden by machine tables.  */
+  { "*tm regparm",            0, 0, false, true, true,
+			      ignore_attribute, false },
+  { NULL,                     0, 0, false, false, false, NULL, false }
+};
+
+/* Give the specifications for the format attributes, used by C and all
+   descendants.  */
+
+const struct attribute_spec lhd_format_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity } */
+  { "format",                 3, 3, false, true,  true,
+			      ignore_attribute, false },
+  { "format_arg",             1, 1, false, true,  true,
+			      ignore_attribute, false },
+  { NULL,                     0, 0, false, false, false, NULL, false }
+};
+
+/* Attribute handlers.  */
+
+/* Handle a "noreturn" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+			   int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  tree type = TREE_TYPE (*node);
+
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    TREE_THIS_VOLATILE (*node) = 1;
+  else if (TREE_CODE (type) == POINTER_TYPE
+	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+    TREE_TYPE (*node)
+      = build_pointer_type
+	(build_type_variant (TREE_TYPE (type),
+			     TYPE_READONLY (TREE_TYPE (type)), 1));
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "leaf" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_leaf_attribute (tree *node, tree name,
+		       tree ARG_UNUSED (args),
+		       int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  if (!TREE_PUBLIC (*node))
+    {
+      warning (OPT_Wattributes, "%qE attribute has no effect", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "const" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_const_attribute (tree *node, tree ARG_UNUSED (name),
+			tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+			bool *no_add_attrs)
+{
+  tree type = TREE_TYPE (*node);
+
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    TREE_READONLY (*node) = 1;
+  else if (TREE_CODE (type) == POINTER_TYPE
+	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
+    TREE_TYPE (*node)
+      = build_pointer_type
+	(build_type_variant (TREE_TYPE (type),
+			     TYPE_READONLY (TREE_TYPE (type)), 1));
+  else
+    *no_add_attrs = true;
+
+  return NULL_TREE;
+}
+
+
+/* Handle a "malloc" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+			 int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL
+      && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
+    DECL_IS_MALLOC (*node) = 1;
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+
+/* Handle a "pure" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+		       int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    DECL_PURE_P (*node) = 1;
+  /* ??? TODO: Support types.  */
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+
+/* Handle a "no vops" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
+			 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+			 bool *ARG_UNUSED (no_add_attrs))
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+  DECL_IS_NOVOPS (*node) = 1;
+  return NULL_TREE;
+}
+
+
+/* Helper for nonnull attribute handling; fetch the operand number
+   from the attribute argument list.  */
+
+static bool
+get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
+{
+  /* Verify the arg number is a constant.  */
+  if (TREE_CODE (arg_num_expr) != INTEGER_CST
+      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
+    return false;
+
+  *valp = TREE_INT_CST_LOW (arg_num_expr);
+  return true;
+}
+
+/* Handle the "nonnull" attribute.  */
+
+static tree
+handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
+			  tree args, int ARG_UNUSED (flags),
+			  bool *no_add_attrs)
+{
+  tree type = *node;
+  unsigned HOST_WIDE_INT attr_arg_num
+
+  /* If no arguments are specified, all pointer arguments should be
+     non-null.  Verify a full prototype is given so that the arguments
+     will have the correct types when we actually check them later.  */
+  if (!args)
+    {
+      if (!prototype_p (type))
+	{
+	  error ("nonnull attribute without arguments on a non-prototype");
+	  *no_add_attrs = true;
+	}
+      return NULL_TREE;
+    }
+
+  /* Argument list specified.  Verify that each argument number references
+     a pointer argument.  */
+  for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
+    {
+      unsigned HOST_WIDE_INT arg_num = 0, ck_num;
+
+      if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
+	{
+	  error ("nonnull argument has invalid operand number (argument %lu)",
+		 (unsigned long) attr_arg_num);
+	  *no_add_attrs = true;
+	  return NULL_TREE;
+	}
+
+      if (prototype_p (type))
+	{
+	  function_args_iterator iter;
+	  tree argument;
+
+	  function_args_iter_init (&iter, type);
+	  for (ck_num = 1; ; ck_num++, function_args_iter_next (&iter))
+	    {
+	      argument = function_args_iter_cond (&iter);
+	      if (!argument || ck_num == arg_num)
+		break;
+	    }
+
+	  if (!argument
+	      || TREE_CODE (argument) == VOID_TYPE)
+	    {
+	      error ("nonnull argument with out-of-range operand number "
+		     "(argument %lu, operand %lu)",
+		     (unsigned long) attr_arg_num, (unsigned long) arg_num);
+	      *no_add_attrs = true;
+	      return NULL_TREE;
+	    }
+
+	  if (TREE_CODE (argument) != POINTER_TYPE)
+	    {
+	      error ("nonnull argument references non-pointer operand "
+		     "(argument %lu, operand %lu)",
+		     (unsigned long) attr_arg_num, (unsigned long) arg_num);
+	      *no_add_attrs = true;
+	      return NULL_TREE;
+	    }
+	}
+    }
+
+  return NULL_TREE;
+}
+
+
+/* Handle a "nothrow" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
+			  tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+			  bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    TREE_NOTHROW (*node) = 1;
+  else
+    *no_add_attrs = true;
+
+  return NULL_TREE;
+}
+
+
+/* Handle a "sentinel" attribute.  */
+
+static tree
+handle_sentinel_attribute (tree *node, tree name, tree args,
+			   int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (!prototype_p (*node))
+    {
+      warning (OPT_Wattributes,
+	       "%qs attribute requires prototypes with named arguments",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+  else
+    {
+      if (!stdarg_p (*node))
+	{
+	  warning (OPT_Wattributes,
+		   "%qs attribute only applies to variadic functions",
+		   IDENTIFIER_POINTER (name));
+	  *no_add_attrs = true;
+	}
+    }
+
+  if (args)
+    {
+      tree position = TREE_VALUE (args);
+
+      if (TREE_CODE (position) != INTEGER_CST)
+	{
+	  warning (0, "requested position is not an integer constant");
+	  *no_add_attrs = true;
+	}
+      else
+	{
+	  if (tree_int_cst_lt (position, integer_zero_node))
+	    {
+	      warning (0, "requested position is less than zero");
+	      *no_add_attrs = true;
+	    }
+	}
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "type_generic" attribute.  */
+
+static tree
+handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
+			       tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+			       bool * ARG_UNUSED (no_add_attrs))
+{
+  /* Ensure we have a function type.  */
+  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+  
+  /* Ensure we have a variadic function.  */
+  gcc_assert (!prototype_p (*node) || stdarg_p (*node));
+
+  return NULL_TREE;
+}
+
+/* Handle a "transaction_pure" attribute.  */
+
+static tree
+handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
+				   tree ARG_UNUSED (args),
+				   int ARG_UNUSED (flags),
+				   bool *no_add_attrs)
+{
+  /* Ensure we have a function type.  */
+  if (TREE_CODE (*node) != FUNCTION_TYPE)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "returns_twice" attribute.  */
+
+static tree
+handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+				int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    DECL_IS_RETURNS_TWICE (*node) = 1;
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "fn spec" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_fnspec_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+			 tree args, int ARG_UNUSED (flags),
+			 bool * ARG_UNUSED (no_add_attrs))
+{
+  gcc_assert (args
+	      && TREE_CODE (TREE_VALUE (args)) == STRING_CST
+	      && !TREE_CHAIN (args));
+  return NULL_TREE;
+}
+
+/* Ignore the given attribute.  Used when this attribute may be usefully
+   overridden by the target, but is not used generically.  */
+
+static tree
+ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+		  tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+		  bool *no_add_attrs)
+{
+  *no_add_attrs = true;
+  return NULL_TREE;
+}
+
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 339bebf..875a345 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -46,77 +46,6 @@  along with GCC; see the file COPYING3.  If not see
 
 static tree lto_type_for_size (unsigned, int);
 
-static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
-static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
-static tree handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
-static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
-static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
-static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
-static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
-static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
-static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
-static tree ignore_attribute (tree *, tree, tree, int, bool *);
-
-static tree handle_format_attribute (tree *, tree, tree, int, bool *);
-static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
-static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
-
-/* Table of machine-independent attributes supported in GIMPLE.  */
-const struct attribute_spec lto_attribute_table[] =
-{
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
-       do_diagnostic } */
-  { "noreturn",               0, 0, true,  false, false,
-			      handle_noreturn_attribute, false },
-  { "leaf",		      0, 0, true,  false, false,
-			      handle_leaf_attribute, false },
-  /* The same comments as for noreturn attributes apply to const ones.  */
-  { "const",                  0, 0, true,  false, false,
-			      handle_const_attribute, false },
-  { "malloc",                 0, 0, true,  false, false,
-			      handle_malloc_attribute, false },
-  { "pure",                   0, 0, true,  false, false,
-			      handle_pure_attribute, false },
-  { "no vops",                0, 0, true,  false, false,
-			      handle_novops_attribute, false },
-  { "nonnull",                0, -1, false, true, true,
-			      handle_nonnull_attribute, false },
-  { "nothrow",                0, 0, true,  false, false,
-			      handle_nothrow_attribute, false },
-  { "returns_twice",          0, 0, true,  false, false,
-			      handle_returns_twice_attribute, false },
-  { "sentinel",               0, 1, false, true, true,
-			      handle_sentinel_attribute, false },
-  { "type generic",           0, 0, false, true, true,
-			      handle_type_generic_attribute, false },
-  { "fn spec",	 	      1, 1, false, true, true,
-			      handle_fnspec_attribute, false },
-  { "transaction_pure",	      0, 0, false, true, true,
-			      handle_transaction_pure_attribute, false },
-  /* For internal use only.  The leading '*' both prevents its usage in
-     source code and signals that it may be overridden by machine tables.  */
-  { "*tm regparm",            0, 0, false, true, true,
-			      ignore_attribute, false },
-  { NULL,                     0, 0, false, false, false, NULL, false }
-};
-
-/* Give the specifications for the format attributes, used by C and all
-   descendants.  */
-
-const struct attribute_spec lto_format_attribute_table[] =
-{
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
-       affects_type_identity } */
-  { "format",                 3, 3, false, true,  true,
-			      handle_format_attribute, false },
-  { "format_arg",             1, 1, false, true,  true,
-			      handle_format_arg_attribute, false },
-  { NULL,                     0, 0, false, false, false, NULL, false }
-};
-
 enum built_in_attribute
 {
 #define DEF_ATTR_NULL_TREE(ENUM) ENUM,
@@ -194,325 +123,6 @@  int flag_isoc94;
 int flag_isoc99;
 int flag_isoc11;
 
-/* Attribute handlers.  */
-
-/* Handle a "noreturn" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
-			   tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			   bool * ARG_UNUSED (no_add_attrs))
-{
-  tree type = TREE_TYPE (*node);
-
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_THIS_VOLATILE (*node) = 1;
-  else if (TREE_CODE (type) == POINTER_TYPE
-	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
-    TREE_TYPE (*node)
-      = build_pointer_type
-	(build_type_variant (TREE_TYPE (type),
-			     TYPE_READONLY (TREE_TYPE (type)), 1));
-  else
-    gcc_unreachable ();
-
-  return NULL_TREE;
-}
-
-/* Handle a "leaf" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_leaf_attribute (tree *node, tree name,
-		       tree ARG_UNUSED (args),
-		       int ARG_UNUSED (flags), bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FUNCTION_DECL)
-    {
-      warning (OPT_Wattributes, "%qE attribute ignored", name);
-      *no_add_attrs = true;
-    }
-  if (!TREE_PUBLIC (*node))
-    {
-      warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions", name);
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "const" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_const_attribute (tree *node, tree ARG_UNUSED (name),
-			tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			bool * ARG_UNUSED (no_add_attrs))
-{
-  tree type = TREE_TYPE (*node);
-
-  /* See FIXME comment on noreturn in c_common_attribute_table.  */
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_READONLY (*node) = 1;
-  else if (TREE_CODE (type) == POINTER_TYPE
-	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
-    TREE_TYPE (*node)
-      = build_pointer_type
-	(build_type_variant (TREE_TYPE (type), 1,
-			     TREE_THIS_VOLATILE (TREE_TYPE (type))));
-  else
-    gcc_unreachable ();
-
-  return NULL_TREE;
-}
-
-
-/* Handle a "malloc" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
-			 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			 bool * ARG_UNUSED (no_add_attrs))
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL
-      && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
-    DECL_IS_MALLOC (*node) = 1;
-  else
-    gcc_unreachable ();
-
-  return NULL_TREE;
-}
-
-
-/* Handle a "pure" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
-		       tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-		       bool * ARG_UNUSED (no_add_attrs))
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_PURE_P (*node) = 1;
-  else
-    gcc_unreachable ();
-
-  return NULL_TREE;
-}
-
-
-/* Handle a "no vops" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
-			 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			 bool *ARG_UNUSED (no_add_attrs))
-{
-  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
-  DECL_IS_NOVOPS (*node) = 1;
-  return NULL_TREE;
-}
-
-
-/* Helper for nonnull attribute handling; fetch the operand number
-   from the attribute argument list.  */
-
-static bool
-get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
-{
-  /* Verify the arg number is a constant.  */
-  if (TREE_CODE (arg_num_expr) != INTEGER_CST
-      || TREE_INT_CST_HIGH (arg_num_expr) != 0)
-    return false;
-
-  *valp = TREE_INT_CST_LOW (arg_num_expr);
-  return true;
-}
-
-/* Handle the "nonnull" attribute.  */
-
-static tree
-handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
-			  tree args, int ARG_UNUSED (flags),
-			  bool * ARG_UNUSED (no_add_attrs))
-{
-  tree type = *node;
-
-  /* If no arguments are specified, all pointer arguments should be
-     non-null.  Verify a full prototype is given so that the arguments
-     will have the correct types when we actually check them later.  */
-  if (!args)
-    {
-      gcc_assert (prototype_p (type));
-      return NULL_TREE;
-    }
-
-  /* Argument list specified.  Verify that each argument number references
-     a pointer argument.  */
-  for (; args; args = TREE_CHAIN (args))
-    {
-      tree argument;
-      unsigned HOST_WIDE_INT arg_num = 0, ck_num;
-
-      if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
-	gcc_unreachable ();
-
-      argument = TYPE_ARG_TYPES (type);
-      if (argument)
-	{
-	  for (ck_num = 1; ; ck_num++)
-	    {
-	      if (!argument || ck_num == arg_num)
-		break;
-	      argument = TREE_CHAIN (argument);
-	    }
-
-	  gcc_assert (argument
-		      && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
-	}
-    }
-
-  return NULL_TREE;
-}
-
-
-/* Handle a "nothrow" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
-			  tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			  bool * ARG_UNUSED (no_add_attrs))
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_NOTHROW (*node) = 1;
-  else
-    gcc_unreachable ();
-
-  return NULL_TREE;
-}
-
-
-/* Handle a "sentinel" attribute.  */
-
-static tree
-handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args,
-			   int ARG_UNUSED (flags),
-			   bool * ARG_UNUSED (no_add_attrs))
-{
-  gcc_assert (stdarg_p (*node));
-
-  if (args)
-    {
-      tree position = TREE_VALUE (args);
-      gcc_assert (TREE_CODE (position) == INTEGER_CST);
-      if (tree_int_cst_lt (position, integer_zero_node))
-	gcc_unreachable ();
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "type_generic" attribute.  */
-
-static tree
-handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
-			       tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			       bool * ARG_UNUSED (no_add_attrs))
-{
-  /* Ensure we have a function type.  */
-  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-  
-  /* Ensure we have a variadic function.  */
-  gcc_assert (!prototype_p (*node) || stdarg_p (*node));
-
-  return NULL_TREE;
-}
-
-/* Handle a "transaction_pure" attribute.  */
-
-static tree
-handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
-				   tree ARG_UNUSED (args),
-				   int ARG_UNUSED (flags),
-				   bool * ARG_UNUSED (no_add_attrs))
-{
-  /* Ensure we have a function type.  */
-  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
-  return NULL_TREE;
-}
-
-/* Handle a "returns_twice" attribute.  */
-
-static tree
-handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
-				tree ARG_UNUSED (args),
-				int ARG_UNUSED (flags),
-				bool * ARG_UNUSED (no_add_attrs))
-{
-  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
-
-  DECL_IS_RETURNS_TWICE (*node) = 1;
-
-  return NULL_TREE;
-}
-
-/* Ignore the given attribute.  Used when this attribute may be usefully
-   overridden by the target, but is not used generically.  */
-
-static tree
-ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
-		  tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-		  bool *no_add_attrs)
-{
-  *no_add_attrs = true;
-  return NULL_TREE;
-}
-
-/* Handle a "format" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_format_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
-			 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			 bool *no_add_attrs)
-{
-  *no_add_attrs = true;
-  return NULL_TREE;
-}
-
-
-/* Handle a "format_arg" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-tree
-handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
-			     tree ARG_UNUSED (args), int ARG_UNUSED (flags),
-			     bool *no_add_attrs)
-{
-  *no_add_attrs = true;
-  return NULL_TREE;
-}
-
-
-/* Handle a "fn spec" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
-			 tree args, int ARG_UNUSED (flags),
-			 bool *no_add_attrs ATTRIBUTE_UNUSED)
-{
-  gcc_assert (args
-	      && TREE_CODE (TREE_VALUE (args)) == STRING_CST
-	      && !TREE_CHAIN (args));
-  return NULL_TREE;
-}
-
 /* Cribbed from c-common.c.  */
 
 static void
@@ -1286,12 +896,6 @@  static void lto_init_ts (void)
 #undef LANG_HOOKS_EH_PERSONALITY
 #define LANG_HOOKS_EH_PERSONALITY lto_eh_personality
 
-/* Attribute hooks.  */
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE lto_attribute_table
-#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
-#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE lto_format_attribute_table
-
 #undef LANG_HOOKS_BEGIN_SECTION
 #define LANG_HOOKS_BEGIN_SECTION lto_obj_begin_section
 #undef LANG_HOOKS_APPEND_DATA