aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-10-15 23:53:28 +0000
committerDouglas Gregor <dgregor@apple.com>2010-10-15 23:53:28 +0000
commitc6eddf50bff68683238f06625fa9fb5016a3694c (patch)
tree6ae934075b7ffd1d95865c0f8ef3f91767d444da
parent31df9be7a85615a6aaeaf8b0ce6721760d4efdcf (diff)
Allow list-initialization of a local variable of class type with a
flexible array member, so long as the flexibility array member is either not initialized or is initialized with an empty initializer list. Fixes <rdar://problem/8540437>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116647 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp16
-rw-r--r--test/Sema/flexible-array-init.c9
2 files changed, 20 insertions, 5 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 23721e5d99..e7714521c8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4395,9 +4395,19 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// global/static definition.
if (VDecl->hasLocalStorage())
if (const RecordType *RT = VDecl->getType()->getAs<RecordType>())
- if (RT->getDecl()->hasFlexibleArrayMember() && isa<InitListExpr>(Init)) {
- Diag(VDecl->getLocation(), diag::err_nonstatic_flexible_variable);
- VDecl->setInvalidDecl();
+ if (RT->getDecl()->hasFlexibleArrayMember()) {
+ // Check whether the initializer tries to initialize the flexible
+ // array member itself to anything other than an empty initializer list.
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
+ unsigned Index = std::distance(RT->getDecl()->field_begin(),
+ RT->getDecl()->field_end()) - 1;
+ if (Index < ILE->getNumInits() &&
+ !(isa<InitListExpr>(ILE->getInit(Index)) &&
+ cast<InitListExpr>(ILE->getInit(Index))->getNumInits() == 0)) {
+ Diag(VDecl->getLocation(), diag::err_nonstatic_flexible_variable);
+ VDecl->setInvalidDecl();
+ }
+ }
}
// Check any implicit conversions within the expression.
diff --git a/test/Sema/flexible-array-init.c b/test/Sema/flexible-array-init.c
index a0f1acd071..12f5d4f5d6 100644
--- a/test/Sema/flexible-array-init.c
+++ b/test/Sema/flexible-array-init.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
struct one {
int a;
- int values[]; // expected-note 3{{initialized flexible array member 'values' is here}}
+ int values[]; // expected-note 4{{initialized flexible array member 'values' is here}}
} x = {5, {1, 2, 3}}; // expected-warning{{flexible array initialization is a GNU extension}}
struct one x2 = { 5, 1, 2, 3 }; // expected-warning{{flexible array initialization is a GNU extension}}
@@ -10,6 +10,11 @@ void test() {
struct one x3 = {5, {1, 2, 3}}; // \
// expected-warning{{flexible array initialization is a GNU extension}} \
// expected-error {{non-static initialization of a variable with flexible array member}}
+ struct one x3a = { 5 };
+ struct one x3b = { .a = 5 };
+ struct one x3c = { 5, {} }; // expected-warning{{use of GNU empty initializer extension}} \
+ // expected-warning{{flexible array initialization is a GNU extension}} \
+ // expected-warning{{zero size arrays are an extension}}
}
struct foo {
@@ -68,7 +73,7 @@ struct PR8217a {
void PR8217() {
struct PR8217a foo1 = { .i = 0, .v = "foo" }; // expected-error {{non-static initialization of a variable with flexible array member}}
- struct PR8217a foo2 = { .i = 0 }; // expected-error {{non-static initialization of a variable with flexible array member}}
+ struct PR8217a foo2 = { .i = 0 };
struct PR8217a foo3 = { .i = 0, .v = { 'b', 'a', 'r', '\0' } }; // expected-error {{non-static initialization of a variable with flexible array member}}
struct PR8217a bar;
}