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