From 2c5f4139a91db294f1ab34da9bbae585d8c65eb2 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 14 Jan 1995 01:09:01 +0000 Subject: [PATCH] __attribute__ ((constructor)) From-SVN: r8747 --- gcc/c-common.c | 26 ++++++++++++++++++++++++++ gcc/c-decl.c | 29 +++++++++++++++++++++++++++++ gcc/c-lang.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ gcc/c-parse.in | 8 ++------ gcc/objc/objc-act.c | 2 +- gcc/objc/objc-act.h | 2 +- gcc/tree.h | 9 ++++++++- 7 files changed, 117 insertions(+), 9 deletions(-) diff --git a/gcc/c-common.c b/gcc/c-common.c index e420756..8b3b887 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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 diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 02ffa99..8243ad7 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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 diff --git a/gcc/c-lang.c b/gcc/c-lang.c index 8b46b3c..d429bea 100644 --- a/gcc/c-lang.c +++ b/gcc/c-lang.c @@ -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 +} diff --git a/gcc/c-parse.in b/gcc/c-parse.in index fc1bab6..0862d30 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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 (); } ; diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 937384d..96be32f 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -537,7 +537,7 @@ objc_fatal () } void -objc_finish () +finish_file () { if (doing_objc_thang) finish_objc (); /* Objective-C finalization */ diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index e6765d9..1a88fca 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -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)); diff --git a/gcc/tree.h b/gcc/tree.h index 997edba..3b5fde3 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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; -- 2.7.4