Patchwork C++ PATCH to improve VLA/EH diagnostics

login
register
mail settings
Submitter Jason Merrill
Date May 8, 2013, 9:22 p.m.
Message ID <518AC20B.1070203@redhat.com>
Download mbox | patch
Permalink /patch/242646/
State New
Headers show

Comments

Jason Merrill - May 8, 2013, 9:22 p.m.
VLA types in diagnostics have tended to look like

int[(((sizetype)(((ssizetype)i) + -1)) + 1)]

...which is horrible.  This patch fixes that to

int[i]

and also specifically diagnoses trying to use a variably modified type 
in throw or catch.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 628060335341d57090cd83e45b5e577674a3c0a9
Author: Jason Merrill <jason@redhat.com>
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" }
   }
 }