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