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:
parent
fc69382254
commit
db4283a074
@ -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.
|
||||
|
@ -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));
|
||||
|
||||
|
228
gcc/cp/decl.c
228
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;
|
||||
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
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
|
@ -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" },
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user