diff options
author | Joseph Myers <jsm28@cam.ac.uk> | 2000-11-18 23:18:36 +0000 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2000-11-18 23:18:36 +0000 |
commit | 77c4d6c06a83f7d86471befb76a1be433dc2e3a3 (patch) | |
tree | b4a745279c572b08d93715d1c76a506422218e89 | |
parent | ce7d4fc8dd42a1885bc22d1c720c6c94314acad1 (diff) | |
download | gcc-77c4d6c06a83f7d86471befb76a1be433dc2e3a3.zip gcc-77c4d6c06a83f7d86471befb76a1be433dc2e3a3.tar.gz gcc-77c4d6c06a83f7d86471befb76a1be433dc2e3a3.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/c-decl.c | 49 | ||||
-rw-r--r-- | gcc/c-parse.in | 24 | ||||
-rw-r--r-- | gcc/c-tree.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c90-fordecl-1.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c99-fordecl-1.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/c99-fordecl-2.c | 28 |
8 files changed, 153 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e5850e..e80a489 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 8d66b4e..d97419d 100644 --- a/gcc/c-decl.c +++ b/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. */ diff --git a/gcc/c-parse.in b/gcc/c-parse.in index ae47466..517b488 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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 diff --git a/gcc/c-tree.h b/gcc/c-tree.h index efd5083..669c89b 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -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)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6b0dcaa..78eb81f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/gcc.dg/c90-fordecl-1.c b/gcc/testsuite/gcc.dg/c90-fordecl-1.c new file mode 100644 index 0000000..8e48dd6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c90-fordecl-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 } */ +} diff --git a/gcc/testsuite/gcc.dg/c99-fordecl-1.c b/gcc/testsuite/gcc.dg/c99-fordecl-1.c new file mode 100644 index 0000000..faaab1e --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-fordecl-1.c @@ -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); +} diff --git a/gcc/testsuite/gcc.dg/c99-fordecl-2.c b/gcc/testsuite/gcc.dg/c99-fordecl-2.c new file mode 100644 index 0000000..0ef11f6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-fordecl-2.c @@ -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 } */ +} |