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
This commit is contained in:
Mark Mitchell 1999-12-17 07:40:08 +00:00 committed by Mark Mitchell
parent fc69382254
commit db4283a074
7 changed files with 242 additions and 88 deletions

View File

@ -1,3 +1,27 @@
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.

View File

@ -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));

View File

@ -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;
tree args;
tree fcall;
int saved_flag_access_control;
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);
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

View File

@ -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},

View File

@ -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

View File

@ -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" },

View File

@ -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