]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c/107305 - avoid ICEing with invalid GIMPLE input to the GIMPLE FE
authorRichard Biener <rguenther@suse.de>
Wed, 19 Oct 2022 12:12:11 +0000 (14:12 +0200)
committerRichard Biener <rguenther@suse.de>
Thu, 20 Oct 2022 09:29:28 +0000 (11:29 +0200)
The GIMPLE FE was designed to defer semantic error checking to the
GIMPLE IL verifier.  But that can end up causing spurious ICEs
earlier and in fact it will report an internal error.  The following
tries to improve the situation by explicitely calling into the
verifier from the parser and intructing it to not ICE but instead
zap the parsed body after an error is discovered.

PR c/107305
PR c/107306
gcc/c/
* gimple-parser.cc (c_parser_parse_gimple_body): Verify
the parsed IL and zap the body on error.

gcc/
* tree-cfg.h (verify_gimple_in_seq): Add parameter to
indicate whether to emit an ICE.  Add return value.
(verify_gimple_in_cfg): Likewise.
* tree-cfg.cc (verify_gimple_in_seq): Likewise.
(verify_gimple_in_cfg): Likewise.

gcc/testsuite/
* gcc.dg/gimplefe-error-15.c: New testcase.

gcc/c/gimple-parser.cc
gcc/testsuite/gcc.dg/gimplefe-error-15.c [new file with mode: 0644]
gcc/tree-cfg.cc
gcc/tree-cfg.h

index 5a2da2cfa0e7a6d9a66968ef31c20eeaa2c89497..18ed4d4236d77a7824f3aca321d166a47e247585 100644 (file)
@@ -364,6 +364,16 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
       cgraph_node::get_create (cfun->decl);
       cgraph_edge::rebuild_edges ();
     }
+
+  /* Perform IL validation and if any error is found abort compilation
+     of this function by zapping its body.  */
+  if ((cfun->curr_properties & PROP_cfg)
+      && verify_gimple_in_cfg (cfun, false, false))
+    init_empty_tree_cfg ();
+  else if (!(cfun->curr_properties & PROP_cfg)
+          && verify_gimple_in_seq (gimple_body (current_function_decl), false))
+    gimple_set_body (current_function_decl, NULL);
+
   dump_function (TDI_gimple, current_function_decl);
 }
 
diff --git a/gcc/testsuite/gcc.dg/gimplefe-error-15.c b/gcc/testsuite/gcc.dg/gimplefe-error-15.c
new file mode 100644 (file)
index 0000000..066cd84
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+unsigned a;
+static double *d;
+static _Bool b;
+__GIMPLE int
+foo (int n)
+{
+  b = __builtin_add_overflow (n, *d, &a);
+} /* { dg-error "invalid argument" } */
+
+/* { dg-message "" "" { target *-*-* } 0 } */
index 9b2c0f6956c41471cb25dae1c939b5c86ea54335..d982988048f24eb318c01ec84298282a1b8b1ba8 100644 (file)
@@ -5300,13 +5300,15 @@ verify_gimple_transaction (gtransaction *stmt)
 
 /* Verify the GIMPLE statements inside the statement list STMTS.  */
 
-DEBUG_FUNCTION void
-verify_gimple_in_seq (gimple_seq stmts)
+DEBUG_FUNCTION bool
+verify_gimple_in_seq (gimple_seq stmts, bool ice)
 {
   timevar_push (TV_TREE_STMT_VERIFY);
-  if (verify_gimple_in_seq_2 (stmts))
+  bool res = verify_gimple_in_seq_2 (stmts);
+  if (res && ice)
     internal_error ("%<verify_gimple%> failed");
   timevar_pop (TV_TREE_STMT_VERIFY);
+  return res;
 }
 
 /* Return true when the T can be shared.  */
@@ -5496,8 +5498,8 @@ collect_subblocks (hash_set<tree> *blocks, tree block)
 
 /* Verify the GIMPLE statements in the CFG of FN.  */
 
-DEBUG_FUNCTION void
-verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
+DEBUG_FUNCTION bool
+verify_gimple_in_cfg (struct function *fn, bool verify_nothrow, bool ice)
 {
   basic_block bb;
   bool err = false;
@@ -5652,11 +5654,13 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
     eh_table->traverse<hash_set<gimple *> *, verify_eh_throw_stmt_node>
       (&visited_throwing_stmts);
 
-  if (err || eh_error_found)
+  if (ice && (err || eh_error_found))
     internal_error ("verify_gimple failed");
 
   verify_histograms ();
   timevar_pop (TV_TREE_STMT_VERIFY);
+
+  return (err || eh_error_found);
 }
 
 
index 95ec93e3a9171acc4b27bc13071485c0c991a0a2..8c22c3dbbe36325cfe15a326fe6cb0db3ef89a84 100644 (file)
@@ -63,8 +63,8 @@ extern gphi *get_virtual_phi (basic_block);
 extern gimple *first_stmt (basic_block);
 extern gimple *last_stmt (basic_block);
 extern gimple *last_and_only_stmt (basic_block);
-extern void verify_gimple_in_seq (gimple_seq);
-extern void verify_gimple_in_cfg (struct function *, bool);
+extern bool verify_gimple_in_seq (gimple_seq, bool = true);
+extern bool verify_gimple_in_cfg (struct function *, bool, bool = true);
 extern tree gimple_block_label (basic_block);
 extern void add_phi_args_after_copy_bb (basic_block);
 extern void add_phi_args_after_copy (basic_block *, unsigned, edge);