Bug 24276 – ImportC: typedef aliases not emitted correctly in .di files

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2023-12-09T17:10:01Z
Last change time
2023-12-12T08:36:24Z
Keywords
pull
Assigned to
No Owner
Creator
Tom Kral

Comments

Comment #0 by mail — 2023-12-09T17:10:01Z
Consider the following C file with a typedef alias: // hmm.c typedef union hmm_vec2 { struct { float X, Y; }; float Elements[2]; } hmm_vec2; typedef hmm_vec2 hmm_v2; used in a D program: // main.d import hmm; void main() { hmm_v2 v2 = { X: 1, Y: 2 }; } Compiling both files in a single pass, without emitting the .di file, i.e.: $ dmd main.d hmm.c works fine. But doing it by generating hmm.o and hmm.di first, and then linking the program, fails: $ dmd -c hmm.c -Hf=hmm.di $ dmd main.d hmm.o hmm.di(13): Error: union `hmm.hmm_vec2` conflicts with union `hmm.hmm_vec2` at hmm.di(4) The emitted .di file looks like this: extern (C) { union hmm_vec2 { struct { float X = void; float Y = void; } float[2] Elements = void; } union hmm_vec2; ... The second union is incorrect; it should have been the typedef alias alias hmm_v2 = hmm_vec2; instead.
Comment #1 by bugzilla — 2023-12-12T05:26:45Z
This is coming from this line in the C parser: if (isalias) { auto ad = new AST.AliasDeclaration(token.loc, id, dt); ad.adFlags |= ad.hidden; // do not print when generating .di files s = ad; } https://github.com/dlang/dmd/blob/master/compiler/src/dmd/cparse.d#L1937
Comment #2 by bugzilla — 2023-12-12T06:49:45Z
Simplifying: typedef union S { int x; } S; typedef S T; Produces the .di file: // D import file generated from 'test.i' extern (C) { union S { int x = void; } union S; alias T = S; // this line is missing } I can fix it to emit the missing `alias T` line. But getting rid of the extra `union S;` is a problem. The trouble is, the .di file is generated before the symbol table is built, and so doesn't know about the collision. D and C have different semantics (in C you can redeclare a tag name as many times as you want, but not in D). A .di file is compiled as a D file, not a C. The impedance mismatch between C and D is taken care of in the semantic routines, but the .di file has not undergone semantic analysis. This looks like this will be one of those cases where human tweaking of the .di file or the C file will be needed. Either delete the `union S;` from the .di file, or remove the first typedef, or don't name the typedef the same as the tag name. In general, C=>D translation problems are inevitable when using a C symbol with the same name as a C tag symbol. These problems exist for every source translation program, which is why ImportC is a compiler not a translator, and why importing the C code works fine, as you reported.
Comment #3 by dlang-bot — 2023-12-12T06:59:16Z
@WalterBright created dlang/dmd pull request #15899 "fix Issue 24276 - ImportC: typedef aliases not emitted correctly in .…" fixing this issue: - fix Issue 24276 - ImportC: typedef aliases not emitted correctly in .di files https://github.com/dlang/dmd/pull/15899
Comment #4 by dlang-bot — 2023-12-12T08:36:24Z
dlang/dmd pull request #15899 "fix Issue 24276 - ImportC: typedef aliases not emitted correctly in .…" was merged into master: - 0cc531948c80af3afcab95f7edf397651592ad40 by Walter Bright: fix Issue 24276 - ImportC: typedef aliases not emitted correctly in .di files https://github.com/dlang/dmd/pull/15899