[cfe-commits] r41690 - 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
Mon Sep 3 19:20:05 PDT 2007
Author: snaroff
Date: Mon Sep 3 21:20:04 2007
New Revision: 41690
URL: http://llvm.org/viewvc/llvm-project?rev=41690&view=rev
Log:
More fun with initializers!
- Fixed many bugs, enhanced test case considerably, added a diagnostic, etc.
- Refactored CheckInitList() into CheckVariableInitList()/CheckConstantInitList().
- Added CheckInitExpr().
- Support for multi-dimensional arrays looking good.
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=41690&r1=41689&r2=41690&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Mon Sep 3 21:20:04 2007
@@ -445,9 +445,14 @@
bool CheckInitializer(Expr *simpleInit_or_initList, QualType &declType,
bool isStatic);
bool CheckSingleInitializer(Expr *simpleInit, QualType declType);
- void CheckInitList(InitListExpr *IList, QualType DType, bool isStatic,
- int &nInitializers, int maxElements, bool &hadError);
-
+ bool CheckInitExpr(Expr *expr, bool isStatic, QualType ElementType);
+ void CheckVariableInitList(QualType DeclType, InitListExpr *IList,
+ QualType ElementType, bool isStatic,
+ int &nInitializers, bool &hadError);
+ void CheckConstantInitList(QualType DeclType, InitListExpr *IList,
+ QualType ElementType, bool isStatic,
+ int &nInitializers, bool &hadError);
+
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
/// the specified width and sign. If an overflow occurs, detect it and emit
/// the specified diagnostic.
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=41690&r1=41689&r2=41690&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Mon Sep 3 21:20:04 2007
@@ -289,29 +289,101 @@
return false;
}
-void Sema::CheckInitList(InitListExpr *IList, QualType DType,
- bool isStatic, int &nInitializers, int maxElements,
- bool &hadError) {
+bool Sema::CheckInitExpr(Expr *expr, bool isStatic, QualType ElementType) {
+ SourceLocation loc;
+
+ if (isStatic && !expr->isConstantExpr(Context, &loc)) { // C99 6.7.8p4.
+ Diag(loc, diag::err_init_element_not_constant, expr->getSourceRange());
+ return true;
+ } else if (CheckSingleInitializer(expr, ElementType)) {
+ return true; // types weren't compatible.
+ }
+ return false;
+}
+
+void Sema::CheckVariableInitList(QualType DeclType, InitListExpr *IList,
+ QualType ElementType, bool isStatic,
+ int &nInitializers, bool &hadError) {
for (unsigned i = 0; i < IList->getNumInits(); i++) {
Expr *expr = IList->getInit(i);
- if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr))
- CheckInitList(InitList, DType, isStatic, nInitializers, maxElements,
- hadError);
- else {
- SourceLocation loc = expr->getLocStart();
+ if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) {
+ if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
+ QualType ElmtType = CAT->getElementType();
+ int maxElements = CAT->getSize().getZExtValue();
+
+ // If we have a multi-dimensional array, navigate to the base type. Also
+ // compute the absolute array, so we can detect excess elements.
+ while ((CAT = ElmtType->getAsConstantArrayType())) {
+ ElmtType = CAT->getElementType();
+ maxElements *= CAT->getSize().getZExtValue();
+ }
+ CheckConstantInitList(DeclType, InitList, ElementType, isStatic,
+ maxElements, hadError);
+ }
+ } else {
+ hadError = CheckInitExpr(expr, isStatic, ElementType);
+ }
+ nInitializers++;
+ }
+ return;
+}
+
+// FIXME: Doesn't deal with arrays of structures yet.
+void Sema::CheckConstantInitList(QualType DeclType, InitListExpr *IList,
+ QualType ElementType, bool isStatic,
+ int &totalInits, bool &hadError) {
+ int maxElementsAtThisLevel = 0;
+ int nInitsAtLevel = 0;
- if (isStatic && !expr->isConstantExpr(Context, &loc)) { // C99 6.7.8p4.
- Diag(loc, diag::err_init_element_not_constant, expr->getSourceRange());
- hadError = true;
- } else if (CheckSingleInitializer(expr, DType)) {
- hadError = true; // types didn't match.
+ if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
+ // We have a constant array type, compute maxElements *at this level*.
+ QualType ElmtType = CAT->getElementType();
+ maxElementsAtThisLevel = CAT->getSize().getZExtValue();
+
+ // Set DeclType, important for correctly handling multi-dimensional arrays.
+ DeclType = ElmtType;
+
+ // If we have a multi-dimensional array, navigate to the base type. Also
+ // compute the absolute size of the array *at this level* array, so we can
+ // detect excess elements.
+ while ((CAT = ElmtType->getAsConstantArrayType())) {
+ ElmtType = CAT->getElementType();
+ maxElementsAtThisLevel *= CAT->getSize().getZExtValue();
+ }
+ } else if (DeclType->isScalarType()) {
+ 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) {
+ for (unsigned i = 0; i < numInits; i++) {
+ Expr *expr = IList->getInit(i);
+
+ if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) {
+ CheckConstantInitList(DeclType, InitList, ElementType, isStatic,
+ totalInits, hadError);
+ } else {
+ hadError = CheckInitExpr(expr, isStatic, 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());
}
- // Does the element fit?
- nInitializers++;
- if ((maxElements >= 0) && (nInitializers > maxElements))
- Diag(loc, 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());
}
return;
}
@@ -325,7 +397,6 @@
Init->setType(DeclType);
bool hadError = false;
- int nInits = 0;
// 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.
@@ -338,36 +409,46 @@
// We have a VariableArrayType with unknown size.
QualType ElmtType = VAT->getElementType();
- // If we have a multi-dimensional array, navigate to the base type.
- while ((VAT = ElmtType->getAsVariableArrayType())) {
- ElmtType = VAT->getElementType();
- }
- CheckInitList(InitList, ElmtType, isStatic, nInits, -1, hadError);
+ // Set DeclType, important for correctly handling multi-dimensional arrays.
+ DeclType = ElmtType;
+ // If we have a multi-dimensional array, navigate to the base type.
+ // Use getAsArrayType(), since it is illegal for an array to have an
+ // incomplete element type. For example, "int [][]" is illegal.
+ const ArrayType *ATY;
+ while ((ATY = ElmtType->getAsArrayType())) {
+ ElmtType = ATY->getElementType();
+ }
+ int numInits = 0;
+ CheckVariableInitList(DeclType, InitList, ElmtType, isStatic, numInits,
+ hadError);
if (!hadError) {
// Return a new array type from the number of initializers (C99 6.7.8p22).
llvm::APSInt ConstVal(32);
- ConstVal = nInits;
- DeclType = Context.getConstantArrayType(ElmtType, ConstVal,
+ ConstVal = numInits;
+ DeclType = Context.getConstantArrayType(DeclType, ConstVal,
ArrayType::Normal, 0);
}
return hadError;
}
if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
QualType ElmtType = CAT->getElementType();
- unsigned numElements = CAT->getSize().getZExtValue();
+ int maxElements = CAT->getSize().getZExtValue();
// If we have a multi-dimensional array, navigate to the base type. Also
// compute the absolute size of the array, so we can detect excess elements.
while ((CAT = ElmtType->getAsConstantArrayType())) {
ElmtType = CAT->getElementType();
- numElements *= CAT->getSize().getZExtValue();
+ maxElements *= CAT->getSize().getZExtValue();
}
- CheckInitList(InitList, ElmtType, isStatic, nInits, numElements, hadError);
+ CheckConstantInitList(DeclType, InitList, ElmtType, isStatic, maxElements,
+ hadError);
return hadError;
}
- if (DeclType->isScalarType()) { // C99 6.7.8p11
- CheckInitList(InitList, DeclType, isStatic, nInits, 1, hadError);
+ if (DeclType->isScalarType()) { // C99 6.7.8p11: Allow "int x = { 1, 2 };"
+ int maxElements = 1;
+ CheckConstantInitList(DeclType, InitList, DeclType, isStatic, maxElements,
+ hadError);
return hadError;
}
// FIXME: Handle struct/union types.
@@ -476,7 +557,8 @@
if (Init) {
if (SC == VarDecl::Extern)
Diag(D.getIdentifierLoc(), diag::warn_extern_init);
- CheckInitializer(Init, R, true);
+ if (!D.getInvalidType())
+ CheckInitializer(Init, R, true);
}
// File scope. C99 6.9.2p2: A declaration of an identifier for and
// object that has file scope without an initializer, and without a
@@ -520,7 +602,7 @@
if (SC == VarDecl::Extern) { // C99 6.7.8p5
Diag(D.getIdentifierLoc(), diag::err_block_extern_cant_init);
InvalidDecl = true;
- } else {
+ } else if (!D.getInvalidType()) {
CheckInitializer(Init, R, SC == VarDecl::Static);
}
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41690&r1=41689&r2=41690&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Sep 3 21:20:04 2007
@@ -552,6 +552,8 @@
"variable-sized object may not be initialized")
DIAG(warn_excess_initializers, WARNING,
"excess elements in array initializer")
+DIAG(warn_braces_around_scalar_init, WARNING,
+ "braces around scalar initializer")
DIAG(err_redefinition_of_label, ERROR,
"redefinition of label '%0'")
Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=41690&r1=41689&r2=41690&view=diff
==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Mon Sep 3 21:20:04 2007
@@ -16,7 +16,7 @@
int x3[x] = { 1, 2 }; // expected-error{{variable-sized object may not be initialized}}
- int x4 = { 1, 2 }; // // expected-warning{{excess elements in array initializer}}
+ int x4 = { 1, 2 }; // expected-warning{{braces around scalar initializer}} expected-warning{{excess elements in array initializer}}
int y[4][3] = {
{ 1, 3, 5 },
@@ -46,3 +46,85 @@
static int x2[3] = { 1.0, "abc" , 5.8 }; // expected-warning{{incompatible types assigning 'char *' to 'int'}}
}
+
+void test() {
+ int y1[3] = {
+ { 1, 2, 3 } // expected-warning{{braces around scalar initializer}} expected-warning{{excess elements in array initializer}}
+ };
+ int y3[4][3] = {
+ { 1, 3, 5 },
+ { 2, 4, 6 },
+ { 3, 5, 7 },
+ { 4, 6, 8 },
+ { }, // expected-warning{{use of GNU empty initializer extension}} expected-warning{{excess elements in array initializer}}
+ };
+ int y4[4][3] = {
+ { 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}}
+ };
+}
+
+void allLegalAndSynonymous() {
+ short q[4][3][2] = {
+ { 1 },
+ { 2, 3 },
+ { 4, 5, 6 }
+ };
+ short q2[4][3][2] = {
+ { 1, 0, 0, 0, 0, 0 },
+ { 2, 3, 0, 0, 0, 0 },
+ { 4, 5, 6 }
+ };
+ short q3[4][3][2] = {
+ {
+ { 1 },
+ },
+ {
+ { 2, 3 },
+ },
+ {
+ { 4, 5 },
+ { 6 },
+ },
+ };
+}
+
+void legal() {
+ short q[][3][2] = {
+ { 1 },
+ { 2, 3 },
+ { 4, 5, 6 }
+ };
+}
+
+void illegal() {
+ short q2[4][][2] = { // expected-error{{array has incomplete element type 'short [][2]'}}
+ { 1, 0, 0, 0, 0, 0 },
+ { 2, 3, 0, 0, 0, 0 },
+ { 4, 5, 6 }
+ };
+ short q3[4][3][] = { // expected-error{{array has incomplete element type 'short []'}}
+ {
+ { 1 },
+ },
+ {
+ { 2, 3 },
+ },
+ {
+ { 4, 5 },
+ { 6 },
+ },
+ };
+ // FIXME: the following two errors are redundant
+ int a[][] = { 1, 2 }; // expected-error{{array has incomplete element type 'int []'}} expected-error{{variable has incomplete type 'int []'}}
+}
+
+typedef int AryT[];
+
+void testTypedef()
+{
+ AryT a = { 1, 2 }, b = { 3, 4, 5 };
+}
+
More information about the cfe-commits
mailing list