aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-08-28 05:03:08 +0000
committerChris Lattner <sabre@nondot.org>2007-08-28 05:03:08 +0000
commitae3b701f59e78e058b83344be17206af3bf5d277 (patch)
tree87b0a4ecfab82336a35dbf9f4a367a878eda0767
parent36c4b0ec13453bc003bbac380770b45ae35ef19c (diff)
now that all the infrastructure is in place, enforce C99 6.8.5p3.
Note the FIXME: we need some way to mark a decl erroneous :) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41524 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Sema/SemaStmt.cpp15
-rw-r--r--include/clang/Basic/DiagnosticKinds.def2
-rw-r--r--test/Sema/for.c7
3 files changed, 20 insertions, 4 deletions
diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp
index 5b4be815c0..6247215f0e 100644
--- a/Sema/SemaStmt.cpp
+++ b/Sema/SemaStmt.cpp
@@ -453,10 +453,17 @@ Sema::ParseForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
Expr *Third = static_cast<Expr*>(third);
Stmt *Body = static_cast<Stmt*>(body);
- if (First) {
- // C99 6.8.5p3: FIXME. Need to hack Parser::ParseForStatement() and
- // declaration support to create a DeclStmt node. Once this is done,
- // we can test for DeclStmt vs. Expr (already a sub-class of Stmt).
+ if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
+ // C99 6.8.5p3: The declaration part of a 'for' statement shall only declare
+ // identifiers for objects having storage class 'auto' or 'register'.
+ for (Decl *D = DS->getDecl(); D; D = D->getNextDeclarator()) {
+ BlockVarDecl *BVD = dyn_cast<BlockVarDecl>(D);
+ if (BVD && !BVD->hasLocalStorage())
+ BVD = 0;
+ if (BVD == 0)
+ Diag(D->getLocation(), diag::err_non_variable_decl_in_for);
+ // FIXME: mark decl erroneous!
+ }
}
if (Second) {
DefaultFunctionArrayConversion(Second);
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 1ca8cf0b3a..d77fb77fa8 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -367,6 +367,8 @@ DIAG(err_expected_semi_after_expr, ERROR,
"expected ';' after expression")
DIAG(err_expected_semi_for, ERROR,
"expected ';' in 'for' statement specifier")
+DIAG(err_non_variable_decl_in_for, ERROR,
+ "declaration of non-local variable in 'for' loop")
DIAG(err_expected_colon_after, ERROR,
"expected ':' after %0")
DIAG(err_label_end_of_compound_statement, ERROR,
diff --git a/test/Sema/for.c b/test/Sema/for.c
new file mode 100644
index 0000000000..9004d9f41c
--- /dev/null
+++ b/test/Sema/for.c
@@ -0,0 +1,7 @@
+// RUN: clang -parse-ast-check %s
+
+// Check C99 6.8.5p3
+void b1 (void) { for (void (*f) (void);;); }
+void b2 (void) { for (void f (void);;); } // expected-error {{declaration of non-local variable}}
+void b3 (void) { for (static int f;;); } // expected-error {{declaration of non-local variable}}
+void b4 (void) { for (typedef int f;;); } // expected-error {{declaration of non-local variable}}