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:
parent
ce7d4fc8dd
commit
77c4d6c06a
|
@ -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.
|
||||
|
|
49
gcc/c-decl.c
49
gcc/c-decl.c
|
@ -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));
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 } */
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 } */
|
||||
}
|
Loading…
Reference in New Issue