mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 03:46:02 +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
40
ddmd/func.d
40
ddmd/func.d
|
@ -1102,8 +1102,13 @@ extern (C++) class FuncDeclaration : Declaration
|
||||||
* even if this functions doesn't have an out contract.
|
* even if this functions doesn't have an out contract.
|
||||||
*/
|
*/
|
||||||
fdensureParams = new Expressions();
|
fdensureParams = new Expressions();
|
||||||
if (outId)
|
/* The return type may still need to be inferred, so we can't know for
|
||||||
fdensureParams.push(new IdentifierExp(loc, outId));
|
* 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)
|
if (fensure)
|
||||||
{
|
{
|
||||||
|
@ -1123,15 +1128,19 @@ extern (C++) class FuncDeclaration : Declaration
|
||||||
}
|
}
|
||||||
Loc loc = fensure.loc;
|
Loc loc = fensure.loc;
|
||||||
Parameter p = null;
|
Parameter p = null;
|
||||||
if (outId)
|
version(IN_LLVM)
|
||||||
{
|
{
|
||||||
p = new Parameter(STCref | STCconst, f.nextOf(), outId, null);
|
if (outId || inferRetType)
|
||||||
version(IN_LLVM)
|
|
||||||
{
|
{
|
||||||
|
p = new Parameter(STCref | STCconst, f.nextOf(), outId ? outId : Id.result, null);
|
||||||
fparams.insert(0, p);
|
fparams.insert(0, p);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (outId)
|
||||||
{
|
{
|
||||||
|
p = new Parameter(STCref | STCconst, f.nextOf(), outId, null);
|
||||||
fparams.push(p);
|
fparams.push(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1915,6 +1924,13 @@ extern (C++) class FuncDeclaration : Declaration
|
||||||
if (!global.params.useIn)
|
if (!global.params.useIn)
|
||||||
freq = null;
|
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)
|
if (fens)
|
||||||
{
|
{
|
||||||
/* fensure is composed of the [out] contracts
|
/* fensure is composed of the [out] contracts
|
||||||
|
@ -1934,7 +1950,17 @@ extern (C++) class FuncDeclaration : Declaration
|
||||||
if (out_params.dim > 0)
|
if (out_params.dim > 0)
|
||||||
{
|
{
|
||||||
Parameter p = (*out_params)[0];
|
Parameter p = (*out_params)[0];
|
||||||
p.type = f.next;
|
version(IN_LLVM)
|
||||||
|
{
|
||||||
|
if (f.next.toBasetype().ty == Tvoid)
|
||||||
|
out_params.remove(0);
|
||||||
|
else
|
||||||
|
p.type = f.next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p.type = f.next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1060,8 +1060,9 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
|
|
||||||
DtoCreateNestedContext(funcGen);
|
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);
|
DtoVarDeclaration(fd->vresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue