[cfe-commits] r44816 - in /cfe/trunk: Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaExpr.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/array-constraint.c test/Sema/array-init.c
Steve Naroff
snaroff at apple.com
Mon Dec 10 14:44:33 PST 2007
Author: snaroff
Date: Mon Dec 10 16:44:33 2007
New Revision: 44816
URL: http://llvm.org/viewvc/llvm-project?rev=44816&view=rev
Log:
Add support for initializing char arrays from string literals.
Adapted from a patch by Anders Carlsson.
Modified:
cfe/trunk/Sema/Sema.h
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/Sema/SemaExpr.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/test/Sema/array-constraint.c
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=44816&r1=44815&r2=44816&view=diff
==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Mon Dec 10 16:44:33 2007
@@ -684,7 +684,10 @@
void CheckConstantInitList(QualType DeclType, InitListExpr *IList,
QualType ElementType, bool isStatic,
int &nInitializers, bool &hadError);
-
+ bool CheckForCharArrayInitializer(InitListExpr *IList, QualType ElementType,
+ int &nInitializers, bool isConstant,
+ bool &hadError);
+
// CheckVectorCast - check type constraints for vectors.
// Since vectors are an extension, there are no C standard reference for this.
// We allow casting between vectors and integer datatypes of the same size.
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=44816&r1=44815&r2=44816&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Mon Dec 10 16:44:33 2007
@@ -429,21 +429,75 @@
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);
+ 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, isStatic,
- maxElements, hadError);
+ if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) {
+ if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
+ int maxElements = CAT->getMaximumElements();
+ CheckConstantInitList(DeclType, InitList, ElementType, isStatic,
+ maxElements, hadError);
+ }
+ } else {
+ hadError = CheckInitExpr(expr, IList, i, isStatic, 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 {
- hadError = CheckInitExpr(expr, IList, i, isStatic, ElementType);
+ // 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;
}
- nInitializers++;
+
+ // 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;
+
+ return false;
}
// FIXME: Doesn't deal with arrays of structures yet.
@@ -473,6 +527,11 @@
// 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);
@@ -499,19 +558,42 @@
Diag(IList->getLocStart(), diag::warn_excess_initializers,
IList->getSourceRange());
}
- return;
}
bool Sema::CheckInitializer(Expr *&Init, QualType &DeclType, bool isStatic) {
+ bool hadError = false;
+
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
- if (!InitList)
+ if (!InitList) {
+ if (StringLiteral *strLiteral = dyn_cast<StringLiteral>(Init)) {
+ const VariableArrayType *VAT = DeclType->getAsVariableArrayType();
+ // FIXME: Handle wide strings
+ if (VAT && VAT->getElementType()->isCharType()) {
+ // C99 6.7.8p14. We have an array of character type with unknown size
+ // being initialized to a string literal.
+ llvm::APSInt ConstVal(32);
+ ConstVal = strLiteral->getByteLength() + 1;
+ // Return a new array type (C99 6.7.8p22).
+ DeclType = Context.getConstantArrayType(VAT->getElementType(), ConstVal,
+ ArrayType::Normal, 0);
+ return hadError;
+ }
+ const ConstantArrayType *CAT = DeclType->getAsConstantArrayType();
+ if (CAT && CAT->getElementType()->isCharType()) {
+ // C99 6.7.8p14. We have an array of character type with known size.
+ if (strLiteral->getByteLength() > (unsigned)CAT->getMaximumElements()) {
+ Diag(strLiteral->getSourceRange().getBegin(),
+ diag::warn_initializer_string_for_char_array_too_long,
+ strLiteral->getSourceRange());
+ }
+ return hadError;
+ }
+ }
return CheckSingleInitializer(Init, isStatic, DeclType);
-
+ }
// We have an InitListExpr, make sure we set the type.
Init->setType(DeclType);
- bool hadError = false;
-
// 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->getAsVariableArrayType()) {
@@ -525,13 +607,19 @@
int numInits = 0;
CheckVariableInitList(VAT->getElementType(), InitList, VAT->getBaseType(),
isStatic, numInits, hadError);
- if (!hadError) {
- // Return a new array type from the number of initializers (C99 6.7.8p22).
- llvm::APSInt ConstVal(32);
+ llvm::APSInt ConstVal(32);
+
+ if (!hadError)
ConstVal = numInits;
- DeclType = Context.getConstantArrayType(VAT->getElementType(), ConstVal,
- ArrayType::Normal, 0);
- }
+
+ // 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()) {
Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=44816&r1=44815&r2=44816&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Mon Dec 10 16:44:33 2007
@@ -689,15 +689,9 @@
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
Expr *literalExpr = static_cast<Expr*>(InitExpr);
- // FIXME: This is just a temporary workaround to get
- // test/Parser/compound_literal.c passing. (CheckInitializer does not support
- // initializing a char array from a single string literal).
- if (!literalType->isArrayType() ||
- !literalType->getAsArrayType()->getElementType()->isCharType()) {
- // FIXME: add more semantic analysis (C99 6.5.2.5).
- if (CheckInitializer(literalExpr, literalType, false))
- return 0;
- }
+ // FIXME: add more semantic analysis (C99 6.5.2.5).
+ if (CheckInitializer(literalExpr, literalType, false))
+ return 0;
return new CompoundLiteralExpr(literalType, literalExpr);
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=44816&r1=44815&r2=44816&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Dec 10 16:44:33 2007
@@ -605,6 +605,10 @@
"array size is negative")
DIAG(ext_typecheck_zero_array_size, EXTENSION,
"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,
@@ -617,6 +621,10 @@
"variable-sized object may not be initialized")
DIAG(warn_excess_initializers, EXTENSION,
"excess elements in array 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,
+ "initializer-string for char array is too long")
DIAG(warn_braces_around_scalar_init, WARNING,
"braces around scalar initializer")
DIAG(err_illegal_initializer, ERROR,
Modified: cfe/trunk/test/Sema/array-constraint.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-constraint.c?rev=44816&r1=44815&r2=44816&view=diff
==============================================================================
--- cfe/trunk/test/Sema/array-constraint.c (original)
+++ cfe/trunk/test/Sema/array-constraint.c Mon Dec 10 16:44:33 2007
@@ -45,7 +45,7 @@
void strFunc(char *);
const char staticAry[] = "test";
int checkStaticAry() {
- strFunc(staticAry); // expected-warning{{passing 'char const []' to 'char *' discards qualifiers}}
+ strFunc(staticAry); // expected-warning{{passing 'char const [5]' to 'char *' discards qualifiers}}
}
Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=44816&r1=44815&r2=44816&view=diff
==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Mon Dec 10 16:44:33 2007
@@ -137,3 +137,28 @@
AryT a = { 1, 2 }, b = { 3, 4, 5 };
}
+static char const xx[] = "test";
+static char const yy[5] = "test";
+static char const zz[3] = "test"; // expected-warning{{initializer-string for char array is too long}}
+
+void charArrays()
+{
+ static char const test[] = "test";
+ static char const test2[] = { "weird stuff" };
+ static char const test3[] = { "test", "excess stuff" }; // expected-error{{excess elements in char array initializer}}
+
+ char* cp[] = { "Hello" };
+
+ char c[] = { "Hello" };
+ int l[sizeof(c) == 6 ? 1 : -1];
+
+ int i[] = { "Hello "}; // expected-error{{array of wrong type 'int' initialized from string constant}}
+ 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}}
+ 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}}
+}
+
More information about the cfe-commits
mailing list