diff gcc/c-family/c-attribs.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/c-family/c-attribs.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/c-family/c-attribs.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* C-family attributes handling.
-   Copyright (C) 1992-2017 Free Software Foundation, Inc.
+   Copyright (C) 1992-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -143,252 +143,334 @@
 static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
 						 bool *);
 static tree handle_designated_init_attribute (tree *, tree, tree, int, bool *);
-static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *);
-static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
-static tree handle_bnd_instrument (tree *, tree, tree, int, bool *);
 static tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
 static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
 						       int, bool *);
 
+/* Helper to define attribute exclusions.  */
+#define ATTR_EXCL(name, function, type, variable)	\
+  { name, function, type, variable }
+
+/* Define attributes that are mutually exclusive with one another.  */
+static const struct attribute_spec::exclusions attr_aligned_exclusions[] =
+{
+  /* Attribute name     exclusion applies to:
+	                function, type, variable */
+  ATTR_EXCL ("aligned", true, false, false),
+  ATTR_EXCL ("packed", true, false, false),
+  ATTR_EXCL (NULL, false, false, false)
+};
+
+static const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
+{
+  ATTR_EXCL ("cold", true, true, true),
+  ATTR_EXCL ("hot", true, true, true),
+  ATTR_EXCL (NULL, false, false, false)
+};
+
+static const struct attribute_spec::exclusions attr_common_exclusions[] =
+{
+  ATTR_EXCL ("common", true, true, true),
+  ATTR_EXCL ("nocommon", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_inline_exclusions[] =
+{
+  ATTR_EXCL ("noinline", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
+{
+  ATTR_EXCL ("always_inline", true, true, true),
+  ATTR_EXCL ("gnu_inline", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
+{
+  ATTR_EXCL ("alloc_align", true, true, true),
+  ATTR_EXCL ("alloc_size", true, true, true),
+  ATTR_EXCL ("const", true, true, true),
+  ATTR_EXCL ("malloc", true, true, true),
+  ATTR_EXCL ("pure", true, true, true),
+  ATTR_EXCL ("returns_twice", true, true, true),
+  ATTR_EXCL ("warn_unused_result", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions
+attr_warn_unused_result_exclusions[] =
+{
+  ATTR_EXCL ("noreturn", true, true, true),
+  ATTR_EXCL ("warn_unused_result", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
+{
+  ATTR_EXCL ("noreturn", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+/* Exclusions that apply to attribute alloc_align, alloc_size, and malloc.  */
+static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
+{
+  ATTR_EXCL ("const", true, true, true),
+  ATTR_EXCL ("noreturn", true, true, true),
+  ATTR_EXCL ("pure", true, true, true),
+  ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
+{
+  ATTR_EXCL ("const", true, true, true),
+  ATTR_EXCL ("alloc_align", true, true, true),
+  ATTR_EXCL ("alloc_size", true, true, true),
+  ATTR_EXCL ("malloc", true, true, true),
+  ATTR_EXCL ("noreturn", true, true, true),
+  ATTR_EXCL ("pure", true, true, true),
+  ATTR_EXCL (NULL, false, false, false)
+};
+
 /* Table of machine-independent attributes common to all C-like languages.
 
-   All attributes referencing arguments should be additionally processed
-   in chkp_copy_function_type_adding_bounds for correct instrumentation
-   by Pointer Bounds Checker.
    Current list of processed common attributes: nonnull.  */
 const struct attribute_spec c_common_attribute_table[] =
 {
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
-       affects_type_identity } */
-  { "packed",                 0, 0, false, false, false,
-			      handle_packed_attribute , false},
-  { "nocommon",               0, 0, true,  false, false,
-			      handle_nocommon_attribute, false},
-  { "common",                 0, 0, true,  false, false,
-			      handle_common_attribute, false },
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+       affects_type_identity, handler, exclude } */
+  { "packed",                 0, 0, false, false, false, false,
+			      handle_packed_attribute,
+	                      attr_aligned_exclusions },
+  { "nocommon",               0, 0, true,  false, false, false,
+			      handle_nocommon_attribute,
+	                      attr_common_exclusions },
+  { "common",                 0, 0, true,  false, false, false,
+			      handle_common_attribute,
+	                      attr_common_exclusions },
   /* FIXME: logically, noreturn attributes should be listed as
      "false, true, true" and apply to function types.  But implementing this
      would require all the places in the compiler that use TREE_THIS_VOLATILE
      on a decl to identify non-returning functions to be located and fixed
      to check the function type instead.  */
-  { "noreturn",               0, 0, true,  false, false,
-			      handle_noreturn_attribute, false },
-  { "volatile",               0, 0, true,  false, false,
-			      handle_noreturn_attribute, false },
-  { "stack_protect",          0, 0, true,  false, false,
-			      handle_stack_protect_attribute, false },
-  { "noinline",               0, 0, true,  false, false,
-			      handle_noinline_attribute, false },
-  { "noclone",                0, 0, true,  false, false,
-			      handle_noclone_attribute, false },
-  { "no_icf",                 0, 0, true,  false, false,
-			      handle_noicf_attribute, false },
-  { "noipa",		      0, 0, true,  false, false,
-			      handle_noipa_attribute, false },
-  { "leaf",                   0, 0, true,  false, false,
-			      handle_leaf_attribute, false },
-  { "always_inline",          0, 0, true,  false, false,
-			      handle_always_inline_attribute, false },
-  { "gnu_inline",             0, 0, true,  false, false,
-			      handle_gnu_inline_attribute, false },
-  { "artificial",             0, 0, true,  false, false,
-			      handle_artificial_attribute, false },
-  { "flatten",                0, 0, true,  false, false,
-			      handle_flatten_attribute, false },
-  { "used",                   0, 0, true,  false, false,
-			      handle_used_attribute, false },
-  { "unused",                 0, 0, false, false, false,
-			      handle_unused_attribute, false },
-  { "externally_visible",     0, 0, true,  false, false,
-			      handle_externally_visible_attribute, false },
-  { "no_reorder",	      0, 0, true, false, false,
-                              handle_no_reorder_attribute, false },
+  { "noreturn",               0, 0, true,  false, false, false,
+			      handle_noreturn_attribute,
+	                      attr_noreturn_exclusions },
+  { "volatile",               0, 0, true,  false, false, false,
+			      handle_noreturn_attribute, NULL },
+  { "stack_protect",          0, 0, true,  false, false, false,
+			      handle_stack_protect_attribute, NULL },
+  { "noinline",               0, 0, true,  false, false, false,
+			      handle_noinline_attribute,
+	                      attr_noinline_exclusions },
+  { "noclone",                0, 0, true,  false, false, false,
+			      handle_noclone_attribute, NULL },
+  { "no_icf",                 0, 0, true,  false, false, false,
+			      handle_noicf_attribute, NULL },
+  { "noipa",		      0, 0, true,  false, false, false,
+			      handle_noipa_attribute, NULL },
+  { "leaf",                   0, 0, true,  false, false, false,
+			      handle_leaf_attribute, NULL },
+  { "always_inline",          0, 0, true,  false, false, false,
+			      handle_always_inline_attribute,
+	                      attr_inline_exclusions },
+  { "gnu_inline",             0, 0, true,  false, false, false,
+			      handle_gnu_inline_attribute,
+	                      attr_inline_exclusions },
+  { "artificial",             0, 0, true,  false, false, false,
+			      handle_artificial_attribute, NULL },
+  { "flatten",                0, 0, true,  false, false, false,
+			      handle_flatten_attribute, NULL },
+  { "used",                   0, 0, true,  false, false, false,
+			      handle_used_attribute, NULL },
+  { "unused",                 0, 0, false, false, false, false,
+			      handle_unused_attribute, NULL },
+  { "externally_visible",     0, 0, true,  false, false, false,
+			      handle_externally_visible_attribute, NULL },
+  { "no_reorder",	      0, 0, true, false, false, false,
+	                      handle_no_reorder_attribute, NULL },
   /* The same comments as for noreturn attributes apply to const ones.  */
-  { "const",                  0, 0, true,  false, false,
-			      handle_const_attribute, false },
-  { "scalar_storage_order",   1, 1, false, false, false,
-			      handle_scalar_storage_order_attribute, false },
-  { "transparent_union",      0, 0, false, false, false,
-			      handle_transparent_union_attribute, false },
-  { "constructor",            0, 1, true,  false, false,
-			      handle_constructor_attribute, false },
-  { "destructor",             0, 1, true,  false, false,
-			      handle_destructor_attribute, false },
-  { "mode",                   1, 1, false,  true, false,
-			      handle_mode_attribute, false },
-  { "section",                1, 1, true,  false, false,
-			      handle_section_attribute, false },
-  { "aligned",                0, 1, false, false, false,
-			      handle_aligned_attribute, false },
-  { "warn_if_not_aligned",    0, 1, false, false, false,
-			      handle_warn_if_not_aligned_attribute,
-			      false },
-  { "weak",                   0, 0, true,  false, false,
-			      handle_weak_attribute, false },
-  { "noplt",                   0, 0, true,  false, false,
-			      handle_noplt_attribute, false },
-  { "ifunc",                  1, 1, true,  false, false,
-			      handle_ifunc_attribute, false },
-  { "alias",                  1, 1, true,  false, false,
-			      handle_alias_attribute, false },
-  { "weakref",                0, 1, true,  false, false,
-			      handle_weakref_attribute, false },
-  { "no_instrument_function", 0, 0, true,  false, false,
+  { "const",                  0, 0, true,  false, false, false,
+			      handle_const_attribute,
+	                      attr_const_pure_exclusions },
+  { "scalar_storage_order",   1, 1, false, false, false, false,
+			      handle_scalar_storage_order_attribute, NULL },
+  { "transparent_union",      0, 0, false, false, false, false,
+			      handle_transparent_union_attribute, NULL },
+  { "constructor",            0, 1, true,  false, false, false,
+			      handle_constructor_attribute, NULL },
+  { "destructor",             0, 1, true,  false, false, false,
+			      handle_destructor_attribute, NULL },
+  { "mode",                   1, 1, false,  true, false, false,
+			      handle_mode_attribute, NULL },
+  { "section",                1, 1, true,  false, false, false,
+			      handle_section_attribute, NULL },
+  { "aligned",                0, 1, false, false, false, false,
+			      handle_aligned_attribute,
+	                      attr_aligned_exclusions },
+  { "warn_if_not_aligned",    0, 1, false, false, false, false,
+			      handle_warn_if_not_aligned_attribute, NULL },
+  { "weak",                   0, 0, true,  false, false, false,
+			      handle_weak_attribute, NULL },
+  { "noplt",                   0, 0, true,  false, false, false,
+			      handle_noplt_attribute, NULL },
+  { "ifunc",                  1, 1, true,  false, false, false,
+			      handle_ifunc_attribute, NULL },
+  { "alias",                  1, 1, true,  false, false, false,
+			      handle_alias_attribute, NULL },
+  { "weakref",                0, 1, true,  false, false, false,
+			      handle_weakref_attribute, NULL },
+  { "no_instrument_function", 0, 0, true,  false, false, false,
 			      handle_no_instrument_function_attribute,
-			      false },
-  { "no_profile_instrument_function",  0, 0, true, false, false,
+			      NULL },
+  { "no_profile_instrument_function",  0, 0, true, false, false, false,
 			      handle_no_profile_instrument_function_attribute,
-			      false },
-  { "malloc",                 0, 0, true,  false, false,
-			      handle_malloc_attribute, false },
-  { "returns_twice",          0, 0, true,  false, false,
-			      handle_returns_twice_attribute, false },
-  { "no_stack_limit",         0, 0, true,  false, false,
-			      handle_no_limit_stack_attribute, false },
-  { "pure",                   0, 0, true,  false, false,
-			      handle_pure_attribute, false },
-  { "transaction_callable",   0, 0, false, true,  false,
-			      handle_tm_attribute, false },
-  { "transaction_unsafe",     0, 0, false, true,  false,
-			      handle_tm_attribute, true },
-  { "transaction_safe",       0, 0, false, true,  false,
-			      handle_tm_attribute, true },
-  { "transaction_safe_dynamic", 0, 0, true, false,  false,
-			      handle_tm_attribute, false },
-  { "transaction_may_cancel_outer", 0, 0, false, true, false,
-			      handle_tm_attribute, false },
+			      NULL },
+  { "malloc",                 0, 0, true,  false, false, false,
+			      handle_malloc_attribute, attr_alloc_exclusions },
+  { "returns_twice",          0, 0, true,  false, false, false,
+			      handle_returns_twice_attribute,
+	                      attr_returns_twice_exclusions },
+  { "no_stack_limit",         0, 0, true,  false, false, false,
+			      handle_no_limit_stack_attribute, NULL },
+  { "pure",                   0, 0, true,  false, false, false,
+			      handle_pure_attribute,
+	                      attr_const_pure_exclusions },
+  { "transaction_callable",   0, 0, false, true,  false, false,
+			      handle_tm_attribute, NULL },
+  { "transaction_unsafe",     0, 0, false, true,  false, true,
+			      handle_tm_attribute, NULL },
+  { "transaction_safe",       0, 0, false, true,  false, true,
+			      handle_tm_attribute, NULL },
+  { "transaction_safe_dynamic", 0, 0, true, false,  false, false,
+			      handle_tm_attribute, NULL },
+  { "transaction_may_cancel_outer", 0, 0, false, true, false, false,
+			      handle_tm_attribute, NULL },
   /* ??? These two attributes didn't make the transition from the
      Intel language document to the multi-vendor language document.  */
-  { "transaction_pure",       0, 0, false, true,  false,
-			      handle_tm_attribute, false },
-  { "transaction_wrap",       1, 1, true,  false,  false,
-			     handle_tm_wrap_attribute, false },
+  { "transaction_pure",       0, 0, false, true,  false, false,
+			      handle_tm_attribute, NULL },
+  { "transaction_wrap",       1, 1, true,  false,  false, false,
+			     handle_tm_wrap_attribute, NULL },
   /* For internal use (marking of builtins) only.  The name contains space
      to prevent its usage in source code.  */
-  { "no vops",                0, 0, true,  false, false,
-			      handle_novops_attribute, false },
-  { "deprecated",             0, 1, false, false, false,
-			      handle_deprecated_attribute, false },
-  { "vector_size",	      1, 1, false, true, false,
-			      handle_vector_size_attribute, true },
-  { "visibility",	      1, 1, false, false, false,
-			      handle_visibility_attribute, false },
-  { "tls_model",	      1, 1, true,  false, false,
-			      handle_tls_model_attribute, false },
-  { "nonnull",                0, -1, false, true, true,
-			      handle_nonnull_attribute, false },
-  { "nonstring",              0, 0, true, false, false,
-			      handle_nonstring_attribute, false },
-  { "nothrow",                0, 0, true,  false, false,
-			      handle_nothrow_attribute, false },
-  { "may_alias",	      0, 0, false, true, false, NULL, false },
-  { "cleanup",		      1, 1, true, false, false,
-			      handle_cleanup_attribute, false },
-  { "warn_unused_result",     0, 0, false, true, true,
-			      handle_warn_unused_result_attribute, false },
-  { "sentinel",               0, 1, false, true, true,
-			      handle_sentinel_attribute, false },
+  { "no vops",                0, 0, true,  false, false, false,
+			      handle_novops_attribute, NULL },
+  { "deprecated",             0, 1, false, false, false, false,
+			      handle_deprecated_attribute, NULL },
+  { "vector_size",	      1, 1, false, true, false, true,
+			      handle_vector_size_attribute, NULL },
+  { "visibility",	      1, 1, false, false, false, false,
+			      handle_visibility_attribute, NULL },
+  { "tls_model",	      1, 1, true,  false, false, false,
+			      handle_tls_model_attribute, NULL },
+  { "nonnull",                0, -1, false, true, true, false,
+			      handle_nonnull_attribute, NULL },
+  { "nonstring",              0, 0, true, false, false, false,
+			      handle_nonstring_attribute, NULL },
+  { "nothrow",                0, 0, true,  false, false, false,
+			      handle_nothrow_attribute, NULL },
+  { "may_alias",	      0, 0, false, true, false, false, NULL, NULL },
+  { "cleanup",		      1, 1, true, false, false, false,
+			      handle_cleanup_attribute, NULL },
+  { "warn_unused_result",     0, 0, false, true, true, false,
+			      handle_warn_unused_result_attribute,
+	                      attr_warn_unused_result_exclusions },
+  { "sentinel",               0, 1, false, true, true, false,
+			      handle_sentinel_attribute, NULL },
   /* For internal use (marking of builtins) only.  The name contains space
      to prevent its usage in source code.  */
-  { "type generic",           0, 0, false, true, true,
-			      handle_type_generic_attribute, false },
-  { "alloc_size",	      1, 2, false, true, true,
-			      handle_alloc_size_attribute, false },
-  { "cold",                   0, 0, true,  false, false,
-			      handle_cold_attribute, false },
-  { "hot",                    0, 0, true,  false, false,
-			      handle_hot_attribute, false },
+  { "type generic",           0, 0, false, true, true, false,
+			      handle_type_generic_attribute, NULL },
+  { "alloc_size",	      1, 2, false, true, true, false,
+			      handle_alloc_size_attribute,
+	                      attr_alloc_exclusions },
+  { "cold",                   0, 0, true,  false, false, false,
+			      handle_cold_attribute,
+	                      attr_cold_hot_exclusions },
+  { "hot",                    0, 0, true,  false, false, false,
+			      handle_hot_attribute,
+	                      attr_cold_hot_exclusions },
   { "no_address_safety_analysis",
-			      0, 0, true, false, false,
+			      0, 0, true, false, false, false,
 			      handle_no_address_safety_analysis_attribute,
-			      false },
-  { "no_sanitize",	      1, 1, true, false, false,
-			      handle_no_sanitize_attribute,
-			      false },
-  { "no_sanitize_address",    0, 0, true, false, false,
-			      handle_no_sanitize_address_attribute,
-			      false },
-  { "no_sanitize_thread",     0, 0, true, false, false,
-			      handle_no_sanitize_thread_attribute,
-			      false },
-  { "no_sanitize_undefined",  0, 0, true, false, false,
-			      handle_no_sanitize_undefined_attribute,
-			      false },
-  { "asan odr indicator",     0, 0, true, false, false,
-			      handle_asan_odr_indicator_attribute,
-			      false },
-  { "warning",		      1, 1, true,  false, false,
-			      handle_error_attribute, false },
-  { "error",		      1, 1, true,  false, false,
-			      handle_error_attribute, false },
-  { "target",                 1, -1, true, false, false,
-			      handle_target_attribute, false },
-  { "target_clones",          1, -1, true, false, false,
-			      handle_target_clones_attribute, false },
-  { "optimize",               1, -1, true, false, false,
-			      handle_optimize_attribute, false },
+			      NULL },
+  { "no_sanitize",	      1, -1, true, false, false, false,
+			      handle_no_sanitize_attribute, NULL },
+  { "no_sanitize_address",    0, 0, true, false, false, false,
+			      handle_no_sanitize_address_attribute, NULL },
+  { "no_sanitize_thread",     0, 0, true, false, false, false,
+			      handle_no_sanitize_thread_attribute, NULL },
+  { "no_sanitize_undefined",  0, 0, true, false, false, false,
+			      handle_no_sanitize_undefined_attribute, NULL },
+  { "asan odr indicator",     0, 0, true, false, false, false,
+			      handle_asan_odr_indicator_attribute, NULL },
+  { "warning",		      1, 1, true,  false, false, false,
+			      handle_error_attribute, NULL },
+  { "error",		      1, 1, true,  false, false, false,
+			      handle_error_attribute, NULL },
+  { "target",                 1, -1, true, false, false, false,
+			      handle_target_attribute, NULL },
+  { "target_clones",          1, -1, true, false, false, false,
+			      handle_target_clones_attribute, NULL },
+  { "optimize",               1, -1, true, false, false, false,
+			      handle_optimize_attribute, NULL },
   /* 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 },
-  { "no_split_stack",	      0, 0, true,  false, false,
-			      handle_no_split_stack_attribute, false },
+  { "*tm regparm",            0, 0, false, true, true, false,
+			      ignore_attribute, NULL },
+  { "no_split_stack",	      0, 0, true,  false, false, false,
+			      handle_no_split_stack_attribute, NULL },
   /* For internal use (marking of builtins and runtime functions) only.
      The name contains space to prevent its usage in source code.  */
-  { "fn spec",		      1, 1, false, true, true,
-			      handle_fnspec_attribute, false },
-  { "warn_unused",            0, 0, false, false, false,
-			      handle_warn_unused_attribute, false },
-  { "returns_nonnull",        0, 0, false, true, true,
-			      handle_returns_nonnull_attribute, false },
-  { "omp declare simd",       0, -1, true,  false, false,
-			      handle_omp_declare_simd_attribute, false },
-  { "cilk simd function",     0, -1, true,  false, false,
-			      handle_omp_declare_simd_attribute, false },
-  { "simd",		      0, 1, true,  false, false,
-			      handle_simd_attribute, false },
-  { "omp declare target",     0, 0, true, false, false,
-			      handle_omp_declare_target_attribute, false },
-  { "omp declare target link", 0, 0, true, false, false,
-			      handle_omp_declare_target_attribute, false },
-  { "alloc_align",	      1, 1, false, true, true,
-			      handle_alloc_align_attribute, false },
-  { "assume_aligned",	      1, 2, false, true, true,
-			      handle_assume_aligned_attribute, false },
-  { "designated_init",        0, 0, false, true, false,
-			      handle_designated_init_attribute, false },
-  { "bnd_variable_size",      0, 0, true,  false, false,
-			      handle_bnd_variable_size_attribute, false },
-  { "bnd_legacy",             0, 0, true, false, false,
-			      handle_bnd_legacy, false },
-  { "bnd_instrument",         0, 0, true, false, false,
-			      handle_bnd_instrument, false },
-  { "fallthrough",	      0, 0, false, false, false,
-			      handle_fallthrough_attribute, false },
-  { "patchable_function_entry",	1, 2, true, false, false,
+  { "fn spec",		      1, 1, false, true, true, false,
+			      handle_fnspec_attribute, NULL },
+  { "warn_unused",            0, 0, false, false, false, false,
+			      handle_warn_unused_attribute, NULL },
+  { "returns_nonnull",        0, 0, false, true, true, false,
+			      handle_returns_nonnull_attribute, NULL },
+  { "omp declare simd",       0, -1, true,  false, false, false,
+			      handle_omp_declare_simd_attribute, NULL },
+  { "simd",		      0, 1, true,  false, false, false,
+			      handle_simd_attribute, NULL },
+  { "omp declare target",     0, 0, true, false, false, false,
+			      handle_omp_declare_target_attribute, NULL },
+  { "omp declare target link", 0, 0, true, false, false, false,
+			      handle_omp_declare_target_attribute, NULL },
+  { "omp declare target implicit", 0, 0, true, false, false, false,
+			      handle_omp_declare_target_attribute, NULL },
+  { "alloc_align",	      1, 1, false, true, true, false,
+			      handle_alloc_align_attribute,
+	                      attr_alloc_exclusions },
+  { "assume_aligned",	      1, 2, false, true, true, false,
+			      handle_assume_aligned_attribute, NULL },
+  { "designated_init",        0, 0, false, true, false, false,
+			      handle_designated_init_attribute, NULL },
+  { "fallthrough",	      0, 0, false, false, false, false,
+			      handle_fallthrough_attribute, NULL },
+  { "patchable_function_entry",	1, 2, true, false, false, false,
 			      handle_patchable_function_entry_attribute,
-			      false },
-  { "nocf_check",		      0, 0, false, true, true,
-			      handle_nocf_check_attribute, true },
-  { NULL,                     0, 0, false, false, false, NULL, false }
+			      NULL },
+  { "nocf_check",	      0, 0, false, true, true, true,
+			      handle_nocf_check_attribute, NULL },
+  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
 };
 
 /* Give the specifications for the format attributes, used by C and all
    descendants.
 
-   All attributes referencing arguments should be additionally processed
-   in chkp_copy_function_type_adding_bounds for correct instrumentation
-   by Pointer Bounds Checker.
    Current list of processed format attributes: format, format_arg.  */
 const struct attribute_spec c_common_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 }
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
+       affects_type_identity, handler, exclude } */
+  { "format",                 3, 3, false, true,  true, false,
+			      handle_format_attribute, NULL },
+  { "format_arg",             1, 1, false, true,  true, false,
+			      handle_format_arg_attribute, NULL },
+  { NULL,                     0, 0, false, false, false, false, NULL, NULL }
 };
 
 /* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
@@ -422,8 +504,13 @@
   if (TYPE_P (*node))
     {
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-	*node = build_variant_type_copy (*node);
-      TYPE_PACKED (*node) = 1;
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute ignored for type %qT", name, *node);
+	  *no_add_attrs = true;
+	}
+      else
+	TYPE_PACKED (*node) = 1;
     }
   else if (TREE_CODE (*node) == FIELD_DECL)
     {
@@ -526,14 +613,7 @@
   if (TREE_CODE (*node) == FUNCTION_DECL
       || TREE_CODE (*node) == LABEL_DECL)
     {
-      if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL)
-	{
-	  warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
-		   "with attribute %qs", name, "cold");
-	  *no_add_attrs = true;
-	}
-      /* Most of the rest of the hot processing is done later with
-	 lookup_attribute.  */
+      /* Attribute hot processing is done later with lookup_attribute.  */
     }
   else
     {
@@ -554,14 +634,7 @@
   if (TREE_CODE (*node) == FUNCTION_DECL
       || TREE_CODE (*node) == LABEL_DECL)
     {
-      if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL)
-	{
-	  warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
-		   "with attribute %qs", name, "hot");
-	  *no_add_attrs = true;
-	}
-      /* Most of the rest of the cold processing is done later with
-	 lookup_attribute.  */
+      /* Attribute cold processing is done later with lookup_attribute.  */
     }
   else
     {
@@ -602,23 +675,27 @@
 handle_no_sanitize_attribute (tree *node, tree name, tree args, int,
 			      bool *no_add_attrs)
 {
+  unsigned int flags = 0;
   *no_add_attrs = true;
-  tree id = TREE_VALUE (args);
   if (TREE_CODE (*node) != FUNCTION_DECL)
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
-  if (TREE_CODE (id) != STRING_CST)
+  for (; args; args = TREE_CHAIN (args))
     {
-      error ("no_sanitize argument not a string");
-      return NULL_TREE;
+      tree id = TREE_VALUE (args);
+      if (TREE_CODE (id) != STRING_CST)
+	{
+	  error ("no_sanitize argument not a string");
+	  return NULL_TREE;
+	}
+
+      char *string = ASTRDUP (TREE_STRING_POINTER (id));
+      flags |= parse_no_sanitize_attribute (string);
     }
 
-  char *string = ASTRDUP (TREE_STRING_POINTER (id));
-  unsigned int flags = parse_no_sanitize_attribute (string);
-
   add_no_sanitize_value (*node, flags);
 
   return NULL_TREE;
@@ -1088,7 +1165,7 @@
 
 static tree
 handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-			int ARG_UNUSED (flags), bool *no_add_attrs)
+			int flags, bool *no_add_attrs)
 {
   tree type = TREE_TYPE (*node);
 
@@ -1109,6 +1186,14 @@
       *no_add_attrs = true;
     }
 
+  /* void __builtin_unreachable(void) is const.  Accept other such
+     built-ins but warn on user-defined functions that return void.  */
+  if (!(flags & ATTR_FLAG_BUILT_IN)
+      && TREE_CODE (*node) == FUNCTION_DECL
+      && VOID_TYPE_P (TREE_TYPE (type)))
+    warning (OPT_Wattributes, "%qE attribute on function "
+	     "returning %<void%>", name);
+
   return NULL_TREE;
 }
 
@@ -1265,12 +1350,12 @@
   if (pri <= MAX_RESERVED_INIT_PRIORITY)
     {
       if (is_destructor)
-	warning (0,
+	warning (OPT_Wprio_ctor_dtor,
 		 "destructor priorities from 0 to %d are reserved "
 		 "for the implementation",
 		 MAX_RESERVED_INIT_PRIORITY);
       else
-	warning (0,
+	warning (OPT_Wprio_ctor_dtor,
 		 "constructor priorities from 0 to %d are reserved "
 		 "for the implementation",
 		 MAX_RESERVED_INIT_PRIORITY);
@@ -1439,6 +1524,10 @@
 	  return NULL_TREE;
 	}
 
+      /* Allow the target a chance to translate MODE into something supported.
+	 See PR86324.  */
+      mode = targetm.translate_mode_attribute (mode);
+
       valid_mode = false;
       switch (GET_MODE_CLASS (mode))
 	{
@@ -1691,15 +1780,19 @@
    handle_aligned_attribute.  */
 
 static tree
-common_handle_aligned_attribute (tree *node, tree args, int flags,
+common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
 				 bool *no_add_attrs,
 				 bool warn_if_not_aligned_p)
 {
   tree decl = NULL_TREE;
   tree *type = NULL;
-  int is_type = 0;
+  bool is_type = false;
   tree align_expr;
-  int i;
+
+  /* The last (already pushed) declaration with all validated attributes
+     merged in or the current about-to-be-pushed one if one hasn't been
+     yet.  */
+  tree last_decl = node[1] ? node[1] : *node;
 
   if (args)
     {
@@ -1718,12 +1811,26 @@
       is_type = TREE_CODE (*node) == TYPE_DECL;
     }
   else if (TYPE_P (*node))
-    type = node, is_type = 1;
-
-  if ((i = check_user_alignment (align_expr, true)) == -1
-      || !check_cxx_fundamental_alignment_constraints (*node, i, flags))
-    *no_add_attrs = true;
-  else if (is_type)
+    type = node, is_type = true;
+
+  /* Log2 of specified alignment.  */
+  int pow2align = check_user_alignment (align_expr, true);
+  if (pow2align == -1
+      || !check_cxx_fundamental_alignment_constraints (*node, pow2align, flags))
+    {
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* The alignment in bits corresponding to the specified alignment.  */
+  unsigned bitalign = (1U << pow2align) * BITS_PER_UNIT;
+
+  /* The alignment of the current declaration and that of the last
+     pushed declaration, determined on demand below.  */
+  unsigned curalign = 0;
+  unsigned lastalign = 0;
+
+  if (is_type)
     {
       if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
 	/* OK, modify the type in place.  */;
@@ -1744,12 +1851,12 @@
 
       if (warn_if_not_aligned_p)
 	{
-	  SET_TYPE_WARN_IF_NOT_ALIGN (*type, (1U << i) * BITS_PER_UNIT);
+	  SET_TYPE_WARN_IF_NOT_ALIGN (*type, bitalign);
 	  warn_if_not_aligned_p = false;
 	}
       else
 	{
-	  SET_TYPE_ALIGN (*type, (1U << i) * BITS_PER_UNIT);
+	  SET_TYPE_ALIGN (*type, bitalign);
 	  TYPE_USER_ALIGN (*type) = 1;
 	}
     }
@@ -1759,8 +1866,38 @@
       error ("alignment may not be specified for %q+D", decl);
       *no_add_attrs = true;
     }
+  else if (TREE_CODE (decl) == FUNCTION_DECL
+	   && ((curalign = DECL_ALIGN (decl)) > bitalign
+	       || ((lastalign = DECL_ALIGN (last_decl)) > bitalign)))
+    {
+      /* Either a prior attribute on the same declaration or one
+	 on a prior declaration of the same function specifies
+	 stricter alignment than this attribute.  */
+      bool note = lastalign != 0;
+      if (lastalign)
+	curalign = lastalign;
+
+      curalign /= BITS_PER_UNIT;
+      bitalign /= BITS_PER_UNIT;
+
+      bool diagd = true;
+      auto_diagnostic_group d;
+      if (DECL_USER_ALIGN (decl) || DECL_USER_ALIGN (last_decl))
+	diagd = warning (OPT_Wattributes,
+			  "ignoring attribute %<%E (%u)%> because it conflicts "
+			  "with attribute %<%E (%u)%>",
+			  name, bitalign, name, curalign);
+      else if (!warn_if_not_aligned_p)
+	/* Do not error out for attribute warn_if_not_aligned.  */
+	error ("alignment for %q+D must be at least %d", decl, curalign);
+
+      if (diagd && note)
+	inform (DECL_SOURCE_LOCATION (last_decl), "previous declaration here");
+
+      *no_add_attrs = true;
+    }
   else if (DECL_USER_ALIGN (decl)
-	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
+	   && DECL_ALIGN (decl) > bitalign)
     /* C++-11 [dcl.align/4]:
 
 	   When multiple alignment-specifiers are specified for an
@@ -1772,7 +1909,7 @@
     *no_add_attrs = true;
   else if (!warn_if_not_aligned_p
 	   && TREE_CODE (decl) == FUNCTION_DECL
-	   && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
+	   && DECL_ALIGN (decl) > bitalign)
     {
       /* Don't warn function alignment here if warn_if_not_aligned_p is
 	 true.  It will be warned later.  */
@@ -1791,13 +1928,13 @@
 	{
 	  if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl))
 	    {
-	      SET_DECL_WARN_IF_NOT_ALIGN (decl, (1U << i) * BITS_PER_UNIT);
+	      SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign);
 	      warn_if_not_aligned_p = false;
 	    }
 	}
       else
 	{
-	  SET_DECL_ALIGN (decl, (1U << i) * BITS_PER_UNIT);
+	  SET_DECL_ALIGN (decl, bitalign);
 	  DECL_USER_ALIGN (decl) = 1;
 	}
     }
@@ -1816,10 +1953,10 @@
    struct attribute_spec.handler.  */
 
 static tree
-handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+handle_aligned_attribute (tree *node, tree name, tree args,
 			  int flags, bool *no_add_attrs)
 {
-  return common_handle_aligned_attribute (node, args, flags,
+  return common_handle_aligned_attribute (node, name, args, flags,
 					 no_add_attrs, false);
 }
 
@@ -1827,11 +1964,11 @@
    struct attribute_spec.handler.  */
 
 static tree
-handle_warn_if_not_aligned_attribute (tree *node, tree ARG_UNUSED (name),
+handle_warn_if_not_aligned_attribute (tree *node, tree name,
 				      tree args, int flags,
 				      bool *no_add_attrs)
 {
-  return common_handle_aligned_attribute (node, args, flags,
+  return common_handle_aligned_attribute (node, name, args, flags,
 					  no_add_attrs, true);
 }
 
@@ -2163,14 +2300,13 @@
 
 static tree
 handle_tls_model_attribute (tree *node, tree name, tree args,
-			    int ARG_UNUSED (flags), bool *no_add_attrs)
+			    int ARG_UNUSED (flags),
+			    bool *ARG_UNUSED (no_add_attrs))
 {
   tree id;
   tree decl = *node;
   enum tls_model kind;
 
-  *no_add_attrs = true;
-
   if (!VAR_P (decl) || !DECL_THREAD_LOCAL_P (decl))
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -2350,54 +2486,6 @@
   return NULL_TREE;
 }
 
-/* Handle a "bnd_variable_size" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_bnd_variable_size_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-				    int ARG_UNUSED (flags), bool *no_add_attrs)
-{
-  if (TREE_CODE (*node) != FIELD_DECL)
-    {
-      warning (OPT_Wattributes, "%qE attribute ignored", name);
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "bnd_legacy" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_bnd_legacy (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;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "bnd_instrument" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_bnd_instrument (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;
-    }
-
-  return NULL_TREE;
-}
-
 /* Handle a "warn_unused" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -2435,50 +2523,37 @@
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     {
-      if (lookup_attribute ("cilk simd function",
-			    DECL_ATTRIBUTES (*node)) != NULL)
+      tree t = get_identifier ("omp declare simd");
+      tree attr = NULL_TREE;
+      if (args)
 	{
-	  error_at (DECL_SOURCE_LOCATION (*node),
-		    "%<__simd__%> attribute cannot be used in the same "
-		    "function marked as a Cilk Plus SIMD-enabled function");
-	  *no_add_attrs = true;
-	}
-      else
-	{
-	  tree t = get_identifier ("omp declare simd");
-	  tree attr = NULL_TREE;
-	  if (args)
+	  tree id = TREE_VALUE (args);
+
+	  if (TREE_CODE (id) != STRING_CST)
 	    {
-	      tree id = TREE_VALUE (args);
-
-	      if (TREE_CODE (id) != STRING_CST)
-		{
-		  error ("attribute %qE argument not a string", name);
-		  *no_add_attrs = true;
-		  return NULL_TREE;
-		}
-
-	      if (strcmp (TREE_STRING_POINTER (id), "notinbranch") == 0)
-		attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
-					 OMP_CLAUSE_NOTINBRANCH);
-	      else
-		if (strcmp (TREE_STRING_POINTER (id), "inbranch") == 0)
-		  attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
-					   OMP_CLAUSE_INBRANCH);
-		else
-		{
-		  error ("only %<inbranch%> and %<notinbranch%> flags are "
-			 "allowed for %<__simd__%> attribute");
-		  *no_add_attrs = true;
-		  return NULL_TREE;
-		}
+	      error ("attribute %qE argument not a string", name);
+	      *no_add_attrs = true;
+	      return NULL_TREE;
 	    }
 
-	  DECL_ATTRIBUTES (*node) = tree_cons (t,
-					       build_tree_list (NULL_TREE,
-								attr),
-					       DECL_ATTRIBUTES (*node));
+	  if (strcmp (TREE_STRING_POINTER (id), "notinbranch") == 0)
+	    attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
+				     OMP_CLAUSE_NOTINBRANCH);
+	  else if (strcmp (TREE_STRING_POINTER (id), "inbranch") == 0)
+	    attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
+				     OMP_CLAUSE_INBRANCH);
+	  else
+	    {
+	      error ("only %<inbranch%> and %<notinbranch%> flags are "
+		     "allowed for %<__simd__%> attribute");
+	      *no_add_attrs = true;
+	      return NULL_TREE;
+	    }
 	}
+
+      DECL_ATTRIBUTES (*node)
+	= tree_cons (t, build_tree_list (NULL_TREE, attr),
+		     DECL_ATTRIBUTES (*node));
     }
   else
     {
@@ -2553,8 +2628,15 @@
 		       int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_PURE_P (*node) = 1;
-  /* ??? TODO: Support types.  */
+    {
+      tree type = TREE_TYPE (*node);
+      if (VOID_TYPE_P (TREE_TYPE (type)))
+	warning (OPT_Wattributes, "%qE attribute on function "
+		 "returning %<void%>", name);
+
+      DECL_PURE_P (*node) = 1;
+      /* ??? TODO: Support types.  */
+    }
   else
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -3064,8 +3146,13 @@
 
       if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
 	{
+	  /* Accept the attribute on arrays and pointers to all three
+	     narrow character types.  */
 	  tree eltype = TREE_TYPE (type);
-	  if (eltype == char_type_node)
+	  eltype = TYPE_MAIN_VARIANT (eltype);
+	  if (eltype == char_type_node
+	      || eltype == signed_char_type_node
+	      || eltype == unsigned_char_type_node)
 	    return NULL_TREE;
 	}