This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ patch] Set attributes for C++ runtime library calls
- From: Gabriel Dos Reis <gdr at integrable-solutions dot net>
- To: Jan Hubicka <hubicka at ucw dot cz>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>
- Date: Thu, 22 Aug 2013 09:31:25 -0500
- Subject: Re: [C++ patch] Set attributes for C++ runtime library calls
- References: <20130822131927 dot GA18084 at kam dot mff dot cuni dot cz>
On Thu, Aug 22, 2013 at 8:19 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>
> Hi,
> this patch started as a work to make cxa_pure_virtual as noreturn. This
> is good for middle-end to figure out that it should not care about
> devirtualizing to it and it should devirtualize speculative where there
> is only one variant. I ended up switching the function building
> stuff to use ecf_flags that is handy to set other attributes, too.
>
> I tried to go across all functions build and assign them correct attributes.
> I expecitely listed them all in changelog to make it easier to double
> check: I am not expert on C++ runtime.
>
> I have three questions:
>
> - I tried to track functions that lead to terminate() and not mark them
> as ECF_LEAF. This is because user can set handler. If the handler
> can resonably expect the static vars defined in its unit to be
> in the final form, we can not consider it ECF_LEAF.
> Perhaps there are cases where terminate() is called only for programs
> already after undefined effect?
> - I would like to recall issue if we can make NEW_EXPR annotated with
> MALLOC attribute. Without it, it is basically impossible to track
> any dynamically allocated objects in the middle-end
operator new is replaceable by user program.
> - Is do_end_catch nothrow? It does not seem to be declared so in libsupc++
>
> Bootstrapped/regtested x86_64-linux, OK?
>
> * class.c (build_vtbl_initializer): Make __cxa_deleted_virtual
> ECF_NORETURN
> * cp-tree.h (build_library_fn_ptr, build_cp_library_fn_ptr,
> push_library_fn, push_void_library_fn): Update prototype.
> * decl.c (build_library_fn_1): Remove.
> (push_cp_library_fn, build_cp_library_fn): Update to take ECF flags.
> (cxx_init_decl_processing): Update; global_delete_fndecl is ECF_NOTROW;
> __cxa_pure_virtual is ECF_NORETURN | ECF_NORETURN.
> (build_library_fn_1): Add ecf_flags argument; rename to ...
> (build_library_fn): ... this one.
> (build_cp_library_fn): Take ecf_flags; do not copy NOTHROW flag.
> (build_library_fn_ptr): Take ecf_flags.
> (build_cp_library_fn_ptr): Likewise.
> (push_library_fn): Likewise.
> (push_cp_library_fn): Likewise.
> (push_void_library_fn): Likewise.
> (push_throw_library_fn): All throws are ECF_NORETURN.
> (__cxa_atexit, __cxa_thread_atexit): Add ECF_LEAF | ECF_NOTHROW attributes.
> (expand_static_init): __cxa_guard_acquire, __cxa_guard_release,
> __cxa_guard_abort are ECF_NOTHROW | ECF_LEAF.
> * except.c (init_exception_processing): terminate is
> ECF_NOTHROW | ECF_NORETURN.
> (declare_nothrow_library_fn): Add ecf_flags parameter.
> (__cxa_get_exception_ptr): Is ECF_NOTHROW | ECF_PURE | ECF_LEAF |
> ECF_TM_PURE.
> (do_begin_catch): cxa_begin_catch and _ITM_cxa_begin_catch
> are ECF_NOTHROW.
> (do_end_catch): __cxa_end_catch and _ITM_cxa_end_catch is
> nothing.
> (do_allocate_exception): _cxa_allocate_exception
> and _ITM_cxa_allocate_exception are ECF_NOTHROW | ECF_MALLOC
> (do_free_exception): __cxa_free_exception is
> ECF_NOTHROW | ECF_LEAF.
> * rtti.c (build_dynamic_cast_1): __dynamic_cast
> is ECF_LEAF | ECF_PURE | ECF_NOTHROW.
>
> Index: cp/class.c
> ===================================================================
> *** cp/class.c (revision 201910)
> --- cp/class.c (working copy)
> *************** build_vtbl_initializer (tree binfo,
> *** 8857,8863 ****
> if (!get_global_value_if_present (fn, &fn))
> fn = push_library_fn (fn, (build_function_type_list
> (void_type_node, NULL_TREE)),
> ! NULL_TREE);
> if (!TARGET_VTABLE_USES_DESCRIPTORS)
> init = fold_convert (vfunc_ptr_type_node,
> build_fold_addr_expr (fn));
> --- 8857,8863 ----
> if (!get_global_value_if_present (fn, &fn))
> fn = push_library_fn (fn, (build_function_type_list
> (void_type_node, NULL_TREE)),
> ! NULL_TREE, ECF_NORETURN);
> if (!TARGET_VTABLE_USES_DESCRIPTORS)
> init = fold_convert (vfunc_ptr_type_node,
> build_fold_addr_expr (fn));
> Index: cp/cp-tree.h
> ===================================================================
> *** cp/cp-tree.h (revision 201910)
> --- cp/cp-tree.h (working copy)
> *************** extern void check_goto (tree);
> *** 5173,5182 ****
> extern bool check_omp_return (void);
> extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t);
> extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
> ! extern tree build_library_fn_ptr (const char *, tree);
> ! extern tree build_cp_library_fn_ptr (const char *, tree);
> ! extern tree push_library_fn (tree, tree, tree);
> ! extern tree push_void_library_fn (tree, tree);
> extern tree push_throw_library_fn (tree, tree);
> extern void warn_misplaced_attr_for_class_type (source_location location,
> tree class_type);
> --- 5169,5178 ----
> extern bool check_omp_return (void);
> extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t);
> extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
> ! extern tree build_library_fn_ptr (const char *, tree, int);
> ! extern tree build_cp_library_fn_ptr (const char *, tree, int);
> ! extern tree push_library_fn (tree, tree, tree, int);
> ! extern tree push_void_library_fn (tree, tree, int);
> extern tree push_throw_library_fn (tree, tree);
> extern void warn_misplaced_attr_for_class_type (source_location location,
> tree class_type);
> Index: cp/decl.c
> ===================================================================
> *** cp/decl.c (revision 201910)
> --- cp/decl.c (working copy)
> *************** static tree grokvardecl (tree, tree, con
> *** 75,81 ****
> static int check_static_variable_definition (tree, tree);
> static void record_unknown_type (tree, const char *);
> static tree builtin_function_1 (tree, tree, bool);
> - static tree build_library_fn_1 (tree, enum tree_code, tree);
> static int member_function_or_else (tree, tree, enum overload_flags);
> static void bad_specifiers (tree, enum bad_spec_place, int, int, int, int,
> int);
> --- 75,80 ----
> *************** static tree cp_make_fname_decl (location
> *** 107,114 ****
> static void initialize_predefined_identifiers (void);
> static tree check_special_function_return_type
> (special_function_kind, tree, tree);
> ! static tree push_cp_library_fn (enum tree_code, tree);
> ! static tree build_cp_library_fn (tree, enum tree_code, tree);
> static void store_parm_decls (tree);
> static void initialize_local_var (tree, tree);
> static void expand_static_init (tree, tree);
> --- 106,113 ----
> static void initialize_predefined_identifiers (void);
> static tree check_special_function_return_type
> (special_function_kind, tree, tree);
> ! static tree push_cp_library_fn (enum tree_code, tree, int);
> ! static tree build_cp_library_fn (tree, enum tree_code, tree, int);
> static void store_parm_decls (tree);
> static void initialize_local_var (tree, tree);
> static void expand_static_init (tree, tree);
> *************** cxx_init_decl_processing (void)
> *** 3800,3809 ****
> newtype = build_exception_variant (newtype, new_eh_spec);
> deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
> deltype = build_exception_variant (deltype, empty_except_spec);
> ! push_cp_library_fn (NEW_EXPR, newtype);
> ! push_cp_library_fn (VEC_NEW_EXPR, newtype);
> ! global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
> ! push_cp_library_fn (VEC_DELETE_EXPR, deltype);
>
> nullptr_type_node = make_node (NULLPTR_TYPE);
> TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
> --- 3799,3808 ----
> newtype = build_exception_variant (newtype, new_eh_spec);
> deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
> deltype = build_exception_variant (deltype, empty_except_spec);
> ! push_cp_library_fn (NEW_EXPR, newtype, 0);
> ! push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
> ! global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
> ! push_cp_library_fn (VEC_DELETE_EXPR, deltype);
>
> nullptr_type_node = make_node (NULLPTR_TYPE);
> TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
> *************** cxx_init_decl_processing (void)
> *** 3816,3822 ****
> }
>
> abort_fndecl
> ! = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
>
> /* Perform other language dependent initializations. */
> init_class_processing ();
> --- 3815,3822 ----
> }
>
> abort_fndecl
> ! = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
> ! ECF_NORETURN | ECF_NOTHROW);
>
> /* Perform other language dependent initializations. */
> init_class_processing ();
> *************** cxx_builtin_function_ext_scope (tree dec
> *** 4007,4013 ****
> function. Not called directly. */
>
> static tree
> ! build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
> {
> tree fn = build_lang_decl (FUNCTION_DECL, name, type);
> DECL_EXTERNAL (fn) = 1;
> --- 4007,4014 ----
> function. Not called directly. */
>
> static tree
> ! build_library_fn (tree name, enum tree_code operator_code, tree type,
> ! int ecf_flags)
> {
> tree fn = build_lang_decl (FUNCTION_DECL, name, type);
> DECL_EXTERNAL (fn) = 1;
> *************** build_library_fn_1 (tree name, enum tree
> *** 4019,4046 ****
> external shared object. */
> DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
> DECL_VISIBILITY_SPECIFIED (fn) = 1;
> ! return fn;
> ! }
> !
> ! /* Returns the _DECL for a library function with C linkage.
> ! We assume that such functions never throw; if this is incorrect,
> ! callers should unset TREE_NOTHROW. */
> !
> ! static tree
> ! build_library_fn (tree name, tree type)
> ! {
> ! tree fn = build_library_fn_1 (name, ERROR_MARK, type);
> ! TREE_NOTHROW (fn) = 1;
> return fn;
> }
>
> /* Returns the _DECL for a library function with C++ linkage. */
>
> static tree
> ! build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
> {
> ! tree fn = build_library_fn_1 (name, operator_code, type);
> ! TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
> DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
> SET_DECL_LANGUAGE (fn, lang_cplusplus);
> return fn;
> --- 4020,4036 ----
> external shared object. */
> DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
> DECL_VISIBILITY_SPECIFIED (fn) = 1;
> ! set_call_expr_flags (fn, ecf_flags);
> return fn;
> }
>
> /* Returns the _DECL for a library function with C++ linkage. */
>
> static tree
> ! build_cp_library_fn (tree name, enum tree_code operator_code, tree type,
> ! int ecf_flags)
> {
> ! tree fn = build_library_fn (name, operator_code, type, ecf_flags);
> DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
> SET_DECL_LANGUAGE (fn, lang_cplusplus);
> return fn;
> *************** build_cp_library_fn (tree name, enum tre
> *** 4050,4067 ****
> IDENTIFIER_NODE. */
>
> tree
> ! build_library_fn_ptr (const char* name, tree type)
> {
> ! return build_library_fn (get_identifier (name), type);
> }
>
> /* Like build_cp_library_fn, but takes a C string instead of an
> IDENTIFIER_NODE. */
>
> tree
> ! build_cp_library_fn_ptr (const char* name, tree type)
> {
> ! return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
> }
>
> /* Like build_library_fn, but also pushes the function so that we will
> --- 4040,4058 ----
> IDENTIFIER_NODE. */
>
> tree
> ! build_library_fn_ptr (const char* name, tree type, int ecf_flags)
> {
> ! return build_library_fn (get_identifier (name), ERROR_MARK, type, ecf_flags);
> }
>
> /* Like build_cp_library_fn, but takes a C string instead of an
> IDENTIFIER_NODE. */
>
> tree
> ! build_cp_library_fn_ptr (const char* name, tree type, int ecf_flags)
> {
> ! return build_cp_library_fn (get_identifier (name), ERROR_MARK, type,
> ! ecf_flags);
> }
>
> /* Like build_library_fn, but also pushes the function so that we will
> *************** build_cp_library_fn_ptr (const char* nam
> *** 4069,4082 ****
> may throw exceptions listed in RAISES. */
>
> tree
> ! push_library_fn (tree name, tree type, tree raises)
> {
> tree fn;
>
> if (raises)
> type = build_exception_variant (type, raises);
>
> ! fn = build_library_fn (name, type);
> pushdecl_top_level (fn);
> return fn;
> }
> --- 4060,4073 ----
> may throw exceptions listed in RAISES. */
>
> tree
> ! push_library_fn (tree name, tree type, tree raises, int ecf_flags)
> {
> tree fn;
>
> if (raises)
> type = build_exception_variant (type, raises);
>
> ! fn = build_library_fn (name, ERROR_MARK, type, ecf_flags);
> pushdecl_top_level (fn);
> return fn;
> }
> *************** push_library_fn (tree name, tree type, t
> *** 4085,4095 ****
> will be found by normal lookup. */
>
> static tree
> ! push_cp_library_fn (enum tree_code operator_code, tree type)
> {
> tree fn = build_cp_library_fn (ansi_opname (operator_code),
> operator_code,
> ! type);
> pushdecl (fn);
> if (flag_tm)
> apply_tm_attr (fn, get_identifier ("transaction_safe"));
> --- 4076,4087 ----
> will be found by normal lookup. */
>
> static tree
> ! push_cp_library_fn (enum tree_code operator_code, tree type,
> ! int ecf_flags)
> {
> tree fn = build_cp_library_fn (ansi_opname (operator_code),
> operator_code,
> ! type, ecf_flags);
> pushdecl (fn);
> if (flag_tm)
> apply_tm_attr (fn, get_identifier ("transaction_safe"));
> *************** push_cp_library_fn (enum tree_code opera
> *** 4100,4109 ****
> a FUNCTION_TYPE. */
>
> tree
> ! push_void_library_fn (tree name, tree parmtypes)
> {
> tree type = build_function_type (void_type_node, parmtypes);
> ! return push_library_fn (name, type, NULL_TREE);
> }
>
> /* Like push_library_fn, but also note that this function throws
> --- 4092,4101 ----
> a FUNCTION_TYPE. */
>
> tree
> ! push_void_library_fn (tree name, tree parmtypes, int ecf_flags)
> {
> tree type = build_function_type (void_type_node, parmtypes);
> ! return push_library_fn (name, type, NULL_TREE, ecf_flags);
> }
>
> /* Like push_library_fn, but also note that this function throws
> *************** push_void_library_fn (tree name, tree pa
> *** 4112,4120 ****
> tree
> push_throw_library_fn (tree name, tree type)
> {
> ! tree fn = push_library_fn (name, type, NULL_TREE);
> ! TREE_THIS_VOLATILE (fn) = 1;
> ! TREE_NOTHROW (fn) = 0;
> return fn;
> }
>
> --- 4104,4110 ----
> tree
> push_throw_library_fn (tree name, tree type)
> {
> ! tree fn = push_library_fn (name, type, NULL_TREE, ECF_NORETURN);
> return fn;
> }
>
> *************** get_atexit_node (void)
> *** 6644,6650 ****
>
> /* Now, build the function declaration. */
> push_lang_context (lang_name_c);
> ! atexit_fndecl = build_library_fn_ptr (name, fn_type);
> mark_used (atexit_fndecl);
> pop_lang_context ();
> atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error);
> --- 6634,6640 ----
>
> /* Now, build the function declaration. */
> push_lang_context (lang_name_c);
> ! atexit_fndecl = build_library_fn_ptr (name, fn_type, ECF_LEAF | ECF_NOTHROW);
> mark_used (atexit_fndecl);
> pop_lang_context ();
> atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error);
> *************** get_thread_atexit_node (void)
> *** 6666,6672 ****
> NULL_TREE);
>
> /* Now, build the function declaration. */
> ! tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type);
> return decay_conversion (atexit_fndecl, tf_warning_or_error);
> }
>
> --- 6656,6663 ----
> NULL_TREE);
>
> /* Now, build the function declaration. */
> ! tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type,
> ! ECF_LEAF | ECF_NOTHROW);
> return decay_conversion (atexit_fndecl, tf_warning_or_error);
> }
>
> *************** expand_static_init (tree decl, tree init
> *** 6992,7006 ****
> (acquire_name, build_function_type_list (integer_type_node,
> TREE_TYPE (guard_addr),
> NULL_TREE),
> ! NULL_TREE);
> if (!release_fn || !abort_fn)
> vfntype = build_function_type_list (void_type_node,
> TREE_TYPE (guard_addr),
> NULL_TREE);
> if (!release_fn)
> ! release_fn = push_library_fn (release_name, vfntype, NULL_TREE);
> if (!abort_fn)
> ! abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE);
>
> inner_if_stmt = begin_if_stmt ();
> finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
> --- 6983,6999 ----
> (acquire_name, build_function_type_list (integer_type_node,
> TREE_TYPE (guard_addr),
> NULL_TREE),
> ! NULL_TREE, ECF_NOTHROW | ECF_LEAF);
> if (!release_fn || !abort_fn)
> vfntype = build_function_type_list (void_type_node,
> TREE_TYPE (guard_addr),
> NULL_TREE);
> if (!release_fn)
> ! release_fn = push_library_fn (release_name, vfntype, NULL_TREE,
> ! ECF_NOTHROW | ECF_LEAF);
> if (!abort_fn)
> ! abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE,
> ! ECF_NOTHROW | ECF_LEAF);
>
> inner_if_stmt = begin_if_stmt ();
> finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
> Index: cp/except.c
> ===================================================================
> *** cp/except.c (revision 201910)
> --- cp/except.c (working copy)
> *************** init_exception_processing (void)
> *** 57,63 ****
> /* void std::terminate (); */
> push_namespace (std_identifier);
> tmp = build_function_type_list (void_type_node, NULL_TREE);
> ! terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
> TREE_THIS_VOLATILE (terminate_node) = 1;
> TREE_NOTHROW (terminate_node) = 1;
> pop_namespace ();
> --- 57,64 ----
> /* void std::terminate (); */
> push_namespace (std_identifier);
> tmp = build_function_type_list (void_type_node, NULL_TREE);
> ! terminate_node = build_cp_library_fn_ptr ("terminate", tmp,
> ! ECF_NOTHROW | ECF_NORETURN);
> TREE_THIS_VOLATILE (terminate_node) = 1;
> TREE_NOTHROW (terminate_node) = 1;
> pop_namespace ();
> *************** build_exc_ptr (void)
> *** 149,160 ****
> are consistent with the actual implementations in libsupc++. */
>
> static tree
> ! declare_nothrow_library_fn (tree name, tree return_type, tree parm_type)
> {
> return push_library_fn (name, build_function_type_list (return_type,
> parm_type,
> NULL_TREE),
> ! empty_except_spec);
> }
>
> /* Build up a call to __cxa_get_exception_ptr so that we can build a
> --- 150,162 ----
> are consistent with the actual implementations in libsupc++. */
>
> static tree
> ! declare_library_fn (tree name, tree return_type, tree parm_type, int ecf_flags)
> {
> return push_library_fn (name, build_function_type_list (return_type,
> parm_type,
> NULL_TREE),
> ! empty_except_spec,
> ! ecf_flags);
> }
>
> /* Build up a call to __cxa_get_exception_ptr so that we can build a
> *************** do_get_exception_ptr (void)
> *** 169,178 ****
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void* __cxa_get_exception_ptr (void *) throw(). */
> ! fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
> !
> ! if (flag_tm)
> ! apply_tm_attr (fn, get_identifier ("transaction_pure"));
> }
>
> return cp_build_function_call_nary (fn, tf_warning_or_error,
> --- 171,178 ----
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void* __cxa_get_exception_ptr (void *) throw(). */
> ! fn = declare_library_fn (fn, ptr_type_node, ptr_type_node,
> ! ECF_NOTHROW | ECF_PURE | ECF_LEAF | ECF_TM_PURE);
> }
>
> return cp_build_function_call_nary (fn, tf_warning_or_error,
> *************** do_begin_catch (void)
> *** 191,206 ****
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void* __cxa_begin_catch (void *) throw(). */
> ! fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node);
>
> /* Create its transactional-memory equivalent. */
> if (flag_tm)
> {
> tree fn2 = get_identifier ("_ITM_cxa_begin_catch");
> if (!get_global_value_if_present (fn2, &fn2))
> ! fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
> ! ptr_type_node);
> ! apply_tm_attr (fn2, get_identifier ("transaction_pure"));
> record_tm_replacement (fn, fn2);
> }
> }
> --- 191,205 ----
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void* __cxa_begin_catch (void *) throw(). */
> ! fn = declare_library_fn (fn, ptr_type_node, ptr_type_node, ECF_NOTHROW);
>
> /* Create its transactional-memory equivalent. */
> if (flag_tm)
> {
> tree fn2 = get_identifier ("_ITM_cxa_begin_catch");
> if (!get_global_value_if_present (fn2, &fn2))
> ! fn2 = declare_library_fn (fn2, ptr_type_node,
> ! ptr_type_node, ECF_NOTHROW | ECF_TM_PURE);
> record_tm_replacement (fn, fn2);
> }
> }
> *************** do_end_catch (tree type)
> *** 238,258 ****
> fn = get_identifier ("__cxa_end_catch");
> if (!get_global_value_if_present (fn, &fn))
> {
> ! /* Declare void __cxa_end_catch (). */
> ! fn = push_void_library_fn (fn, void_list_node);
> ! /* This can throw if the destructor for the exception throws. */
> ! TREE_NOTHROW (fn) = 0;
>
> /* Create its transactional-memory equivalent. */
> if (flag_tm)
> {
> tree fn2 = get_identifier ("_ITM_cxa_end_catch");
> if (!get_global_value_if_present (fn2, &fn2))
> ! {
> ! fn2 = push_void_library_fn (fn2, void_list_node);
> ! TREE_NOTHROW (fn2) = 0;
> ! }
> ! apply_tm_attr (fn2, get_identifier ("transaction_pure"));
> record_tm_replacement (fn, fn2);
> }
> }
> --- 237,252 ----
> fn = get_identifier ("__cxa_end_catch");
> if (!get_global_value_if_present (fn, &fn))
> {
> ! /* Declare void __cxa_end_catch ().
> ! This can throw if the destructor for the exception throws. */
> ! fn = push_void_library_fn (fn, void_list_node, 0);
>
> /* Create its transactional-memory equivalent. */
> if (flag_tm)
> {
> tree fn2 = get_identifier ("_ITM_cxa_end_catch");
> if (!get_global_value_if_present (fn2, &fn2))
> ! fn2 = push_void_library_fn (fn2, void_list_node, ECF_TM_PURE);
> record_tm_replacement (fn, fn2);
> }
> }
> *************** do_allocate_exception (tree type)
> *** 631,645 ****
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void *__cxa_allocate_exception(size_t) throw(). */
> ! fn = declare_nothrow_library_fn (fn, ptr_type_node, size_type_node);
>
> if (flag_tm)
> {
> tree fn2 = get_identifier ("_ITM_cxa_allocate_exception");
> if (!get_global_value_if_present (fn2, &fn2))
> ! fn2 = declare_nothrow_library_fn (fn2, ptr_type_node,
> ! size_type_node);
> ! apply_tm_attr (fn2, get_identifier ("transaction_pure"));
> record_tm_replacement (fn, fn2);
> }
> }
> --- 625,640 ----
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void *__cxa_allocate_exception(size_t) throw(). */
> ! fn = declare_library_fn (fn, ptr_type_node, size_type_node,
> ! ECF_NOTHROW | ECF_MALLOC);
>
> if (flag_tm)
> {
> tree fn2 = get_identifier ("_ITM_cxa_allocate_exception");
> if (!get_global_value_if_present (fn2, &fn2))
> ! fn2 = declare_library_fn (fn2, ptr_type_node,
> ! size_type_node,
> ! ECF_NOTHROW | ECF_MALLOC | ECF_TM_PURE);
> record_tm_replacement (fn, fn2);
> }
> }
> *************** do_free_exception (tree ptr)
> *** 660,666 ****
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void __cxa_free_exception (void *) throw(). */
> ! fn = declare_nothrow_library_fn (fn, void_type_node, ptr_type_node);
> }
>
> return cp_build_function_call_nary (fn, tf_warning_or_error, ptr, NULL_TREE);
> --- 655,662 ----
> if (!get_global_value_if_present (fn, &fn))
> {
> /* Declare void __cxa_free_exception (void *) throw(). */
> ! fn = declare_library_fn (fn, void_type_node, ptr_type_node,
> ! ECF_NOTHROW | ECF_LEAF);
> }
>
> return cp_build_function_call_nary (fn, tf_warning_or_error, ptr, NULL_TREE);
> Index: cp/rtti.c
> ===================================================================
> *** cp/rtti.c (revision 201910)
> --- cp/rtti.c (working copy)
> *************** build_dynamic_cast_1 (tree type, tree ex
> *** 739,745 ****
> const_ptr_type_node,
> tinfo_ptr, tinfo_ptr,
> ptrdiff_type_node, NULL_TREE);
> ! dcast_fn = build_library_fn_ptr (name, tmp);
> ! DECL_PURE_P (dcast_fn) = 1;
> pop_abi_namespace ();
> dynamic_cast_node = dcast_fn;
> --- 739,745 ----
> const_ptr_type_node,
> tinfo_ptr, tinfo_ptr,
> ptrdiff_type_node, NULL_TREE);
> ! dcast_fn = build_library_fn_ptr (name, tmp,
> ! ECF_LEAF | ECF_PURE | ECF_NOTHROW);
> pop_abi_namespace ();
> dynamic_cast_node = dcast_fn;