]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/cppmangle.c
d: Merge upstream dmd 47ed0330f
[thirdparty/gcc.git] / gcc / d / dmd / cppmangle.c
1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2020 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
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 * 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 */
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 */
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
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 */
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 */
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
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>
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>
347 static bool isAllocator_char(RootObject *o)
348 {
349 return isIdent_char(Id::allocator, o);
350 }
351
352 // Detect type ::std::ident<char>
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 */
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
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
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
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
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
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
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:
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 */
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
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 */
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
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 */
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
792 void visit(TypeNull *t)
793 {
794 if (t->isImmutable() || t->isShared())
795 return error(t);
796
797 writeBasicType(t, 'D', 'n');
798 }
799
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
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
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
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
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
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
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
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 */
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
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 */
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
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
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
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 }