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