c++, mingw, v2: Fix up types of dtor hooks to __cxa_{,thread_}atexit/__cxa_throw on mingw ia32 [PR114968]
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Testing passed
|
Commit Message
On Thu, May 09, 2024 at 01:05:59PM -0400, Jason Merrill wrote:
> I think I'd rather pass ob_parm to start_cleanup_fn, where it can also
> replace the flag_use_cxa_atexit check in that function.
Good idea, changed in the following patch.
> > @@ -9998,7 +10004,8 @@ register_dtor_fn (tree decl)
> > {
> > /* We must convert CLEANUP to the type that "__cxa_atexit"
> > expects. */
> > - cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
> > + cleanup = build_nop (ob_parm ? get_cxa_atexit_fn_ptr_type ()
> > + : get_atexit_fn_ptr_type (), cleanup);
>
> If we're (now) using the correct type to build the cleanup fn, this
> conversion should be unnecessary.
This is the use_dtor case, where cleanup will have METHOD_TYPE, so
I think we need to cast. But, we can cast always to
get_cxa_atexit_fn_ptr_type () type, because this is in use_dtor guarded code
and use_dtor is ob_parm && CLASS_TYPE_P (type), so when use_dtor is true,
ob_parm is also true.
Ok for trunk if it passes another bootstrap/regtest?
2024-05-09 Jakub Jelinek <jakub@redhat.com>
PR target/114968
gcc/
* target.def (use_atexit_for_cxa_atexit): Remove spurious space
from comment.
(adjust_cdtor_callabi_fntype): New cxx target hook.
* targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
* targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
function.
* doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
* doc/tm.texi: Regenerate.
* config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
function.
(TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
gcc/cp/
* cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
comments.
(get_cxa_atexit_fn_ptr_type): Declare.
* decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
build type for atexit argument.
(get_cxa_atexit_fn_ptr_type): New function.
(get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
get_atexit_fn_ptr_type when using __cxa_atexit.
(get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
rather than get_atexit_fn_ptr_type.
(start_cleanup_fn): Add ob_parm argument, call
get_cxa_atexit_fn_ptr_type or get_atexit_fn_ptr_type depending
on it and create PARM_DECL also based on that argument.
(register_dtor_fn): Adjust start_cleanup_fn caller, use
get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
for use_dtor casts.
* except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().
Jakub
Comments
On 5/9/24 14:46, Jakub Jelinek wrote:
> On Thu, May 09, 2024 at 01:05:59PM -0400, Jason Merrill wrote:
>> I think I'd rather pass ob_parm to start_cleanup_fn, where it can also
>> replace the flag_use_cxa_atexit check in that function.
>
> Good idea, changed in the following patch.
>
>>> @@ -9998,7 +10004,8 @@ register_dtor_fn (tree decl)
>>> {
>>> /* We must convert CLEANUP to the type that "__cxa_atexit"
>>> expects. */
>>> - cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
>>> + cleanup = build_nop (ob_parm ? get_cxa_atexit_fn_ptr_type ()
>>> + : get_atexit_fn_ptr_type (), cleanup);
>>
>> If we're (now) using the correct type to build the cleanup fn, this
>> conversion should be unnecessary.
>
> This is the use_dtor case, where cleanup will have METHOD_TYPE, so
> I think we need to cast. But, we can cast always to
> get_cxa_atexit_fn_ptr_type () type, because this is in use_dtor guarded code
> and use_dtor is ob_parm && CLASS_TYPE_P (type), so when use_dtor is true,
> ob_parm is also true.
>
> Ok for trunk if it passes another bootstrap/regtest?
OK.
> 2024-05-09 Jakub Jelinek <jakub@redhat.com>
>
> PR target/114968
> gcc/
> * target.def (use_atexit_for_cxa_atexit): Remove spurious space
> from comment.
> (adjust_cdtor_callabi_fntype): New cxx target hook.
> * targhooks.h (default_cxx_adjust_cdtor_callabi_fntype): Declare.
> * targhooks.cc (default_cxx_adjust_cdtor_callabi_fntype): New
> function.
> * doc/tm.texi.in (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Add.
> * doc/tm.texi: Regenerate.
> * config/i386/i386.cc (ix86_cxx_adjust_cdtor_callabi_fntype): New
> function.
> (TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE): Redefine.
> gcc/cp/
> * cp-tree.h (atexit_fn_ptr_type_node, cleanup_type): Adjust macro
> comments.
> (get_cxa_atexit_fn_ptr_type): Declare.
> * decl.cc (get_atexit_fn_ptr_type): Adjust function comment, only
> build type for atexit argument.
> (get_cxa_atexit_fn_ptr_type): New function.
> (get_atexit_node): Call get_cxa_atexit_fn_ptr_type rather than
> get_atexit_fn_ptr_type when using __cxa_atexit.
> (get_thread_atexit_node): Call get_cxa_atexit_fn_ptr_type
> rather than get_atexit_fn_ptr_type.
> (start_cleanup_fn): Add ob_parm argument, call
> get_cxa_atexit_fn_ptr_type or get_atexit_fn_ptr_type depending
> on it and create PARM_DECL also based on that argument.
> (register_dtor_fn): Adjust start_cleanup_fn caller, use
> get_cxa_atexit_fn_ptr_type rather than get_atexit_fn_ptr_type
> for use_dtor casts.
> * except.cc (build_throw): Use get_cxa_atexit_fn_ptr_type ().
>
> --- gcc/target.def.jj 2024-05-09 10:30:54.926503473 +0200
> +++ gcc/target.def 2024-05-09 20:27:16.294780780 +0200
> @@ -6498,7 +6498,7 @@ is in effect. The default is to return
> hook_bool_void_false)
>
> /* Returns true if target may use atexit in the same manner as
> - __cxa_atexit to register static destructors. */
> + __cxa_atexit to register static destructors. */
> DEFHOOK
> (use_atexit_for_cxa_atexit,
> "This hook returns true if the target @code{atexit} function can be used\n\
> @@ -6509,6 +6509,17 @@ unloaded. The default is to return false
> bool, (void),
> hook_bool_void_false)
>
> +/* Returns modified FUNCTION_TYPE for cdtor callabi. */
> +DEFHOOK
> +(adjust_cdtor_callabi_fntype,
> + "This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments\n\
> +to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}\n\
> +function pointers. ABIs like mingw32 require special attributes to be added\n\
> +to function types pointed to by arguments of these functions.\n\
> +The default is to return the passed argument unmodified.",
> + tree, (tree fntype),
> + default_cxx_adjust_cdtor_callabi_fntype)
> +
> DEFHOOK
> (adjust_class_at_definition,
> "@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just\n\
> --- gcc/targhooks.h.jj 2024-05-09 10:30:54.941503269 +0200
> +++ gcc/targhooks.h 2024-05-09 20:27:16.315780505 +0200
> @@ -65,6 +65,7 @@ extern machine_mode default_mode_for_suf
>
> extern tree default_cxx_guard_type (void);
> extern tree default_cxx_get_cookie_size (tree);
> +extern tree default_cxx_adjust_cdtor_callabi_fntype (tree);
>
> extern bool hook_pass_by_reference_must_pass_in_stack
> (cumulative_args_t, const function_arg_info &);
> --- gcc/targhooks.cc.jj 2024-05-09 10:30:54.927503459 +0200
> +++ gcc/targhooks.cc 2024-05-09 20:27:16.338780204 +0200
> @@ -329,6 +329,14 @@ default_cxx_get_cookie_size (tree type)
> return cookie_size;
> }
>
> +/* Returns modified FUNCTION_TYPE for cdtor callabi. */
> +
> +tree
> +default_cxx_adjust_cdtor_callabi_fntype (tree fntype)
> +{
> + return fntype;
> +}
> +
> /* Return true if a parameter must be passed by reference. This version
> of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK. */
>
> --- gcc/doc/tm.texi.in.jj 2024-05-09 10:30:54.897503866 +0200
> +++ gcc/doc/tm.texi.in 2024-05-09 20:27:16.355779981 +0200
> @@ -7223,6 +7223,8 @@ floating-point support; they are not inc
>
> @hook TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT
>
> +@hook TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
> +
> @hook TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
>
> @hook TARGET_CXX_DECL_MANGLING_CONTEXT
> --- gcc/doc/tm.texi.jj 2024-05-09 10:30:54.862504342 +0200
> +++ gcc/doc/tm.texi 2024-05-09 20:27:16.368779810 +0200
> @@ -11117,6 +11117,14 @@ shared libraries are run in the correct
> unloaded. The default is to return false.
> @end deftypefn
>
> +@deftypefn {Target Hook} tree TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE (tree @var{fntype})
> +This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments
> +to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}
> +function pointers. ABIs like mingw32 require special attributes to be added
> +to function types pointed to by arguments of these functions.
> +The default is to return the passed argument unmodified.
> +@end deftypefn
> +
> @deftypefn {Target Hook} void TARGET_CXX_ADJUST_CLASS_AT_DEFINITION (tree @var{type})
> @var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just
> been defined. Use this hook to make adjustments to the class (eg, tweak
> --- gcc/config/i386/i386.cc.jj 2024-05-09 10:30:58.508454809 +0200
> +++ gcc/config/i386/i386.cc 2024-05-09 20:27:16.392779496 +0200
> @@ -25800,6 +25800,20 @@ ix86_bitint_type_info (int n, struct bit
> return true;
> }
>
> +/* Returns modified FUNCTION_TYPE for cdtor callabi. */
> +tree
> +ix86_cxx_adjust_cdtor_callabi_fntype (tree fntype)
> +{
> + if (TARGET_64BIT
> + || TARGET_RTD
> + || ix86_function_type_abi (fntype) != MS_ABI)
> + return fntype;
> + /* For 32-bit MS ABI add thiscall attribute. */
> + tree attribs = tree_cons (get_identifier ("thiscall"), NULL_TREE,
> + TYPE_ATTRIBUTES (fntype));
> + return build_type_attribute_variant (fntype, attribs);
> +}
> +
> /* Implement PUSH_ROUNDING. On 386, we have pushw instruction that
> decrements by exactly 2 no matter what the position was, there is no pushb.
>
> @@ -26411,6 +26425,8 @@ static const scoped_attribute_specs *con
> #define TARGET_C_EXCESS_PRECISION ix86_get_excess_precision
> #undef TARGET_C_BITINT_TYPE_INFO
> #define TARGET_C_BITINT_TYPE_INFO ix86_bitint_type_info
> +#undef TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
> +#define TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE ix86_cxx_adjust_cdtor_callabi_fntype
> #undef TARGET_PROMOTE_PROTOTYPES
> #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
> #undef TARGET_PUSH_ARGUMENT
> --- gcc/cp/cp-tree.h.jj 2024-05-09 20:26:12.619615230 +0200
> +++ gcc/cp/cp-tree.h 2024-05-09 20:27:16.395779457 +0200
> @@ -368,8 +368,7 @@ extern GTY(()) tree cp_global_trees[CPTI
> #define throw_fn cp_global_trees[CPTI_THROW_FN]
> #define rethrow_fn cp_global_trees[CPTI_RETHROW_FN]
>
> -/* The type of the function-pointer argument to "__cxa_atexit" (or
> - "std::atexit", if "__cxa_atexit" is not being used). */
> +/* The type of the function-pointer argument to "std::atexit". */
> #define atexit_fn_ptr_type_node cp_global_trees[CPTI_ATEXIT_FN_PTR_TYPE]
>
> /* A pointer to `std::atexit'. */
> @@ -384,7 +383,8 @@ extern GTY(()) tree cp_global_trees[CPTI
> /* The declaration of the dynamic_cast runtime. */
> #define dynamic_cast_node cp_global_trees[CPTI_DCAST]
>
> -/* The type of a destructor. */
> +/* The type of a destructor, passed to __cxa_atexit, __cxa_thread_atexit
> + or __cxa_throw. */
> #define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE]
>
> /* The type of the vtt parameter passed to subobject constructors and
> @@ -7067,6 +7067,7 @@ extern tree check_default_argument (tre
> extern int wrapup_namespace_globals ();
> extern tree create_implicit_typedef (tree, tree);
> extern int local_variable_p (const_tree);
> +extern tree get_cxa_atexit_fn_ptr_type ();
> extern tree register_dtor_fn (tree);
> extern tmpl_spec_kind current_tmpl_spec_kind (int);
> extern tree cxx_builtin_function (tree decl);
> --- gcc/cp/decl.cc.jj 2024-05-09 20:26:12.670614561 +0200
> +++ gcc/cp/decl.cc 2024-05-09 20:34:08.556378168 +0200
> @@ -93,7 +93,7 @@ static void record_key_method_defined (t
> static tree create_array_type_for_decl (tree, tree, tree, location_t);
> static tree get_atexit_node (void);
> static tree get_dso_handle_node (void);
> -static tree start_cleanup_fn (void);
> +static tree start_cleanup_fn (bool);
> static void end_cleanup_fn (void);
> static tree cp_make_fname_decl (location_t, tree, int);
> static void initialize_predefined_identifiers (void);
> @@ -9678,34 +9678,39 @@ declare_global_var (tree name, tree type
> return decl;
> }
>
> -/* Returns the type for the argument to "__cxa_atexit" (or "atexit",
> - if "__cxa_atexit" is not being used) corresponding to the function
> +/* Returns the type for the argument to "atexit" corresponding to the function
> to be called when the program exits. */
>
> static tree
> -get_atexit_fn_ptr_type (void)
> +get_atexit_fn_ptr_type ()
> {
> - tree fn_type;
> -
> if (!atexit_fn_ptr_type_node)
> {
> - tree arg_type;
> - if (flag_use_cxa_atexit
> - && !targetm.cxx.use_atexit_for_cxa_atexit ())
> - /* The parameter to "__cxa_atexit" is "void (*)(void *)". */
> - arg_type = ptr_type_node;
> - else
> - /* The parameter to "atexit" is "void (*)(void)". */
> - arg_type = NULL_TREE;
> -
> - fn_type = build_function_type_list (void_type_node,
> - arg_type, NULL_TREE);
> + tree fn_type = build_function_type_list (void_type_node, NULL_TREE);
> atexit_fn_ptr_type_node = build_pointer_type (fn_type);
> }
>
> return atexit_fn_ptr_type_node;
> }
>
> +/* Returns the type for the argument to "__cxa_atexit", "__cxa_thread_atexit"
> + or "__cxa_throw" corresponding to the destructor to be called when the
> + program exits. */
> +
> +tree
> +get_cxa_atexit_fn_ptr_type ()
> +{
> + if (!cleanup_type)
> + {
> + tree fntype = build_function_type_list (void_type_node,
> + ptr_type_node, NULL_TREE);
> + fntype = targetm.cxx.adjust_cdtor_callabi_fntype (fntype);
> + cleanup_type = build_pointer_type (fntype);
> + }
> +
> + return cleanup_type;
> +}
> +
> /* Returns a pointer to the `atexit' function. Note that if
> FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
> `__cxa_atexit' function specified in the IA64 C++ ABI. */
> @@ -9736,7 +9741,7 @@ get_atexit_node (void)
> use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
> /* First, build the pointer-to-function type for the first
> argument. */
> - fn_ptr_type = get_atexit_fn_ptr_type ();
> + fn_ptr_type = get_cxa_atexit_fn_ptr_type ();
> /* Then, build the rest of the argument types. */
> argtype2 = ptr_type_node;
> if (use_aeabi_atexit)
> @@ -9819,7 +9824,7 @@ get_thread_atexit_node (void)
>
> int __cxa_thread_atexit (void (*)(void *), void *, void *) */
> tree fn_type = build_function_type_list (integer_type_node,
> - get_atexit_fn_ptr_type (),
> + get_cxa_atexit_fn_ptr_type (),
> ptr_type_node, ptr_type_node,
> NULL_TREE);
>
> @@ -9861,12 +9866,13 @@ get_dso_handle_node (void)
> }
>
> /* Begin a new function with internal linkage whose job will be simply
> - to destroy some particular variable. */
> + to destroy some particular variable. OB_PARM is true if object pointer
> + is passed to the cleanup function, otherwise no argument is passed. */
>
> static GTY(()) int start_cleanup_cnt;
>
> static tree
> -start_cleanup_fn (void)
> +start_cleanup_fn (bool ob_parm)
> {
> char name[32];
>
> @@ -9877,8 +9883,9 @@ start_cleanup_fn (void)
>
> /* Build the name of the function. */
> sprintf (name, "__tcf_%d", start_cleanup_cnt++);
> + tree fntype = TREE_TYPE (ob_parm ? get_cxa_atexit_fn_ptr_type ()
> + : get_atexit_fn_ptr_type ());
> /* Build the function declaration. */
> - tree fntype = TREE_TYPE (get_atexit_fn_ptr_type ());
> tree fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
> DECL_CONTEXT (fndecl) = FROB_CONTEXT (current_namespace);
> /* It's a function with internal linkage, generated by the
> @@ -9891,7 +9898,7 @@ start_cleanup_fn (void)
> emissions this way. */
> DECL_DECLARED_INLINE_P (fndecl) = 1;
> DECL_INTERFACE_KNOWN (fndecl) = 1;
> - if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit ())
> + if (ob_parm)
> {
> /* Build the parameter. */
> tree parmdecl = cp_build_parm_decl (fndecl, NULL_TREE, ptr_type_node);
> @@ -9968,8 +9975,8 @@ register_dtor_fn (tree decl)
> build_cleanup (decl);
>
> /* Now start the function. */
> - cleanup = start_cleanup_fn ();
> -
> + cleanup = start_cleanup_fn (ob_parm);
> +
> /* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer
> to the original function, rather than the anonymous one. That
> will make the back end think that nested functions are in use,
> @@ -9998,7 +10005,7 @@ register_dtor_fn (tree decl)
> {
> /* We must convert CLEANUP to the type that "__cxa_atexit"
> expects. */
> - cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
> + cleanup = build_nop (get_cxa_atexit_fn_ptr_type (), cleanup);
> /* "__cxa_atexit" will pass the address of DECL to the
> cleanup function. */
> mark_used (decl);
> --- gcc/cp/except.cc.jj 2024-05-09 10:30:54.821504899 +0200
> +++ gcc/cp/except.cc 2024-05-09 20:27:16.412779234 +0200
> @@ -645,11 +645,7 @@ build_throw (location_t loc, tree exp, t
>
> /* The CLEANUP_TYPE is the internal type of a destructor. */
> if (!cleanup_type)
> - {
> - tree tmp = build_function_type_list (void_type_node,
> - ptr_type_node, NULL_TREE);
> - cleanup_type = build_pointer_type (tmp);
> - }
> + cleanup_type = get_cxa_atexit_fn_ptr_type ();
>
> if (!throw_fn)
> {
>
>
> Jakub
>
@@ -6498,7 +6498,7 @@ is in effect. The default is to return
hook_bool_void_false)
/* Returns true if target may use atexit in the same manner as
- __cxa_atexit to register static destructors. */
+ __cxa_atexit to register static destructors. */
DEFHOOK
(use_atexit_for_cxa_atexit,
"This hook returns true if the target @code{atexit} function can be used\n\
@@ -6509,6 +6509,17 @@ unloaded. The default is to return false
bool, (void),
hook_bool_void_false)
+/* Returns modified FUNCTION_TYPE for cdtor callabi. */
+DEFHOOK
+(adjust_cdtor_callabi_fntype,
+ "This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments\n\
+to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}\n\
+function pointers. ABIs like mingw32 require special attributes to be added\n\
+to function types pointed to by arguments of these functions.\n\
+The default is to return the passed argument unmodified.",
+ tree, (tree fntype),
+ default_cxx_adjust_cdtor_callabi_fntype)
+
DEFHOOK
(adjust_class_at_definition,
"@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just\n\
@@ -65,6 +65,7 @@ extern machine_mode default_mode_for_suf
extern tree default_cxx_guard_type (void);
extern tree default_cxx_get_cookie_size (tree);
+extern tree default_cxx_adjust_cdtor_callabi_fntype (tree);
extern bool hook_pass_by_reference_must_pass_in_stack
(cumulative_args_t, const function_arg_info &);
@@ -329,6 +329,14 @@ default_cxx_get_cookie_size (tree type)
return cookie_size;
}
+/* Returns modified FUNCTION_TYPE for cdtor callabi. */
+
+tree
+default_cxx_adjust_cdtor_callabi_fntype (tree fntype)
+{
+ return fntype;
+}
+
/* Return true if a parameter must be passed by reference. This version
of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK. */
@@ -7223,6 +7223,8 @@ floating-point support; they are not inc
@hook TARGET_CXX_USE_ATEXIT_FOR_CXA_ATEXIT
+@hook TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
+
@hook TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
@hook TARGET_CXX_DECL_MANGLING_CONTEXT
@@ -11117,6 +11117,14 @@ shared libraries are run in the correct
unloaded. The default is to return false.
@end deftypefn
+@deftypefn {Target Hook} tree TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE (tree @var{fntype})
+This hook returns a possibly modified @code{FUNCTION_TYPE} for arguments
+to @code{__cxa_atexit}, @code{__cxa_thread_atexit} or @code{__cxa_throw}
+function pointers. ABIs like mingw32 require special attributes to be added
+to function types pointed to by arguments of these functions.
+The default is to return the passed argument unmodified.
+@end deftypefn
+
@deftypefn {Target Hook} void TARGET_CXX_ADJUST_CLASS_AT_DEFINITION (tree @var{type})
@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just
been defined. Use this hook to make adjustments to the class (eg, tweak
@@ -25800,6 +25800,20 @@ ix86_bitint_type_info (int n, struct bit
return true;
}
+/* Returns modified FUNCTION_TYPE for cdtor callabi. */
+tree
+ix86_cxx_adjust_cdtor_callabi_fntype (tree fntype)
+{
+ if (TARGET_64BIT
+ || TARGET_RTD
+ || ix86_function_type_abi (fntype) != MS_ABI)
+ return fntype;
+ /* For 32-bit MS ABI add thiscall attribute. */
+ tree attribs = tree_cons (get_identifier ("thiscall"), NULL_TREE,
+ TYPE_ATTRIBUTES (fntype));
+ return build_type_attribute_variant (fntype, attribs);
+}
+
/* Implement PUSH_ROUNDING. On 386, we have pushw instruction that
decrements by exactly 2 no matter what the position was, there is no pushb.
@@ -26411,6 +26425,8 @@ static const scoped_attribute_specs *con
#define TARGET_C_EXCESS_PRECISION ix86_get_excess_precision
#undef TARGET_C_BITINT_TYPE_INFO
#define TARGET_C_BITINT_TYPE_INFO ix86_bitint_type_info
+#undef TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE
+#define TARGET_CXX_ADJUST_CDTOR_CALLABI_FNTYPE ix86_cxx_adjust_cdtor_callabi_fntype
#undef TARGET_PROMOTE_PROTOTYPES
#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
#undef TARGET_PUSH_ARGUMENT
@@ -368,8 +368,7 @@ extern GTY(()) tree cp_global_trees[CPTI
#define throw_fn cp_global_trees[CPTI_THROW_FN]
#define rethrow_fn cp_global_trees[CPTI_RETHROW_FN]
-/* The type of the function-pointer argument to "__cxa_atexit" (or
- "std::atexit", if "__cxa_atexit" is not being used). */
+/* The type of the function-pointer argument to "std::atexit". */
#define atexit_fn_ptr_type_node cp_global_trees[CPTI_ATEXIT_FN_PTR_TYPE]
/* A pointer to `std::atexit'. */
@@ -384,7 +383,8 @@ extern GTY(()) tree cp_global_trees[CPTI
/* The declaration of the dynamic_cast runtime. */
#define dynamic_cast_node cp_global_trees[CPTI_DCAST]
-/* The type of a destructor. */
+/* The type of a destructor, passed to __cxa_atexit, __cxa_thread_atexit
+ or __cxa_throw. */
#define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE]
/* The type of the vtt parameter passed to subobject constructors and
@@ -7067,6 +7067,7 @@ extern tree check_default_argument (tre
extern int wrapup_namespace_globals ();
extern tree create_implicit_typedef (tree, tree);
extern int local_variable_p (const_tree);
+extern tree get_cxa_atexit_fn_ptr_type ();
extern tree register_dtor_fn (tree);
extern tmpl_spec_kind current_tmpl_spec_kind (int);
extern tree cxx_builtin_function (tree decl);
@@ -93,7 +93,7 @@ static void record_key_method_defined (t
static tree create_array_type_for_decl (tree, tree, tree, location_t);
static tree get_atexit_node (void);
static tree get_dso_handle_node (void);
-static tree start_cleanup_fn (void);
+static tree start_cleanup_fn (bool);
static void end_cleanup_fn (void);
static tree cp_make_fname_decl (location_t, tree, int);
static void initialize_predefined_identifiers (void);
@@ -9678,34 +9678,39 @@ declare_global_var (tree name, tree type
return decl;
}
-/* Returns the type for the argument to "__cxa_atexit" (or "atexit",
- if "__cxa_atexit" is not being used) corresponding to the function
+/* Returns the type for the argument to "atexit" corresponding to the function
to be called when the program exits. */
static tree
-get_atexit_fn_ptr_type (void)
+get_atexit_fn_ptr_type ()
{
- tree fn_type;
-
if (!atexit_fn_ptr_type_node)
{
- tree arg_type;
- if (flag_use_cxa_atexit
- && !targetm.cxx.use_atexit_for_cxa_atexit ())
- /* The parameter to "__cxa_atexit" is "void (*)(void *)". */
- arg_type = ptr_type_node;
- else
- /* The parameter to "atexit" is "void (*)(void)". */
- arg_type = NULL_TREE;
-
- fn_type = build_function_type_list (void_type_node,
- arg_type, NULL_TREE);
+ tree fn_type = build_function_type_list (void_type_node, NULL_TREE);
atexit_fn_ptr_type_node = build_pointer_type (fn_type);
}
return atexit_fn_ptr_type_node;
}
+/* Returns the type for the argument to "__cxa_atexit", "__cxa_thread_atexit"
+ or "__cxa_throw" corresponding to the destructor to be called when the
+ program exits. */
+
+tree
+get_cxa_atexit_fn_ptr_type ()
+{
+ if (!cleanup_type)
+ {
+ tree fntype = build_function_type_list (void_type_node,
+ ptr_type_node, NULL_TREE);
+ fntype = targetm.cxx.adjust_cdtor_callabi_fntype (fntype);
+ cleanup_type = build_pointer_type (fntype);
+ }
+
+ return cleanup_type;
+}
+
/* Returns a pointer to the `atexit' function. Note that if
FLAG_USE_CXA_ATEXIT is nonzero, then this will actually be the new
`__cxa_atexit' function specified in the IA64 C++ ABI. */
@@ -9736,7 +9741,7 @@ get_atexit_node (void)
use_aeabi_atexit = targetm.cxx.use_aeabi_atexit ();
/* First, build the pointer-to-function type for the first
argument. */
- fn_ptr_type = get_atexit_fn_ptr_type ();
+ fn_ptr_type = get_cxa_atexit_fn_ptr_type ();
/* Then, build the rest of the argument types. */
argtype2 = ptr_type_node;
if (use_aeabi_atexit)
@@ -9819,7 +9824,7 @@ get_thread_atexit_node (void)
int __cxa_thread_atexit (void (*)(void *), void *, void *) */
tree fn_type = build_function_type_list (integer_type_node,
- get_atexit_fn_ptr_type (),
+ get_cxa_atexit_fn_ptr_type (),
ptr_type_node, ptr_type_node,
NULL_TREE);
@@ -9861,12 +9866,13 @@ get_dso_handle_node (void)
}
/* Begin a new function with internal linkage whose job will be simply
- to destroy some particular variable. */
+ to destroy some particular variable. OB_PARM is true if object pointer
+ is passed to the cleanup function, otherwise no argument is passed. */
static GTY(()) int start_cleanup_cnt;
static tree
-start_cleanup_fn (void)
+start_cleanup_fn (bool ob_parm)
{
char name[32];
@@ -9877,8 +9883,9 @@ start_cleanup_fn (void)
/* Build the name of the function. */
sprintf (name, "__tcf_%d", start_cleanup_cnt++);
+ tree fntype = TREE_TYPE (ob_parm ? get_cxa_atexit_fn_ptr_type ()
+ : get_atexit_fn_ptr_type ());
/* Build the function declaration. */
- tree fntype = TREE_TYPE (get_atexit_fn_ptr_type ());
tree fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
DECL_CONTEXT (fndecl) = FROB_CONTEXT (current_namespace);
/* It's a function with internal linkage, generated by the
@@ -9891,7 +9898,7 @@ start_cleanup_fn (void)
emissions this way. */
DECL_DECLARED_INLINE_P (fndecl) = 1;
DECL_INTERFACE_KNOWN (fndecl) = 1;
- if (flag_use_cxa_atexit && !targetm.cxx.use_atexit_for_cxa_atexit ())
+ if (ob_parm)
{
/* Build the parameter. */
tree parmdecl = cp_build_parm_decl (fndecl, NULL_TREE, ptr_type_node);
@@ -9968,8 +9975,8 @@ register_dtor_fn (tree decl)
build_cleanup (decl);
/* Now start the function. */
- cleanup = start_cleanup_fn ();
-
+ cleanup = start_cleanup_fn (ob_parm);
+
/* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer
to the original function, rather than the anonymous one. That
will make the back end think that nested functions are in use,
@@ -9998,7 +10005,7 @@ register_dtor_fn (tree decl)
{
/* We must convert CLEANUP to the type that "__cxa_atexit"
expects. */
- cleanup = build_nop (get_atexit_fn_ptr_type (), cleanup);
+ cleanup = build_nop (get_cxa_atexit_fn_ptr_type (), cleanup);
/* "__cxa_atexit" will pass the address of DECL to the
cleanup function. */
mark_used (decl);
@@ -645,11 +645,7 @@ build_throw (location_t loc, tree exp, t
/* The CLEANUP_TYPE is the internal type of a destructor. */
if (!cleanup_type)
- {
- tree tmp = build_function_type_list (void_type_node,
- ptr_type_node, NULL_TREE);
- cleanup_type = build_pointer_type (tmp);
- }
+ cleanup_type = get_cxa_atexit_fn_ptr_type ();
if (!throw_fn)
{