From: Paolo Carlini Date: Thu, 17 May 2012 15:55:51 +0000 (+0000) Subject: re PR c++/53371 (rvalue reference type as exception-declaration) X-Git-Tag: misc/gccgo-go1_1_2~2833 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f9eead1f8953869fcfd8be7b0e58aff50fbe1fd5;p=thirdparty%2Fgcc.git re PR c++/53371 (rvalue reference type as exception-declaration) /cp 2012-05-17 Paolo Carlini PR c++/53371 * except.c (is_admissible_throw_operand): Rename to is_admissible_throw_operand_or_catch_parameter and handle catch parameter too. (expand_start_catch_block): Use it. (build_throw): Adjust. /testsuite 2012-05-17 Paolo Carlini PR c++/53371 * g++.dg/cpp0x/catch1.C: New. From-SVN: r187630 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 54ae298ffd14..98fb081217ef 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2012-05-17 Paolo Carlini + + PR c++/53371 + * except.c (is_admissible_throw_operand): Rename to + is_admissible_throw_operand_or_catch_parameter and handle + catch parameter too. + (expand_start_catch_block): Use it. + (build_throw): Adjust. + 2012-05-17 Paolo Carlini PR c++/44516 diff --git a/gcc/cp/except.c b/gcc/cp/except.c index d39cfa6abd33..f4af7806fe12 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -46,7 +46,7 @@ static void initialize_handler_parm (tree, tree); static tree do_allocate_exception (tree); static tree wrap_cleanups_r (tree *, int *, void *); static int complete_ptr_ref_or_void_ptr_p (tree, tree); -static bool is_admissible_throw_operand (tree); +static bool is_admissible_throw_operand_or_catch_parameter (tree, bool); static int can_convert_eh (tree, tree); /* Sets up all the global eh stuff that needs to be initialized at the @@ -485,12 +485,13 @@ expand_start_catch_block (tree decl) if (! doing_eh ()) return NULL_TREE; - /* Make sure this declaration is reasonable. */ - if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE)) - decl = error_mark_node; - if (decl) - type = prepare_eh_type (TREE_TYPE (decl)); + { + if (!is_admissible_throw_operand_or_catch_parameter (decl, false)) + decl = error_mark_node; + + type = prepare_eh_type (TREE_TYPE (decl)); + } else type = NULL_TREE; @@ -720,7 +721,7 @@ build_throw (tree exp) if (exp != NULL_TREE) { - if (!is_admissible_throw_operand (exp)) + if (!is_admissible_throw_operand_or_catch_parameter (exp, true)) return error_mark_node; } @@ -944,14 +945,21 @@ complete_ptr_ref_or_void_ptr_p (tree type, tree from) return 1; } -/* Return truth-value if EXPRESSION is admissible in throw-expression, - i.e. if it is not of incomplete type or a pointer/reference to such - a type or of an abstract class type. */ +/* If IS_THROW is true return truth-value if T is an expression admissible + in throw-expression, i.e. if it is not of incomplete type or a pointer/ + reference to such a type or of an abstract class type. + If IS_THROW is false, likewise for a catch parameter, same requirements + for its type plus rvalue reference type is also not admissible. */ static bool -is_admissible_throw_operand (tree expr) +is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw) { - tree type = TREE_TYPE (expr); + tree expr = is_throw ? t : NULL_TREE; + tree type = TREE_TYPE (t); + + /* C++11 [except.handle] The exception-declaration shall not denote + an incomplete type, an abstract class type, or an rvalue reference + type. */ /* 15.1/4 [...] The type of the throw-expression shall not be an incomplete type, or a pointer or a reference to an incomplete @@ -968,8 +976,20 @@ is_admissible_throw_operand (tree expr) conversion. */ else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type)) { - error ("expression %qE of abstract class type %qT cannot " - "be used in throw-expression", expr, type); + if (is_throw) + error ("expression %qE of abstract class type %qT cannot " + "be used in throw-expression", expr, type); + else + error ("cannot declare catch parameter to be of abstract " + "class type %qT", type); + return false; + } + else if (!is_throw + && TREE_CODE (type) == REFERENCE_TYPE + && TYPE_REF_IS_RVALUE (type)) + { + error ("cannot declare catch parameter to be of rvalue " + "reference type %qT", type); return false; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b3072637a42c..2eb3d5b15502 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-05-17 Paolo Carlini + + PR c++/53371 + * g++.dg/cpp0x/catch1.C: New. + 2012-05-17 Paolo Carlini PR c++/44516 diff --git a/gcc/testsuite/g++.dg/cpp0x/catch1.C b/gcc/testsuite/g++.dg/cpp0x/catch1.C new file mode 100644 index 000000000000..81778ea78076 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/catch1.C @@ -0,0 +1,16 @@ +// PR c++/53371 +// { dg-do compile { target c++11 } } + +struct Abs +{ + virtual void a() = 0; +}; + +void foo() +{ + try { + } catch (Abs) { } // { dg-error "abstract class type" } + + try { + } catch (int&&) { } // { dg-error "rvalue reference type" } +}