diff --git a/expr.cpp b/expr.cpp index 8925de2b..0d46c211 100644 --- a/expr.cpp +++ b/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(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(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(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(type) != NULL) { #if defined(LLVM_2_9) return llvm::ConstantStruct::get(*g->ctx, cv, false); diff --git a/tests_errors/decl-1.ispc b/tests_errors/decl-1.ispc deleted file mode 100644 index 71e773c1..00000000 --- a/tests_errors/decl-1.ispc +++ /dev/null @@ -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}; -} diff --git a/tests_errors/decl-2.ispc b/tests_errors/decl-2.ispc deleted file mode 100644 index 23ef497b..00000000 --- a/tests_errors/decl-2.ispc +++ /dev/null @@ -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}; -} diff --git a/tests_errors/initexpr-2.ispc b/tests_errors/initexpr-2.ispc index e36a18a7..66b4a438 100644 --- a/tests_errors/initexpr-2.ispc +++ b/tests_errors/initexpr-2.ispc @@ -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 }; diff --git a/tests_errors/initexpr.ispc b/tests_errors/initexpr.ispc deleted file mode 100644 index 5c19b6b7..00000000 --- a/tests_errors/initexpr.ispc +++ /dev/null @@ -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 } };