From 527f0080b0407487c0ed478b63989e443b112144 Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Thu, 9 Sep 1999 22:28:15 +0000
Subject: [PATCH] cp-tree.h (begin_switch_stmt): Adjust prototype.

* cp-tree.h (begin_switch_stmt): Adjust prototype.
	(finish_switch_cond): Likewise.
	* parse.y (simple_stmt): Adjust accordingly.
	* parse.c: Regenerated.
	* pt.c (tsubst_expr): Adjust accordingly.
	* semantics.c (expand_cond): New function.
	(FINISH_COND): New macro.
	(begin_switch_stmt): Build the SWITCH_STMT here.
	(finish_switch_stmt_cond): Not here.
	(expand_stmt): Adjust calls to begin_switch_stmt and
	finish_switch_cond.  Use expand_cond throughout.

From-SVN: r29246
---
 gcc/cp/ChangeLog                            | 12 ++++++++++++
 gcc/cp/cp-tree.h                            |  4 ++--
 gcc/cp/parse.c                              |  4 ++--
 gcc/cp/parse.y                              |  4 ++--
 gcc/cp/pt.c                                 |  4 ++--
 gcc/cp/semantics.c                          | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
 gcc/testsuite/g++.old-deja/g++.pt/switch1.C | 15 +++++++++++++++
 7 files changed, 99 insertions(+), 37 deletions(-)
 create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/switch1.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 399a3d4..49c585d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,17 @@
 1999-09-09  Mark Mitchell  <mark@codesourcery.com>
 
+	* cp-tree.h (begin_switch_stmt): Adjust prototype.
+	(finish_switch_cond): Likewise.
+	* parse.y (simple_stmt): Adjust accordingly.
+	* parse.c: Regenerated.
+	* pt.c (tsubst_expr): Adjust accordingly.
+	* semantics.c (expand_cond): New function.
+	(FINISH_COND): New macro.
+	(begin_switch_stmt): Build the SWITCH_STMT here.
+	(finish_switch_stmt_cond): Not here.
+	(expand_stmt): Adjust calls to begin_switch_stmt and
+	finish_switch_cond.  Use expand_cond throughout.
+
 	* dump.c (dequeue_and_dump): Dump types for constants.
 	Describe DECL_ARG_TYPE more intuitively.
 	Handle ARRAY_REF.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 04f26c2..c8fc430 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3572,8 +3572,8 @@ extern void finish_for_expr                     PROTO((tree, tree));
 extern void finish_for_stmt                     PROTO((tree, tree));
 extern void finish_break_stmt                   PROTO((void));
 extern void finish_continue_stmt                PROTO((void));
-extern void begin_switch_stmt                   PROTO((void));
-extern tree finish_switch_cond                  PROTO((tree));
+extern tree begin_switch_stmt                   PROTO((void));
+extern void finish_switch_cond                  PROTO((tree, tree));
 extern void finish_switch_stmt                  PROTO((tree, tree));
 extern void finish_case_label                   PROTO((tree, tree));
 extern void finish_goto_stmt                    PROTO((tree));
diff --git a/gcc/cp/parse.c b/gcc/cp/parse.c
index 0283e62..76c762a 100644
--- a/gcc/cp/parse.c
+++ b/gcc/cp/parse.c
@@ -7623,11 +7623,11 @@ case 738:
     break;}
 case 739:
 #line 3277 "parse.y"
-{ begin_switch_stmt (); ;
+{ yyval.ttype = begin_switch_stmt (); ;
     break;}
 case 740:
 #line 3279 "parse.y"
-{ yyval.ttype = finish_switch_cond (yyvsp[-1].ttype); ;
+{ finish_switch_cond (yyvsp[-1].ttype, yyvsp[-3].ttype); ;
     break;}
 case 741:
 #line 3281 "parse.y"
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 76b8830..1b1c8b5 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -3274,9 +3274,9 @@ simple_stmt:
 	  already_scoped_stmt
                 { finish_for_stmt ($9, $<ttype>2); }
 	| SWITCH 
-                { begin_switch_stmt (); }
+                { $<ttype>$ = begin_switch_stmt (); }
 	    '(' condition ')'
-                { $<ttype>$ = finish_switch_cond ($4); }
+                { finish_switch_cond ($4, $<ttype>2); }
 	  implicitly_scoped_stmt
                 { finish_switch_stmt ($4, $<ttype>6); }
 	| CASE expr_no_commas ':'
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index feb7f76..0795a19 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7392,9 +7392,9 @@ tsubst_expr (t, args, complain, in_decl)
 	tree val;
 
 	lineno = STMT_LINENO (t);
-	begin_switch_stmt ();
+	stmt = begin_switch_stmt ();
 	val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
-	stmt = finish_switch_cond (val);
+	finish_switch_cond (val, stmt);
 	tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
 	finish_switch_stmt (val, stmt);
       }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 38eab3b..4d6a234 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -44,6 +44,7 @@
 static void expand_stmts PROTO((tree));
 static void do_pushlevel PROTO((void));
 static tree do_poplevel PROTO((void));
+static tree expand_cond PROTO((tree));
 
 /* When parsing a template, LAST_TREE contains the last statement
    parsed.  These are chained together through the TREE_CHAIN field,
@@ -64,6 +65,16 @@ static tree do_poplevel PROTO((void));
 #define RECHAIN_STMTS_FROM_CHAIN(stmt, substmt)	\
   RECHAIN_STMTS (stmt, substmt, TREE_CHAIN (stmt))
 
+/* Finish processing the COND, the SUBSTMT condition for STMT.  */
+
+#define FINISH_COND(cond, stmt, substmt) 	\
+  do {						\
+    if (last_tree != stmt)			\
+      RECHAIN_STMTS_FROM_LAST (stmt, substmt);	\
+    else					\
+      substmt = cond;				\
+  } while (0)
+  
 /* Finish an expression-statement, whose EXPRESSION is as indicated.  */
 
 void 
@@ -492,49 +503,51 @@ finish_continue_stmt ()
     cp_error ("continue statement not within a loop");   
 }
 
