summaryrefslogtreecommitdiff
path: root/gcc/cp/except.c
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-17 15:55:51 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-17 15:55:51 +0000
commit2572143c16564137a3042a04b9eca06ef5919600 (patch)
tree9367aeb410690c46507d07fb1ea823ff0e5b0670 /gcc/cp/except.c
parent009ec0e54e4980f943b59366f465a3e5d85fcfec (diff)
downloadgcc-2572143c16564137a3042a04b9eca06ef5919600.tar.gz
/cp
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. /testsuite 2012-05-17 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53371 * g++.dg/cpp0x/catch1.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187630 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/except.c')
-rw-r--r--gcc/cp/except.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index d39cfa6abd3..f4af7806fe1 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;
}