aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Sema/SemaDecl.cpp21
-rw-r--r--lib/Sema/SemaInit.cpp69
-rw-r--r--test/Sema/flexible-array-init.c35
4 files changed, 70 insertions, 59 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 0ded2fb3e4..3d8fbd37c1 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2716,8 +2716,8 @@ def ext_flexible_array_in_struct : Extension<
"%0 may not be nested in a struct due to flexible array member">;
def ext_flexible_array_in_array : Extension<
"%0 may not be used as an array element due to flexible array member">;
-def err_flexible_array_init_nonempty : Error<
- "non-empty initialization of flexible array member inside subobject">;
+def err_flexible_array_init : Error<
+ "initialization of flexible array member is not allowed">;
def ext_flexible_array_empty_aggregate_ms : Extension<
"flexible array member %0 in otherwise empty %select{struct|class}1 "
"is a Microsoft extension">, InGroup<Microsoft>;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 62032e8b65..9f43aa2f05 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5740,27 +5740,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
VDecl->setType(DclT);
Init->setType(DclT);
}
-
-
- // If this variable is a local declaration with record type, make sure it
- // doesn't have a flexible member initialization. We only support this as a
- // global/static definition.
- if (VDecl->hasLocalStorage())
- if (const RecordType *RT = VDecl->getType()->getAs<RecordType>())
- 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.
CheckImplicitConversions(Init, VDecl->getLocation());
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index a61b1d11fc..2d47cda0e0 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -249,6 +249,9 @@ class InitListChecker {
InitListExpr *ILE, bool &RequiresSecondPass);
void FillInValueInitializations(const InitializedEntity &Entity,
InitListExpr *ILE, bool &RequiresSecondPass);
+ bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
+ Expr *InitExpr, FieldDecl *Field,
+ bool TopLevelObject);
public:
InitListChecker(Sema &S, const InitializedEntity &Entity,
InitListExpr *IL, QualType &T);
@@ -1113,6 +1116,43 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
}
}
+bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
+ Expr *InitExpr,
+ FieldDecl *Field,
+ bool TopLevelObject) {
+ // Handle GNU flexible array initializers.
+ unsigned FlexArrayDiag;
+ if (isa<InitListExpr>(InitExpr) &&
+ cast<InitListExpr>(InitExpr)->getNumInits() == 0) {
+ // Empty flexible array init always allowed as an extension
+ FlexArrayDiag = diag::ext_flexible_array_init;
+ } else if (SemaRef.getLangOptions().CPlusPlus) {
+ // Disallow flexible array init in C++; it is not required for gcc
+ // compatibility, and it needs work to IRGen correctly in general.
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else if (!TopLevelObject) {
+ // Disallow flexible array init on non-top-level object
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else if (Entity.getKind() != InitializedEntity::EK_Variable) {
+ // Disallow flexible array init on anything which is not a variable.
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else if (cast<VarDecl>(Entity.getDecl())->hasLocalStorage()) {
+ // Disallow flexible array init on local variables.
+ FlexArrayDiag = diag::err_flexible_array_init;
+ } else {
+ // Allow other cases.
+ FlexArrayDiag = diag::ext_flexible_array_init;
+ }
+
+ SemaRef.Diag(InitExpr->getSourceRange().getBegin(),
+ FlexArrayDiag)
+ << InitExpr->getSourceRange().getBegin();
+ SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << Field;
+
+ return FlexArrayDiag != diag::ext_flexible_array_init;
+}
+
void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
InitListExpr *IList,
QualType DeclType,
@@ -1239,24 +1279,11 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity,
Index >= IList->getNumInits())
return;
- // Handle GNU flexible array initializers.
- if (!TopLevelObject &&
- (!isa<InitListExpr>(IList->getInit(Index)) ||
- cast<InitListExpr>(IList->getInit(Index))->getNumInits() > 0)) {
- SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
- diag::err_flexible_array_init_nonempty)
- << IList->getInit(Index)->getSourceRange().getBegin();
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
+ if (CheckFlexibleArrayInit(Entity, IList->getInit(Index), *Field,
+ TopLevelObject)) {
hadError = true;
++Index;
return;
- } else {
- SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(),
- diag::ext_flexible_array_init)
- << IList->getInit(Index)->getSourceRange().getBegin();
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
}
InitializedEntity MemberEntity =
@@ -1567,16 +1594,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
Invalid = true;
}
- // Handle GNU flexible array initializers.
- if (!Invalid && !TopLevelObject &&
- cast<InitListExpr>(DIE->getInit())->getNumInits() > 0) {
- SemaRef.Diag(DIE->getSourceRange().getBegin(),
- diag::err_flexible_array_init_nonempty)
- << DIE->getSourceRange().getBegin();
- SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member)
- << *Field;
+ // Check GNU flexible array initializer.
+ if (!Invalid && CheckFlexibleArrayInit(Entity, DIE->getInit(), *Field,
+ TopLevelObject))
Invalid = true;
- }
if (Invalid) {
++Index;
diff --git a/test/Sema/flexible-array-init.c b/test/Sema/flexible-array-init.c
index 12f5d4f5d6..78fc7c5e0d 100644
--- a/test/Sema/flexible-array-init.c
+++ b/test/Sema/flexible-array-init.c
@@ -7,9 +7,7 @@ struct one {
struct one x2 = { 5, 1, 2, 3 }; // expected-warning{{flexible array initialization is a GNU extension}}
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 x3 = {5, {1, 2, 3}}; // expected-error{{initialization of flexible array member is not allowed}}
struct one x3a = { 5 };
struct one x3b = { .a = 5 };
struct one x3c = { 5, {} }; // expected-warning{{use of GNU empty initializer extension}} \
@@ -19,22 +17,23 @@ void test() {
struct foo {
int x;
- int y[]; // expected-note 6 {{initialized flexible array member 'y' is here}}
+ int y[]; // expected-note 8 {{initialized flexible array member 'y' is here}}
};
struct bar { struct foo z; }; // expected-warning {{'z' may not be nested in a struct due to flexible array member}}
struct foo a = { 1, { 2, 3, 4 } }; // expected-warning{{flexible array initialization is a GNU extension}}
-struct bar b = { { 1, { 2, 3, 4 } } }; // expected-error{{non-empty initialization of flexible array member inside subobject}}
+struct bar b = { { 1, { 2, 3, 4 } } }; // expected-error{{initialization of flexible array member is not allowed}}
struct bar c = { { 1, { } } }; // // expected-warning{{flexible array initialization is a GNU extension}} \
// expected-warning{{use of GNU empty initializer extension}} \
// expected-warning{{zero size arrays are an extension}}
struct foo d[1] = { { 1, { 2, 3, 4 } } }; // expected-warning{{'struct foo' may not be used as an array element due to flexible array member}} \
- // expected-error{{non-empty initialization of flexible array member inside subobject}}
+ // expected-error{{initialization of flexible array member is not allowed}}
-struct foo desig_foo = { .y = {2, 3, 4} };
+struct foo desig_foo = { .y = {2, 3, 4} }; // expected-warning{{flexible array initialization is a GNU extension}}
struct bar desig_bar = { .z.y = { } }; // expected-warning{{use of GNU empty initializer extension}} \
- // expected-warning{{zero size arrays are an extension}}
-struct bar desig_bar2 = { .z.y = { 2, 3, 4} }; // expected-error{{non-empty initialization of flexible array member inside subobject}}
+ // expected-warning{{zero size arrays are an extension}} \
+ // expected-warning{{flexible array initialization is a GNU extension}}
+struct bar desig_bar2 = { .z.y = { 2, 3, 4} }; // expected-error{{initialization of flexible array member is not allowed}}
struct foo design_foo2 = { .y = 2 }; // expected-error{{flexible array requires brace-enclosed initializer}}
struct point {
@@ -68,13 +67,25 @@ struct Y {
// PR8217
struct PR8217a {
int i;
- char v[];
+ char v[]; // expected-note 2 {{initialized flexible array member 'v' is here}}
};
void PR8217() {
- struct PR8217a foo1 = { .i = 0, .v = "foo" }; // expected-error {{non-static initialization of a variable with flexible array member}}
+ struct PR8217a foo1 = { .i = 0, .v = "foo" }; // expected-error {{initialization of flexible array member is not allowed}}
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 foo3 = { .i = 0, .v = { 'b', 'a', 'r', '\0' } }; // expected-error {{initialization of flexible array member is not allowed}}
struct PR8217a bar;
}
+typedef struct PR10648 {
+ unsigned long n;
+ int v[]; // expected-note {{initialized flexible array member 'v' is here}}
+} PR10648;
+int f10648() {
+ return (PR10648){2, {3, 4}}.v[1]; // expected-error {{initialization of flexible array member is not allowed}}
+}
+
+struct FlexWithUnnamedBitfield { int : 10; int x; int y[]; }; // expected-note {{initialized flexible array member 'y' is here}}
+void TestFlexWithUnnamedBitfield() {
+ struct FlexWithUnnamedBitfield x = {10, {3}}; // expected-error {{initialization of flexible array member is not allowed}}
+}