From b6bbe4a726fdfc970a77bca7fe7eeb31d30eb556 Mon Sep 17 00:00:00 2001
From: rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Wed, 16 Jun 2004 23:05:37 +0000
Subject: [PATCH]         * c-parse.in (if_stmt_locus): Remove.        
 (if_prefix): Increment stmt_count; pass it to c_finish_if_cond.        
 (select_or_iter_stmt): Move empty if warnings to c-typeck.c.         *
 c-typeck.c (if_elt): Sort by expected size.  Rename locus to        
 empty_locus.  Add stmt_count, saw_else.         (c_begin_if_stmt): Push
 if_stack here.         (c_finish_if_cond): Rename from c_expand_end_cond. 
 Record stmt_count.         (c_finish_then, c_finish_else): Record
 empty_locus.         (c_begin_else): Rename from c_expand_start_else.  Record
 stmt_count.         (c_finish_if_stmt): Rename from c_expand_end_cond.  Warn
 for empty         if or else body.         * c-tree.h: Update prototypes.
 testsuite/         * gcc.dg/20001116-1.c: Move expected warning line.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83274 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                     | 15 +++++
 gcc/c-parse.in                    | 62 ++++++---------------
 gcc/c-tree.h                      |  8 +--
 gcc/c-typeck.c                    | 92 ++++++++++++++++++-------------
 gcc/testsuite/ChangeLog           |  4 ++
 gcc/testsuite/gcc.dg/20001116-1.c |  4 +-
 6 files changed, 96 insertions(+), 89 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7745ee927eb4..50bfa931162f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2004-06-16  Richard Henderson  <rth@redhat.com>
+
+	* c-parse.in (if_stmt_locus): Remove.
+	(if_prefix): Increment stmt_count; pass it to c_finish_if_cond.
+	(select_or_iter_stmt): Move empty if warnings to c-typeck.c.
+	* c-typeck.c (if_elt): Sort by expected size.  Rename locus to
+	empty_locus.  Add stmt_count, saw_else.
+	(c_begin_if_stmt): Push if_stack here.
+	(c_finish_if_cond): Rename from c_expand_end_cond.  Record stmt_count.
+	(c_finish_then, c_finish_else): Record empty_locus.
+	(c_begin_else): Rename from c_expand_start_else.  Record stmt_count.
+	(c_finish_if_stmt): Rename from c_expand_end_cond.  Warn for empty
+	if or else body.
+	* c-tree.h: Update prototypes.
+
 2004-06-16  Steven Bosscher  <stevenb@suse.de>
 
 	* tree.h (PHI_CHAIN): New.
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index 147dbc009f40..8b8f6db86e39 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -259,11 +259,6 @@ do {									\
 static int stmt_count;
 static int compstmt_count;
 
-/* Input location of the end of the body of last simple_if;
-   used by the stmt-rule immediately after simple_if returns.  */
-static location_t if_stmt_locus;
-
-
 /* List of types and structure classes of the current declaration.  */
 static GTY(()) tree current_declspecs;
 static GTY(()) tree prefix_attributes;
@@ -2068,34 +2063,25 @@ compstmt: compstmt_start compstmt_nostart
 		  $$ = NULL_TREE; }
 	;
 
-/* Value is number of statements counted as of the closeparen.  */
-simple_if:
-	  if_prefix c99_block_lineno_labeled_stmt
-                { c_finish_then ($2); }
-/* Make sure c_expand_end_cond is run once
-   for each call to c_expand_start_cond.
-   Otherwise a crash is likely.  */
-	| if_prefix error
-	;
-
 if_prefix:
-	  /* We must build the IF_STMT node before parsing its
-	     condition so that EXPR_LOCUS refers to the line
-	     containing the "if", and not the line containing
-	     the close-parenthesis.
-
-	     c_begin_if_stmt returns the IF_STMT node, which
-	     we later pass to c_expand_start_cond to fill
-	     in the condition and other tidbits.  */
+	  /* We must build the if statement node before parsing its
+	     condition so that we get its location pointing to the
+	     line containing the "if", and not the line containing
+	     the close-parenthesis.  */
           IF
                 { $<ttype>$ = c_begin_if_stmt (); }
             '(' expr ')'
-		{ c_expand_start_cond (lang_hooks.truthvalue_conversion ($4),
-				       compstmt_count,$<ttype>2);
-		  $<itype>$ = stmt_count;
-		  if_stmt_locus = $<location>-1; }
+		{ c_finish_if_cond ($4, compstmt_count, ++stmt_count); }
         ;
 