-/* Begin a switch-statement.  */
+/* Begin a switch-statement.  Returns a new SWITCH_STMT if
+   appropriate.  */
 
-void
+tree
 begin_switch_stmt ()
 {
+  tree r;
+
+  if (building_stmt_tree ())
+    {
+      r = build_min_nt (SWITCH_STMT, NULL_TREE, NULL_TREE);
+      add_tree (r);
+    }
+  else
+    r = NULL_TREE;
+
   do_pushlevel ();
+
+  return r;
 }
 
-/* Finish the cond of a switch-statement.  Returns a new
-   SWITCH_STMT if appropriate.  */ 
+/* Finish the cond of a switch-statement.  */
 
-tree
-finish_switch_cond (cond)
+void
+finish_switch_cond (cond, switch_stmt)
      tree cond;
+     tree switch_stmt;
 {
-  tree r;
-
   if (building_stmt_tree ())
-    {
-      r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
-      add_tree (r);
-    }
+    FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
   else if (cond != error_mark_node)
     {
       emit_line_note (input_filename, lineno);
       c_expand_start_case (cond);
-      r = NULL_TREE;
     }
   else
-    {
-      /* The code is in error, but we don't want expand_end_case to
-         crash. */
-      c_expand_start_case (boolean_false_node);
-      r = NULL_TREE;
-    }
+    /* The code is in error, but we don't want expand_end_case to
+       crash. */
+    c_expand_start_case (boolean_false_node);
 
   push_switch ();
 
   /* Don't let the tree nodes for COND be discarded by
      clear_momentary during the parsing of the next stmt.  */
   push_momentary ();
-
-  return r;
 }
 
 /* Finish the body of a switch-statement, which may be given by
@@ -1963,6 +1976,24 @@ finish_stmt_tree (fn)
   DECL_SAVED_TREE (fn) = TREE_CHAIN (DECL_SAVED_TREE (fn));
 }
 
+/* Some statements, like for-statements or if-statements, require a
+   condition.  This condition can be a declaration.  If T is such a
+   declaration it is processed, and an expression appropriate to use
+   as the condition is returned.  Otherwise, T itself is returned.  */
+
+static tree
+expand_cond (t)
+     tree t;
+{
+  if (t && TREE_CODE (t) == DECL_STMT)
+    {
+      expand_stmt (t);
+      return convert_from_reference (DECL_STMT_DECL (t));
+    }
+  else 
+    return t;
+}
+
 /* Generate RTL for the chain of statements T.  */
 
 static void 
@@ -2038,7 +2069,7 @@ expand_stmt (t)
 	for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
 	  expand_stmt (tmp);
 	finish_for_init_stmt (NULL_TREE);
-	finish_for_cond (FOR_COND (t), NULL_TREE);
+	finish_for_cond (expand_cond (FOR_COND (t)), NULL_TREE);
 	tmp = FOR_EXPR (t);
 	finish_for_expr (tmp, NULL_TREE);
 	expand_stmt (FOR_BODY (t));
@@ -2050,7 +2081,7 @@ expand_stmt (t)
       {
 	lineno = STMT_LINENO (t);
 	begin_while_stmt ();
-	finish_while_stmt_cond (WHILE_COND (t), NULL_TREE);
+	finish_while_stmt_cond (expand_cond (WHILE_COND (t)), NULL_TREE);
 	expand_stmt (WHILE_BODY (t));
 	finish_while_stmt (NULL_TREE);
       }
@@ -2069,7 +2100,7 @@ expand_stmt (t)
     case IF_STMT:
       lineno = STMT_LINENO (t);
       begin_if_stmt ();
-      finish_if_stmt_cond (IF_COND (t), NULL_TREE);
+      finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE);
       if (THEN_CLAUSE (t))
 	{
 	  expand_stmt (THEN_CLAUSE (t));
@@ -2102,12 +2133,16 @@ expand_stmt (t)
       break;
 
     case SWITCH_STMT:
-      lineno = STMT_LINENO (t);
-      begin_switch_stmt ();
-      finish_switch_cond (SWITCH_COND (t));
-      if (TREE_OPERAND (t, 1))
+      {
+	tree cond;
+
+	lineno = STMT_LINENO (t);
+	begin_switch_stmt ();
+	cond = expand_cond (SWITCH_COND (t));
+	finish_switch_cond (cond, NULL_TREE);
 	expand_stmt (SWITCH_BODY (t));
-      finish_switch_stmt (SWITCH_COND (t), NULL_TREE);
+	finish_switch_stmt (cond, NULL_TREE);
+      }
       break;
 
     case CASE_LABEL:
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/switch1.C b/gcc/testsuite/g++.old-deja/g++.pt/switch1.C
new file mode 100644
index 0000000..51d2de1
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/switch1.C
@@ -0,0 +1,15 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+template <class T>
+void f ()
+{
+  int i;
+  
+  switch (int i = 3) {
+  }
+}
+
+template void f<int>();
+
+
--
libgit2 0.26.0