Hi rsmith, hfinkel,
According to the C11 standard, `_Static_assert` should be allowed as clause-1
in a for loop.
For example:
```
for (_Static_assert(1, "1 is nonzero");;) {}
```
The relevant section of the C11 grammar is:
//for ( declaration expressionopt ; expressionopt ) statement
declaration:
declaration-specifiers init-declarator-listopt ;
static_assert-declaration//
It is not allowed in C++11, where the for statement has the form:
//for ( for-init-statement conditionopt; expressionopt) statement//
and for-init-statement can only be an //expression-statement// or a
//simple-declaration//, not a //static_assert-declaration//
http://reviews.llvm.org/D9113
Files:
include/clang/Parse/Parser.h
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseStmt.cpp
lib/Sema/SemaStmt.cpp
test/Parser/static-assert.c
test/Parser/static-assert.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1803,7 +1803,7 @@
/// isForInitDeclaration - Disambiguates between a declaration or an
/// expression in the context of the C 'clause-1' or the C++
// 'for-init-statement' part of a 'for' statement.
- /// Returns true for declaration, false for expression.
+ /// Returns true for C declaration or C++ simple-declaration, false otherwise
bool isForInitDeclaration() {
if (getLangOpts().CPlusPlus)
return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/true);
@@ -2275,7 +2275,8 @@
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none,
Decl **OwnedType = nullptr);
- Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
+ Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd,
+ bool RequireSemi = true);
Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
SourceLocation &DeclEnd);
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -684,7 +684,8 @@
/// [C11] static_assert-declaration:
/// _Static_assert ( constant-expression , string-literal ) ;
///
-Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
+Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd,
+ bool RequireSemi) {
assert((Tok.is(tok::kw_static_assert) || Tok.is(tok::kw__Static_assert)) &&
"Not a static_assert declaration");
@@ -739,7 +740,8 @@
T.consumeClose();
DeclEnd = Tok.getLocation();
- ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert);
+ if (RequireSemi)
+ ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert);
return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc,
AssertExpr.get(),
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1553,9 +1553,17 @@
ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(
- Declarator::ForContext, DeclEnd, attrs, false,
- MightBeForRangeStmt ? &ForRangeInit : nullptr);
+ DeclGroupPtrTy DG;
+ // in C11, the declaration may be a static_assert-declaration
+ if (Tok.is(tok::kw__Static_assert)) {
+ ProhibitAttributes(attrs);
+ DG = Actions.ConvertDeclToDeclGroup(
+ ParseStaticAssertDeclaration(DeclEnd, false));
+ } else {
+ DG = ParseSimpleDeclaration(
+ Declarator::ForContext, DeclEnd, attrs, false,
+ MightBeForRangeStmt ? &ForRangeInit : nullptr);
+ }
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (ForRangeInit.ParsedForRangeDecl()) {
Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ?
Index: lib/Sema/SemaStmt.cpp
===================================================================
--- lib/Sema/SemaStmt.cpp
+++ lib/Sema/SemaStmt.cpp
@@ -1612,6 +1612,9 @@
// declare identifiers for objects having storage class 'auto' or
// 'register'.
for (auto *DI : DS->decls()) {
+ // C11: skip over static assertions
+ if (isa<StaticAssertDecl>(DI))
+ continue;
VarDecl *VD = dyn_cast<VarDecl>(DI);
if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage())
VD = nullptr;
Index: test/Parser/static-assert.c
===================================================================
--- test/Parser/static-assert.c
+++ test/Parser/static-assert.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify %s
+
+void f() {
+ for (_Static_assert(1, "1 is nonzero");;) {}
+ for (_Static_assert(0, "0 is nonzero");;) {} // expected-error {{static_assert failed "0 is nonzero"}}
+}
Index: test/Parser/static-assert.cpp
===================================================================
--- test/Parser/static-assert.cpp
+++ test/Parser/static-assert.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -xc++ -std=c++11 -fsyntax-only -verify %s
+
+void f() {
+ for (static_assert(1, "1 is nonzero");;) {} // expected-error {{expected expression}}
+ for (static_assert(0, "0 is nonzero");;) {} // expected-error {{expected expression}}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits