From a4a591f9f768fb7cde4659c2b4cf09031cee5486 Mon Sep 17 00:00:00 2001
From: mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Fri, 19 May 2006 03:01:14 +0000
Subject: 	PR c++/27471 	PR c++/27506 	* typeck.c (decay_conversion):
 Convert bitfields to their declared 	types here.  Improve documentation. 
 Avoid use of cp_convert. 	(default_conversion): Make it static.  Perform
 integral promotions 	before lvalue-to-rvalue, function-to-pointer, and
 array-to-pointer 	conversions. 	* init.c (build_init): Remove. 
 (expand_default_init): Do not call rvalue. 	* call.c (null_ptr_cst_p):
 Robustify. 	(build_conditional_expr): Tidy. 	* except.c
 (build_throw): Do not perform lvalue-to-rvalue 	conversion on operand
 before initializing temporary. 	* tree.c (convert.h): Include it. 
 (convert_bitfield_to_declared_type): Use convert_to_integer, not 
 cp_convert. 	(rvalue): Don't convert bitfields to their declared type here.
 	* cp-tree.h (build_init): Remove. 	(default_conversion):
 Likewise. 	* typeck2.c (build_m_component_ref): Do not perform 
 lvalue-to-rvalue, function-to-pointer, or array-to-pointer 	conversions
 here.  Correct error message. 	PR c++/27471 	PR c++/27506 	*
 g++.dg/conversion/bitfield5.C: New test. 	*
 g++.dg/conversion/bitfield6.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@113902 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/except.c | 38 +++++++++++++++++++++++++++++---------
 1 file changed, 29 insertions(+), 9 deletions(-)

(limited to 'gcc/cp/except.c')

diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index d82c07ff329..efdbd91e857 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -638,6 +638,7 @@ build_throw (tree exp)
   else if (exp)
     {
       tree throw_type;
+      tree temp_type;
       tree cleanup;
       tree object, ptr;
       tree tmp;
@@ -666,9 +667,17 @@ build_throw (tree exp)
 	  fn = push_throw_library_fn (fn, tmp);
 	}
 
-      /* throw expression */
-      /* First, decay it.  */
-      exp = decay_conversion (exp);
+      /* [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 = type_decays_to (TYPE_MAIN_VARIANT (TREE_TYPE (exp)));
 
       /* OK, this is kind of wacky.  The standard says that we call
 	 terminate when the exception handling mechanism, after
@@ -684,21 +693,32 @@ build_throw (tree exp)
 	 matter, since it can't throw).  */
 
       /* Allocate the space for the exception.  */
-      allocate_expr = do_allocate_exception (TREE_TYPE (exp));
+      allocate_expr = do_allocate_exception (temp_type);
       allocate_expr = get_target_expr (allocate_expr);
       ptr = TARGET_EXPR_SLOT (allocate_expr);
-      object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
+      object = build_nop (build_pointer_type (temp_type), ptr);
       object = build_indirect_ref (object, NULL);
 
       elided = (TREE_CODE (exp) == TARGET_EXPR);
 
       /* And initialize the exception object.  */
-      exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
-      if (exp == error_mark_node)
+      if (CLASS_TYPE_P (temp_type))
 	{
-	  error ("  in thrown expression");
-	  return error_mark_node;
+	  /* Call the copy constructor.  */
+	  exp = (build_special_member_call 
+		 (object, complete_ctor_identifier,
+		  build_tree_list (NULL_TREE, exp),
+		  TREE_TYPE (object),
+		  LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
+	  if (exp == error_mark_node)
+	    {
+	      error ("  in thrown expression");
+	      return error_mark_node;
+	    }
 	}
+      else
+	exp = build2 (INIT_EXPR, temp_type, object, 
+		      decay_conversion (exp));
 
       /* Pre-evaluate the thrown expression first, since if we allocated
 	 the space first we would have to deal with cleaning it up if
-- 
cgit v1.2.1