Skip to content

Commit 41f6e94

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 5c76d45 commit 41f6e94

File tree

9 files changed

+196
-16
lines changed

9 files changed

+196
-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
@@ -268,7 +268,9 @@ public:
268268

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

@@ -1106,7 +1108,9 @@ extern (C++) const(char)* mangleExact(FuncDeclaration fd)
11061108

11071109
extern (C++) void mangleToBuffer(Type t, OutBuffer* buf)
11081110
{
1109-
if (t.deco)
1111+
if (t.mangleOverride)
1112+
buf.writestring(t.mangleOverride);
1113+
else if (t.deco)
11101114
buf.writestring(t.deco);
11111115
else
11121116
{

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: 10 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;
@@ -1053,8 +1056,15 @@ extern (C++) abstract class Type : RootObject
10531056
StringValue* sv = stringtable.lookup(t.deco, strlen(t.deco));
10541057
if (sv && sv.ptrvalue)
10551058
{
1059+
auto mangleOverride = t.mangleOverride;
10561060
t = cast(Type)sv.ptrvalue;
10571061
assert(t.deco);
1062+
1063+
if (mangleOverride)
1064+
{
1065+
t = t.copy();
1066+
t.mangleOverride = mangleOverride;
1067+
}
10581068
}
10591069
else
10601070
assert(0);

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;

src/dmd/typesem.d

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,7 @@ static Type merge(Type type)
14001400
StringValue* sv = type.stringtable.update(cast(char*)buf.data, buf.offset);
14011401
if (sv.ptrvalue)
14021402
{
1403+
auto mangleOverride = t.mangleOverride;
14031404
t = cast(Type)sv.ptrvalue;
14041405
debug
14051406
{
@@ -1409,6 +1410,12 @@ static Type merge(Type type)
14091410
}
14101411
assert(t.deco);
14111412
//printf("old value, deco = '%s' %p\n", t.deco, t.deco);
1413+
1414+
if (mangleOverride)
1415+
{
1416+
t = t.copy();
1417+
t.mangleOverride = mangleOverride;
1418+
}
14121419
}
14131420
else
14141421
{

test/compilable/cppmangle.d

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,40 @@ version (linux)
444444
{
445445
static assert(test36.mangleof == "_Z6test36PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPiPS12_");
446446
}
447+
448+
// test overriding mangling for alias declaration
449+
version (Posix) extern (C++) struct TestOverridingManglingAlias
450+
{
451+
version (OSX)
452+
enum prefix = "_";
453+
else
454+
enum prefix = "";
455+
456+
enum baseMangling = prefix ~ "_ZN27TestOverridingManglingAlias";
457+
458+
// basic type
459+
460+
// override mangling
461+
pragma(mangle, "bar") alias a = int;
462+
static assert(a.mangleof == "bar");
463+
464+
// alias without overriding
465+
alias b = int;
466+
static assert(b.mangleof == "i");
467+
468+
// default mangling of basic type
469+
static assert(int.mangleof == "i");
470+
471+
472+
473+
// function
474+
475+
// type of parameter is an alias"
476+
pragma(mangle, "foo") alias c = int;
477+
void d(c);
478+
static assert(d.mangleof == baseMangling ~ "1dEfoo");
479+
480+
// default mangling of function"
481+
void e(int);
482+
static assert(e.mangleof == baseMangling ~ "1eEi");
483+
}

test/runnable/mangle.d

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,89 @@ 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+
pragma(mangle, "bar") alias a = int;
603+
static assert(a.mangleof == "bar");
604+
605+
// alias without overriding
606+
alias b = int;
607+
static assert(b.mangleof == "i");
608+
609+
// default mangling of basic type
610+
static assert(int.mangleof == "i");
611+
612+
// verify that the alias and the aliased type is the same type
613+
pragma(mangle, "bar") alias c = int;
614+
static assert(is(int == c));
615+
616+
// override mangling at intermediate step
617+
alias d = int;
618+
pragma(mangle, "foo") alias e = d;
619+
alias f = e;
620+
f g;
621+
static assert(g.mangleof == "_D" ~ baseMangling ~ "1g" ~ e.mangleof);
622+
623+
624+
625+
// struct
626+
627+
struct Struct
628+
{
629+
enum defaultMangling = "S" ~ baseMangling ~"6Struct";
630+
}
631+
632+
// override mangling
633+
pragma(mangle, "Bar") alias h = Struct;
634+
static assert(h.mangleof == "Bar");
635+
636+
// alias without overriding
637+
alias i = Struct;
638+
static assert(i.mangleof == Struct.defaultMangling);
639+
640+
// default mangling of struct
641+
static assert(Struct.mangleof == Struct.defaultMangling);
642+
643+
644+
645+
// class
646+
struct Class
647+
{
648+
enum defaultMangling = "S" ~ baseMangling ~ "5Class";
649+
}
650+
651+
// override mangling
652+
pragma(mangle, "Bar") alias j = Struct;
653+
static assert(j.mangleof == "Bar");
654+
655+
// alias without overriding
656+
alias k = Class;
657+
static assert(k.mangleof == Class.defaultMangling);
658+
659+
// default mangling of class
660+
static assert(Class.mangleof == Class.defaultMangling);
661+
662+
663+
664+
// function
665+
666+
// type of parameter is an alias"
667+
pragma(mangle, "foo") alias l = int;
668+
void m(l);
669+
static assert(m.mangleof == "_D" ~ baseMangling ~ "1mMFfooZv");
670+
671+
// default mangling of function"
672+
void n(int);
673+
static assert(n.mangleof == "_D" ~ baseMangling ~ "1nMFiZv");
674+
}
592675

593676
/***************************************************/
594677

0 commit comments

Comments
 (0)