xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/cppmangle.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
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