Skip to content

Commit 08b37dd

Browse files
CHIKI BadreddineCHIKI Badreddine
authored andcommitted
Fix Bugzilla Issue 22688 - disambiguate module and struct mangling by zero-padding modules
1 parent e3c9e82 commit 08b37dd

8 files changed

Lines changed: 704 additions & 630 deletions

File tree

compiler/src/dmd/mangle/package.d

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,17 @@ public:
567567
}
568568
else if (p.getIdent())
569569
{
570-
mangleIdentifier(p.ident, s);
570+
/* Use a leading zero in the length prefix for packages and modules
571+
* to disambiguate them from other parent symbols (e.g. structs, classes, enums).
572+
* For example, module `bar` is mangled as `03bar` while
573+
* struct `bar` stays as `3bar`. Leading zeros don't change
574+
* the numeric value, so existing demanglers handle this
575+
* correctly.
576+
* See: https://github.com/dlang/dmd/issues/22688
577+
*/
578+
const zeroPad = (p.isModule() !is null) || (p.isPackage() !is null);
579+
if (!backref.addRefToIdentifier(*buf, p.ident))
580+
toBuffer(*buf, p.ident.toString(), s, zeroPad);
571581
if (FuncDeclaration f = p.isFuncDeclaration())
572582
mangleFunc(f, true);
573583
}
@@ -1225,15 +1235,23 @@ void writeBackRef(ref OutBuffer buf, size_t pos) @safe
12251235

12261236
/************************************************************
12271237
* Write length prefixed string to buf.
1238+
* Params:
1239+
* buf = buffer to write to
1240+
* id = identifier string to write
1241+
* s = symbol for error reporting
1242+
* zeroPad = if true, prefix the length with a leading '0'
1243+
* to disambiguate non-module symbols from modules
12281244
*/
12291245
private
1230-
extern (D) void toBuffer(ref OutBuffer buf, const(char)[] id, Dsymbol s)
1246+
extern (D) void toBuffer(ref OutBuffer buf, const(char)[] id, Dsymbol s, bool zeroPad = false)
12311247
{
12321248
const len = id.length;
12331249
if (buf.length + len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
12341250
error(s.loc, "%s `%s` excessive length %llu for symbol, possible recursive expansion?", s.kind, s.toPrettyChars, cast(ulong)(buf.length + len));
12351251
else
12361252
{
1253+
if (zeroPad)
1254+
buf.writeByte('0');
12371255
buf.print(len);
12381256
buf.writestring(id);
12391257
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module issue22688.bar;
2+
3+
int zen() => 1;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module issue22688;
2+
3+
import issue22688.bar;
4+
5+
struct bar
6+
{
7+
static int zen() => 2;
8+
}
9+
10+
void test22688()
11+
{
12+
// The module function and the struct function must have
13+
// different mangled names to avoid linker collisions.
14+
// The struct parent component gets a leading zero prefix:
15+
// module bar -> "3bar", struct bar -> "03bar".
16+
static assert(zen.mangleof != bar.zen.mangleof,
17+
"Module and struct functions must have different mangles");
18+
19+
// Module-level zen: issue22688.bar.zen (bar is a module)
20+
// Struct-level zen: issue22688.bar.zen (bar is a struct, gets leading zero)
21+
static assert(zen.mangleof == "_D10issue226883bar3zenFZi",
22+
"Module function zen should use normal module mangling");
23+
static assert(bar.zen.mangleof == "_D10issue2268803bar3zenFZi",
24+
"Struct function zen should use zero-padded struct mangling");
25+
26+
assert(zen() == 1);
27+
assert(bar.zen() == 2);
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// EXTRA_FILES: imports/issue22688/package.d imports/issue22688/bar.d
2+
3+
module issue22688_test;
4+
5+
import issue22688;
6+
7+
void main()
8+
{
9+
test22688();
10+
}

0 commit comments

Comments
 (0)