Fix bug that prohibited assignments with pointer expressions on the LHS
Previously, code like "*(ptr+1) = foo" would claim that the LHS was invalid for an assignment expression. Issue #138.
This commit is contained in:
25
expr.cpp
25
expr.cpp
@@ -639,6 +639,9 @@ lLLVMConstantValue(const Type *type, llvm::LLVMContext *ctx, double value) {
|
||||
|
||||
static llvm::Value *
|
||||
lMaskForSymbol(Symbol *baseSym, FunctionEmitContext *ctx) {
|
||||
if (baseSym == NULL)
|
||||
return ctx->GetFullMask();
|
||||
|
||||
if (dynamic_cast<const PointerType *>(baseSym->type) != NULL ||
|
||||
dynamic_cast<const ReferenceType *>(baseSym->type) != NULL)
|
||||
// FIXME: for pointers, we really only want to do this for
|
||||
@@ -659,10 +662,11 @@ lMaskForSymbol(Symbol *baseSym, FunctionEmitContext *ctx) {
|
||||
static void
|
||||
lStoreAssignResult(llvm::Value *value, llvm::Value *ptr, const Type *ptrType,
|
||||
FunctionEmitContext *ctx, Symbol *baseSym) {
|
||||
Assert(baseSym != NULL &&
|
||||
Assert(baseSym == NULL ||
|
||||
baseSym->varyingCFDepth <= ctx->VaryingCFDepth());
|
||||
if (!g->opt.disableMaskedStoreToStore &&
|
||||
!g->opt.disableMaskAllOnOptimizations &&
|
||||
baseSym != NULL &&
|
||||
baseSym->varyingCFDepth == ctx->VaryingCFDepth() &&
|
||||
baseSym->storageClass != SC_STATIC &&
|
||||
dynamic_cast<const ReferenceType *>(baseSym->type) == NULL &&
|
||||
@@ -2017,14 +2021,13 @@ AssignExpr::GetValue(FunctionEmitContext *ctx) const {
|
||||
ctx->SetDebugPos(pos);
|
||||
|
||||
Symbol *baseSym = lvalue->GetBaseSymbol();
|
||||
// Should be caught during type-checking...
|
||||
assert(baseSym != NULL);
|
||||
|
||||
switch (op) {
|
||||
case Assign: {
|
||||
llvm::Value *lv = lvalue->GetLValue(ctx);
|
||||
if (lv == NULL) {
|
||||
Assert(m->errorCount > 0);
|
||||
Error(lvalue->pos, "Left hand side of assignment expression can't "
|
||||
"be assigned to.");
|
||||
return NULL;
|
||||
}
|
||||
const Type *lvalueType = lvalue->GetLValueType();
|
||||
@@ -2147,13 +2150,13 @@ AssignExpr::TypeCheck() {
|
||||
}
|
||||
}
|
||||
|
||||
if (lvalue->GetBaseSymbol() == NULL) {
|
||||
Error(lvalue->pos, "Left hand side of assignment statement can't be "
|
||||
"assigned to.");
|
||||
const Type *lhsType = lvalue->GetType();
|
||||
if (lhsType->IsConstType()) {
|
||||
Error(lvalue->pos, "Can't assign to type \"%s\" on left-hand side of "
|
||||
"expression.", lhsType->GetString().c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Type *lhsType = lvalue->GetType();
|
||||
if (dynamic_cast<const PointerType *>(lhsType) != NULL) {
|
||||
if (op == AddAssign || op == SubAssign) {
|
||||
if (PointerType::IsVoidPointer(lhsType)) {
|
||||
@@ -2187,12 +2190,6 @@ AssignExpr::TypeCheck() {
|
||||
if (rvalue == NULL)
|
||||
return NULL;
|
||||
|
||||
if (lhsType->IsConstType()) {
|
||||
Error(pos, "Can't assign to type \"%s\" on left-hand side of "
|
||||
"expression.", lhsType->GetString().c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Make sure we're not assigning to a struct that has a constant member
|
||||
const StructType *st = dynamic_cast<const StructType *>(lhsType);
|
||||
if (st != NULL && lCheckForConstStructMember(pos, st, st))
|
||||
|
||||
16
tests/ptr-assign-lhs-math-1.ispc
Normal file
16
tests/ptr-assign-lhs-math-1.ispc
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||
uniform float a[programCount];
|
||||
a[programIndex] = aFOO[programIndex];
|
||||
|
||||
uniform float * uniform ptr = a;
|
||||
*(ptr+1) = 0;
|
||||
RET[programIndex] = a[programIndex];
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 1+programIndex;
|
||||
RET[1] = 0;
|
||||
}
|
||||
15
tests/ptr-assign-lhs-math-2.ispc
Normal file
15
tests/ptr-assign-lhs-math-2.ispc
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||
uniform float a[programCount];
|
||||
a[programIndex] = aFOO[programIndex];
|
||||
|
||||
uniform float * varying ptr = a;
|
||||
*(ptr+programIndex) = 0;
|
||||
RET[programIndex] = a[programIndex];
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 0;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Left hand side of assignment statement can't be assigned to
|
||||
// Left hand side of assignment expression can't be assigned to
|
||||
|
||||
int foo() {return 2;}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Left hand side of assignment statement can't be assigned to
|
||||
// Can't assign to type "const uniform int32" on left-hand side of expression
|
||||
|
||||
int bar(){
|
||||
4 = 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Left hand side of assignment statement can't be assigned to
|
||||
// Can't assign to type "const uniform int32" on left-hand side of expression
|
||||
|
||||
int bar(){
|
||||
int x;
|
||||
|
||||
Reference in New Issue
Block a user