[cfe-commits] r63785 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/Sema.cpp lib/Sema/SemaInit.cpp test/Sema/array-init.c test/Sema/flexible-array-init.c test/SemaCXX/dcl_init_aggr.cpp
Douglas Gregor
dgregor at apple.com
Wed Feb 4 14:46:26 PST 2009
Author: dgregor
Date: Wed Feb 4 16:46:25 2009
New Revision: 63785
URL: http://llvm.org/viewvc/llvm-project?rev=63785&view=rev
Log:
Implement semantic analysis for the GNU flexible array initialization
extension. The interaction with designated initializers is a
bit... interesting... but we follow GNU's lead and don't permit too
much crazy code in this area.
Also, make the "excess initializers" error message a bit more
informative.
Addresses PR2561: http://llvm.org/bugs/show_bug.cgi?id=2561
Added:
cfe/trunk/test/Sema/flexible-array-init.c
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/Sema/array-init.c
cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=63785&r1=63784&r2=63785&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Feb 4 16:46:25 2009
@@ -60,6 +60,10 @@
"initializer overrides prior initialization of this subobject")
DIAG(note_previous_initializer, NOTE,
"previous initialization %select{|with side effects }0is here%select{| (side effects may not occur at run time)}0")
+DIAG(err_designator_into_flexible_array_member, ERROR,
+ "designator into flexible array member subobject")
+DIAG(note_flexible_array_member, NOTE,
+ "initialized flexible array member %0 is here")
// Declarations.
DIAG(ext_vla, EXTENSION,
@@ -547,7 +551,7 @@
DIAG(err_array_init_list_required, ERROR,
"initialization with '{...}' expected for array")
DIAG(err_excess_initializers, ERROR,
- "excess elements in array initializer")
+ "excess elements in %select{array|vector|scalar|union|struct}0 initializer")
DIAG(err_excess_initializers_in_char_array_initializer, ERROR,
"excess elements in char array initializer")
DIAG(warn_initializer_string_for_char_array_too_long, WARNING,
@@ -593,6 +597,10 @@
"%0 may not be nested in a struct due to flexible array member")
DIAG(err_flexible_array_in_array, ERROR,
"%0 may not be used as an array element due to flexible array member")
+DIAG(err_flexible_array_init_nonempty, ERROR,
+ "non-empty initialization of flexible array member inside subobject")
+DIAG(err_flexible_array_init_needs_braces, ERROR,
+ "flexible array requires brace-enclosed initializer")
DIAG(err_illegal_decl_array_of_functions, ERROR,
"'%0' declared as array of functions")
DIAG(err_illegal_decl_array_incomplete_type, ERROR,
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=63785&r1=63784&r2=63785&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Feb 4 16:46:25 2009
@@ -50,11 +50,13 @@
"Invalid modifier for DeclarationName argument");
} else {
assert(Kind == Diagnostic::ak_nameddecl);
- assert(ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0 &&
+ if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
+ S = reinterpret_cast<NamedDecl*>(Val)->getQualifiedNameAsString();
+ else {
+ assert(ModLen == 0 && ArgLen == 0 &&
"Invalid modifier for NamedDecl* argument");
-
- S = reinterpret_cast<NamedDecl*>(Val)->getQualifiedNameAsString();
-
+ S = reinterpret_cast<NamedDecl*>(Val)->getNameAsString();
+ }
}
Output.append(S.begin(), S.end());
}
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=63785&r1=63784&r2=63785&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Feb 4 16:46:25 2009
@@ -56,15 +56,18 @@
void CheckImplicitInitList(InitListExpr *ParentIList, QualType T,
unsigned &Index, InitListExpr *StructuredList,
- unsigned &StructuredIndex);
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
void CheckExplicitInitList(InitListExpr *IList, QualType &T,
unsigned &Index, InitListExpr *StructuredList,
- unsigned &StructuredIndex);
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
void CheckListElementTypes(InitListExpr *IList, QualType &DeclType,
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex);
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
void CheckSubElementType(InitListExpr *IList, QualType ElemType,
unsigned &Index,
InitListExpr *StructuredList,
@@ -84,7 +87,8 @@
RecordDecl::field_iterator Field,
bool SubobjectIsDesignatorContext, unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex);
+ unsigned &StructuredIndex,
+ bool TopLevelObject = false);
void CheckArrayType(InitListExpr *IList, QualType &DeclType,
llvm::APSInt elementIndex,
bool SubobjectIsDesignatorContext, unsigned &Index,
@@ -98,7 +102,8 @@
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
- bool FinishSubobjectInit = true);
+ bool FinishSubobjectInit,
+ bool TopLevelObject);
InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
QualType CurrentObjectType,
InitListExpr *StructuredList,
@@ -220,7 +225,8 @@
unsigned newStructuredIndex = 0;
FullyStructuredList
= getStructuredSubobjectInit(IL, newIndex, T, 0, 0, SourceRange());
- CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex);
+ CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex,
+ /*TopLevelObject=*/true);
if (!hadError)
FillInValueInitializations(FullyStructuredList);
@@ -253,7 +259,8 @@
void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList,
QualType T, unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex) {
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
int maxElements = 0;
if (T->isArrayType())
@@ -284,7 +291,8 @@
unsigned StartIndex = Index;
CheckListElementTypes(ParentIList, T, false, Index,
StructuredSubobjectInitList,
- StructuredSubobjectInitIndex);
+ StructuredSubobjectInitIndex,
+ TopLevelObject);
unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1);
// Update the structured sub-object initialize so that it's ending
@@ -299,12 +307,13 @@
void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex) {
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
assert(IList->isExplicit() && "Illegal Implicit InitListExpr");
SyntacticToSemantic[IList] = StructuredList;
StructuredList->setSyntacticForm(IList);
CheckListElementTypes(IList, T, true, Index, StructuredList,
- StructuredIndex);
+ StructuredIndex, TopLevelObject);
IList->setType(T);
StructuredList->setType(T);
if (hadError)
@@ -322,9 +331,16 @@
} else if (!T->isIncompleteType()) {
// Don't complain for incomplete types, since we'll get an error
// elsewhere
+ QualType CurrentObjectType = StructuredList->getType();
+ int initKind =
+ CurrentObjectType->isArrayType()? 0 :
+ CurrentObjectType->isVectorType()? 1 :
+ CurrentObjectType->isScalarType()? 2 :
+ CurrentObjectType->isUnionType()? 3 :
+ 4;
SemaRef->Diag(IList->getInit(Index)->getLocStart(),
diag::err_excess_initializers)
- << IList->getInit(Index)->getSourceRange();
+ << initKind << IList->getInit(Index)->getSourceRange();
}
}
@@ -338,7 +354,8 @@
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex) {
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
if (DeclType->isScalarType()) {
CheckScalarType(IList, DeclType, Index, StructuredList, StructuredIndex);
} else if (DeclType->isVectorType()) {
@@ -348,7 +365,8 @@
RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
CheckStructUnionTypes(IList, DeclType, RD->field_begin(),
SubobjectIsDesignatorContext, Index,
- StructuredList, StructuredIndex);
+ StructuredList, StructuredIndex,
+ TopLevelObject);
} else if (DeclType->isArrayType()) {
llvm::APSInt Zero(
SemaRef->Context.getTypeSize(SemaRef->Context.getSizeType()),
@@ -643,7 +661,8 @@
// updated to be the next array element we'll initialize.
if (CheckDesignatedInitializer(IList, DIE, DIE->designators_begin(),
DeclType, 0, &elementIndex, Index,
- StructuredList, StructuredIndex)) {
+ StructuredList, StructuredIndex, true,
+ false)) {
hadError = true;
continue;
}
@@ -699,7 +718,8 @@
bool SubobjectIsDesignatorContext,
unsigned &Index,
InitListExpr *StructuredList,
- unsigned &StructuredIndex) {
+ unsigned &StructuredIndex,
+ bool TopLevelObject) {
RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
// If the record is invalid, some of it's members are invalid. To avoid
@@ -744,7 +764,8 @@
// the next field that we'll be initializing.
if (CheckDesignatedInitializer(IList, DIE, DIE->designators_begin(),
DeclType, &Field, 0, Index,
- StructuredList, StructuredIndex))
+ StructuredList, StructuredIndex,
+ true, TopLevelObject))
hadError = true;
// Abort early for unions: the designator handled the
@@ -782,9 +803,24 @@
++Field;
}
- // FIXME: Implement flexible array initialization GCC extension (it's a
- // really messy extension to implement, unfortunately...the necessary
- // information isn't actually even here!)
+ if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() ||
+ Index >= IList->getNumInits() ||
+ !isa<InitListExpr>(IList->getInit(Index)))
+ return;
+
+ // Handle GNU flexible array initializers.
+ if (!TopLevelObject &&
+ 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;
+ hadError = true;
+ }
+
+ CheckSubElementType(IList, Field->getType(), Index, StructuredList,
+ StructuredIndex);
}
/// @brief Check the well-formedness of a C99 designated initializer.
@@ -831,7 +867,8 @@
unsigned &Index,
InitListExpr *StructuredList,
unsigned &StructuredIndex,
- bool FinishSubobjectInit) {
+ bool FinishSubobjectInit,
+ bool TopLevelObject) {
if (D == DIE->designators_end()) {
// Check the actual initialization for the designated object type.
bool prevHadError = hadError;
@@ -949,12 +986,74 @@
if (FieldIndex >= StructuredList->getNumInits())
StructuredList->resizeInits(SemaRef->Context, FieldIndex + 1);
- // Recurse to check later designated subobjects.
- QualType FieldType = (*Field)->getType();
- unsigned newStructuredIndex = FieldIndex;
- if (CheckDesignatedInitializer(IList, DIE, ++D, FieldType, 0, 0, Index,
- StructuredList, newStructuredIndex))
- return true;
+ // This designator names a flexible array member.
+ if (Field->getType()->isIncompleteArrayType()) {
+ bool Invalid = false;
+ DesignatedInitExpr::designators_iterator NextD = D;
+ ++NextD;
+ if (NextD != DIE->designators_end()) {
+ // We can't designate an object within the flexible array
+ // member (because GCC doesn't allow it).
+ SemaRef->Diag(NextD->getStartLocation(),
+ diag::err_designator_into_flexible_array_member)
+ << SourceRange(NextD->getStartLocation(),
+ DIE->getSourceRange().getEnd());
+ SemaRef->Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ Invalid = true;
+ }
+
+ if (!hadError && !isa<InitListExpr>(DIE->getInit())) {
+ // The initializer is not an initializer list.
+ SemaRef->Diag(DIE->getInit()->getSourceRange().getBegin(),
+ diag::err_flexible_array_init_needs_braces)
+ << DIE->getInit()->getSourceRange();
+ SemaRef->Diag(Field->getLocation(), diag::note_flexible_array_member)
+ << *Field;
+ 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;
+ Invalid = true;
+ }
+
+ if (Invalid) {
+ ++Index;
+ return true;
+ }
+
+ // Initialize the array.
+ bool prevHadError = hadError;
+ unsigned newStructuredIndex = FieldIndex;
+ unsigned OldIndex = Index;
+ IList->setInit(Index, DIE->getInit());
+ CheckSubElementType(IList, Field->getType(), Index,
+ StructuredList, newStructuredIndex);
+ IList->setInit(OldIndex, DIE);
+ if (hadError && !prevHadError) {
+ ++Field;
+ ++FieldIndex;
+ if (NextField)
+ *NextField = Field;
+ StructuredIndex = FieldIndex;
+ return true;
+ }
+ } else {
+ // Recurse to check later designated subobjects.
+ QualType FieldType = (*Field)->getType();
+ unsigned newStructuredIndex = FieldIndex;
+ if (CheckDesignatedInitializer(IList, DIE, ++D, FieldType, 0, 0, Index,
+ StructuredList, newStructuredIndex,
+ true, false))
+ return true;
+ }
// Find the position of the next field to be initialized in this
// subobject.
@@ -1075,7 +1174,8 @@
Index = OldIndex;
if (CheckDesignatedInitializer(IList, DIE, D, ElementType, 0, 0, Index,
StructuredList, ElementIndex,
- (DesignatedStartIndex == DesignatedEndIndex)))
+ (DesignatedStartIndex == DesignatedEndIndex),
+ false))
return true;
// Move to the next index in the array that we'll be initializing.
Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=63785&r1=63784&r2=63785&view=diff
==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Wed Feb 4 16:46:25 2009
@@ -20,7 +20,7 @@
int x3[x] = { 1, 2 }; // expected-error{{variable-sized object may not be initialized}}
- int x4 = { 1, 2 }; // expected-warning{{braces around scalar initializer}} expected-error{{excess elements in array initializer}}
+ int x4 = { 1, 2 }; // expected-warning{{braces around scalar initializer}} expected-error{{excess elements in scalar initializer}}
int y[4][3] = {
{ 1, 3, 5 },
@@ -53,7 +53,7 @@
void test() {
int y1[3] = {
- { 1, 2, 3 } // expected-warning{{braces around scalar initializer}} expected-error{{excess elements in array initializer}}
+ { 1, 2, 3 } // expected-warning{{braces around scalar initializer}} expected-error{{excess elements in scalar initializer}}
};
int y3[4][3] = {
{ 1, 3, 5 },
@@ -201,14 +201,13 @@
return z.z;
}
struct s3 {void (*a)(void);} t5 = {autoStructTest};
-// FIXME: GCC extension; flexible array init. Once this is implemented, the warning should be removed.
// Note that clang objc implementation depends on this extension.
-struct {int a; int b[];} t6 = {1, {1, 2, 3}}; //expected-error{{excess elements in array initializer}}
+struct {int a; int b[];} t6 = {1, {1, 2, 3}};
union {char a; int b;} t7[] = {1, 2, 3};
int t8[sizeof t7 == (3*sizeof(int)) ? 1 : -1];
struct bittest{int : 31, a, :21, :12, b;};
-struct bittest bittestvar = {1, 2, 3, 4}; //expected-error{{excess elements in array initializer}}
+struct bittest bittestvar = {1, 2, 3, 4}; //expected-error{{excess elements in struct initializer}}
// Not completely sure what should happen here...
int u1 = {}; //expected-warning{{use of GNU empty initializer extension}} expected-error{{scalar initializer cannot be empty}}
@@ -243,7 +242,7 @@
};
static void sppp_ipv6cp_up();
-const struct {} ipcp = { sppp_ipv6cp_up }; //expected-warning{{empty struct extension}} expected-error{{excess elements in array initializer}}
+const struct {} ipcp = { sppp_ipv6cp_up }; //expected-warning{{empty struct extension}} expected-error{{excess elements in struct initializer}}
struct _Matrix { union { float m[4][4]; }; }; //expected-warning{{anonymous unions are a GNU extension in C}}
typedef struct _Matrix Matrix;
Added: cfe/trunk/test/Sema/flexible-array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/flexible-array-init.c?rev=63785&view=auto
==============================================================================
--- cfe/trunk/test/Sema/flexible-array-init.c (added)
+++ cfe/trunk/test/Sema/flexible-array-init.c Wed Feb 4 16:46:25 2009
@@ -0,0 +1,38 @@
+// RUN: clang -fsyntax-only -verify %s
+struct one {
+ int a;
+ int values[];
+} x = {5, {1, 2, 3}};
+
+struct one x2 = { 5, 1, 2, 3 }; // expected-error{{excess elements in struct initializer}}
+
+void test() {
+ struct one x3 = {5, {1, 2, 3}};
+}
+
+struct foo {
+ int x;
+ int y[]; // expected-note{{initialized flexible array member 'y' is here}}
+};
+struct bar { struct foo z; };
+
+struct foo a = { 1, { 2, 3, 4 } }; // Valid.
+struct bar b = { { 1, { 2, 3, 4 } } }; // expected-error{{non-empty initialization of flexible array member inside subobject}}
+struct bar c = { { 1, { } } }; // Valid.
+struct foo d[1] = { { 1, { 2, 3, 4 } } }; // expected-error{{'struct foo' may not be used as an array element due to flexible array member}}
+
+struct foo desig_foo = { .y = {2, 3, 4} };
+struct bar desig_bar = { .z.y = { } };
+struct bar desig_bar2 = { .z.y = { 2, 3, 4} }; // expected-error{{non-empty initialization of flexible array member inside subobject}}
+struct foo design_foo2 = { .y = 2 }; // expected-error{{flexible array requires brace-enclosed initializer}}
+
+struct point {
+ int x, y;
+};
+
+struct polygon {
+ int numpoints;
+ struct point points[]; // expected-note{{initialized flexible array member 'points' is here}}
+};
+struct polygon poly = {
+ .points[2] = { 1, 2} }; // expected-error{{designator into flexible array member subobject}}
Modified: cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp?rev=63785&r1=63784&r2=63785&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp (original)
+++ cfe/trunk/test/SemaCXX/dcl_init_aggr.cpp Wed Feb 4 16:46:25 2009
@@ -118,5 +118,5 @@
u u1 = { 1 };
u u2 = u1;
u u3 = 1; // expected-error{{cannot initialize 'u3' with an rvalue of type 'int'}}
-u u4 = { 0, "asdf" }; // expected-error{{excess elements in array initializer}}
+u u4 = { 0, "asdf" }; // expected-error{{excess elements in union initializer}}
u u5 = { "asdf" }; // expected-error{{incompatible type initializing 'char const [5]', expected 'int'}}
More information about the cfe-commits
mailing list