aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-12-17 07:40:08 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-12-17 07:40:08 +0000
commitdb4283a0747a8598d17fa8d2ca94846354831d0d (patch)
treebaf33a58f78965a95318fce634a68a64f07a3cc4
parentfc69382254fcf45ced69a604adea5b6123c3c1c8 (diff)
downloadgcc-db4283a0747a8598d17fa8d2ca94846354831d0d.zip
gcc-db4283a0747a8598d17fa8d2ca94846354831d0d.tar.gz
gcc-db4283a0747a8598d17fa8d2ca94846354831d0d.tar.bz2
cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE.
* cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE. (dso_handle_node): New macro. (flag_use_cxa_atexit): New variable. (declare_global_var): New function. (start_anon_func): Remove declaration. (end_anon_func): Likewise. * decl.c (get_atexit_node): New function, split out from destroy_local_static. Handle flag_use_cxa_atexit. (get_dso_handle_node): Likewise. (start_cleanup_fn): Renamed from start_anon_func. Moved here from except.c. Handle flag_use_cxa_atexit. (end_cleanup_fn): Renamed from end_anon_func. Moved here from except.c. (declare_global_var): New variable. (destroy_local_static): Handle flag_use_cxa_atexit. * decl2.c (flag_use_cxa_atexit): New variable. (lang_f_options): Likewise. * except.c (start_anon_func): Remove. (end_anon_func): Liekwise. * lang-options.h: Add -fuse-cxa-atexit and -fno-use-cxa-atexit. * rtti.c (get_tinfo_var): Use declare_global_var. From-SVN: r30990
-rw-r--r--gcc/cp/ChangeLog24
-rw-r--r--gcc/cp/cp-tree.h14
-rw-r--r--gcc/cp/decl.c228
-rw-r--r--gcc/cp/decl2.c6
-rw-r--r--gcc/cp/except.c43
-rw-r--r--gcc/cp/lang-options.h2
-rw-r--r--gcc/cp/rtti.c13
7 files changed, 242 insertions, 88 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2fe8bd3..73cfd67 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,29 @@
1999-12-16 Mark Mitchell <mark@codesourcery.com>
+ * cp-tree.h (cp_tree_index): Add CPTI_DSO_HANDLE.
+ (dso_handle_node): New macro.
+ (flag_use_cxa_atexit): New variable.
+ (declare_global_var): New function.
+ (start_anon_func): Remove declaration.
+ (end_anon_func): Likewise.
+ * decl.c (get_atexit_node): New function, split out from
+ destroy_local_static. Handle flag_use_cxa_atexit.
+ (get_dso_handle_node): Likewise.
+ (start_cleanup_fn): Renamed from start_anon_func. Moved here from
+ except.c. Handle flag_use_cxa_atexit.
+ (end_cleanup_fn): Renamed from end_anon_func. Moved here from
+ except.c.
+ (declare_global_var): New variable.
+ (destroy_local_static): Handle flag_use_cxa_atexit.
+ * decl2.c (flag_use_cxa_atexit): New variable.
+ (lang_f_options): Likewise.
+ * except.c (start_anon_func): Remove.
+ (end_anon_func): Liekwise.
+ * lang-options.h: Add -fuse-cxa-atexit and -fno-use-cxa-atexit.
+ * rtti.c (get_tinfo_var): Use declare_global_var.
+
+1999-12-16 Mark Mitchell <mark@codesourcery.com>
+
* class.c (check_field_decls): Don't return a value.
(avoid_overlap): Moved here from tree.c.
(build_base_fields): Likewise.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0fefc7d..6b22ee9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -483,6 +483,7 @@ enum cp_tree_index
CPTI_MINUS_ONE,
CPTI_TERMINATE,
CPTI_ATEXIT,
+ CPTI_DSO_HANDLE,
CPTI_MAX
};
@@ -574,9 +575,12 @@ extern tree cp_global_trees[CPTI_MAX];
/* The declaration for `std::terminate'. */
#define terminate_node cp_global_trees[CPTI_TERMINATE]
-/* The declaration for `std::atexit'. */
+/* A pointer to `std::atexit'. */
#define atexit_node cp_global_trees[CPTI_ATEXIT]
+/* A pointer to `__dso_handle'. */
+#define dso_handle_node cp_global_trees[CPTI_DSO_HANDLE]
+
/* The type of a destructor. */
#define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE]
@@ -3128,6 +3132,11 @@ extern int flag_weak;
extern int flag_new_abi;
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+ destructors for local statics and global objects. */
+
+extern int flag_use_cxa_atexit;
+
/* Nonzero to not ignore namespace std. */
extern int flag_honor_std;
@@ -3564,6 +3573,7 @@ extern tree build_target_expr_with_type PROTO((tree, tree));
extern void make_rtl_for_local_static PROTO((tree));
extern int local_variable_p PROTO((tree));
extern int nonstatic_local_decl_p PROTO((tree));
+extern tree declare_global_var PROTO((tree, tree));
/* in decl2.c */
extern void init_decl2 PROTO((void));
@@ -3659,8 +3669,6 @@ extern void expand_builtin_throw PROTO((void));
extern tree expand_start_eh_spec PROTO((void));
extern void expand_end_eh_spec PROTO((tree, tree));
extern void expand_exception_blocks PROTO((void));
-extern tree start_anon_func PROTO((void));
-extern void end_anon_func PROTO((void));
extern tree build_throw PROTO((tree));
extern void mark_all_runtime_matches PROTO((void));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index b08f4db..6b240f9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -175,6 +175,10 @@ static void destroy_local_var PROTO((tree));
static void finish_constructor_body PROTO((void));
static void finish_destructor_body PROTO((void));
static tree create_array_type_for_decl PROTO((tree, tree, tree));
+static tree get_atexit_node PROTO((void));
+static tree get_dso_handle_node PROTO((void));
+static tree start_cleanup_fn PROTO((void));
+static void end_cleanup_fn PROTO((void));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -7856,6 +7860,184 @@ finish_decl (decl, init, asmspec_tree)
cp_finish_decl (decl, init, asmspec_tree, 0);
}
+/* Returns a declaration for a VAR_DECL as if:
+
+ extern "C" TYPE NAME;
+
+ had been seen. Used to create compiler-generated global
+ variables. */
+
+tree
+declare_global_var (name, type)
+ tree name;
+ tree type;
+{
+ tree decl;
+
+ push_to_top_level ();
+ decl = build_decl (VAR_DECL, name, type);
+ TREE_PUBLIC (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ pushdecl (decl);
+ cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+ pop_from_top_level ();
+
+ return decl;
+}
+
+/* Returns a pointer to the `atexit' function. Note that if
+ FLAG_USE_CXA_ATEXIT is non-zero, then this will actually be the new
+ `__cxa_atexit' function specified in the IA64 C++ ABI. */
+
+static tree
+get_atexit_node ()
+{
+ tree atexit_fndecl;
+ tree arg_types;
+ tree fn_type;
+ tree fn_ptr_type;
+ const char *name;
+
+ if (atexit_node)
+ return atexit_node;
+
+ if (flag_use_cxa_atexit)
+ {
+ /* The declaration for `__cxa_atexit' is:
+
+ int __cxa_atexit (void (*)(void *), void *, void *)
+
+ We build up the argument types and then then function type
+ itself. */
+
+ /* First, build the pointer-to-function type for the first
+ argument. */
+ arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ fn_type = build_function_type (void_type_node, arg_types);
+ fn_ptr_type = build_pointer_type (fn_type);
+ /* Then, build the rest of the argument types. */
+ arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
+ arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
+ /* And the final __cxa_atexit type. */
+ fn_type = build_function_type (integer_type_node, arg_types);
+ fn_ptr_type = build_pointer_type (fn_type);
+ name = "__cxa_atexit";
+ }
+ else
+ {
+ /* The declaration for `atexit' is:
+
+ int atexit (void (*)());
+
+ We build up the argument types and then then function type
+ itself. */
+ fn_type = build_function_type (void_type_node, void_list_node);
+ fn_ptr_type = build_pointer_type (fn_type);
+ arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node);
+ /* Build the final atexit type. */
+ fn_type = build_function_type (integer_type_node, arg_types);
+ name = "atexit";
+ }
+
+ /* Now, build the function declaration. */
+ push_lang_context (lang_name_c);
+ atexit_fndecl = define_function (name, fn_type, /*pfn=*/0, NULL_PTR);
+ mark_used (atexit_fndecl);
+ pop_lang_context ();
+ atexit_node = default_conversion (atexit_fndecl);
+
+ return atexit_node;
+}
+
+/* Returns the __dso_handle VAR_DECL. */
+
+static tree
+get_dso_handle_node ()
+{
+ if (dso_handle_node)
+ return dso_handle_node;
+
+ /* Declare the variable. */
+ dso_handle_node = declare_global_var (get_identifier ("__dso_handle"),
+ ptr_type_node);
+
+ return dso_handle_node;
+}
+
+/* Begin a new function with internal linkage whose job will be simply
+ to destroy some particular variable. */
+
+static tree
+start_cleanup_fn ()
+{
+ static int counter = 0;
+ int old_interface_unknown = interface_unknown;
+ char name[32];
+ tree parmtypes;
+ tree fntype;
+ tree fndecl;
+
+ push_to_top_level ();
+
+ /* No need to mangle this. */
+ push_lang_context (lang_name_c);
+
+ interface_unknown = 1;
+
+ /* Build the parameter-types. */
+ parmtypes = void_list_node;
+ /* Functions passed to __cxa_atexit take an additional parameter.
+ We'll just ignore it. After we implement the new calling
+ convention for destructors, we can eliminate the use of
+ additional cleanup functions entirely in the -fnew-abi case. */
+ if (flag_use_cxa_atexit)
+ parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
+ /* Build the function type itself. */
+ fntype = build_function_type (void_type_node, parmtypes);
+ /* Build the name of the function. */
+ sprintf (name, "__tcf_%d", counter++);
+ /* Build the function declaration. */
+ fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
+ /* It's a function with internal linkage, generated by the
+ compiler. */
+ TREE_PUBLIC (fndecl) = 0;
+ DECL_ARTIFICIAL (fndecl) = 1;
+ /* Build the parameter. */
+ if (flag_use_cxa_atexit)
+ {
+ tree parmdecl;
+
+ parmdecl = build_decl (PARM_DECL, NULL_TREE, ptr_type_node);
+ DECL_CONTEXT (parmdecl) = fndecl;
+ DECL_ARG_TYPE (parmdecl) = ptr_type_node;
+ TREE_USED (parmdecl) = 1;
+ DECL_ARGUMENTS (fndecl) = parmdecl;
+ }
+
+ start_function (/*specs=*/NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED);
+ do_pushlevel ();
+
+ interface_unknown = old_interface_unknown;
+
+ pop_lang_context ();
+
+ return current_function_decl;
+}
+
+/* Finish the cleanup function begun by start_cleanup_fn. */
+
+static void
+end_cleanup_fn ()
+{
+ do_poplevel ();
+
+ expand_body (finish_function (lineno, 0));
+
+ pop_from_top_level ();
+}
+
/* Generate code to handle the destruction of the function-scoped
static variable DECL. */
@@ -7863,40 +8045,20 @@ static void
destroy_local_static (decl)
tree decl;
{
- tree cleanup, fcall;
+ tree cleanup;
tree compound_stmt;
- int saved_flag_access_control;
+ tree args;
+ tree fcall;
- if (atexit_node == 0)
- {
- tree atexit_fndecl, PFV, pfvlist;
-
- PFV = build_pointer_type (build_function_type
- (void_type_node, void_list_node));
-
- pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
+ int saved_flag_access_control;
- push_lang_context (lang_name_c);
- /* Note that we do not call pushdecl for this function;
- there's no reason that this declaration should be
- accessible to anyone. */
- atexit_fndecl
- = define_function ("atexit",
- build_function_type (void_type_node,
- pfvlist),
- /*pfn=*/0, NULL_PTR);
- mark_used (atexit_fndecl);
- atexit_node = default_conversion (atexit_fndecl);
- pop_lang_context ();
- }
-
/* Call build_cleanup before we enter the anonymous function so that
any access checks will be done relative to the current scope,
rather than the scope of the anonymous function. */
build_cleanup (decl);
/* Now start the function. */
- cleanup = start_anon_func ();
+ cleanup = start_cleanup_fn ();
/* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer
to the original function, rather than the anonymous one. That
@@ -7911,16 +8073,20 @@ destroy_local_static (decl)
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
finish_expr_stmt (fcall);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
- end_anon_func ();
+ end_cleanup_fn ();
/* Call atexit with the cleanup function. */
mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
- fcall = build_function_call (atexit_node,
- tree_cons (NULL_TREE,
- cleanup,
- NULL_TREE));
- finish_expr_stmt (fcall);
+ if (flag_use_cxa_atexit)
+ {
+ args = tree_cons (NULL_TREE, get_dso_handle_node (), NULL_TREE);
+ args = tree_cons (NULL_TREE, null_pointer_node, args);
+ args = tree_cons (NULL_TREE, cleanup, args);
+ }
+ else
+ args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
+ finish_expr_stmt (build_function_call (get_atexit_node (), args));
}
void
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 937a164..7ed8ab0 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -441,6 +441,11 @@ int flag_weak = 1;
int flag_new_abi;
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+ destructors for local statics and global objects. */
+
+int flag_use_cxa_atexit;
+
/* Nonzero to not ignore namespace std. */
int flag_honor_std;
@@ -535,6 +540,7 @@ lang_f_options[] =
{"squangle", &flag_do_squangling, 1},
{"stats", &flag_detailed_statistics, 1},
{"strict-prototype", &flag_strict_prototype, 1},
+ {"use-cxa-atexit", &flag_use_cxa_atexit, 1},
{"vtable-gc", &flag_vtable_gc, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
{"weak", &flag_weak, 1},
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 7e41d2e..1dd167c 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -681,49 +681,6 @@ expand_exception_blocks ()
}
}
-tree
-start_anon_func ()
-{
- static int counter = 0;
- int old_interface_unknown = interface_unknown;
- char name[32];
- tree params;
- tree t;
-
- push_to_top_level ();
-
- /* No need to mangle this. */
- push_lang_context (lang_name_c);
-
- interface_unknown = 1;
-
- params = void_list_node;
- /* tcf stands for throw clean function. */
- sprintf (name, "__tcf_%d", counter++);
- t = make_call_declarator (get_identifier (name), params, NULL_TREE,
- NULL_TREE);
- start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
- void_list_node),
- t, NULL_TREE, SF_DEFAULT);
- do_pushlevel ();
-
- interface_unknown = old_interface_unknown;
-
- pop_lang_context ();
-
- return current_function_decl;
-}
-
-void
-end_anon_func ()
-{
- do_poplevel ();
-
- expand_body (finish_function (lineno, 0));
-
- pop_from_top_level ();
-}
-
/* Return a pointer to a buffer for an exception object of type TYPE. */
static tree
diff --git a/gcc/cp/lang-options.h b/gcc/cp/lang-options.h
index 4b743c0..779cbcd 100644
--- a/gcc/cp/lang-options.h
+++ b/gcc/cp/lang-options.h
@@ -98,6 +98,8 @@ DEFINE_LANG_NAME ("C++")
{ "-ftemplate-depth-", "Specify maximum template instantiation depth"},
{ "-fthis-is-variable", "Make 'this' not be type '* const'" },
{ "-fno-this-is-variable", "" },
+ { "-fuse-cxa-atexit", "Use __cxa_atexit to register destructors." },
+ { "-fno-use-cxa-atexit", "" },
{ "-fvtable-gc", "Discard unused virtual functions" },
{ "-fno-vtable-gc", "" },
{ "-fvtable-thunks", "Implement vtables using thunks" },
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 6776d11..5c8da91 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -308,7 +308,7 @@ get_tinfo_var (type)
tree type;
{
tree tname = build_overload_with_type (get_identifier ("__ti"), type);
- tree tdecl, arrtype;
+ tree arrtype;
int size;
if (IDENTIFIER_GLOBAL_VALUE (tname))
@@ -342,16 +342,7 @@ get_tinfo_var (type)
(unsigned_char_type_node,
build_index_type (size_int (size / BITS_PER_UNIT - 1)));
- tdecl = build_decl (VAR_DECL, tname, arrtype);
- TREE_PUBLIC (tdecl) = 1;
- DECL_EXTERNAL (tdecl) = 1;
- DECL_ARTIFICIAL (tdecl) = 1;
- push_to_top_level ();
- pushdecl (tdecl);
- cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0);
- pop_from_top_level ();
-
- return tdecl;
+ return declare_global_var (tname, arrtype);
}
/* Returns the decl for a function which will return a type_info node for