static tree
do_end_catch (tree type)
{
  tree fn, cleanup;

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

  cleanup = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
  TREE_NOTHROW (cleanup) = dtor_nothrow (type);

  return cleanup;
}
static tree
do_begin_catch (void)
{
  tree fn;

  fn = get_identifier ("__cxa_begin_catch");
  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);
	}
    }

  return cp_build_function_call_nary (fn, tf_warning_or_error,
				      build_exc_ptr (), NULL_TREE);
}
static tree
do_allocate_exception (tree type)
{
  tree fn;

  fn = get_identifier ("__cxa_allocate_exception");
  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);
	}
    }

  return cp_build_function_call_nary (fn, tf_warning_or_error,
				      size_in_bytes (type), NULL_TREE);
}
示例#4
0
static tree
do_free_exception (tree ptr)
{
  tree fn;

  fn = get_identifier ("__cxa_free_exception");
  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);

      if (flag_tm)
	{
	  tree fn2 = get_identifier ("_ITM_cxa_free_exception");
	  if (!get_global_value_if_present (fn2, &fn2))
	    fn2 = declare_library_fn (fn2, void_type_node,
				      ptr_type_node,
				      ECF_NOTHROW | ECF_LEAF | ECF_TM_PURE);
	  record_tm_replacement (fn, fn2);
	}
    }

  return cp_build_function_call_nary (fn, tf_warning_or_error, ptr, NULL_TREE);
}
示例#5
0
static tree
throw_bad_cast (void)
{
  tree fn = get_identifier ("__cxa_bad_cast");
  if (!get_global_value_if_present (fn, &fn))
    fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
							 void_list_node));
  
  return build_cxx_call (fn, NULL_TREE);
}
示例#6
0
static tree
do_free_exception (tree ptr)
{
  tree fn;

  fn = get_identifier ("__cxa_free_exception");
  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);
}
示例#7
0
static tree
throw_bad_typeid (void)
{
  tree fn = get_identifier ("__cxa_bad_typeid");
  if (!get_global_value_if_present (fn, &fn))
    {
      tree t;

      t = build_reference_type (const_type_info_type_node);
      t = build_function_type (t, void_list_node);
      fn = push_throw_library_fn (fn, t);
    }

  return build_cxx_call (fn, NULL_TREE);
}
示例#8
0
static tree
do_free_exception (tree ptr)
{
  tree fn;

  fn = get_identifier ("__cxa_free_exception");
  if (!get_global_value_if_present (fn, &fn))
    {
      /* Declare void __cxa_free_exception (void *).  */
      fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node,
						void_list_node));
    }

  return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
}
static tree
do_get_exception_ptr (void)
{
  tree fn;

  fn = get_identifier ("__cxa_get_exception_ptr");
  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,
				      build_exc_ptr (), NULL_TREE);
}
示例#10
0
static tree
do_allocate_exception (tree type)
{
  tree fn;

  fn = get_identifier ("__cxa_allocate_exception");
  if (!get_global_value_if_present (fn, &fn))
    {
      /* Declare void *__cxa_allocate_exception(size_t).  */
      tree tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
      fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
    }
  
  return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
					     NULL_TREE));
}
static tree
do_begin_catch (void)
{
  tree fn;

  fn = get_identifier ("__cxa_begin_catch");
  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);
    }

  return cp_build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
						NULL_TREE),
				 tf_warning_or_error);
}
示例#12
0
static tree
do_begin_catch (void)
{
  tree fn;

  fn = get_identifier ("__cxa_begin_catch");
  if (!get_global_value_if_present (fn, &fn))
    {
      /* Declare void* __cxa_begin_catch (void *).  */
      tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
      fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
    }

  return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
					     NULL_TREE));
}
static tree
do_allocate_exception (tree type)
{
  tree fn;

  fn = get_identifier ("__cxa_allocate_exception");
  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);
    }

  return cp_build_function_call (fn, 
				 tree_cons (NULL_TREE, size_in_bytes (type),
					    NULL_TREE),
				 tf_warning_or_error);
}
示例#14
0
static tree
do_get_exception_ptr (void)
{
  tree fn;

  fn = get_identifier ("__cxa_get_exception_ptr");
  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,
				      build_exc_ptr (), NULL_TREE);
}
示例#15
0
static tree
do_end_catch (tree type)
{
  tree fn, cleanup;

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

  cleanup = build_function_call (fn, NULL_TREE);
  TREE_NOTHROW (cleanup) = dtor_nothrow (type);

  return cleanup;
}
示例#16
0
static tree
/* APPLE LOCAL radar 2848255 */
do_begin_catch (tree type)
{
  tree fn;

  /* APPLE LOCAL begin radar 2848255 */
  if (c_dialect_objc () && objc2_valid_objc_catch_type (type))
    fn = get_identifier ("objc_begin_catch");
  else
    fn = get_identifier ("__cxa_begin_catch");
  /* APPLE LOCAL end radar 2848255 */
  if (!get_global_value_if_present (fn, &fn))
    {
      /* Declare void* __cxa_begin_catch (void *).  */
      tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
      fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
    }

  return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
					     NULL_TREE));
}
示例#17
0
static tree
do_end_catch (tree type)
{
  tree fn, cleanup;

  /* APPLE LOCAL begin radar 2848255 */
  if (c_dialect_objc () && objc2_valid_objc_catch_type (type))
    fn = get_identifier ("objc_end_catch");
  else
    fn = get_identifier ("__cxa_end_catch");
  /* APPLE LOCAL end radar 2848255 */
  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;
    }

  cleanup = build_function_call (fn, NULL_TREE);
  TREE_NOTHROW (cleanup) = dtor_nothrow (type);

  return cleanup;
}
示例#18
0
tree
build_throw (tree exp)
{
  tree fn;

  if (exp == error_mark_node)
    return exp;

  if (processing_template_decl)
    {
      if (cfun)
	current_function_returns_abnormally = 1;
      exp = build_min (THROW_EXPR, void_type_node, exp);
      SET_EXPR_LOCATION (exp, input_location);
      return exp;
    }

  if (exp == null_node)
    warning (0, "throwing NULL, which has integral, not pointer type");

  if (exp != NULL_TREE)
    {
      if (!is_admissible_throw_operand_or_catch_parameter (exp, true))
	return error_mark_node;
    }

  if (! doing_eh ())
    return error_mark_node;

  if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
    {
      tree fn = get_identifier ("_Jv_Throw");
      if (!get_global_value_if_present (fn, &fn))
	{
	  /* Declare void _Jv_Throw (void *).  */
	  tree tmp;
	  tmp = build_function_type_list (ptr_type_node,
					  ptr_type_node, NULL_TREE);
	  fn = push_throw_library_fn (fn, tmp);
	}
      else if (really_overloaded_fn (fn))
	{
	  error ("%qD should never be overloaded", fn);
	  return error_mark_node;
	}
      fn = OVL_CURRENT (fn);
      exp = cp_build_function_call_nary (fn, tf_warning_or_error,
					 exp, NULL_TREE);
    }
  else if (exp)
    {
      tree throw_type;
      tree temp_type;
      tree cleanup;
      tree object, ptr;
      tree tmp;
      tree allocate_expr;

      /* The CLEANUP_TYPE is the internal type of a destructor.  */
      if (!cleanup_type)
	{
	  tmp = build_function_type_list (void_type_node,
					  ptr_type_node, NULL_TREE);
	  cleanup_type = build_pointer_type (tmp);
	}

      fn = get_identifier ("__cxa_throw");
      if (!get_global_value_if_present (fn, &fn))
	{
	  /* Declare void __cxa_throw (void*, void*, void (*)(void*)).  */
	  /* ??? Second argument is supposed to be "std::type_info*".  */
	  tmp = build_function_type_list (void_type_node,
					  ptr_type_node, ptr_type_node,
					  cleanup_type, NULL_TREE);
	  fn = push_throw_library_fn (fn, tmp);

	  if (flag_tm)
	    {
	      tree fn2 = get_identifier ("_ITM_cxa_throw");
	      if (!get_global_value_if_present (fn2, &fn2))
		fn2 = push_throw_library_fn (fn2, tmp);
	      apply_tm_attr (fn2, get_identifier ("transaction_pure"));
	      record_tm_replacement (fn, fn2);
	    }
	}

      /* [except.throw]

	 A throw-expression initializes a temporary object, the type
	 of which is determined by removing any top-level
	 cv-qualifiers from the static type of the operand of throw
	 and adjusting the type from "array of T" or "function return
	 T" to "pointer to T" or "pointer to function returning T"
	 respectively.  */
      temp_type = is_bitfield_expr_with_lowered_type (exp);
      if (!temp_type)
	temp_type = cv_unqualified (type_decays_to (TREE_TYPE (exp)));

      /* OK, this is kind of wacky.  The standard says that we call
	 terminate when the exception handling mechanism, after
	 completing evaluation of the expression to be thrown but
	 before the exception is caught (_except.throw_), calls a
	 user function that exits via an uncaught exception.

	 So we have to protect the actual initialization of the
	 exception object with terminate(), but evaluate the
	 expression first.  Since there could be temps in the
	 expression, we need to handle that, too.  We also expand
	 the call to __cxa_allocate_exception first (which doesn't
	 matter, since it can't throw).  */

      /* Allocate the space for the exception.  */
      allocate_expr = do_allocate_exception (temp_type);
      allocate_expr = get_target_expr (allocate_expr);
      ptr = TARGET_EXPR_SLOT (allocate_expr);
      TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr);
      CLEANUP_EH_ONLY (allocate_expr) = 1;

      object = build_nop (build_pointer_type (temp_type), ptr);
      object = cp_build_indirect_ref (object, RO_NULL, tf_warning_or_error);

      /* And initialize the exception object.  */
      if (CLASS_TYPE_P (temp_type))
	{
	  int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
	  vec<tree, va_gc> *exp_vec;

	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
	     treated as an rvalue for the purposes of overload resolution
	     to favor move constructors over copy constructors.  */
	  if (/* Must be a local, automatic variable.  */
	      VAR_P (exp)
	      && DECL_CONTEXT (exp) == current_function_decl
	      && ! TREE_STATIC (exp)
	      /* The variable must not have the `volatile' qualifier.  */
	      && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE))
	    flags = flags | LOOKUP_PREFER_RVALUE;

	  /* Call the copy constructor.  */
	  exp_vec = make_tree_vector_single (exp);
	  exp = (build_special_member_call
		 (object, complete_ctor_identifier, &exp_vec,
		  TREE_TYPE (object), flags, tf_warning_or_error));
	  release_tree_vector (exp_vec);
	  if (exp == error_mark_node)
	    {
	      error ("  in thrown expression");
	      return error_mark_node;
	    }
	}
      else
	{
	  tmp = decay_conversion (exp, tf_warning_or_error);
	  if (tmp == error_mark_node)
	    return error_mark_node;
	  exp = build2 (INIT_EXPR, temp_type, object, tmp);
	}

      /* Mark any cleanups from the initialization as MUST_NOT_THROW, since
	 they are run after the exception object is initialized.  */
      cp_walk_tree_without_duplicates (&exp, wrap_cleanups_r, 0);

      /* Prepend the allocation.  */
      exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);

      /* Force all the cleanups to be evaluated here so that we don't have
	 to do them during unwinding.  */
      exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp);

      throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));

      cleanup = NULL_TREE;
      if (type_build_dtor_call (TREE_TYPE (object)))
	{
	  tree fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
				     complete_dtor_identifier, 0);
	  fn = BASELINK_FUNCTIONS (fn);
	  mark_used (fn);
	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
	    {
	      cxx_mark_addressable (fn);
	      /* Pretend it's a normal function.  */
	      cleanup = build1 (ADDR_EXPR, cleanup_type, fn);
	    }
	}
      if (cleanup == NULL_TREE)
	cleanup = build_int_cst (cleanup_type, 0);

      /* ??? Indicate that this function call throws throw_type.  */
      tmp = cp_build_function_call_nary (fn, tf_warning_or_error,
					 ptr, throw_type, cleanup, NULL_TREE);

      /* Tack on the initialization stuff.  */
      exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
    }
  else
    {
      /* Rethrow current exception.  */

      tree fn = get_identifier ("__cxa_rethrow");
      if (!get_global_value_if_present (fn, &fn))
	{
	  /* Declare void __cxa_rethrow (void).  */
	  fn = push_throw_library_fn
	    (fn, build_function_type_list (void_type_node, NULL_TREE));
	}

      if (flag_tm)
	apply_tm_attr (fn, get_identifier ("transaction_pure"));

      /* ??? Indicate that this function call allows exceptions of the type
	 of the enclosing catch block (if known).  */
      exp = cp_build_function_call_vec (fn, NULL, tf_warning_or_error);
    }

  exp = build1 (THROW_EXPR, void_type_node, exp);
  SET_EXPR_LOCATION (exp, input_location);

  return exp;
}