commit 628060335341d57090cd83e45b5e577674a3c0a9 Author: Jason Merrill Date: Mon May 6 21:30:20 2013 -0400 * except.c (is_admissible_throw_operand_or_catch_parameter): Check variably_modified_type_p. (expand_start_catch_block): Mark the typeinfo used here. * semantics.c (finish_handler_parms): Not here. * error.c (dump_type_suffix): Try harder on VLA length. diff --git a/gcc/cp/error.c b/gcc/cp/error.c index c57a5aa..48327dd 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -848,14 +848,24 @@ dump_type_suffix (tree t, int flags) pp_character (cxx_pp, '0'); else if (host_integerp (max, 0)) pp_wide_integer (cxx_pp, tree_low_cst (max, 0) + 1); - else if (TREE_CODE (max) == MINUS_EXPR) - dump_expr (TREE_OPERAND (max, 0), - flags & ~TFF_EXPR_IN_PARENS); else - dump_expr (fold_build2_loc (input_location, - PLUS_EXPR, dtype, max, - build_int_cst (dtype, 1)), - flags & ~TFF_EXPR_IN_PARENS); + { + STRIP_NOPS (max); + if (TREE_CODE (max) == SAVE_EXPR) + max = TREE_OPERAND (max, 0); + if (TREE_CODE (max) == MINUS_EXPR + || TREE_CODE (max) == PLUS_EXPR) + { + max = TREE_OPERAND (max, 0); + while (CONVERT_EXPR_P (max)) + max = TREE_OPERAND (max, 0); + } + else + max = fold_build2_loc (input_location, + PLUS_EXPR, dtype, max, + build_int_cst (dtype, 1)); + dump_expr (max, flags & ~TFF_EXPR_IN_PARENS); + } } pp_cxx_right_bracket (cxx_pp); dump_type_suffix (TREE_TYPE (t), flags); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index b762a51..be003d2 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -490,6 +490,7 @@ expand_start_catch_block (tree decl) decl = error_mark_node; type = prepare_eh_type (TREE_TYPE (decl)); + mark_used (eh_type_info (type)); } else type = NULL_TREE; @@ -982,6 +983,16 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw) "reference type %qT", type); return false; } + else if (variably_modified_type_p (type, NULL_TREE)) + { + if (is_throw) + error ("cannot throw expression of type %qT because it involves " + "types of variable size", type); + else + error ("cannot catch type %qT because it involves types of " + "variable size", type); + return false; + } return true; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index a06a23a..2165649 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1199,8 +1199,6 @@ finish_handler_parms (tree decl, tree handler) else type = expand_start_catch_block (decl); HANDLER_TYPE (handler) = type; - if (!processing_template_decl && type) - mark_used (eh_type_info (type)); } /* Finish a handler, which may be given by HANDLER. The BLOCKs are diff --git a/gcc/testsuite/g++.dg/ext/vla4.C b/gcc/testsuite/g++.dg/ext/vla4.C index ecec908..90e4160 100644 --- a/gcc/testsuite/g++.dg/ext/vla4.C +++ b/gcc/testsuite/g++.dg/ext/vla4.C @@ -6,7 +6,7 @@ void f(int i) { try { int a[i]; - throw &a; // { dg-error "variable size" } + throw &a; // { dg-error "int \\(\\*\\)\\\[i\\\]" } } catch (int (*)[i]) { // { dg-error "variable size" } } }