c-decl.c (check_for_loop_decls): New function.

* c-decl.c (check_for_loop_decls): New function.
	* c-parse.in (for_init_stmt): New.
	(select_or_iter_stmt): Use for_init_stmt.
	* c-tree.h (check_for_loop_decls): New declaration.

testsuite:
	* gcc.dg/c90-fordecl-1.c, gcc.dg/c99-fordecl-1.c,
	gcc.dg/c99-fordecl-2.c: New tests.

From-SVN: r37549
This commit is contained in:
Joseph Myers 2000-11-18 23:18:36 +00:00 committed by Joseph Myers
parent ce7d4fc8dd
commit 77c4d6c06a
8 changed files with 153 additions and 9 deletions

View File

@ -1,3 +1,10 @@
2000-11-18 Joseph S. Myers <jsm28@cam.ac.uk>
* c-decl.c (check_for_loop_decls): New function.
* c-parse.in (for_init_stmt): New.
(select_or_iter_stmt): Use for_init_stmt.
* c-tree.h (check_for_loop_decls): New declaration.
2000-11-18 Neil Booth <neilb@earthling.net>
* cppinit.c: Update comments.

View File

@ -6924,6 +6924,55 @@ c_expand_body (fndecl, nested_p)
}
/* Check the declarations given in a for-loop for satisfying the C99
constraints. */
void
check_for_loop_decls ()
{
tree t;
if (!flag_isoc99)
{
/* If we get here, declarations have been used in a for loop without
the C99 for loop scope. This doesn't make much sense, so don't
allow it. */
error ("`for' loop initial declaration used outside C99 mode");
return;
}
/* C99 subclause 6.8.5 paragraph 3:
[#3] The declaration part of a for statement shall only
declare identifiers for objects having storage class auto or
register.
It isn't clear whether, in this sentence, "identifiers" binds to
"shall only declare" or to "objects" - that is, whether all identifiers
declared must be identifiers for objects, or whether the restriction
only applies to those that are. (A question on this in comp.std.c
in November 2000 received no answer.) We implement the strictest
interpretation, to avoid creating an extension which later causes
problems. */
for (t = gettags (); t; t = TREE_CHAIN (t))
{
if (TREE_PURPOSE (t) != 0)
error ("`%s %s' declared in `for' loop initial declaration",
(TREE_CODE (TREE_VALUE (t)) == RECORD_TYPE ? "struct"
: TREE_CODE (TREE_VALUE (t)) == UNION_TYPE ? "union"
: "enum"),
IDENTIFIER_POINTER (TREE_PURPOSE (t)));
}
for (t = getdecls (); t; t = TREE_CHAIN (t))
{
if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
error_with_decl (t, "declaration of non-variable `%s' in `for' loop initial declaration");
else if (TREE_STATIC (t))
error_with_decl (t, "declaration of static variable `%s' in `for' loop initial declaration");
else if (DECL_EXTERNAL (t))
error_with_decl (t, "declaration of `extern' variable `%s' in `for' loop initial declaration");
}
}
/* Save and restore the variables in this file and elsewhere
that keep track of the progress of compilation of the current function.
Used for nested functions. */

View File

@ -1868,19 +1868,18 @@ select_or_iter_stmt:
| do_stmt_start error
{ }
| FOR
'(' xexpr ';'
{ stmt_count++;
$3 = build_stmt (EXPR_STMT, $3);
$<ttype>$ = build_stmt (FOR_STMT, $3, NULL_TREE,
{ $<ttype>$ = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
add_stmt ($<ttype>$);
}
add_stmt ($<ttype>$); }
'(' for_init_stmt
{ stmt_count++;
RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
xexpr ';'
{ FOR_COND ($<ttype>5) = $6; }
{ FOR_COND ($<ttype>2) = $6; }
xexpr ')'
{ FOR_EXPR ($<ttype>5) = $9; }
{ FOR_EXPR ($<ttype>2) = $9; }
c99_block_lineno_labeled_stmt
{ RECHAIN_STMTS ($<ttype>5, FOR_BODY ($<ttype>5)); }
{ RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2)); }
| SWITCH '(' expr ')'
{ stmt_count++;
$<ttype>$ = c_start_case ($3); }
@ -1888,6 +1887,13 @@ select_or_iter_stmt:
{ c_finish_case (); }
;
for_init_stmt:
xexpr ';'
{ add_stmt (build_stmt (EXPR_STMT, $1)); }
| decl
{ check_for_loop_decls (); }
;
/* Parse a single real statement, not including any labels. */
stmt:
compstmt

View File

@ -170,6 +170,7 @@ extern tree build_enumerator PARAMS ((tree, tree));
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
extern int c_decode_option PARAMS ((int, char **));
extern void c_mark_varargs PARAMS ((void));
extern void check_for_loop_decls PARAMS ((void));
extern tree check_identifier PARAMS ((tree, tree));
extern void clear_parm_order PARAMS ((void));
extern tree combine_parm_decls PARAMS ((tree, tree, int));

View File

@ -1,3 +1,8 @@
2000-11-18 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/c90-fordecl-1.c, gcc.dg/c99-fordecl-1.c,
gcc.dg/c99-fordecl-2.c: New tests.
2000-11-18 Richard Henderson <rth@redhat.com>
* gcc.c-torture/execute/zerolen-1.c: Rename from 20001115-1.c.

View File

@ -0,0 +1,13 @@
/* Test for C99 declarations in for loops - rejection in C90 mode. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
void
foo (void)
{
int j = 0;
for (int i = 1; i <= 10; i++) /* { dg-bogus "warning" "warning in place of error" } */
j += i;
/* { dg-error "parse|decl" "declaration in for loop" { target *-*-* } 10 } */
}

View File

@ -0,0 +1,35 @@
/* Test for C99 declarations in for loops. */
/* 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)
{
int j = 0;
int i = -1;
for (int i = 1; i <= 10; i++)
j += i;
if (j != 55)
abort ();
if (i != -1)
abort ();
j = 0;
for (auto int i = 1; i <= 10; i++)
j += i;
if (j != 55)
abort ();
if (i != -1)
abort ();
j = 0;
for (register int i = 1; i <= 10; i++)
j += i;
if (j != 55)
abort ();
if (i != -1)
abort ();
exit (0);
}

View File

@ -0,0 +1,28 @@
/* Test for C99 declarations in for loops. Test constraints. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
void
foo (void)
{
/* See comments in check_for_loop_decls (c-decl.c) for the presumptions
behind these tests. */
int j = 0;
for (int i = 1, bar (void); i <= 10; i++) /* { dg-bogus "warning" "warning in place of error" } */
j += i;
/* { dg-error "bar" "function in for loop" { target *-*-* } 12 } */
for (static int i = 1; i <= 10; i++) /* { dg-bogus "warning" "warning in place of error" } */
j += i;
/* { dg-error "static" "static in for loop" { target *-*-* } 15 } */
for (extern int i; j <= 500; j++) /* { dg-bogus "warning" "warning in place of error" } */
j += 5;
/* { dg-error "extern" "extern in for loop" { target *-*-* } 18 } */
for (enum { FOO } i = FOO; i < 10; i++) /* { dg-bogus "warning" "warning in place of error" } */
j += i;
/* { dg-error "FOO" "enum value in for loop" { target *-*-* } 21 } */
for (enum BAR { FOO } i = FOO; i < 10; i++) /* { dg-bogus "warning" "warning in place of error" } */
j += i;
/* { dg-error "FOO" "enum value in for loop" { target *-*-* } 24 } */
/* { dg-error "BAR" "enum tag in for loop" { target *-*-* } 24 } */
}