This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ patch] Set attributes for C++ runtime library calls


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]