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
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 symType Type of variable being initialized
@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
*/
void
InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
InitSymbol(llvm::Value *ptr, const Type *symType, Expr *initExpr,
FunctionEmitContext *ctx, SourcePos pos) {
if (initExpr == NULL)
// leave it uninitialized
@@ -571,7 +571,7 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
llvm::Value *initializerValue = initExpr->GetValue(ctx);
if (initializerValue != NULL)
// Bingo; store the value in the variable's storage
ctx->StoreInst(initializerValue, lvalue);
ctx->StoreInst(initializerValue, ptr);
return;
}
}
@@ -585,7 +585,7 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
ExprList *elist = dynamic_cast<ExprList *>(initExpr);
if (elist != NULL) {
if (elist->exprs.size() == 1)
InitSymbol(lvalue, symType, elist->exprs[0], ctx, pos);
InitSymbol(ptr, symType, elist->exprs[0], ctx, pos);
else
Error(initExpr->pos, "Expression list initializers can't be used "
"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);
if (initializerValue)
ctx->StoreInst(initializerValue, lvalue);
ctx->StoreInst(initializerValue, ptr);
return;
}
@@ -629,12 +629,12 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
ExprList *exprList = dynamic_cast<ExprList *>(initExpr);
if (exprList != NULL) {
// The { ... } case; make sure we have the same number of
// expressions in the ExprList as we have struct members
// The { ... } case; make sure we have the no more expressions
// in the ExprList as we have struct members
int nInits = exprList->exprs.size();
if (nInits != collectionType->GetElementCount()) {
if (nInits > collectionType->GetElementCount()) {
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(),
collectionType->GetElementCount(), nInits);
return;
@@ -642,17 +642,36 @@ InitSymbol(llvm::Value *lvalue, const Type *symType, Expr *initExpr,
// Initialize each element with the corresponding value from
// 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;
if (dynamic_cast<const StructType *>(symType) != NULL)
ep = ctx->AddElementOffset(lvalue, i, NULL, "element");
ep = ctx->AddElementOffset(ptr, i, NULL, "element");
else
ep = ctx->GetElementPtrInst(lvalue, LLVMInt32(0), LLVMInt32(i),
PointerType::GetUniform(collectionType->GetElementType(i)),
ep = ctx->GetElementPtrInst(ptr, LLVMInt32(0), LLVMInt32(i),
PointerType::GetUniform(elementType),
"gep");
InitSymbol(ep, collectionType->GetElementType(i),
exprList->exprs[i], ctx, pos);
if (i < nInits)
InitSymbol(ep, collectionType->GetElementType(i),
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
@@ -3436,9 +3455,10 @@ ExprList::GetConstant(const Type *type) const {
else
FATAL("Unexpected CollectionType in ExprList::GetConstant()");
if ((int)exprs.size() != collectionType->GetElementCount()) {
Error(pos, "Initializer list for %s \"%s\" must have %d elements "
"(has %d).", name.c_str(), collectionType->GetString().c_str(),
if ((int)exprs.size() > collectionType->GetElementCount()) {
Error(pos, "Initializer list for %s \"%s\" must have no more than %d "
"elements (has %d).", name.c_str(),
collectionType->GetString().c_str(),
collectionType->GetElementCount(), (int)exprs.size());
return NULL;
}
@@ -3456,6 +3476,24 @@ ExprList::GetConstant(const Type *type) const {
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 defined(LLVM_2_9)
return llvm::ConstantStruct::get(*g->ctx, cv, false);