summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authormerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>1995-01-14 01:09:01 +0000
committermerrill <merrill@138bc75d-0d04-0410-961f-82ee72b054a4>1995-01-14 01:09:01 +0000
commitaa5ec236cf31ff5a76ef0440a181a8036a849017 (patch)
tree9af815a0feebeea5b32fc5a358886913ab5dd30e /gcc
parentf377226ecebe6b5c95b73996ae121bc78c8bff01 (diff)
downloadgcc-aa5ec236cf31ff5a76ef0440a181a8036a849017.tar.gz
__attribute__ ((constructor))
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@8747 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-common.c26
-rw-r--r--gcc/c-decl.c29
-rw-r--r--gcc/c-lang.c50
-rw-r--r--gcc/c-parse.in8
-rw-r--r--gcc/objc/objc-act.c2
-rw-r--r--gcc/objc/objc-act.h2
-rw-r--r--gcc/tree.h9
7 files changed, 117 insertions, 9 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index e4207569c96..8b3b887f8fd 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 02ffa998fcb..8243ad7457b 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 8b46b3c10cb..d429bea0979 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 fc1bab613fa..0862d30a065 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 937384d615a..96be32f0b91 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 e6765d9168d..1a88fcaa3c7 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 997edba8715..3b5fde31eab 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;