Issue 24528 - Add offending member to "no size because of forward reference" error
Summary: Add offending member to "no size because of forward reference" error
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 enhancement
Assignee: No Owner
URL:
Keywords: diagnostic, industry
Depends on:
Blocks:
 
Reported: 2024-04-29 08:43 UTC by johanengelen
Modified: 2024-04-29 12:38 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description johanengelen 2024-04-29 08:43:44 UTC
I don't have a testcase (I hit it on a complex codebase), but improvement is needed for the "no size because of forward reference" error reported by `AggregateDeclaration.determineSize` (https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L237).

The error now reads:
`Error: struct `A` no size because of forward reference`
It is unclear what the forward reference is. Is there a forward reference inside struct `A`? Is struct `A` referenced elsewhere (if yes, where?) which constitutes the forward reference?

What helped me find the fwd reference quickly in the code, is hacking the compiler to add extra diagnostics. All paths that lead to the error (`goto LFail` or the "fallthrough" before `Lfail`) should store which struct member field is causing trouble, such that it can be reported upon error.

1. `determineSize` https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L218
2. `determineFields` https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L224
3. `finalizeSize` https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/aggregate.d#L226

In my case, I added extra error output inside `finalizeSize` (https://github.com/dlang/dmd/blob/4414c2aeaa968ed0ce638a8162d3254dbf2ee2f5/compiler/src/dmd/dstruct.d#L297) which got me to the actual code problem.

Perhaps change this code:
```
        for (size_t i = 0; i < members.length; i++)
        {
            Dsymbol s = (*members)[i];
            s.setFieldOffset(this, &fieldState, isunion);
        }
        if (type.ty == Terror)
        {
            .error(loc, "finalizeSize err");
            errors = true;
            return;
        }
```

to this:

```
        for (size_t i = 0; i < members.length; i++)
        {
            Dsymbol s = (*members)[i];
            s.setFieldOffset(this, &fieldState, isunion);
            if (type.ty == Terror)
            {
                error(loc, "error on member `%s`", s.toPrettyChars);
                errors = true;
                return;
            }
        }
```