From ca7cc4744eaa14c6221bc57f5548c59616343788 Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Thu, 12 Apr 2012 06:08:19 -0700 Subject: [PATCH] Fix bug with taking references of temporaries. Previously, the compiler would crash if e.g. the program passed a temporary value to a function taking a const reference. This change fixes ReferenceExpr::GetValue() to handle this case and allocate temporary storage for the temporary so that the pointer to that storage can be used for the reference value. --- expr.cpp | 29 ++++++++++++++++++++++++++++- tests/ref-as-temporary.ispc | 14 ++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/ref-as-temporary.ispc diff --git a/expr.cpp b/expr.cpp index dab2b416..cbef1622 100644 --- a/expr.cpp +++ b/expr.cpp @@ -6861,7 +6861,34 @@ ReferenceExpr::ReferenceExpr(Expr *e, SourcePos p) llvm::Value * ReferenceExpr::GetValue(FunctionEmitContext *ctx) const { ctx->SetDebugPos(pos); - return expr ? expr->GetLValue(ctx) : NULL; + if (expr == NULL) { + Assert(m->errorCount > 0); + return NULL; + } + + llvm::Value *value = expr->GetLValue(ctx); + if (value != NULL) + return value; + + // value is NULL if the expression is a temporary; in this case, we'll + // allocate storage for it so that we can return the pointer to that... + const Type *type; + LLVM_TYPE_CONST llvm::Type *llvmType; + if ((type = expr->GetType()) == NULL || + (llvmType = type->LLVMType(g->ctx)) == NULL) { + Assert(m->errorCount > 0); + return NULL; + } + + value = expr->GetValue(ctx); + if (value == NULL) { + Assert(m->errorCount > 0); + return NULL; + } + + llvm::Value *ptr = ctx->AllocaInst(llvmType); + ctx->StoreInst(value, ptr); + return ptr; } diff --git a/tests/ref-as-temporary.ispc b/tests/ref-as-temporary.ispc new file mode 100644 index 00000000..1b167da6 --- /dev/null +++ b/tests/ref-as-temporary.ispc @@ -0,0 +1,14 @@ + +export uniform int width() { return programCount; } + + +int func(const int &a) { return a+1; } +int bar() { return 0; } + +export void f_f(uniform float RET[], uniform float aFOO[]) { + RET[programIndex] = func(bar()); +} + +export void result(uniform float RET[]) { + RET[programIndex] = 1; +}