]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/hdrgen.c
af933bd2e88d94fce383850bcbb0aeb71f11d3fc
[thirdparty/gcc.git] / gcc / d / dmd / hdrgen.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 Dave Fladebo
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/hdrgen.c
9 */
10
11 // Routines to emit header files
12
13 #include "root/dsystem.h"
14 #include "root/rmem.h"
15
16 #include "mars.h"
17 #include "id.h"
18 #include "init.h"
19
20 #include "attrib.h"
21 #include "cond.h"
22 #include "doc.h"
23 #include "enum.h"
24 #include "import.h"
25 #include "module.h"
26 #include "mtype.h"
27 #include "parse.h"
28 #include "scope.h"
29 #include "staticassert.h"
30 #include "target.h"
31 #include "template.h"
32 #include "utf.h"
33 #include "version.h"
34
35 #include "declaration.h"
36 #include "aggregate.h"
37 #include "expression.h"
38 #include "ctfe.h"
39 #include "statement.h"
40 #include "aliasthis.h"
41 #include "nspace.h"
42 #include "hdrgen.h"
43
44 void linkageToBuffer(OutBuffer *buf, LINK linkage);
45 void MODtoBuffer(OutBuffer *buf, MOD mod);
46
47 void genhdrfile(Module *m)
48 {
49 OutBuffer buf;
50 buf.doindent = 1;
51
52 buf.printf("// D import file generated from '%s'", m->srcfile->toChars());
53 buf.writenl();
54
55 HdrGenState hgs;
56 hgs.hdrgen = true;
57
58 toCBuffer(m, &buf, &hgs);
59
60 // Transfer image to file
61 m->hdrfile->setbuffer(buf.data, buf.offset);
62 buf.extractData();
63
64 ensurePathToNameExists(Loc(), m->hdrfile->toChars());
65 writeFile(m->loc, m->hdrfile);
66 }
67
68 /**
69 * Dumps the full contents of module `m` to `buf`.
70 * Params:
71 * buf = buffer to write to.
72 * m = module to visit all members of.
73 */
74 void moduleToBuffer(OutBuffer *buf, Module *m)
75 {
76 HdrGenState hgs;
77 hgs.fullDump = true;
78 toCBuffer(m, buf, &hgs);
79 }
80
81 class PrettyPrintVisitor : public Visitor
82 {
83 public:
84 OutBuffer *buf;
85 HdrGenState *hgs;
86 bool declstring; // set while declaring alias for string,wstring or dstring
87 EnumDeclaration *inEnumDecl;
88
89 PrettyPrintVisitor(OutBuffer *buf, HdrGenState *hgs)
90 : buf(buf), hgs(hgs), declstring(false), inEnumDecl(NULL)
91 {
92 }
93
94 void visit(Statement *)
95 {
96 buf->printf("Statement::toCBuffer()");
97 buf->writenl();
98 assert(0);
99 }
100
101 void visit(ErrorStatement *)
102 {
103 buf->printf("__error__");
104 buf->writenl();
105 }
106
107 void visit(ExpStatement *s)
108 {
109 if (s->exp && s->exp->op == TOKdeclaration)
110 {
111 // bypass visit(DeclarationExp)
112 ((DeclarationExp *)s->exp)->declaration->accept(this);
113 return;
114 }
115 if (s->exp)
116 s->exp->accept(this);
117 buf->writeByte(';');
118 if (!hgs->forStmtInit)
119 buf->writenl();
120 }
121
122 void visit(CompileStatement *s)
123 {
124 buf->writestring("mixin(");
125 s->exp->accept(this);
126 buf->writestring(");");
127 if (!hgs->forStmtInit)
128 buf->writenl();
129 }
130
131 void visit(CompoundStatement *s)
132 {
133 for (size_t i = 0; i < s->statements->length; i++)
134 {
135 Statement *sx = (*s->statements)[i];
136 if (sx)
137 sx->accept(this);
138 }
139 }
140
141 void visit(CompoundDeclarationStatement *s)
142 {
143 bool anywritten = false;
144 for (size_t i = 0; i < s->statements->length; i++)
145 {
146 Statement *sx = (*s->statements)[i];
147 ExpStatement *ds = sx ? sx->isExpStatement() : NULL;
148 if (ds && ds->exp->op == TOKdeclaration)
149 {
150 Dsymbol *d = ((DeclarationExp *)ds->exp)->declaration;
151 assert(d->isDeclaration());
152 if (VarDeclaration *v = d->isVarDeclaration())
153 visitVarDecl(v, anywritten);
154 else
155 d->accept(this);
156 anywritten = true;
157 }
158 }
159 buf->writeByte(';');
160 if (!hgs->forStmtInit)
161 buf->writenl();
162 }
163
164 void visit(UnrolledLoopStatement *s)
165 {
166 buf->writestring("unrolled {");
167 buf->writenl();
168 buf->level++;
169
170 for (size_t i = 0; i < s->statements->length; i++)
171 {
172 Statement *sx = (*s->statements)[i];
173 if (sx)
174 sx->accept(this);
175 }
176
177 buf->level--;
178 buf->writeByte('}');
179 buf->writenl();
180 }
181
182 void visit(ScopeStatement *s)
183 {
184 buf->writeByte('{');
185 buf->writenl();
186 buf->level++;
187
188 if (s->statement)
189 s->statement->accept(this);
190
191 buf->level--;
192 buf->writeByte('}');
193 buf->writenl();
194 }
195
196 void visit(WhileStatement *s)
197 {
198 buf->writestring("while (");
199 s->condition->accept(this);
200 buf->writeByte(')');
201 buf->writenl();
202 if (s->_body)
203 s->_body->accept(this);
204 }
205
206 void visit(DoStatement *s)
207 {
208 buf->writestring("do");
209 buf->writenl();
210 if (s->_body)
211 s->_body->accept(this);
212 buf->writestring("while (");
213 s->condition->accept(this);
214 buf->writestring(");");
215 buf->writenl();
216 }
217
218 void visit(ForStatement *s)
219 {
220 buf->writestring("for (");
221 if (s->_init)
222 {
223 hgs->forStmtInit++;
224 s->_init->accept(this);
225 hgs->forStmtInit--;
226 }
227 else
228 buf->writeByte(';');
229 if (s->condition)
230 {
231 buf->writeByte(' ');
232 s->condition->accept(this);
233 }
234 buf->writeByte(';');
235 if (s->increment)
236 {
237 buf->writeByte(' ');
238 s->increment->accept(this);
239 }
240 buf->writeByte(')');
241 buf->writenl();
242 buf->writeByte('{');
243 buf->writenl();
244 buf->level++;
245 if (s->_body)
246 s->_body->accept(this);
247 buf->level--;
248 buf->writeByte('}');
249 buf->writenl();
250 }
251
252 void foreachWithoutBody(ForeachStatement *s)
253 {
254 buf->writestring(Token::toChars(s->op));
255 buf->writestring(" (");
256 for (size_t i = 0; i < s->parameters->length; i++)
257 {
258 Parameter *p = (*s->parameters)[i];
259 if (i)
260 buf->writestring(", ");
261 if (stcToBuffer(buf, p->storageClass))
262 buf->writeByte(' ');
263 if (p->type)
264 typeToBuffer(p->type, p->ident);
265 else
266 buf->writestring(p->ident->toChars());
267 }
268 buf->writestring("; ");
269 s->aggr->accept(this);
270 buf->writeByte(')');
271 buf->writenl();
272 }
273
274 void visit(ForeachStatement *s)
275 {
276 foreachWithoutBody(s);
277 buf->writeByte('{');
278 buf->writenl();
279 buf->level++;
280 if (s->_body)
281 s->_body->accept(this);
282 buf->level--;
283 buf->writeByte('}');
284 buf->writenl();
285 }
286
287 void foreachRangeWithoutBody(ForeachRangeStatement *s)
288 {
289 buf->writestring(Token::toChars(s->op));
290 buf->writestring(" (");
291
292 if (s->prm->type)
293 typeToBuffer(s->prm->type, s->prm->ident);
294 else
295 buf->writestring(s->prm->ident->toChars());
296
297 buf->writestring("; ");
298 s->lwr->accept(this);
299 buf->writestring(" .. ");
300 s->upr->accept(this);
301 buf->writeByte(')');
302 buf->writenl();
303 buf->writeByte('{');
304 buf->writenl();
305 }
306
307 void visit(ForeachRangeStatement *s)
308 {
309 foreachRangeWithoutBody(s);
310 buf->level++;
311 if (s->_body)
312 s->_body->accept(this);
313 buf->level--;
314 buf->writeByte('}');
315 buf->writenl();
316 }
317
318 void visit(StaticForeachStatement *s)
319 {
320 buf->writestring("static ");
321 if (s->sfe->aggrfe)
322 {
323 visit(s->sfe->aggrfe);
324 }
325 else
326 {
327 assert(s->sfe->rangefe);
328 visit(s->sfe->rangefe);
329 }
330 }
331
332 void visit(IfStatement *s)
333 {
334 buf->writestring("if (");
335 if (Parameter *p = s->prm)
336 {
337 StorageClass stc = p->storageClass;
338 if (!p->type && !stc)
339 stc = STCauto;
340 if (stcToBuffer(buf, stc))
341 buf->writeByte(' ');
342 if (p->type)
343 typeToBuffer(p->type, p->ident);
344 else
345 buf->writestring(p->ident->toChars());
346 buf->writestring(" = ");
347 }
348 s->condition->accept(this);
349 buf->writeByte(')');
350 buf->writenl();
351 if (s->ifbody->isScopeStatement())
352 {
353 s->ifbody->accept(this);
354 }
355 else
356 {
357 buf->level++;
358 s->ifbody->accept(this);
359 buf->level--;
360 }
361 if (s->elsebody)
362 {
363 buf->writestring("else");
364 if (!s->elsebody->isIfStatement())
365 {
366 buf->writenl();
367 }
368 else
369 {
370 buf->writeByte(' ');
371 }
372 if (s->elsebody->isScopeStatement() || s->elsebody->isIfStatement())
373 {
374 s->elsebody->accept(this);
375 }
376 else
377 {
378 buf->level++;
379 s->elsebody->accept(this);
380 buf->level--;
381 }
382 }
383 }
384
385 void visit(ConditionalStatement *s)
386 {
387 s->condition->accept(this);
388 buf->writenl();
389 buf->writeByte('{');
390 buf->writenl();
391 buf->level++;
392 if (s->ifbody)
393 s->ifbody->accept(this);
394 buf->level--;
395 buf->writeByte('}');
396 buf->writenl();
397 if (s->elsebody)
398 {
399 buf->writestring("else");
400 buf->writenl();
401 buf->writeByte('{');
402 buf->level++;
403 buf->writenl();
404 s->elsebody->accept(this);
405 buf->level--;
406 buf->writeByte('}');
407 }
408 buf->writenl();
409 }
410
411 void visit(PragmaStatement *s)
412 {
413 buf->writestring("pragma (");
414 buf->writestring(s->ident->toChars());
415 if (s->args && s->args->length)
416 {
417 buf->writestring(", ");
418 argsToBuffer(s->args);
419 }
420 buf->writeByte(')');
421 if (s->_body)
422 {
423 buf->writenl();
424 buf->writeByte('{');
425 buf->writenl();
426 buf->level++;
427
428 s->_body->accept(this);
429
430 buf->level--;
431 buf->writeByte('}');
432 buf->writenl();
433 }
434 else
435 {
436 buf->writeByte(';');
437 buf->writenl();
438 }
439 }
440
441 void visit(StaticAssertStatement *s)
442 {
443 s->sa->accept(this);
444 }
445
446 void visit(SwitchStatement *s)
447 {
448 buf->writestring(s->isFinal ? "final switch (" : "switch (");
449 s->condition->accept(this);
450 buf->writeByte(')');
451 buf->writenl();
452 if (s->_body)
453 {
454 if (!s->_body->isScopeStatement())
455 {
456 buf->writeByte('{');
457 buf->writenl();
458 buf->level++;
459 s->_body->accept(this);
460 buf->level--;
461 buf->writeByte('}');
462 buf->writenl();
463 }
464 else
465 {
466 s->_body->accept(this);
467 }
468 }
469 }
470
471 void visit(CaseStatement *s)
472 {
473 buf->writestring("case ");
474 s->exp->accept(this);
475 buf->writeByte(':');
476 buf->writenl();
477 s->statement->accept(this);
478 }
479
480 void visit(CaseRangeStatement *s)
481 {
482 buf->writestring("case ");
483 s->first->accept(this);
484 buf->writestring(": .. case ");
485 s->last->accept(this);
486 buf->writeByte(':');
487 buf->writenl();
488 s->statement->accept(this);
489 }
490
491 void visit(DefaultStatement *s)
492 {
493 buf->writestring("default:");
494 buf->writenl();
495 s->statement->accept(this);
496 }
497
498 void visit(GotoDefaultStatement *)
499 {
500 buf->writestring("goto default;");
501 buf->writenl();
502 }
503
504 void visit(GotoCaseStatement *s)
505 {
506 buf->writestring("goto case");
507 if (s->exp)
508 {
509 buf->writeByte(' ');
510 s->exp->accept(this);
511 }
512 buf->writeByte(';');
513 buf->writenl();
514 }
515
516 void visit(SwitchErrorStatement *)
517 {
518 buf->writestring("SwitchErrorStatement::toCBuffer()");
519 buf->writenl();
520 }
521
522 void visit(ReturnStatement *s)
523 {
524 buf->printf("return ");
525 if (s->exp)
526 s->exp->accept(this);
527 buf->writeByte(';');
528 buf->writenl();
529 }
530
531 void visit(BreakStatement *s)
532 {
533 buf->writestring("break");
534 if (s->ident)
535 {
536 buf->writeByte(' ');
537 buf->writestring(s->ident->toChars());
538 }
539 buf->writeByte(';');
540 buf->writenl();
541 }
542
543 void visit(ContinueStatement *s)
544 {
545 buf->writestring("continue");
546 if (s->ident)
547 {
548 buf->writeByte(' ');
549 buf->writestring(s->ident->toChars());
550 }
551 buf->writeByte(';');
552 buf->writenl();
553 }
554
555 void visit(SynchronizedStatement *s)
556 {
557 buf->writestring("synchronized");
558 if (s->exp)
559 {
560 buf->writeByte('(');
561 s->exp->accept(this);
562 buf->writeByte(')');
563 }
564 if (s->_body)
565 {
566 buf->writeByte(' ');
567 s->_body->accept(this);
568 }
569 }
570
571 void visit(WithStatement *s)
572 {
573 buf->writestring("with (");
574 s->exp->accept(this);
575 buf->writestring(")");
576 buf->writenl();
577 if (s->_body)
578 s->_body->accept(this);
579 }
580
581 void visit(TryCatchStatement *s)
582 {
583 buf->writestring("try");
584 buf->writenl();
585 if (s->_body)
586 s->_body->accept(this);
587 for (size_t i = 0; i < s->catches->length; i++)
588 {
589 Catch *c = (*s->catches)[i];
590 visit(c);
591 }
592 }
593
594 void visit(TryFinallyStatement *s)
595 {
596 buf->writestring("try");
597 buf->writenl();
598 buf->writeByte('{');
599 buf->writenl();
600 buf->level++;
601 s->_body->accept(this);
602 buf->level--;
603 buf->writeByte('}');
604 buf->writenl();
605 buf->writestring("finally");
606 buf->writenl();
607 if (s->finalbody->isScopeStatement())
608 {
609 s->finalbody->accept(this);
610 }
611 else
612 {
613 buf->level++;
614 s->finalbody->accept(this);
615 buf->level--;
616 }
617 buf->writeByte('}');
618 buf->writenl();
619 }
620
621 void visit(OnScopeStatement *s)
622 {
623 buf->writestring(Token::toChars(s->tok));
624 buf->writeByte(' ');
625 s->statement->accept(this);
626 }
627
628 void visit(ThrowStatement *s)
629 {
630 buf->printf("throw ");
631 s->exp->accept(this);
632 buf->writeByte(';');
633 buf->writenl();
634 }
635
636 void visit(DebugStatement *s)
637 {
638 if (s->statement)
639 {
640 s->statement->accept(this);
641 }
642 }
643
644 void visit(GotoStatement *s)
645 {
646 buf->writestring("goto ");
647 buf->writestring(s->ident->toChars());
648 buf->writeByte(';');
649 buf->writenl();
650 }
651
652 void visit(LabelStatement *s)
653 {
654 buf->writestring(s->ident->toChars());
655 buf->writeByte(':');
656 buf->writenl();
657 if (s->statement)
658 s->statement->accept(this);
659 }
660
661 void visit(AsmStatement *s)
662 {
663 buf->writestring("asm { ");
664 Token *t = s->tokens;
665 buf->level++;
666 while (t)
667 {
668 buf->writestring(t->toChars());
669 if (t->next &&
670 t->value != TOKmin &&
671 t->value != TOKcomma && t->next->value != TOKcomma &&
672 t->value != TOKlbracket && t->next->value != TOKlbracket &&
673 t->next->value != TOKrbracket &&
674 t->value != TOKlparen && t->next->value != TOKlparen &&
675 t->next->value != TOKrparen &&
676 t->value != TOKdot && t->next->value != TOKdot)
677 {
678 buf->writeByte(' ');
679 }
680 t = t->next;
681 }
682 buf->level--;
683 buf->writestring("; }");
684 buf->writenl();
685 }
686
687 void visit(ImportStatement *s)
688 {
689 for (size_t i = 0; i < s->imports->length; i++)
690 {
691 Dsymbol *imp = (*s->imports)[i];
692 imp->accept(this);
693 }
694 }
695
696 void visit(Catch *c)
697 {
698 buf->writestring("catch");
699 if (c->type)
700 {
701 buf->writeByte('(');
702 typeToBuffer(c->type, c->ident);
703 buf->writeByte(')');
704 }
705 buf->writenl();
706 buf->writeByte('{');
707 buf->writenl();
708 buf->level++;
709 if (c->handler)
710 c->handler->accept(this);
711 buf->level--;
712 buf->writeByte('}');
713 buf->writenl();
714 }
715
716 ////////////////////////////////////////////////////////////////////////////
717
718 /**************************************************
719 * An entry point to pretty-print type.
720 */
721 void typeToBuffer(Type *t, Identifier *ident)
722 {
723 if (t->ty == Tfunction)
724 {
725 visitFuncIdentWithPrefix((TypeFunction *)t, ident, NULL);
726 return;
727 }
728
729 visitWithMask(t, 0);
730
731 if (ident)
732 {
733 buf->writeByte(' ');
734 buf->writestring(ident->toChars());
735 }
736 }
737
738 void visitWithMask(Type *t, unsigned char modMask)
739 {
740 // Tuples and functions don't use the type constructor syntax
741 if (modMask == t->mod ||
742 t->ty == Tfunction ||
743 t->ty == Ttuple)
744 {
745 t->accept(this);
746 }
747 else
748 {
749 unsigned char m = t->mod & ~(t->mod & modMask);
750 if (m & MODshared)
751 {
752 MODtoBuffer(buf, MODshared);
753 buf->writeByte('(');
754 }
755 if (m & MODwild)
756 {
757 MODtoBuffer(buf, MODwild);
758 buf->writeByte('(');
759 }
760 if (m & (MODconst | MODimmutable))
761 {
762 MODtoBuffer(buf, m & (MODconst | MODimmutable));
763 buf->writeByte('(');
764 }
765
766 t->accept(this);
767
768 if (m & (MODconst | MODimmutable))
769 buf->writeByte(')');
770 if (m & MODwild)
771 buf->writeByte(')');
772 if (m & MODshared)
773 buf->writeByte(')');
774 }
775 }
776
777 void visit(Type *t)
778 {
779 printf("t = %p, ty = %d\n", t, t->ty);
780 assert(0);
781 }
782
783 void visit(TypeError *)
784 {
785 buf->writestring("_error_");
786 }
787
788 void visit(TypeBasic *t)
789 {
790 //printf("TypeBasic::toCBuffer2(t->mod = %d)\n", t->mod);
791 buf->writestring(t->dstring);
792 }
793
794 void visit(TypeTraits *t)
795 {
796 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
797 t->exp->accept(this);
798 }
799
800 void visit(TypeVector *t)
801 {
802 //printf("TypeVector::toCBuffer2(t->mod = %d)\n", t->mod);
803 buf->writestring("__vector(");
804 visitWithMask(t->basetype, t->mod);
805 buf->writestring(")");
806 }
807
808 void visit(TypeSArray *t)
809 {
810 visitWithMask(t->next, t->mod);
811 buf->writeByte('[');
812 sizeToBuffer(t->dim);
813 buf->writeByte(']');
814 }
815
816 void visit(TypeDArray *t)
817 {
818 Type *ut = t->castMod(0);
819 if (declstring)
820 goto L1;
821 if (ut->equals(Type::tstring))
822 buf->writestring("string");
823 else if (ut->equals(Type::twstring))
824 buf->writestring("wstring");
825 else if (ut->equals(Type::tdstring))
826 buf->writestring("dstring");
827 else
828 {
829 L1:
830 visitWithMask(t->next, t->mod);
831 buf->writestring("[]");
832 }
833 }
834
835 void visit(TypeAArray *t)
836 {
837 visitWithMask(t->next, t->mod);
838 buf->writeByte('[');
839 visitWithMask(t->index, 0);
840 buf->writeByte(']');
841 }
842
843 void visit(TypePointer *t)
844 {
845 //printf("TypePointer::toCBuffer2() next = %d\n", t->next->ty);
846 if (t->next->ty == Tfunction)
847 visitFuncIdentWithPostfix((TypeFunction *)t->next, "function");
848 else
849 {
850 visitWithMask(t->next, t->mod);
851 buf->writeByte('*');
852 }
853 }
854
855 void visit(TypeReference *t)
856 {
857 visitWithMask(t->next, t->mod);
858 buf->writeByte('&');
859 }
860
861 void visit(TypeFunction *t)
862 {
863 //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t->isref);
864 visitFuncIdentWithPostfix(t, NULL);
865 }
866
867 // callback for TypeFunction::attributesApply
868 struct PrePostAppendStrings
869 {
870 OutBuffer *buf;
871 bool isPostfixStyle;
872 bool isCtor;
873
874 static int fp(void *param, const char *str)
875 {
876 PrePostAppendStrings *p = (PrePostAppendStrings *)param;
877
878 // don't write 'ref' for ctors
879 if (p->isCtor && strcmp(str, "ref") == 0)
880 return 0;
881
882 if ( p->isPostfixStyle) p->buf->writeByte(' ');
883 p->buf->writestring(str);
884 if (!p->isPostfixStyle) p->buf->writeByte(' ');
885 return 0;
886 }
887 };
888
889 void visitFuncIdentWithPostfix(TypeFunction *t, const char *ident)
890 {
891 if (t->inuse)
892 {
893 t->inuse = 2; // flag error to caller
894 return;
895 }
896 t->inuse++;
897
898 PrePostAppendStrings pas;
899 pas.buf = buf;
900 pas.isCtor = false;
901 pas.isPostfixStyle = true;
902
903 if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen)
904 {
905 linkageToBuffer(buf, t->linkage);
906 buf->writeByte(' ');
907 }
908
909 if (t->next)
910 {
911 typeToBuffer(t->next, NULL);
912 if (ident)
913 buf->writeByte(' ');
914 }
915 else if (hgs->ddoc)
916 buf->writestring("auto ");
917
918 if (ident)
919 buf->writestring(ident);
920
921 parametersToBuffer(t->parameterList.parameters, t->parameterList.varargs);
922
923 /* Use postfix style for attributes
924 */
925 if (t->mod)
926 {
927 buf->writeByte(' ');
928 MODtoBuffer(buf, t->mod);
929 }
930 t->attributesApply(&pas, &PrePostAppendStrings::fp);
931
932 t->inuse--;
933 }
934 void visitFuncIdentWithPrefix(TypeFunction *t, Identifier *ident, TemplateDeclaration *td)
935 {
936 if (t->inuse)
937 {
938 t->inuse = 2; // flag error to caller
939 return;
940 }
941 t->inuse++;
942
943 PrePostAppendStrings pas;
944 pas.buf = buf;
945 pas.isCtor = (ident == Id::ctor);
946 pas.isPostfixStyle = false;
947
948 /* Use 'storage class' (prefix) style for attributes
949 */
950 if (t->mod)
951 {
952 MODtoBuffer(buf, t->mod);
953 buf->writeByte(' ');
954 }
955 t->attributesApply(&pas, &PrePostAppendStrings::fp);
956
957 if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen)
958 {
959 linkageToBuffer(buf, t->linkage);
960 buf->writeByte(' ');
961 }
962
963 if (ident && ident->toHChars2() != ident->toChars())
964 {
965 // Don't print return type for ctor, dtor, unittest, etc
966 }
967 else if (t->next)
968 {
969 typeToBuffer(t->next, NULL);
970 if (ident)
971 buf->writeByte(' ');
972 }
973 else if (hgs->ddoc)
974 buf->writestring("auto ");
975
976 if (ident)
977 buf->writestring(ident->toHChars2());
978
979 if (td)
980 {
981 buf->writeByte('(');
982 for (size_t i = 0; i < td->origParameters->length; i++)
983 {
984 TemplateParameter *p = (*td->origParameters)[i];
985 if (i)
986 buf->writestring(", ");
987 p->accept(this);
988 }
989 buf->writeByte(')');
990 }
991 parametersToBuffer(t->parameterList.parameters, t->parameterList.varargs);
992
993 t->inuse--;
994 }
995
996 void visit(TypeDelegate *t)
997 {
998 visitFuncIdentWithPostfix((TypeFunction *)t->next, "delegate");
999 }
1000
1001 void visitTypeQualifiedHelper(TypeQualified *t)
1002 {
1003 for (size_t i = 0; i < t->idents.length; i++)
1004 {
1005 RootObject *id = t->idents[i];
1006
1007 if (id->dyncast() == DYNCAST_DSYMBOL)
1008 {
1009 buf->writeByte('.');
1010 TemplateInstance *ti = (TemplateInstance *)id;
1011 ti->accept(this);
1012 }
1013 else if (id->dyncast() == DYNCAST_EXPRESSION)
1014 {
1015 buf->writeByte('[');
1016 ((Expression *)id)->accept(this);
1017 buf->writeByte(']');
1018 }
1019 else if (id->dyncast() == DYNCAST_TYPE)
1020 {
1021 buf->writeByte('[');
1022 ((Type *)id)->accept(this);
1023 buf->writeByte(']');
1024 }
1025 else
1026 {
1027 buf->writeByte('.');
1028 buf->writestring(id->toChars());
1029 }
1030 }
1031 }
1032
1033 void visit(TypeIdentifier *t)
1034 {
1035 buf->writestring(t->ident->toChars());
1036 visitTypeQualifiedHelper(t);
1037 }
1038
1039 void visit(TypeInstance *t)
1040 {
1041 t->tempinst->accept(this);
1042 visitTypeQualifiedHelper(t);
1043 }
1044
1045 void visit(TypeTypeof *t)
1046 {
1047 buf->writestring("typeof(");
1048 t->exp->accept(this);
1049 buf->writeByte(')');
1050 visitTypeQualifiedHelper(t);
1051 }
1052
1053 void visit(TypeReturn *t)
1054 {
1055 buf->writestring("typeof(return)");
1056 visitTypeQualifiedHelper(t);
1057 }
1058
1059 void visit(TypeEnum *t)
1060 {
1061 buf->writestring(t->sym->toChars());
1062 }
1063
1064 void visit(TypeStruct *t)
1065 {
1066 // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error
1067 // while printing messages.
1068 TemplateInstance *ti = t->sym->parent ? t->sym->parent->isTemplateInstance() : NULL;
1069 if (ti && ti->aliasdecl == t->sym)
1070 buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars());
1071 else
1072 buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars());
1073 }
1074
1075 void visit(TypeClass *t)
1076 {
1077 // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error
1078 // while printing messages.
1079 TemplateInstance *ti = t->sym->parent->isTemplateInstance();
1080 if (ti && ti->aliasdecl == t->sym)
1081 buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars());
1082 else
1083 buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars());
1084 }
1085
1086 void visit(TypeTuple *t)
1087 {
1088 parametersToBuffer(t->arguments, 0);
1089 }
1090
1091 void visit(TypeSlice *t)
1092 {
1093 visitWithMask(t->next, t->mod);
1094
1095 buf->writeByte('[');
1096 sizeToBuffer(t->lwr);
1097 buf->writestring(" .. ");
1098 sizeToBuffer(t->upr);
1099 buf->writeByte(']');
1100 }
1101
1102 void visit(TypeNull *)
1103 {
1104 buf->writestring("typeof(null)");
1105 }
1106
1107 ////////////////////////////////////////////////////////////////////////////
1108
1109 void visit(Dsymbol *s)
1110 {
1111 buf->writestring(s->toChars());
1112 }
1113
1114 void visit(StaticAssert *s)
1115 {
1116 buf->writestring(s->kind());
1117 buf->writeByte('(');
1118 s->exp->accept(this);
1119 if (s->msg)
1120 {
1121 buf->writestring(", ");
1122 s->msg->accept(this);
1123 }
1124 buf->writestring(");");
1125 buf->writenl();
1126 }
1127
1128 void visit(DebugSymbol *s)
1129 {
1130 buf->writestring("debug = ");
1131 if (s->ident)
1132 buf->writestring(s->ident->toChars());
1133 else
1134 buf->printf("%u", s->level);
1135 buf->writestring(";");
1136 buf->writenl();
1137 }
1138
1139 void visit(VersionSymbol *s)
1140 {
1141 buf->writestring("version = ");
1142 if (s->ident)
1143 buf->writestring(s->ident->toChars());
1144 else
1145 buf->printf("%u", s->level);
1146 buf->writestring(";");
1147 buf->writenl();
1148 }
1149
1150 void visit(EnumMember *em)
1151 {
1152 if (em->type)
1153 typeToBuffer(em->type, em->ident);
1154 else
1155 buf->writestring(em->ident->toChars());
1156 if (em->value())
1157 {
1158 buf->writestring(" = ");
1159 em->value()->accept(this);
1160 }
1161 }
1162
1163 void visit(Import *imp)
1164 {
1165 if (hgs->hdrgen && imp->id == Id::object)
1166 return; // object is imported by default
1167
1168 if (imp->isstatic)
1169 buf->writestring("static ");
1170 buf->writestring("import ");
1171 if (imp->aliasId)
1172 {
1173 buf->printf("%s = ", imp->aliasId->toChars());
1174 }
1175 if (imp->packages && imp->packages->length)
1176 {
1177 for (size_t i = 0; i < imp->packages->length; i++)
1178 {
1179 Identifier *pid = (*imp->packages)[i];
1180 buf->printf("%s.", pid->toChars());
1181 }
1182 }
1183 buf->printf("%s", imp->id->toChars());
1184 if (imp->names.length)
1185 {
1186 buf->writestring(" : ");
1187 for (size_t i = 0; i < imp->names.length; i++)
1188 {
1189 if (i)
1190 buf->writestring(", ");
1191
1192 Identifier *name = imp->names[i];
1193 Identifier *alias = imp->aliases[i];
1194 if (alias)
1195 buf->printf("%s = %s", alias->toChars(), name->toChars());
1196 else
1197 buf->printf("%s", name->toChars());
1198 }
1199 }
1200 buf->printf(";");
1201 buf->writenl();
1202 }
1203
1204 void visit(AliasThis *d)
1205 {
1206 buf->writestring("alias ");
1207 buf->writestring(d->ident->toChars());
1208 buf->writestring(" this;\n");
1209 }
1210
1211 void visit(AttribDeclaration *d)
1212 {
1213 if (!d->decl)
1214 {
1215 buf->writeByte(';');
1216 buf->writenl();
1217 return;
1218 }
1219
1220 if (d->decl->length == 0)
1221 buf->writestring("{}");
1222 else if (hgs->hdrgen && d->decl->length == 1 && (*d->decl)[0]->isUnitTestDeclaration())
1223 {
1224 // hack for bugzilla 8081
1225 buf->writestring("{}");
1226 }
1227 else if (d->decl->length == 1)
1228 {
1229 ((*d->decl)[0])->accept(this);
1230 return;
1231 }
1232 else
1233 {
1234 buf->writenl();
1235 buf->writeByte('{');
1236 buf->writenl();
1237 buf->level++;
1238 for (size_t i = 0; i < d->decl->length; i++)
1239 {
1240 Dsymbol *de = (*d->decl)[i];
1241 de->accept(this);
1242 }
1243 buf->level--;
1244 buf->writeByte('}');
1245 }
1246 buf->writenl();
1247 }
1248
1249 void visit(StorageClassDeclaration *d)
1250 {
1251 if (stcToBuffer(buf, d->stc))
1252 buf->writeByte(' ');
1253 visit((AttribDeclaration *)d);
1254 }
1255
1256 void visit(DeprecatedDeclaration *d)
1257 {
1258 buf->writestring("deprecated(");
1259 d->msg->accept(this);
1260 buf->writestring(") ");
1261 visit((AttribDeclaration *)d);
1262 }
1263
1264 void visit(LinkDeclaration *d)
1265 {
1266 const char *p;
1267
1268 switch (d->linkage)
1269 {
1270 case LINKd: p = "D"; break;
1271 case LINKc: p = "C"; break;
1272 case LINKcpp: p = "C++"; break;
1273 case LINKwindows: p = "Windows"; break;
1274 case LINKpascal: p = "Pascal"; break;
1275 case LINKobjc: p = "Objective-C"; break;
1276 default:
1277 assert(0);
1278 break;
1279 }
1280 buf->writestring("extern (");
1281 buf->writestring(p);
1282 buf->writestring(") ");
1283 visit((AttribDeclaration *)d);
1284 }
1285
1286 void visit(CPPMangleDeclaration *d)
1287 {
1288 const char *p;
1289
1290 switch (d->cppmangle)
1291 {
1292 case CPPMANGLEclass: p = "class"; break;
1293 case CPPMANGLEstruct: p = "struct"; break;
1294 default:
1295 assert(0);
1296 break;
1297 }
1298 buf->writestring("extern (C++, ");
1299 buf->writestring(p);
1300 buf->writestring(") ");
1301 visit((AttribDeclaration *)d);
1302 }
1303
1304 void visit(ProtDeclaration *d)
1305 {
1306 protectionToBuffer(buf, d->protection);
1307 buf->writeByte(' ');
1308 visit((AttribDeclaration *)d);
1309 }
1310
1311 void visit(AlignDeclaration *d)
1312 {
1313 if (!d->ealign)
1314 buf->printf("align ");
1315 else
1316 buf->printf("align (%s)", d->ealign->toChars());
1317 visit((AttribDeclaration *)d);
1318 }
1319
1320 void visit(AnonDeclaration *d)
1321 {
1322 buf->printf(d->isunion ? "union" : "struct");
1323 buf->writenl();
1324 buf->writestring("{");
1325 buf->writenl();
1326 buf->level++;
1327 if (d->decl)
1328 {
1329 for (size_t i = 0; i < d->decl->length; i++)
1330 {
1331 Dsymbol *de = (*d->decl)[i];
1332 de->accept(this);
1333 }
1334 }
1335 buf->level--;
1336 buf->writestring("}");
1337 buf->writenl();
1338 }
1339
1340 void visit(PragmaDeclaration *d)
1341 {
1342 buf->printf("pragma (%s", d->ident->toChars());
1343 if (d->args && d->args->length)
1344 {
1345 buf->writestring(", ");
1346 argsToBuffer(d->args);
1347 }
1348 buf->writeByte(')');
1349 visit((AttribDeclaration *)d);
1350 }
1351
1352 void visit(ConditionalDeclaration *d)
1353 {
1354 d->condition->accept(this);
1355 if (d->decl || d->elsedecl)
1356 {
1357 buf->writenl();
1358 buf->writeByte('{');
1359 buf->writenl();
1360 buf->level++;
1361 if (d->decl)
1362 {
1363 for (size_t i = 0; i < d->decl->length; i++)
1364 {
1365 Dsymbol *de = (*d->decl)[i];
1366 de->accept(this);
1367 }
1368 }
1369 buf->level--;
1370 buf->writeByte('}');
1371 if (d->elsedecl)
1372 {
1373 buf->writenl();
1374 buf->writestring("else");
1375 buf->writenl();
1376 buf->writeByte('{');
1377 buf->writenl();
1378 buf->level++;
1379 for (size_t i = 0; i < d->elsedecl->length; i++)
1380 {
1381 Dsymbol *de = (*d->elsedecl)[i];
1382 de->accept(this);
1383 }
1384 buf->level--;
1385 buf->writeByte('}');
1386 }
1387 }
1388 else
1389 buf->writeByte(':');
1390 buf->writenl();
1391 }
1392
1393 void visit(ForwardingStatement *s)
1394 {
1395 s->statement->accept(this);
1396 }
1397
1398 void visit(StaticForeachDeclaration *s)
1399 {
1400 buf->writestring("static ");
1401 if (s->sfe->aggrfe)
1402 {
1403 foreachWithoutBody(s->sfe->aggrfe);
1404 }
1405 else
1406 {
1407 assert(s->sfe->rangefe);
1408 foreachRangeWithoutBody(s->sfe->rangefe);
1409 }
1410 buf->writeByte('{');
1411 buf->writenl();
1412 buf->level++;
1413 visit((AttribDeclaration *)s);
1414 buf->level--;
1415 buf->writeByte('}');
1416 buf->writenl();
1417 }
1418
1419 void visit(CompileDeclaration *d)
1420 {
1421 buf->writestring("mixin(");
1422 d->exp->accept(this);
1423 buf->writestring(");");
1424 buf->writenl();
1425 }
1426
1427 void visit(UserAttributeDeclaration *d)
1428 {
1429 buf->writestring("@(");
1430 argsToBuffer(d->atts);
1431 buf->writeByte(')');
1432 visit((AttribDeclaration *)d);
1433 }
1434
1435 void visit(TemplateDeclaration *d)
1436 {
1437 if ((hgs->hdrgen || hgs->fullDump) && visitEponymousMember(d))
1438 return;
1439
1440 if (hgs->ddoc)
1441 buf->writestring(d->kind());
1442 else
1443 buf->writestring("template");
1444 buf->writeByte(' ');
1445 buf->writestring(d->ident->toChars());
1446 buf->writeByte('(');
1447 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1448 buf->writeByte(')');
1449 visitTemplateConstraint(d->constraint);
1450
1451 if (hgs->hdrgen || hgs->fullDump)
1452 {
1453 hgs->tpltMember++;
1454 buf->writenl();
1455 buf->writeByte('{');
1456 buf->writenl();
1457 buf->level++;
1458 for (size_t i = 0; i < d->members->length; i++)
1459 {
1460 Dsymbol *s = (*d->members)[i];
1461 s->accept(this);
1462 }
1463 buf->level--;
1464 buf->writeByte('}');
1465 buf->writenl();
1466 hgs->tpltMember--;
1467 }
1468 }
1469
1470 bool visitEponymousMember(TemplateDeclaration *d)
1471 {
1472 if (!d->members || d->members->length != 1)
1473 return false;
1474
1475 Dsymbol *onemember = (*d->members)[0];
1476 if (onemember->ident != d->ident)
1477 return false;
1478
1479 if (FuncDeclaration *fd = onemember->isFuncDeclaration())
1480 {
1481 assert(fd->type);
1482 if (stcToBuffer(buf, fd->storage_class))
1483 buf->writeByte(' ');
1484 functionToBufferFull((TypeFunction *)fd->type, buf, d->ident, hgs, d);
1485 visitTemplateConstraint(d->constraint);
1486
1487 hgs->tpltMember++;
1488 bodyToBuffer(fd);
1489 hgs->tpltMember--;
1490 return true;
1491 }
1492 if (AggregateDeclaration *ad = onemember->isAggregateDeclaration())
1493 {
1494 buf->writestring(ad->kind());
1495 buf->writeByte(' ');
1496 buf->writestring(ad->ident->toChars());
1497 buf->writeByte('(');
1498 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1499 buf->writeByte(')');
1500 visitTemplateConstraint(d->constraint);
1501 visitBaseClasses(ad->isClassDeclaration());
1502
1503 hgs->tpltMember++;
1504 if (ad->members)
1505 {
1506 buf->writenl();
1507 buf->writeByte('{');
1508 buf->writenl();
1509 buf->level++;
1510 for (size_t i = 0; i < ad->members->length; i++)
1511 {
1512 Dsymbol *s = (*ad->members)[i];
1513 s->accept(this);
1514 }
1515 buf->level--;
1516 buf->writeByte('}');
1517 }
1518 else
1519 buf->writeByte(';');
1520 buf->writenl();
1521 hgs->tpltMember--;
1522 return true;
1523 }
1524 if (VarDeclaration *vd = onemember->isVarDeclaration())
1525 {
1526 if (d->constraint)
1527 return false;
1528
1529 if (stcToBuffer(buf, vd->storage_class))
1530 buf->writeByte(' ');
1531 if (vd->type)
1532 typeToBuffer(vd->type, vd->ident);
1533 else
1534 buf->writestring(vd->ident->toChars());
1535
1536 buf->writeByte('(');
1537 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1538 buf->writeByte(')');
1539
1540 if (vd->_init)
1541 {
1542 buf->writestring(" = ");
1543 ExpInitializer *ie = vd->_init->isExpInitializer();
1544 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
1545 ((AssignExp *)ie->exp)->e2->accept(this);
1546 else
1547 vd->_init->accept(this);
1548 }
1549 buf->writeByte(';');
1550 buf->writenl();
1551 return true;
1552 }
1553
1554 return false;
1555 }
1556 void visitTemplateParameters(TemplateParameters *parameters)
1557 {
1558 if (!parameters || !parameters->length)
1559 return;
1560 for (size_t i = 0; i < parameters->length; i++)
1561 {
1562 TemplateParameter *p = (*parameters)[i];
1563 if (i)
1564 buf->writestring(", ");
1565 p->accept(this);
1566 }
1567 }
1568 void visitTemplateConstraint(Expression *constraint)
1569 {
1570 if (!constraint)
1571 return;
1572 buf->writestring(" if (");
1573 constraint->accept(this);
1574 buf->writeByte(')');
1575 }
1576
1577 void visit(TemplateInstance *ti)
1578 {
1579 buf->writestring(ti->name->toChars());
1580 tiargsToBuffer(ti);
1581
1582 if (hgs->fullDump)
1583 {
1584 buf->writenl();
1585 if (ti->aliasdecl)
1586 {
1587 // the ti.aliasDecl is the instantiated body
1588 // if we have it, print it.
1589 ti->aliasdecl->accept(this);
1590 }
1591 }
1592 }
1593
1594 void visit(TemplateMixin *tm)
1595 {
1596 buf->writestring("mixin ");
1597
1598 typeToBuffer(tm->tqual, NULL);
1599 tiargsToBuffer(tm);
1600
1601 if (tm->ident && memcmp(tm->ident->toChars(), "__mixin", 7) != 0)
1602 {
1603 buf->writeByte(' ');
1604 buf->writestring(tm->ident->toChars());
1605 }
1606 buf->writeByte(';');
1607 buf->writenl();
1608 }
1609
1610 void tiargsToBuffer(TemplateInstance *ti)
1611 {
1612 buf->writeByte('!');
1613 if (ti->nest)
1614 {
1615 buf->writestring("(...)");
1616 return;
1617 }
1618 if (!ti->tiargs)
1619 {
1620 buf->writestring("()");
1621 return;
1622 }
1623
1624 if (ti->tiargs->length == 1)
1625 {
1626 RootObject *oarg = (*ti->tiargs)[0];
1627 if (Type *t = isType(oarg))
1628 {
1629 if (t->equals(Type::tstring) ||
1630 t->equals(Type::twstring) ||
1631 t->equals(Type::tdstring) ||
1632 (t->mod == 0 &&
1633 (t->isTypeBasic() ||
1634 (t->ty == Tident && ((TypeIdentifier *)t)->idents.length == 0))))
1635 {
1636 buf->writestring(t->toChars());
1637 return;
1638 }
1639 }
1640 else if (Expression *e = isExpression(oarg))
1641 {
1642 if (e->op == TOKint64 ||
1643 e->op == TOKfloat64 ||
1644 e->op == TOKnull ||
1645 e->op == TOKstring ||
1646 e->op == TOKthis)
1647 {
1648 buf->writestring(e->toChars());
1649 return;
1650 }
1651 }
1652 }
1653 buf->writeByte('(');
1654 ti->nest++;
1655 for (size_t i = 0; i < ti->tiargs->length; i++)
1656 {
1657 RootObject *arg = (*ti->tiargs)[i];
1658 if (i)
1659 buf->writestring(", ");
1660 objectToBuffer(arg);
1661 }
1662 ti->nest--;
1663 buf->writeByte(')');
1664 }
1665
1666 /****************************************
1667 * This makes a 'pretty' version of the template arguments.
1668 * It's analogous to genIdent() which makes a mangled version.
1669 */
1670 void objectToBuffer(RootObject *oarg)
1671 {
1672 //printf("objectToBuffer()\n");
1673
1674 /* The logic of this should match what genIdent() does. The _dynamic_cast()
1675 * function relies on all the pretty strings to be unique for different classes
1676 * (see Bugzilla 7375).
1677 * Perhaps it would be better to demangle what genIdent() does.
1678 */
1679 if (Type *t = isType(oarg))
1680 {
1681 //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
1682 typeToBuffer(t, NULL);
1683 }
1684 else if (Expression *e = isExpression(oarg))
1685 {
1686 if (e->op == TOKvar)
1687 e = e->optimize(WANTvalue); // added to fix Bugzilla 7375
1688 e->accept(this);
1689 }
1690 else if (Dsymbol *s = isDsymbol(oarg))
1691 {
1692 const char *p = s->ident ? s->ident->toChars() : s->toChars();
1693 buf->writestring(p);
1694 }
1695 else if (Tuple *v = isTuple(oarg))
1696 {
1697 Objects *args = &v->objects;
1698 for (size_t i = 0; i < args->length; i++)
1699 {
1700 RootObject *arg = (*args)[i];
1701 if (i)
1702 buf->writestring(", ");
1703 objectToBuffer(arg);
1704 }
1705 }
1706 else if (!oarg)
1707 {
1708 buf->writestring("NULL");
1709 }
1710 else
1711 {
1712 assert(0);
1713 }
1714 }
1715
1716 void visit(EnumDeclaration *d)
1717 {
1718 EnumDeclaration *oldInEnumDecl = inEnumDecl;
1719 inEnumDecl = d;
1720 buf->writestring("enum ");
1721 if (d->ident)
1722 {
1723 buf->writestring(d->ident->toChars());
1724 buf->writeByte(' ');
1725 }
1726 if (d->memtype)
1727 {
1728 buf->writestring(": ");
1729 typeToBuffer(d->memtype, NULL);
1730 }
1731 if (!d->members)
1732 {
1733 buf->writeByte(';');
1734 buf->writenl();
1735 inEnumDecl = oldInEnumDecl;
1736 return;
1737 }
1738 buf->writenl();
1739 buf->writeByte('{');
1740 buf->writenl();
1741 buf->level++;
1742 for (size_t i = 0; i < d->members->length; i++)
1743 {
1744 EnumMember *em = (*d->members)[i]->isEnumMember();
1745 if (!em)
1746 continue;
1747 em->accept(this);
1748 buf->writeByte(',');
1749 buf->writenl();
1750 }
1751 buf->level--;
1752 buf->writeByte('}');
1753 buf->writenl();
1754 inEnumDecl = oldInEnumDecl;
1755 }
1756
1757 void visit(Nspace *d)
1758 {
1759 buf->writestring("extern (C++, ");
1760 buf->writestring(d->ident->toChars());
1761 buf->writeByte(')');
1762 buf->writenl();
1763 buf->writeByte('{');
1764 buf->writenl();
1765 buf->level++;
1766 for (size_t i = 0; i < d->members->length; i++)
1767 {
1768 Dsymbol *s = (*d->members)[i];
1769 s->accept(this);
1770 }
1771 buf->level--;
1772 buf->writeByte('}');
1773 buf->writenl();
1774 }
1775
1776 void visit(StructDeclaration *d)
1777 {
1778 buf->printf("%s ", d->kind());
1779 if (!d->isAnonymous())
1780 buf->writestring(d->toChars());
1781 if (!d->members)
1782 {
1783 buf->writeByte(';');
1784 buf->writenl();
1785 return;
1786 }
1787 buf->writenl();
1788 buf->writeByte('{');
1789 buf->writenl();
1790 buf->level++;
1791 for (size_t i = 0; i < d->members->length; i++)
1792 {
1793 Dsymbol *s = (*d->members)[i];
1794 s->accept(this);
1795 }
1796 buf->level--;
1797 buf->writeByte('}');
1798 buf->writenl();
1799 }
1800
1801 void visit(ClassDeclaration *d)
1802 {
1803 if (!d->isAnonymous())
1804 {
1805 buf->writestring(d->kind());
1806 buf->writeByte(' ');
1807 buf->writestring(d->ident->toChars());
1808 }
1809 visitBaseClasses(d);
1810 if (d->members)
1811 {
1812 buf->writenl();
1813 buf->writeByte('{');
1814 buf->writenl();
1815 buf->level++;
1816 for (size_t i = 0; i < d->members->length; i++)
1817 {
1818 Dsymbol *s = (*d->members)[i];
1819 s->accept(this);
1820 }
1821 buf->level--;
1822 buf->writeByte('}');
1823 }
1824 else
1825 buf->writeByte(';');
1826 buf->writenl();
1827 }
1828
1829 void visitBaseClasses(ClassDeclaration *d)
1830 {
1831 if (!d || !d->baseclasses->length)
1832 return;
1833
1834 buf->writestring(" : ");
1835 for (size_t i = 0; i < d->baseclasses->length; i++)
1836 {
1837 if (i)
1838 buf->writestring(", ");
1839 BaseClass *b = (*d->baseclasses)[i];
1840 typeToBuffer(b->type, NULL);
1841 }
1842 }
1843
1844 void visit(AliasDeclaration *d)
1845 {
1846 if (d->storage_class & STClocal)
1847 return;
1848 buf->writestring("alias ");
1849 if (d->aliassym)
1850 {
1851 buf->writestring(d->ident->toChars());
1852 buf->writestring(" = ");
1853 if (stcToBuffer(buf, d->storage_class))
1854 buf->writeByte(' ');
1855 d->aliassym->accept(this);
1856 }
1857 else if (d->type->ty == Tfunction)
1858 {
1859 if (stcToBuffer(buf, d->storage_class))
1860 buf->writeByte(' ');
1861 typeToBuffer(d->type, d->ident);
1862 }
1863 else
1864 {
1865 declstring = (d->ident == Id::string || d->ident == Id::wstring || d->ident == Id::dstring);
1866 buf->writestring(d->ident->toChars());
1867 buf->writestring(" = ");
1868 if (stcToBuffer(buf, d->storage_class))
1869 buf->writeByte(' ');
1870 typeToBuffer(d->type, NULL);
1871 declstring = false;
1872 }
1873 buf->writeByte(';');
1874 buf->writenl();
1875 }
1876
1877 void visit(VarDeclaration *d)
1878 {
1879 if (d->storage_class & STClocal)
1880 return;
1881 visitVarDecl(d, false);
1882 buf->writeByte(';');
1883 buf->writenl();
1884 }
1885 void visitVarDecl(VarDeclaration *v, bool anywritten)
1886 {
1887 if (anywritten)
1888 {
1889 buf->writestring(", ");
1890 buf->writestring(v->ident->toChars());
1891 }
1892 else
1893 {
1894 if (stcToBuffer(buf, v->storage_class))
1895 buf->writeByte(' ');
1896 if (v->type)
1897 typeToBuffer(v->type, v->ident);
1898 else
1899 buf->writestring(v->ident->toChars());
1900 }
1901 if (v->_init)
1902 {
1903 buf->writestring(" = ");
1904 ExpInitializer *ie = v->_init->isExpInitializer();
1905 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
1906 ((AssignExp *)ie->exp)->e2->accept(this);
1907 else
1908 v->_init->accept(this);
1909 }
1910 }
1911
1912 void visit(FuncDeclaration *f)
1913 {
1914 //printf("FuncDeclaration::toCBuffer() '%s'\n", f->toChars());
1915
1916 if (stcToBuffer(buf, f->storage_class))
1917 buf->writeByte(' ');
1918 TypeFunction *tf = (TypeFunction *)f->type;
1919 typeToBuffer(tf, f->ident);
1920 if (hgs->hdrgen)
1921 {
1922 // if the return type is missing (e.g. ref functions or auto)
1923 if (!tf->next || f->storage_class & STCauto)
1924 {
1925 hgs->autoMember++;
1926 bodyToBuffer(f);
1927 hgs->autoMember--;
1928 }
1929 else if (hgs->tpltMember == 0 && global.params.hdrStripPlainFunctions)
1930 {
1931 buf->writeByte(';');
1932 buf->writenl();
1933 }
1934 else
1935 bodyToBuffer(f);
1936 }
1937 else
1938 bodyToBuffer(f);
1939 }
1940
1941 void bodyToBuffer(FuncDeclaration *f)
1942 {
1943 if (!f->fbody || (hgs->hdrgen && global.params.hdrStripPlainFunctions && !hgs->autoMember && !hgs->tpltMember))
1944 {
1945 buf->writeByte(';');
1946 buf->writenl();
1947 return;
1948 }
1949
1950 int savetlpt = hgs->tpltMember;
1951 int saveauto = hgs->autoMember;
1952 hgs->tpltMember = 0;
1953 hgs->autoMember = 0;
1954
1955 buf->writenl();
1956
1957 // in{}
1958 if (f->frequire)
1959 {
1960 buf->writestring("in");
1961 buf->writenl();
1962 f->frequire->accept(this);
1963 }
1964
1965 // out{}
1966 if (f->fensure)
1967 {
1968 buf->writestring("out");
1969 if (f->outId)
1970 {
1971 buf->writeByte('(');
1972 buf->writestring(f->outId->toChars());
1973 buf->writeByte(')');
1974 }
1975 buf->writenl();
1976 f->fensure->accept(this);
1977 }
1978
1979 if (f->frequire || f->fensure)
1980 {
1981 buf->writestring("body");
1982 buf->writenl();
1983 }
1984
1985 buf->writeByte('{');
1986 buf->writenl();
1987 buf->level++;
1988 f->fbody->accept(this);
1989 buf->level--;
1990 buf->writeByte('}');
1991 buf->writenl();
1992
1993 hgs->tpltMember = savetlpt;
1994 hgs->autoMember = saveauto;
1995 }
1996
1997 void visit(FuncLiteralDeclaration *f)
1998 {
1999 if (f->type->ty == Terror)
2000 {
2001 buf->writestring("__error");
2002 return;
2003 }
2004
2005 if (f->tok != TOKreserved)
2006 {
2007 buf->writestring(f->kind());
2008 buf->writeByte(' ');
2009 }
2010
2011 TypeFunction *tf = (TypeFunction *)f->type;
2012 // Don't print tf->mod, tf->trust, and tf->linkage
2013 if (!f->inferRetType && tf->next)
2014 typeToBuffer(tf->next, NULL);
2015 parametersToBuffer(tf->parameterList.parameters, tf->parameterList.varargs);
2016
2017 CompoundStatement *cs = f->fbody->isCompoundStatement();
2018 Statement *s1;
2019 if (f->semanticRun >= PASSsemantic3done && cs)
2020 {
2021 s1 = (*cs->statements)[cs->statements->length - 1];
2022 }
2023 else
2024 s1 = !cs ? f->fbody : NULL;
2025 ReturnStatement *rs = s1 ? s1->isReturnStatement() : NULL;
2026 if (rs && rs->exp)
2027 {
2028 buf->writestring(" => ");
2029 rs->exp->accept(this);
2030 }
2031 else
2032 {
2033 hgs->tpltMember++;
2034 bodyToBuffer(f);
2035 hgs->tpltMember--;
2036 }
2037 }
2038
2039 void visit(PostBlitDeclaration *d)
2040 {
2041 if (stcToBuffer(buf, d->storage_class))
2042 buf->writeByte(' ');
2043 buf->writestring("this(this)");
2044 bodyToBuffer(d);
2045 }
2046
2047 void visit(DtorDeclaration *d)
2048 {
2049 if (d->storage_class & STCtrusted)
2050 buf->writestring("@trusted ");
2051 if (d->storage_class & STCsafe)
2052 buf->writestring("@safe ");
2053 if (d->storage_class & STCnogc)
2054 buf->writestring("@nogc ");
2055 if (d->storage_class & STCdisable)
2056 buf->writestring("@disable ");
2057
2058 buf->writestring("~this()");
2059 bodyToBuffer(d);
2060 }
2061
2062 void visit(StaticCtorDeclaration *d)
2063 {
2064 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2065 buf->writeByte(' ');
2066 if (d->isSharedStaticCtorDeclaration())
2067 buf->writestring("shared ");
2068 buf->writestring("static this()");
2069 if (hgs->hdrgen && !hgs->tpltMember)
2070 {
2071 buf->writeByte(';');
2072 buf->writenl();
2073 }
2074 else
2075 bodyToBuffer(d);
2076 }
2077
2078 void visit(StaticDtorDeclaration *d)
2079 {
2080 if (hgs->hdrgen)
2081 return;
2082 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2083 buf->writeByte(' ');
2084 if (d->isSharedStaticDtorDeclaration())
2085 buf->writestring("shared ");
2086 buf->writestring("static ~this()");
2087 bodyToBuffer(d);
2088 }
2089
2090 void visit(InvariantDeclaration *d)
2091 {
2092 if (hgs->hdrgen)
2093 return;
2094 if (stcToBuffer(buf, d->storage_class))
2095 buf->writeByte(' ');
2096 buf->writestring("invariant");
2097 bodyToBuffer(d);
2098 }
2099
2100 void visit(UnitTestDeclaration *d)
2101 {
2102 if (hgs->hdrgen)
2103 return;
2104 if (stcToBuffer(buf, d->storage_class))
2105 buf->writeByte(' ');
2106 buf->writestring("unittest");
2107 bodyToBuffer(d);
2108 }
2109
2110 void visit(NewDeclaration *d)
2111 {
2112 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2113 buf->writeByte(' ');
2114 buf->writestring("new");
2115 parametersToBuffer(d->parameters, d->varargs);
2116 bodyToBuffer(d);
2117 }
2118
2119 void visit(DeleteDeclaration *d)
2120 {
2121 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2122 buf->writeByte(' ');
2123 buf->writestring("delete");
2124 parametersToBuffer(d->parameters, 0);
2125 bodyToBuffer(d);
2126 }
2127
2128 ////////////////////////////////////////////////////////////////////////////
2129
2130 void visit(ErrorInitializer *)
2131 {
2132 buf->writestring("__error__");
2133 }
2134
2135 void visit(VoidInitializer *)
2136 {
2137 buf->writestring("void");
2138 }
2139
2140 void visit(StructInitializer *si)
2141 {
2142 //printf("StructInitializer::toCBuffer()\n");
2143 buf->writeByte('{');
2144 for (size_t i = 0; i < si->field.length; i++)
2145 {
2146 if (i)
2147 buf->writestring(", ");
2148 if (Identifier *id = si->field[i])
2149 {
2150 buf->writestring(id->toChars());
2151 buf->writeByte(':');
2152 }
2153 if (Initializer *iz = si->value[i])
2154 iz->accept(this);
2155 }
2156 buf->writeByte('}');
2157 }
2158
2159 void visit(ArrayInitializer *ai)
2160 {
2161 buf->writeByte('[');
2162 for (size_t i = 0; i < ai->index.length; i++)
2163 {
2164 if (i)
2165 buf->writestring(", ");
2166 if (Expression *ex = ai->index[i])
2167 {
2168 ex->accept(this);
2169 buf->writeByte(':');
2170 }
2171 if (Initializer *iz = ai->value[i])
2172 iz->accept(this);
2173 }
2174 buf->writeByte(']');
2175 }
2176
2177 void visit(ExpInitializer *ei)
2178 {
2179 ei->exp->accept(this);
2180 }
2181
2182 ////////////////////////////////////////////////////////////////////////////
2183
2184 /**************************************************
2185 * Write out argument list to buf.
2186 */
2187 void argsToBuffer(Expressions *expressions, Expression *basis = NULL)
2188 {
2189 if (!expressions || !expressions->length)
2190 return;
2191
2192 for (size_t i = 0; i < expressions->length; i++)
2193 {
2194 Expression *el = (*expressions)[i];
2195 if (i)
2196 buf->writestring(", ");
2197 if (!el)
2198 el = basis;
2199 if (el)
2200 expToBuffer(el, PREC_assign);
2201 }
2202 }
2203
2204 void sizeToBuffer(Expression *e)
2205 {
2206 if (e->type == Type::tsize_t)
2207 {
2208 Expression *ex = (e->op == TOKcast ? ((CastExp *)e)->e1 : e);
2209 ex = ex->optimize(WANTvalue);
2210
2211 dinteger_t uval = ex->op == TOKint64 ? ex->toInteger() : (dinteger_t)-1;
2212 if ((sinteger_t)uval >= 0)
2213 {
2214 dinteger_t sizemax;
2215 if (target.ptrsize == 8)
2216 sizemax = 0xFFFFFFFFFFFFFFFFULL;
2217 else if (target.ptrsize == 4)
2218 sizemax = 0xFFFFFFFFUL;
2219 else if (target.ptrsize == 2)
2220 sizemax = 0xFFFFUL;
2221 else
2222 assert(0);
2223 if (uval <= sizemax && uval <= 0x7FFFFFFFFFFFFFFFULL)
2224 {
2225 buf->printf("%llu", uval);
2226 return;
2227 }
2228 }
2229 }
2230 expToBuffer(e, PREC_assign);
2231 }
2232
2233 /**************************************************
2234 * Write expression out to buf, but wrap it
2235 * in ( ) if its precedence is less than pr.
2236 */
2237 void expToBuffer(Expression *e, PREC pr)
2238 {
2239 assert(precedence[e->op] != PREC_zero);
2240 assert(pr != PREC_zero);
2241
2242 //if (precedence[e->op] == 0) e->print();
2243 /* Despite precedence, we don't allow a<b<c expressions.
2244 * They must be parenthesized.
2245 */
2246 if (precedence[e->op] < pr ||
2247 (pr == PREC_rel && precedence[e->op] == pr))
2248 {
2249 buf->writeByte('(');
2250 e->accept(this);
2251 buf->writeByte(')');
2252 }
2253 else
2254 e->accept(this);
2255 }
2256
2257 void visit(Expression *e)
2258 {
2259 buf->writestring(Token::toChars(e->op));
2260 }
2261
2262 void visit(IntegerExp *e)
2263 {
2264 dinteger_t v = e->toInteger();
2265
2266 if (e->type)
2267 {
2268 Type *t = e->type;
2269 L1:
2270 switch (t->ty)
2271 {
2272 case Tenum:
2273 {
2274 TypeEnum *te = (TypeEnum *)t;
2275 if (hgs->fullDump)
2276 {
2277 EnumDeclaration *sym = te->sym;
2278 if (inEnumDecl != sym)
2279 {
2280 for (size_t i = 0; i < sym->members->length; i++)
2281 {
2282 EnumMember *em = (EnumMember *)(*sym->members)[i];
2283 if (em->value()->toInteger() == v)
2284 {
2285 buf->printf("%s.%s", sym->toChars(), em->ident->toChars());
2286 return;
2287 }
2288 }
2289 }
2290 }
2291 buf->printf("cast(%s)", te->sym->toChars());
2292 t = te->sym->memtype;
2293 goto L1;
2294 }
2295
2296 case Twchar: // BUG: need to cast(wchar)
2297 case Tdchar: // BUG: need to cast(dchar)
2298 if ((uinteger_t)v > 0xFF)
2299 {
2300 buf->printf("'\\U%08x'", v);
2301 break;
2302 }
2303 /* fall through */
2304 case Tchar:
2305 {
2306 size_t o = buf->offset;
2307 if (v == '\'')
2308 buf->writestring("'\\''");
2309 else if (isprint((int)v) && v != '\\')
2310 buf->printf("'%c'", (int)v);
2311 else
2312 buf->printf("'\\x%02x'", (int)v);
2313 if (hgs->ddoc)
2314 escapeDdocString(buf, o);
2315 break;
2316 }
2317
2318 case Tint8:
2319 buf->writestring("cast(byte)");
2320 goto L2;
2321
2322 case Tint16:
2323 buf->writestring("cast(short)");
2324 goto L2;
2325
2326 case Tint32:
2327 L2:
2328 buf->printf("%d", (int)v);
2329 break;
2330
2331 case Tuns8:
2332 buf->writestring("cast(ubyte)");
2333 goto L3;
2334
2335 case Tuns16:
2336 buf->writestring("cast(ushort)");
2337 goto L3;
2338
2339 case Tuns32:
2340 L3:
2341 buf->printf("%uu", (unsigned)v);
2342 break;
2343
2344 case Tint64:
2345 buf->printf("%lldL", v);
2346 break;
2347
2348 case Tuns64:
2349 L4:
2350 buf->printf("%lluLU", v);
2351 break;
2352
2353 case Tbool:
2354 buf->writestring(v ? "true" : "false");
2355 break;
2356
2357 case Tpointer:
2358 buf->writestring("cast(");
2359 buf->writestring(t->toChars());
2360 buf->writeByte(')');
2361 if (target.ptrsize == 8)
2362 goto L4;
2363 else
2364 goto L3;
2365
2366 default:
2367 /* This can happen if errors, such as
2368 * the type is painted on like in fromConstInitializer().
2369 */
2370 if (!global.errors)
2371 {
2372 assert(0);
2373 }
2374 break;
2375 }
2376 }
2377 else if (v & 0x8000000000000000LL)
2378 buf->printf("0x%llx", v);
2379 else
2380 buf->printf("%lld", v);
2381 }
2382
2383 void visit(ErrorExp *)
2384 {
2385 buf->writestring("__error");
2386 }
2387
2388 void floatToBuffer(Type *type, real_t value)
2389 {
2390 /** sizeof(value)*3 is because each byte of mantissa is max
2391 of 256 (3 characters). The string will be "-M.MMMMe-4932".
2392 (ie, 8 chars more than mantissa). Plus one for trailing \0.
2393 Plus one for rounding. */
2394 const size_t BUFFER_LEN = sizeof(value) * 3 + 8 + 1 + 1;
2395 char buffer[BUFFER_LEN];
2396 memset(buffer, 0, BUFFER_LEN);
2397 CTFloat::sprint(buffer, 'g', value);
2398 assert(strlen(buffer) < BUFFER_LEN);
2399
2400 if (hgs->hdrgen)
2401 {
2402 real_t r = CTFloat::parse(buffer);
2403 if (r != value) // if exact duplication
2404 CTFloat::sprint(buffer, 'a', value);
2405 }
2406 buf->writestring(buffer);
2407
2408 if (type)
2409 {
2410 Type *t = type->toBasetype();
2411 switch (t->ty)
2412 {
2413 case Tfloat32:
2414 case Timaginary32:
2415 case Tcomplex32:
2416 buf->writeByte('F');
2417 break;
2418
2419 case Tfloat80:
2420 case Timaginary80:
2421 case Tcomplex80:
2422 buf->writeByte('L');
2423 break;
2424
2425 default:
2426 break;
2427 }
2428 if (t->isimaginary())
2429 buf->writeByte('i');
2430 }
2431 }
2432
2433 void visit(RealExp *e)
2434 {
2435 floatToBuffer(e->type, e->value);
2436 }
2437
2438 void visit(ComplexExp *e)
2439 {
2440 /* Print as:
2441 * (re+imi)
2442 */
2443 buf->writeByte('(');
2444 floatToBuffer(e->type, creall(e->value));
2445 buf->writeByte('+');
2446 floatToBuffer(e->type, cimagl(e->value));
2447 buf->writestring("i)");
2448 }
2449
2450 void visit(IdentifierExp *e)
2451 {
2452 if (hgs->hdrgen || hgs->ddoc)
2453 buf->writestring(e->ident->toHChars2());
2454 else
2455 buf->writestring(e->ident->toChars());
2456 }
2457
2458 void visit(DsymbolExp *e)
2459 {
2460 buf->writestring(e->s->toChars());
2461 }
2462
2463 void visit(ThisExp *)
2464 {
2465 buf->writestring("this");
2466 }
2467
2468 void visit(SuperExp *)
2469 {
2470 buf->writestring("super");
2471 }
2472
2473 void visit(NullExp *)
2474 {
2475 buf->writestring("null");
2476 }
2477
2478 void visit(StringExp *e)
2479 {
2480 buf->writeByte('"');
2481 size_t o = buf->offset;
2482 for (size_t i = 0; i < e->len; i++)
2483 {
2484 unsigned c = e->charAt(i);
2485 switch (c)
2486 {
2487 case '"':
2488 case '\\':
2489 buf->writeByte('\\');
2490 /* fall through */
2491 default:
2492 if (c <= 0xFF)
2493 {
2494 if (c <= 0x7F && isprint(c))
2495 buf->writeByte(c);
2496 else
2497 buf->printf("\\x%02x", c);
2498 }
2499 else if (c <= 0xFFFF)
2500 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2501 else
2502 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2503 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2504 break;
2505 }
2506 }
2507 if (hgs->ddoc)
2508 escapeDdocString(buf, o);
2509 buf->writeByte('"');
2510 if (e->postfix)
2511 buf->writeByte(e->postfix);
2512 }
2513
2514 void visit(ArrayLiteralExp *e)
2515 {
2516 buf->writeByte('[');
2517 argsToBuffer(e->elements, e->basis);
2518 buf->writeByte(']');
2519 }
2520
2521 void visit(AssocArrayLiteralExp *e)
2522 {
2523 buf->writeByte('[');
2524 for (size_t i = 0; i < e->keys->length; i++)
2525 {
2526 Expression *key = (*e->keys)[i];
2527 Expression *value = (*e->values)[i];
2528
2529 if (i)
2530 buf->writestring(", ");
2531 expToBuffer(key, PREC_assign);
2532 buf->writeByte(':');
2533 expToBuffer(value, PREC_assign);
2534 }
2535 buf->writeByte(']');
2536 }
2537
2538 void visit(StructLiteralExp *e)
2539 {
2540 buf->writestring(e->sd->toChars());
2541 buf->writeByte('(');
2542
2543 // CTFE can generate struct literals that contain an AddrExp pointing
2544 // to themselves, need to avoid infinite recursion:
2545 // struct S { this(int){ this.s = &this; } S* s; }
2546 // const foo = new S(0);
2547 if (e->stageflags & stageToCBuffer)
2548 buf->writestring("<recursion>");
2549 else
2550 {
2551 int old = e->stageflags;
2552 e->stageflags |= stageToCBuffer;
2553 argsToBuffer(e->elements);
2554 e->stageflags = old;
2555 }
2556
2557 buf->writeByte(')');
2558 }
2559
2560 void visit(TypeExp *e)
2561 {
2562 typeToBuffer(e->type, NULL);
2563 }
2564
2565 void visit(ScopeExp *e)
2566 {
2567 if (e->sds->isTemplateInstance())
2568 {
2569 e->sds->accept(this);
2570 }
2571 else if (hgs != NULL && hgs->ddoc)
2572 {
2573 // fixes bug 6491
2574 Module *m = e->sds->isModule();
2575 if (m)
2576 buf->writestring(m->md->toChars());
2577 else
2578 buf->writestring(e->sds->toChars());
2579 }
2580 else
2581 {
2582 buf->writestring(e->sds->kind());
2583 buf->writeByte(' ');
2584 buf->writestring(e->sds->toChars());
2585 }
2586 }
2587
2588 void visit(TemplateExp *e)
2589 {
2590 buf->writestring(e->td->toChars());
2591 }
2592
2593 void visit(NewExp *e)
2594 {
2595 if (e->thisexp)
2596 {
2597 expToBuffer(e->thisexp, PREC_primary);
2598 buf->writeByte('.');
2599 }
2600 buf->writestring("new ");
2601 if (e->newargs && e->newargs->length)
2602 {
2603 buf->writeByte('(');
2604 argsToBuffer(e->newargs);
2605 buf->writeByte(')');
2606 }
2607 typeToBuffer(e->newtype, NULL);
2608 if (e->arguments && e->arguments->length)
2609 {
2610 buf->writeByte('(');
2611 argsToBuffer(e->arguments);
2612 buf->writeByte(')');
2613 }
2614 }
2615
2616 void visit(NewAnonClassExp *e)
2617 {
2618 if (e->thisexp)
2619 {
2620 expToBuffer(e->thisexp, PREC_primary);
2621 buf->writeByte('.');
2622 }
2623 buf->writestring("new");
2624 if (e->newargs && e->newargs->length)
2625 {
2626 buf->writeByte('(');
2627 argsToBuffer(e->newargs);
2628 buf->writeByte(')');
2629 }
2630 buf->writestring(" class ");
2631 if (e->arguments && e->arguments->length)
2632 {
2633 buf->writeByte('(');
2634 argsToBuffer(e->arguments);
2635 buf->writeByte(')');
2636 }
2637 if (e->cd)
2638 e->cd->accept(this);
2639 }
2640
2641 void visit(SymOffExp *e)
2642 {
2643 if (e->offset)
2644 buf->printf("(& %s+%u)", e->var->toChars(), e->offset);
2645 else if (e->var->isTypeInfoDeclaration())
2646 buf->printf("%s", e->var->toChars());
2647 else
2648 buf->printf("& %s", e->var->toChars());
2649 }
2650
2651 void visit(VarExp *e)
2652 {
2653 buf->writestring(e->var->toChars());
2654 }
2655
2656 void visit(OverExp *e)
2657 {
2658 buf->writestring(e->vars->ident->toChars());
2659 }
2660
2661 void visit(TupleExp *e)
2662 {
2663 if (e->e0)
2664 {
2665 buf->writeByte('(');
2666 e->e0->accept(this);
2667 buf->writestring(", tuple(");
2668 argsToBuffer(e->exps);
2669 buf->writestring("))");
2670 }
2671 else
2672 {
2673 buf->writestring("tuple(");
2674 argsToBuffer(e->exps);
2675 buf->writeByte(')');
2676 }
2677 }
2678
2679 void visit(FuncExp *e)
2680 {
2681 e->fd->accept(this);
2682 //buf->writestring(e->fd->toChars());
2683 }
2684
2685 void visit(DeclarationExp *e)
2686 {
2687 /* Normal dmd execution won't reach here - regular variable declarations
2688 * are handled in visit(ExpStatement), so here would be used only when
2689 * we'll directly call Expression::toChars() for debugging.
2690 */
2691 if (VarDeclaration *v = e->declaration->isVarDeclaration())
2692 {
2693 // For debugging use:
2694 // - Avoid printing newline.
2695 // - Intentionally use the format (Type var;)
2696 // which isn't correct as regular D code.
2697 buf->writeByte('(');
2698 visitVarDecl(v, false);
2699 buf->writeByte(';');
2700 buf->writeByte(')');
2701 }
2702 else
2703 e->declaration->accept(this);
2704 }
2705
2706 void visit(TypeidExp *e)
2707 {
2708 buf->writestring("typeid(");
2709 objectToBuffer(e->obj);
2710 buf->writeByte(')');
2711 }
2712
2713 void visit(TraitsExp *e)
2714 {
2715 buf->writestring("__traits(");
2716 if (e->ident)
2717 buf->writestring(e->ident->toChars());
2718 if (e->args)
2719 {
2720 for (size_t i = 0; i < e->args->length; i++)
2721 {
2722 RootObject *arg = (*e->args)[i];
2723 buf->writestring(", ");
2724 objectToBuffer(arg);
2725 }
2726 }
2727 buf->writeByte(')');
2728 }
2729
2730 void visit(HaltExp *)
2731 {
2732 buf->writestring("halt");
2733 }
2734
2735 void visit(IsExp *e)
2736 {
2737 buf->writestring("is(");
2738 typeToBuffer(e->targ, e->id);
2739 if (e->tok2 != TOKreserved)
2740 {
2741 buf->printf(" %s %s", Token::toChars(e->tok), Token::toChars(e->tok2));
2742 }
2743 else if (e->tspec)
2744 {
2745 if (e->tok == TOKcolon)
2746 buf->writestring(" : ");
2747 else
2748 buf->writestring(" == ");
2749 typeToBuffer(e->tspec, NULL);
2750 }
2751 if (e->parameters && e->parameters->length)
2752 {
2753 buf->writestring(", ");
2754 visitTemplateParameters(e->parameters);
2755 }
2756 buf->writeByte(')');
2757 }
2758
2759 void visit(UnaExp *e)
2760 {
2761 buf->writestring(Token::toChars(e->op));
2762 expToBuffer(e->e1, precedence[e->op]);
2763 }
2764
2765 void visit(BinExp *e)
2766 {
2767 expToBuffer(e->e1, precedence[e->op]);
2768 buf->writeByte(' ');
2769 buf->writestring(Token::toChars(e->op));
2770 buf->writeByte(' ');
2771 expToBuffer(e->e2, (PREC)(precedence[e->op] + 1));
2772 }
2773
2774 void visit(CompileExp *e)
2775 {
2776 buf->writestring("mixin(");
2777 expToBuffer(e->e1, PREC_assign);
2778 buf->writeByte(')');
2779 }
2780
2781 void visit(ImportExp *e)
2782 {
2783 buf->writestring("import(");
2784 expToBuffer(e->e1, PREC_assign);
2785 buf->writeByte(')');
2786 }
2787
2788 void visit(AssertExp *e)
2789 {
2790 buf->writestring("assert(");
2791 expToBuffer(e->e1, PREC_assign);
2792 if (e->msg)
2793 {
2794 buf->writestring(", ");
2795 expToBuffer(e->msg, PREC_assign);
2796 }
2797 buf->writeByte(')');
2798 }
2799
2800 void visit(DotIdExp *e)
2801 {
2802 expToBuffer(e->e1, PREC_primary);
2803 buf->writeByte('.');
2804 buf->writestring(e->ident->toChars());
2805 }
2806
2807 void visit(DotTemplateExp *e)
2808 {
2809 expToBuffer(e->e1, PREC_primary);
2810 buf->writeByte('.');
2811 buf->writestring(e->td->toChars());
2812 }
2813
2814 void visit(DotVarExp *e)
2815 {
2816 expToBuffer(e->e1, PREC_primary);
2817 buf->writeByte('.');
2818 buf->writestring(e->var->toChars());
2819 }
2820
2821 void visit(DotTemplateInstanceExp *e)
2822 {
2823 expToBuffer(e->e1, PREC_primary);
2824 buf->writeByte('.');
2825 e->ti->accept(this);
2826 }
2827
2828 void visit(DelegateExp *e)
2829 {
2830 buf->writeByte('&');
2831 if (!e->func->isNested())
2832 {
2833 expToBuffer(e->e1, PREC_primary);
2834 buf->writeByte('.');
2835 }
2836 buf->writestring(e->func->toChars());
2837 }
2838
2839 void visit(DotTypeExp *e)
2840 {
2841 expToBuffer(e->e1, PREC_primary);
2842 buf->writeByte('.');
2843 buf->writestring(e->sym->toChars());
2844 }
2845
2846 void visit(CallExp *e)
2847 {
2848 if (e->e1->op == TOKtype)
2849 {
2850 /* Avoid parens around type to prevent forbidden cast syntax:
2851 * (sometype)(arg1)
2852 * This is ok since types in constructor calls
2853 * can never depend on parens anyway
2854 */
2855 e->e1->accept(this);
2856 }
2857 else
2858 expToBuffer(e->e1, precedence[e->op]);
2859 buf->writeByte('(');
2860 argsToBuffer(e->arguments);
2861 buf->writeByte(')');
2862 }
2863
2864 void visit(PtrExp *e)
2865 {
2866 buf->writeByte('*');
2867 expToBuffer(e->e1, precedence[e->op]);
2868 }
2869
2870 void visit(DeleteExp *e)
2871 {
2872 buf->writestring("delete ");
2873 expToBuffer(e->e1, precedence[e->op]);
2874 }
2875
2876 void visit(CastExp *e)
2877 {
2878 buf->writestring("cast(");
2879 if (e->to)
2880 typeToBuffer(e->to, NULL);
2881 else
2882 {
2883 MODtoBuffer(buf, e->mod);
2884 }
2885 buf->writeByte(')');
2886 expToBuffer(e->e1, precedence[e->op]);
2887 }
2888
2889 void visit(VectorExp *e)
2890 {
2891 buf->writestring("cast(");
2892 typeToBuffer(e->to, NULL);
2893 buf->writeByte(')');
2894 expToBuffer(e->e1, precedence[e->op]);
2895 }
2896
2897 void visit(VectorArrayExp *e)
2898 {
2899 expToBuffer(e->e1, PREC_primary);
2900 buf->writestring(".array");
2901 }
2902
2903 void visit(SliceExp *e)
2904 {
2905 expToBuffer(e->e1, precedence[e->op]);
2906 buf->writeByte('[');
2907 if (e->upr || e->lwr)
2908 {
2909 if (e->lwr)
2910 sizeToBuffer(e->lwr);
2911 else
2912 buf->writeByte('0');
2913 buf->writestring("..");
2914 if (e->upr)
2915 sizeToBuffer(e->upr);
2916 else
2917 buf->writeByte('$');
2918 }
2919 buf->writeByte(']');
2920 }
2921
2922 void visit(ArrayLengthExp *e)
2923 {
2924 expToBuffer(e->e1, PREC_primary);
2925 buf->writestring(".length");
2926 }
2927
2928 void visit(IntervalExp *e)
2929 {
2930 expToBuffer(e->lwr, PREC_assign);
2931 buf->writestring("..");
2932 expToBuffer(e->upr, PREC_assign);
2933 }
2934
2935 void visit(DelegatePtrExp *e)
2936 {
2937 expToBuffer(e->e1, PREC_primary);
2938 buf->writestring(".ptr");
2939 }
2940
2941 void visit(DelegateFuncptrExp *e)
2942 {
2943 expToBuffer(e->e1, PREC_primary);
2944 buf->writestring(".funcptr");
2945 }
2946
2947 void visit(ArrayExp *e)
2948 {
2949 expToBuffer(e->e1, PREC_primary);
2950 buf->writeByte('[');
2951 argsToBuffer(e->arguments);
2952 buf->writeByte(']');
2953 }
2954
2955 void visit(DotExp *e)
2956 {
2957 expToBuffer(e->e1, PREC_primary);
2958 buf->writeByte('.');
2959 expToBuffer(e->e2, PREC_primary);
2960 }
2961
2962 void visit(IndexExp *e)
2963 {
2964 expToBuffer(e->e1, PREC_primary);
2965 buf->writeByte('[');
2966 sizeToBuffer(e->e2);
2967 buf->writeByte(']');
2968 }
2969
2970 void visit(PostExp *e)
2971 {
2972 expToBuffer(e->e1, precedence[e->op]);
2973 buf->writestring(Token::toChars(e->op));
2974 }
2975
2976 void visit(PreExp *e)
2977 {
2978 buf->writestring(Token::toChars(e->op));
2979 expToBuffer(e->e1, precedence[e->op]);
2980 }
2981
2982 void visit(RemoveExp *e)
2983 {
2984 expToBuffer(e->e1, PREC_primary);
2985 buf->writestring(".remove(");
2986 expToBuffer(e->e2, PREC_assign);
2987 buf->writeByte(')');
2988 }
2989
2990 void visit(CondExp *e)
2991 {
2992 expToBuffer(e->econd, PREC_oror);
2993 buf->writestring(" ? ");
2994 expToBuffer(e->e1, PREC_expr);
2995 buf->writestring(" : ");
2996 expToBuffer(e->e2, PREC_cond);
2997 }
2998
2999 void visit(DefaultInitExp *e)
3000 {
3001 buf->writestring(Token::toChars(e->subop));
3002 }
3003
3004 void visit(ClassReferenceExp *e)
3005 {
3006 buf->writestring(e->value->toChars());
3007 }
3008
3009 ////////////////////////////////////////////////////////////////////////////
3010
3011 void visit(TemplateTypeParameter *tp)
3012 {
3013 buf->writestring(tp->ident->toChars());
3014 if (tp->specType)
3015 {
3016 buf->writestring(" : ");
3017 typeToBuffer(tp->specType, NULL);
3018 }
3019 if (tp->defaultType)
3020 {
3021 buf->writestring(" = ");
3022 typeToBuffer(tp->defaultType, NULL);
3023 }
3024 }
3025
3026 void visit(TemplateThisParameter *tp)
3027 {
3028 buf->writestring("this ");
3029 visit((TemplateTypeParameter *)tp);
3030 }
3031
3032 void visit(TemplateAliasParameter *tp)
3033 {
3034 buf->writestring("alias ");
3035 if (tp->specType)
3036 typeToBuffer(tp->specType, tp->ident);
3037 else
3038 buf->writestring(tp->ident->toChars());
3039 if (tp->specAlias)
3040 {
3041 buf->writestring(" : ");
3042 objectToBuffer(tp->specAlias);
3043 }
3044 if (tp->defaultAlias)
3045 {
3046 buf->writestring(" = ");
3047 objectToBuffer(tp->defaultAlias);
3048 }
3049 }
3050
3051 void visit(TemplateValueParameter *tp)
3052 {
3053 typeToBuffer(tp->valType, tp->ident);
3054 if (tp->specValue)
3055 {
3056 buf->writestring(" : ");
3057 tp->specValue->accept(this);
3058 }
3059 if (tp->defaultValue)
3060 {
3061 buf->writestring(" = ");
3062 tp->defaultValue->accept(this);
3063 }
3064 }
3065
3066 void visit(TemplateTupleParameter *tp)
3067 {
3068 buf->writestring(tp->ident->toChars());
3069 buf->writestring("...");
3070 }
3071
3072 ////////////////////////////////////////////////////////////////////////////
3073
3074 void visit(DebugCondition *c)
3075 {
3076 if (c->ident)
3077 buf->printf("debug (%s)", c->ident->toChars());
3078 else
3079 buf->printf("debug (%u)", c->level);
3080 }
3081
3082 void visit(VersionCondition *c)
3083 {
3084 if (c->ident)
3085 buf->printf("version (%s)", c->ident->toChars());
3086 else
3087 buf->printf("version (%u)", c->level);
3088 }
3089
3090 void visit(StaticIfCondition *c)
3091 {
3092 buf->writestring("static if (");
3093 c->exp->accept(this);
3094 buf->writeByte(')');
3095 }
3096
3097 ////////////////////////////////////////////////////////////////////////////
3098
3099 void visit(Parameter *p)
3100 {
3101 if (p->storageClass & STCauto)
3102 buf->writestring("auto ");
3103
3104 if (p->storageClass & STCreturn)
3105 buf->writestring("return ");
3106
3107 if (p->storageClass & STCout)
3108 buf->writestring("out ");
3109 else if (p->storageClass & STCref)
3110 buf->writestring("ref ");
3111 else if (p->storageClass & STCin)
3112 buf->writestring("in ");
3113 else if (p->storageClass & STClazy)
3114 buf->writestring("lazy ");
3115 else if (p->storageClass & STCalias)
3116 buf->writestring("alias ");
3117
3118 StorageClass stc = p->storageClass;
3119 if (p->type && p->type->mod & MODshared)
3120 stc &= ~STCshared;
3121
3122 if (stcToBuffer(buf, stc & (STCconst | STCimmutable | STCwild | STCshared | STCscope | STCscopeinferred)))
3123 buf->writeByte(' ');
3124
3125 if (p->storageClass & STCalias)
3126 {
3127 if (p->ident)
3128 buf->writestring(p->ident->toChars());
3129 }
3130 else if (p->type->ty == Tident &&
3131 strlen(((TypeIdentifier *)p->type)->ident->toChars()) > 3 &&
3132 strncmp(((TypeIdentifier *)p->type)->ident->toChars(), "__T", 3) == 0)
3133 {
3134 // print parameter name, instead of undetermined type parameter
3135 buf->writestring(p->ident->toChars());
3136 }
3137 else
3138 typeToBuffer(p->type, p->ident);
3139 if (p->defaultArg)
3140 {
3141 buf->writestring(" = ");
3142 p->defaultArg->accept(this);
3143 }
3144 }
3145
3146 void parametersToBuffer(Parameters *parameters, int varargs)
3147 {
3148 buf->writeByte('(');
3149 if (parameters)
3150 {
3151 size_t dim = Parameter::dim(parameters);
3152 for (size_t i = 0; i < dim; i++)
3153 {
3154 if (i)
3155 buf->writestring(", ");
3156 Parameter *fparam = Parameter::getNth(parameters, i);
3157 fparam->accept(this);
3158 }
3159 if (varargs)
3160 {
3161 if (parameters->length && varargs == 1)
3162 buf->writestring(", ");
3163 buf->writestring("...");
3164 }
3165 }
3166 buf->writeByte(')');
3167 }
3168
3169 void visit(Module *m)
3170 {
3171 if (m->md)
3172 {
3173 if (m->userAttribDecl)
3174 {
3175 buf->writestring("@(");
3176 argsToBuffer(m->userAttribDecl->atts);
3177 buf->writeByte(')');
3178 buf->writenl();
3179 }
3180 if (m->md->isdeprecated)
3181 {
3182 if (m->md->msg)
3183 {
3184 buf->writestring("deprecated(");
3185 m->md->msg->accept(this);
3186 buf->writestring(") ");
3187 }
3188 else
3189 buf->writestring("deprecated ");
3190 }
3191
3192 buf->writestring("module ");
3193 buf->writestring(m->md->toChars());
3194 buf->writeByte(';');
3195 buf->writenl();
3196 }
3197 for (size_t i = 0; i < m->members->length; i++)
3198 {
3199 Dsymbol *s = (*m->members)[i];
3200 s->accept(this);
3201 }
3202 }
3203 };
3204
3205 void toCBuffer(Statement *s, OutBuffer *buf, HdrGenState *hgs)
3206 {
3207 PrettyPrintVisitor v(buf, hgs);
3208 s->accept(&v);
3209 }
3210
3211 void toCBuffer(Type *t, OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3212 {
3213 PrettyPrintVisitor v(buf, hgs);
3214 v.typeToBuffer(t, ident);
3215 }
3216
3217 void toCBuffer(Dsymbol *s, OutBuffer *buf, HdrGenState *hgs)
3218 {
3219 PrettyPrintVisitor v(buf, hgs);
3220 s->accept(&v);
3221 }
3222
3223 // used from TemplateInstance::toChars() and TemplateMixin::toChars()
3224 void toCBufferInstance(TemplateInstance *ti, OutBuffer *buf, bool qualifyTypes)
3225 {
3226 HdrGenState hgs;
3227 hgs.fullQual = qualifyTypes;
3228 PrettyPrintVisitor v(buf, &hgs);
3229 v.visit(ti);
3230 }
3231
3232 void toCBuffer(Initializer *iz, OutBuffer *buf, HdrGenState *hgs)
3233 {
3234 PrettyPrintVisitor v(buf, hgs);
3235 iz->accept(&v);
3236 }
3237
3238 bool stcToBuffer(OutBuffer *buf, StorageClass stc)
3239 {
3240 bool result = false;
3241 if ((stc & (STCreturn | STCscope)) == (STCreturn | STCscope))
3242 stc &= ~STCscope;
3243 if (stc & STCscopeinferred)
3244 stc &= ~(STCscope | STCscopeinferred);
3245 while (stc)
3246 {
3247 const char *p = stcToChars(stc);
3248 if (!p)
3249 break;
3250 if (!result)
3251 result = true;
3252 else
3253 buf->writeByte(' ');
3254 buf->writestring(p);
3255 }
3256 return result;
3257 }
3258
3259 /*************************************************
3260 * Pick off one of the storage classes from stc,
3261 * and return a pointer to a string representation of it.
3262 * stc is reduced by the one picked.
3263 */
3264 const char *stcToChars(StorageClass& stc)
3265 {
3266 struct SCstring
3267 {
3268 StorageClass stc;
3269 TOK tok;
3270 const char *id;
3271 };
3272
3273 static SCstring table[] =
3274 {
3275 { STCauto, TOKauto, NULL },
3276 { STCscope, TOKscope, NULL },
3277 { STCstatic, TOKstatic, NULL },
3278 { STCextern, TOKextern, NULL },
3279 { STCconst, TOKconst, NULL },
3280 { STCfinal, TOKfinal, NULL },
3281 { STCabstract, TOKabstract, NULL },
3282 { STCsynchronized, TOKsynchronized, NULL },
3283 { STCdeprecated, TOKdeprecated, NULL },
3284 { STCoverride, TOKoverride, NULL },
3285 { STClazy, TOKlazy, NULL },
3286 { STCalias, TOKalias, NULL },
3287 { STCout, TOKout, NULL },
3288 { STCin, TOKin, NULL },
3289 { STCmanifest, TOKenum, NULL },
3290 { STCimmutable, TOKimmutable, NULL },
3291 { STCshared, TOKshared, NULL },
3292 { STCnothrow, TOKnothrow, NULL },
3293 { STCwild, TOKwild, NULL },
3294 { STCpure, TOKpure, NULL },
3295 { STCref, TOKref, NULL },
3296 { STCtls, TOKreserved, NULL },
3297 { STCgshared, TOKgshared, NULL },
3298 { STCnogc, TOKat, "@nogc" },
3299 { STCproperty, TOKat, "@property" },
3300 { STCsafe, TOKat, "@safe" },
3301 { STCtrusted, TOKat, "@trusted" },
3302 { STCsystem, TOKat, "@system" },
3303 { STCdisable, TOKat, "@disable" },
3304 { STCfuture, TOKat, "@__future" },
3305 { STClocal, TOKat, "__local" },
3306 { 0, TOKreserved, NULL }
3307 };
3308
3309 for (int i = 0; table[i].stc; i++)
3310 {
3311 StorageClass tbl = table[i].stc;
3312 assert(tbl & STCStorageClass);
3313 if (stc & tbl)
3314 {
3315 stc &= ~tbl;
3316 if (tbl == STCtls) // TOKtls was removed
3317 return "__thread";
3318
3319 TOK tok = table[i].tok;
3320 if (tok == TOKat)
3321 return table[i].id;
3322 else
3323 return Token::toChars(tok);
3324 }
3325 }
3326 //printf("stc = %llx\n", stc);
3327 return NULL;
3328 }
3329
3330 void trustToBuffer(OutBuffer *buf, TRUST trust)
3331 {
3332 const char *p = trustToChars(trust);
3333 if (p)
3334 buf->writestring(p);
3335 }
3336
3337 const char *trustToChars(TRUST trust)
3338 {
3339 switch (trust)
3340 {
3341 case TRUSTdefault: return NULL;
3342 case TRUSTsystem: return "@system";
3343 case TRUSTtrusted: return "@trusted";
3344 case TRUSTsafe: return "@safe";
3345 default: assert(0);
3346 }
3347 return NULL; // never reached
3348 }
3349
3350 void linkageToBuffer(OutBuffer *buf, LINK linkage)
3351 {
3352 const char *p = linkageToChars(linkage);
3353 if (p)
3354 {
3355 buf->writestring("extern (");
3356 buf->writestring(p);
3357 buf->writeByte(')');
3358 }
3359 }
3360
3361 const char *linkageToChars(LINK linkage)
3362 {
3363 switch (linkage)
3364 {
3365 case LINKdefault: return NULL;
3366 case LINKd: return "D";
3367 case LINKc: return "C";
3368 case LINKcpp: return "C++";
3369 case LINKwindows: return "Windows";
3370 case LINKpascal: return "Pascal";
3371 case LINKobjc: return "Objective-C";
3372 case LINKsystem: return "System";
3373 default: assert(0);
3374 }
3375 return NULL; // never reached
3376 }
3377
3378 void protectionToBuffer(OutBuffer *buf, Prot prot)
3379 {
3380 const char *p = protectionToChars(prot.kind);
3381 if (p)
3382 buf->writestring(p);
3383
3384 if (prot.kind == PROTpackage && prot.pkg)
3385 {
3386 buf->writeByte('(');
3387 buf->writestring(prot.pkg->toPrettyChars(true));
3388 buf->writeByte(')');
3389 }
3390 }
3391
3392 const char *protectionToChars(PROTKIND kind)
3393 {
3394 switch (kind)
3395 {
3396 case PROTundefined: return NULL;
3397 case PROTnone: return "none";
3398 case PROTprivate: return "private";
3399 case PROTpackage: return "package";
3400 case PROTprotected: return "protected";
3401 case PROTpublic: return "public";
3402 case PROTexport: return "export";
3403 default: assert(0);
3404 }
3405 return NULL; // never reached
3406 }
3407
3408 // Print the full function signature with correct ident, attributes and template args
3409 void functionToBufferFull(TypeFunction *tf, OutBuffer *buf, Identifier *ident,
3410 HdrGenState* hgs, TemplateDeclaration *td)
3411 {
3412 //printf("TypeFunction::toCBuffer() this = %p\n", this);
3413 PrettyPrintVisitor v(buf, hgs);
3414 v.visitFuncIdentWithPrefix(tf, ident, td);
3415 }
3416
3417 // ident is inserted before the argument list and will be "function" or "delegate" for a type
3418 void functionToBufferWithIdent(TypeFunction *tf, OutBuffer *buf, const char *ident)
3419 {
3420 HdrGenState hgs;
3421 PrettyPrintVisitor v(buf, &hgs);
3422 v.visitFuncIdentWithPostfix(tf, ident);
3423 }
3424
3425 void toCBuffer(Expression *e, OutBuffer *buf, HdrGenState *hgs)
3426 {
3427 PrettyPrintVisitor v(buf, hgs);
3428 e->accept(&v);
3429 }
3430
3431 /**************************************************
3432 * Write out argument types to buf.
3433 */
3434 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments)
3435 {
3436 if (!arguments || !arguments->length)
3437 return;
3438
3439 HdrGenState hgs;
3440 PrettyPrintVisitor v(buf, &hgs);
3441 for (size_t i = 0; i < arguments->length; i++)
3442 {
3443 Expression *arg = (*arguments)[i];
3444 if (i)
3445 buf->writestring(", ");
3446 v.typeToBuffer(arg->type, NULL);
3447 }
3448 }
3449
3450 void toCBuffer(TemplateParameter *tp, OutBuffer *buf, HdrGenState *hgs)
3451 {
3452 PrettyPrintVisitor v(buf, hgs);
3453 tp->accept(&v);
3454 }
3455
3456 void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects)
3457 {
3458 if (!objects || !objects->length)
3459 return;
3460
3461 HdrGenState hgs;
3462 PrettyPrintVisitor v(buf, &hgs);
3463 for (size_t i = 0; i < objects->length; i++)
3464 {
3465 RootObject *o = (*objects)[i];
3466 if (i)
3467 buf->writestring(", ");
3468 v.objectToBuffer(o);
3469 }
3470 }
3471
3472 const char *parametersTypeToChars(ParameterList pl)
3473 {
3474 OutBuffer buf;
3475 HdrGenState hgs;
3476 PrettyPrintVisitor v(&buf, &hgs);
3477 v.parametersToBuffer(pl.parameters, pl.varargs);
3478 return buf.extractString();
3479 }