static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
static tree handle_section_attribute (tree *, tree, tree, int, bool *);
+static tree handle_special_var_sec_attribute (tree *, tree, tree, int, bool *);
static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree,
int, bool *);
-static tree handle_noinit_attribute (tree *, tree, tree, int, bool *);
static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
ATTR_EXCL (NULL, false, false, false)
};
-static const struct attribute_spec::exclusions attr_noinit_exclusions[] =
+/* Exclusions that apply to attributes that put declarations in specific
+ sections. */
+static const struct attribute_spec::exclusions attr_section_exclusions[] =
{
ATTR_EXCL ("noinit", true, true, true),
+ ATTR_EXCL ("persistent", true, true, true),
ATTR_EXCL ("section", true, true, true),
ATTR_EXCL (NULL, false, false, false),
};
{ "mode", 1, 1, false, true, false, false,
handle_mode_attribute, NULL },
{ "section", 1, 1, true, false, false, false,
- handle_section_attribute, attr_noinit_exclusions },
+ handle_section_attribute, attr_section_exclusions },
{ "aligned", 0, 1, false, false, false, false,
handle_aligned_attribute,
attr_aligned_exclusions },
{ "copy", 1, 1, false, false, false, false,
handle_copy_attribute, NULL },
{ "noinit", 0, 0, true, false, false, false,
- handle_noinit_attribute, attr_noinit_exclusions },
+ handle_special_var_sec_attribute, attr_section_exclusions },
+ { "persistent", 0, 0, true, false, false, false,
+ handle_special_var_sec_attribute, attr_section_exclusions },
{ "access", 1, 3, false, true, true, false,
handle_access_attribute, NULL },
/* Attributes used by Objective-C. */
return NULL_TREE;
}
-/* Handle a "noinit" attribute; arguments as in struct
- attribute_spec.handler. Check whether the attribute is allowed
- here and add the attribute to the variable decl tree or otherwise
- issue a diagnostic. This function checks NODE is of the expected
- type and issues diagnostics otherwise using NAME. If it is not of
- the expected type *NO_ADD_ATTRS will be set to true. */
-
+/* Handle a "noinit" or "persistent" attribute; arguments as in
+ struct attribute_spec.handler.
+ This generic handler is used for "special variable sections" that allow the
+ section name to be set using a dedicated attribute. Additional validation
+ is performed for the specific properties of the section corresponding to the
+ attribute.
+ The ".noinit" section *is not* loaded by the program loader, and is not
+ initialized by the runtime startup code.
+ The ".persistent" section *is* loaded by the program loader, but is not
+ initialized by the runtime startup code. */
static tree
-handle_noinit_attribute (tree * node,
- tree name,
- tree args,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
+handle_special_var_sec_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
{
- const char *message = NULL;
+ tree decl = *node;
tree res = NULL_TREE;
- gcc_assert (DECL_P (*node));
- gcc_assert (args == NULL);
+ /* First perform generic validation common to "noinit" and "persistent"
+ attributes. */
+ if (!targetm_common.have_named_sections)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "section attributes are not supported for this target");
+ goto fail;
+ }
- if (TREE_CODE (*node) != VAR_DECL)
- message = G_("%qE attribute only applies to variables");
+ if (!VAR_P (decl))
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute not set on a variable",
+ name);
+ goto fail;
+ }
- /* Check that it's possible for the variable to have a section. */
- else if ((TREE_STATIC (*node) || DECL_EXTERNAL (*node) || in_lto_p)
- && DECL_SECTION_NAME (*node))
- message = G_("%qE attribute cannot be applied to variables "
- "with specific sections");
+ if (VAR_P (decl)
+ && current_function_decl != NULL_TREE
+ && !TREE_STATIC (decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "%qE attribute cannot be specified for local variables",
+ name);
+ goto fail;
+ }
- else if (!targetm.have_switchable_bss_sections)
- message = G_("%qE attribute is specific to ELF targets");
+ if (VAR_P (decl)
+ && !targetm.have_tls && targetm.emutls.tmpl_section
+ && DECL_THREAD_LOCAL_P (decl))
+ {
+ error ("section of %q+D cannot be overridden", decl);
+ goto fail;
+ }
- if (message)
+ if (!targetm.have_switchable_bss_sections)
{
- warning (OPT_Wattributes, message, name);
- *no_add_attrs = true;
+ error ("%qE attribute is specific to ELF targets", name);
+ goto fail;
}
- else
+
+ if (TREE_READONLY (decl))
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute set on const variable",
+ name);
+ goto fail;
+ }
+
+ /* Now validate noinit/persistent individually. */
+ if (strcmp (IDENTIFIER_POINTER (name), "noinit") == 0)
+ {
+ if (DECL_INITIAL (decl))
+ {
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute set on initialized variable",
+ name);
+ goto fail;
+ }
+ /* If this var is thought to be common, then change this. "noinit"
+ variables must be placed in an explicit ".noinit" section. */
+ DECL_COMMON (decl) = 0;
+ }
+ else if (strcmp (IDENTIFIER_POINTER (name), "persistent") == 0)
{
- res = targetm.handle_generic_attribute (node, name, args, flags,
- no_add_attrs);
- /* If the back end confirms the attribute can be added then continue onto
- final processing. */
- if (!(*no_add_attrs))
+ if (DECL_COMMON (decl) || DECL_INITIAL (decl) == NULL_TREE)
{
- /* If this var is thought to be common, then change this. Common
- variables are assigned to sections before the backend has a
- chance to process them. Do this only if the attribute is
- valid. */
- if (DECL_COMMON (*node))
- DECL_COMMON (*node) = 0;
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
+ "ignoring %qE attribute set on uninitialized variable",
+ name);
+ goto fail;
}
}
+ else
+ gcc_unreachable ();
+
+ res = targetm.handle_generic_attribute (node, name, args, flags,
+ no_add_attrs);
+
+ /* If the back end confirms the attribute can be added then continue onto
+ final processing. */
+ if (!(*no_add_attrs))
+ return res;
+fail:
+ *no_add_attrs = true;
return res;
}
-
/* Handle a "noplt" attribute; arguments as in
struct attribute_spec.handler. */