Commit 2c5f4139 by Jason Merrill

__attribute__ ((constructor))

From-SVN: r8747
parent 34cd1bd7
...@@ -271,6 +271,32 @@ decl_attributes (decl, attributes) ...@@ -271,6 +271,32 @@ decl_attributes (decl, attributes)
else else
warning_with_decl (decl, "`transparent_union' attribute ignored"); warning_with_decl (decl, "`transparent_union' attribute ignored");
} }
else if (TREE_VALUE (a) == get_identifier ("constructor")
|| TREE_VALUE (a) == get_identifier ("__constructor__"))
{
if (TREE_CODE (decl) != FUNCTION_DECL
|| TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
|| decl_function_context (decl))
{
error_with_decl (decl,
"`constructor' attribute meaningless for non-function %s");
continue;
}
DECL_STATIC_CONSTRUCTOR (decl) = 1;
}
else if (TREE_VALUE (a) == get_identifier ("destructor")
|| TREE_VALUE (a) == get_identifier ("__destructor__"))
{
if (TREE_CODE (decl) != FUNCTION_DECL
|| TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
|| decl_function_context (decl))
{
error_with_decl (decl,
"`destructor' attribute meaningless for non-function %s");
continue;
}
DECL_STATIC_DESTRUCTOR (decl) = 1;
}
else if (TREE_CODE (name) != TREE_LIST) else if (TREE_CODE (name) != TREE_LIST)
{ {
#ifdef VALID_MACHINE_ATTRIBUTE #ifdef VALID_MACHINE_ATTRIBUTE
......
...@@ -400,6 +400,10 @@ static int keep_next_if_subblocks; ...@@ -400,6 +400,10 @@ static int keep_next_if_subblocks;
static struct binding_level *label_level_chain; static struct binding_level *label_level_chain;
/* Functions called automatically at the beginning and end of execution. */
tree static_ctors, static_dtors;
/* Forward declarations. */ /* Forward declarations. */
static tree grokparms (), grokdeclarator (); static tree grokparms (), grokdeclarator ();
...@@ -1744,6 +1748,12 @@ duplicate_decls (newdecl, olddecl) ...@@ -1744,6 +1748,12 @@ duplicate_decls (newdecl, olddecl)
if (DECL_SECTION_NAME (newdecl) == NULL_TREE) if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
}
pop_obstacks (); pop_obstacks ();
} }
/* If cannot merge, then use the new type and qualifiers, /* If cannot merge, then use the new type and qualifiers,
...@@ -6749,6 +6759,25 @@ finish_function (nested) ...@@ -6749,6 +6759,25 @@ finish_function (nested)
DECL_ARGUMENTS (fndecl) = 0; DECL_ARGUMENTS (fndecl) = 0;
} }
if (DECL_STATIC_CONSTRUCTOR (fndecl))
{
#ifndef ASM_OUTPUT_CONSTRUCTOR
if (! flag_gnu_linker)
static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
else
#endif
assemble_constructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
}
if (DECL_STATIC_DESTRUCTOR (fndecl))
{
#ifndef ASM_OUTPUT_DESTRUCTOR
if (! flag_gnu_linker)
static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
else
#endif
assemble_destructor (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
}
if (! nested) if (! nested)
{ {
/* Let the error reporting routines know that we're outside a /* Let the error reporting routines know that we're outside a
......
...@@ -127,3 +127,53 @@ GNU_xref_end () ...@@ -127,3 +127,53 @@ GNU_xref_end ()
{ {
fatal ("GCC does not yet support XREF"); fatal ("GCC does not yet support XREF");
} }
/* called at end of parsing, but before end-of-file processing. */
void
finish_file ()
{
extern tree static_ctors, static_dtors;
extern tree get_file_function_name ();
extern tree build_function_call PROTO((tree, tree));
tree void_list_node = build_tree_list (NULL_TREE, void_type_node);
#ifndef ASM_OUTPUT_CONSTRUCTOR
if (static_ctors)
{
tree fnname = get_file_function_name ('I');
start_function (void_list_node,
build_parse_node (CALL_EXPR, fnname, void_list_node,
NULL_TREE),
0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls ();
for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
NULL_TREE));
finish_function (0);
assemble_constructor (IDENTIFIER_POINTER (fnname));
}
#endif
#ifndef ASM_OUTPUT_DESTRUCTOR
if (static_dtors)
{
tree fnname = get_file_function_name ('D');
start_function (void_list_node,
build_parse_node (CALL_EXPR, fnname, void_list_node,
NULL_TREE),
0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls ();
for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
NULL_TREE));
finish_function (0);
assemble_destructor (IDENTIFIER_POINTER (fnname));
}
#endif
}
...@@ -258,9 +258,7 @@ extern void yyprint (); ...@@ -258,9 +258,7 @@ extern void yyprint ();
program: /* empty */ program: /* empty */
{ if (pedantic) { if (pedantic)
pedwarn ("ANSI C forbids an empty source file"); pedwarn ("ANSI C forbids an empty source file");
ifobjc finish_file ();
objc_finish ();
end ifobjc
} }
| extdefs | extdefs
{ {
...@@ -268,9 +266,7 @@ end ifobjc ...@@ -268,9 +266,7 @@ end ifobjc
get us back to the global binding level. */ get us back to the global binding level. */
while (! global_bindings_p ()) while (! global_bindings_p ())
poplevel (0, 0, 0); poplevel (0, 0, 0);
ifobjc finish_file ();
objc_finish ();
end ifobjc
} }
; ;
......
...@@ -537,7 +537,7 @@ objc_fatal () ...@@ -537,7 +537,7 @@ objc_fatal ()
} }
void void
objc_finish () finish_file ()
{ {
if (doing_objc_thang) if (doing_objc_thang)
finish_objc (); /* Objective-C finalization */ finish_objc (); /* Objective-C finalization */
......
...@@ -22,7 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -22,7 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* used by yyparse */ /* used by yyparse */
void objc_finish PROTO((void)); void finish_file PROTO((void));
tree start_class PROTO((enum tree_code, tree, tree, tree)); tree start_class PROTO((enum tree_code, tree, tree, tree));
tree continue_class PROTO((tree)); tree continue_class PROTO((tree));
void finish_class PROTO((tree)); void finish_class PROTO((tree));
......
...@@ -943,6 +943,11 @@ struct tree_type ...@@ -943,6 +943,11 @@ struct tree_type
alternative would be passed. */ alternative would be passed. */
#define DECL_TRANSPARENT_UNION(NODE) ((NODE)->decl.transparent_union) #define DECL_TRANSPARENT_UNION(NODE) ((NODE)->decl.transparent_union)
/* Used in FUNCTION_DECLs to indicate that they should be run automatically
at the beginning or end of execution. */
#define DECL_STATIC_CONSTRUCTOR(NODE) ((NODE)->decl.static_ctor_flag)
#define DECL_STATIC_DESTRUCTOR(NODE) ((NODE)->decl.static_dtor_flag)
/* Additional flags for language-specific uses. */ /* Additional flags for language-specific uses. */
#define DECL_LANG_FLAG_0(NODE) ((NODE)->decl.lang_flag_0) #define DECL_LANG_FLAG_0(NODE) ((NODE)->decl.lang_flag_0)
#define DECL_LANG_FLAG_1(NODE) ((NODE)->decl.lang_flag_1) #define DECL_LANG_FLAG_1(NODE) ((NODE)->decl.lang_flag_1)
...@@ -979,7 +984,9 @@ struct tree_decl ...@@ -979,7 +984,9 @@ struct tree_decl
unsigned common_flag : 1; unsigned common_flag : 1;
unsigned defer_output : 1; unsigned defer_output : 1;
unsigned transparent_union : 1; unsigned transparent_union : 1;
/* room for four more */ unsigned static_ctor_flag : 1;
unsigned static_dtor_flag : 1;
/* room for two more */
unsigned lang_flag_0 : 1; unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1; unsigned lang_flag_1 : 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment