Allow fewer initializer values in initializer expr lists than expected.

We now match C's behavior, where if we have an initializer list with
too-few values for the underlying type, any additional elements are
initialized to zero.

Fixes issue #123.
This commit is contained in:
Matt Pharr
2012-02-14 13:47:11 -08:00
parent c63d139482
commit 317a1f51f7
5 changed files with 57 additions and 32 deletions

View File

@@ -545,7 +545,7 @@ PossiblyResolveFunctionOverloads(Expr *expr, const Type *type) {
/** Utility routine that emits code to initialize a symbol given an /** Utility routine that emits code to initialize a symbol given an
initializer expression. initializer expression.
@param lvalue Memory location of storage for the symbol's data @param ptr Memory location of storage for the symbol's data
@param symName Name of symbol (used in error messages) @param symName Name of symbol (used in error messages)
@param symType Type of variable being initialized @param symType Type of variable being initialized
@param initExpr Expression for the initializer @param initExpr Expression for the initializer
@@ -553,7 +553,7 @@ PossiblyResolveFunctionOverloads(Expr *expr, const Type *type) {
@param pos Source file position of the variable being initialized @param pos Source file position of the variable being initialized
*/ */
void void
InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr, InitSymbol(llvm::Value *ptr, const Type *symType, Expr *initExpr,
FunctionEmitContext *ctx, SourcePos pos) { FunctionEmitContext *ctx, SourcePos pos) {
if (initExpr == NULL) if (initExpr == NULL)
// leave it uninitialized // leave it uninitialized
@@ -571,7 +571,7 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
llvm::Value *initializerValue = initExpr->GetValue(ctx); llvm::Value *initializerValue = initExpr->GetValue(ctx);
if (initializerValue != NULL) if (initializerValue != NULL)
// Bingo; store the value in the variable's storage // Bingo; store the value in the variable's storage
ctx->StoreInst(initializerValue, lvalue); ctx->StoreInst(initializerValue, ptr);
return; return;
} }
} }
@@ -585,7 +585,7 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
ExprList *elist = dynamic_cast<ExprList *>(initExpr); ExprList *elist = dynamic_cast<ExprList *>(initExpr);
if (elist != NULL) { if (elist != NULL) {
if (elist->exprs.size() == 1) if (elist->exprs.size() == 1)
InitSymbol(lvalue, symType, elist->exprs[0], ctx, pos); InitSymbol(ptr, symType, elist->exprs[0], ctx, pos);
else else
Error(initExpr->pos, "Expression list initializers can't be used " Error(initExpr->pos, "Expression list initializers can't be used "
"with type \"%s\".", symType->GetString().c_str()); "with type \"%s\".", symType->GetString().c_str());
@@ -604,7 +604,7 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
llvm::Value *initializerValue = initExpr->GetValue(ctx); llvm::Value *initializerValue = initExpr->GetValue(ctx);
if (initializerValue) if (initializerValue)
ctx->StoreInst(initializerValue, lvalue); ctx->StoreInst(initializerValue, ptr);
return; return;
} }
@@ -629,12 +629,12 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
ExprList *exprList = dynamic_cast<ExprList *>(initExpr); ExprList *exprList = dynamic_cast<ExprList *>(initExpr);
if (exprList != NULL) { if (exprList != NULL) {
// The { ... } case; make sure we have the same number of // The { ... } case; make sure we have the no more expressions
// expressions in the ExprList as we have struct members // in the ExprList as we have struct members
int nInits = exprList->exprs.size(); int nInits = exprList->exprs.size();
if (nInits != collectionType->GetElementCount()) { if (nInits > collectionType->GetElementCount()) {
Error(initExpr->pos, "Initializer for %s type \"%s\" requires " Error(initExpr->pos, "Initializer for %s type \"%s\" requires "
"%d values; %d provided.", name.c_str(), "no more than %d values; %d provided.", name.c_str(),
symType->GetString().c_str(), symType->GetString().c_str(),
collectionType->GetElementCount(), nInits); collectionType->GetElementCount(), nInits);
return; return;
@@ -642,17 +642,36 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
// Initialize each element with the corresponding value from // Initialize each element with the corresponding value from
// the ExprList // the ExprList
for (int i = 0; i < nInits; ++i) { for (int i = 0; i < collectionType->GetElementCount(); ++i) {
const Type *elementType = collectionType->GetElementType(i);
if (elementType == NULL) {
Assert(m->errorCount > 0);
return;
}
llvm::Value *ep; llvm::Value *ep;
if (dynamic_cast<const StructType *>(symType) != NULL) if (dynamic_cast<const StructType *>(symType) != NULL)
ep = ctx->AddElementOffset(lvalue, i, NULL, "element"); ep = ctx->AddElementOffset(ptr, i, NULL, "element");
else else
ep = ctx->GetElementPtrInst(lvalue, LLVMInt32(0), LLVMInt32(i), ep = ctx->GetElementPtrInst(ptr, LLVMInt32(0), LLVMInt32(i),
PointerType::GetUniform(collectionType->GetElementType(i)), PointerType::GetUniform(elementType),
"gep"); "gep");
if (i < nInits)
InitSymbol(ep, collectionType->GetElementType(i), InitSymbol(ep, collectionType->GetElementType(i),
exprList->exprs[i], ctx, pos); exprList->exprs[i], ctx, pos);
else {
// If we don't have enough initializer values, initialize the
// rest as zero.
LLVM_TYPE_CONST llvm::Type *llvmType = elementType->LLVMType(g->ctx);
if (llvmType == NULL) {
Assert(m->errorCount > 0);
return;
}
llvm::Constant *zeroInit = llvm::ConstantAggregateZero::get(llvmType);
ctx->StoreInst(zeroInit, ep);
}
} }
} }
else else
@@ -3436,9 +3455,10 @@ ExprList::GetConstant(const Type *type) const {
else else
FATAL("Unexpected CollectionType in ExprList::GetConstant()"); FATAL("Unexpected CollectionType in ExprList::GetConstant()");
if ((int)exprs.size() != collectionType->GetElementCount()) { if ((int)exprs.size() > collectionType->GetElementCount()) {
Error(pos, "Initializer list for %s \"%s\" must have %d elements " Error(pos, "Initializer list for %s \"%s\" must have no more than %d "
"(has %d).", name.c_str(), collectionType->GetString().c_str(), "elements (has %d).", name.c_str(),
collectionType->GetString().c_str(),
collectionType->GetElementCount(), (int)exprs.size()); collectionType->GetElementCount(), (int)exprs.size());
return NULL; return NULL;
} }
@@ -3456,6 +3476,24 @@ ExprList::GetConstant(const Type *type) const {
cv.push_back(c); cv.push_back(c);
} }
// If there are too few, then treat missing ones as if they were zero
for (int i = (int)exprs.size(); i < collectionType->GetElementCount(); ++i) {
const Type *elementType = collectionType->GetElementType(i);
if (elementType == NULL) {
Assert(m->errorCount > 0);
return NULL;
}
LLVM_TYPE_CONST llvm::Type *llvmType = elementType->LLVMType(g->ctx);
if (llvmType == NULL) {
Assert(m->errorCount > 0);
return NULL;
}
llvm::Constant *c = llvm::Constant::getNullValue(llvmType);
cv.push_back(c);
}
if (dynamic_cast<const StructType *>(type) != NULL) { if (dynamic_cast<const StructType *>(type) != NULL) {
#if defined(LLVM_2_9) #if defined(LLVM_2_9)
return llvm::ConstantStruct::get(*g->ctx, cv, false); return llvm::ConstantStruct::get(*g->ctx, cv, false);

View File

@@ -1,5 +0,0 @@
// requires 10 values; 11 provided
int func() {
int a[10] = {1,2,3,4,5,6,7,8,9,10,11};
}

View File

@@ -1,5 +0,0 @@
// requires 12 values; 11 provided
int func() {
int a[12] = {1,2,3,4,5,6,7,8,9,10,11};
}

View File

@@ -1,3 +1,3 @@
// Initializer list for array "int32[4]" must have 4 elements (has 3) // Initializer list for array "int32[2][4]" must have no more than 2 elements (has 3)
int a[2][4] = { { 1, 2, 3 }, { 1, 2, 3, 4 }, 1 }; int a[2][4] = { { 1, 2, 3 }, { 1, 2, 3, 4 }, 1 };

View File

@@ -1,3 +0,0 @@
// Initializer list for array "int32[4]" must have 4 elements
int a[2][4] = { { 1, 2, 3 }, { 1, 2, 3, 4 } };