+simple_if:
+	  if_prefix c99_block_lineno_labeled_stmt
+                { c_finish_then ($2); }
+	/* Make sure c_finish_if_stmt is run for each call to
+	   c_begin_if_stmt.  Otherwise a crash is likely.  */
+	| if_prefix error
+	;
+
 /* This is a subroutine of stmt.
    It is used twice, once for valid DO statements
    and once for catching errors in parsing the end test.  */
@@ -2172,27 +2158,13 @@ lineno_label:
 
 select_or_iter_stmt:
 	  simple_if ELSE
-		{ c_expand_start_else ();
-		  $<itype>1 = stmt_count; }
+		{ c_begin_else (stmt_count); }
 	  c99_block_lineno_labeled_stmt
-                { c_finish_else ($4);
-		  c_expand_end_cond ();
-		  if (extra_warnings && stmt_count == $<itype>1)
-		    warning ("empty body in an else-statement"); }
+                { c_finish_else ($4); c_finish_if_stmt (stmt_count); }
 	| simple_if %prec IF
-		{ c_expand_end_cond ();
-		  /* This warning is here instead of in simple_if, because we
-		     do not want a warning if an empty if is followed by an
-		     else statement.  Increment stmt_count so we don't
-		     give a second error if this is a nested `if'.  */
-		  if (extra_warnings && stmt_count++ == $<itype>1)
-		    warning ("%Hempty body in an if-statement",
-                             &if_stmt_locus); }
-/* Make sure c_expand_end_cond is run once
-   for each call to c_expand_start_cond.
-   Otherwise a crash is likely.  */
+		{ c_finish_if_stmt (stmt_count); }
 	| simple_if ELSE error
-		{ c_expand_end_cond (); }
+		{ c_finish_if_stmt (stmt_count + 1); }
        /* We must build the WHILE_STMT node before parsing its
 	  condition so that EXPR_LOCUS refers to the line
 	  containing the "while", and not the line containing
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index b311bb3e205c..031883e95fb6 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -256,12 +256,12 @@ extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
 extern int c_types_compatible_p (tree, tree);
 extern tree c_begin_compound_stmt (bool);
 extern tree c_end_compound_stmt (tree, bool);
-extern void c_expand_start_cond (tree, int, tree);
+extern tree c_begin_if_stmt (void);
+extern void c_finish_if_cond (tree, int, int);
 extern void c_finish_then (tree);
-extern void c_expand_start_else (void);
+extern void c_begin_else (int);
 extern void c_finish_else (tree);
-extern void c_expand_end_cond (void);
-extern tree c_begin_if_stmt (void);
+extern void c_finish_if_stmt (int);
 extern tree c_begin_while_stmt (void);
 extern void c_finish_while_stmt_cond (tree, tree);
 extern void c_finish_while_stmt (tree, tree);
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 32bf24a41939..7433c51a62ef 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -6467,10 +6467,12 @@ c_finish_case (tree body)
    the enclosing if statement does not have an else branch.  */
 typedef struct
 {
-  int compstmt_count;
-  location_t locus;
-  int needs_warning;
   tree if_stmt;
+  location_t empty_locus;
+  int compstmt_count;
+  int stmt_count;
+  unsigned int needs_warning : 1;
+  unsigned int saw_else : 1;
 } if_elt;
 
 static if_elt *if_stack;
@@ -6488,22 +6490,8 @@ tree
 c_begin_if_stmt (void)
 {
   tree r;
-  r = add_stmt (build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE));
-  return r;
-}
-
-/* Record the start of an if-then, and record the start of it
-   for ambiguous else detection.
-
-   COND is the condition for the if-then statement.
+  if_elt *elt;
 
-   IF_STMT is the statement node that has already been created for
-   this if-then statement.  It is created before parsing the
-   condition to keep line number information accurate.  */
-
-void
-c_expand_start_cond (tree cond, int compstmt_count, tree if_stmt)
-{
   /* Make sure there is enough space on the stack.  */
   if (if_stack_space == 0)
     {
@@ -6516,42 +6504,47 @@ c_expand_start_cond (tree cond, int compstmt_count, tree if_stmt)
       if_stack = xrealloc (if_stack, if_stack_space * sizeof (if_elt));
     }
 
-  IF_COND (if_stmt) = cond;
+  r = add_stmt (build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE));
 
   /* Record this if statement.  */
