__attribute__ ((constructor))

From-SVN: r8747
This commit is contained in:
Jason Merrill 1995-01-14 01:09:01 +00:00
parent 34cd1bd74c
commit 2c5f4139a9
7 changed files with 117 additions and 9 deletions

View File

@ -271,6 +271,32 @@ decl_attributes (decl, attributes)
else
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)
{
#ifdef VALID_MACHINE_ATTRIBUTE

View File

@ -400,6 +400,10 @@ static int keep_next_if_subblocks;
static struct binding_level *label_level_chain;
/* Functions called automatically at the beginning and end of execution. */
tree static_ctors, static_dtors;
/* Forward declarations. */
static tree grokparms (), grokdeclarator ();
@ -1744,6 +1748,12 @@ duplicate_decls (newdecl, olddecl)
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
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 ();
}
/* If cannot merge, then use the new type and qualifiers,
@ -6749,6 +6759,25 @@ finish_function (nested)
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)
{
/* Let the error reporting routines know that we're outside a

View File

@ -127,3 +127,53 @@ GNU_xref_end ()
{
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
}

View File

@ -258,9 +258,7 @@ extern void yyprint ();
program: /* empty */
{ if (pedantic)
pedwarn ("ANSI C forbids an empty source file");
ifobjc
objc_finish ();
end ifobjc
finish_file ();
}
| extdefs
{
@ -268,9 +266,7 @@ end ifobjc
get us back to the global binding level. */
while (! global_bindings_p ())
poplevel (0, 0, 0);
ifobjc
objc_finish ();
end ifobjc
finish_file ();
}
;

View File

@ -537,7 +537,7 @@ objc_fatal ()
}
void
objc_finish ()
finish_file ()
{
if (doing_objc_thang)
finish_objc (); /* Objective-C finalization */

View File

@ -22,7 +22,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* used by yyparse */
void objc_finish PROTO((void));
void finish_file PROTO((void));
tree start_class PROTO((enum tree_code, tree, tree, tree));
tree continue_class PROTO((tree));
void finish_class PROTO((tree));

View File

@ -943,6 +943,11 @@ struct tree_type
alternative would be passed. */
#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. */
#define DECL_LANG_FLAG_0(NODE) ((NODE)->decl.lang_flag_0)
#define DECL_LANG_FLAG_1(NODE) ((NODE)->decl.lang_flag_1)
@ -979,7 +984,9 @@ struct tree_decl
unsigned common_flag : 1;
unsigned defer_output : 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_1 : 1;