mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Fixed templated interface member call codegen.
Fixes DMD testcase 'test7618'.
This commit is contained in:
56
gen/toir.cpp
56
gen/toir.cpp
@@ -1425,25 +1425,32 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
{
|
||||
DtoResolveDsymbol(fdecl);
|
||||
|
||||
LLValue* funcval;
|
||||
LLValue* vthis2 = 0;
|
||||
if (e1type->ty == Tclass) {
|
||||
// This is a bit more convoluted than it would need to be, because it
|
||||
// has to take templated interface methods into account, for which
|
||||
// isFinal is not necessarily true.
|
||||
const bool nonFinal = !fdecl->isFinal() &&
|
||||
(fdecl->isAbstract() || fdecl->isVirtual());
|
||||
|
||||
// If we are calling a non-final interface function, we need to get
|
||||
// the pointer to the underlying object instead of passing the
|
||||
// interface pointer directly.
|
||||
LLValue* passedThis = 0;
|
||||
if (e1type->ty == Tclass)
|
||||
{
|
||||
TypeClass* tc = static_cast<TypeClass*>(e1type);
|
||||
if (tc->sym->isInterfaceDeclaration() && !fdecl->isFinal())
|
||||
vthis2 = DtoCastInterfaceToObject(l, NULL)->getRVal();
|
||||
if (tc->sym->isInterfaceDeclaration() && nonFinal)
|
||||
passedThis = DtoCastInterfaceToObject(l, NULL)->getRVal();
|
||||
}
|
||||
LLValue* vthis = l->getRVal();
|
||||
if (!vthis2) vthis2 = vthis;
|
||||
if (!passedThis) passedThis = vthis;
|
||||
|
||||
//
|
||||
// decide whether this function needs to be looked up in the vtable
|
||||
//
|
||||
bool vtbllookup = !fdecl->isFinal() && (fdecl->isAbstract() || fdecl->isVirtual());
|
||||
|
||||
// even virtual functions are looked up directly if super or DotTypeExp
|
||||
// are used, thus we need to walk through the this expression and check
|
||||
// Decide whether this function needs to be looked up in the vtable.
|
||||
// Even virtual functions are looked up directly if super or DotTypeExp
|
||||
// are used, thus we need to walk through the this expression and check.
|
||||
bool vtbllookup = nonFinal;
|
||||
Expression* e = e1;
|
||||
while (e && vtbllookup) {
|
||||
while (e && vtbllookup)
|
||||
{
|
||||
if (e->op == TOKsuper || e->op == TOKdottype)
|
||||
vtbllookup = false;
|
||||
else if (e->op == TOKcast)
|
||||
@@ -1452,20 +1459,21 @@ DValue* DotVarExp::toElem(IRState* p)
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// look up function
|
||||
//
|
||||
if (!vtbllookup) {
|
||||
// Get the actual function value to call.
|
||||
LLValue* funcval = 0;
|
||||
if (vtbllookup)
|
||||
{
|
||||
DImValue thisVal(e1type, vthis);
|
||||
funcval = DtoVirtualFunctionPointer(&thisVal, fdecl, toChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
fdecl->codegen(Type::sir);
|
||||
funcval = fdecl->ir.irFunc->func;
|
||||
assert(funcval);
|
||||
}
|
||||
else {
|
||||
DImValue vthis3(e1type, vthis);
|
||||
funcval = DtoVirtualFunctionPointer(&vthis3, fdecl, toChars());
|
||||
}
|
||||
assert(funcval);
|
||||
|
||||
return new DFuncValue(fdecl, funcval, vthis2);
|
||||
return new DFuncValue(fdecl, funcval, passedThis);
|
||||
}
|
||||
else {
|
||||
printf("unsupported dotvarexp: %s\n", var->toChars());
|
||||
|
||||
Reference in New Issue
Block a user