From c6eddf50bff68683238f06625fa9fb5016a3694c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 15 Oct 2010 23:53:28 +0000 Subject: [PATCH] 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116647 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 16 +++++++++++++--- test/Sema/flexible-array-init.c | 9 +++++++-- 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()) - if (RT->getDecl()->hasFlexibleArrayMember() && isa(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(Init)) { + unsigned Index = std::distance(RT->getDecl()->field_begin(), + RT->getDecl()->field_end()) - 1; + if (Index < ILE->getNumInits() && + !(isa(ILE->getInit(Index)) && + cast(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; } -- 2.40.0