This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch for C99 new scopes


This patch adds the new C99 block scopes for selection and iteration
statements (in C99, each selection or iteration statement gets its own
scope, as do its substatements, so for example "if (foo) bar; else
baz;" means "{ if (foo) { bar; } else { baz; } }").  It should make no
difference to programs in C90 (default) mode, but is needed for a
couple of C99 features as well as for obscure testcases.

Bootstrapped with no regressions on i686-pc-linux-gnu, including a
bootstrap with -std=gnu99 in BOOT_CFLAGS.  This patch adds no new
parser conflicts.  OK to commit?

gcc/ChangeLog:
2000-11-05  Joseph S. Myers  <jsm28@cam.ac.uk>

	* c-parse.in (c99_block_start, c99_block_end,
	c99_block_lineno_labeled_stmt): New.
	(simple_if, do_stmt_start): Use c99_block_lineno_labeled_stmt.
	(stmt): Split off selection and iteration statements into...
	(select_or_iter_stmt): New.  Use c99_block_lineno_labeled_stmt.

gcc/testsuite/ChangeLog:
2000-11-05  Joseph S. Myers  <jsm28@cam.ac.uk>

	* gcc.dg/c99-scope-1.c: Remove xfail.
	* gcc.dg/c99-scope-2.c: New test.

--- c-parse.in.orig	Sat Nov  4 21:33:00 2000
+++ c-parse.in	Sun Nov  5 14:56:53 2000
@@ -176,6 +176,7 @@ end ifc
 %type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
 %type <ttype> do_stmt_start poplevel

+%type <ttype> c99_block_start c99_block_end
 %type <ttype> declarator
 %type <ttype> notype_declarator after_type_declarator
 %type <ttype> parm_declarator
@@ -1615,6 +1616,40 @@ end ifobjc
 poplevel:  /* empty */
                 { $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }

+/* Start and end blocks created for the new scopes of C99.  */
+c99_block_start: /* empty */
+		{ if (flag_isoc99)
+		    {
+		      $$ = c_begin_compound_stmt ();
+		      pushlevel (0);
+		      clear_last_expr ();
+		      add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
+ifobjc
+		      if (objc_method_context)
+			add_objc_decls ();
+end ifobjc
+		    }
+		  else
+		    $$ = NULL_TREE;
+		}
+	;
+
+/* Productions using c99_block_start and c99_block_end will need to do what's
+   in compstmt: RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); $$ = $2; where
+   $1 is the value of c99_block_start and $2 of c99_block_end.  */
+c99_block_end: /* empty */
+                { if (flag_isoc99)
+		    {
+		      tree scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
+		      $$ = poplevel (kept_level_p (), 0, 0);
+		      SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
+			= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
+			= $$;
+		    }
+		  else
+		    $$ = NULL_TREE; }
+	;
+
 /* Read zero or more forward-declarations for labels
    that nested functions can jump to.  */
 maybe_label_decls:
@@ -1695,7 +1730,7 @@ compstmt: compstmt_start compstmt_nostar

 /* Value is number of statements counted as of the closeparen.  */
 simple_if:
-	  if_prefix lineno_labeled_stmt
+	  if_prefix c99_block_lineno_labeled_stmt
                 { c_finish_then (); }
 /* Make sure c_expand_end_cond is run once
    for each call to c_expand_start_cond.
@@ -1727,7 +1762,7 @@ do_stmt_start:
 		     condition now.  Otherwise, we can get crashes at
 		     RTL-generation time.  */
 		  DO_COND ($<ttype>$) = error_mark_node; }
-	  lineno_labeled_stmt WHILE
+	  c99_block_lineno_labeled_stmt WHILE
 		{ $$ = $<ttype>2;
 		  RECHAIN_STMTS ($$, DO_BODY ($$)); }
 	;
@@ -1757,6 +1792,13 @@ lineno_labeled_stmt:
 		{ }
 	;

+/* Like lineno_labeled_stmt, but a block in C99.  */
+c99_block_lineno_labeled_stmt:
+	  c99_block_start lineno_labeled_stmt c99_block_end
+		{ if (flag_isoc99)
+		    RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); }
+	;
+
 lineno_stmt_or_label:
 	  save_filename save_lineno stmt_or_label
 		{ $$ = $3; }
@@ -1769,17 +1811,11 @@ stmt_or_label:
 		{ $$ = 1; }
 	;

-/* Parse a single real statement, not including any labels.  */
-stmt:
-	  compstmt
-		{ stmt_count++; }
-	| expr ';'
-		{ stmt_count++;
-		  c_expand_expr_stmt ($1); }
-	| simple_if ELSE
+select_or_iter_stmt:
+	  simple_if ELSE
 		{ c_expand_start_else ();
 		  $<itype>1 = stmt_count; }
