On Thu, Aug 22, 2013 at 8:19 AM, Jan Hubicka <hubi...@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;