Return undef instead of null on toConstElem failure.

This fixes a segfault with associative array literals of
arrays of associative array literals, which occured because
of arrayLiteralToConst not handling null values properly.
Ensuring that null pointers are handled correctly in all
toConstElem callers is much more error-prone than just
returning an LLVM undef, an error is emitted anyway.

The root of the problem is actually in the kludgly
implementation of AssocArrayLiteral::toElem, we should
revisit this at some point.
This commit is contained in:
David Nadlinger
2013-12-26 22:48:11 +01:00
parent 6a17b38d83
commit 3ec084da59
2 changed files with 22 additions and 13 deletions

View File

@@ -237,9 +237,15 @@ public:
virtual elem *toElem(IRState *irs);
elem *toElemDtor(IRState *irs);
#if IN_LLVM
/// Emits an LLVM constant corresponding to the expression.
///
/// Due to the current implementation of AssocArrayLiteralExp::toElem,the
/// implementations have to be able to handle being called on expressions
/// that are not actually constant. In such a case, an LLVM undef of the
/// expected type should be returned (_not_ null).
virtual llvm::Constant *toConstElem(IRState *irs);
virtual void cacheLvalue(IRState* irs);
virtual void cacheLvalue(IRState* irs);
llvm::Value* cachedLvalue;
virtual AssignExp* isAssignExp() { return NULL; }

View File

@@ -652,8 +652,8 @@ LLConstant* AddExp::toConstElem(IRState* p)
}
error("expression '%s' is not a constant", toChars());
fatal();
return NULL;
if (!global.gag) fatal();
return llvm::UndefValue::get(DtoType(type));
}
/// Tries to remove a MulExp by a constant value of baseSize from e. Returns
@@ -766,8 +766,8 @@ LLConstant* MinExp::toConstElem(IRState* p)
}
error("expression '%s' is not a constant", toChars());
fatal();
return NULL;
if (!global.gag) fatal();
return llvm::UndefValue::get(DtoType(type));
}
DValue* MinExp::toElem(IRState* p)
@@ -1231,7 +1231,7 @@ Lerr:
error("cannot cast %s to %s at compile time", e1->type->toChars(), type->toChars());
if (!global.gag)
fatal();
return NULL;
return llvm::UndefValue::get(DtoType(type));
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1290,11 +1290,7 @@ llvm::Constant* SymOffExp::toConstElem(IRState* p)
IF_LOG Logger::println("SymOffExp::toConstElem: %s @ %s", toChars(), type->toChars());
LOG_SCOPE;
// We might get null here due to the hackish implementation of
// AssocArrayLiteralExp::toElem.
llvm::Constant* base = DtoConstSymbolAddress(loc, var);
if (!base) return 0;
llvm::Constant* result;
if (offset == 0)
{
@@ -1462,7 +1458,8 @@ LLConstant* AddrExp::toConstElem(IRState* p)
else if (e1->op == TOKslice)
{
error("non-constant expression '%s'", toChars());
fatal();
if (!global.gag) fatal();
return llvm::UndefValue::get(DtoType(type));
}
// not yet supported
else
@@ -2872,7 +2869,8 @@ LLConstant* FuncExp::toConstElem(IRState* p)
{
assert(fd->tok == TOKdelegate || fd->tok == TOKreserved);
error("delegate literals as constant expressions are not yet allowed");
return 0;
if (!global.gag) fatal();
return llvm::UndefValue::get(DtoType(type));
}
// We need to actually codegen the function here, as literals are not added
@@ -3557,5 +3555,10 @@ llvm::Constant* Expression::toConstElem(IRState * p)
error("expression '%s' is not a constant", toChars());
if (!global.gag)
fatal();
return NULL;
// Do not return null here, as AssocArrayLiteralExp::toElem determines
// whether it can allocate the needed arrays statically by just invoking
// toConstElem on its key/value expressions, and handling the null value
// consequently would require error-prone adaptions in all other code.
return llvm::UndefValue::get(DtoType(type));
}