diff options
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/except.c | 48 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/catch1.C | 16 |
4 files changed, 64 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 54ae298..98fb081 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,14 @@ 2012-05-17 Paolo Carlini <paolo.carlini@oracle.com> + 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 <paolo.carlini@oracle.com> + PR c++/44516 * typeck.c (build_x_array_ref, build_x_conditional_expr, build_x_compound_expr, build_x_modify_expr): Add location_t parameter. diff --git a/gcc/cp/except.c b/gcc/cp/except.c index d39cfa6..f4af780 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 b307263..2eb3d5b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2012-05-17 Paolo Carlini <paolo.carlini@oracle.com> + PR c++/53371 + * g++.dg/cpp0x/catch1.C: New. + +2012-05-17 Paolo Carlini <paolo.carlini@oracle.com> + PR c++/44516 * g++.dg/parse/error48.C: New. * g++.dg/template/crash89.C: Adjust dg-error line numbers. diff --git a/gcc/testsuite/g++.dg/cpp0x/catch1.C b/gcc/testsuite/g++.dg/cpp0x/catch1.C new file mode 100644 index 0000000..81778ea --- /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" } +} |