From fdc1f34302906036637445455a53a09f25a4acfd Mon Sep 17 00:00:00 2001
From: Alexandre Oliva <oliva@adacore.com>
Date: Fri, 12 Jul 2019 13:50:49 +0000
Subject: [PATCH] introduce try/finally/else in gimplefe

for  gcc/c/ChangeLog

	* gimple-parser.c (c_parser_gimple_try_stmt): New.
	(c_parser_compound_statement): Call it.

for  gcc/testsuite/ChangeLog

	* gcc.dg/gimplefe-43.c: New.

From-SVN: r273443
---
 gcc/c/ChangeLog                    |  5 +++
 gcc/c/gimple-parser.c              | 61 ++++++++++++++++++++++++++++++
 gcc/testsuite/ChangeLog            |  4 ++
 gcc/testsuite/gcc.dg/gimplefe-43.c | 25 ++++++++++++
 4 files changed, 95 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/gimplefe-43.c

diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index c58680c135b5..927fa914bfb6 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2019-07-12  Alexandre Oliva <oliva@adacore.com>
+
+	* gimple-parser.c (c_parser_gimple_try_stmt): New.
+	(c_parser_compound_statement): Call it.
+
 2019-07-12  Jakub Jelinek  <jakub@redhat.com>
 
 	* c-parser.c (c_parser_omp_clause_name): Handle order clause.
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index a0ea7215984a..4970ae1e9e08 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -117,6 +117,7 @@ static struct c_expr c_parser_gimple_postfix_expression_after_primary
 static void c_parser_gimple_declaration (gimple_parser &);
 static void c_parser_gimple_goto_stmt (gimple_parser &, location_t,
 				       tree, gimple_seq *);
+static void c_parser_gimple_try_stmt (gimple_parser &, gimple_seq *);
 static void c_parser_gimple_if_stmt (gimple_parser &, gimple_seq *);
 static void c_parser_gimple_switch_stmt (gimple_parser &, gimple_seq *);
 static void c_parser_gimple_return_stmt (gimple_parser &, gimple_seq *);
@@ -407,6 +408,9 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
 	case CPP_KEYWORD:
 	  switch (c_parser_peek_token (parser)->keyword)
 	    {
+	    case RID_AT_TRY:
+	      c_parser_gimple_try_stmt (parser, seq);
+	      break;
 	    case RID_IF:
 	      c_parser_gimple_if_stmt (parser, seq);
 	      break;
@@ -448,6 +452,14 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
 	      c_parser_gimple_label (parser, seq);
 	      break;
 	    }
+	  if (c_parser_next_token_is (parser, CPP_NAME)
+	      && c_parser_peek_token (parser)->id_kind == C_ID_ID
+	      && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+			 "try") == 0)
+	    {
+	      c_parser_gimple_try_stmt (parser, seq);
+	      break;
+	    }
 	  /* Basic block specification.
 	     __BB (index, ...)  */
 	  if ((cfun->curr_properties & PROP_cfg)
@@ -2092,6 +2104,55 @@ c_parser_gimple_paren_condition (gimple_parser &parser)
   return cond;
 }
 
+/* Parse gimple try statement.
+
+   try-statement:
+     try { ... } finally { ... }
+     try { ... } finally { ... } else { ... }
+
+   This could support try/catch as well, but it's not implemented yet.
+ */
+
+static void
+c_parser_gimple_try_stmt (gimple_parser &parser, gimple_seq *seq)
+{
+  gimple_seq tryseq = NULL;
+  c_parser_consume_token (parser);
+  c_parser_gimple_compound_statement (parser, &tryseq);
+
+  if ((c_parser_next_token_is (parser, CPP_KEYWORD)
+       && c_parser_peek_token (parser)->keyword == RID_AT_FINALLY)
+      || (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_token (parser)->id_kind == C_ID_ID
+	  && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
+		     "finally") == 0))
+    {
+      gimple_seq finseq = NULL;
+      c_parser_consume_token (parser);
+      c_parser_gimple_compound_statement (parser, &finseq);
+
+      if (c_parser_next_token_is (parser, CPP_KEYWORD)
+	  && c_parser_peek_token (parser)->keyword == RID_ELSE)
+	{
+	  gimple_seq elsseq = NULL;
+	  c_parser_consume_token (parser);
+	  c_parser_gimple_compound_statement (parser, &elsseq);
+
+	  geh_else *stmt = gimple_build_eh_else (finseq, elsseq);
+	  finseq = NULL;
+	  gimple_seq_add_stmt_without_update (&finseq, stmt);
+	}
+
+      gtry *stmt = gimple_build_try (tryseq, finseq, GIMPLE_TRY_FINALLY);
+      gimple_seq_add_stmt_without_update (seq, stmt);
+    }
+  else if (c_parser_next_token_is (parser, CPP_KEYWORD)
+      && c_parser_peek_token (parser)->keyword == RID_AT_CATCH)
+    c_parser_error (parser, "%<catch%> is not supported");
+  else
+    c_parser_error (parser, "expected %<finally%> or %<catch%>");
+}
+
 /* Parse gimple if-else statement.
 
    if-statement:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dfda37f912c0..c2352005a370 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2019-07-12  Alexandre Oliva <oliva@adacore.com>
+
+	* gcc.dg/gimplefe-43.c: New.
+
 2019-07-12  Richard Biener  <rguenther@suse.de>
 
 	* gcc.dg/tree-ssa/vector-7.c: New testcase.
diff --git a/gcc/testsuite/gcc.dg/gimplefe-43.c b/gcc/testsuite/gcc.dg/gimplefe-43.c
new file mode 100644
index 000000000000..5fd66e6dfa5c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-43.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+void __GIMPLE foo()
+{
+  try
+    {
+      try
+	{
+	  ;
+	}
+      finally
+	{
+	  ;
+	}
+      else
+	{
+	  ;
+	}
+    }
+  finally
+    {
+      ;
+    }
+}
-- 
GitLab