1*627f7eb2Smrg
2*627f7eb2Smrg /* Compiler implementation of the D programming language
3*627f7eb2Smrg * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4*627f7eb2Smrg * written by Walter Bright
5*627f7eb2Smrg * http://www.digitalmars.com
6*627f7eb2Smrg * Distributed under the Boost Software License, Version 1.0.
7*627f7eb2Smrg * http://www.boost.org/LICENSE_1_0.txt
8*627f7eb2Smrg * https://github.com/D-Programming-Language/dmd/blob/master/src/cppmangle.c
9*627f7eb2Smrg */
10*627f7eb2Smrg
11*627f7eb2Smrg /**
12*627f7eb2Smrg * Do mangling for C++ linkage.
13*627f7eb2Smrg *
14*627f7eb2Smrg * References:
15*627f7eb2Smrg * Follows Itanium C++ ABI 1.86 section 5.1
16*627f7eb2Smrg * http://refspecs.linux-foundation.org/cxxabi-1.86.html#mangling
17*627f7eb2Smrg * which is where the grammar comments come from.
18*627f7eb2Smrg *
19*627f7eb2Smrg * Bugs:
20*627f7eb2Smrg * https://issues.dlang.org/query.cgi
21*627f7eb2Smrg * enter `C++, mangling` as the keywords.
22*627f7eb2Smrg */
23*627f7eb2Smrg
24*627f7eb2Smrg #include "root/dsystem.h"
25*627f7eb2Smrg
26*627f7eb2Smrg #include "mars.h"
27*627f7eb2Smrg #include "dsymbol.h"
28*627f7eb2Smrg #include "mtype.h"
29*627f7eb2Smrg #include "scope.h"
30*627f7eb2Smrg #include "init.h"
31*627f7eb2Smrg #include "expression.h"
32*627f7eb2Smrg #include "attrib.h"
33*627f7eb2Smrg #include "declaration.h"
34*627f7eb2Smrg #include "template.h"
35*627f7eb2Smrg #include "id.h"
36*627f7eb2Smrg #include "enum.h"
37*627f7eb2Smrg #include "import.h"
38*627f7eb2Smrg #include "aggregate.h"
39*627f7eb2Smrg #include "target.h"
40*627f7eb2Smrg
41*627f7eb2Smrg typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param);
42*627f7eb2Smrg int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL);
43*627f7eb2Smrg
44*627f7eb2Smrg class CppMangleVisitor : public Visitor
45*627f7eb2Smrg {
46*627f7eb2Smrg Objects components; // array of components available for substitution
47*627f7eb2Smrg OutBuffer *buf; // append the mangling to buf[]
48*627f7eb2Smrg public:
49*627f7eb2Smrg Loc loc; // location for use in error messages
50*627f7eb2Smrg
51*627f7eb2Smrg // Write <seq-id> to buf
write_seq_id(size_t i)52*627f7eb2Smrg void write_seq_id(size_t i)
53*627f7eb2Smrg {
54*627f7eb2Smrg if (i >= 36)
55*627f7eb2Smrg {
56*627f7eb2Smrg write_seq_id(i / 36);
57*627f7eb2Smrg i %= 36;
58*627f7eb2Smrg }
59*627f7eb2Smrg i += (i < 10) ? '0' : 'A' - 10;
60*627f7eb2Smrg buf->writeByte((char)i);
61*627f7eb2Smrg }
62*627f7eb2Smrg
substitute(RootObject * p)63*627f7eb2Smrg bool substitute(RootObject *p)
64*627f7eb2Smrg {
65*627f7eb2Smrg //printf("substitute %s\n", p ? p->toChars() : NULL);
66*627f7eb2Smrg int i = find(p);
67*627f7eb2Smrg if (i >= 0)
68*627f7eb2Smrg {
69*627f7eb2Smrg //printf("\tmatch\n");
70*627f7eb2Smrg /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
71*627f7eb2Smrg */
72*627f7eb2Smrg buf->writeByte('S');
73*627f7eb2Smrg if (i)
74*627f7eb2Smrg {
75*627f7eb2Smrg write_seq_id(i - 1);
76*627f7eb2Smrg }
77*627f7eb2Smrg buf->writeByte('_');
78*627f7eb2Smrg return true;
79*627f7eb2Smrg }
80*627f7eb2Smrg return false;
81*627f7eb2Smrg }
82*627f7eb2Smrg
83*627f7eb2Smrg /******
84*627f7eb2Smrg * See if `p` exists in components[]
85*627f7eb2Smrg * Returns:
86*627f7eb2Smrg * index if found, -1 if not
87*627f7eb2Smrg */
find(RootObject * p)88*627f7eb2Smrg int find(RootObject *p)
89*627f7eb2Smrg {
90*627f7eb2Smrg //printf("find %p %d %s\n", p, p.dyncast(), p ? p.toChars() : NULL);
91*627f7eb2Smrg for (size_t i = 0; i < components.dim; i++)
92*627f7eb2Smrg {
93*627f7eb2Smrg if (p == components[i])
94*627f7eb2Smrg return (int)i;
95*627f7eb2Smrg }
96*627f7eb2Smrg return -1;
97*627f7eb2Smrg }
98*627f7eb2Smrg
99*627f7eb2Smrg /*********************
100*627f7eb2Smrg * Append p to components[]
101*627f7eb2Smrg */
append(RootObject * p)102*627f7eb2Smrg void append(RootObject *p)
103*627f7eb2Smrg {
104*627f7eb2Smrg //printf("append %p %d %s\n", p, p.dyncast(), p ? p.toChars() : "null");
105*627f7eb2Smrg components.push(p);
106*627f7eb2Smrg }
107*627f7eb2Smrg
108*627f7eb2Smrg /************************
109*627f7eb2Smrg * Determine if symbol is indeed the global ::std namespace.
110*627f7eb2Smrg * Params:
111*627f7eb2Smrg * s = symbol to check
112*627f7eb2Smrg * Returns:
113*627f7eb2Smrg * true if it is ::std
114*627f7eb2Smrg */
isStd(Dsymbol * s)115*627f7eb2Smrg static bool isStd(Dsymbol *s)
116*627f7eb2Smrg {
117*627f7eb2Smrg return (s &&
118*627f7eb2Smrg s->ident == Id::std && // the right name
119*627f7eb2Smrg s->isNspace() && // g++ disallows global "std" for other than a namespace
120*627f7eb2Smrg !getQualifier(s)); // at global level
121*627f7eb2Smrg }
122*627f7eb2Smrg
123*627f7eb2Smrg /************************
124*627f7eb2Smrg * Determine if type is a C++ fundamental type.
125*627f7eb2Smrg * Params:
126*627f7eb2Smrg * t = type to check
127*627f7eb2Smrg * Returns:
128*627f7eb2Smrg * true if it is a fundamental type
129*627f7eb2Smrg */
isFundamentalType(Type * t)130*627f7eb2Smrg static bool isFundamentalType(Type *t)
131*627f7eb2Smrg {
132*627f7eb2Smrg // First check the target whether some specific ABI is being followed.
133*627f7eb2Smrg bool isFundamental;
134*627f7eb2Smrg if (Target::cppFundamentalType(t, isFundamental))
135*627f7eb2Smrg return isFundamental;
136*627f7eb2Smrg if (t->ty == Tenum)
137*627f7eb2Smrg {
138*627f7eb2Smrg // Peel off enum type from special types.
139*627f7eb2Smrg TypeEnum *te = (TypeEnum *)t;
140*627f7eb2Smrg if (te->sym->isSpecial())
141*627f7eb2Smrg t = te->sym->getMemtype(Loc());
142*627f7eb2Smrg }
143*627f7eb2Smrg
144*627f7eb2Smrg // Fundamental arithmetic types:
145*627f7eb2Smrg // 1. integral types: bool, char, int, ...
146*627f7eb2Smrg // 2. floating point types: float, double, real
147*627f7eb2Smrg // 3. void
148*627f7eb2Smrg // 4. null pointer: std::nullptr_t (since C++11)
149*627f7eb2Smrg if (t->ty == Tvoid || t->ty == Tbool)
150*627f7eb2Smrg return true;
151*627f7eb2Smrg else if (t->ty == Tnull && global.params.cplusplus >= CppStdRevisionCpp11)
152*627f7eb2Smrg return true;
153*627f7eb2Smrg else
154*627f7eb2Smrg return t->isTypeBasic() && (t->isintegral() || t->isreal());
155*627f7eb2Smrg }
156*627f7eb2Smrg
157*627f7eb2Smrg /******************************
158*627f7eb2Smrg * Write the mangled representation of the template arguments.
159*627f7eb2Smrg * Params:
160*627f7eb2Smrg * ti = the template instance
161*627f7eb2Smrg */
template_args(TemplateInstance * ti)162*627f7eb2Smrg void template_args(TemplateInstance *ti)
163*627f7eb2Smrg {
164*627f7eb2Smrg /* <template-args> ::= I <template-arg>+ E
165*627f7eb2Smrg */
166*627f7eb2Smrg if (!ti) // could happen if std::basic_string is not a template
167*627f7eb2Smrg return;
168*627f7eb2Smrg buf->writeByte('I');
169*627f7eb2Smrg for (size_t i = 0; i < ti->tiargs->dim; i++)
170*627f7eb2Smrg {
171*627f7eb2Smrg RootObject *o = (*ti->tiargs)[i];
172*627f7eb2Smrg TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration();
173*627f7eb2Smrg assert(td);
174*627f7eb2Smrg TemplateParameter *tp = (*td->parameters)[i];
175*627f7eb2Smrg
176*627f7eb2Smrg /*
177*627f7eb2Smrg * <template-arg> ::= <type> # type or template
178*627f7eb2Smrg * ::= X <expression> E # expression
179*627f7eb2Smrg * ::= <expr-primary> # simple expressions
180*627f7eb2Smrg * ::= I <template-arg>* E # argument pack
181*627f7eb2Smrg */
182*627f7eb2Smrg if (tp->isTemplateTupleParameter())
183*627f7eb2Smrg {
184*627f7eb2Smrg buf->writeByte('I'); // argument pack
185*627f7eb2Smrg
186*627f7eb2Smrg // mangle the rest of the arguments as types
187*627f7eb2Smrg for (size_t j = i; j < ti->tiargs->dim; j++)
188*627f7eb2Smrg {
189*627f7eb2Smrg Type *t = isType((*ti->tiargs)[j]);
190*627f7eb2Smrg assert(t);
191*627f7eb2Smrg t->accept(this);
192*627f7eb2Smrg }
193*627f7eb2Smrg
194*627f7eb2Smrg buf->writeByte('E');
195*627f7eb2Smrg break;
196*627f7eb2Smrg }
197*627f7eb2Smrg if (tp->isTemplateTypeParameter())
198*627f7eb2Smrg {
199*627f7eb2Smrg Type *t = isType(o);
200*627f7eb2Smrg assert(t);
201*627f7eb2Smrg t->accept(this);
202*627f7eb2Smrg }
203*627f7eb2Smrg else if (TemplateValueParameter *tv = tp->isTemplateValueParameter())
204*627f7eb2Smrg {
205*627f7eb2Smrg // <expr-primary> ::= L <type> <value number> E # integer literal
206*627f7eb2Smrg if (tv->valType->isintegral())
207*627f7eb2Smrg {
208*627f7eb2Smrg Expression *e = isExpression(o);
209*627f7eb2Smrg assert(e);
210*627f7eb2Smrg buf->writeByte('L');
211*627f7eb2Smrg tv->valType->accept(this);
212*627f7eb2Smrg uinteger_t val = e->toUInteger();
213*627f7eb2Smrg if (!tv->valType->isunsigned() && (sinteger_t)val < 0)
214*627f7eb2Smrg {
215*627f7eb2Smrg val = -val;
216*627f7eb2Smrg buf->writeByte('n');
217*627f7eb2Smrg }
218*627f7eb2Smrg buf->printf("%llu", val);
219*627f7eb2Smrg buf->writeByte('E');
220*627f7eb2Smrg }
221*627f7eb2Smrg else
222*627f7eb2Smrg {
223*627f7eb2Smrg ti->error("Internal Compiler Error: C++ `%s` template value parameter is not supported", tv->valType->toChars());
224*627f7eb2Smrg fatal();
225*627f7eb2Smrg }
226*627f7eb2Smrg }
227*627f7eb2Smrg else if (tp->isTemplateAliasParameter())
228*627f7eb2Smrg {
229*627f7eb2Smrg Dsymbol *d = isDsymbol(o);
230*627f7eb2Smrg Expression *e = isExpression(o);
231*627f7eb2Smrg if (d && d->isFuncDeclaration())
232*627f7eb2Smrg {
233*627f7eb2Smrg bool is_nested = d->toParent3() &&
234*627f7eb2Smrg !d->toParent3()->isModule() &&
235*627f7eb2Smrg ((TypeFunction*)d->isFuncDeclaration()->type)->linkage == LINKcpp;
236*627f7eb2Smrg if (is_nested)
237*627f7eb2Smrg buf->writeByte('X');
238*627f7eb2Smrg buf->writeByte('L');
239*627f7eb2Smrg mangle_function(d->isFuncDeclaration());
240*627f7eb2Smrg buf->writeByte('E');
241*627f7eb2Smrg if (is_nested)
242*627f7eb2Smrg buf->writeByte('E');
243*627f7eb2Smrg }
244*627f7eb2Smrg else if (e && e->op == TOKvar && ((VarExp*)e)->var->isVarDeclaration())
245*627f7eb2Smrg {
246*627f7eb2Smrg VarDeclaration *vd = ((VarExp*)e)->var->isVarDeclaration();
247*627f7eb2Smrg buf->writeByte('L');
248*627f7eb2Smrg mangle_variable(vd, true);
249*627f7eb2Smrg buf->writeByte('E');
250*627f7eb2Smrg }
251*627f7eb2Smrg else if (d && d->isTemplateDeclaration() && d->isTemplateDeclaration()->onemember)
252*627f7eb2Smrg {
253*627f7eb2Smrg if (!substitute(d))
254*627f7eb2Smrg {
255*627f7eb2Smrg cpp_mangle_name(d, false);
256*627f7eb2Smrg }
257*627f7eb2Smrg }
258*627f7eb2Smrg else
259*627f7eb2Smrg {
260*627f7eb2Smrg ti->error("Internal Compiler Error: `%s` is unsupported parameter for C++ template", o->toChars());
261*627f7eb2Smrg fatal();
262*627f7eb2Smrg }
263*627f7eb2Smrg }
264*627f7eb2Smrg else if (tp->isTemplateThisParameter())
265*627f7eb2Smrg {
266*627f7eb2Smrg ti->error("Internal Compiler Error: C++ `%s` template this parameter is not supported", o->toChars());
267*627f7eb2Smrg fatal();
268*627f7eb2Smrg }
269*627f7eb2Smrg else
270*627f7eb2Smrg {
271*627f7eb2Smrg assert(0);
272*627f7eb2Smrg }
273*627f7eb2Smrg }
274*627f7eb2Smrg buf->writeByte('E');
275*627f7eb2Smrg }
276*627f7eb2Smrg
source_name(Dsymbol * s)277*627f7eb2Smrg void source_name(Dsymbol *s)
278*627f7eb2Smrg {
279*627f7eb2Smrg //printf("source_name(%s)\n", s->toChars());
280*627f7eb2Smrg if (TemplateInstance *ti = s->isTemplateInstance())
281*627f7eb2Smrg {
282*627f7eb2Smrg if (!substitute(ti->tempdecl))
283*627f7eb2Smrg {
284*627f7eb2Smrg append(ti->tempdecl);
285*627f7eb2Smrg const char *name = ti->tempdecl->toAlias()->ident->toChars();
286*627f7eb2Smrg buf->printf("%d", strlen(name));
287*627f7eb2Smrg buf->writestring(name);
288*627f7eb2Smrg }
289*627f7eb2Smrg template_args(ti);
290*627f7eb2Smrg }
291*627f7eb2Smrg else
292*627f7eb2Smrg {
293*627f7eb2Smrg const char *name = s->ident->toChars();
294*627f7eb2Smrg buf->printf("%d", strlen(name));
295*627f7eb2Smrg buf->writestring(name);
296*627f7eb2Smrg }
297*627f7eb2Smrg }
298*627f7eb2Smrg
299*627f7eb2Smrg /********
300*627f7eb2Smrg * See if s is actually an instance of a template
301*627f7eb2Smrg * Params:
302*627f7eb2Smrg * s = symbol
303*627f7eb2Smrg * Returns:
304*627f7eb2Smrg * if s is instance of a template, return the instance, otherwise return s
305*627f7eb2Smrg */
getInstance(Dsymbol * s)306*627f7eb2Smrg Dsymbol *getInstance(Dsymbol *s)
307*627f7eb2Smrg {
308*627f7eb2Smrg Dsymbol *p = s->toParent3();
309*627f7eb2Smrg if (p)
310*627f7eb2Smrg {
311*627f7eb2Smrg if (TemplateInstance *ti = p->isTemplateInstance())
312*627f7eb2Smrg return ti;
313*627f7eb2Smrg }
314*627f7eb2Smrg return s;
315*627f7eb2Smrg }
316*627f7eb2Smrg
317*627f7eb2Smrg /********
318*627f7eb2Smrg * Get qualifier for `s`, meaning the symbol
319*627f7eb2Smrg * that s is in the symbol table of.
320*627f7eb2Smrg * The module does not count as a qualifier, because C++
321*627f7eb2Smrg * does not have modules.
322*627f7eb2Smrg * Params:
323*627f7eb2Smrg * s = symbol that may have a qualifier
324*627f7eb2Smrg * Returns:
325*627f7eb2Smrg * qualifier, NULL if none
326*627f7eb2Smrg */
getQualifier(Dsymbol * s)327*627f7eb2Smrg static Dsymbol *getQualifier(Dsymbol *s)
328*627f7eb2Smrg {
329*627f7eb2Smrg Dsymbol *p = s->toParent3();
330*627f7eb2Smrg return (p && !p->isModule()) ? p : NULL;
331*627f7eb2Smrg }
332*627f7eb2Smrg
333*627f7eb2Smrg // Detect type char
isChar(RootObject * o)334*627f7eb2Smrg static bool isChar(RootObject *o)
335*627f7eb2Smrg {
336*627f7eb2Smrg Type *t = isType(o);
337*627f7eb2Smrg return (t && t->equals(Type::tchar));
338*627f7eb2Smrg }
339*627f7eb2Smrg
340*627f7eb2Smrg // Detect type ::std::char_traits<char>
isChar_traits_char(RootObject * o)341*627f7eb2Smrg static bool isChar_traits_char(RootObject *o)
342*627f7eb2Smrg {
343*627f7eb2Smrg return isIdent_char(Id::char_traits, o);
344*627f7eb2Smrg }
345*627f7eb2Smrg
346*627f7eb2Smrg // Detect type ::std::allocator<char>
isAllocator_char(RootObject * o)347*627f7eb2Smrg static bool isAllocator_char(RootObject *o)
348*627f7eb2Smrg {
349*627f7eb2Smrg return isIdent_char(Id::allocator, o);
350*627f7eb2Smrg }
351*627f7eb2Smrg
352*627f7eb2Smrg // Detect type ::std::ident<char>
isIdent_char(Identifier * ident,RootObject * o)353*627f7eb2Smrg static bool isIdent_char(Identifier *ident, RootObject *o)
354*627f7eb2Smrg {
355*627f7eb2Smrg Type *t = isType(o);
356*627f7eb2Smrg if (!t || t->ty != Tstruct)
357*627f7eb2Smrg return false;
358*627f7eb2Smrg Dsymbol *s = ((TypeStruct*)t)->toDsymbol(NULL);
359*627f7eb2Smrg if (s->ident != ident)
360*627f7eb2Smrg return false;
361*627f7eb2Smrg Dsymbol *p = s->toParent3();
362*627f7eb2Smrg if (!p)
363*627f7eb2Smrg return false;
364*627f7eb2Smrg TemplateInstance *ti = p->isTemplateInstance();
365*627f7eb2Smrg if (!ti)
366*627f7eb2Smrg return false;
367*627f7eb2Smrg Dsymbol *q = getQualifier(ti);
368*627f7eb2Smrg return isStd(q) && ti->tiargs->dim == 1 && isChar((*ti->tiargs)[0]);
369*627f7eb2Smrg }
370*627f7eb2Smrg
371*627f7eb2Smrg /***
372*627f7eb2Smrg * Detect template args <char, ::std::char_traits<char>>
373*627f7eb2Smrg * and write st if found.
374*627f7eb2Smrg * Returns:
375*627f7eb2Smrg * true if found
376*627f7eb2Smrg */
char_std_char_traits_char(TemplateInstance * ti,const char * st)377*627f7eb2Smrg bool char_std_char_traits_char(TemplateInstance *ti, const char *st)
378*627f7eb2Smrg {
379*627f7eb2Smrg if (ti->tiargs->dim == 2 &&
380*627f7eb2Smrg isChar((*ti->tiargs)[0]) &&
381*627f7eb2Smrg isChar_traits_char((*ti->tiargs)[1]))
382*627f7eb2Smrg {
383*627f7eb2Smrg buf->writestring(st);
384*627f7eb2Smrg return true;
385*627f7eb2Smrg }
386*627f7eb2Smrg return false;
387*627f7eb2Smrg }
388*627f7eb2Smrg
389*627f7eb2Smrg
prefix_name(Dsymbol * s)390*627f7eb2Smrg void prefix_name(Dsymbol *s)
391*627f7eb2Smrg {
392*627f7eb2Smrg //printf("prefix_name(%s)\n", s->toChars());
393*627f7eb2Smrg if (!substitute(s))
394*627f7eb2Smrg {
395*627f7eb2Smrg Dsymbol *si = getInstance(s);
396*627f7eb2Smrg Dsymbol *p = getQualifier(si);
397*627f7eb2Smrg if (p)
398*627f7eb2Smrg {
399*627f7eb2Smrg if (isStd(p))
400*627f7eb2Smrg {
401*627f7eb2Smrg TemplateInstance *ti = si->isTemplateInstance();
402*627f7eb2Smrg if (ti)
403*627f7eb2Smrg {
404*627f7eb2Smrg if (s->ident == Id::allocator)
405*627f7eb2Smrg {
406*627f7eb2Smrg buf->writestring("Sa");
407*627f7eb2Smrg template_args(ti);
408*627f7eb2Smrg append(ti);
409*627f7eb2Smrg return;
410*627f7eb2Smrg }
411*627f7eb2Smrg if (s->ident == Id::basic_string)
412*627f7eb2Smrg {
413*627f7eb2Smrg // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
414*627f7eb2Smrg if (ti->tiargs->dim == 3 &&
415*627f7eb2Smrg isChar((*ti->tiargs)[0]) &&
416*627f7eb2Smrg isChar_traits_char((*ti->tiargs)[1]) &&
417*627f7eb2Smrg isAllocator_char((*ti->tiargs)[2]))
418*627f7eb2Smrg
419*627f7eb2Smrg {
420*627f7eb2Smrg buf->writestring("Ss");
421*627f7eb2Smrg return;
422*627f7eb2Smrg }
423*627f7eb2Smrg buf->writestring("Sb"); // ::std::basic_string
424*627f7eb2Smrg template_args(ti);
425*627f7eb2Smrg append(ti);
426*627f7eb2Smrg return;
427*627f7eb2Smrg }
428*627f7eb2Smrg
429*627f7eb2Smrg // ::std::basic_istream<char, ::std::char_traits<char>>
430*627f7eb2Smrg if (s->ident == Id::basic_istream &&
431*627f7eb2Smrg char_std_char_traits_char(ti, "Si"))
432*627f7eb2Smrg return;
433*627f7eb2Smrg
434*627f7eb2Smrg // ::std::basic_ostream<char, ::std::char_traits<char>>
435*627f7eb2Smrg if (s->ident == Id::basic_ostream &&
436*627f7eb2Smrg char_std_char_traits_char(ti, "So"))
437*627f7eb2Smrg return;
438*627f7eb2Smrg
439*627f7eb2Smrg // ::std::basic_iostream<char, ::std::char_traits<char>>
440*627f7eb2Smrg if (s->ident == Id::basic_iostream &&
441*627f7eb2Smrg char_std_char_traits_char(ti, "Sd"))
442*627f7eb2Smrg return;
443*627f7eb2Smrg }
444*627f7eb2Smrg buf->writestring("St");
445*627f7eb2Smrg }
446*627f7eb2Smrg else
447*627f7eb2Smrg prefix_name(p);
448*627f7eb2Smrg }
449*627f7eb2Smrg source_name(si);
450*627f7eb2Smrg if (!isStd(si))
451*627f7eb2Smrg {
452*627f7eb2Smrg /* Do this after the source_name() call to keep components[]
453*627f7eb2Smrg * in the right order.
454*627f7eb2Smrg * https://issues.dlang.org/show_bug.cgi?id=17947
455*627f7eb2Smrg */
456*627f7eb2Smrg append(si);
457*627f7eb2Smrg }
458*627f7eb2Smrg }
459*627f7eb2Smrg }
460*627f7eb2Smrg
cpp_mangle_name(Dsymbol * s,bool qualified)461*627f7eb2Smrg void cpp_mangle_name(Dsymbol *s, bool qualified)
462*627f7eb2Smrg {
463*627f7eb2Smrg //printf("cpp_mangle_name(%s, %d)\n", s->toChars(), qualified);
464*627f7eb2Smrg Dsymbol *p = s->toParent3();
465*627f7eb2Smrg Dsymbol *se = s;
466*627f7eb2Smrg bool write_prefix = true;
467*627f7eb2Smrg if (p && p->isTemplateInstance())
468*627f7eb2Smrg {
469*627f7eb2Smrg se = p;
470*627f7eb2Smrg if (find(p->isTemplateInstance()->tempdecl) >= 0)
471*627f7eb2Smrg write_prefix = false;
472*627f7eb2Smrg p = p->toParent3();
473*627f7eb2Smrg }
474*627f7eb2Smrg
475*627f7eb2Smrg if (p && !p->isModule())
476*627f7eb2Smrg {
477*627f7eb2Smrg /* The N..E is not required if:
478*627f7eb2Smrg * 1. the parent is 'std'
479*627f7eb2Smrg * 2. 'std' is the initial qualifier
480*627f7eb2Smrg * 3. there is no CV-qualifier or a ref-qualifier for a member function
481*627f7eb2Smrg * ABI 5.1.8
482*627f7eb2Smrg */
483*627f7eb2Smrg if (isStd(p) && !qualified)
484*627f7eb2Smrg {
485*627f7eb2Smrg TemplateInstance *ti = se->isTemplateInstance();
486*627f7eb2Smrg if (s->ident == Id::allocator)
487*627f7eb2Smrg {
488*627f7eb2Smrg buf->writestring("Sa"); // "Sa" is short for ::std::allocator
489*627f7eb2Smrg template_args(ti);
490*627f7eb2Smrg }
491*627f7eb2Smrg else if (s->ident == Id::basic_string)
492*627f7eb2Smrg {
493*627f7eb2Smrg // ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
494*627f7eb2Smrg if (ti->tiargs->dim == 3 &&
495*627f7eb2Smrg isChar((*ti->tiargs)[0]) &&
496*627f7eb2Smrg isChar_traits_char((*ti->tiargs)[1]) &&
497*627f7eb2Smrg isAllocator_char((*ti->tiargs)[2]))
498*627f7eb2Smrg
499*627f7eb2Smrg {
500*627f7eb2Smrg buf->writestring("Ss");
501*627f7eb2Smrg return;
502*627f7eb2Smrg }
503*627f7eb2Smrg buf->writestring("Sb"); // ::std::basic_string
504*627f7eb2Smrg template_args(ti);
505*627f7eb2Smrg }
506*627f7eb2Smrg else
507*627f7eb2Smrg {
508*627f7eb2Smrg // ::std::basic_istream<char, ::std::char_traits<char>>
509*627f7eb2Smrg if (s->ident == Id::basic_istream)
510*627f7eb2Smrg {
511*627f7eb2Smrg if (char_std_char_traits_char(ti, "Si"))
512*627f7eb2Smrg return;
513*627f7eb2Smrg }
514*627f7eb2Smrg else if (s->ident == Id::basic_ostream)
515*627f7eb2Smrg {
516*627f7eb2Smrg if (char_std_char_traits_char(ti, "So"))
517*627f7eb2Smrg return;
518*627f7eb2Smrg }
519*627f7eb2Smrg else if (s->ident == Id::basic_iostream)
520*627f7eb2Smrg {
521*627f7eb2Smrg if (char_std_char_traits_char(ti, "Sd"))
522*627f7eb2Smrg return;
523*627f7eb2Smrg }
524*627f7eb2Smrg buf->writestring("St");
525*627f7eb2Smrg source_name(se);
526*627f7eb2Smrg }
527*627f7eb2Smrg }
528*627f7eb2Smrg else
529*627f7eb2Smrg {
530*627f7eb2Smrg buf->writeByte('N');
531*627f7eb2Smrg if (write_prefix)
532*627f7eb2Smrg prefix_name(p);
533*627f7eb2Smrg source_name(se);
534*627f7eb2Smrg buf->writeByte('E');
535*627f7eb2Smrg }
536*627f7eb2Smrg }
537*627f7eb2Smrg else
538*627f7eb2Smrg source_name(se);
539*627f7eb2Smrg append(s);
540*627f7eb2Smrg }
541*627f7eb2Smrg
CV_qualifiers(Type * t)542*627f7eb2Smrg void CV_qualifiers(Type *t)
543*627f7eb2Smrg {
544*627f7eb2Smrg // CV-qualifiers are 'r': restrict, 'V': volatile, 'K': const
545*627f7eb2Smrg if (t->isConst())
546*627f7eb2Smrg buf->writeByte('K');
547*627f7eb2Smrg }
548*627f7eb2Smrg
mangle_variable(VarDeclaration * d,bool is_temp_arg_ref)549*627f7eb2Smrg void mangle_variable(VarDeclaration *d, bool is_temp_arg_ref)
550*627f7eb2Smrg {
551*627f7eb2Smrg // fake mangling for fields to fix https://issues.dlang.org/show_bug.cgi?id=16525
552*627f7eb2Smrg if (!(d->storage_class & (STCextern | STCfield | STCgshared)))
553*627f7eb2Smrg {
554*627f7eb2Smrg d->error("Internal Compiler Error: C++ static non-`__gshared` non-`extern` variables not supported");
555*627f7eb2Smrg fatal();
556*627f7eb2Smrg }
557*627f7eb2Smrg
558*627f7eb2Smrg Dsymbol *p = d->toParent3();
559*627f7eb2Smrg if (p && !p->isModule()) //for example: char Namespace1::beta[6] should be mangled as "_ZN10Namespace14betaE"
560*627f7eb2Smrg {
561*627f7eb2Smrg buf->writestring("_ZN");
562*627f7eb2Smrg prefix_name(p);
563*627f7eb2Smrg source_name(d);
564*627f7eb2Smrg buf->writeByte('E');
565*627f7eb2Smrg }
566*627f7eb2Smrg else //char beta[6] should mangle as "beta"
567*627f7eb2Smrg {
568*627f7eb2Smrg if (!is_temp_arg_ref)
569*627f7eb2Smrg {
570*627f7eb2Smrg buf->writestring(d->ident->toChars());
571*627f7eb2Smrg }
572*627f7eb2Smrg else
573*627f7eb2Smrg {
574*627f7eb2Smrg buf->writestring("_Z");
575*627f7eb2Smrg source_name(d);
576*627f7eb2Smrg }
577*627f7eb2Smrg }
578*627f7eb2Smrg }
579*627f7eb2Smrg
mangle_function(FuncDeclaration * d)580*627f7eb2Smrg void mangle_function(FuncDeclaration *d)
581*627f7eb2Smrg {
582*627f7eb2Smrg //printf("mangle_function(%s)\n", d->toChars());
583*627f7eb2Smrg /*
584*627f7eb2Smrg * <mangled-name> ::= _Z <encoding>
585*627f7eb2Smrg * <encoding> ::= <function name> <bare-function-type>
586*627f7eb2Smrg * ::= <data name>
587*627f7eb2Smrg * ::= <special-name>
588*627f7eb2Smrg */
589*627f7eb2Smrg TypeFunction *tf = (TypeFunction *)d->type;
590*627f7eb2Smrg
591*627f7eb2Smrg buf->writestring("_Z");
592*627f7eb2Smrg if (getFuncTemplateDecl(d))
593*627f7eb2Smrg {
594*627f7eb2Smrg /* It's an instance of a function template
595*627f7eb2Smrg */
596*627f7eb2Smrg TemplateInstance *ti = d->parent->isTemplateInstance();
597*627f7eb2Smrg assert(ti);
598*627f7eb2Smrg Dsymbol *p = ti->toParent3();
599*627f7eb2Smrg if (p && !p->isModule() && tf->linkage == LINKcpp)
600*627f7eb2Smrg {
601*627f7eb2Smrg buf->writeByte('N');
602*627f7eb2Smrg CV_qualifiers(d->type);
603*627f7eb2Smrg prefix_name(p);
604*627f7eb2Smrg if (d->isCtorDeclaration())
605*627f7eb2Smrg buf->writestring("C1");
606*627f7eb2Smrg else if (d->isDtorDeclaration())
607*627f7eb2Smrg buf->writestring("D1");
608*627f7eb2Smrg else
609*627f7eb2Smrg source_name(ti);
610*627f7eb2Smrg buf->writeByte('E');
611*627f7eb2Smrg }
612*627f7eb2Smrg else
613*627f7eb2Smrg source_name(ti);
614*627f7eb2Smrg headOfType(tf->nextOf()); // mangle return type
615*627f7eb2Smrg }
616*627f7eb2Smrg else
617*627f7eb2Smrg {
618*627f7eb2Smrg Dsymbol *p = d->toParent3();
619*627f7eb2Smrg if (p && !p->isModule() && tf->linkage == LINKcpp)
620*627f7eb2Smrg {
621*627f7eb2Smrg /* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
622*627f7eb2Smrg * ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
623*627f7eb2Smrg */
624*627f7eb2Smrg buf->writeByte('N');
625*627f7eb2Smrg CV_qualifiers(d->type);
626*627f7eb2Smrg
627*627f7eb2Smrg /* <prefix> ::= <prefix> <unqualified-name>
628*627f7eb2Smrg * ::= <template-prefix> <template-args>
629*627f7eb2Smrg * ::= <template-param>
630*627f7eb2Smrg * ::= # empty
631*627f7eb2Smrg * ::= <substitution>
632*627f7eb2Smrg * ::= <prefix> <data-member-prefix>
633*627f7eb2Smrg */
634*627f7eb2Smrg prefix_name(p);
635*627f7eb2Smrg //printf("p: %s\n", buf.peekString());
636*627f7eb2Smrg
637*627f7eb2Smrg if (d->isCtorDeclaration())
638*627f7eb2Smrg {
639*627f7eb2Smrg buf->writestring("C1");
640*627f7eb2Smrg }
641*627f7eb2Smrg else if (d->isDtorDeclaration())
642*627f7eb2Smrg {
643*627f7eb2Smrg buf->writestring("D1");
644*627f7eb2Smrg }
645*627f7eb2Smrg else
646*627f7eb2Smrg {
647*627f7eb2Smrg source_name(d);
648*627f7eb2Smrg }
649*627f7eb2Smrg buf->writeByte('E');
650*627f7eb2Smrg }
651*627f7eb2Smrg else
652*627f7eb2Smrg {
653*627f7eb2Smrg source_name(d);
654*627f7eb2Smrg }
655*627f7eb2Smrg }
656*627f7eb2Smrg
657*627f7eb2Smrg if (tf->linkage == LINKcpp) //Template args accept extern "C" symbols with special mangling
658*627f7eb2Smrg {
659*627f7eb2Smrg assert(tf->ty == Tfunction);
660*627f7eb2Smrg mangleFunctionParameters(tf->parameters, tf->varargs);
661*627f7eb2Smrg }
662*627f7eb2Smrg }
663*627f7eb2Smrg
mangleFunctionParameters(Parameters * parameters,int varargs)664*627f7eb2Smrg void mangleFunctionParameters(Parameters *parameters, int varargs)
665*627f7eb2Smrg {
666*627f7eb2Smrg struct ParamsCppMangle
667*627f7eb2Smrg {
668*627f7eb2Smrg int numparams;
669*627f7eb2Smrg CppMangleVisitor *mangler;
670*627f7eb2Smrg
671*627f7eb2Smrg static int dg(void *ctx, size_t, Parameter *fparam)
672*627f7eb2Smrg {
673*627f7eb2Smrg ParamsCppMangle *p = (ParamsCppMangle *)ctx;
674*627f7eb2Smrg CppMangleVisitor *mangler = p->mangler;
675*627f7eb2Smrg Type *t = Target::cppParameterType(fparam);
676*627f7eb2Smrg if (t->ty == Tsarray)
677*627f7eb2Smrg {
678*627f7eb2Smrg // Static arrays in D are passed by value; no counterpart in C++
679*627f7eb2Smrg t->error(mangler->loc, "Internal Compiler Error: unable to pass static array `%s` to extern(C++) function, use pointer instead",
680*627f7eb2Smrg t->toChars());
681*627f7eb2Smrg fatal();
682*627f7eb2Smrg }
683*627f7eb2Smrg mangler->headOfType(t);
684*627f7eb2Smrg p->numparams++;
685*627f7eb2Smrg return 0;
686*627f7eb2Smrg }
687*627f7eb2Smrg };
688*627f7eb2Smrg
689*627f7eb2Smrg ParamsCppMangle p;
690*627f7eb2Smrg p.numparams = 0;
691*627f7eb2Smrg p.mangler = this;
692*627f7eb2Smrg
693*627f7eb2Smrg if (parameters)
694*627f7eb2Smrg Parameter_foreach(parameters, &ParamsCppMangle::dg, (void*)&p);
695*627f7eb2Smrg
696*627f7eb2Smrg if (varargs)
697*627f7eb2Smrg buf->writeByte('z');
698*627f7eb2Smrg else if (!p.numparams)
699*627f7eb2Smrg buf->writeByte('v'); // encode (void) parameters
700*627f7eb2Smrg }
701*627f7eb2Smrg
702*627f7eb2Smrg public:
CppMangleVisitor(OutBuffer * buf,Loc loc)703*627f7eb2Smrg CppMangleVisitor(OutBuffer *buf, Loc loc)
704*627f7eb2Smrg : components(), buf(buf), loc(loc)
705*627f7eb2Smrg {
706*627f7eb2Smrg }
707*627f7eb2Smrg
708*627f7eb2Smrg /*****
709*627f7eb2Smrg * Entry point. Append mangling to buf[]
710*627f7eb2Smrg * Params:
711*627f7eb2Smrg * s = symbol to mangle
712*627f7eb2Smrg */
mangleOf(Dsymbol * s)713*627f7eb2Smrg void mangleOf(Dsymbol *s)
714*627f7eb2Smrg {
715*627f7eb2Smrg if (VarDeclaration *vd = s->isVarDeclaration())
716*627f7eb2Smrg {
717*627f7eb2Smrg mangle_variable(vd, false);
718*627f7eb2Smrg }
719*627f7eb2Smrg else if (FuncDeclaration *fd = s->isFuncDeclaration())
720*627f7eb2Smrg {
721*627f7eb2Smrg mangle_function(fd);
722*627f7eb2Smrg }
723*627f7eb2Smrg else
724*627f7eb2Smrg {
725*627f7eb2Smrg assert(0);
726*627f7eb2Smrg }
727*627f7eb2Smrg }
728*627f7eb2Smrg
729*627f7eb2Smrg /****** The rest is type mangling ************/
730*627f7eb2Smrg
error(Type * t)731*627f7eb2Smrg void error(Type *t)
732*627f7eb2Smrg {
733*627f7eb2Smrg const char *p;
734*627f7eb2Smrg if (t->isImmutable())
735*627f7eb2Smrg p = "`immutable` ";
736*627f7eb2Smrg else if (t->isShared())
737*627f7eb2Smrg p = "`shared` ";
738*627f7eb2Smrg else
739*627f7eb2Smrg p = "";
740*627f7eb2Smrg t->error(loc, "Internal Compiler Error: %stype `%s` can not be mapped to C++", p, t->toChars());
741*627f7eb2Smrg fatal(); //Fatal, because this error should be handled in frontend
742*627f7eb2Smrg }
743*627f7eb2Smrg
744*627f7eb2Smrg /****************************
745*627f7eb2Smrg * Mangle a type,
746*627f7eb2Smrg * treating it as a Head followed by a Tail.
747*627f7eb2Smrg * Params:
748*627f7eb2Smrg * t = Head of a type
749*627f7eb2Smrg */
headOfType(Type * t)750*627f7eb2Smrg void headOfType(Type *t)
751*627f7eb2Smrg {
752*627f7eb2Smrg if (t->ty == Tclass)
753*627f7eb2Smrg {
754*627f7eb2Smrg mangleTypeClass((TypeClass*)t, true);
755*627f7eb2Smrg }
756*627f7eb2Smrg else
757*627f7eb2Smrg {
758*627f7eb2Smrg // For value types, strip const/immutable/shared from the head of the type
759*627f7eb2Smrg t->mutableOf()->unSharedOf()->accept(this);
760*627f7eb2Smrg }
761*627f7eb2Smrg }
762*627f7eb2Smrg
visit(Type * t)763*627f7eb2Smrg void visit(Type *t)
764*627f7eb2Smrg {
765*627f7eb2Smrg error(t);
766*627f7eb2Smrg }
767*627f7eb2Smrg
768*627f7eb2Smrg /******
769*627f7eb2Smrg * Write out 1 or 2 character basic type mangling.
770*627f7eb2Smrg * Handle const and substitutions.
771*627f7eb2Smrg * Params:
772*627f7eb2Smrg * t = type to mangle
773*627f7eb2Smrg * p = if not 0, then character prefix
774*627f7eb2Smrg * c = mangling character
775*627f7eb2Smrg */
writeBasicType(Type * t,char p,char c)776*627f7eb2Smrg void writeBasicType(Type *t, char p, char c)
777*627f7eb2Smrg {
778*627f7eb2Smrg // Only do substitutions for non-fundamental types.
779*627f7eb2Smrg if (!isFundamentalType(t) || t->isConst())
780*627f7eb2Smrg {
781*627f7eb2Smrg if (substitute(t))
782*627f7eb2Smrg return;
783*627f7eb2Smrg else
784*627f7eb2Smrg append(t);
785*627f7eb2Smrg }
786*627f7eb2Smrg CV_qualifiers(t);
787*627f7eb2Smrg if (p)
788*627f7eb2Smrg buf->writeByte(p);
789*627f7eb2Smrg buf->writeByte(c);
790*627f7eb2Smrg }
791*627f7eb2Smrg
visit(TypeNull * t)792*627f7eb2Smrg void visit(TypeNull *t)
793*627f7eb2Smrg {
794*627f7eb2Smrg if (t->isImmutable() || t->isShared())
795*627f7eb2Smrg return error(t);
796*627f7eb2Smrg
797*627f7eb2Smrg writeBasicType(t, 'D', 'n');
798*627f7eb2Smrg }
799*627f7eb2Smrg
visit(TypeBasic * t)800*627f7eb2Smrg void visit(TypeBasic *t)
801*627f7eb2Smrg {
802*627f7eb2Smrg if (t->isImmutable() || t->isShared())
803*627f7eb2Smrg return error(t);
804*627f7eb2Smrg
805*627f7eb2Smrg // Handle any target-specific basic types.
806*627f7eb2Smrg if (const char *tm = Target::cppTypeMangle(t))
807*627f7eb2Smrg {
808*627f7eb2Smrg // Only do substitutions for non-fundamental types.
809*627f7eb2Smrg if (!isFundamentalType(t) || t->isConst())
810*627f7eb2Smrg {
811*627f7eb2Smrg if (substitute(t))
812*627f7eb2Smrg return;
813*627f7eb2Smrg else
814*627f7eb2Smrg append(t);
815*627f7eb2Smrg }
816*627f7eb2Smrg CV_qualifiers(t);
817*627f7eb2Smrg buf->writestring(tm);
818*627f7eb2Smrg return;
819*627f7eb2Smrg }
820*627f7eb2Smrg
821*627f7eb2Smrg /* <builtin-type>:
822*627f7eb2Smrg * v void
823*627f7eb2Smrg * w wchar_t
824*627f7eb2Smrg * b bool
825*627f7eb2Smrg * c char
826*627f7eb2Smrg * a signed char
827*627f7eb2Smrg * h unsigned char
828*627f7eb2Smrg * s short
829*627f7eb2Smrg * t unsigned short
830*627f7eb2Smrg * i int
831*627f7eb2Smrg * j unsigned int
832*627f7eb2Smrg * l long
833*627f7eb2Smrg * m unsigned long
834*627f7eb2Smrg * x long long, __int64
835*627f7eb2Smrg * y unsigned long long, __int64
836*627f7eb2Smrg * n __int128
837*627f7eb2Smrg * o unsigned __int128
838*627f7eb2Smrg * f float
839*627f7eb2Smrg * d double
840*627f7eb2Smrg * e long double, __float80
841*627f7eb2Smrg * g __float128
842*627f7eb2Smrg * z ellipsis
843*627f7eb2Smrg * Dd 64 bit IEEE 754r decimal floating point
844*627f7eb2Smrg * De 128 bit IEEE 754r decimal floating point
845*627f7eb2Smrg * Df 32 bit IEEE 754r decimal floating point
846*627f7eb2Smrg * Dh 16 bit IEEE 754r half-precision floating point
847*627f7eb2Smrg * Di char32_t
848*627f7eb2Smrg * Ds char16_t
849*627f7eb2Smrg * u <source-name> # vendor extended type
850*627f7eb2Smrg */
851*627f7eb2Smrg
852*627f7eb2Smrg char c;
853*627f7eb2Smrg char p = 0;
854*627f7eb2Smrg switch (t->ty)
855*627f7eb2Smrg {
856*627f7eb2Smrg case Tvoid: c = 'v'; break;
857*627f7eb2Smrg case Tint8: c = 'a'; break;
858*627f7eb2Smrg case Tuns8: c = 'h'; break;
859*627f7eb2Smrg case Tint16: c = 's'; break;
860*627f7eb2Smrg case Tuns16: c = 't'; break;
861*627f7eb2Smrg case Tint32: c = 'i'; break;
862*627f7eb2Smrg case Tuns32: c = 'j'; break;
863*627f7eb2Smrg case Tfloat32: c = 'f'; break;
864*627f7eb2Smrg case Tint64:
865*627f7eb2Smrg c = (Target::c_longsize == 8 ? 'l' : 'x');
866*627f7eb2Smrg break;
867*627f7eb2Smrg case Tuns64:
868*627f7eb2Smrg c = (Target::c_longsize == 8 ? 'm' : 'y');
869*627f7eb2Smrg break;
870*627f7eb2Smrg case Tint128: c = 'n'; break;
871*627f7eb2Smrg case Tuns128: c = 'o'; break;
872*627f7eb2Smrg case Tfloat64: c = 'd'; break;
873*627f7eb2Smrg case Tfloat80: c = 'e'; break;
874*627f7eb2Smrg case Tbool: c = 'b'; break;
875*627f7eb2Smrg case Tchar: c = 'c'; break;
876*627f7eb2Smrg case Twchar: c = 't'; break; // unsigned short (perhaps use 'Ds' ?
877*627f7eb2Smrg case Tdchar: c = 'w'; break; // wchar_t (UTF-32) (perhaps use 'Di' ?
878*627f7eb2Smrg case Timaginary32: p = 'G'; c = 'f'; break; // 'G' means imaginary
879*627f7eb2Smrg case Timaginary64: p = 'G'; c = 'd'; break;
880*627f7eb2Smrg case Timaginary80: p = 'G'; c = 'e'; break;
881*627f7eb2Smrg case Tcomplex32: p = 'C'; c = 'f'; break; // 'C' means complex
882*627f7eb2Smrg case Tcomplex64: p = 'C'; c = 'd'; break;
883*627f7eb2Smrg case Tcomplex80: p = 'C'; c = 'e'; break;
884*627f7eb2Smrg
885*627f7eb2Smrg default:
886*627f7eb2Smrg return error(t);
887*627f7eb2Smrg }
888*627f7eb2Smrg writeBasicType(t, p, c);
889*627f7eb2Smrg }
890*627f7eb2Smrg
visit(TypeVector * t)891*627f7eb2Smrg void visit(TypeVector *t)
892*627f7eb2Smrg {
893*627f7eb2Smrg if (t->isImmutable() || t->isShared())
894*627f7eb2Smrg return error(t);
895*627f7eb2Smrg
896*627f7eb2Smrg if (substitute(t))
897*627f7eb2Smrg return;
898*627f7eb2Smrg append(t);
899*627f7eb2Smrg CV_qualifiers(t);
900*627f7eb2Smrg
901*627f7eb2Smrg // Handle any target-specific vector types.
902*627f7eb2Smrg if (const char *tm = Target::cppTypeMangle(t))
903*627f7eb2Smrg {
904*627f7eb2Smrg buf->writestring(tm);
905*627f7eb2Smrg }
906*627f7eb2Smrg else
907*627f7eb2Smrg {
908*627f7eb2Smrg assert(t->basetype && t->basetype->ty == Tsarray);
909*627f7eb2Smrg assert(((TypeSArray *)t->basetype)->dim);
910*627f7eb2Smrg buf->writestring("U8__vector"); //-- Gnu ABI v.3
911*627f7eb2Smrg t->basetype->nextOf()->accept(this);
912*627f7eb2Smrg }
913*627f7eb2Smrg }
914*627f7eb2Smrg
visit(TypeSArray * t)915*627f7eb2Smrg void visit(TypeSArray *t)
916*627f7eb2Smrg {
917*627f7eb2Smrg if (t->isImmutable() || t->isShared())
918*627f7eb2Smrg return error(t);
919*627f7eb2Smrg
920*627f7eb2Smrg if (!substitute(t))
921*627f7eb2Smrg append(t);
922*627f7eb2Smrg CV_qualifiers(t);
923*627f7eb2Smrg buf->writeByte('A');
924*627f7eb2Smrg buf->printf("%llu", t->dim ? t->dim->toInteger() : 0);
925*627f7eb2Smrg buf->writeByte('_');
926*627f7eb2Smrg t->next->accept(this);
927*627f7eb2Smrg }
928*627f7eb2Smrg
visit(TypePointer * t)929*627f7eb2Smrg void visit(TypePointer *t)
930*627f7eb2Smrg {
931*627f7eb2Smrg if (t->isImmutable() || t->isShared())
932*627f7eb2Smrg return error(t);
933*627f7eb2Smrg
934*627f7eb2Smrg if (substitute(t))
935*627f7eb2Smrg return;
936*627f7eb2Smrg CV_qualifiers(t);
937*627f7eb2Smrg buf->writeByte('P');
938*627f7eb2Smrg t->next->accept(this);
939*627f7eb2Smrg append(t);
940*627f7eb2Smrg }
941*627f7eb2Smrg
visit(TypeReference * t)942*627f7eb2Smrg void visit(TypeReference *t)
943*627f7eb2Smrg {
944*627f7eb2Smrg //printf("TypeReference %s\n", t->toChars());
945*627f7eb2Smrg if (substitute(t))
946*627f7eb2Smrg return;
947*627f7eb2Smrg buf->writeByte('R');
948*627f7eb2Smrg t->next->accept(this);
949*627f7eb2Smrg append(t);
950*627f7eb2Smrg }
951*627f7eb2Smrg
visit(TypeFunction * t)952*627f7eb2Smrg void visit(TypeFunction *t)
953*627f7eb2Smrg {
954*627f7eb2Smrg /*
955*627f7eb2Smrg * <function-type> ::= F [Y] <bare-function-type> E
956*627f7eb2Smrg * <bare-function-type> ::= <signature type>+
957*627f7eb2Smrg * # types are possible return type, then parameter types
958*627f7eb2Smrg */
959*627f7eb2Smrg
960*627f7eb2Smrg /* ABI says:
961*627f7eb2Smrg "The type of a non-static member function is considered to be different,
962*627f7eb2Smrg for the purposes of substitution, from the type of a namespace-scope or
963*627f7eb2Smrg static member function whose type appears similar. The types of two
964*627f7eb2Smrg non-static member functions are considered to be different, for the
965*627f7eb2Smrg purposes of substitution, if the functions are members of different
966*627f7eb2Smrg classes. In other words, for the purposes of substitution, the class of
967*627f7eb2Smrg which the function is a member is considered part of the type of
968*627f7eb2Smrg function."
969*627f7eb2Smrg
970*627f7eb2Smrg BUG: Right now, types of functions are never merged, so our simplistic
971*627f7eb2Smrg component matcher always finds them to be different.
972*627f7eb2Smrg We should use Type::equals on these, and use different
973*627f7eb2Smrg TypeFunctions for non-static member functions, and non-static
974*627f7eb2Smrg member functions of different classes.
975*627f7eb2Smrg */
976*627f7eb2Smrg if (substitute(t))
977*627f7eb2Smrg return;
978*627f7eb2Smrg buf->writeByte('F');
979*627f7eb2Smrg if (t->linkage == LINKc)
980*627f7eb2Smrg buf->writeByte('Y');
981*627f7eb2Smrg Type *tn = t->next;
982*627f7eb2Smrg if (t->isref)
983*627f7eb2Smrg tn = tn->referenceTo();
984*627f7eb2Smrg tn->accept(this);
985*627f7eb2Smrg mangleFunctionParameters(t->parameters, t->varargs);
986*627f7eb2Smrg buf->writeByte('E');
987*627f7eb2Smrg append(t);
988*627f7eb2Smrg }
989*627f7eb2Smrg
visit(TypeStruct * t)990*627f7eb2Smrg void visit(TypeStruct *t)
991*627f7eb2Smrg {
992*627f7eb2Smrg if (t->isImmutable() || t->isShared())
993*627f7eb2Smrg return error(t);
994*627f7eb2Smrg
995*627f7eb2Smrg //printf("TypeStruct %s\n", t->toChars());
996*627f7eb2Smrg doSymbol(t);
997*627f7eb2Smrg }
998*627f7eb2Smrg
999*627f7eb2Smrg
visit(TypeEnum * t)1000*627f7eb2Smrg void visit(TypeEnum *t)
1001*627f7eb2Smrg {
1002*627f7eb2Smrg if (t->isImmutable() || t->isShared())
1003*627f7eb2Smrg return error(t);
1004*627f7eb2Smrg
1005*627f7eb2Smrg /* __c_(u)long(long) get special mangling
1006*627f7eb2Smrg */
1007*627f7eb2Smrg Identifier *id = t->sym->ident;
1008*627f7eb2Smrg //printf("enum id = '%s'\n", id->toChars());
1009*627f7eb2Smrg if (id == Id::__c_long)
1010*627f7eb2Smrg return writeBasicType(t, 0, 'l');
1011*627f7eb2Smrg else if (id == Id::__c_ulong)
1012*627f7eb2Smrg return writeBasicType(t, 0, 'm');
1013*627f7eb2Smrg else if (id == Id::__c_longlong)
1014*627f7eb2Smrg return writeBasicType(t, 0, 'x');
1015*627f7eb2Smrg else if (id == Id::__c_ulonglong)
1016*627f7eb2Smrg return writeBasicType(t, 0, 'y');
1017*627f7eb2Smrg
1018*627f7eb2Smrg doSymbol(t);
1019*627f7eb2Smrg }
1020*627f7eb2Smrg
1021*627f7eb2Smrg /****************
1022*627f7eb2Smrg * Write structs and enums.
1023*627f7eb2Smrg * Params:
1024*627f7eb2Smrg * t = TypeStruct or TypeEnum
1025*627f7eb2Smrg */
doSymbol(Type * t)1026*627f7eb2Smrg void doSymbol(Type *t)
1027*627f7eb2Smrg {
1028*627f7eb2Smrg if (substitute(t))
1029*627f7eb2Smrg return;
1030*627f7eb2Smrg CV_qualifiers(t);
1031*627f7eb2Smrg
1032*627f7eb2Smrg // Handle any target-specific struct types.
1033*627f7eb2Smrg if (const char *tm = Target::cppTypeMangle(t))
1034*627f7eb2Smrg {
1035*627f7eb2Smrg buf->writestring(tm);
1036*627f7eb2Smrg }
1037*627f7eb2Smrg else
1038*627f7eb2Smrg {
1039*627f7eb2Smrg Dsymbol *s = t->toDsymbol(NULL);
1040*627f7eb2Smrg Dsymbol *p = s->toParent3();
1041*627f7eb2Smrg if (p && p->isTemplateInstance())
1042*627f7eb2Smrg {
1043*627f7eb2Smrg /* https://issues.dlang.org/show_bug.cgi?id=17947
1044*627f7eb2Smrg * Substitute the template instance symbol, not the struct/enum symbol
1045*627f7eb2Smrg */
1046*627f7eb2Smrg if (substitute(p))
1047*627f7eb2Smrg return;
1048*627f7eb2Smrg }
1049*627f7eb2Smrg if (!substitute(s))
1050*627f7eb2Smrg {
1051*627f7eb2Smrg cpp_mangle_name(s, t->isConst());
1052*627f7eb2Smrg }
1053*627f7eb2Smrg }
1054*627f7eb2Smrg if (t->isConst())
1055*627f7eb2Smrg append(t);
1056*627f7eb2Smrg }
1057*627f7eb2Smrg
visit(TypeClass * t)1058*627f7eb2Smrg void visit(TypeClass *t)
1059*627f7eb2Smrg {
1060*627f7eb2Smrg mangleTypeClass(t, false);
1061*627f7eb2Smrg }
1062*627f7eb2Smrg
1063*627f7eb2Smrg /************************
1064*627f7eb2Smrg * Mangle a class type.
1065*627f7eb2Smrg * If it's the head, treat the initial pointer as a value type.
1066*627f7eb2Smrg * Params:
1067*627f7eb2Smrg * t = class type
1068*627f7eb2Smrg * head = true for head of a type
1069*627f7eb2Smrg */
mangleTypeClass(TypeClass * t,bool head)1070*627f7eb2Smrg void mangleTypeClass(TypeClass *t, bool head)
1071*627f7eb2Smrg {
1072*627f7eb2Smrg if (t->isImmutable() || t->isShared())
1073*627f7eb2Smrg return error(t);
1074*627f7eb2Smrg
1075*627f7eb2Smrg /* Mangle as a <pointer to><struct>
1076*627f7eb2Smrg */
1077*627f7eb2Smrg if (substitute(t))
1078*627f7eb2Smrg return;
1079*627f7eb2Smrg if (!head)
1080*627f7eb2Smrg CV_qualifiers(t);
1081*627f7eb2Smrg buf->writeByte('P');
1082*627f7eb2Smrg
1083*627f7eb2Smrg CV_qualifiers(t);
1084*627f7eb2Smrg
1085*627f7eb2Smrg {
1086*627f7eb2Smrg Dsymbol *s = t->toDsymbol(NULL);
1087*627f7eb2Smrg Dsymbol *p = s->toParent3();
1088*627f7eb2Smrg if (p && p->isTemplateInstance())
1089*627f7eb2Smrg {
1090*627f7eb2Smrg /* https://issues.dlang.org/show_bug.cgi?id=17947
1091*627f7eb2Smrg * Substitute the template instance symbol, not the class symbol
1092*627f7eb2Smrg */
1093*627f7eb2Smrg if (substitute(p))
1094*627f7eb2Smrg return;
1095*627f7eb2Smrg }
1096*627f7eb2Smrg }
1097*627f7eb2Smrg
1098*627f7eb2Smrg if (!substitute(t->sym))
1099*627f7eb2Smrg {
1100*627f7eb2Smrg cpp_mangle_name(t->sym, t->isConst());
1101*627f7eb2Smrg }
1102*627f7eb2Smrg if (t->isConst())
1103*627f7eb2Smrg append(NULL); // C++ would have an extra type here
1104*627f7eb2Smrg append(t);
1105*627f7eb2Smrg }
1106*627f7eb2Smrg
mangle_typeinfo(Dsymbol * s)1107*627f7eb2Smrg const char *mangle_typeinfo(Dsymbol *s)
1108*627f7eb2Smrg {
1109*627f7eb2Smrg buf->writestring("_ZTI");
1110*627f7eb2Smrg cpp_mangle_name(s, false);
1111*627f7eb2Smrg return buf->extractString();
1112*627f7eb2Smrg }
1113*627f7eb2Smrg };
1114*627f7eb2Smrg
toCppMangleItanium(Dsymbol * s)1115*627f7eb2Smrg const char *toCppMangleItanium(Dsymbol *s)
1116*627f7eb2Smrg {
1117*627f7eb2Smrg //printf("toCppMangleItanium(%s)\n", s->toChars());
1118*627f7eb2Smrg OutBuffer buf;
1119*627f7eb2Smrg CppMangleVisitor v(&buf, s->loc);
1120*627f7eb2Smrg v.mangleOf(s);
1121*627f7eb2Smrg return buf.extractString();
1122*627f7eb2Smrg }
1123*627f7eb2Smrg
cppTypeInfoMangleItanium(Dsymbol * s)1124*627f7eb2Smrg const char *cppTypeInfoMangleItanium(Dsymbol *s)
1125*627f7eb2Smrg {
1126*627f7eb2Smrg //printf("cppTypeInfoMangleItanium(%s)\n", s->toChars());
1127*627f7eb2Smrg OutBuffer buf;
1128*627f7eb2Smrg buf.writestring("_ZTI"); // "TI" means typeinfo structure
1129*627f7eb2Smrg CppMangleVisitor v(&buf, s->loc);
1130*627f7eb2Smrg v.cpp_mangle_name(s, false);
1131*627f7eb2Smrg return buf.extractString();
1132*627f7eb2Smrg }
1133