@@ -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 */
12291245private
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 }
0 commit comments