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