]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/dmangle.c
d/dmd: Merge upstream dmd e9420cfbf
[thirdparty/gcc.git] / gcc / d / dmd / dmangle.c
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/mangle.c
9 */
10
11 #include "root/dsystem.h"
12 #include "root/root.h"
13
14 #include "mangle.h"
15 #include "init.h"
16 #include "declaration.h"
17 #include "aggregate.h"
18 #include "mtype.h"
19 #include "attrib.h"
20 #include "target.h"
21 #include "template.h"
22 #include "id.h"
23 #include "module.h"
24 #include "enum.h"
25 #include "expression.h"
26 #include "utf.h"
27
28 typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param);
29 int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL);
30
31 static const char *mangleChar[TMAX];
32
33 void initTypeMangle()
34 {
35 mangleChar[Tarray] = "A";
36 mangleChar[Tsarray] = "G";
37 mangleChar[Taarray] = "H";
38 mangleChar[Tpointer] = "P";
39 mangleChar[Treference] = "R";
40 mangleChar[Tfunction] = "F";
41 mangleChar[Tident] = "I";
42 mangleChar[Tclass] = "C";
43 mangleChar[Tstruct] = "S";
44 mangleChar[Tenum] = "E";
45 mangleChar[Tdelegate] = "D";
46
47 mangleChar[Tnone] = "n";
48 mangleChar[Tvoid] = "v";
49 mangleChar[Tint8] = "g";
50 mangleChar[Tuns8] = "h";
51 mangleChar[Tint16] = "s";
52 mangleChar[Tuns16] = "t";
53 mangleChar[Tint32] = "i";
54 mangleChar[Tuns32] = "k";
55 mangleChar[Tint64] = "l";
56 mangleChar[Tuns64] = "m";
57 mangleChar[Tint128] = "zi";
58 mangleChar[Tuns128] = "zk";
59 mangleChar[Tfloat32] = "f";
60 mangleChar[Tfloat64] = "d";
61 mangleChar[Tfloat80] = "e";
62
63 mangleChar[Timaginary32] = "o";
64 mangleChar[Timaginary64] = "p";
65 mangleChar[Timaginary80] = "j";
66 mangleChar[Tcomplex32] = "q";
67 mangleChar[Tcomplex64] = "r";
68 mangleChar[Tcomplex80] = "c";
69
70 mangleChar[Tbool] = "b";
71 mangleChar[Tchar] = "a";
72 mangleChar[Twchar] = "u";
73 mangleChar[Tdchar] = "w";
74
75 // '@' shouldn't appear anywhere in the deco'd names
76 mangleChar[Tinstance] = "@";
77 mangleChar[Terror] = "@";
78 mangleChar[Ttypeof] = "@";
79 mangleChar[Ttuple] = "B";
80 mangleChar[Tslice] = "@";
81 mangleChar[Treturn] = "@";
82 mangleChar[Tvector] = "@";
83 mangleChar[Ttraits] = "@";
84
85 mangleChar[Tnull] = "n"; // same as TypeNone
86
87 for (size_t i = 0; i < TMAX; i++)
88 {
89 if (!mangleChar[i])
90 fprintf(stderr, "ty = %llu\n", (ulonglong)i);
91 assert(mangleChar[i]);
92 }
93 }
94
95 /*********************************
96 * Mangling for mod.
97 */
98 void MODtoDecoBuffer(OutBuffer *buf, MOD mod)
99 {
100 switch (mod)
101 {
102 case 0:
103 break;
104 case MODconst:
105 buf->writeByte('x');
106 break;
107 case MODimmutable:
108 buf->writeByte('y');
109 break;
110 case MODshared:
111 buf->writeByte('O');
112 break;
113 case MODshared | MODconst:
114 buf->writestring("Ox");
115 break;
116 case MODwild:
117 buf->writestring("Ng");
118 break;
119 case MODwildconst:
120 buf->writestring("Ngx");
121 break;
122 case MODshared | MODwild:
123 buf->writestring("ONg");
124 break;
125 case MODshared | MODwildconst:
126 buf->writestring("ONgx");
127 break;
128 default:
129 assert(0);
130 }
131 }
132
133 class Mangler : public Visitor
134 {
135 public:
136 OutBuffer *buf;
137
138 Mangler(OutBuffer *buf)
139 {
140 this->buf = buf;
141 }
142
143
144 ////////////////////////////////////////////////////////////////////////////
145
146 /**************************************************
147 * Type mangling
148 */
149
150 void visitWithMask(Type *t, unsigned char modMask)
151 {
152 if (modMask != t->mod)
153 {
154 MODtoDecoBuffer(buf, t->mod);
155 }
156 t->accept(this);
157 }
158
159 void visit(Type *t)
160 {
161 buf->writestring(mangleChar[t->ty]);
162 }
163
164 void visit(TypeNext *t)
165 {
166 visit((Type *)t);
167 visitWithMask(t->next, t->mod);
168 }
169
170 void visit(TypeVector *t)
171 {
172 buf->writestring("Nh");
173 visitWithMask(t->basetype, t->mod);
174 }
175
176 void visit(TypeSArray *t)
177 {
178 visit((Type *)t);
179 if (t->dim)
180 buf->printf("%llu", t->dim->toInteger());
181 if (t->next)
182 visitWithMask(t->next, t->mod);
183 }
184
185 void visit(TypeDArray *t)
186 {
187 visit((Type *)t);
188 if (t->next)
189 visitWithMask(t->next, t->mod);
190 }
191
192 void visit(TypeAArray *t)
193 {
194 visit((Type *)t);
195 visitWithMask(t->index, 0);
196 visitWithMask(t->next, t->mod);
197 }
198
199 void visit(TypeFunction *t)
200 {
201 //printf("TypeFunction::toDecoBuffer() t = %p %s\n", t, t->toChars());
202 //static int nest; if (++nest == 50) *(char*)0=0;
203
204 mangleFuncType(t, t, t->mod, t->next);
205 }
206
207 void mangleFuncType(TypeFunction *t, TypeFunction *ta, unsigned char modMask, Type *tret)
208 {
209 //printf("mangleFuncType() %s\n", t->toChars());
210 if (t->inuse)
211 {
212 t->inuse = 2; // flag error to caller
213 return;
214 }
215 t->inuse++;
216
217 if (modMask != t->mod)
218 MODtoDecoBuffer(buf, t->mod);
219
220 unsigned char mc;
221 switch (t->linkage)
222 {
223 case LINKd: mc = 'F'; break;
224 case LINKc: mc = 'U'; break;
225 case LINKwindows: mc = 'W'; break;
226 case LINKpascal: mc = 'V'; break;
227 case LINKcpp: mc = 'R'; break;
228 case LINKobjc: mc = 'Y'; break;
229 default:
230 assert(0);
231 }
232 buf->writeByte(mc);
233
234 if (ta->purity || ta->isnothrow || ta->isnogc || ta->isproperty || ta->isref || ta->trust || ta->isreturn || ta->isscope)
235 {
236 if (ta->purity)
237 buf->writestring("Na");
238 if (ta->isnothrow)
239 buf->writestring("Nb");
240 if (ta->isref)
241 buf->writestring("Nc");
242 if (ta->isproperty)
243 buf->writestring("Nd");
244 if (ta->isnogc)
245 buf->writestring("Ni");
246 if (ta->isreturn)
247 buf->writestring("Nj");
248 if (ta->isscope && !ta->isreturn && !ta->isscopeinferred)
249 buf->writestring("Nl");
250 switch (ta->trust)
251 {
252 case TRUSTtrusted:
253 buf->writestring("Ne");
254 break;
255 case TRUSTsafe:
256 buf->writestring("Nf");
257 break;
258 default:
259 break;
260 }
261 }
262
263 // Write argument types
264 paramsToDecoBuffer(t->parameters);
265 //if (buf->data[buf->offset - 1] == '@') halt();
266 buf->writeByte('Z' - t->varargs); // mark end of arg list
267 if (tret != NULL)
268 visitWithMask(tret, 0);
269
270 t->inuse--;
271 }
272
273 void visit(TypeIdentifier *t)
274 {
275 visit((Type *)t);
276 const char *name = t->ident->toChars();
277 size_t len = strlen(name);
278 buf->printf("%u%s", (unsigned)len, name);
279 }
280
281 void visit(TypeEnum *t)
282 {
283 visit((Type *)t);
284 t->sym->accept(this);
285 }
286
287 void visit(TypeStruct *t)
288 {
289 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", t->toChars(), name);
290 visit((Type *)t);
291 t->sym->accept(this);
292 }
293
294 void visit(TypeClass *t)
295 {
296 //printf("TypeClass::toDecoBuffer('%s' mod=%x) = '%s'\n", t->toChars(), mod, name);
297 visit((Type *)t);
298 t->sym->accept(this);
299 }
300
301 void visit(TypeTuple *t)
302 {
303 //printf("TypeTuple::toDecoBuffer() t = %p, %s\n", t, t->toChars());
304 visit((Type *)t);
305
306 OutBuffer buf2;
307 buf2.reserve(32);
308 Mangler v(&buf2);
309 v.paramsToDecoBuffer(t->arguments);
310 const char *s = buf2.peekString();
311 int len = (int)buf2.offset;
312 buf->printf("%d%.*s", len, len, s);
313 }
314
315 void visit(TypeNull *t)
316 {
317 visit((Type *)t);
318 }
319
320 ////////////////////////////////////////////////////////////////////////////
321
322 void mangleDecl(Declaration *sthis)
323 {
324 mangleParent(sthis);
325
326 assert(sthis->ident);
327 const char *id = sthis->ident->toChars();
328 toBuffer(id, sthis);
329
330 if (FuncDeclaration *fd = sthis->isFuncDeclaration())
331 {
332 mangleFunc(fd, false);
333 }
334 else if (sthis->type->deco)
335 {
336 buf->writestring(sthis->type->deco);
337 }
338 else
339 assert(0);
340 }
341
342 void mangleParent(Dsymbol *s)
343 {
344 Dsymbol *p;
345 if (TemplateInstance *ti = s->isTemplateInstance())
346 p = ti->isTemplateMixin() ? ti->parent : ti->tempdecl->parent;
347 else
348 p = s->parent;
349
350 if (p)
351 {
352 mangleParent(p);
353
354 if (p->getIdent())
355 {
356 const char *id = p->ident->toChars();
357 toBuffer(id, s);
358
359 if (FuncDeclaration *f = p->isFuncDeclaration())
360 mangleFunc(f, true);
361 }
362 else
363 buf->writeByte('0');
364 }
365 }
366
367 void mangleFunc(FuncDeclaration *fd, bool inParent)
368 {
369 //printf("deco = '%s'\n", fd->type->deco ? fd->type->deco : "null");
370 //printf("fd->type = %s\n", fd->type->toChars());
371 if (fd->needThis() || fd->isNested())
372 buf->writeByte('M');
373 if (inParent)
374 {
375 TypeFunction *tf = (TypeFunction *)fd->type;
376 TypeFunction *tfo = (TypeFunction *)fd->originalType;
377 mangleFuncType(tf, tfo, 0, NULL);
378 }
379 else if (fd->type->deco)
380 {
381 buf->writestring(fd->type->deco);
382 }
383 else
384 {
385 printf("[%s] %s %s\n", fd->loc.toChars(), fd->toChars(), fd->type->toChars());
386 assert(0); // don't mangle function until semantic3 done.
387 }
388 }
389
390 /************************************************************
391 * Write length prefixed string to buf.
392 */
393 void toBuffer(const char *id, Dsymbol *s)
394 {
395 size_t len = strlen(id);
396 if (len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
397 s->error("excessive length %llu for symbol, possible recursive expansion?", len);
398 else
399 {
400 buf->printf("%llu", (ulonglong)len);
401 buf->write(id, len);
402 }
403 }
404
405 void visit(Declaration *d)
406 {
407 //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n",
408 // d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage);
409 if (!d->parent || d->parent->isModule() || d->linkage == LINKcpp) // if at global scope
410 {
411 switch (d->linkage)
412 {
413 case LINKd:
414 break;
415
416 case LINKc:
417 case LINKwindows:
418 case LINKpascal:
419 case LINKobjc:
420 buf->writestring(d->ident->toChars());
421 return;
422
423 case LINKcpp:
424 buf->writestring(Target::toCppMangle(d));
425 return;
426
427 case LINKdefault:
428 d->error("forward declaration");
429 buf->writestring(d->ident->toChars());
430 return;
431
432 default:
433 fprintf(stderr, "'%s', linkage = %d\n", d->toChars(), d->linkage);
434 assert(0);
435 return;
436 }
437 }
438
439 buf->writestring("_D");
440 mangleDecl(d);
441 }
442
443 /******************************************************************************
444 * Normally FuncDeclaration and FuncAliasDeclaration have overloads.
445 * If and only if there is no overloads, mangle() could return
446 * exact mangled name.
447 *
448 * module test;
449 * void foo(long) {} // _D4test3fooFlZv
450 * void foo(string) {} // _D4test3fooFAyaZv
451 *
452 * // from FuncDeclaration::mangle().
453 * pragma(msg, foo.mangleof); // prints unexact mangled name "4test3foo"
454 * // by calling Dsymbol::mangle()
455 *
456 * // from FuncAliasDeclaration::mangle()
457 * pragma(msg, __traits(getOverloads, test, "foo")[0].mangleof); // "_D4test3fooFlZv"
458 * pragma(msg, __traits(getOverloads, test, "foo")[1].mangleof); // "_D4test3fooFAyaZv"
459 *
460 * If a function has no overloads, .mangleof property still returns exact mangled name.
461 *
462 * void bar() {}
463 * pragma(msg, bar.mangleof); // still prints "_D4test3barFZv"
464 * // by calling FuncDeclaration::mangleExact().
465 */
466 void visit(FuncDeclaration *fd)
467 {
468 if (fd->isUnique())
469 mangleExact(fd);
470 else
471 visit((Dsymbol *)fd);
472 }
473
474 // ditto
475 void visit(FuncAliasDeclaration *fd)
476 {
477 FuncDeclaration *f = fd->toAliasFunc();
478 FuncAliasDeclaration *fa = f->isFuncAliasDeclaration();
479 if (!fd->hasOverloads && !fa)
480 {
481 mangleExact(f);
482 return;
483 }
484 if (fa)
485 {
486 fa->accept(this);
487 return;
488 }
489 visit((Dsymbol *)fd);
490 }
491
492 void visit(OverDeclaration *od)
493 {
494 if (od->overnext)
495 {
496 visit((Dsymbol *)od);
497 return;
498 }
499
500 if (FuncDeclaration *fd = od->aliassym->isFuncDeclaration())
501 {
502 if (!od->hasOverloads || fd->isUnique())
503 {
504 mangleExact(fd);
505 return;
506 }
507 }
508 if (TemplateDeclaration *td = od->aliassym->isTemplateDeclaration())
509 {
510 if (!od->hasOverloads || td->overnext == NULL)
511 {
512 td->accept(this);
513 return;
514 }
515 }
516 visit((Dsymbol *)od);
517 }
518
519 void mangleExact(FuncDeclaration *fd)
520 {
521 assert(!fd->isFuncAliasDeclaration());
522
523 if (fd->mangleOverride)
524 {
525 buf->writestring(fd->mangleOverride);
526 return;
527 }
528
529 if (fd->isMain())
530 {
531 buf->writestring("_Dmain");
532 return;
533 }
534
535 if (fd->isWinMain() || fd->isDllMain() || fd->ident == Id::tls_get_addr)
536 {
537 buf->writestring(fd->ident->toChars());
538 return;
539 }
540
541 visit((Declaration *)fd);
542 }
543
544 void visit(VarDeclaration *vd)
545 {
546 if (vd->mangleOverride)
547 {
548 buf->writestring(vd->mangleOverride);
549 return;
550 }
551
552 visit((Declaration *)vd);
553 }
554
555 void visit(AggregateDeclaration *ad)
556 {
557 ClassDeclaration *cd = ad->isClassDeclaration();
558 Dsymbol *parentsave = ad->parent;
559 if (cd)
560 {
561 /* These are reserved to the compiler, so keep simple
562 * names for them.
563 */
564 if ((cd->ident == Id::Exception && cd->parent->ident == Id::object) ||
565 cd->ident == Id::TypeInfo ||
566 cd->ident == Id::TypeInfo_Struct ||
567 cd->ident == Id::TypeInfo_Class ||
568 cd->ident == Id::TypeInfo_Tuple ||
569 cd == ClassDeclaration::object ||
570 cd == Type::typeinfoclass ||
571 cd == Module::moduleinfo ||
572 strncmp(cd->ident->toChars(), "TypeInfo_", 9) == 0)
573 {
574 // Don't mangle parent
575 ad->parent = NULL;
576 }
577 }
578
579 visit((Dsymbol *)ad);
580
581 ad->parent = parentsave;
582 }
583
584 void visit(TemplateInstance *ti)
585 {
586 if (!ti->tempdecl)
587 ti->error("is not defined");
588 else
589 mangleParent(ti);
590
591 ti->getIdent();
592 const char *id = ti->ident ? ti->ident->toChars() : ti->toChars();
593 toBuffer(id, ti);
594
595 //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id);
596 }
597
598 void visit(Dsymbol *s)
599 {
600 mangleParent(s);
601
602 const char *id = s->ident ? s->ident->toChars() : s->toChars();
603 toBuffer(id, s);
604
605 //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id);
606 }
607
608 ////////////////////////////////////////////////////////////////////////////
609
610 void visit(Expression *e)
611 {
612 e->error("expression %s is not a valid template value argument", e->toChars());
613 }
614
615 void visit(IntegerExp *e)
616 {
617 if ((sinteger_t)e->value < 0)
618 buf->printf("N%lld", -e->value);
619 else
620 buf->printf("i%lld", e->value);
621 }
622
623 void visit(RealExp *e)
624 {
625 buf->writeByte('e');
626 realToMangleBuffer(e->value);
627 }
628
629 void realToMangleBuffer(real_t value)
630 {
631 /* Rely on %A to get portable mangling.
632 * Must munge result to get only identifier characters.
633 *
634 * Possible values from %A => mangled result
635 * NAN => NAN
636 * -INF => NINF
637 * INF => INF
638 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
639 * 0X1.9P+2 => 19P2
640 */
641
642 if (CTFloat::isNaN(value))
643 buf->writestring("NAN"); // no -NAN bugs
644 else if (CTFloat::isInfinity(value))
645 buf->writestring(value < CTFloat::zero ? "NINF" : "INF");
646 else
647 {
648 const size_t BUFFER_LEN = 36;
649 char buffer[BUFFER_LEN];
650 size_t n = CTFloat::sprint(buffer, 'A', value);
651 assert(n < BUFFER_LEN);
652 for (size_t i = 0; i < n; i++)
653 {
654 char c = buffer[i];
655 switch (c)
656 {
657 case '-':
658 buf->writeByte('N');
659 break;
660
661 case '+':
662 case 'X':
663 case '.':
664 break;
665
666 case '0':
667 if (i < 2)
668 break; // skip leading 0X
669 /* fall through */
670 default:
671 buf->writeByte(c);
672 break;
673 }
674 }
675 }
676 }
677
678 void visit(ComplexExp *e)
679 {
680 buf->writeByte('c');
681 realToMangleBuffer(e->toReal());
682 buf->writeByte('c'); // separate the two
683 realToMangleBuffer(e->toImaginary());
684 }
685
686 void visit(NullExp *)
687 {
688 buf->writeByte('n');
689 }
690
691 void visit(StringExp *e)
692 {
693 char m;
694 OutBuffer tmp;
695 utf8_t *q;
696 size_t qlen;
697
698 /* Write string in UTF-8 format
699 */
700 switch (e->sz)
701 {
702 case 1:
703 m = 'a';
704 q = (utf8_t *)e->string;
705 qlen = e->len;
706 break;
707
708 case 2:
709 m = 'w';
710 for (size_t u = 0; u < e->len; )
711 {
712 unsigned c;
713 const char *p = utf_decodeWchar((unsigned short *)e->string, e->len, &u, &c);
714 if (p)
715 e->error("%s", p);
716 else
717 tmp.writeUTF8(c);
718 }
719 q = (utf8_t *)tmp.data;
720 qlen = tmp.offset;
721 break;
722
723 case 4:
724 m = 'd';
725 for (size_t u = 0; u < e->len; u++)
726 {
727 unsigned c = ((unsigned *)e->string)[u];
728 if (!utf_isValidDchar(c))
729 e->error("invalid UCS-32 char \\U%08x", c);
730 else
731 tmp.writeUTF8(c);
732 }
733 q = (utf8_t *)tmp.data;
734 qlen = tmp.offset;
735 break;
736
737 default:
738 assert(0);
739 }
740 buf->reserve(1 + 11 + 2 * qlen);
741 buf->writeByte(m);
742 buf->printf("%d_", (int)qlen); // nbytes <= 11
743
744 for (utf8_t *p = (utf8_t *)buf->data + buf->offset, *pend = p + 2 * qlen;
745 p < pend; p += 2, ++q)
746 {
747 utf8_t hi = *q >> 4 & 0xF;
748 p[0] = (utf8_t)(hi < 10 ? hi + '0' : hi - 10 + 'a');
749 utf8_t lo = *q & 0xF;
750 p[1] = (utf8_t)(lo < 10 ? lo + '0' : lo - 10 + 'a');
751 }
752 buf->offset += 2 * qlen;
753 }
754
755 void visit(ArrayLiteralExp *e)
756 {
757 size_t dim = e->elements ? e->elements->dim : 0;
758 buf->printf("A%u", dim);
759 for (size_t i = 0; i < dim; i++)
760 {
761 e->getElement(i)->accept(this);
762 }
763 }
764
765 void visit(AssocArrayLiteralExp *e)
766 {
767 size_t dim = e->keys->dim;
768 buf->printf("A%u", dim);
769 for (size_t i = 0; i < dim; i++)
770 {
771 (*e->keys)[i]->accept(this);
772 (*e->values)[i]->accept(this);
773 }
774 }
775
776 void visit(StructLiteralExp *e)
777 {
778 size_t dim = e->elements ? e->elements->dim : 0;
779 buf->printf("S%u", dim);
780 for (size_t i = 0; i < dim; i++)
781 {
782 Expression *ex = (*e->elements)[i];
783 if (ex)
784 ex->accept(this);
785 else
786 buf->writeByte('v'); // 'v' for void
787 }
788 }
789
790 ////////////////////////////////////////////////////////////////////////////
791
792 void paramsToDecoBuffer(Parameters *parameters)
793 {
794 //printf("Parameter::paramsToDecoBuffer()\n");
795 Parameter_foreach(parameters, &paramsToDecoBufferDg, (void *)this);
796 }
797
798 static int paramsToDecoBufferDg(void *ctx, size_t, Parameter *p)
799 {
800 p->accept((Visitor *)ctx);
801 return 0;
802 }
803
804 void visit(Parameter *p)
805 {
806 if (p->storageClass & STCscope && !(p->storageClass & STCscopeinferred))
807 buf->writeByte('M');
808 // 'return inout ref' is the same as 'inout ref'
809 if ((p->storageClass & (STCreturn | STCwild)) == STCreturn)
810 buf->writestring("Nk");
811 switch (p->storageClass & (STCin | STCout | STCref | STClazy))
812 {
813 case 0:
814 case STCin:
815 break;
816 case STCout:
817 buf->writeByte('J');
818 break;
819 case STCref:
820 buf->writeByte('K');
821 break;
822 case STClazy:
823 buf->writeByte('L');
824 break;
825 default:
826 assert(0);
827 }
828 visitWithMask(p->type, 0);
829 }
830 };
831
832 /******************************************************************************
833 * Returns exact mangled name of function.
834 */
835 const char *mangleExact(FuncDeclaration *fd)
836 {
837 if (!fd->mangleString)
838 {
839 OutBuffer buf;
840 Mangler v(&buf);
841 v.mangleExact(fd);
842 fd->mangleString = buf.extractString();
843 }
844 return fd->mangleString;
845 }
846
847 void mangleToBuffer(Type *t, OutBuffer *buf)
848 {
849 Mangler v(buf);
850 v.visitWithMask(t, 0);
851 }
852
853 void mangleToBuffer(Expression *e, OutBuffer *buf)
854 {
855 Mangler v(buf);
856 e->accept(&v);
857 }
858
859 void mangleToBuffer(Dsymbol *s, OutBuffer *buf)
860 {
861 Mangler v(buf);
862 s->accept(&v);
863 }