February 16, 2023 [Issue 23722] New: Lambdas are mangled incorrectly when using multiple compilation units, resulting in incorrect code | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23722 Issue ID: 23722 Summary: Lambdas are mangled incorrectly when using multiple compilation units, resulting in incorrect code Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nobody@puremagic.com Reporter: zach-dmd@cs.stanford.edu I have two files, foo.d and bar.d: bar.d: ``` module bar; struct A { import core.stdc.stdio; alias x = () { printf("x\n"); }; alias y = () { printf("y\n"); }; } // do_x should call A.x (and print "x") void do_x() { A.x(); } ``` and foo.d: ``` module foo; import bar; // do_y should call A.y (and print "y") void do_y() { A.y(); } extern (C) void main() { do_y(); // should print y do_x(); // should print x } ``` This program should print `y` and then `x`. If I compile as one compilation unit then it works fine: ``` $ dmd -betterC foo.d bar.d $ ./foo y x ``` But if I compile with separate compilation units then it has incorrect behavior: ``` $ dmd -betterC -c foo.d $ dmd -betterC -c bar.d $ gcc foo.o bar.o -o foo $ ./foo x x ``` This is because in foo.d `A.y` is mangled as `_D3bar1A9__lambda4FNbNiZv`, but and in bar.d `A.x` is mangled as `_D3bar1A9__lambda4FNbNiZv`. They both have the same mangled value but they are different lambdas that do different things. Thus the call to `A.y` ends up being a call to `A.x` once the linker has resolved the symbols. The mangled name seems to use a count of instantiated lambdas for uniqueness, but it should instead to depend on something that is unique across compilation units, such as a counter for the total number of lambdas (this appears to be the approach C++ takes to solve this). Thanks. -- |
Copyright © 1999-2021 by the D Language Foundation