Commit 77c4d6c0 by Joseph Myers Committed by Joseph Myers

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
parent ce7d4fc8
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.
......
......@@ -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. */
......
......@@ -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
......
......@@ -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));
......
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.
......
/* 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 } */
}
/* 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);
}
/* 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 } */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment