summaryrefslogtreecommitdiff
path: root/gcc/cp/except.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/except.c')
-rw-r--r--gcc/cp/except.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 208e52a405b..b25b91b97be 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -665,6 +665,7 @@ build_throw (tree exp)
{
int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
vec<tree, va_gc> *exp_vec;
+ bool converted = false;
/* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
treated as an rvalue for the purposes of overload resolution
@@ -675,14 +676,31 @@ build_throw (tree exp)
&& ! 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;
+ {
+ tree moved = move (exp);
+ exp_vec = make_tree_vector_single (moved);
+ moved = (build_special_member_call
+ (object, complete_ctor_identifier, &exp_vec,
+ TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE,
+ tf_none));
+ release_tree_vector (exp_vec);
+ if (moved != error_mark_node)
+ {
+ exp = moved;
+ converted = true;
+ }
+ }
/* 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 (!converted)
+ {
+ 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");