mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 20:06:03 +03:00
Fix parameter-less out contracts of virtual methods with auto return type
These out contracts can still access the return value via __result. LDC always passes the return value by reference to the out contract - as long as there is a result (non-void). As the return type may still need to be inferred in the first semantic pass, reserve a parameter there and remove it later in semantic3() in case it is void (or finalize its type). Fixes compilable/test17502.
This commit is contained in:
parent
41aae46b91
commit
1fa90a0381
2 changed files with 36 additions and 9 deletions
36
ddmd/func.d
36
ddmd/func.d
|
@ -1102,8 +1102,13 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
* even if this functions doesn't have an out contract.
|
||||
*/
|
||||
fdensureParams = new Expressions();
|
||||
if (outId)
|
||||
fdensureParams.push(new IdentifierExp(loc, outId));
|
||||
/* The return type may still need to be inferred, so we can't know for
|
||||
* sure whether there's a return value to be passed to the out contract.
|
||||
* Reserve a parameter for now and remove it later in semantic3() in case
|
||||
* the return type is void (or finalize its type).
|
||||
*/
|
||||
if (outId || inferRetType)
|
||||
fdensureParams.push(new IdentifierExp(loc, outId ? outId : Id.result));
|
||||
}
|
||||
if (fensure)
|
||||
{
|
||||
|
@ -1123,15 +1128,19 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
}
|
||||
Loc loc = fensure.loc;
|
||||
Parameter p = null;
|
||||
if (outId)
|
||||
{
|
||||
p = new Parameter(STCref | STCconst, f.nextOf(), outId, null);
|
||||
version(IN_LLVM)
|
||||
{
|
||||
if (outId || inferRetType)
|
||||
{
|
||||
p = new Parameter(STCref | STCconst, f.nextOf(), outId ? outId : Id.result, null);
|
||||
fparams.insert(0, p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outId)
|
||||
{
|
||||
p = new Parameter(STCref | STCconst, f.nextOf(), outId, null);
|
||||
fparams.push(p);
|
||||
}
|
||||
}
|
||||
|
@ -1915,6 +1924,13 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
if (!global.params.useIn)
|
||||
freq = null;
|
||||
}
|
||||
version(IN_LLVM)
|
||||
{
|
||||
// If a void return type has been inferred, remove the return value
|
||||
// parameter for the out contract reserved in the first semantic pass.
|
||||
if (inferRetType && fdensureParams && f.next.toBasetype().ty == Tvoid)
|
||||
fdensureParams.remove(0);
|
||||
}
|
||||
if (fens)
|
||||
{
|
||||
/* fensure is composed of the [out] contracts
|
||||
|
@ -1934,8 +1950,18 @@ extern (C++) class FuncDeclaration : Declaration
|
|||
if (out_params.dim > 0)
|
||||
{
|
||||
Parameter p = (*out_params)[0];
|
||||
version(IN_LLVM)
|
||||
{
|
||||
if (f.next.toBasetype().ty == Tvoid)
|
||||
out_params.remove(0);
|
||||
else
|
||||
p.type = f.next;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.type = f.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fensure && f.next.ty != Tvoid)
|
||||
|
|
|
@ -1060,8 +1060,9 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
|
||||
DtoCreateNestedContext(funcGen);
|
||||
|
||||
if (fd->vresult && !fd->vresult->nestedrefs.dim) // FIXME: not sure here :/
|
||||
{
|
||||
// Declare the special __result variable. If it's captured, it has already
|
||||
// been allocated by DtoCreateNestedContext().
|
||||
if (fd->vresult) {
|
||||
DtoVarDeclaration(fd->vresult);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue