diff options
Diffstat (limited to 'gcc/cp/except.c')
-rw-r--r-- | gcc/cp/except.c | 30 |
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"); |