Generalized init_priority attribute
Richard Henderson
rth@redhat.com
Sun Nov 28 22:01:00 GMT 2004
On Thu, Nov 25, 2004 at 10:54:45AM +1300, Danny Smith wrote:
> void my_ctor (void) __attribute__ ((constructor,
> init_priority(MAX_INIT_PRIORITY)));
>
> gets me:
>
> error: can only use 'init_priority' attribute on file-scope definitions
> of objects of class type
Here is generalized support for init_priority in conjunction with
the constructor and destructor attributes. I don't recall if you
are trying to fix regressions or not, and so don't know if this is
appropriate for mainline at this time.
r~
* c-common.c (handle_init_priority_attribute): New.
(c_common_attribute_table): Add init_priority.
(handle_destructor_attribute): Fix quoting.
* c-decl.c (c_expand_body): Look up priority of cdtors.
* tree.h (DECL_INIT_PRIORITY): Move from cp/cp-tree.h.
* doc/extend.texi (Function Attributes): Document init_priority
in relation to the C++ variable attribute.
cp/
* cp-tree.h (DECL_INIT_PRIORITY): Move to tree.h.
* tree.c (cxx_attribute_table): Remove init_priority.
(handle_init_priority_attribute): Remove.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.588
diff -u -p -r1.588 c-common.c
--- c-common.c 25 Nov 2004 17:11:17 -0000 1.588
+++ c-common.c 28 Nov 2004 21:44:01 -0000
@@ -533,6 +533,7 @@ static tree handle_transparent_union_att
int, bool *);
static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
+static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
static tree handle_section_attribute (tree *, tree, tree, int, bool *);
static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
@@ -601,6 +602,8 @@ const struct attribute_spec c_common_att
handle_constructor_attribute },
{ "destructor", 0, 0, true, false, false,
handle_destructor_attribute },
+ { "init_priority", 1, 1, true, false, false,
+ handle_init_priority_attribute },
{ "mode", 1, 1, false, true, false,
handle_mode_attribute },
{ "section", 1, 1, true, false, false,
@@ -4183,13 +4186,92 @@ handle_destructor_attribute (tree *node,
}
else
{
- warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+ warning ("%qE attribute ignored", name);
*no_add_attrs = true;
}
return NULL_TREE;
}
+/* Handle an "init_priority" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+handle_init_priority_attribute (tree* node,
+ tree name,
+ tree args,
+ int flags ATTRIBUTE_UNUSED ,
+ bool* no_add_attrs)
+{
+ tree initp_expr = TREE_VALUE (args);
+ tree decl = *node;
+ tree type = TREE_TYPE (decl);
+ int pri;
+
+ STRIP_NOPS (initp_expr);
+ *no_add_attrs = true;
+
+ if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
+ {
+ error ("requested init_priority is not an integer constant");
+ return NULL_TREE;
+ }
+
+ pri = TREE_INT_CST_LOW (initp_expr);
+ if (pri > MAX_INIT_PRIORITY || pri <= 0)
+ {
+ error ("requested init_priority is out of range");
+ return NULL_TREE;
+ }
+
+ /* Check for init_priorities that are reserved for language and
+ runtime support implementations.*/
+ if (pri <= MAX_RESERVED_INIT_PRIORITY)
+ warning ("requested init_priority is reserved for internal use");
+
+ if (!SUPPORTS_INIT_PRIORITY)
+ {
+ error ("%qE attribute is not supported on this platform", name);
+ return NULL_TREE;
+ }
+
+ /* Accept the attribute on functions, which presumably will be marked
+ with __attribute__ constructor or destructor as well. We'll pull out
+ the priority with lookup_attribute when it's time to use it. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && decl_function_context (decl) == 0)
+ {
+ *no_add_attrs = false;
+ return NULL_TREE;
+ }
+
+ /* For C++, we also allow priorities on file-scope objects. */
+ if (c_dialect_cxx ())
+ {
+ type = strip_array_types (type);
+ if (TREE_CODE (decl) == VAR_DECL
+ && TREE_STATIC (decl)
+ && !DECL_EXTERNAL (decl)
+ && (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
+ /* Static objects in functions are initialized the first time
+ control passes through that function. This is not precise
+ enough to pin down an init_priority value, so don't allow it. */
+ && decl_function_context (decl) == NULL)
+ {
+ DECL_INIT_PRIORITY (decl) = pri;
+ return NULL_TREE;
+ }
+
+ error ("can only use %qE attribute on file-scope definitions "
+ "of objects of class type", name);
+ }
+ else
+ warning ("%qE attribute ignored", name);
+
+ return NULL_TREE;
+}
+
/* Handle a "mode" attribute; arguments as in
struct attribute_spec.handler. */
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.611
diff -u -p -r1.611 c-decl.c
--- c-decl.c 19 Nov 2004 19:54:39 -0000 1.611
+++ c-decl.c 28 Nov 2004 21:44:02 -0000
@@ -6371,6 +6371,8 @@ finish_function (void)
void
c_expand_body (tree fndecl)
{
+ tree attr;
+ int pri;
if (!DECL_INITIAL (fndecl)
|| DECL_INITIAL (fndecl) == error_mark_node)
@@ -6378,14 +6380,18 @@ c_expand_body (tree fndecl)
tree_rest_of_compilation (fndecl);
+ attr = lookup_attribute ("init_priority", DECL_ATTRIBUTES (fndecl));
+ if (attr)
+ pri = tree_low_cst (TREE_VALUE (TREE_VALUE (attr)), 0);
+ else
+ pri = DEFAULT_INIT_PRIORITY;
+
if (DECL_STATIC_CONSTRUCTOR (fndecl)
&& targetm.have_ctors_dtors)
- targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
+ targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0), pri);
if (DECL_STATIC_DESTRUCTOR (fndecl)
&& targetm.have_ctors_dtors)
- targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
+ targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0), pri);
}
/* Check the declarations given in a for-loop for satisfying the C99
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.662
diff -u -p -r1.662 tree.h
--- tree.h 27 Nov 2004 17:26:17 -0000 1.662
+++ tree.h 28 Nov 2004 21:44:04 -0000
@@ -1985,6 +1985,11 @@ struct tree_binfo GTY (())
that describes the status of this function. */
#define DECL_STRUCT_FUNCTION(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.u2.f)
+/* In a file-scope VAR_DECL with static storage duration, this is the
+ initialization priority. If this value is zero, the NODE will be
+ initialized at the DEFAULT_INIT_PRIORITY. */
+#define DECL_INIT_PRIORITY(NODE) (VAR_DECL_CHECK (NODE)->decl.u2.i)
+
/* For FUNCTION_DECL, if it is built-in,
this identifies which built-in operation it is. */
#define DECL_FUNCTION_CODE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.u1.f)
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1075
diff -u -p -r1.1075 cp-tree.h
--- cp/cp-tree.h 26 Nov 2004 17:15:37 -0000 1.1075
+++ cp/cp-tree.h 28 Nov 2004 21:44:05 -0000
@@ -2011,11 +2011,6 @@ struct lang_decl GTY(())
&& CP_DECL_CONTEXT (NODE) == global_namespace \
&& DECL_NAME (NODE) == std_identifier)
-/* In a non-local VAR_DECL with static storage duration, this is the
- initialization priority. If this value is zero, the NODE will be
- initialized at the DEFAULT_INIT_PRIORITY. */
-#define DECL_INIT_PRIORITY(NODE) (VAR_DECL_CHECK (NODE)->decl.u2.i)
-
/* In a TREE_LIST concatenating using directives, indicate indirect
directives */
#define TREE_INDIRECT_USING(NODE) (TREE_LIST_CHECK (NODE)->common.lang_flag_0)
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.420
diff -u -p -r1.420 tree.c
--- cp/tree.c 25 Nov 2004 17:11:37 -0000 1.420
+++ cp/tree.c 28 Nov 2004 21:44:05 -0000
@@ -50,7 +50,6 @@ static tree build_local_temp (tree);
static tree handle_java_interface_attribute (tree *, tree, tree, int, bool *);
static tree handle_com_interface_attribute (tree *, tree, tree, int, bool *);
-static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
@@ -1740,7 +1739,6 @@ const struct attribute_spec cxx_attribut
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
{ "com_interface", 0, 0, false, false, false, handle_com_interface_attribute },
- { "init_priority", 1, 1, true, false, false, handle_init_priority_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -1797,79 +1795,6 @@ handle_com_interface_attribute (tree* no
return NULL_TREE;
}
-/* Handle an "init_priority" attribute; arguments as in
- struct attribute_spec.handler. */
-static tree
-handle_init_priority_attribute (tree* node,
- tree name,
- tree args,
- int flags ATTRIBUTE_UNUSED ,
- bool* no_add_attrs)
-{
- tree initp_expr = TREE_VALUE (args);
- tree decl = *node;
- tree type = TREE_TYPE (decl);
- int pri;
-
- STRIP_NOPS (initp_expr);
-
- if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
- {
- error ("requested init_priority is not an integer constant");
- *no_add_attrs = true;
- return NULL_TREE;
- }
-
- pri = TREE_INT_CST_LOW (initp_expr);
-
- type = strip_array_types (type);
-
- if (decl == NULL_TREE
- || TREE_CODE (decl) != VAR_DECL
- || !TREE_STATIC (decl)
- || DECL_EXTERNAL (decl)
- || (TREE_CODE (type) != RECORD_TYPE
- && TREE_CODE (type) != UNION_TYPE)
- /* Static objects in functions are initialized the
- first time control passes through that
- function. This is not precise enough to pin down an
- init_priority value, so don't allow it. */
- || current_function_decl)
- {
- error ("can only use %qE attribute on file-scope definitions "
- "of objects of class type", name);
- *no_add_attrs = true;
- return NULL_TREE;
- }
-
- if (pri > MAX_INIT_PRIORITY || pri <= 0)
- {
- error ("requested init_priority is out of range");
- *no_add_attrs = true;
- return NULL_TREE;
- }
-
- /* Check for init_priorities that are reserved for
- language and runtime support implementations.*/
- if (pri <= MAX_RESERVED_INIT_PRIORITY)
- {
- warning
- ("requested init_priority is reserved for internal use");
- }
-
- if (SUPPORTS_INIT_PRIORITY)
- {
- DECL_INIT_PRIORITY (decl) = pri;
- return NULL_TREE;
- }
- else
- {
- error ("%qE attribute is not supported on this platform", name);
- *no_add_attrs = true;
- return NULL_TREE;
- }
-}
-
/* Return a new TINST_LEVEL for DECL at location locus. */
tree
make_tinst_level (tree decl, location_t locus)
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.234
diff -u -p -r1.234 extend.texi
--- doc/extend.texi 27 Nov 2004 16:45:15 -0000 1.234
+++ doc/extend.texi 28 Nov 2004 21:44:06 -0000
@@ -1840,6 +1840,13 @@ and 64 entries on the H8/300H and H8S) a
You must use GAS and GLD from GNU binutils version 2.7 or later for
this attribute to work correctly.
+@item init_priority (@var{priority})
+@cindex init_priority attribute
+This attribute may be used in conjunction with the @code{constructor} or
+@code{destructor} attributes to set the associated priority, typically in
+order to define the interaction of such function calls with respect to the
+C++ attribute of the same name (@pxref{C++ init_priority}).
+
@item interrupt
@cindex interrupt handler functions
Use this attribute on the ARM, AVR, C4x, M32R/D and Xstormy16 ports to indicate
@@ -9633,10 +9640,10 @@ You must specify @option{-Wno-pmf-conver
Some attributes only make sense for C++ programs.
@table @code
+@anchor{C++ init_priority}
@item init_priority (@var{priority})
@cindex init_priority attribute
-
In Standard C++, objects defined at namespace scope are guaranteed to be
initialized in an order in strict accordance with that of their definitions
@emph{in a given translation unit}. No guarantee is made for initializations
More information about the Gcc-patches
mailing list