[cfe-commits] r46339 - in /cfe/trunk: Sema/Sema.h Sema/SemaDecl.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/array-init.c
Steve Naroff
snaroff at apple.com
Thu Jan 24 16:51:06 PST 2008
Author: snaroff
Date: Thu Jan 24 18:51:06 2008
New Revision: 46339
URL: http://llvm.org/viewvc/llvm-project?rev=46339&view=rev
Log:
Replace Sema::CheckVariableInitList, CheckConstantInitList, and CheckForCharArrayInitializer with CheckInitializerListTypes. The new routine now supports struct/union initializers.
This is a modified version of a patch by Eli Friedman. This version passes all of the clang tests and supports vectors:-)
Note that Eli and I are still unsatisfied the implementation of CheckInitializerListTypes(). We'd like to find a more elegant implementation. Nevertheless, this is a complex part of the standard (and may be hard to simplify). Since the complexity is localized to this routine, we can iterate without too much disruption:-)
Modified:
cfe/trunk/Sema/Sema.h
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/test/Sema/array-init.c
Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=46339&r1=46338&r2=46339&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Thu Jan 24 18:51:06 2008
@@ -740,16 +740,8 @@
bool CheckSingleInitializer(Expr *&simpleInit, QualType declType);
bool CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot,
QualType ElementType);
-
- void CheckVariableInitList(QualType DeclType, InitListExpr *IList,
- QualType ElementType,
- int &nInitializers, bool &hadError);
- void CheckConstantInitList(QualType DeclType, InitListExpr *IList,
- QualType ElementType,
- int &nInitializers, bool &hadError);
- bool CheckForCharArrayInitializer(InitListExpr *IList, QualType ElementType,
- int &nInitializers, bool isConstant,
- bool &hadError);
+ bool CheckInitializerListTypes(InitListExpr*& IList, QualType &DeclType,
+ bool topLevel, unsigned& startIndex);
bool CheckForConstantInitializer(Expr *e, QualType t);
StringLiteral *IsStringLiteralInit(Expr *Init, QualType DeclType);
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=46339&r1=46338&r2=46339&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Thu Jan 24 18:51:06 2008
@@ -376,140 +376,6 @@
return false;
}
-void Sema::CheckVariableInitList(QualType DeclType, InitListExpr *IList,
- QualType ElementType,
- int &nInitializers, bool &hadError) {
- unsigned numInits = IList->getNumInits();
-
- if (numInits) {
- if (CheckForCharArrayInitializer(IList, ElementType, nInitializers,
- false, hadError))
- return;
-
- for (unsigned i = 0; i < numInits; i++) {
- Expr *expr = IList->getInit(i);
-
- if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) {
- if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
- int maxElements = CAT->getMaximumElements();
- CheckConstantInitList(DeclType, InitList, ElementType,
- maxElements, hadError);
- }
- } else {
- hadError = CheckInitExpr(expr, IList, i, ElementType);
- }
- nInitializers++;
- }
- } else {
- Diag(IList->getLocStart(),
- diag::err_at_least_one_initializer_needed_to_size_array);
- hadError = true;
- }
-}
-
-bool Sema::CheckForCharArrayInitializer(InitListExpr *IList,
- QualType ElementType,
- int &nInitializers, bool isConstant,
- bool &hadError)
-{
- if (ElementType->isPointerType())
- return false;
-
- if (StringLiteral *literal = dyn_cast<StringLiteral>(IList->getInit(0))) {
- // FIXME: Handle wide strings
- if (ElementType->isCharType()) {
- if (isConstant) {
- if (literal->getByteLength() > (unsigned)nInitializers) {
- Diag(literal->getSourceRange().getBegin(),
- diag::warn_initializer_string_for_char_array_too_long,
- literal->getSourceRange());
- }
- } else {
- nInitializers = literal->getByteLength() + 1;
- }
- } else {
- // FIXME: It might be better if we could point to the declaration
- // here, instead of the string literal.
- Diag(literal->getSourceRange().getBegin(),
- diag::array_of_wrong_type_initialized_from_string,
- ElementType.getAsString());
- hadError = true;
- }
-
- // Check for excess initializers
- for (unsigned i = 1; i < IList->getNumInits(); i++) {
- Expr *expr = IList->getInit(i);
- Diag(expr->getLocStart(),
- diag::err_excess_initializers_in_char_array_initializer,
- expr->getSourceRange());
- }
-
- return true;
- }
-
- return false;
-}
-
-// FIXME: Doesn't deal with arrays of structures yet.
-void Sema::CheckConstantInitList(QualType DeclType, InitListExpr *IList,
- QualType ElementType,
- int &totalInits, bool &hadError) {
- int maxElementsAtThisLevel = 0;
- int nInitsAtLevel = 0;
-
- if (ElementType->isRecordType()) // FIXME: until we support structures...
- return;
-
- if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
- // We have a constant array type, compute maxElements *at this level*.
- maxElementsAtThisLevel = CAT->getMaximumElements();
- // Set DeclType, used below to recurse (for multi-dimensional arrays).
- DeclType = CAT->getElementType();
- } else if (DeclType->isScalarType()) {
- if (const VectorType *VT = DeclType->getAsVectorType())
- maxElementsAtThisLevel = VT->getNumElements();
- else {
- Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init,
- IList->getSourceRange());
- maxElementsAtThisLevel = 1;
- }
- }
- // The empty init list "{ }" is treated specially below.
- unsigned numInits = IList->getNumInits();
- if (numInits) {
- if (CheckForCharArrayInitializer(IList, ElementType,
- maxElementsAtThisLevel,
- true, hadError))
- return;
-
- for (unsigned i = 0; i < numInits; i++) {
- Expr *expr = IList->getInit(i);
-
- if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) {
- CheckConstantInitList(DeclType, InitList, ElementType,
- totalInits, hadError);
- } else {
- hadError = CheckInitExpr(expr, IList, i, ElementType);
- nInitsAtLevel++; // increment the number of initializers at this level.
- totalInits--; // decrement the total number of initializers.
-
- // Check if we have space for another initializer.
- if (((nInitsAtLevel > maxElementsAtThisLevel) || (totalInits < 0)))
- Diag(expr->getLocStart(), diag::warn_excess_initializers,
- expr->getSourceRange());
- }
- }
- if (nInitsAtLevel < maxElementsAtThisLevel) // fill the remaining elements.
- totalInits -= (maxElementsAtThisLevel - nInitsAtLevel);
- } else {
- // we have an initializer list with no elements.
- totalInits -= maxElementsAtThisLevel;
- if (totalInits < 0)
- Diag(IList->getLocStart(), diag::warn_excess_initializers,
- IList->getSourceRange());
- }
-}
-
bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) {
if (const VariableArrayType *VAT = DeclT->getAsIncompleteArrayType()) {
// C99 6.7.8p14. We have an array of character type with unknown size
@@ -535,16 +401,199 @@
}
StringLiteral *Sema::IsStringLiteralInit(Expr *Init, QualType DeclType) {
- StringLiteral *strLiteral = dyn_cast<StringLiteral>(Init);
const ArrayType *AT = DeclType->getAsArrayType();
- if (strLiteral && (AT && AT->getElementType()->isCharType()))
- return strLiteral;
+ if (AT && AT->getElementType()->isCharType()) {
+ return dyn_cast<StringLiteral>(Init);
+ }
return 0;
}
-bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
+// CheckInitializerListTypes - Checks the types of elements of an initializer
+// list. This function is recursive: it calls itself to initialize subelements
+// of aggregate types. Note that the topLevel parameter essentially refers to
+// whether this expression "owns" the initializer list passed in, or if this
+// initialization is taking elements out of a parent initializer. Each
+// call to this function adds zero or more to startIndex, reports any errors,
+// and returns true if it found any inconsistent types.
+bool Sema::CheckInitializerListTypes(InitListExpr*& IList, QualType &DeclType,
+ bool topLevel, unsigned& startIndex) {
bool hadError = false;
-
+
+ if (DeclType->isScalarType()) {
+ // The simplest case: initializing a single scalar
+ if (topLevel) {
+ Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init,
+ IList->getSourceRange());
+ }
+ if (startIndex < IList->getNumInits()) {
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ // FIXME: Should an error be reported here instead?
+ unsigned newIndex = 0;
+ CheckInitializerListTypes(SubInitList, DeclType, true, newIndex);
+ } else {
+ hadError |= CheckInitExpr(expr, IList, startIndex, DeclType);
+ }
+ ++startIndex;
+ }
+ // FIXME: Should an error be reported for empty initializer list + scalar?
+ } else if (DeclType->isVectorType()) {
+ if (startIndex < IList->getNumInits()) {
+ const VectorType *VT = DeclType->getAsVectorType();
+ int maxElements = VT->getNumElements();
+ QualType elementType = VT->getElementType();
+
+ for (int i = 0; i < maxElements; ++i) {
+ // Don't attempt to go past the end of the init list
+ if (startIndex >= IList->getNumInits())
+ break;
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ unsigned newIndex = 0;
+ hadError |= CheckInitializerListTypes(SubInitList, elementType,
+ true, newIndex);
+ ++startIndex;
+ } else {
+ hadError |= CheckInitializerListTypes(IList, elementType,
+ false, startIndex);
+ }
+ }
+ }
+ } else if (DeclType->isAggregateType() || DeclType->isUnionType()) {
+ if (DeclType->isStructureType() || DeclType->isUnionType()) {
+ if (startIndex < IList->getNumInits() &&
+ Context.typesAreCompatible(IList->getInit(startIndex)->getType(), DeclType)) {
+ // We found a compatible struct; per the standard, this initializes the
+ // struct. (The C standard technically says that this only applies for
+ // initializers for declarations with automatic scope; however, this
+ // construct is unambiguous anyway because a struct cannot contain
+ // a type compatible with itself. We'll output an error when we check
+ // if the initializer is constant.)
+ // FIXME: Is a call to CheckSingleInitializer required here?
+ ++startIndex;
+ } else {
+ RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
+ // If structDecl is a forward declaration, this loop won't do anything;
+ // That's okay, because an error should get printed out elsewhere. It
+ // might be worthwhile to skip over the rest of the initializer, though.
+ int numMembers = structDecl->getNumMembers() -
+ structDecl->hasFlexibleArrayMember();
+ for (int i = 0; i < numMembers; i++) {
+ // Don't attempt to go past the end of the init list
+ if (startIndex >= IList->getNumInits())
+ break;
+ FieldDecl * curField = structDecl->getMember(i);
+ if (!curField->getIdentifier()) {
+ // Don't initialize unnamed fields, e.g. "int : 20;"
+ continue;
+ }
+ QualType fieldType = curField->getType();
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ unsigned newStart = 0;
+ hadError |= CheckInitializerListTypes(SubInitList, fieldType,
+ true, newStart);
+ ++startIndex;
+ } else {
+ hadError |= CheckInitializerListTypes(IList, fieldType,
+ false, startIndex);
+ }
+ if (DeclType->isUnionType())
+ break;
+ }
+ // FIXME: Implement flexible array initialization GCC extension (it's a
+ // really messy extension to implement, unfortunately...the necessary
+ // information isn't actually even here!)
+ }
+ } else if (DeclType->isArrayType()) {
+ // Check for the special-case of initializing an array with a string.
+ if (startIndex < IList->getNumInits()) {
+ if (StringLiteral *lit = IsStringLiteralInit(IList->getInit(startIndex),
+ DeclType)) {
+ CheckStringLiteralInit(lit, DeclType);
+ ++startIndex;
+ if (topLevel && startIndex < IList->getNumInits()) {
+ // We have leftover initializers; warn
+ Diag(IList->getInit(startIndex)->getLocStart(),
+ diag::err_excess_initializers_in_char_array_initializer,
+ IList->getInit(startIndex)->getSourceRange());
+ }
+ return false;
+ }
+ }
+ int maxElements;
+ if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) {
+ // FIXME: use a proper constant
+ maxElements = 0x7FFFFFFF;
+ // Check for VLAs; in standard C it would be possible to check this
+ // earlier, but I don't know where clang accepts VLAs (gcc accepts
+ // them in all sorts of strange places).
+ if (const Expr *expr = VAT->getSizeExpr()) {
+ Diag(expr->getLocStart(), diag::err_variable_object_no_init,
+ expr->getSourceRange());
+ hadError = true;
+ }
+ } else {
+ const ConstantArrayType *CAT = DeclType->getAsConstantArrayType();
+ maxElements = static_cast<int>(CAT->getSize().getZExtValue());
+ }
+ QualType elementType = DeclType->getAsArrayType()->getElementType();
+ int numElements = 0;
+ for (int i = 0; i < maxElements; ++i, ++numElements) {
+ // Don't attempt to go past the end of the init list
+ if (startIndex >= IList->getNumInits())
+ break;
+ Expr* expr = IList->getInit(startIndex);
+ if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+ unsigned newIndex = 0;
+ hadError |= CheckInitializerListTypes(SubInitList, elementType,
+ true, newIndex);
+ ++startIndex;
+ } else {
+ hadError |= CheckInitializerListTypes(IList, elementType,
+ false, startIndex);
+ }
+ }
+ if (DeclType->getAsVariableArrayType()) {
+ // If this is an incomplete array type, the actual type needs to
+ // be calculated here
+ if (numElements == 0) {
+ // Sizing an array implicitly to zero is not allowed
+ // (It could in theory be allowed, but it doesn't really matter.)
+ Diag(IList->getLocStart(),
+ diag::err_at_least_one_initializer_needed_to_size_array);
+ hadError = true;
+ } else {
+ llvm::APSInt ConstVal(32);
+ ConstVal = numElements;
+ DeclType = Context.getConstantArrayType(elementType, ConstVal,
+ ArrayType::Normal, 0);
+ }
+ }
+ } else {
+ assert(0 && "Aggregate that isn't a function or array?!");
+ }
+ } else {
+ // In C, all types are either scalars or aggregates, but
+ // additional handling is needed here for C++ (and possibly others?).
+ assert(0 && "Unsupported initializer type");
+ }
+
+ // If this init list is a base list, we set the type; an initializer doesn't
+ // fundamentally have a type, but this makes the ASTs a bit easier to read
+ if (topLevel)
+ IList->setType(DeclType);
+
+ if (topLevel && startIndex < IList->getNumInits()) {
+ // We have leftover initializers; warn
+ Diag(IList->getInit(startIndex)->getLocStart(),
+ diag::warn_excess_initializers,
+ IList->getInit(startIndex)->getSourceRange());
+ }
+ return hadError;
+}
+
+bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
// C99 6.7.8p3: The type of the entity to be initialized shall be an array
// of unknown size ("[]") or an object type that is not a variable array type.
if (const VariableArrayType *VAT = DeclType->getAsVariablyModifiedType())
@@ -559,53 +608,8 @@
return CheckStringLiteralInit(strLiteral, DeclType);
return CheckSingleInitializer(Init, DeclType);
}
- // We have an InitListExpr, make sure we set the type.
- Init->setType(DeclType);
-
- // C99 6.7.8p3: The type of the entity to be initialized shall be an array
- // of unknown size ("[]") or an object type that is not a variable array type.
- if (const VariableArrayType *VAT = DeclType->getAsIncompleteArrayType()) {
-
- // We have a VariableArrayType with unknown size. Note that only the first
- // array can have unknown size. For example, "int [][]" is illegal.
- int numInits = 0;
- CheckVariableInitList(VAT->getElementType(), InitList, VAT->getBaseType(),
- numInits, hadError);
- llvm::APSInt ConstVal(32);
-
- if (!hadError)
- ConstVal = numInits;
-
- // Return a new array type from the number of initializers (C99 6.7.8p22).
-
- // Note that if there was an error, we will still set the decl type,
- // to an array type with 0 elements.
- // This is to avoid "incomplete type foo[]" errors when we've already
- // reported the real cause of the error.
- DeclType = Context.getConstantArrayType(VAT->getElementType(), ConstVal,
- ArrayType::Normal, 0);
- return hadError;
- }
- if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
- int maxElements = CAT->getMaximumElements();
- CheckConstantInitList(DeclType, InitList, CAT->getBaseType(),
- maxElements, hadError);
- return hadError;
- }
- if (const VectorType *VT = DeclType->getAsVectorType()) {
- int maxElements = VT->getNumElements();
- CheckConstantInitList(DeclType, InitList, VT->getElementType(),
- maxElements, hadError);
- return hadError;
- }
- if (DeclType->isScalarType()) { // C99 6.7.8p11: Allow "int x = { 1, 2 };"
- int maxElements = 1;
- CheckConstantInitList(DeclType, InitList, DeclType, maxElements, hadError);
- return hadError;
- }
- // FIXME: Handle struct/union types, including those appearing in a
- // CompoundLiteralExpr...
- return hadError;
+ unsigned newIndex = 0;
+ return CheckInitializerListTypes(InitList, DeclType, true, newIndex);
}
Sema::DeclTy *
@@ -784,7 +788,8 @@
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
BVD->setInvalidDecl();
} else if (!BVD->isInvalidDecl()) {
- CheckInitializerTypes(Init, DclT);
+ if (CheckInitializerTypes(Init, DclT))
+ BVD->setInvalidDecl();
if (SC == VarDecl::Static) // C99 6.7.8p4.
CheckForConstantInitializer(Init, DclT);
}
@@ -792,7 +797,8 @@
if (FVD->getStorageClass() == VarDecl::Extern)
Diag(VDecl->getLocation(), diag::warn_extern_init);
if (!FVD->isInvalidDecl())
- CheckInitializerTypes(Init, DclT);
+ if (CheckInitializerTypes(Init, DclT))
+ FVD->setInvalidDecl();
// C99 6.7.8p4. All file scoped initializers need to be constant.
CheckForConstantInitializer(Init, DclT);
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=46339&r1=46338&r2=46339&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Jan 24 18:51:06 2008
@@ -628,8 +628,6 @@
"zero size arrays are an extension")
DIAG(err_at_least_one_initializer_needed_to_size_array, ERROR,
"at least one initializer value required to size array")
-DIAG(array_of_wrong_type_initialized_from_string, ERROR,
- "array of wrong type '%0' initialized from string constant")
DIAG(err_array_size_non_int, ERROR,
"size of array has non-integer type '%0'")
DIAG(err_init_element_not_constant, ERROR,
@@ -640,7 +638,7 @@
"'extern' variable has an initializer")
DIAG(err_variable_object_no_init, ERROR,
"variable-sized object may not be initialized")
-DIAG(warn_excess_initializers, EXTENSION,
+DIAG(warn_excess_initializers, WARNING,
"excess elements in array initializer")
DIAG(err_excess_initializers_in_char_array_initializer, ERROR,
"excess elements in char array initializer")
Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=46339&r1=46338&r2=46339&view=diff
==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Thu Jan 24 18:51:06 2008
@@ -66,7 +66,7 @@
{ 1, 3, 5, 2 }, // expected-warning{{excess elements in array initializer}}
{ 4, 6 },
{ 3, 5, 7 },
- { 4, 6, 8 }, // expected-warning{{excess elements in array initializer}}
+ { 4, 6, 8 },
};
}
@@ -152,14 +152,14 @@
char c[] = { "Hello" };
int l[sizeof(c) == 6 ? 1 : -1];
- int i[] = { "Hello "}; // expected-error{{array of wrong type 'int' initialized from string constant}}
+ int i[] = { "Hello "}; // expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
char c2[] = { "Hello", "Good bye" }; //expected-error{{excess elements in char array initializer}}
- int i2[1] = { "Hello" }; //expected-error{{array of wrong type 'int' initialized from string constant}}
+ int i2[1] = { "Hello" }; //expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
char c3[5] = { "Hello" };
char c4[4] = { "Hello" }; //expected-warning{{initializer-string for char array is too long}}
- int i3[] = {}; //expected-error{{at least one initializer value required to size array}} expected-warning{{use of GNU empty initializer extension}}
+ int i3[] = {}; //expected-error{{at least one initializer value required to size array}} expected-error{{variable has incomplete type 'int []'}} expected-warning{{use of GNU empty initializer extension}}
}
void variableArrayInit() {
@@ -167,3 +167,40 @@
char strlit[a] = "foo"; //expected-error{{variable-sized object may not be initialized}}
int b[a] = { 1, 2, 4 }; //expected-error{{variable-sized object may not be initialized}}
}
+
+// Pure array tests
+float r1[10] = {{7}}; //expected-warning{{braces around scalar initializer}}
+float r2[] = {{8}}; //expected-warning{{braces around scalar initializer}}
+char r3[][5] = {1,2,3,4,5,6};
+char r3_2[sizeof r3 == 10 ? 1 : -1];
+float r4[1][2] = {1,{2},3,4}; //expected-warning{{braces around scalar initializer}} expected-warning{{excess elements in array initializer}}
+char r5[][5] = {"aa", "bbb", "ccccc"};
+char r6[sizeof r5 == 15 ? 1 : -1];
+const char r7[] = "zxcv";
+char r8[5] = "5char";
+char r9[5] = "6chars"; //expected-warning{{initializer-string for char array is too long}}
+
+int r11[0] = {}; //expected-warning{{zero size arrays are an extension}} expected-warning{{use of GNU empty initializer extension}}
+
+// Some struct tests
+void autoStructTest() {
+struct s1 {char a; char b;} t1;
+struct s2 {struct s1 c;} t2 = { t1 };
+// The following is a less than great diagnostic (though it's on par with EDG).
+struct s1 t3[] = {t1, t1, "abc", 0}; //expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'char'}}
+int t4[sizeof t3 == 6 ? 1 : -1];
+}
+struct s3 {void (*a)(void);} t5 = {autoStructTest};
+// 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-warning{{excess elements in array initializer}}
+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-warning{{excess elements in array initializer}}
+
+// Not completely sure what should happen here...
+int u1 = {}; //expected-warning{{use of GNU empty initializer extension}} expected-warning{{braces around scalar initializer}}
+int u2 = {{3}}; //expected-warning{{braces around scalar initializer}}
+
More information about the cfe-commits
mailing list