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:
74
expr.cpp
74
expr.cpp
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user