-	  lineno_labeled_stmt
+	  c99_block_lineno_labeled_stmt
                 { c_finish_else ();
 		  c_expand_end_cond ();
 		  if (extra_warnings && stmt_count == $<itype>1)
@@ -1804,7 +1840,7 @@ stmt:
                 { $4 = truthvalue_conversion ($4);
 		  $<ttype>$
 		    = add_stmt (build_stmt (WHILE_STMT, $4, NULL_TREE)); }
-	  lineno_labeled_stmt
+	  c99_block_lineno_labeled_stmt
 		{ RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
 	| do_stmt_start
 	  '(' expr ')' ';'
@@ -1823,13 +1859,25 @@ stmt:
                 { FOR_COND ($<ttype>5) = $6; }
 	  xexpr ')'
 		{ FOR_EXPR ($<ttype>5) = $9; }
-	  lineno_labeled_stmt
+	  c99_block_lineno_labeled_stmt
                 { RECHAIN_STMTS ($<ttype>5, FOR_BODY ($<ttype>5)); }
 	| SWITCH '(' expr ')'
 		{ stmt_count++;
 		  $<ttype>$ = c_start_case ($3); }
-	  lineno_labeled_stmt
+	  c99_block_lineno_labeled_stmt
                 { c_finish_case (); }
+	;
+
+/* Parse a single real statement, not including any labels.  */
+stmt:
+	  compstmt
+		{ stmt_count++; }
+	| expr ';'
+		{ stmt_count++;
+		  c_expand_expr_stmt ($1); }
+	| c99_block_start select_or_iter_stmt c99_block_end
+		{ if (flag_isoc99)
+		    RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); }
 	| BREAK ';'
 	        { stmt_count++;
 		  add_stmt (build_break_stmt ()); }
--- testsuite/gcc.dg/c99-scope-1.c.orig	Thu Aug 10 08:16:09 2000
+++ testsuite/gcc.dg/c99-scope-1.c	Sun Nov  5 17:18:09 2000
@@ -1,6 +1,6 @@
 /* Test for new block scopes in C99.  Inspired by C99 Rationale (N897).  */
 /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
-/* { dg-do run { xfail *-*-* } } */
+/* { dg-do run } */
 /* { dg-options "-std=iso9899:1999 -pedantic-errors" } */

 struct foo {
--- testsuite/gcc.dg/c99-scope-2.c.orig	Fri Sep 11 11:31:59 1998
+++ testsuite/gcc.dg/c99-scope-2.c	Sun Nov  5 17:37:44 2000
@@ -0,0 +1,71 @@
+/* Test for new block scopes in C99.  Test for each new scope.  */
+/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
+/* { dg-do run } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+  struct foo { int i0; };
+  int a, b, c, d;
+  a = sizeof (struct foo);
+  if (b = sizeof (struct foo { int i0; int i1; }))
+    c = sizeof (struct foo { int i0; int i1; int i2; });
+  if (!(a < b && b < c))
+    abort ();
+  if ((b = sizeof (struct foo { int i0; int i1; })), 0)
+    c = sizeof (struct foo { int i0; int i1; int i2; });
+  else
+    d = sizeof (struct foo { int i0; int i1; int i2; int i3; });
+  if (!(a < b && b < d))
+    abort ();
+  switch (b = sizeof (struct foo { int i0; int i1; }))
+    default:
+      c = sizeof (struct foo { int i0; int i1; int i2; });
+  if (!(a < b && b < c))
+    abort ();
+  do
+    c = sizeof (struct foo { int i0; int i1; int i2; });
+  while ((b = sizeof (struct foo { int i0; int i1; })), 0);
+  if (!(a < b && b < c))
+    abort ();
+  d = 1;
+  while ((b = sizeof (struct foo { int i0; int i1; })), d)
+    (c = sizeof (struct foo { int i0; int i1; int i2; })), d--;
+  if (!(a < b && b < c))
+    abort ();
+  d = 1;
+  for ((b = sizeof (struct foo { int i0; int i1; })); d; d--)
+    c = sizeof (struct foo { int i0; int i1; int i2; });
+  if (!(a < b && b < c))
+    abort ();
+  d = 1;
+  for ((b = sizeof (struct foo { int i0; int i1; })); d; d--)
+    c = sizeof (struct foo);
+  if (!(a < b && b == c))
+    abort ();
+  d = 1;
+  for (; (b = sizeof (struct foo { int i0; int i1; })), d; d--)
+    c = sizeof (struct foo { int i0; int i1; int i2; });
+  if (!(a < b && b < c))
+    abort ();
+  d = 1;
+  for (; (b = sizeof (struct foo { int i0; int i1; })), d; d--)
+    c = sizeof (struct foo);
+  if (!(a < b && b == c))
+    abort ();
+  d = 1;
+  for (; d; (b = sizeof (struct foo { int i0; int i1; })), d--)
+    c = sizeof (struct foo { int i0; int i1; int i2; });
+  if (!(a < b && b < c))
+    abort ();
+  d = 1;
+  for (; d; (b = sizeof (struct foo { int i0; int i1; })), d--)
+    c = sizeof (struct foo);
+  if (!(a < b && b == c))
+    abort ();
+  exit (0);
+}

-- 
Joseph S. Myers
jsm28@cam.ac.uk


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]