]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/hdrgen.c
d: Merge upstream dmd 7132b3537
[thirdparty/gcc.git] / gcc / d / dmd / hdrgen.c
CommitLineData
b4c522fa
IB
1
2/* Compiler implementation of the D programming language
a3b38b77 3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
b4c522fa
IB
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
f9ab59ff 13#include "root/dsystem.h"
b4c522fa
IB
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
44void linkageToBuffer(OutBuffer *buf, LINK linkage);
45void MODtoBuffer(OutBuffer *buf, MOD mod);
46
47void 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
d103f336 61 m->hdrfile->setbuffer(buf.slice().ptr, buf.length());
b4c522fa
IB
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 */
74void moduleToBuffer(OutBuffer *buf, Module *m)
75{
76 HdrGenState hgs;
77 hgs.fullDump = true;
78 toCBuffer(m, buf, &hgs);
79}
80
81class PrettyPrintVisitor : public Visitor
82{
83public:
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 {
2cbc99d1 133 for (size_t i = 0; i < s->statements->length; i++)
b4c522fa
IB
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;
2cbc99d1 144 for (size_t i = 0; i < s->statements->length; i++)
b4c522fa
IB
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
2cbc99d1 170 for (size_t i = 0; i < s->statements->length; i++)
b4c522fa
IB
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
5b74dd0a 252 void foreachWithoutBody(ForeachStatement *s)
b4c522fa
IB
253 {
254 buf->writestring(Token::toChars(s->op));
255 buf->writestring(" (");
2cbc99d1 256 for (size_t i = 0; i < s->parameters->length; i++)
b4c522fa
IB
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();
5b74dd0a
IB
272 }
273
274 void visit(ForeachStatement *s)
275 {
276 foreachWithoutBody(s);
b4c522fa
IB
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
5b74dd0a 287 void foreachRangeWithoutBody(ForeachRangeStatement *s)
b4c522fa
IB
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();
5b74dd0a
IB
305 }
306
307 void visit(ForeachRangeStatement *s)
308 {
309 foreachRangeWithoutBody(s);
b4c522fa
IB
310 buf->level++;
311 if (s->_body)
312 s->_body->accept(this);
313 buf->level--;
314 buf->writeByte('}');
315 buf->writenl();
316 }
317
5b74dd0a
IB
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
b4c522fa
IB
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());
2cbc99d1 415 if (s->args && s->args->length)
b4c522fa
IB
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);
2cbc99d1 587 for (size_t i = 0; i < s->catches->length; i++)
b4c522fa
IB
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
72acf751 621 void visit(ScopeGuardStatement *s)
b4c522fa
IB
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 {
2cbc99d1 689 for (size_t i = 0; i < s->imports->length; i++)
b4c522fa
IB
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
5b74dd0a
IB
794 void visit(TypeTraits *t)
795 {
796 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
797 t->exp->accept(this);
798 }
799
b4c522fa
IB
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
c3a2ba10 921 parametersToBuffer(t->parameterList.parameters, t->parameterList.varargs);
b4c522fa
IB
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('(');
2cbc99d1 982 for (size_t i = 0; i < td->origParameters->length; i++)
b4c522fa
IB
983 {
984 TemplateParameter *p = (*td->origParameters)[i];
985 if (i)
986 buf->writestring(", ");
987 p->accept(this);
988 }
989 buf->writeByte(')');
990 }
c3a2ba10 991 parametersToBuffer(t->parameterList.parameters, t->parameterList.varargs);
b4c522fa
IB
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 {
2cbc99d1 1003 for (size_t i = 0; i < t->idents.length; i++)
b4c522fa
IB
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 }
2cbc99d1 1175 if (imp->packages && imp->packages->length)
b4c522fa 1176 {
2cbc99d1 1177 for (size_t i = 0; i < imp->packages->length; i++)
b4c522fa
IB
1178 {
1179 Identifier *pid = (*imp->packages)[i];
1180 buf->printf("%s.", pid->toChars());
1181 }
1182 }
1183 buf->printf("%s", imp->id->toChars());
2cbc99d1 1184 if (imp->names.length)
b4c522fa
IB
1185 {
1186 buf->writestring(" : ");
2cbc99d1 1187 for (size_t i = 0; i < imp->names.length; i++)
b4c522fa
IB
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
2cbc99d1 1220 if (d->decl->length == 0)
b4c522fa 1221 buf->writestring("{}");
2cbc99d1 1222 else if (hgs->hdrgen && d->decl->length == 1 && (*d->decl)[0]->isUnitTestDeclaration())
b4c522fa
IB
1223 {
1224 // hack for bugzilla 8081
1225 buf->writestring("{}");
1226 }
2cbc99d1 1227 else if (d->decl->length == 1)
b4c522fa
IB
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++;
2cbc99d1 1238 for (size_t i = 0; i < d->decl->length; i++)
b4c522fa
IB
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;
b4c522fa
IB
1274 case LINKobjc: p = "Objective-C"; break;
1275 default:
1276 assert(0);
1277 break;
1278 }
1279 buf->writestring("extern (");
1280 buf->writestring(p);
1281 buf->writestring(") ");
1282 visit((AttribDeclaration *)d);
1283 }
1284
1285 void visit(CPPMangleDeclaration *d)
1286 {
1287 const char *p;
1288
1289 switch (d->cppmangle)
1290 {
1291 case CPPMANGLEclass: p = "class"; break;
1292 case CPPMANGLEstruct: p = "struct"; break;
1293 default:
1294 assert(0);
1295 break;
1296 }
1297 buf->writestring("extern (C++, ");
1298 buf->writestring(p);
1299 buf->writestring(") ");
1300 visit((AttribDeclaration *)d);
1301 }
1302
1303 void visit(ProtDeclaration *d)
1304 {
1305 protectionToBuffer(buf, d->protection);
1306 buf->writeByte(' ');
1307 visit((AttribDeclaration *)d);
1308 }
1309
1310 void visit(AlignDeclaration *d)
1311 {
1312 if (!d->ealign)
1313 buf->printf("align ");
1314 else
1315 buf->printf("align (%s)", d->ealign->toChars());
1316 visit((AttribDeclaration *)d);
1317 }
1318
1319 void visit(AnonDeclaration *d)
1320 {
1321 buf->printf(d->isunion ? "union" : "struct");
1322 buf->writenl();
1323 buf->writestring("{");
1324 buf->writenl();
1325 buf->level++;
1326 if (d->decl)
1327 {
2cbc99d1 1328 for (size_t i = 0; i < d->decl->length; i++)
b4c522fa
IB
1329 {
1330 Dsymbol *de = (*d->decl)[i];
1331 de->accept(this);
1332 }
1333 }
1334 buf->level--;
1335 buf->writestring("}");
1336 buf->writenl();
1337 }
1338
1339 void visit(PragmaDeclaration *d)
1340 {
1341 buf->printf("pragma (%s", d->ident->toChars());
2cbc99d1 1342 if (d->args && d->args->length)
b4c522fa
IB
1343 {
1344 buf->writestring(", ");
1345 argsToBuffer(d->args);
1346 }
1347 buf->writeByte(')');
1348 visit((AttribDeclaration *)d);
1349 }
1350
1351 void visit(ConditionalDeclaration *d)
1352 {
1353 d->condition->accept(this);
1354 if (d->decl || d->elsedecl)
1355 {
1356 buf->writenl();
1357 buf->writeByte('{');
1358 buf->writenl();
1359 buf->level++;
1360 if (d->decl)
1361 {
2cbc99d1 1362 for (size_t i = 0; i < d->decl->length; i++)
b4c522fa
IB
1363 {
1364 Dsymbol *de = (*d->decl)[i];
1365 de->accept(this);
1366 }
1367 }
1368 buf->level--;
1369 buf->writeByte('}');
1370 if (d->elsedecl)
1371 {
1372 buf->writenl();
1373 buf->writestring("else");
1374 buf->writenl();
1375 buf->writeByte('{');
1376 buf->writenl();
1377 buf->level++;
2cbc99d1 1378 for (size_t i = 0; i < d->elsedecl->length; i++)
b4c522fa
IB
1379 {
1380 Dsymbol *de = (*d->elsedecl)[i];
1381 de->accept(this);
1382 }
1383 buf->level--;
1384 buf->writeByte('}');
1385 }
1386 }
1387 else
1388 buf->writeByte(':');
1389 buf->writenl();
1390 }
1391
5b74dd0a
IB
1392 void visit(ForwardingStatement *s)
1393 {
1394 s->statement->accept(this);
1395 }
1396
1397 void visit(StaticForeachDeclaration *s)
1398 {
1399 buf->writestring("static ");
1400 if (s->sfe->aggrfe)
1401 {
1402 foreachWithoutBody(s->sfe->aggrfe);
1403 }
1404 else
1405 {
1406 assert(s->sfe->rangefe);
1407 foreachRangeWithoutBody(s->sfe->rangefe);
1408 }
1409 buf->writeByte('{');
1410 buf->writenl();
1411 buf->level++;
1412 visit((AttribDeclaration *)s);
1413 buf->level--;
1414 buf->writeByte('}');
1415 buf->writenl();
1416 }
1417
b4c522fa
IB
1418 void visit(CompileDeclaration *d)
1419 {
1420 buf->writestring("mixin(");
1421 d->exp->accept(this);
1422 buf->writestring(");");
1423 buf->writenl();
1424 }
1425
1426 void visit(UserAttributeDeclaration *d)
1427 {
1428 buf->writestring("@(");
1429 argsToBuffer(d->atts);
1430 buf->writeByte(')');
1431 visit((AttribDeclaration *)d);
1432 }
1433
1434 void visit(TemplateDeclaration *d)
1435 {
1436 if ((hgs->hdrgen || hgs->fullDump) && visitEponymousMember(d))
1437 return;
1438
1439 if (hgs->ddoc)
1440 buf->writestring(d->kind());
1441 else
1442 buf->writestring("template");
1443 buf->writeByte(' ');
1444 buf->writestring(d->ident->toChars());
1445 buf->writeByte('(');
1446 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1447 buf->writeByte(')');
1448 visitTemplateConstraint(d->constraint);
1449
1450 if (hgs->hdrgen || hgs->fullDump)
1451 {
1452 hgs->tpltMember++;
1453 buf->writenl();
1454 buf->writeByte('{');
1455 buf->writenl();
1456 buf->level++;
2cbc99d1 1457 for (size_t i = 0; i < d->members->length; i++)
b4c522fa
IB
1458 {
1459 Dsymbol *s = (*d->members)[i];
1460 s->accept(this);
1461 }
1462 buf->level--;
1463 buf->writeByte('}');
1464 buf->writenl();
1465 hgs->tpltMember--;
1466 }
1467 }
1468
1469 bool visitEponymousMember(TemplateDeclaration *d)
1470 {
2cbc99d1 1471 if (!d->members || d->members->length != 1)
b4c522fa
IB
1472 return false;
1473
1474 Dsymbol *onemember = (*d->members)[0];
1475 if (onemember->ident != d->ident)
1476 return false;
1477
1478 if (FuncDeclaration *fd = onemember->isFuncDeclaration())
1479 {
1480 assert(fd->type);
1481 if (stcToBuffer(buf, fd->storage_class))
1482 buf->writeByte(' ');
1483 functionToBufferFull((TypeFunction *)fd->type, buf, d->ident, hgs, d);
1484 visitTemplateConstraint(d->constraint);
1485
1486 hgs->tpltMember++;
1487 bodyToBuffer(fd);
1488 hgs->tpltMember--;
1489 return true;
1490 }
1491 if (AggregateDeclaration *ad = onemember->isAggregateDeclaration())
1492 {
1493 buf->writestring(ad->kind());
1494 buf->writeByte(' ');
1495 buf->writestring(ad->ident->toChars());
1496 buf->writeByte('(');
1497 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1498 buf->writeByte(')');
1499 visitTemplateConstraint(d->constraint);
1500 visitBaseClasses(ad->isClassDeclaration());
1501
1502 hgs->tpltMember++;
1503 if (ad->members)
1504 {
1505 buf->writenl();
1506 buf->writeByte('{');
1507 buf->writenl();
1508 buf->level++;
2cbc99d1 1509 for (size_t i = 0; i < ad->members->length; i++)
b4c522fa
IB
1510 {
1511 Dsymbol *s = (*ad->members)[i];
1512 s->accept(this);
1513 }
1514 buf->level--;
1515 buf->writeByte('}');
1516 }
1517 else
1518 buf->writeByte(';');
1519 buf->writenl();
1520 hgs->tpltMember--;
1521 return true;
1522 }
1523 if (VarDeclaration *vd = onemember->isVarDeclaration())
1524 {
1525 if (d->constraint)
1526 return false;
1527
1528 if (stcToBuffer(buf, vd->storage_class))
1529 buf->writeByte(' ');
1530 if (vd->type)
1531 typeToBuffer(vd->type, vd->ident);
1532 else
1533 buf->writestring(vd->ident->toChars());
1534
1535 buf->writeByte('(');
1536 visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
1537 buf->writeByte(')');
1538
1539 if (vd->_init)
1540 {
1541 buf->writestring(" = ");
1542 ExpInitializer *ie = vd->_init->isExpInitializer();
1543 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
1544 ((AssignExp *)ie->exp)->e2->accept(this);
1545 else
1546 vd->_init->accept(this);
1547 }
1548 buf->writeByte(';');
1549 buf->writenl();
1550 return true;
1551 }
1552
1553 return false;
1554 }
1555 void visitTemplateParameters(TemplateParameters *parameters)
1556 {
2cbc99d1 1557 if (!parameters || !parameters->length)
b4c522fa 1558 return;
2cbc99d1 1559 for (size_t i = 0; i < parameters->length; i++)
b4c522fa
IB
1560 {
1561 TemplateParameter *p = (*parameters)[i];
1562 if (i)
1563 buf->writestring(", ");
1564 p->accept(this);
1565 }
1566 }
1567 void visitTemplateConstraint(Expression *constraint)
1568 {
1569 if (!constraint)
1570 return;
1571 buf->writestring(" if (");
1572 constraint->accept(this);
1573 buf->writeByte(')');
1574 }
1575
1576 void visit(TemplateInstance *ti)
1577 {
1578 buf->writestring(ti->name->toChars());
1579 tiargsToBuffer(ti);
1580
1581 if (hgs->fullDump)
1582 {
1583 buf->writenl();
1584 if (ti->aliasdecl)
1585 {
1586 // the ti.aliasDecl is the instantiated body
1587 // if we have it, print it.
1588 ti->aliasdecl->accept(this);
1589 }
1590 }
1591 }
1592
1593 void visit(TemplateMixin *tm)
1594 {
1595 buf->writestring("mixin ");
1596
1597 typeToBuffer(tm->tqual, NULL);
1598 tiargsToBuffer(tm);
1599
1600 if (tm->ident && memcmp(tm->ident->toChars(), "__mixin", 7) != 0)
1601 {
1602 buf->writeByte(' ');
1603 buf->writestring(tm->ident->toChars());
1604 }
1605 buf->writeByte(';');
1606 buf->writenl();
1607 }
1608
1609 void tiargsToBuffer(TemplateInstance *ti)
1610 {
1611 buf->writeByte('!');
1612 if (ti->nest)
1613 {
1614 buf->writestring("(...)");
1615 return;
1616 }
1617 if (!ti->tiargs)
1618 {
1619 buf->writestring("()");
1620 return;
1621 }
1622
2cbc99d1 1623 if (ti->tiargs->length == 1)
b4c522fa
IB
1624 {
1625 RootObject *oarg = (*ti->tiargs)[0];
1626 if (Type *t = isType(oarg))
1627 {
1628 if (t->equals(Type::tstring) ||
1629 t->equals(Type::twstring) ||
1630 t->equals(Type::tdstring) ||
1631 (t->mod == 0 &&
1632 (t->isTypeBasic() ||
2cbc99d1 1633 (t->ty == Tident && ((TypeIdentifier *)t)->idents.length == 0))))
b4c522fa
IB
1634 {
1635 buf->writestring(t->toChars());
1636 return;
1637 }
1638 }
1639 else if (Expression *e = isExpression(oarg))
1640 {
1641 if (e->op == TOKint64 ||
1642 e->op == TOKfloat64 ||
1643 e->op == TOKnull ||
1644 e->op == TOKstring ||
1645 e->op == TOKthis)
1646 {
1647 buf->writestring(e->toChars());
1648 return;
1649 }
1650 }
1651 }
1652 buf->writeByte('(');
1653 ti->nest++;
2cbc99d1 1654 for (size_t i = 0; i < ti->tiargs->length; i++)
b4c522fa
IB
1655 {
1656 RootObject *arg = (*ti->tiargs)[i];
1657 if (i)
1658 buf->writestring(", ");
1659 objectToBuffer(arg);
1660 }
1661 ti->nest--;
1662 buf->writeByte(')');
1663 }
1664
1665 /****************************************
1666 * This makes a 'pretty' version of the template arguments.
1667 * It's analogous to genIdent() which makes a mangled version.
1668 */
1669 void objectToBuffer(RootObject *oarg)
1670 {
1671 //printf("objectToBuffer()\n");
1672
1673 /* The logic of this should match what genIdent() does. The _dynamic_cast()
1674 * function relies on all the pretty strings to be unique for different classes
1675 * (see Bugzilla 7375).
1676 * Perhaps it would be better to demangle what genIdent() does.
1677 */
1678 if (Type *t = isType(oarg))
1679 {
1680 //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
1681 typeToBuffer(t, NULL);
1682 }
1683 else if (Expression *e = isExpression(oarg))
1684 {
1685 if (e->op == TOKvar)
1686 e = e->optimize(WANTvalue); // added to fix Bugzilla 7375
1687 e->accept(this);
1688 }
1689 else if (Dsymbol *s = isDsymbol(oarg))
1690 {
1691 const char *p = s->ident ? s->ident->toChars() : s->toChars();
1692 buf->writestring(p);
1693 }
1694 else if (Tuple *v = isTuple(oarg))
1695 {
1696 Objects *args = &v->objects;
2cbc99d1 1697 for (size_t i = 0; i < args->length; i++)
b4c522fa
IB
1698 {
1699 RootObject *arg = (*args)[i];
1700 if (i)
1701 buf->writestring(", ");
1702 objectToBuffer(arg);
1703 }
1704 }
1705 else if (!oarg)
1706 {
1707 buf->writestring("NULL");
1708 }
1709 else
1710 {
1711 assert(0);
1712 }
1713 }
1714
1715 void visit(EnumDeclaration *d)
1716 {
1717 EnumDeclaration *oldInEnumDecl = inEnumDecl;
1718 inEnumDecl = d;
1719 buf->writestring("enum ");
1720 if (d->ident)
1721 {
1722 buf->writestring(d->ident->toChars());
1723 buf->writeByte(' ');
1724 }
1725 if (d->memtype)
1726 {
1727 buf->writestring(": ");
1728 typeToBuffer(d->memtype, NULL);
1729 }
1730 if (!d->members)
1731 {
1732 buf->writeByte(';');
1733 buf->writenl();
1734 inEnumDecl = oldInEnumDecl;
1735 return;
1736 }
1737 buf->writenl();
1738 buf->writeByte('{');
1739 buf->writenl();
1740 buf->level++;
2cbc99d1 1741 for (size_t i = 0; i < d->members->length; i++)
b4c522fa
IB
1742 {
1743 EnumMember *em = (*d->members)[i]->isEnumMember();
1744 if (!em)
1745 continue;
1746 em->accept(this);
1747 buf->writeByte(',');
1748 buf->writenl();
1749 }
1750 buf->level--;
1751 buf->writeByte('}');
1752 buf->writenl();
1753 inEnumDecl = oldInEnumDecl;
1754 }
1755
1756 void visit(Nspace *d)
1757 {
1758 buf->writestring("extern (C++, ");
1759 buf->writestring(d->ident->toChars());
1760 buf->writeByte(')');
1761 buf->writenl();
1762 buf->writeByte('{');
1763 buf->writenl();
1764 buf->level++;
2cbc99d1 1765 for (size_t i = 0; i < d->members->length; i++)
b4c522fa
IB
1766 {
1767 Dsymbol *s = (*d->members)[i];
1768 s->accept(this);
1769 }
1770 buf->level--;
1771 buf->writeByte('}');
1772 buf->writenl();
1773 }
1774
1775 void visit(StructDeclaration *d)
1776 {
1777 buf->printf("%s ", d->kind());
1778 if (!d->isAnonymous())
1779 buf->writestring(d->toChars());
1780 if (!d->members)
1781 {
1782 buf->writeByte(';');
1783 buf->writenl();
1784 return;
1785 }
1786 buf->writenl();
1787 buf->writeByte('{');
1788 buf->writenl();
1789 buf->level++;
2cbc99d1 1790 for (size_t i = 0; i < d->members->length; i++)
b4c522fa
IB
1791 {
1792 Dsymbol *s = (*d->members)[i];
1793 s->accept(this);
1794 }
1795 buf->level--;
1796 buf->writeByte('}');
1797 buf->writenl();
1798 }
1799
1800 void visit(ClassDeclaration *d)
1801 {
1802 if (!d->isAnonymous())
1803 {
1804 buf->writestring(d->kind());
1805 buf->writeByte(' ');
1806 buf->writestring(d->ident->toChars());
1807 }
1808 visitBaseClasses(d);
1809 if (d->members)
1810 {
1811 buf->writenl();
1812 buf->writeByte('{');
1813 buf->writenl();
1814 buf->level++;
2cbc99d1 1815 for (size_t i = 0; i < d->members->length; i++)
b4c522fa
IB
1816 {
1817 Dsymbol *s = (*d->members)[i];
1818 s->accept(this);
1819 }
1820 buf->level--;
1821 buf->writeByte('}');
1822 }
1823 else
1824 buf->writeByte(';');
1825 buf->writenl();
1826 }
1827
1828 void visitBaseClasses(ClassDeclaration *d)
1829 {
2cbc99d1 1830 if (!d || !d->baseclasses->length)
b4c522fa
IB
1831 return;
1832
1833 buf->writestring(" : ");
2cbc99d1 1834 for (size_t i = 0; i < d->baseclasses->length; i++)
b4c522fa
IB
1835 {
1836 if (i)
1837 buf->writestring(", ");
1838 BaseClass *b = (*d->baseclasses)[i];
1839 typeToBuffer(b->type, NULL);
1840 }
1841 }
1842
1843 void visit(AliasDeclaration *d)
1844 {
5b74dd0a
IB
1845 if (d->storage_class & STClocal)
1846 return;
b4c522fa
IB
1847 buf->writestring("alias ");
1848 if (d->aliassym)
1849 {
1850 buf->writestring(d->ident->toChars());
1851 buf->writestring(" = ");
1852 if (stcToBuffer(buf, d->storage_class))
1853 buf->writeByte(' ');
1854 d->aliassym->accept(this);
1855 }
1856 else if (d->type->ty == Tfunction)
1857 {
1858 if (stcToBuffer(buf, d->storage_class))
1859 buf->writeByte(' ');
1860 typeToBuffer(d->type, d->ident);
1861 }
1862 else
1863 {
1864 declstring = (d->ident == Id::string || d->ident == Id::wstring || d->ident == Id::dstring);
1865 buf->writestring(d->ident->toChars());
1866 buf->writestring(" = ");
1867 if (stcToBuffer(buf, d->storage_class))
1868 buf->writeByte(' ');
1869 typeToBuffer(d->type, NULL);
1870 declstring = false;
1871 }
1872 buf->writeByte(';');
1873 buf->writenl();
1874 }
1875
1876 void visit(VarDeclaration *d)
1877 {
5b74dd0a
IB
1878 if (d->storage_class & STClocal)
1879 return;
b4c522fa
IB
1880 visitVarDecl(d, false);
1881 buf->writeByte(';');
1882 buf->writenl();
1883 }
1884 void visitVarDecl(VarDeclaration *v, bool anywritten)
1885 {
1886 if (anywritten)
1887 {
1888 buf->writestring(", ");
1889 buf->writestring(v->ident->toChars());
1890 }
1891 else
1892 {
1893 if (stcToBuffer(buf, v->storage_class))
1894 buf->writeByte(' ');
1895 if (v->type)
1896 typeToBuffer(v->type, v->ident);
1897 else
1898 buf->writestring(v->ident->toChars());
1899 }
1900 if (v->_init)
1901 {
1902 buf->writestring(" = ");
1903 ExpInitializer *ie = v->_init->isExpInitializer();
1904 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
1905 ((AssignExp *)ie->exp)->e2->accept(this);
1906 else
1907 v->_init->accept(this);
1908 }
1909 }
1910
1911 void visit(FuncDeclaration *f)
1912 {
1913 //printf("FuncDeclaration::toCBuffer() '%s'\n", f->toChars());
1914
1915 if (stcToBuffer(buf, f->storage_class))
1916 buf->writeByte(' ');
1917 TypeFunction *tf = (TypeFunction *)f->type;
1918 typeToBuffer(tf, f->ident);
1919 if (hgs->hdrgen)
1920 {
1921 // if the return type is missing (e.g. ref functions or auto)
1922 if (!tf->next || f->storage_class & STCauto)
1923 {
1924 hgs->autoMember++;
1925 bodyToBuffer(f);
1926 hgs->autoMember--;
1927 }
1928 else if (hgs->tpltMember == 0 && global.params.hdrStripPlainFunctions)
1929 {
1930 buf->writeByte(';');
1931 buf->writenl();
1932 }
1933 else
1934 bodyToBuffer(f);
1935 }
1936 else
1937 bodyToBuffer(f);
1938 }
1939
1940 void bodyToBuffer(FuncDeclaration *f)
1941 {
1942 if (!f->fbody || (hgs->hdrgen && global.params.hdrStripPlainFunctions && !hgs->autoMember && !hgs->tpltMember))
1943 {
1944 buf->writeByte(';');
1945 buf->writenl();
1946 return;
1947 }
1948
1949 int savetlpt = hgs->tpltMember;
1950 int saveauto = hgs->autoMember;
1951 hgs->tpltMember = 0;
1952 hgs->autoMember = 0;
b4c522fa 1953 buf->writenl();
acae7b21 1954 bool requireDo = false;
b4c522fa 1955 // in{}
acae7b21 1956 if (f->frequires)
b4c522fa 1957 {
acae7b21
IB
1958 for (size_t i = 0; i < f->frequires->length; i++)
1959 {
1960 Statement *frequire = (*f->frequires)[i];
1961 buf->writestring("in");
1962 if (ExpStatement *es = frequire->isExpStatement())
1963 {
1964 assert(es->exp && es->exp->op == TOKassert);
1965 buf->writestring(" (");
1966 ((AssertExp *)es->exp)->e1->accept(this);
1967 buf->writeByte(')');
1968 buf->writenl();
1969 requireDo = false;
1970 }
1971 else
1972 {
1973 buf->writenl();
1974 frequire->accept(this);
1975 requireDo = true;
1976 }
1977 }
b4c522fa
IB
1978 }
1979
1980 // out{}
acae7b21 1981 if (f->fensures)
b4c522fa 1982 {
acae7b21 1983 for (size_t i = 0; i < f->fensures->length; i++)
b4c522fa 1984 {
acae7b21
IB
1985 Ensure fensure = (*f->fensures)[i];
1986 buf->writestring("out");
1987 if (ExpStatement *es = fensure.ensure->isExpStatement())
1988 {
1989 assert(es->exp && es->exp->op == TOKassert);
1990 buf->writestring(" (");
1991 if (fensure.id)
1992 {
1993 buf->writestring(fensure.id->toChars());
1994 }
1995 buf->writestring("; ");
1996 ((AssertExp *)es->exp)->e1->accept(this);
1997 buf->writeByte(')');
1998 buf->writenl();
1999 requireDo = false;
2000 }
2001 else
2002 {
2003 if (fensure.id)
2004 {
2005 buf->writeByte('(');
2006 buf->writestring(fensure.id->toChars());
2007 buf->writeByte(')');
2008 }
2009 buf->writenl();
2010 fensure.ensure->accept(this);
2011 requireDo = true;
2012 }
b4c522fa 2013 }
b4c522fa
IB
2014 }
2015
acae7b21 2016 if (requireDo)
b4c522fa
IB
2017 {
2018 buf->writestring("body");
2019 buf->writenl();
2020 }
2021
2022 buf->writeByte('{');
2023 buf->writenl();
2024 buf->level++;
2025 f->fbody->accept(this);
2026 buf->level--;
2027 buf->writeByte('}');
2028 buf->writenl();
2029
2030 hgs->tpltMember = savetlpt;
2031 hgs->autoMember = saveauto;
2032 }
2033
2034 void visit(FuncLiteralDeclaration *f)
2035 {
2036 if (f->type->ty == Terror)
2037 {
2038 buf->writestring("__error");
2039 return;
2040 }
2041
2042 if (f->tok != TOKreserved)
2043 {
2044 buf->writestring(f->kind());
2045 buf->writeByte(' ');
2046 }
2047
2048 TypeFunction *tf = (TypeFunction *)f->type;
2049 // Don't print tf->mod, tf->trust, and tf->linkage
2050 if (!f->inferRetType && tf->next)
2051 typeToBuffer(tf->next, NULL);
c3a2ba10 2052 parametersToBuffer(tf->parameterList.parameters, tf->parameterList.varargs);
b4c522fa
IB
2053
2054 CompoundStatement *cs = f->fbody->isCompoundStatement();
2055 Statement *s1;
2056 if (f->semanticRun >= PASSsemantic3done && cs)
2057 {
2cbc99d1 2058 s1 = (*cs->statements)[cs->statements->length - 1];
b4c522fa
IB
2059 }
2060 else
2061 s1 = !cs ? f->fbody : NULL;
2062 ReturnStatement *rs = s1 ? s1->isReturnStatement() : NULL;
2063 if (rs && rs->exp)
2064 {
2065 buf->writestring(" => ");
2066 rs->exp->accept(this);
2067 }
2068 else
2069 {
2070 hgs->tpltMember++;
2071 bodyToBuffer(f);
2072 hgs->tpltMember--;
2073 }
2074 }
2075
2076 void visit(PostBlitDeclaration *d)
2077 {
2078 if (stcToBuffer(buf, d->storage_class))
2079 buf->writeByte(' ');
2080 buf->writestring("this(this)");
2081 bodyToBuffer(d);
2082 }
2083
2084 void visit(DtorDeclaration *d)
2085 {
2086 if (d->storage_class & STCtrusted)
2087 buf->writestring("@trusted ");
2088 if (d->storage_class & STCsafe)
2089 buf->writestring("@safe ");
2090 if (d->storage_class & STCnogc)
2091 buf->writestring("@nogc ");
2092 if (d->storage_class & STCdisable)
2093 buf->writestring("@disable ");
2094
2095 buf->writestring("~this()");
2096 bodyToBuffer(d);
2097 }
2098
2099 void visit(StaticCtorDeclaration *d)
2100 {
2101 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2102 buf->writeByte(' ');
2103 if (d->isSharedStaticCtorDeclaration())
2104 buf->writestring("shared ");
2105 buf->writestring("static this()");
2106 if (hgs->hdrgen && !hgs->tpltMember)
2107 {
2108 buf->writeByte(';');
2109 buf->writenl();
2110 }
2111 else
2112 bodyToBuffer(d);
2113 }
2114
2115 void visit(StaticDtorDeclaration *d)
2116 {
2117 if (hgs->hdrgen)
2118 return;
2119 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2120 buf->writeByte(' ');
2121 if (d->isSharedStaticDtorDeclaration())
2122 buf->writestring("shared ");
2123 buf->writestring("static ~this()");
2124 bodyToBuffer(d);
2125 }
2126
2127 void visit(InvariantDeclaration *d)
2128 {
2129 if (hgs->hdrgen)
2130 return;
2131 if (stcToBuffer(buf, d->storage_class))
2132 buf->writeByte(' ');
2133 buf->writestring("invariant");
acae7b21
IB
2134 if (ExpStatement *es = d->fbody->isExpStatement())
2135 {
2136 assert(es->exp && es->exp->op == TOKassert);
2137 buf->writestring(" (");
2138 ((AssertExp *)es->exp)->e1->accept(this);
2139 buf->writestring(");");
2140 buf->writenl();
2141 }
2142 else
2143 {
2144 bodyToBuffer(d);
2145 }
b4c522fa
IB
2146 }
2147
2148 void visit(UnitTestDeclaration *d)
2149 {
2150 if (hgs->hdrgen)
2151 return;
2152 if (stcToBuffer(buf, d->storage_class))
2153 buf->writeByte(' ');
2154 buf->writestring("unittest");
2155 bodyToBuffer(d);
2156 }
2157
2158 void visit(NewDeclaration *d)
2159 {
2160 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2161 buf->writeByte(' ');
2162 buf->writestring("new");
2163 parametersToBuffer(d->parameters, d->varargs);
2164 bodyToBuffer(d);
2165 }
2166
2167 void visit(DeleteDeclaration *d)
2168 {
2169 if (stcToBuffer(buf, d->storage_class & ~STCstatic))
2170 buf->writeByte(' ');
2171 buf->writestring("delete");
2172 parametersToBuffer(d->parameters, 0);
2173 bodyToBuffer(d);
2174 }
2175
2176 ////////////////////////////////////////////////////////////////////////////
2177
2178 void visit(ErrorInitializer *)
2179 {
2180 buf->writestring("__error__");
2181 }
2182
2183 void visit(VoidInitializer *)
2184 {
2185 buf->writestring("void");
2186 }
2187
2188 void visit(StructInitializer *si)
2189 {
2190 //printf("StructInitializer::toCBuffer()\n");
2191 buf->writeByte('{');
2cbc99d1 2192 for (size_t i = 0; i < si->field.length; i++)
b4c522fa
IB
2193 {
2194 if (i)
2195 buf->writestring(", ");
2196 if (Identifier *id = si->field[i])
2197 {
2198 buf->writestring(id->toChars());
2199 buf->writeByte(':');
2200 }
2201 if (Initializer *iz = si->value[i])
2202 iz->accept(this);
2203 }
2204 buf->writeByte('}');
2205 }
2206
2207 void visit(ArrayInitializer *ai)
2208 {
2209 buf->writeByte('[');
2cbc99d1 2210 for (size_t i = 0; i < ai->index.length; i++)
b4c522fa
IB
2211 {
2212 if (i)
2213 buf->writestring(", ");
2214 if (Expression *ex = ai->index[i])
2215 {
2216 ex->accept(this);
2217 buf->writeByte(':');
2218 }
2219 if (Initializer *iz = ai->value[i])
2220 iz->accept(this);
2221 }
2222 buf->writeByte(']');
2223 }
2224
2225 void visit(ExpInitializer *ei)
2226 {
2227 ei->exp->accept(this);
2228 }
2229
2230 ////////////////////////////////////////////////////////////////////////////
2231
2232 /**************************************************
2233 * Write out argument list to buf.
2234 */
2235 void argsToBuffer(Expressions *expressions, Expression *basis = NULL)
2236 {
2cbc99d1 2237 if (!expressions || !expressions->length)
b4c522fa
IB
2238 return;
2239
2cbc99d1 2240 for (size_t i = 0; i < expressions->length; i++)
b4c522fa
IB
2241 {
2242 Expression *el = (*expressions)[i];
2243 if (i)
2244 buf->writestring(", ");
2245 if (!el)
2246 el = basis;
2247 if (el)
2248 expToBuffer(el, PREC_assign);
2249 }
2250 }
2251
2252 void sizeToBuffer(Expression *e)
2253 {
2254 if (e->type == Type::tsize_t)
2255 {
2256 Expression *ex = (e->op == TOKcast ? ((CastExp *)e)->e1 : e);
2257 ex = ex->optimize(WANTvalue);
2258
2259 dinteger_t uval = ex->op == TOKint64 ? ex->toInteger() : (dinteger_t)-1;
2260 if ((sinteger_t)uval >= 0)
2261 {
2262 dinteger_t sizemax;
5905cbdb 2263 if (target.ptrsize == 8)
b4c522fa 2264 sizemax = 0xFFFFFFFFFFFFFFFFULL;
5905cbdb 2265 else if (target.ptrsize == 4)
de83a4c1 2266 sizemax = 0xFFFFFFFFUL;
5905cbdb 2267 else if (target.ptrsize == 2)
de83a4c1 2268 sizemax = 0xFFFFUL;
b4c522fa
IB
2269 else
2270 assert(0);
2271 if (uval <= sizemax && uval <= 0x7FFFFFFFFFFFFFFFULL)
2272 {
2273 buf->printf("%llu", uval);
2274 return;
2275 }
2276 }
2277 }
2278 expToBuffer(e, PREC_assign);
2279 }
2280
2281 /**************************************************
2282 * Write expression out to buf, but wrap it
2283 * in ( ) if its precedence is less than pr.
2284 */
2285 void expToBuffer(Expression *e, PREC pr)
2286 {
2287 assert(precedence[e->op] != PREC_zero);
2288 assert(pr != PREC_zero);
2289
2290 //if (precedence[e->op] == 0) e->print();
2291 /* Despite precedence, we don't allow a<b<c expressions.
2292 * They must be parenthesized.
2293 */
2294 if (precedence[e->op] < pr ||
2295 (pr == PREC_rel && precedence[e->op] == pr))
2296 {
2297 buf->writeByte('(');
2298 e->accept(this);
2299 buf->writeByte(')');
2300 }
2301 else
2302 e->accept(this);
2303 }
2304
2305 void visit(Expression *e)
2306 {
2307 buf->writestring(Token::toChars(e->op));
2308 }
2309
2310 void visit(IntegerExp *e)
2311 {
2312 dinteger_t v = e->toInteger();
2313
2314 if (e->type)
2315 {
2316 Type *t = e->type;
2317 L1:
2318 switch (t->ty)
2319 {
2320 case Tenum:
2321 {
2322 TypeEnum *te = (TypeEnum *)t;
2323 if (hgs->fullDump)
2324 {
2325 EnumDeclaration *sym = te->sym;
2326 if (inEnumDecl != sym)
2327 {
2cbc99d1 2328 for (size_t i = 0; i < sym->members->length; i++)
b4c522fa
IB
2329 {
2330 EnumMember *em = (EnumMember *)(*sym->members)[i];
2331 if (em->value()->toInteger() == v)
2332 {
2333 buf->printf("%s.%s", sym->toChars(), em->ident->toChars());
2334 return;
2335 }
2336 }
2337 }
2338 }
2339 buf->printf("cast(%s)", te->sym->toChars());
2340 t = te->sym->memtype;
2341 goto L1;
2342 }
2343
2344 case Twchar: // BUG: need to cast(wchar)
2345 case Tdchar: // BUG: need to cast(dchar)
2346 if ((uinteger_t)v > 0xFF)
2347 {
2348 buf->printf("'\\U%08x'", v);
2349 break;
2350 }
2351 /* fall through */
2352 case Tchar:
2353 {
d103f336 2354 size_t o = buf->length();
b4c522fa
IB
2355 if (v == '\'')
2356 buf->writestring("'\\''");
2357 else if (isprint((int)v) && v != '\\')
2358 buf->printf("'%c'", (int)v);
2359 else
2360 buf->printf("'\\x%02x'", (int)v);
2361 if (hgs->ddoc)
2362 escapeDdocString(buf, o);
2363 break;
2364 }
2365
2366 case Tint8:
2367 buf->writestring("cast(byte)");
2368 goto L2;
2369
2370 case Tint16:
2371 buf->writestring("cast(short)");
2372 goto L2;
2373
2374 case Tint32:
2375 L2:
2376 buf->printf("%d", (int)v);
2377 break;
2378
2379 case Tuns8:
2380 buf->writestring("cast(ubyte)");
2381 goto L3;
2382
2383 case Tuns16:
2384 buf->writestring("cast(ushort)");
2385 goto L3;
2386
2387 case Tuns32:
2388 L3:
2389 buf->printf("%uu", (unsigned)v);
2390 break;
2391
2392 case Tint64:
2393 buf->printf("%lldL", v);
2394 break;
2395
2396 case Tuns64:
2397 L4:
2398 buf->printf("%lluLU", v);
2399 break;
2400
2401 case Tbool:
2402 buf->writestring(v ? "true" : "false");
2403 break;
2404
2405 case Tpointer:
2406 buf->writestring("cast(");
2407 buf->writestring(t->toChars());
2408 buf->writeByte(')');
5905cbdb 2409 if (target.ptrsize == 8)
b4c522fa
IB
2410 goto L4;
2411 else
de83a4c1 2412 goto L3;
b4c522fa
IB
2413
2414 default:
2415 /* This can happen if errors, such as
2416 * the type is painted on like in fromConstInitializer().
2417 */
2418 if (!global.errors)
2419 {
2420 assert(0);
2421 }
2422 break;
2423 }
2424 }
2425 else if (v & 0x8000000000000000LL)
2426 buf->printf("0x%llx", v);
2427 else
2428 buf->printf("%lld", v);
2429 }
2430
2431 void visit(ErrorExp *)
2432 {
2433 buf->writestring("__error");
2434 }
2435
2436 void floatToBuffer(Type *type, real_t value)
2437 {
2438 /** sizeof(value)*3 is because each byte of mantissa is max
2439 of 256 (3 characters). The string will be "-M.MMMMe-4932".
2440 (ie, 8 chars more than mantissa). Plus one for trailing \0.
2441 Plus one for rounding. */
2442 const size_t BUFFER_LEN = sizeof(value) * 3 + 8 + 1 + 1;
f9ab59ff
IB
2443 char buffer[BUFFER_LEN];
2444 memset(buffer, 0, BUFFER_LEN);
b4c522fa
IB
2445 CTFloat::sprint(buffer, 'g', value);
2446 assert(strlen(buffer) < BUFFER_LEN);
2447
2448 if (hgs->hdrgen)
2449 {
2450 real_t r = CTFloat::parse(buffer);
2451 if (r != value) // if exact duplication
2452 CTFloat::sprint(buffer, 'a', value);
2453 }
2454 buf->writestring(buffer);
2455
2456 if (type)
2457 {
2458 Type *t = type->toBasetype();
2459 switch (t->ty)
2460 {
2461 case Tfloat32:
2462 case Timaginary32:
2463 case Tcomplex32:
2464 buf->writeByte('F');
2465 break;
2466
2467 case Tfloat80:
2468 case Timaginary80:
2469 case Tcomplex80:
2470 buf->writeByte('L');
2471 break;
2472
2473 default:
2474 break;
2475 }
2476 if (t->isimaginary())
2477 buf->writeByte('i');
2478 }
2479 }
2480
2481 void visit(RealExp *e)
2482 {
2483 floatToBuffer(e->type, e->value);
2484 }
2485
2486 void visit(ComplexExp *e)
2487 {
2488 /* Print as:
2489 * (re+imi)
2490 */
2491 buf->writeByte('(');
2492 floatToBuffer(e->type, creall(e->value));
2493 buf->writeByte('+');
2494 floatToBuffer(e->type, cimagl(e->value));
2495 buf->writestring("i)");
2496 }
2497
2498 void visit(IdentifierExp *e)
2499 {
2500 if (hgs->hdrgen || hgs->ddoc)
2501 buf->writestring(e->ident->toHChars2());
2502 else
2503 buf->writestring(e->ident->toChars());
2504 }
2505
2506 void visit(DsymbolExp *e)
2507 {
2508 buf->writestring(e->s->toChars());
2509 }
2510
2511 void visit(ThisExp *)
2512 {
2513 buf->writestring("this");
2514 }
2515
2516 void visit(SuperExp *)
2517 {
2518 buf->writestring("super");
2519 }
2520
2521 void visit(NullExp *)
2522 {
2523 buf->writestring("null");
2524 }
2525
2526 void visit(StringExp *e)
2527 {
2528 buf->writeByte('"');
d103f336 2529 size_t o = buf->length();
b4c522fa
IB
2530 for (size_t i = 0; i < e->len; i++)
2531 {
2532 unsigned c = e->charAt(i);
2533 switch (c)
2534 {
2535 case '"':
2536 case '\\':
2537 buf->writeByte('\\');
2538 /* fall through */
2539 default:
2540 if (c <= 0xFF)
2541 {
2542 if (c <= 0x7F && isprint(c))
2543 buf->writeByte(c);
2544 else
2545 buf->printf("\\x%02x", c);
2546 }
2547 else if (c <= 0xFFFF)
2548 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2549 else
2550 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2551 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2552 break;
2553 }
2554 }
2555 if (hgs->ddoc)
2556 escapeDdocString(buf, o);
2557 buf->writeByte('"');
2558 if (e->postfix)
2559 buf->writeByte(e->postfix);
2560 }
2561
2562 void visit(ArrayLiteralExp *e)
2563 {
2564 buf->writeByte('[');
2565 argsToBuffer(e->elements, e->basis);
2566 buf->writeByte(']');
2567 }
2568
2569 void visit(AssocArrayLiteralExp *e)
2570 {
2571 buf->writeByte('[');
2cbc99d1 2572 for (size_t i = 0; i < e->keys->length; i++)
b4c522fa
IB
2573 {
2574 Expression *key = (*e->keys)[i];
2575 Expression *value = (*e->values)[i];
2576
2577 if (i)
2578 buf->writestring(", ");
2579 expToBuffer(key, PREC_assign);
2580 buf->writeByte(':');
2581 expToBuffer(value, PREC_assign);
2582 }
2583 buf->writeByte(']');
2584 }
2585
2586 void visit(StructLiteralExp *e)
2587 {
2588 buf->writestring(e->sd->toChars());
2589 buf->writeByte('(');
2590
2591 // CTFE can generate struct literals that contain an AddrExp pointing
2592 // to themselves, need to avoid infinite recursion:
2593 // struct S { this(int){ this.s = &this; } S* s; }
2594 // const foo = new S(0);
2595 if (e->stageflags & stageToCBuffer)
2596 buf->writestring("<recursion>");
2597 else
2598 {
2599 int old = e->stageflags;
2600 e->stageflags |= stageToCBuffer;
2601 argsToBuffer(e->elements);
2602 e->stageflags = old;
2603 }
2604
2605 buf->writeByte(')');
2606 }
2607
2608 void visit(TypeExp *e)
2609 {
2610 typeToBuffer(e->type, NULL);
2611 }
2612
2613 void visit(ScopeExp *e)
2614 {
2615 if (e->sds->isTemplateInstance())
2616 {
2617 e->sds->accept(this);
2618 }
2619 else if (hgs != NULL && hgs->ddoc)
2620 {
2621 // fixes bug 6491
2622 Module *m = e->sds->isModule();
2623 if (m)
2624 buf->writestring(m->md->toChars());
2625 else
2626 buf->writestring(e->sds->toChars());
2627 }
2628 else
2629 {
2630 buf->writestring(e->sds->kind());
2631 buf->writeByte(' ');
2632 buf->writestring(e->sds->toChars());
2633 }
2634 }
2635
2636 void visit(TemplateExp *e)
2637 {
2638 buf->writestring(e->td->toChars());
2639 }
2640
2641 void visit(NewExp *e)
2642 {
2643 if (e->thisexp)
2644 {
2645 expToBuffer(e->thisexp, PREC_primary);
2646 buf->writeByte('.');
2647 }
2648 buf->writestring("new ");
2cbc99d1 2649 if (e->newargs && e->newargs->length)
b4c522fa
IB
2650 {
2651 buf->writeByte('(');
2652 argsToBuffer(e->newargs);
2653 buf->writeByte(')');
2654 }
2655 typeToBuffer(e->newtype, NULL);
2cbc99d1 2656 if (e->arguments && e->arguments->length)
b4c522fa
IB
2657 {
2658 buf->writeByte('(');
2659 argsToBuffer(e->arguments);
2660 buf->writeByte(')');
2661 }
2662 }
2663
2664 void visit(NewAnonClassExp *e)
2665 {
2666 if (e->thisexp)
2667 {
2668 expToBuffer(e->thisexp, PREC_primary);
2669 buf->writeByte('.');
2670 }
2671 buf->writestring("new");
2cbc99d1 2672 if (e->newargs && e->newargs->length)
b4c522fa
IB
2673 {
2674 buf->writeByte('(');
2675 argsToBuffer(e->newargs);
2676 buf->writeByte(')');
2677 }
2678 buf->writestring(" class ");
2cbc99d1 2679 if (e->arguments && e->arguments->length)
b4c522fa
IB
2680 {
2681 buf->writeByte('(');
2682 argsToBuffer(e->arguments);
2683 buf->writeByte(')');
2684 }
2685 if (e->cd)
2686 e->cd->accept(this);
2687 }
2688
2689 void visit(SymOffExp *e)
2690 {
2691 if (e->offset)
2692 buf->printf("(& %s+%u)", e->var->toChars(), e->offset);
2693 else if (e->var->isTypeInfoDeclaration())
2694 buf->printf("%s", e->var->toChars());
2695 else
2696 buf->printf("& %s", e->var->toChars());
2697 }
2698
2699 void visit(VarExp *e)
2700 {
2701 buf->writestring(e->var->toChars());
2702 }
2703
2704 void visit(OverExp *e)
2705 {
2706 buf->writestring(e->vars->ident->toChars());
2707 }
2708
2709 void visit(TupleExp *e)
2710 {
2711 if (e->e0)
2712 {
2713 buf->writeByte('(');
2714 e->e0->accept(this);
2715 buf->writestring(", tuple(");
2716 argsToBuffer(e->exps);
2717 buf->writestring("))");
2718 }
2719 else
2720 {
2721 buf->writestring("tuple(");
2722 argsToBuffer(e->exps);
2723 buf->writeByte(')');
2724 }
2725 }
2726
2727 void visit(FuncExp *e)
2728 {
2729 e->fd->accept(this);
2730 //buf->writestring(e->fd->toChars());
2731 }
2732
2733 void visit(DeclarationExp *e)
2734 {
2735 /* Normal dmd execution won't reach here - regular variable declarations
2736 * are handled in visit(ExpStatement), so here would be used only when
2737 * we'll directly call Expression::toChars() for debugging.
2738 */
2739 if (VarDeclaration *v = e->declaration->isVarDeclaration())
2740 {
2741 // For debugging use:
2742 // - Avoid printing newline.
2743 // - Intentionally use the format (Type var;)
2744 // which isn't correct as regular D code.
2745 buf->writeByte('(');
2746 visitVarDecl(v, false);
2747 buf->writeByte(';');
2748 buf->writeByte(')');
2749 }
2750 else
2751 e->declaration->accept(this);
2752 }
2753
2754 void visit(TypeidExp *e)
2755 {
2756 buf->writestring("typeid(");
2757 objectToBuffer(e->obj);
2758 buf->writeByte(')');
2759 }
2760
2761 void visit(TraitsExp *e)
2762 {
2763 buf->writestring("__traits(");
5b74dd0a
IB
2764 if (e->ident)
2765 buf->writestring(e->ident->toChars());
b4c522fa
IB
2766 if (e->args)
2767 {
2cbc99d1 2768 for (size_t i = 0; i < e->args->length; i++)
b4c522fa
IB
2769 {
2770 RootObject *arg = (*e->args)[i];
2771 buf->writestring(", ");
2772 objectToBuffer(arg);
2773 }
2774 }
2775 buf->writeByte(')');
2776 }
2777
2778 void visit(HaltExp *)
2779 {
2780 buf->writestring("halt");
2781 }
2782
2783 void visit(IsExp *e)
2784 {
2785 buf->writestring("is(");
2786 typeToBuffer(e->targ, e->id);
2787 if (e->tok2 != TOKreserved)
2788 {
2789 buf->printf(" %s %s", Token::toChars(e->tok), Token::toChars(e->tok2));
2790 }
2791 else if (e->tspec)
2792 {
2793 if (e->tok == TOKcolon)
2794 buf->writestring(" : ");
2795 else
2796 buf->writestring(" == ");
2797 typeToBuffer(e->tspec, NULL);
2798 }
2cbc99d1 2799 if (e->parameters && e->parameters->length)
b4c522fa
IB
2800 {
2801 buf->writestring(", ");
2802 visitTemplateParameters(e->parameters);
2803 }
2804 buf->writeByte(')');
2805 }
2806
2807 void visit(UnaExp *e)
2808 {
2809 buf->writestring(Token::toChars(e->op));
2810 expToBuffer(e->e1, precedence[e->op]);
2811 }
2812
2813 void visit(BinExp *e)
2814 {
2815 expToBuffer(e->e1, precedence[e->op]);
2816 buf->writeByte(' ');
2817 buf->writestring(Token::toChars(e->op));
2818 buf->writeByte(' ');
2819 expToBuffer(e->e2, (PREC)(precedence[e->op] + 1));
2820 }
2821
2822 void visit(CompileExp *e)
2823 {
2824 buf->writestring("mixin(");
2825 expToBuffer(e->e1, PREC_assign);
2826 buf->writeByte(')');
2827 }
2828
2829 void visit(ImportExp *e)
2830 {
2831 buf->writestring("import(");
2832 expToBuffer(e->e1, PREC_assign);
2833 buf->writeByte(')');
2834 }
2835
2836 void visit(AssertExp *e)
2837 {
2838 buf->writestring("assert(");
2839 expToBuffer(e->e1, PREC_assign);
2840 if (e->msg)
2841 {
2842 buf->writestring(", ");
2843 expToBuffer(e->msg, PREC_assign);
2844 }
2845 buf->writeByte(')');
2846 }
2847
2848 void visit(DotIdExp *e)
2849 {
2850 expToBuffer(e->e1, PREC_primary);
2851 buf->writeByte('.');
2852 buf->writestring(e->ident->toChars());
2853 }
2854
2855 void visit(DotTemplateExp *e)
2856 {
2857 expToBuffer(e->e1, PREC_primary);
2858 buf->writeByte('.');
2859 buf->writestring(e->td->toChars());
2860 }
2861
2862 void visit(DotVarExp *e)
2863 {
2864 expToBuffer(e->e1, PREC_primary);
2865 buf->writeByte('.');
2866 buf->writestring(e->var->toChars());
2867 }
2868
2869 void visit(DotTemplateInstanceExp *e)
2870 {
2871 expToBuffer(e->e1, PREC_primary);
2872 buf->writeByte('.');
2873 e->ti->accept(this);
2874 }
2875
2876 void visit(DelegateExp *e)
2877 {
2878 buf->writeByte('&');
2879 if (!e->func->isNested())
2880 {
2881 expToBuffer(e->e1, PREC_primary);
2882 buf->writeByte('.');
2883 }
2884 buf->writestring(e->func->toChars());
2885 }
2886
2887 void visit(DotTypeExp *e)
2888 {
2889 expToBuffer(e->e1, PREC_primary);
2890 buf->writeByte('.');
2891 buf->writestring(e->sym->toChars());
2892 }
2893
2894 void visit(CallExp *e)
2895 {
2896 if (e->e1->op == TOKtype)
2897 {
2898 /* Avoid parens around type to prevent forbidden cast syntax:
2899 * (sometype)(arg1)
2900 * This is ok since types in constructor calls
2901 * can never depend on parens anyway
2902 */
2903 e->e1->accept(this);
2904 }
2905 else
2906 expToBuffer(e->e1, precedence[e->op]);
2907 buf->writeByte('(');
2908 argsToBuffer(e->arguments);
2909 buf->writeByte(')');
2910 }
2911
2912 void visit(PtrExp *e)
2913 {
2914 buf->writeByte('*');
2915 expToBuffer(e->e1, precedence[e->op]);
2916 }
2917
2918 void visit(DeleteExp *e)
2919 {
2920 buf->writestring("delete ");
2921 expToBuffer(e->e1, precedence[e->op]);
2922 }
2923
2924 void visit(CastExp *e)
2925 {
2926 buf->writestring("cast(");
2927 if (e->to)
2928 typeToBuffer(e->to, NULL);
2929 else
2930 {
2931 MODtoBuffer(buf, e->mod);
2932 }
2933 buf->writeByte(')');
2934 expToBuffer(e->e1, precedence[e->op]);
2935 }
2936
2937 void visit(VectorExp *e)
2938 {
2939 buf->writestring("cast(");
2940 typeToBuffer(e->to, NULL);
2941 buf->writeByte(')');
2942 expToBuffer(e->e1, precedence[e->op]);
2943 }
2944
b9da0278
IB
2945 void visit(VectorArrayExp *e)
2946 {
2947 expToBuffer(e->e1, PREC_primary);
2948 buf->writestring(".array");
2949 }
2950
b4c522fa
IB
2951 void visit(SliceExp *e)
2952 {
2953 expToBuffer(e->e1, precedence[e->op]);
2954 buf->writeByte('[');
2955 if (e->upr || e->lwr)
2956 {
2957 if (e->lwr)
2958 sizeToBuffer(e->lwr);
2959 else
2960 buf->writeByte('0');
2961 buf->writestring("..");
2962 if (e->upr)
2963 sizeToBuffer(e->upr);
2964 else
2965 buf->writeByte('$');
2966 }
2967 buf->writeByte(']');
2968 }
2969
2970 void visit(ArrayLengthExp *e)
2971 {
2972 expToBuffer(e->e1, PREC_primary);
2973 buf->writestring(".length");
2974 }
2975
2976 void visit(IntervalExp *e)
2977 {
2978 expToBuffer(e->lwr, PREC_assign);
2979 buf->writestring("..");
2980 expToBuffer(e->upr, PREC_assign);
2981 }
2982
2983 void visit(DelegatePtrExp *e)
2984 {
2985 expToBuffer(e->e1, PREC_primary);
2986 buf->writestring(".ptr");
2987 }
2988
2989 void visit(DelegateFuncptrExp *e)
2990 {
2991 expToBuffer(e->e1, PREC_primary);
2992 buf->writestring(".funcptr");
2993 }
2994
2995 void visit(ArrayExp *e)
2996 {
2997 expToBuffer(e->e1, PREC_primary);
2998 buf->writeByte('[');
2999 argsToBuffer(e->arguments);
3000 buf->writeByte(']');
3001 }
3002
3003 void visit(DotExp *e)
3004 {
3005 expToBuffer(e->e1, PREC_primary);
3006 buf->writeByte('.');
3007 expToBuffer(e->e2, PREC_primary);
3008 }
3009
3010 void visit(IndexExp *e)
3011 {
3012 expToBuffer(e->e1, PREC_primary);
3013 buf->writeByte('[');
3014 sizeToBuffer(e->e2);
3015 buf->writeByte(']');
3016 }
3017
3018 void visit(PostExp *e)
3019 {
3020 expToBuffer(e->e1, precedence[e->op]);
3021 buf->writestring(Token::toChars(e->op));
3022 }
3023
3024 void visit(PreExp *e)
3025 {
3026 buf->writestring(Token::toChars(e->op));
3027 expToBuffer(e->e1, precedence[e->op]);
3028 }
3029
3030 void visit(RemoveExp *e)
3031 {
3032 expToBuffer(e->e1, PREC_primary);
3033 buf->writestring(".remove(");
3034 expToBuffer(e->e2, PREC_assign);
3035 buf->writeByte(')');
3036 }
3037
3038 void visit(CondExp *e)
3039 {
3040 expToBuffer(e->econd, PREC_oror);
3041 buf->writestring(" ? ");
3042 expToBuffer(e->e1, PREC_expr);
3043 buf->writestring(" : ");
3044 expToBuffer(e->e2, PREC_cond);
3045 }
3046
3047 void visit(DefaultInitExp *e)
3048 {
3049 buf->writestring(Token::toChars(e->subop));
3050 }
3051
3052 void visit(ClassReferenceExp *e)
3053 {
3054 buf->writestring(e->value->toChars());
3055 }
3056
3057 ////////////////////////////////////////////////////////////////////////////
3058
3059 void visit(TemplateTypeParameter *tp)
3060 {
3061 buf->writestring(tp->ident->toChars());
3062 if (tp->specType)
3063 {
3064 buf->writestring(" : ");
3065 typeToBuffer(tp->specType, NULL);
3066 }
3067 if (tp->defaultType)
3068 {
3069 buf->writestring(" = ");
3070 typeToBuffer(tp->defaultType, NULL);
3071 }
3072 }
3073
3074 void visit(TemplateThisParameter *tp)
3075 {
3076 buf->writestring("this ");
3077 visit((TemplateTypeParameter *)tp);
3078 }
3079
3080 void visit(TemplateAliasParameter *tp)
3081 {
3082 buf->writestring("alias ");
3083 if (tp->specType)
3084 typeToBuffer(tp->specType, tp->ident);
3085 else
3086 buf->writestring(tp->ident->toChars());
3087 if (tp->specAlias)
3088 {
3089 buf->writestring(" : ");
3090 objectToBuffer(tp->specAlias);
3091 }
3092 if (tp->defaultAlias)
3093 {
3094 buf->writestring(" = ");
3095 objectToBuffer(tp->defaultAlias);
3096 }
3097 }
3098
3099 void visit(TemplateValueParameter *tp)
3100 {
3101 typeToBuffer(tp->valType, tp->ident);
3102 if (tp->specValue)
3103 {
3104 buf->writestring(" : ");
3105 tp->specValue->accept(this);
3106 }
3107 if (tp->defaultValue)
3108 {
3109 buf->writestring(" = ");
3110 tp->defaultValue->accept(this);
3111 }
3112 }
3113
3114 void visit(TemplateTupleParameter *tp)
3115 {
3116 buf->writestring(tp->ident->toChars());
3117 buf->writestring("...");
3118 }
3119
3120 ////////////////////////////////////////////////////////////////////////////
3121
3122 void visit(DebugCondition *c)
3123 {
3124 if (c->ident)
3125 buf->printf("debug (%s)", c->ident->toChars());
3126 else
3127 buf->printf("debug (%u)", c->level);
3128 }
3129
3130 void visit(VersionCondition *c)
3131 {
3132 if (c->ident)
3133 buf->printf("version (%s)", c->ident->toChars());
3134 else
3135 buf->printf("version (%u)", c->level);
3136 }
3137
3138 void visit(StaticIfCondition *c)
3139 {
3140 buf->writestring("static if (");
3141 c->exp->accept(this);
3142 buf->writeByte(')');
3143 }
3144
3145 ////////////////////////////////////////////////////////////////////////////
3146
3147 void visit(Parameter *p)
3148 {
dddea6d4
IB
3149 if (p->userAttribDecl)
3150 {
3151 buf->writestring("@");
3152 bool isAnonymous = p->userAttribDecl->atts->length > 0
3153 && (*p->userAttribDecl->atts)[0]->op != TOKcall;
3154 if (isAnonymous)
3155 buf->writestring("(");
3156 argsToBuffer(p->userAttribDecl->atts);
3157 if (isAnonymous)
3158 buf->writestring(")");
3159 buf->writestring(" ");
3160 }
b4c522fa
IB
3161 if (p->storageClass & STCauto)
3162 buf->writestring("auto ");
3163
3164 if (p->storageClass & STCreturn)
3165 buf->writestring("return ");
3166
3167 if (p->storageClass & STCout)
3168 buf->writestring("out ");
3169 else if (p->storageClass & STCref)
3170 buf->writestring("ref ");
3171 else if (p->storageClass & STCin)
3172 buf->writestring("in ");
3173 else if (p->storageClass & STClazy)
3174 buf->writestring("lazy ");
3175 else if (p->storageClass & STCalias)
3176 buf->writestring("alias ");
3177
3178 StorageClass stc = p->storageClass;
3179 if (p->type && p->type->mod & MODshared)
3180 stc &= ~STCshared;
3181
3182 if (stcToBuffer(buf, stc & (STCconst | STCimmutable | STCwild | STCshared | STCscope | STCscopeinferred)))
3183 buf->writeByte(' ');
3184
3185 if (p->storageClass & STCalias)
3186 {
3187 if (p->ident)
3188 buf->writestring(p->ident->toChars());
3189 }
3190 else if (p->type->ty == Tident &&
3191 strlen(((TypeIdentifier *)p->type)->ident->toChars()) > 3 &&
3192 strncmp(((TypeIdentifier *)p->type)->ident->toChars(), "__T", 3) == 0)
3193 {
3194 // print parameter name, instead of undetermined type parameter
3195 buf->writestring(p->ident->toChars());
3196 }
3197 else
3198 typeToBuffer(p->type, p->ident);
3199 if (p->defaultArg)
3200 {
3201 buf->writestring(" = ");
3202 p->defaultArg->accept(this);
3203 }
3204 }
3205
3206 void parametersToBuffer(Parameters *parameters, int varargs)
3207 {
3208 buf->writeByte('(');
3209 if (parameters)
3210 {
3211 size_t dim = Parameter::dim(parameters);
3212 for (size_t i = 0; i < dim; i++)
3213 {
3214 if (i)
3215 buf->writestring(", ");
3216 Parameter *fparam = Parameter::getNth(parameters, i);
3217 fparam->accept(this);
3218 }
3219 if (varargs)
3220 {
2cbc99d1 3221 if (parameters->length && varargs == 1)
b4c522fa
IB
3222 buf->writestring(", ");
3223 buf->writestring("...");
3224 }
3225 }
3226 buf->writeByte(')');
3227 }
3228
3229 void visit(Module *m)
3230 {
3231 if (m->md)
3232 {
3233 if (m->userAttribDecl)
3234 {
3235 buf->writestring("@(");
3236 argsToBuffer(m->userAttribDecl->atts);
3237 buf->writeByte(')');
3238 buf->writenl();
3239 }
3240 if (m->md->isdeprecated)
3241 {
3242 if (m->md->msg)
3243 {
3244 buf->writestring("deprecated(");
3245 m->md->msg->accept(this);
3246 buf->writestring(") ");
3247 }
3248 else
3249 buf->writestring("deprecated ");
3250 }
3251
3252 buf->writestring("module ");
3253 buf->writestring(m->md->toChars());
3254 buf->writeByte(';');
3255 buf->writenl();
3256 }
2cbc99d1 3257 for (size_t i = 0; i < m->members->length; i++)
b4c522fa
IB
3258 {
3259 Dsymbol *s = (*m->members)[i];
3260 s->accept(this);
3261 }
3262 }
3263};
3264
3265void toCBuffer(Statement *s, OutBuffer *buf, HdrGenState *hgs)
3266{
3267 PrettyPrintVisitor v(buf, hgs);
3268 s->accept(&v);
3269}
3270
3271void toCBuffer(Type *t, OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3272{
3273 PrettyPrintVisitor v(buf, hgs);
3274 v.typeToBuffer(t, ident);
3275}
3276
3277void toCBuffer(Dsymbol *s, OutBuffer *buf, HdrGenState *hgs)
3278{
3279 PrettyPrintVisitor v(buf, hgs);
3280 s->accept(&v);
3281}
3282
3283// used from TemplateInstance::toChars() and TemplateMixin::toChars()
3284void toCBufferInstance(TemplateInstance *ti, OutBuffer *buf, bool qualifyTypes)
3285{
3286 HdrGenState hgs;
3287 hgs.fullQual = qualifyTypes;
3288 PrettyPrintVisitor v(buf, &hgs);
3289 v.visit(ti);
3290}
3291
3292void toCBuffer(Initializer *iz, OutBuffer *buf, HdrGenState *hgs)
3293{
3294 PrettyPrintVisitor v(buf, hgs);
3295 iz->accept(&v);
3296}
3297
3298bool stcToBuffer(OutBuffer *buf, StorageClass stc)
3299{
3300 bool result = false;
3301 if ((stc & (STCreturn | STCscope)) == (STCreturn | STCscope))
3302 stc &= ~STCscope;
3303 if (stc & STCscopeinferred)
3304 stc &= ~(STCscope | STCscopeinferred);
3305 while (stc)
3306 {
3307 const char *p = stcToChars(stc);
3308 if (!p)
3309 break;
3310 if (!result)
3311 result = true;
3312 else
3313 buf->writeByte(' ');
3314 buf->writestring(p);
3315 }
3316 return result;
3317}
3318
3319/*************************************************
3320 * Pick off one of the storage classes from stc,
3321 * and return a pointer to a string representation of it.
3322 * stc is reduced by the one picked.
3323 */
3324const char *stcToChars(StorageClass& stc)
3325{
3326 struct SCstring
3327 {
3328 StorageClass stc;
3329 TOK tok;
3330 const char *id;
3331 };
3332
3333 static SCstring table[] =
3334 {
3335 { STCauto, TOKauto, NULL },
3336 { STCscope, TOKscope, NULL },
3337 { STCstatic, TOKstatic, NULL },
3338 { STCextern, TOKextern, NULL },
3339 { STCconst, TOKconst, NULL },
3340 { STCfinal, TOKfinal, NULL },
3341 { STCabstract, TOKabstract, NULL },
3342 { STCsynchronized, TOKsynchronized, NULL },
3343 { STCdeprecated, TOKdeprecated, NULL },
3344 { STCoverride, TOKoverride, NULL },
3345 { STClazy, TOKlazy, NULL },
3346 { STCalias, TOKalias, NULL },
3347 { STCout, TOKout, NULL },
3348 { STCin, TOKin, NULL },
3349 { STCmanifest, TOKenum, NULL },
3350 { STCimmutable, TOKimmutable, NULL },
3351 { STCshared, TOKshared, NULL },
3352 { STCnothrow, TOKnothrow, NULL },
3353 { STCwild, TOKwild, NULL },
3354 { STCpure, TOKpure, NULL },
3355 { STCref, TOKref, NULL },
3356 { STCtls, TOKreserved, NULL },
3357 { STCgshared, TOKgshared, NULL },
3358 { STCnogc, TOKat, "@nogc" },
3359 { STCproperty, TOKat, "@property" },
3360 { STCsafe, TOKat, "@safe" },
3361 { STCtrusted, TOKat, "@trusted" },
3362 { STCsystem, TOKat, "@system" },
3363 { STCdisable, TOKat, "@disable" },
3364 { STCfuture, TOKat, "@__future" },
5b74dd0a 3365 { STClocal, TOKat, "__local" },
b4c522fa
IB
3366 { 0, TOKreserved, NULL }
3367 };
3368
3369 for (int i = 0; table[i].stc; i++)
3370 {
3371 StorageClass tbl = table[i].stc;
3372 assert(tbl & STCStorageClass);
3373 if (stc & tbl)
3374 {
3375 stc &= ~tbl;
3376 if (tbl == STCtls) // TOKtls was removed
3377 return "__thread";
3378
3379 TOK tok = table[i].tok;
3380 if (tok == TOKat)
3381 return table[i].id;
3382 else
3383 return Token::toChars(tok);
3384 }
3385 }
3386 //printf("stc = %llx\n", stc);
3387 return NULL;
3388}
3389
3390void trustToBuffer(OutBuffer *buf, TRUST trust)
3391{
3392 const char *p = trustToChars(trust);
3393 if (p)
3394 buf->writestring(p);
3395}
3396
3397const char *trustToChars(TRUST trust)
3398{
3399 switch (trust)
3400 {
3401 case TRUSTdefault: return NULL;
3402 case TRUSTsystem: return "@system";
3403 case TRUSTtrusted: return "@trusted";
3404 case TRUSTsafe: return "@safe";
3405 default: assert(0);
3406 }
3407 return NULL; // never reached
3408}
3409
3410void linkageToBuffer(OutBuffer *buf, LINK linkage)
3411{
3412 const char *p = linkageToChars(linkage);
3413 if (p)
3414 {
3415 buf->writestring("extern (");
3416 buf->writestring(p);
3417 buf->writeByte(')');
3418 }
3419}
3420
3421const char *linkageToChars(LINK linkage)
3422{
3423 switch (linkage)
3424 {
3425 case LINKdefault: return NULL;
3426 case LINKd: return "D";
3427 case LINKc: return "C";
3428 case LINKcpp: return "C++";
3429 case LINKwindows: return "Windows";
b4c522fa
IB
3430 case LINKobjc: return "Objective-C";
3431 case LINKsystem: return "System";
3432 default: assert(0);
3433 }
3434 return NULL; // never reached
3435}
3436
3437void protectionToBuffer(OutBuffer *buf, Prot prot)
3438{
3439 const char *p = protectionToChars(prot.kind);
3440 if (p)
3441 buf->writestring(p);
3442
0a2ee409 3443 if (prot.kind == Prot::package_ && prot.pkg)
b4c522fa
IB
3444 {
3445 buf->writeByte('(');
3446 buf->writestring(prot.pkg->toPrettyChars(true));
3447 buf->writeByte(')');
3448 }
3449}
3450
0a2ee409 3451const char *protectionToChars(Prot::Kind kind)
b4c522fa
IB
3452{
3453 switch (kind)
3454 {
0a2ee409
IB
3455 case Prot::undefined: return NULL;
3456 case Prot::none: return "none";
3457 case Prot::private_: return "private";
3458 case Prot::package_: return "package";
3459 case Prot::protected_: return "protected";
3460 case Prot::public_: return "public";
3461 case Prot::export_: return "export";
b4c522fa
IB
3462 default: assert(0);
3463 }
3464 return NULL; // never reached
3465}
3466
3467// Print the full function signature with correct ident, attributes and template args
3468void functionToBufferFull(TypeFunction *tf, OutBuffer *buf, Identifier *ident,
3469 HdrGenState* hgs, TemplateDeclaration *td)
3470{
3471 //printf("TypeFunction::toCBuffer() this = %p\n", this);
3472 PrettyPrintVisitor v(buf, hgs);
3473 v.visitFuncIdentWithPrefix(tf, ident, td);
3474}
3475
3476// ident is inserted before the argument list and will be "function" or "delegate" for a type
3477void functionToBufferWithIdent(TypeFunction *tf, OutBuffer *buf, const char *ident)
3478{
3479 HdrGenState hgs;
3480 PrettyPrintVisitor v(buf, &hgs);
3481 v.visitFuncIdentWithPostfix(tf, ident);
3482}
3483
3484void toCBuffer(Expression *e, OutBuffer *buf, HdrGenState *hgs)
3485{
3486 PrettyPrintVisitor v(buf, hgs);
3487 e->accept(&v);
3488}
3489
3490/**************************************************
3491 * Write out argument types to buf.
3492 */
3493void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments)
3494{
2cbc99d1 3495 if (!arguments || !arguments->length)
b4c522fa
IB
3496 return;
3497
3498 HdrGenState hgs;
3499 PrettyPrintVisitor v(buf, &hgs);
2cbc99d1 3500 for (size_t i = 0; i < arguments->length; i++)
b4c522fa
IB
3501 {
3502 Expression *arg = (*arguments)[i];
3503 if (i)
3504 buf->writestring(", ");
3505 v.typeToBuffer(arg->type, NULL);
3506 }
3507}
3508
3509void toCBuffer(TemplateParameter *tp, OutBuffer *buf, HdrGenState *hgs)
3510{
3511 PrettyPrintVisitor v(buf, hgs);
3512 tp->accept(&v);
3513}
3514
3515void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects)
3516{
2cbc99d1 3517 if (!objects || !objects->length)
b4c522fa
IB
3518 return;
3519
3520 HdrGenState hgs;
3521 PrettyPrintVisitor v(buf, &hgs);
2cbc99d1 3522 for (size_t i = 0; i < objects->length; i++)
b4c522fa
IB
3523 {
3524 RootObject *o = (*objects)[i];
3525 if (i)
3526 buf->writestring(", ");
3527 v.objectToBuffer(o);
3528 }
3529}
3530
c3a2ba10 3531const char *parametersTypeToChars(ParameterList pl)
b4c522fa
IB
3532{
3533 OutBuffer buf;
3534 HdrGenState hgs;
3535 PrettyPrintVisitor v(&buf, &hgs);
c3a2ba10 3536 v.parametersToBuffer(pl.parameters, pl.varargs);
fced594b 3537 return buf.extractChars();
b4c522fa 3538}