-  if_stack[if_stack_pointer].compstmt_count = compstmt_count;
-  if_stack[if_stack_pointer].locus = input_location;
-  if_stack[if_stack_pointer].needs_warning = 0;
-  if_stack[if_stack_pointer].if_stmt = if_stmt;
-  if_stack_pointer++;
+  elt = &if_stack[if_stack_pointer++];
+  memset (elt, 0, sizeof (*elt));
+  elt->if_stmt = r;
 }
 
-/* Called after the then-clause for an if-statement is processed.  */
+/* Record the start of an if-then, and record the start of it
+   for ambiguous else detection.
+
+   COND is the condition for the if-then statement.
+
+   IF_STMT is the statement node that has already been created for
+   this if-then statement.  It is created before parsing the
+   condition to keep line number information accurate.  */
 
 void
-c_finish_then (tree then_stmt)
+c_finish_if_cond (tree cond, int compstmt_count, int stmt_count)
 {
-  tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
-  THEN_CLAUSE (if_stmt) = then_stmt;
+  if_elt *elt = &if_stack[if_stack_pointer - 1];
+  elt->compstmt_count = compstmt_count;
+  elt->stmt_count = stmt_count;
+  IF_COND (elt->if_stmt) = lang_hooks.truthvalue_conversion (cond);
 }
 
-/* Record the end of an if-then.  Optionally warn if a nested
-   if statement had an ambiguous else clause.  */
+/* Called after the then-clause for an if-statement is processed.  */
 
 void
-c_expand_end_cond (void)
+c_finish_then (tree then_stmt)
 {
-  if_stack_pointer--;
-  if (if_stack[if_stack_pointer].needs_warning)
-    warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
-	     &if_stack[if_stack_pointer].locus);
+  if_elt *elt = &if_stack[if_stack_pointer - 1];
+  THEN_CLAUSE (elt->if_stmt) = then_stmt;
+  elt->empty_locus = input_location;
 }
 
 /* Called between the then-clause and the else-clause
    of an if-then-else.  */
 
 void
-c_expand_start_else (void)
+c_begin_else (int stmt_count)
 {
   /* An ambiguous else warning must be generated for the enclosing if
      statement, unless we see an else branch for that one, too.  */
@@ -6566,6 +6559,7 @@ c_expand_start_else (void)
      case.  Also don't warn for any if statements nested in this else.  */
   if_stack[if_stack_pointer - 1].needs_warning = 0;
   if_stack[if_stack_pointer - 1].compstmt_count--;
+  if_stack[if_stack_pointer - 1].saw_else = 1;
 }
 
 /* Called after the else-clause for an if-statement is processed.  */
@@ -6573,8 +6567,30 @@ c_expand_start_else (void)
 void
 c_finish_else (tree else_stmt)
 {
-  tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
-  ELSE_CLAUSE (if_stmt) = else_stmt;
+  if_elt *elt = &if_stack[if_stack_pointer - 1];
+  ELSE_CLAUSE (elt->if_stmt) = else_stmt;
+  elt->empty_locus = input_location;
+}
+
+/* Record the end of an if-then.  Optionally warn if a nested
+   if statement had an ambiguous else clause.  */
+
+void
+c_finish_if_stmt (int stmt_count)
+{
+  if_elt *elt = &if_stack[--if_stack_pointer];
+
+  if (elt->needs_warning)
+    warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
+	     EXPR_LOCUS (elt->if_stmt));
+
+  if (extra_warnings && stmt_count == elt->stmt_count)
+    {
+      if (elt->saw_else)
+	warning ("%Hempty body in an else-statement", &elt->empty_locus);
+      else
+	warning ("%Hempty body in an if-statement", &elt->empty_locus);
+    }
 }
 
 /* Begin a while statement.  Returns a newly created WHILE_STMT if
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bee3c1ed0d6b..286cbb605750 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-06-15  Richard Henderson  <rth@redhat.com>
+
+	* gcc.dg/20001116-1.c: Move expected warning line.
+
 2004-06-15  Richard Henderson  <rth@redhat.com>
 
 	* gcc.dg/i386-ssetype-1.c: Remove XFAIL.
diff --git a/gcc/testsuite/gcc.dg/20001116-1.c b/gcc/testsuite/gcc.dg/20001116-1.c
index 5833dd8b1610..155cfe639624 100644
--- a/gcc/testsuite/gcc.dg/20001116-1.c
+++ b/gcc/testsuite/gcc.dg/20001116-1.c
@@ -6,6 +6,6 @@
 
 void foo (int x)
 {
-  if (x)	/* { dg-warning "empty body in an if-statement" } */
-    ;
+  if (x)
+    ;	/* { dg-warning "empty body in an if-statement" } */
 }
-- 
GitLab