Skip to content

Commit e15d801

Browse files
Fix issue 18095 - Add support for pragma(mangle) on alias declarations
This allows to override the mangling of a type in an alias declaration as follows: ```d pragma(mangle, "foo") alias foo = int; static assert(foo.mangleof == "foo"); static assert(int.mangleof == "i"); ``` Overriding the mangling of a type in an alias allows for more generic solution to get the correct mangling of `c_long/c_ulong` for C++ functions. With the current solution the compiler is looking for a struct with the name `__c_long/__c_ulong` and special cases the mangling for that particular struct. Since D doesn't have implicit conversions to structs one are also forced cast/explicitly construct a `__c_long` struct when calling a function which uses the `__c_long` type as a parameter. With an alias that's not necessary anymore.
1 parent 50f0d43 commit e15d801

File tree

7 files changed

+155
-16
lines changed

7 files changed

+155
-16
lines changed

src/dmd/cppmangle.d

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,12 @@ public:
735735
else
736736
{
737737
// For value types, strip const/immutable/shared from the head of the type
738-
t.mutableOf().unSharedOf().accept(this);
738+
auto unqualified = t.mutableOf().unSharedOf();
739+
740+
if (unqualified.mangleOverride)
741+
buf.writestring(unqualified.mangleOverride);
742+
else
743+
unqualified.accept(this);
739744
}
740745
}
741746

src/dmd/dmangle.d

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,9 @@ public:
267267

268268
final void mangleType(Type t)
269269
{
270-
if (!backrefType(t))
270+
if (t.mangleOverride)
271+
buf.writestring(t.mangleOverride);
272+
else if (!backrefType(t))
271273
t.accept(this);
272274
}
273275

@@ -1105,7 +1107,9 @@ extern (C++) const(char)* mangleExact(FuncDeclaration fd)
11051107

11061108
extern (C++) void mangleToBuffer(Type t, OutBuffer* buf)
11071109
{
1108-
if (t.deco)
1110+
if (t.mangleOverride)
1111+
buf.writestring(t.mangleOverride);
1112+
else if (t.deco)
11091113
buf.writestring(t.deco);
11101114
else
11111115
{

src/dmd/dsymbolsem.d

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ import dmd.visitor;
7777

7878
enum LOG = false;
7979

80-
private uint setMangleOverride(Dsymbol s, char* sym)
80+
private uint setMangleOverride(Dsymbol s, char* sym, Scope* sc)
8181
{
8282
AttribDeclaration ad = s.isAttribDeclaration();
8383
if (ad)
@@ -86,12 +86,16 @@ private uint setMangleOverride(Dsymbol s, char* sym)
8686
uint nestedCount = 0;
8787
if (decls && decls.dim)
8888
for (size_t i = 0; i < decls.dim; ++i)
89-
nestedCount += setMangleOverride((*decls)[i], sym);
89+
nestedCount += setMangleOverride((*decls)[i], sym, sc);
9090
return nestedCount;
9191
}
92-
else if (s.isFuncDeclaration() || s.isVarDeclaration())
92+
else if (s.isFuncDeclaration() || s.isVarDeclaration() || s.isAliasDeclaration)
9393
{
9494
s.isDeclaration().mangleOverride = sym;
95+
96+
if (s.isAliasDeclaration)
97+
semantic2(s, sc);
98+
9599
return 1;
96100
}
97101
else
@@ -382,6 +386,19 @@ extern(C++) final class Semantic2Visitor : Visitor
382386
}
383387
}
384388

