From a53afc648f63d01e874a57cc8490789701f0ae6a Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 13 Dec 2013 16:21:32 -0500
Subject: [PATCH 20/88] Introduce gimple_goto

gcc/
	* coretypes.h (gimple_goto): New typedef.
	(const_gimple_goto): New typedef.

	* gimple.h (gimple_statement_goto): New subclass of
	gimple_statement_with_ops, adding the invariant that
	stmt->code == GIMPLE_GOTO.
	(is_a_helper <gimple_statement_goto>::test): New.
	(gimple_build_goto): Return a gimple_goto rather than a
	plain gimple.

	* gimple-pretty-print.c (dump_gimple_goto): Require a gimple_goto
	rather than a plain gimple.
	(pp_gimple_stmt_1): Add a checked cast to gimple_goto within
	GIMPLE_GOTO case of switch statement.

	* gimple.c (gimple_build_goto): Return a gimple_goto rather than a
	plain gimple.

	* tree-cfg.c (verify_gimple_goto): Require a gimple_goto rather
	than a plain gimple.
	(verify_gimple_stmt): Add a checked cast to gimple_goto within
	GIMPLE_GOTO case of switch statement.
---
 gcc/coretypes.h           |  4 ++++
 gcc/gimple-pretty-print.c |  4 ++--
 gcc/gimple.c              |  5 +++--
 gcc/gimple.h              | 24 +++++++++++++++++++++++-
 gcc/tree-cfg.c            |  4 ++--
 5 files changed, 34 insertions(+), 7 deletions(-)

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index f726053..653343a 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -98,6 +98,10 @@ struct gimple_statement_debug;
 typedef struct gimple_statement_debug *gimple_debug;
 typedef const struct gimple_statement_debug *const_gimple_debug;
 
+struct gimple_statement_goto;
+typedef struct gimple_statement_goto *gimple_goto;
+typedef const struct gimple_statement_goto *const_gimple_goto;
+
 struct gimple_statement_label;
 typedef struct gimple_statement_label *gimple_label;
 typedef const struct gimple_statement_label *const_gimple_label;
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index fe26581..b29d896 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -884,7 +884,7 @@ dump_gimple_label (pretty_printer *buffer, gimple_label gs, int spc, int flags)
    TDF_* in dumpfile.h).  */
 
 static void
-dump_gimple_goto (pretty_printer *buffer, gimple gs, int spc, int flags)
+dump_gimple_goto (pretty_printer *buffer, gimple_goto gs, int spc, int flags)
 {
   tree label = gimple_goto_dest (gs);
   if (flags & TDF_RAW)
@@ -2135,7 +2135,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
       break;
 
     case GIMPLE_GOTO:
-      dump_gimple_goto (buffer, gs, spc, flags);
+      dump_gimple_goto (buffer, as_a <gimple_goto> (gs), spc, flags);
       break;
 
     case GIMPLE_NOP:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index e8c0a62..0e5e473 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -499,10 +499,11 @@ gimple_build_label (tree label)
 
 /* Build a GIMPLE_GOTO statement to label DEST.  */
 
-gimple
+gimple_goto
 gimple_build_goto (tree dest)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1);
+  gimple_goto p =
+    as_a <gimple_goto> (gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1));
   gimple_goto_set_dest (p, dest);
   return p;
 }
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 559d281..128baf5 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -790,6 +790,20 @@ struct GTY((tag("GSS_WITH_OPS")))
 };
 
 /* A statement with the invariant that
+      stmt->code == GIMPLE_GOTO
+   i.e. a goto statement.
+
+   This type will normally be accessed via the gimple_goto and
+   const_gimple_goto typedefs (in coretypes.h), which are pointers to
+   this type.  */
+
+struct GTY((tag("GSS_WITH_OPS")))
+  gimple_statement_goto : public gimple_statement_with_ops
+{
+  /* no additional fields; this uses the layout for GSS_WITH_OPS. */
+};
+
+/* A statement with the invariant that
       stmt->code == GIMPLE_LABEL
    i.e. a label statement.
 
@@ -892,6 +906,14 @@ is_a_helper <gimple_statement_debug *>::test (gimple gs)
 template <>
 template <>
 inline bool
+is_a_helper <gimple_statement_goto *>::test (gimple gs)
+{
+  return gs->code == GIMPLE_GOTO;
+}
+
+template <>
+template <>
+inline bool
 is_a_helper <gimple_statement_label *>::test (gimple gs)
 {
   return gs->code == GIMPLE_LABEL;
@@ -1297,7 +1319,7 @@ gimple_cond gimple_build_cond (enum tree_code, tree, tree, tree, tree);
 gimple_cond gimple_build_cond_from_tree (tree, tree, tree);
 void gimple_cond_set_condition_from_tree (gimple_cond, tree);
 gimple_label gimple_build_label (tree label);
-gimple gimple_build_goto (tree dest);
+gimple_goto gimple_build_goto (tree dest);
 gimple gimple_build_nop (void);
 gimple_bind gimple_build_bind (tree, gimple_seq, tree);
 gimple gimple_build_asm_vec (const char *, vec<tree, va_gc> *,
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index f4d0e17..22e7f4b 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4304,7 +4304,7 @@ verify_gimple_return (gimple_return stmt)
    is a problem, otherwise false.  */
 
 static bool
-verify_gimple_goto (gimple stmt)
+verify_gimple_goto (gimple_goto stmt)
 {
   tree dest = gimple_goto_dest (stmt);
 
@@ -4504,7 +4504,7 @@ verify_gimple_stmt (gimple stmt)
 				       gimple_cond_rhs (stmt));
 
     case GIMPLE_GOTO:
-      return verify_gimple_goto (stmt);
+      return verify_gimple_goto (as_a <gimple_goto> (stmt));
 
     case GIMPLE_SWITCH:
       return verify_gimple_switch (as_a <gimple_switch> (stmt));
-- 
1.8.5.3

