aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/except.c48
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/catch1.C16
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" }
+}