389+
override void visit(AliasDeclaration ad)
390+
{
391+
//printf("AliasDeclaration.semantic2 %s\n", ad.toChars);
392+
393+
if (!ad.mangleOverride || ad.type.mangleOverride)
394+
return;
395+
396+
// make a copy to make sure the mangling of the original type isn't
397+
// overwritten
398+
ad.type = ad.type.copy();
399+
ad.type.mangleOverride = ad.mangleOverride;
400+
}
401+
385402
override void visit(Import i)
386403
{
387404
//printf("Import::semantic2('%s')\n", toChars());
@@ -2915,7 +2932,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
29152932
override void visit(PragmaDeclaration pd)
29162933
{
29172934
// Should be merged with PragmaStatement
2918-
//printf("\tPragmaDeclaration::semantic '%s'\n", pd.toChars());
2935+
//printf("PragmaDeclaration::semantic '%s'\n", pd.toChars());
29192936
if (pd.ident == Id.msg)
29202937
{
29212938
if (pd.args)
@@ -3126,7 +3143,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
31263143
char* name = cast(char*)mem.xmalloc(se.len + 1);
31273144
memcpy(name, se.string, se.len);
31283145
name[se.len] = 0;
3129-
uint cnt = setMangleOverride(s, name);
3146+
uint cnt = setMangleOverride(s, name, sc2);
31303147
if (cnt > 1)
31313148
pd.error("can only apply to a single declaration");
31323149
}
@@ -7016,7 +7033,7 @@ Laftersemantic:
70167033
// function used to perform semantic on AliasDeclaration
70177034
void aliasSemantic(AliasDeclaration ds, Scope* sc)
70187035
{
7019-
//printf("AliasDeclaration::semantic() %s\n", toChars());
7036+
//printf("AliasDeclaration::semantic() %s\n", ds.toChars());
70207037
if (ds.aliassym)
70217038
{
70227039
auto fd = ds.aliassym.isFuncLiteralDeclaration();

src/dmd/expressionsem.d

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9428,7 +9428,17 @@ extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
94289428

94299429
Expression semanticX(DotIdExp exp, Scope* sc)
94309430
{
9431-
//printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
9431+
static Expression mangleToBuffer(Node)(Node node, DotIdExp exp, Scope* sc)
9432+
if (is(Node == Type) || is(Node == Dsymbol))
9433+
{
9434+
OutBuffer buf;
9435+
.mangleToBuffer(node, &buf);
9436+
const s = buf.peekSlice();
9437+
auto e = new StringExp(exp.loc, buf.extractString(), s.length);
9438+
return e.expressionSemantic(sc);
9439+
}
9440+
9441+
//printf("DotIdExp::semanticX(this = %p, '%s')\n", exp, exp.toChars());
94329442
if (Expression ex = unaSemantic(exp, sc))
94339443
return ex;
94349444

@@ -9454,7 +9464,17 @@ Expression semanticX(DotIdExp exp, Scope* sc)
94549464
{
94559465
TemplateExp te = cast(TemplateExp)exp.e1;
94569466
ds = te.fd ? cast(Dsymbol)te.fd : te.td;
9467+
goto L1;
94579468
}
9469+
case TOKtype:
9470+
{
9471+
auto type = (cast(TypeExp)exp.e1).type;
9472+
9473+
if (type.mangleOverride)
9474+
return mangleToBuffer(type, exp, sc);
9475+
else
9476+
break;
9477+
}
94589478
L1:
94599479
{
94609480
assert(ds);
@@ -9465,12 +9485,7 @@ Expression semanticX(DotIdExp exp, Scope* sc)
94659485
return new ErrorExp();
94669486
}
94679487
}
9468-
OutBuffer buf;
9469-
mangleToBuffer(ds, &buf);
9470-
const s = buf.peekSlice();
9471-
Expression e = new StringExp(exp.loc, buf.extractString(), s.length);
9472-
e = e.expressionSemantic(sc);
9473-
return e;
9488+
return mangleToBuffer(ds, exp, sc);
94749489
}
94759490
default:
94769491
break;

src/dmd/mtype.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ extern (C++) abstract class Type : RootObject
513513

514514
type* ctype; // for back end
515515

516+
/// Overridden symbol with `pragma(mangle, "...")`.
517+
const(char)* mangleOverride;
518+
516519
extern (C++) static __gshared Type tvoid;
517520
extern (C++) static __gshared Type tint8;
518521
extern (C++) static __gshared Type tuns8;

src/dmd/mtype.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ class Type : public RootObject
164164

165165
type *ctype; // for back end
166166

167+
const char *mangleOverride; // overridden symbol with pragma(mangle, "...")
168+
167169
static Type *tvoid;
168170
static Type *tint8;
169171
static Type *tuns8;

test/runnable/mangle.d

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,99 @@ void fooB(void delegate (void delegate()) scope dg)
589589
//pragma(msg, fooB.mangleof);
590590
static assert(typeof(fooA).mangleof != typeof(fooB).mangleof);
591591

592+
/***************************************************/
593+
594+
@("test overriding mangling for alias declaration")
595+
struct TestOverridingManglingAlias
596+
{
597+
enum baseMangling = "6mangle27TestOverridingManglingAlias";
598+
599+
@("basic type")
600+
{
601+
@("override mangling")
602+
{
603+
pragma(mangle, "bar") alias a = int;
604+
static assert(a.mangleof == "bar");
605+
}
606+
607+
@("alias without overriding")
608+
{
609+
alias b = int;
610+
static assert(b.mangleof == "i");
611+
}
612+
613+
@("default mangling of basic type")
614+
{
615+
static assert(int.mangleof == "i");
616+
}
617+
}
618+
619+
@("struct")
620+
{
621+
struct Struct
622+
{
623+
enum defaultMangling = "S" ~ baseMangling ~"6Struct";
624+
}
625+
626+
@("override mangling")
627+
{
628+
pragma(mangle, "Bar") alias c = Struct;
629+
static assert(c.mangleof == "Bar");
630+
}
631+
632+
@("alias without overriding")
633+
{
634+
alias d = Struct;
635+
static assert(d.mangleof == Struct.defaultMangling);
636+
}
637+
638+
@("default mangling of struct")
639+
{
640+
static assert(Struct.mangleof == Struct.defaultMangling);
641+
}
642+
}
643+
644+
@("class")
645+
{
646+
struct Class
647+
{
648+
enum defaultMangling = "S" ~ baseMangling ~ "5Class";
649+
}
650+
651+
@("override mangling")
652+
{
653+
pragma(mangle, "Bar") alias e = Struct;
654+
static assert(e.mangleof == "Bar");
655+
}
656+
657+
@("alias without overriding")
658+
{
659+
alias f = Class;
660+
static assert(f.mangleof == Class.defaultMangling);
661+
}
662+
663+
@("default mangling of class")
664+
{
665+
static assert(Class.mangleof == Class.defaultMangling);
666+
}
667+
}
668+
669+
@("function")
670+
{
671+
@("type of parameter is an alias")
672+
{
673+
pragma(mangle, "foo") alias g = int;
674+
void h(g);
675+
static assert(h.mangleof == "_D" ~ baseMangling ~ "1hMFfooZv");
676+
}
677+
678+
@("default mangling of function")
679+
{
680+
void i(int);
681+
static assert(i.mangleof == "_D" ~ baseMangling ~ "1iMFiZv");
682+
}
683+
}
684+
}
592685

593686
/***************************************************/
594687

0 commit comments

Comments
 (0)