+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.
}
\f
+/* 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");
+ }
+}
+\f
/* 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. */
| 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); }
{ 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
((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.
--- /dev/null
+/* 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 } */
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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 } */
+}