xref: /netbsd/external/gpl3/gcc/dist/gcc/d/dmd/hdrgen.c (revision dd083157)
181418a27Smrg 
281418a27Smrg /* Compiler implementation of the D programming language
381418a27Smrg  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
481418a27Smrg  * written by Dave Fladebo
581418a27Smrg  * http://www.digitalmars.com
681418a27Smrg  * Distributed under the Boost Software License, Version 1.0.
781418a27Smrg  * http://www.boost.org/LICENSE_1_0.txt
881418a27Smrg  * https://github.com/D-Programming-Language/dmd/blob/master/src/hdrgen.c
981418a27Smrg  */
1081418a27Smrg 
1181418a27Smrg // Routines to emit header files
1281418a27Smrg 
1381418a27Smrg #include "root/dsystem.h"
1481418a27Smrg #include "root/rmem.h"
1581418a27Smrg 
1681418a27Smrg #include "mars.h"
1781418a27Smrg #include "id.h"
1881418a27Smrg #include "init.h"
1981418a27Smrg 
2081418a27Smrg #include "attrib.h"
2181418a27Smrg #include "cond.h"
2281418a27Smrg #include "doc.h"
2381418a27Smrg #include "enum.h"
2481418a27Smrg #include "import.h"
2581418a27Smrg #include "module.h"
2681418a27Smrg #include "mtype.h"
2781418a27Smrg #include "parse.h"
2881418a27Smrg #include "scope.h"
2981418a27Smrg #include "staticassert.h"
3081418a27Smrg #include "target.h"
3181418a27Smrg #include "template.h"
3281418a27Smrg #include "utf.h"
3381418a27Smrg #include "version.h"
3481418a27Smrg 
3581418a27Smrg #include "declaration.h"
3681418a27Smrg #include "aggregate.h"
3781418a27Smrg #include "expression.h"
3881418a27Smrg #include "ctfe.h"
3981418a27Smrg #include "statement.h"
4081418a27Smrg #include "aliasthis.h"
4181418a27Smrg #include "nspace.h"
4281418a27Smrg #include "hdrgen.h"
4381418a27Smrg 
4481418a27Smrg void linkageToBuffer(OutBuffer *buf, LINK linkage);
4581418a27Smrg void MODtoBuffer(OutBuffer *buf, MOD mod);
4681418a27Smrg 
genhdrfile(Module * m)4781418a27Smrg void genhdrfile(Module *m)
4881418a27Smrg {
4981418a27Smrg     OutBuffer buf;
5081418a27Smrg     buf.doindent = 1;
5181418a27Smrg 
5281418a27Smrg     buf.printf("// D import file generated from '%s'", m->srcfile->toChars());
5381418a27Smrg     buf.writenl();
5481418a27Smrg 
5581418a27Smrg     HdrGenState hgs;
5681418a27Smrg     hgs.hdrgen = true;
5781418a27Smrg 
5881418a27Smrg     toCBuffer(m, &buf, &hgs);
5981418a27Smrg 
6081418a27Smrg     // Transfer image to file
6181418a27Smrg     m->hdrfile->setbuffer(buf.data, buf.offset);
6281418a27Smrg     buf.extractData();
6381418a27Smrg 
6481418a27Smrg     ensurePathToNameExists(Loc(), m->hdrfile->toChars());
6581418a27Smrg     writeFile(m->loc, m->hdrfile);
6681418a27Smrg }
6781418a27Smrg 
6881418a27Smrg /**
6981418a27Smrg  * Dumps the full contents of module `m` to `buf`.
7081418a27Smrg  * Params:
7181418a27Smrg  *   buf = buffer to write to.
7281418a27Smrg  *   m = module to visit all members of.
7381418a27Smrg  */
moduleToBuffer(OutBuffer * buf,Module * m)7481418a27Smrg void moduleToBuffer(OutBuffer *buf, Module *m)
7581418a27Smrg {
7681418a27Smrg     HdrGenState hgs;
7781418a27Smrg     hgs.fullDump = true;
7881418a27Smrg     toCBuffer(m, buf, &hgs);
7981418a27Smrg }
8081418a27Smrg 
8181418a27Smrg class PrettyPrintVisitor : public Visitor
8281418a27Smrg {
8381418a27Smrg public:
8481418a27Smrg     OutBuffer *buf;
8581418a27Smrg     HdrGenState *hgs;
8681418a27Smrg     bool declstring; // set while declaring alias for string,wstring or dstring
8781418a27Smrg     EnumDeclaration *inEnumDecl;
8881418a27Smrg 
PrettyPrintVisitor(OutBuffer * buf,HdrGenState * hgs)8981418a27Smrg     PrettyPrintVisitor(OutBuffer *buf, HdrGenState *hgs)
9081418a27Smrg         : buf(buf), hgs(hgs), declstring(false), inEnumDecl(NULL)
9181418a27Smrg     {
9281418a27Smrg     }
9381418a27Smrg 
visit(Statement *)9481418a27Smrg     void visit(Statement *)
9581418a27Smrg     {
9681418a27Smrg         buf->printf("Statement::toCBuffer()");
9781418a27Smrg         buf->writenl();
9881418a27Smrg         assert(0);
9981418a27Smrg     }
10081418a27Smrg 
visit(ErrorStatement *)10181418a27Smrg     void visit(ErrorStatement *)
10281418a27Smrg     {
10381418a27Smrg         buf->printf("__error__");
10481418a27Smrg         buf->writenl();
10581418a27Smrg     }
10681418a27Smrg 
visit(ExpStatement * s)10781418a27Smrg     void visit(ExpStatement *s)
10881418a27Smrg     {
10981418a27Smrg         if (s->exp && s->exp->op == TOKdeclaration)
11081418a27Smrg         {
11181418a27Smrg             // bypass visit(DeclarationExp)
11281418a27Smrg             ((DeclarationExp *)s->exp)->declaration->accept(this);
11381418a27Smrg             return;
11481418a27Smrg         }
11581418a27Smrg         if (s->exp)
11681418a27Smrg             s->exp->accept(this);
11781418a27Smrg         buf->writeByte(';');
11881418a27Smrg         if (!hgs->forStmtInit)
11981418a27Smrg             buf->writenl();
12081418a27Smrg     }
12181418a27Smrg 
visit(CompileStatement * s)12281418a27Smrg     void visit(CompileStatement *s)
12381418a27Smrg     {
12481418a27Smrg         buf->writestring("mixin(");
12581418a27Smrg         s->exp->accept(this);
12681418a27Smrg         buf->writestring(");");
12781418a27Smrg         if (!hgs->forStmtInit)
12881418a27Smrg             buf->writenl();
12981418a27Smrg     }
13081418a27Smrg 
visit(CompoundStatement * s)13181418a27Smrg     void visit(CompoundStatement *s)
13281418a27Smrg     {
13381418a27Smrg         for (size_t i = 0; i < s->statements->dim; i++)
13481418a27Smrg         {
13581418a27Smrg             Statement *sx = (*s->statements)[i];
13681418a27Smrg             if (sx)
13781418a27Smrg                 sx->accept(this);
13881418a27Smrg         }
13981418a27Smrg     }
14081418a27Smrg 
visit(CompoundDeclarationStatement * s)14181418a27Smrg     void visit(CompoundDeclarationStatement *s)
14281418a27Smrg     {
14381418a27Smrg         bool anywritten = false;
14481418a27Smrg         for (size_t i = 0; i < s->statements->dim; i++)
14581418a27Smrg         {
14681418a27Smrg             Statement *sx = (*s->statements)[i];
14781418a27Smrg             ExpStatement *ds = sx ? sx->isExpStatement() : NULL;
14881418a27Smrg             if (ds && ds->exp->op == TOKdeclaration)
14981418a27Smrg             {
15081418a27Smrg                 Dsymbol *d = ((DeclarationExp *)ds->exp)->declaration;
15181418a27Smrg                 assert(d->isDeclaration());
15281418a27Smrg                 if (VarDeclaration *v = d->isVarDeclaration())
15381418a27Smrg                     visitVarDecl(v, anywritten);
15481418a27Smrg                 else
15581418a27Smrg                     d->accept(this);
15681418a27Smrg                 anywritten = true;
15781418a27Smrg             }
15881418a27Smrg         }
15981418a27Smrg         buf->writeByte(';');
16081418a27Smrg         if (!hgs->forStmtInit)
16181418a27Smrg             buf->writenl();
16281418a27Smrg     }
16381418a27Smrg 
visit(UnrolledLoopStatement * s)16481418a27Smrg     void visit(UnrolledLoopStatement *s)
16581418a27Smrg     {
16681418a27Smrg         buf->writestring("unrolled {");
16781418a27Smrg         buf->writenl();
16881418a27Smrg         buf->level++;
16981418a27Smrg 
17081418a27Smrg         for (size_t i = 0; i < s->statements->dim; i++)
17181418a27Smrg         {
17281418a27Smrg             Statement *sx = (*s->statements)[i];
17381418a27Smrg             if (sx)
17481418a27Smrg                 sx->accept(this);
17581418a27Smrg         }
17681418a27Smrg 
17781418a27Smrg         buf->level--;
17881418a27Smrg         buf->writeByte('}');
17981418a27Smrg         buf->writenl();
18081418a27Smrg     }
18181418a27Smrg 
visit(ScopeStatement * s)18281418a27Smrg     void visit(ScopeStatement *s)
18381418a27Smrg     {
18481418a27Smrg         buf->writeByte('{');
18581418a27Smrg         buf->writenl();
18681418a27Smrg         buf->level++;
18781418a27Smrg 
18881418a27Smrg         if (s->statement)
18981418a27Smrg             s->statement->accept(this);
19081418a27Smrg 
19181418a27Smrg         buf->level--;
19281418a27Smrg         buf->writeByte('}');
19381418a27Smrg         buf->writenl();
19481418a27Smrg     }
19581418a27Smrg 
visit(WhileStatement * s)19681418a27Smrg     void visit(WhileStatement *s)
19781418a27Smrg     {
19881418a27Smrg         buf->writestring("while (");
19981418a27Smrg         s->condition->accept(this);
20081418a27Smrg         buf->writeByte(')');
20181418a27Smrg         buf->writenl();
20281418a27Smrg         if (s->_body)
20381418a27Smrg             s->_body->accept(this);
20481418a27Smrg     }
20581418a27Smrg 
visit(DoStatement * s)20681418a27Smrg     void visit(DoStatement *s)
20781418a27Smrg     {
20881418a27Smrg         buf->writestring("do");
20981418a27Smrg         buf->writenl();
21081418a27Smrg         if (s->_body)
21181418a27Smrg             s->_body->accept(this);
21281418a27Smrg         buf->writestring("while (");
21381418a27Smrg         s->condition->accept(this);
21481418a27Smrg         buf->writestring(");");
21581418a27Smrg         buf->writenl();
21681418a27Smrg     }
21781418a27Smrg 
visit(ForStatement * s)21881418a27Smrg     void visit(ForStatement *s)
21981418a27Smrg     {
22081418a27Smrg         buf->writestring("for (");
22181418a27Smrg         if (s->_init)
22281418a27Smrg         {
22381418a27Smrg             hgs->forStmtInit++;
22481418a27Smrg             s->_init->accept(this);
22581418a27Smrg             hgs->forStmtInit--;
22681418a27Smrg         }
22781418a27Smrg         else
22881418a27Smrg             buf->writeByte(';');
22981418a27Smrg         if (s->condition)
23081418a27Smrg         {
23181418a27Smrg             buf->writeByte(' ');
23281418a27Smrg             s->condition->accept(this);
23381418a27Smrg         }
23481418a27Smrg         buf->writeByte(';');
23581418a27Smrg         if (s->increment)
23681418a27Smrg         {
23781418a27Smrg             buf->writeByte(' ');
23881418a27Smrg             s->increment->accept(this);
23981418a27Smrg         }
24081418a27Smrg         buf->writeByte(')');
24181418a27Smrg         buf->writenl();
24281418a27Smrg         buf->writeByte('{');
24381418a27Smrg         buf->writenl();
24481418a27Smrg         buf->level++;
24581418a27Smrg         if (s->_body)
24681418a27Smrg             s->_body->accept(this);
24781418a27Smrg         buf->level--;
24881418a27Smrg         buf->writeByte('}');
24981418a27Smrg         buf->writenl();
25081418a27Smrg     }
25181418a27Smrg 
foreachWithoutBody(ForeachStatement * s)252*dd083157Smrg     void foreachWithoutBody(ForeachStatement *s)
25381418a27Smrg     {
25481418a27Smrg         buf->writestring(Token::toChars(s->op));
25581418a27Smrg         buf->writestring(" (");
25681418a27Smrg         for (size_t i = 0; i < s->parameters->dim; i++)
25781418a27Smrg         {
25881418a27Smrg             Parameter *p = (*s->parameters)[i];
25981418a27Smrg             if (i)
26081418a27Smrg                 buf->writestring(", ");
26181418a27Smrg             if (stcToBuffer(buf, p->storageClass))
26281418a27Smrg                 buf->writeByte(' ');
26381418a27Smrg             if (p->type)
26481418a27Smrg                 typeToBuffer(p->type, p->ident);
26581418a27Smrg             else
26681418a27Smrg                 buf->writestring(p->ident->toChars());
26781418a27Smrg         }
26881418a27Smrg         buf->writestring("; ");
26981418a27Smrg         s->aggr->accept(this);
27081418a27Smrg         buf->writeByte(')');
27181418a27Smrg         buf->writenl();
272*dd083157Smrg     }
273*dd083157Smrg 
visit(ForeachStatement * s)274*dd083157Smrg     void visit(ForeachStatement *s)
275*dd083157Smrg     {
276*dd083157Smrg         foreachWithoutBody(s);
27781418a27Smrg         buf->writeByte('{');
27881418a27Smrg         buf->writenl();
27981418a27Smrg         buf->level++;
28081418a27Smrg         if (s->_body)
28181418a27Smrg             s->_body->accept(this);
28281418a27Smrg         buf->level--;
28381418a27Smrg         buf->writeByte('}');
28481418a27Smrg         buf->writenl();
28581418a27Smrg     }
28681418a27Smrg 
foreachRangeWithoutBody(ForeachRangeStatement * s)287*dd083157Smrg     void foreachRangeWithoutBody(ForeachRangeStatement *s)
28881418a27Smrg     {
28981418a27Smrg         buf->writestring(Token::toChars(s->op));
29081418a27Smrg         buf->writestring(" (");
29181418a27Smrg 
29281418a27Smrg         if (s->prm->type)
29381418a27Smrg             typeToBuffer(s->prm->type, s->prm->ident);
29481418a27Smrg         else
29581418a27Smrg             buf->writestring(s->prm->ident->toChars());
29681418a27Smrg 
29781418a27Smrg         buf->writestring("; ");
29881418a27Smrg         s->lwr->accept(this);
29981418a27Smrg         buf->writestring(" .. ");
30081418a27Smrg         s->upr->accept(this);
30181418a27Smrg         buf->writeByte(')');
30281418a27Smrg         buf->writenl();
30381418a27Smrg         buf->writeByte('{');
30481418a27Smrg         buf->writenl();
305*dd083157Smrg     }
306*dd083157Smrg 
visit(ForeachRangeStatement * s)307*dd083157Smrg     void visit(ForeachRangeStatement *s)
308*dd083157Smrg     {
309*dd083157Smrg         foreachRangeWithoutBody(s);
31081418a27Smrg         buf->level++;
31181418a27Smrg         if (s->_body)
31281418a27Smrg             s->_body->accept(this);
31381418a27Smrg         buf->level--;
31481418a27Smrg         buf->writeByte('}');
31581418a27Smrg         buf->writenl();
31681418a27Smrg     }
31781418a27Smrg 
visit(StaticForeachStatement * s)318*dd083157Smrg     void visit(StaticForeachStatement *s)
319*dd083157Smrg     {
320*dd083157Smrg         buf->writestring("static ");
321*dd083157Smrg         if (s->sfe->aggrfe)
322*dd083157Smrg         {
323*dd083157Smrg             visit(s->sfe->aggrfe);
324*dd083157Smrg         }
325*dd083157Smrg         else
326*dd083157Smrg         {
327*dd083157Smrg             assert(s->sfe->rangefe);
328*dd083157Smrg             visit(s->sfe->rangefe);
329*dd083157Smrg         }
330*dd083157Smrg     }
331*dd083157Smrg 
visit(IfStatement * s)33281418a27Smrg     void visit(IfStatement *s)
33381418a27Smrg     {
33481418a27Smrg         buf->writestring("if (");
33581418a27Smrg         if (Parameter *p = s->prm)
33681418a27Smrg         {
33781418a27Smrg             StorageClass stc = p->storageClass;
33881418a27Smrg             if (!p->type && !stc)
33981418a27Smrg                 stc = STCauto;
34081418a27Smrg             if (stcToBuffer(buf, stc))
34181418a27Smrg                 buf->writeByte(' ');
34281418a27Smrg             if (p->type)
34381418a27Smrg                 typeToBuffer(p->type, p->ident);
34481418a27Smrg             else
34581418a27Smrg                 buf->writestring(p->ident->toChars());
34681418a27Smrg             buf->writestring(" = ");
34781418a27Smrg         }
34881418a27Smrg         s->condition->accept(this);
34981418a27Smrg         buf->writeByte(')');
35081418a27Smrg         buf->writenl();
35181418a27Smrg         if (s->ifbody->isScopeStatement())
35281418a27Smrg         {
35381418a27Smrg             s->ifbody->accept(this);
35481418a27Smrg         }
35581418a27Smrg         else
35681418a27Smrg         {
35781418a27Smrg             buf->level++;
35881418a27Smrg             s->ifbody->accept(this);
35981418a27Smrg             buf->level--;
36081418a27Smrg         }
36181418a27Smrg         if (s->elsebody)
36281418a27Smrg         {
36381418a27Smrg             buf->writestring("else");
36481418a27Smrg             if (!s->elsebody->isIfStatement())
36581418a27Smrg             {
36681418a27Smrg                 buf->writenl();
36781418a27Smrg             }
36881418a27Smrg             else
36981418a27Smrg             {
37081418a27Smrg                 buf->writeByte(' ');
37181418a27Smrg             }
37281418a27Smrg             if (s->elsebody->isScopeStatement() || s->elsebody->isIfStatement())
37381418a27Smrg             {
37481418a27Smrg                 s->elsebody->accept(this);
37581418a27Smrg             }
37681418a27Smrg             else
37781418a27Smrg             {
37881418a27Smrg                 buf->level++;
37981418a27Smrg                 s->elsebody->accept(this);
38081418a27Smrg                 buf->level--;
38181418a27Smrg             }
38281418a27Smrg         }
38381418a27Smrg     }
38481418a27Smrg 
visit(ConditionalStatement * s)38581418a27Smrg     void visit(ConditionalStatement *s)
38681418a27Smrg     {
38781418a27Smrg         s->condition->accept(this);
38881418a27Smrg         buf->writenl();
38981418a27Smrg         buf->writeByte('{');
39081418a27Smrg         buf->writenl();
39181418a27Smrg         buf->level++;
39281418a27Smrg         if (s->ifbody)
39381418a27Smrg             s->ifbody->accept(this);
39481418a27Smrg         buf->level--;
39581418a27Smrg         buf->writeByte('}');
39681418a27Smrg         buf->writenl();
39781418a27Smrg         if (s->elsebody)
39881418a27Smrg         {
39981418a27Smrg             buf->writestring("else");
40081418a27Smrg             buf->writenl();
40181418a27Smrg             buf->writeByte('{');
40281418a27Smrg             buf->level++;
40381418a27Smrg             buf->writenl();
40481418a27Smrg             s->elsebody->accept(this);
40581418a27Smrg             buf->level--;
40681418a27Smrg             buf->writeByte('}');
40781418a27Smrg         }
40881418a27Smrg         buf->writenl();
40981418a27Smrg     }
41081418a27Smrg 
visit(PragmaStatement * s)41181418a27Smrg     void visit(PragmaStatement *s)
41281418a27Smrg     {
41381418a27Smrg         buf->writestring("pragma (");
41481418a27Smrg         buf->writestring(s->ident->toChars());
41581418a27Smrg         if (s->args && s->args->dim)
41681418a27Smrg         {
41781418a27Smrg             buf->writestring(", ");
41881418a27Smrg             argsToBuffer(s->args);
41981418a27Smrg         }
42081418a27Smrg         buf->writeByte(')');
42181418a27Smrg         if (s->_body)
42281418a27Smrg         {
42381418a27Smrg             buf->writenl();
42481418a27Smrg             buf->writeByte('{');
42581418a27Smrg             buf->writenl();
42681418a27Smrg             buf->level++;
42781418a27Smrg 
42881418a27Smrg             s->_body->accept(this);
42981418a27Smrg 
43081418a27Smrg             buf->level--;
43181418a27Smrg             buf->writeByte('}');
43281418a27Smrg             buf->writenl();
43381418a27Smrg         }
43481418a27Smrg         else
43581418a27Smrg         {
43681418a27Smrg             buf->writeByte(';');
43781418a27Smrg             buf->writenl();
43881418a27Smrg         }
43981418a27Smrg     }
44081418a27Smrg 
visit(StaticAssertStatement * s)44181418a27Smrg     void visit(StaticAssertStatement *s)
44281418a27Smrg     {
44381418a27Smrg         s->sa->accept(this);
44481418a27Smrg     }
44581418a27Smrg 
visit(SwitchStatement * s)44681418a27Smrg     void visit(SwitchStatement *s)
44781418a27Smrg     {
44881418a27Smrg         buf->writestring(s->isFinal ? "final switch (" : "switch (");
44981418a27Smrg         s->condition->accept(this);
45081418a27Smrg         buf->writeByte(')');
45181418a27Smrg         buf->writenl();
45281418a27Smrg         if (s->_body)
45381418a27Smrg         {
45481418a27Smrg             if (!s->_body->isScopeStatement())
45581418a27Smrg             {
45681418a27Smrg                 buf->writeByte('{');
45781418a27Smrg                 buf->writenl();
45881418a27Smrg                 buf->level++;
45981418a27Smrg                 s->_body->accept(this);
46081418a27Smrg                 buf->level--;
46181418a27Smrg                 buf->writeByte('}');
46281418a27Smrg                 buf->writenl();
46381418a27Smrg             }
46481418a27Smrg             else
46581418a27Smrg             {
46681418a27Smrg                 s->_body->accept(this);
46781418a27Smrg             }
46881418a27Smrg         }
46981418a27Smrg     }
47081418a27Smrg 
visit(CaseStatement * s)47181418a27Smrg     void visit(CaseStatement *s)
47281418a27Smrg     {
47381418a27Smrg         buf->writestring("case ");
47481418a27Smrg         s->exp->accept(this);
47581418a27Smrg         buf->writeByte(':');
47681418a27Smrg         buf->writenl();
47781418a27Smrg         s->statement->accept(this);
47881418a27Smrg     }
47981418a27Smrg 
visit(CaseRangeStatement * s)48081418a27Smrg     void visit(CaseRangeStatement *s)
48181418a27Smrg     {
48281418a27Smrg         buf->writestring("case ");
48381418a27Smrg         s->first->accept(this);
48481418a27Smrg         buf->writestring(": .. case ");
48581418a27Smrg         s->last->accept(this);
48681418a27Smrg         buf->writeByte(':');
48781418a27Smrg         buf->writenl();
48881418a27Smrg         s->statement->accept(this);
48981418a27Smrg     }
49081418a27Smrg 
visit(DefaultStatement * s)49181418a27Smrg     void visit(DefaultStatement *s)
49281418a27Smrg     {
49381418a27Smrg         buf->writestring("default:");
49481418a27Smrg         buf->writenl();
49581418a27Smrg         s->statement->accept(this);
49681418a27Smrg     }
49781418a27Smrg 
visit(GotoDefaultStatement *)49881418a27Smrg     void visit(GotoDefaultStatement *)
49981418a27Smrg     {
50081418a27Smrg         buf->writestring("goto default;");
50181418a27Smrg         buf->writenl();
50281418a27Smrg     }
50381418a27Smrg 
visit(GotoCaseStatement * s)50481418a27Smrg     void visit(GotoCaseStatement *s)
50581418a27Smrg     {
50681418a27Smrg         buf->writestring("goto case");
50781418a27Smrg         if (s->exp)
50881418a27Smrg         {
50981418a27Smrg             buf->writeByte(' ');
51081418a27Smrg             s->exp->accept(this);
51181418a27Smrg         }
51281418a27Smrg         buf->writeByte(';');
51381418a27Smrg         buf->writenl();
51481418a27Smrg     }
51581418a27Smrg 
visit(SwitchErrorStatement *)51681418a27Smrg     void visit(SwitchErrorStatement *)
51781418a27Smrg     {
51881418a27Smrg         buf->writestring("SwitchErrorStatement::toCBuffer()");
51981418a27Smrg         buf->writenl();
52081418a27Smrg     }
52181418a27Smrg 
visit(ReturnStatement * s)52281418a27Smrg     void visit(ReturnStatement *s)
52381418a27Smrg     {
52481418a27Smrg         buf->printf("return ");
52581418a27Smrg         if (s->exp)
52681418a27Smrg             s->exp->accept(this);
52781418a27Smrg         buf->writeByte(';');
52881418a27Smrg         buf->writenl();
52981418a27Smrg     }
53081418a27Smrg 
visit(BreakStatement * s)53181418a27Smrg     void visit(BreakStatement *s)
53281418a27Smrg     {
53381418a27Smrg         buf->writestring("break");
53481418a27Smrg         if (s->ident)
53581418a27Smrg         {
53681418a27Smrg             buf->writeByte(' ');
53781418a27Smrg             buf->writestring(s->ident->toChars());
53881418a27Smrg         }
53981418a27Smrg         buf->writeByte(';');
54081418a27Smrg         buf->writenl();
54181418a27Smrg     }
54281418a27Smrg 
visit(ContinueStatement * s)54381418a27Smrg     void visit(ContinueStatement *s)
54481418a27Smrg     {
54581418a27Smrg         buf->writestring("continue");
54681418a27Smrg         if (s->ident)
54781418a27Smrg         {
54881418a27Smrg             buf->writeByte(' ');
54981418a27Smrg             buf->writestring(s->ident->toChars());
55081418a27Smrg         }
55181418a27Smrg         buf->writeByte(';');
55281418a27Smrg         buf->writenl();
55381418a27Smrg     }
55481418a27Smrg 
visit(SynchronizedStatement * s)55581418a27Smrg     void visit(SynchronizedStatement *s)
55681418a27Smrg     {
55781418a27Smrg         buf->writestring("synchronized");
55881418a27Smrg         if (s->exp)
55981418a27Smrg         {
56081418a27Smrg             buf->writeByte('(');
56181418a27Smrg             s->exp->accept(this);
56281418a27Smrg             buf->writeByte(')');
56381418a27Smrg         }
56481418a27Smrg         if (s->_body)
56581418a27Smrg         {
56681418a27Smrg             buf->writeByte(' ');
56781418a27Smrg             s->_body->accept(this);
56881418a27Smrg         }
56981418a27Smrg     }
57081418a27Smrg 
visit(WithStatement * s)57181418a27Smrg     void visit(WithStatement *s)
57281418a27Smrg     {
57381418a27Smrg         buf->writestring("with (");
57481418a27Smrg         s->exp->accept(this);
57581418a27Smrg         buf->writestring(")");
57681418a27Smrg         buf->writenl();
57781418a27Smrg         if (s->_body)
57881418a27Smrg             s->_body->accept(this);
57981418a27Smrg     }
58081418a27Smrg 
visit(TryCatchStatement * s)58181418a27Smrg     void visit(TryCatchStatement *s)
58281418a27Smrg     {
58381418a27Smrg         buf->writestring("try");
58481418a27Smrg         buf->writenl();
58581418a27Smrg         if (s->_body)
58681418a27Smrg             s->_body->accept(this);
58781418a27Smrg         for (size_t i = 0; i < s->catches->dim; i++)
58881418a27Smrg         {
58981418a27Smrg             Catch *c = (*s->catches)[i];
59081418a27Smrg             visit(c);
59181418a27Smrg         }
59281418a27Smrg     }
59381418a27Smrg 
visit(TryFinallyStatement * s)59481418a27Smrg     void visit(TryFinallyStatement *s)
59581418a27Smrg     {
59681418a27Smrg         buf->writestring("try");
59781418a27Smrg         buf->writenl();
59881418a27Smrg         buf->writeByte('{');
59981418a27Smrg         buf->writenl();
60081418a27Smrg         buf->level++;
60181418a27Smrg         s->_body->accept(this);
60281418a27Smrg         buf->level--;
60381418a27Smrg         buf->writeByte('}');
60481418a27Smrg         buf->writenl();
60581418a27Smrg         buf->writestring("finally");
60681418a27Smrg         buf->writenl();
60781418a27Smrg         if (s->finalbody->isScopeStatement())
60881418a27Smrg         {
60981418a27Smrg             s->finalbody->accept(this);
61081418a27Smrg         }
61181418a27Smrg         else
61281418a27Smrg         {
61381418a27Smrg             buf->level++;
61481418a27Smrg             s->finalbody->accept(this);
61581418a27Smrg             buf->level--;
61681418a27Smrg         }
61781418a27Smrg         buf->writeByte('}');
61881418a27Smrg         buf->writenl();
61981418a27Smrg     }
62081418a27Smrg 
visit(OnScopeStatement * s)62181418a27Smrg     void visit(OnScopeStatement *s)
62281418a27Smrg     {
62381418a27Smrg         buf->writestring(Token::toChars(s->tok));
62481418a27Smrg         buf->writeByte(' ');
62581418a27Smrg         s->statement->accept(this);
62681418a27Smrg     }
62781418a27Smrg 
visit(ThrowStatement * s)62881418a27Smrg     void visit(ThrowStatement *s)
62981418a27Smrg     {
63081418a27Smrg         buf->printf("throw ");
63181418a27Smrg         s->exp->accept(this);
63281418a27Smrg         buf->writeByte(';');
63381418a27Smrg         buf->writenl();
63481418a27Smrg     }
63581418a27Smrg 
visit(DebugStatement * s)63681418a27Smrg     void visit(DebugStatement *s)
63781418a27Smrg     {
63881418a27Smrg         if (s->statement)
63981418a27Smrg         {
64081418a27Smrg             s->statement->accept(this);
64181418a27Smrg         }
64281418a27Smrg     }
64381418a27Smrg 
visit(GotoStatement * s)64481418a27Smrg     void visit(GotoStatement *s)
64581418a27Smrg     {
64681418a27Smrg         buf->writestring("goto ");
64781418a27Smrg         buf->writestring(s->ident->toChars());
64881418a27Smrg         buf->writeByte(';');
64981418a27Smrg         buf->writenl();
65081418a27Smrg     }
65181418a27Smrg 
visit(LabelStatement * s)65281418a27Smrg     void visit(LabelStatement *s)
65381418a27Smrg     {
65481418a27Smrg         buf->writestring(s->ident->toChars());
65581418a27Smrg         buf->writeByte(':');
65681418a27Smrg         buf->writenl();
65781418a27Smrg         if (s->statement)
65881418a27Smrg             s->statement->accept(this);
65981418a27Smrg     }
66081418a27Smrg 
visit(AsmStatement * s)66181418a27Smrg     void visit(AsmStatement *s)
66281418a27Smrg     {
66381418a27Smrg         buf->writestring("asm { ");
66481418a27Smrg         Token *t = s->tokens;
66581418a27Smrg         buf->level++;
66681418a27Smrg         while (t)
66781418a27Smrg         {
66881418a27Smrg             buf->writestring(t->toChars());
66981418a27Smrg             if (t->next &&
67081418a27Smrg                 t->value != TOKmin      &&
67181418a27Smrg                 t->value != TOKcomma    && t->next->value != TOKcomma    &&
67281418a27Smrg                 t->value != TOKlbracket && t->next->value != TOKlbracket &&
67381418a27Smrg                                            t->next->value != TOKrbracket &&
67481418a27Smrg                 t->value != TOKlparen   && t->next->value != TOKlparen   &&
67581418a27Smrg                                            t->next->value != TOKrparen   &&
67681418a27Smrg                 t->value != TOKdot      && t->next->value != TOKdot)
67781418a27Smrg             {
67881418a27Smrg                 buf->writeByte(' ');
67981418a27Smrg             }
68081418a27Smrg             t = t->next;
68181418a27Smrg         }
68281418a27Smrg         buf->level--;
68381418a27Smrg         buf->writestring("; }");
68481418a27Smrg         buf->writenl();
68581418a27Smrg     }
68681418a27Smrg 
visit(ImportStatement * s)68781418a27Smrg     void visit(ImportStatement *s)
68881418a27Smrg     {
68981418a27Smrg         for (size_t i = 0; i < s->imports->dim; i++)
69081418a27Smrg         {
69181418a27Smrg             Dsymbol *imp = (*s->imports)[i];
69281418a27Smrg             imp->accept(this);
69381418a27Smrg         }
69481418a27Smrg     }
69581418a27Smrg 
visit(Catch * c)69681418a27Smrg     void visit(Catch *c)
69781418a27Smrg     {
69881418a27Smrg         buf->writestring("catch");
69981418a27Smrg         if (c->type)
70081418a27Smrg         {
70181418a27Smrg             buf->writeByte('(');
70281418a27Smrg             typeToBuffer(c->type, c->ident);
70381418a27Smrg             buf->writeByte(')');
70481418a27Smrg         }
70581418a27Smrg         buf->writenl();
70681418a27Smrg         buf->writeByte('{');
70781418a27Smrg         buf->writenl();
70881418a27Smrg         buf->level++;
70981418a27Smrg         if (c->handler)
71081418a27Smrg             c->handler->accept(this);
71181418a27Smrg         buf->level--;
71281418a27Smrg         buf->writeByte('}');
71381418a27Smrg         buf->writenl();
71481418a27Smrg     }
71581418a27Smrg 
71681418a27Smrg     ////////////////////////////////////////////////////////////////////////////
71781418a27Smrg 
71881418a27Smrg     /**************************************************
71981418a27Smrg      * An entry point to pretty-print type.
72081418a27Smrg      */
typeToBuffer(Type * t,Identifier * ident)72181418a27Smrg     void typeToBuffer(Type *t, Identifier *ident)
72281418a27Smrg     {
72381418a27Smrg         if (t->ty == Tfunction)
72481418a27Smrg         {
72581418a27Smrg             visitFuncIdentWithPrefix((TypeFunction *)t, ident, NULL);
72681418a27Smrg             return;
72781418a27Smrg         }
72881418a27Smrg 
72981418a27Smrg         visitWithMask(t, 0);
73081418a27Smrg 
73181418a27Smrg         if (ident)
73281418a27Smrg         {
73381418a27Smrg             buf->writeByte(' ');
73481418a27Smrg             buf->writestring(ident->toChars());
73581418a27Smrg         }
73681418a27Smrg     }
73781418a27Smrg 
visitWithMask(Type * t,unsigned char modMask)73881418a27Smrg     void visitWithMask(Type *t, unsigned char modMask)
73981418a27Smrg     {
74081418a27Smrg         // Tuples and functions don't use the type constructor syntax
74181418a27Smrg         if (modMask == t->mod ||
74281418a27Smrg             t->ty == Tfunction ||
74381418a27Smrg             t->ty == Ttuple)
74481418a27Smrg         {
74581418a27Smrg             t->accept(this);
74681418a27Smrg         }
74781418a27Smrg         else
74881418a27Smrg         {
74981418a27Smrg             unsigned char m = t->mod & ~(t->mod & modMask);
75081418a27Smrg             if (m & MODshared)
75181418a27Smrg             {
75281418a27Smrg                 MODtoBuffer(buf, MODshared);
75381418a27Smrg                 buf->writeByte('(');
75481418a27Smrg             }
75581418a27Smrg             if (m & MODwild)
75681418a27Smrg             {
75781418a27Smrg                 MODtoBuffer(buf, MODwild);
75881418a27Smrg                 buf->writeByte('(');
75981418a27Smrg             }
76081418a27Smrg             if (m & (MODconst | MODimmutable))
76181418a27Smrg             {
76281418a27Smrg                 MODtoBuffer(buf, m & (MODconst | MODimmutable));
76381418a27Smrg                 buf->writeByte('(');
76481418a27Smrg             }
76581418a27Smrg 
76681418a27Smrg             t->accept(this);
76781418a27Smrg 
76881418a27Smrg             if (m & (MODconst | MODimmutable))
76981418a27Smrg                 buf->writeByte(')');
77081418a27Smrg             if (m & MODwild)
77181418a27Smrg                 buf->writeByte(')');
77281418a27Smrg             if (m & MODshared)
77381418a27Smrg                 buf->writeByte(')');
77481418a27Smrg         }
77581418a27Smrg     }
77681418a27Smrg 
visit(Type * t)77781418a27Smrg     void visit(Type *t)
77881418a27Smrg     {
77981418a27Smrg         printf("t = %p, ty = %d\n", t, t->ty);
78081418a27Smrg         assert(0);
78181418a27Smrg     }
78281418a27Smrg 
visit(TypeError *)78381418a27Smrg     void visit(TypeError *)
78481418a27Smrg     {
78581418a27Smrg         buf->writestring("_error_");
78681418a27Smrg     }
78781418a27Smrg 
visit(TypeBasic * t)78881418a27Smrg     void visit(TypeBasic *t)
78981418a27Smrg     {
79081418a27Smrg         //printf("TypeBasic::toCBuffer2(t->mod = %d)\n", t->mod);
79181418a27Smrg         buf->writestring(t->dstring);
79281418a27Smrg     }
79381418a27Smrg 
visit(TypeTraits * t)794*dd083157Smrg     void visit(TypeTraits *t)
795*dd083157Smrg     {
796*dd083157Smrg         //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
797*dd083157Smrg         t->exp->accept(this);
798*dd083157Smrg     }
799*dd083157Smrg 
visit(TypeVector * t)80081418a27Smrg     void visit(TypeVector *t)
80181418a27Smrg     {
80281418a27Smrg         //printf("TypeVector::toCBuffer2(t->mod = %d)\n", t->mod);
80381418a27Smrg         buf->writestring("__vector(");
80481418a27Smrg         visitWithMask(t->basetype, t->mod);
80581418a27Smrg         buf->writestring(")");
80681418a27Smrg     }
80781418a27Smrg 
visit(TypeSArray * t)80881418a27Smrg     void visit(TypeSArray *t)
80981418a27Smrg     {
81081418a27Smrg         visitWithMask(t->next, t->mod);
81181418a27Smrg         buf->writeByte('[');
81281418a27Smrg         sizeToBuffer(t->dim);
81381418a27Smrg         buf->writeByte(']');
81481418a27Smrg     }
81581418a27Smrg 
visit(TypeDArray * t)81681418a27Smrg     void visit(TypeDArray *t)
81781418a27Smrg     {
81881418a27Smrg         Type *ut = t->castMod(0);
81981418a27Smrg         if (declstring)
82081418a27Smrg             goto L1;
82181418a27Smrg         if (ut->equals(Type::tstring))
82281418a27Smrg             buf->writestring("string");
82381418a27Smrg         else if (ut->equals(Type::twstring))
82481418a27Smrg             buf->writestring("wstring");
82581418a27Smrg         else if (ut->equals(Type::tdstring))
82681418a27Smrg             buf->writestring("dstring");
82781418a27Smrg         else
82881418a27Smrg         {
82981418a27Smrg         L1:
83081418a27Smrg             visitWithMask(t->next, t->mod);
83181418a27Smrg             buf->writestring("[]");
83281418a27Smrg         }
83381418a27Smrg     }
83481418a27Smrg 
visit(TypeAArray * t)83581418a27Smrg     void visit(TypeAArray *t)
83681418a27Smrg     {
83781418a27Smrg         visitWithMask(t->next, t->mod);
83881418a27Smrg         buf->writeByte('[');
83981418a27Smrg         visitWithMask(t->index, 0);
84081418a27Smrg         buf->writeByte(']');
84181418a27Smrg     }
84281418a27Smrg 
visit(TypePointer * t)84381418a27Smrg     void visit(TypePointer *t)
84481418a27Smrg     {
84581418a27Smrg         //printf("TypePointer::toCBuffer2() next = %d\n", t->next->ty);
84681418a27Smrg         if (t->next->ty == Tfunction)
84781418a27Smrg             visitFuncIdentWithPostfix((TypeFunction *)t->next, "function");
84881418a27Smrg         else
84981418a27Smrg         {
85081418a27Smrg             visitWithMask(t->next, t->mod);
85181418a27Smrg             buf->writeByte('*');
85281418a27Smrg         }
85381418a27Smrg     }
85481418a27Smrg 
visit(TypeReference * t)85581418a27Smrg     void visit(TypeReference *t)
85681418a27Smrg     {
85781418a27Smrg         visitWithMask(t->next, t->mod);
85881418a27Smrg         buf->writeByte('&');
85981418a27Smrg     }
86081418a27Smrg 
visit(TypeFunction * t)86181418a27Smrg     void visit(TypeFunction *t)
86281418a27Smrg     {
86381418a27Smrg         //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t->isref);
86481418a27Smrg         visitFuncIdentWithPostfix(t, NULL);
86581418a27Smrg     }
86681418a27Smrg 
86781418a27Smrg     // callback for TypeFunction::attributesApply
86881418a27Smrg     struct PrePostAppendStrings
86981418a27Smrg     {
87081418a27Smrg         OutBuffer *buf;
87181418a27Smrg         bool isPostfixStyle;
87281418a27Smrg         bool isCtor;
87381418a27Smrg 
fpPrePostAppendStrings87481418a27Smrg         static int fp(void *param, const char *str)
87581418a27Smrg         {
87681418a27Smrg             PrePostAppendStrings *p = (PrePostAppendStrings *)param;
87781418a27Smrg 
87881418a27Smrg             // don't write 'ref' for ctors
87981418a27Smrg             if (p->isCtor && strcmp(str, "ref") == 0)
88081418a27Smrg                 return 0;
88181418a27Smrg 
88281418a27Smrg             if ( p->isPostfixStyle) p->buf->writeByte(' ');
88381418a27Smrg             p->buf->writestring(str);
88481418a27Smrg             if (!p->isPostfixStyle) p->buf->writeByte(' ');
88581418a27Smrg             return 0;
88681418a27Smrg         }
88781418a27Smrg     };
88881418a27Smrg 
visitFuncIdentWithPostfix(TypeFunction * t,const char * ident)88981418a27Smrg     void visitFuncIdentWithPostfix(TypeFunction *t, const char *ident)
89081418a27Smrg     {
89181418a27Smrg         if (t->inuse)
89281418a27Smrg         {
89381418a27Smrg             t->inuse = 2;              // flag error to caller
89481418a27Smrg             return;
89581418a27Smrg         }
89681418a27Smrg         t->inuse++;
89781418a27Smrg 
89881418a27Smrg         PrePostAppendStrings pas;
89981418a27Smrg         pas.buf = buf;
90081418a27Smrg         pas.isCtor = false;
90181418a27Smrg         pas.isPostfixStyle = true;
90281418a27Smrg 
90381418a27Smrg         if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen)
90481418a27Smrg         {
90581418a27Smrg             linkageToBuffer(buf, t->linkage);
90681418a27Smrg             buf->writeByte(' ');
90781418a27Smrg         }
90881418a27Smrg 
90981418a27Smrg         if (t->next)
91081418a27Smrg         {
91181418a27Smrg             typeToBuffer(t->next, NULL);
91281418a27Smrg             if (ident)
91381418a27Smrg                 buf->writeByte(' ');
91481418a27Smrg         }
91581418a27Smrg         else if (hgs->ddoc)
91681418a27Smrg             buf->writestring("auto ");
91781418a27Smrg 
91881418a27Smrg         if (ident)
91981418a27Smrg             buf->writestring(ident);
92081418a27Smrg 
92181418a27Smrg         parametersToBuffer(t->parameters, t->varargs);
92281418a27Smrg 
92381418a27Smrg         /* Use postfix style for attributes
92481418a27Smrg          */
92581418a27Smrg         if (t->mod)
92681418a27Smrg         {
92781418a27Smrg             buf->writeByte(' ');
92881418a27Smrg             MODtoBuffer(buf, t->mod);
92981418a27Smrg         }
93081418a27Smrg         t->attributesApply(&pas, &PrePostAppendStrings::fp);
93181418a27Smrg 
93281418a27Smrg         t->inuse--;
93381418a27Smrg     }
visitFuncIdentWithPrefix(TypeFunction * t,Identifier * ident,TemplateDeclaration * td)93481418a27Smrg     void visitFuncIdentWithPrefix(TypeFunction *t, Identifier *ident, TemplateDeclaration *td)
93581418a27Smrg     {
93681418a27Smrg         if (t->inuse)
93781418a27Smrg         {
93881418a27Smrg             t->inuse = 2;              // flag error to caller
93981418a27Smrg             return;
94081418a27Smrg         }
94181418a27Smrg         t->inuse++;
94281418a27Smrg 
94381418a27Smrg         PrePostAppendStrings pas;
94481418a27Smrg         pas.buf = buf;
94581418a27Smrg         pas.isCtor = (ident == Id::ctor);
94681418a27Smrg         pas.isPostfixStyle = false;
94781418a27Smrg 
94881418a27Smrg         /* Use 'storage class' (prefix) style for attributes
94981418a27Smrg          */
95081418a27Smrg         if (t->mod)
95181418a27Smrg         {
95281418a27Smrg             MODtoBuffer(buf, t->mod);
95381418a27Smrg             buf->writeByte(' ');
95481418a27Smrg         }
95581418a27Smrg         t->attributesApply(&pas, &PrePostAppendStrings::fp);
95681418a27Smrg 
95781418a27Smrg         if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen)
95881418a27Smrg         {
95981418a27Smrg             linkageToBuffer(buf, t->linkage);
96081418a27Smrg             buf->writeByte(' ');
96181418a27Smrg         }
96281418a27Smrg 
96381418a27Smrg         if (ident && ident->toHChars2() != ident->toChars())
96481418a27Smrg         {
96581418a27Smrg             // Don't print return type for ctor, dtor, unittest, etc
96681418a27Smrg         }
96781418a27Smrg         else if (t->next)
96881418a27Smrg         {
96981418a27Smrg             typeToBuffer(t->next, NULL);
97081418a27Smrg             if (ident)
97181418a27Smrg                 buf->writeByte(' ');
97281418a27Smrg         }
97381418a27Smrg         else if (hgs->ddoc)
97481418a27Smrg             buf->writestring("auto ");
97581418a27Smrg 
97681418a27Smrg         if (ident)
97781418a27Smrg             buf->writestring(ident->toHChars2());
97881418a27Smrg 
97981418a27Smrg         if (td)
98081418a27Smrg         {
98181418a27Smrg             buf->writeByte('(');
98281418a27Smrg             for (size_t i = 0; i < td->origParameters->dim; i++)
98381418a27Smrg             {
98481418a27Smrg                 TemplateParameter *p = (*td->origParameters)[i];
98581418a27Smrg                 if (i)
98681418a27Smrg                     buf->writestring(", ");
98781418a27Smrg                 p->accept(this);
98881418a27Smrg             }
98981418a27Smrg             buf->writeByte(')');
99081418a27Smrg         }
99181418a27Smrg         parametersToBuffer(t->parameters, t->varargs);
99281418a27Smrg 
99381418a27Smrg         t->inuse--;
99481418a27Smrg     }
99581418a27Smrg 
visit(TypeDelegate * t)99681418a27Smrg     void visit(TypeDelegate *t)
99781418a27Smrg     {
99881418a27Smrg         visitFuncIdentWithPostfix((TypeFunction *)t->next, "delegate");
99981418a27Smrg     }
100081418a27Smrg 
visitTypeQualifiedHelper(TypeQualified * t)100181418a27Smrg     void visitTypeQualifiedHelper(TypeQualified *t)
100281418a27Smrg     {
100381418a27Smrg         for (size_t i = 0; i < t->idents.dim; i++)
100481418a27Smrg         {
100581418a27Smrg             RootObject *id = t->idents[i];
100681418a27Smrg 
100781418a27Smrg             if (id->dyncast() == DYNCAST_DSYMBOL)
100881418a27Smrg             {
100981418a27Smrg                 buf->writeByte('.');
101081418a27Smrg                 TemplateInstance *ti = (TemplateInstance *)id;
101181418a27Smrg                 ti->accept(this);
101281418a27Smrg             }
101381418a27Smrg             else if (id->dyncast() == DYNCAST_EXPRESSION)
101481418a27Smrg             {
101581418a27Smrg                 buf->writeByte('[');
101681418a27Smrg                 ((Expression *)id)->accept(this);
101781418a27Smrg                 buf->writeByte(']');
101881418a27Smrg             }
101981418a27Smrg             else if (id->dyncast() == DYNCAST_TYPE)
102081418a27Smrg             {
102181418a27Smrg                 buf->writeByte('[');
102281418a27Smrg                 ((Type *)id)->accept(this);
102381418a27Smrg                 buf->writeByte(']');
102481418a27Smrg             }
102581418a27Smrg             else
102681418a27Smrg             {
102781418a27Smrg                 buf->writeByte('.');
102881418a27Smrg                 buf->writestring(id->toChars());
102981418a27Smrg             }
103081418a27Smrg         }
103181418a27Smrg     }
103281418a27Smrg 
visit(TypeIdentifier * t)103381418a27Smrg     void visit(TypeIdentifier *t)
103481418a27Smrg     {
103581418a27Smrg         buf->writestring(t->ident->toChars());
103681418a27Smrg         visitTypeQualifiedHelper(t);
103781418a27Smrg     }
103881418a27Smrg 
visit(TypeInstance * t)103981418a27Smrg     void visit(TypeInstance *t)
104081418a27Smrg     {
104181418a27Smrg         t->tempinst->accept(this);
104281418a27Smrg         visitTypeQualifiedHelper(t);
104381418a27Smrg     }
104481418a27Smrg 
visit(TypeTypeof * t)104581418a27Smrg     void visit(TypeTypeof *t)
104681418a27Smrg     {
104781418a27Smrg         buf->writestring("typeof(");
104881418a27Smrg         t->exp->accept(this);
104981418a27Smrg         buf->writeByte(')');
105081418a27Smrg         visitTypeQualifiedHelper(t);
105181418a27Smrg     }
105281418a27Smrg 
visit(TypeReturn * t)105381418a27Smrg     void visit(TypeReturn *t)
105481418a27Smrg     {
105581418a27Smrg         buf->writestring("typeof(return)");
105681418a27Smrg         visitTypeQualifiedHelper(t);
105781418a27Smrg     }
105881418a27Smrg 
visit(TypeEnum * t)105981418a27Smrg     void visit(TypeEnum *t)
106081418a27Smrg     {
106181418a27Smrg         buf->writestring(t->sym->toChars());
106281418a27Smrg     }
106381418a27Smrg 
visit(TypeStruct * t)106481418a27Smrg     void visit(TypeStruct *t)
106581418a27Smrg     {
106681418a27Smrg         // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error
106781418a27Smrg         // while printing messages.
106881418a27Smrg         TemplateInstance *ti = t->sym->parent ? t->sym->parent->isTemplateInstance() : NULL;
106981418a27Smrg         if (ti && ti->aliasdecl == t->sym)
107081418a27Smrg             buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars());
107181418a27Smrg         else
107281418a27Smrg             buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars());
107381418a27Smrg     }
107481418a27Smrg 
visit(TypeClass * t)107581418a27Smrg     void visit(TypeClass *t)
107681418a27Smrg     {
107781418a27Smrg         // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error
107881418a27Smrg         // while printing messages.
107981418a27Smrg         TemplateInstance *ti = t->sym->parent->isTemplateInstance();
108081418a27Smrg         if (ti && ti->aliasdecl == t->sym)
108181418a27Smrg             buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars());
108281418a27Smrg         else
108381418a27Smrg             buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars());
108481418a27Smrg     }
108581418a27Smrg 
visit(TypeTuple * t)108681418a27Smrg     void visit(TypeTuple *t)
108781418a27Smrg     {
108881418a27Smrg         parametersToBuffer(t->arguments, 0);
108981418a27Smrg     }
109081418a27Smrg 
visit(TypeSlice * t)109181418a27Smrg     void visit(TypeSlice *t)
109281418a27Smrg     {
109381418a27Smrg         visitWithMask(t->next, t->mod);
109481418a27Smrg 
109581418a27Smrg         buf->writeByte('[');
109681418a27Smrg         sizeToBuffer(t->lwr);
109781418a27Smrg         buf->writestring(" .. ");
109881418a27Smrg         sizeToBuffer(t->upr);
109981418a27Smrg         buf->writeByte(']');
110081418a27Smrg     }
110181418a27Smrg 
visit(TypeNull *)110281418a27Smrg     void visit(TypeNull *)
110381418a27Smrg     {
110481418a27Smrg         buf->writestring("typeof(null)");
110581418a27Smrg     }
110681418a27Smrg 
110781418a27Smrg     ////////////////////////////////////////////////////////////////////////////
110881418a27Smrg 
visit(Dsymbol * s)110981418a27Smrg     void visit(Dsymbol *s)
111081418a27Smrg     {
111181418a27Smrg         buf->writestring(s->toChars());
111281418a27Smrg     }
111381418a27Smrg 
visit(StaticAssert * s)111481418a27Smrg     void visit(StaticAssert *s)
111581418a27Smrg     {
111681418a27Smrg         buf->writestring(s->kind());
111781418a27Smrg         buf->writeByte('(');
111881418a27Smrg         s->exp->accept(this);
111981418a27Smrg         if (s->msg)
112081418a27Smrg         {
112181418a27Smrg             buf->writestring(", ");
112281418a27Smrg             s->msg->accept(this);
112381418a27Smrg         }
112481418a27Smrg         buf->writestring(");");
112581418a27Smrg         buf->writenl();
112681418a27Smrg     }
112781418a27Smrg 
visit(DebugSymbol * s)112881418a27Smrg     void visit(DebugSymbol *s)
112981418a27Smrg     {
113081418a27Smrg         buf->writestring("debug = ");
113181418a27Smrg         if (s->ident)
113281418a27Smrg             buf->writestring(s->ident->toChars());
113381418a27Smrg         else
113481418a27Smrg             buf->printf("%u", s->level);
113581418a27Smrg         buf->writestring(";");
113681418a27Smrg         buf->writenl();
113781418a27Smrg     }
113881418a27Smrg 
visit(VersionSymbol * s)113981418a27Smrg     void visit(VersionSymbol *s)
114081418a27Smrg     {
114181418a27Smrg         buf->writestring("version = ");
114281418a27Smrg         if (s->ident)
114381418a27Smrg             buf->writestring(s->ident->toChars());
114481418a27Smrg         else
114581418a27Smrg             buf->printf("%u", s->level);
114681418a27Smrg         buf->writestring(";");
114781418a27Smrg         buf->writenl();
114881418a27Smrg     }
114981418a27Smrg 
visit(EnumMember * em)115081418a27Smrg     void visit(EnumMember *em)
115181418a27Smrg     {
115281418a27Smrg         if (em->type)
115381418a27Smrg             typeToBuffer(em->type, em->ident);
115481418a27Smrg         else
115581418a27Smrg             buf->writestring(em->ident->toChars());
115681418a27Smrg         if (em->value())
115781418a27Smrg         {
115881418a27Smrg             buf->writestring(" = ");
115981418a27Smrg             em->value()->accept(this);
116081418a27Smrg         }
116181418a27Smrg     }
116281418a27Smrg 
visit(Import * imp)116381418a27Smrg     void visit(Import *imp)
116481418a27Smrg     {
116581418a27Smrg         if (hgs->hdrgen && imp->id == Id::object)
116681418a27Smrg             return;         // object is imported by default
116781418a27Smrg 
116881418a27Smrg         if (imp->isstatic)
116981418a27Smrg             buf->writestring("static ");
117081418a27Smrg         buf->writestring("import ");
117181418a27Smrg         if (imp->aliasId)
117281418a27Smrg         {
117381418a27Smrg             buf->printf("%s = ", imp->aliasId->toChars());
117481418a27Smrg         }
117581418a27Smrg         if (imp->packages && imp->packages->dim)
117681418a27Smrg         {
117781418a27Smrg             for (size_t i = 0; i < imp->packages->dim; i++)
117881418a27Smrg             {
117981418a27Smrg                 Identifier *pid = (*imp->packages)[i];
118081418a27Smrg                 buf->printf("%s.", pid->toChars());
118181418a27Smrg             }
118281418a27Smrg         }
118381418a27Smrg         buf->printf("%s", imp->id->toChars());
118481418a27Smrg         if (imp->names.dim)
118581418a27Smrg         {
118681418a27Smrg             buf->writestring(" : ");
118781418a27Smrg             for (size_t i = 0; i < imp->names.dim; i++)
118881418a27Smrg             {
118981418a27Smrg                 if (i)
119081418a27Smrg                     buf->writestring(", ");
119181418a27Smrg 
119281418a27Smrg                 Identifier *name = imp->names[i];
119381418a27Smrg                 Identifier *alias = imp->aliases[i];
119481418a27Smrg                 if (alias)
119581418a27Smrg                     buf->printf("%s = %s", alias->toChars(), name->toChars());
119681418a27Smrg                 else
119781418a27Smrg                     buf->printf("%s", name->toChars());
119881418a27Smrg             }
119981418a27Smrg         }
120081418a27Smrg         buf->printf(";");
120181418a27Smrg         buf->writenl();
120281418a27Smrg     }
120381418a27Smrg 
visit(AliasThis * d)120481418a27Smrg     void visit(AliasThis *d)
120581418a27Smrg     {
120681418a27Smrg         buf->writestring("alias ");
120781418a27Smrg         buf->writestring(d->ident->toChars());
120881418a27Smrg         buf->writestring(" this;\n");
120981418a27Smrg     }
121081418a27Smrg 
visit(AttribDeclaration * d)121181418a27Smrg     void visit(AttribDeclaration *d)
121281418a27Smrg     {
121381418a27Smrg         if (!d->decl)
121481418a27Smrg         {
121581418a27Smrg             buf->writeByte(';');
121681418a27Smrg             buf->writenl();
121781418a27Smrg             return;
121881418a27Smrg         }
121981418a27Smrg 
122081418a27Smrg         if (d->decl->dim == 0)
122181418a27Smrg             buf->writestring("{}");
122281418a27Smrg         else if (hgs->hdrgen && d->decl->dim == 1 && (*d->decl)[0]->isUnitTestDeclaration())
122381418a27Smrg         {
122481418a27Smrg             // hack for bugzilla 8081
122581418a27Smrg             buf->writestring("{}");
122681418a27Smrg         }
122781418a27Smrg         else if (d->decl->dim == 1)
122881418a27Smrg         {
122981418a27Smrg             ((*d->decl)[0])->accept(this);
123081418a27Smrg             return;
123181418a27Smrg         }
123281418a27Smrg         else
123381418a27Smrg         {
123481418a27Smrg             buf->writenl();
123581418a27Smrg             buf->writeByte('{');
123681418a27Smrg             buf->writenl();
123781418a27Smrg             buf->level++;
123881418a27Smrg             for (size_t i = 0; i < d->decl->dim; i++)
123981418a27Smrg             {
124081418a27Smrg                 Dsymbol *de = (*d->decl)[i];
124181418a27Smrg                 de->accept(this);
124281418a27Smrg             }
124381418a27Smrg             buf->level--;
124481418a27Smrg             buf->writeByte('}');
124581418a27Smrg         }
124681418a27Smrg         buf->writenl();
124781418a27Smrg     }
124881418a27Smrg 
visit(StorageClassDeclaration * d)124981418a27Smrg     void visit(StorageClassDeclaration *d)
125081418a27Smrg     {
125181418a27Smrg         if (stcToBuffer(buf, d->stc))
125281418a27Smrg             buf->writeByte(' ');
125381418a27Smrg         visit((AttribDeclaration *)d);
125481418a27Smrg     }
125581418a27Smrg 
visit(DeprecatedDeclaration * d)125681418a27Smrg     void visit(DeprecatedDeclaration *d)
125781418a27Smrg     {
125881418a27Smrg         buf->writestring("deprecated(");
125981418a27Smrg         d->msg->accept(this);
126081418a27Smrg         buf->writestring(") ");
126181418a27Smrg         visit((AttribDeclaration *)d);
126281418a27Smrg     }
126381418a27Smrg 
visit(LinkDeclaration * d)126481418a27Smrg     void visit(LinkDeclaration *d)
126581418a27Smrg     {
126681418a27Smrg         const char *p;
126781418a27Smrg 
126881418a27Smrg         switch (d->linkage)
126981418a27Smrg         {
127081418a27Smrg             case LINKd:             p = "D";                break;
127181418a27Smrg             case LINKc:             p = "C";                break;
127281418a27Smrg             case LINKcpp:           p = "C++";              break;
127381418a27Smrg             case LINKwindows:       p = "Windows";          break;
127481418a27Smrg             case LINKpascal:        p = "Pascal";           break;
127581418a27Smrg             case LINKobjc:          p = "Objective-C";      break;
127681418a27Smrg             default:
127781418a27Smrg                 assert(0);
127881418a27Smrg                 break;
127981418a27Smrg         }
128081418a27Smrg         buf->writestring("extern (");
128181418a27Smrg         buf->writestring(p);
128281418a27Smrg         buf->writestring(") ");
128381418a27Smrg         visit((AttribDeclaration *)d);
128481418a27Smrg     }
128581418a27Smrg 
visit(CPPMangleDeclaration * d)128681418a27Smrg     void visit(CPPMangleDeclaration *d)
128781418a27Smrg     {
128881418a27Smrg         const char *p;
128981418a27Smrg 
129081418a27Smrg         switch (d->cppmangle)
129181418a27Smrg         {
129281418a27Smrg             case CPPMANGLEclass:    p = "class";            break;
129381418a27Smrg             case CPPMANGLEstruct:   p = "struct";           break;
129481418a27Smrg             default:
129581418a27Smrg                 assert(0);
129681418a27Smrg                 break;
129781418a27Smrg         }
129881418a27Smrg         buf->writestring("extern (C++, ");
129981418a27Smrg         buf->writestring(p);
130081418a27Smrg         buf->writestring(") ");
130181418a27Smrg         visit((AttribDeclaration *)d);
130281418a27Smrg     }
130381418a27Smrg 
visit(ProtDeclaration * d)130481418a27Smrg     void visit(ProtDeclaration *d)
130581418a27Smrg     {
130681418a27Smrg         protectionToBuffer(buf, d->protection);
130781418a27Smrg         buf->writeByte(' ');
130881418a27Smrg         visit((AttribDeclaration *)d);
130981418a27Smrg     }
131081418a27Smrg 
visit(AlignDeclaration * d)131181418a27Smrg     void visit(AlignDeclaration *d)
131281418a27Smrg     {
131381418a27Smrg         if (!d->ealign)
131481418a27Smrg             buf->printf("align ");
131581418a27Smrg         else
131681418a27Smrg             buf->printf("align (%s)", d->ealign->toChars());
131781418a27Smrg         visit((AttribDeclaration *)d);
131881418a27Smrg     }
131981418a27Smrg 
visit(AnonDeclaration * d)132081418a27Smrg     void visit(AnonDeclaration *d)
132181418a27Smrg     {
132281418a27Smrg         buf->printf(d->isunion ? "union" : "struct");
132381418a27Smrg         buf->writenl();
132481418a27Smrg         buf->writestring("{");
132581418a27Smrg         buf->writenl();
132681418a27Smrg         buf->level++;
132781418a27Smrg         if (d->decl)
132881418a27Smrg         {
132981418a27Smrg             for (size_t i = 0; i < d->decl->dim; i++)
133081418a27Smrg             {
133181418a27Smrg                 Dsymbol *de = (*d->decl)[i];
133281418a27Smrg                 de->accept(this);
133381418a27Smrg             }
133481418a27Smrg         }
133581418a27Smrg         buf->level--;
133681418a27Smrg         buf->writestring("}");
133781418a27Smrg         buf->writenl();
133881418a27Smrg     }
133981418a27Smrg 
visit(PragmaDeclaration * d)134081418a27Smrg     void visit(PragmaDeclaration *d)
134181418a27Smrg     {
134281418a27Smrg         buf->printf("pragma (%s", d->ident->toChars());
134381418a27Smrg         if (d->args && d->args->dim)
134481418a27Smrg         {
134581418a27Smrg             buf->writestring(", ");
134681418a27Smrg             argsToBuffer(d->args);
134781418a27Smrg         }
134881418a27Smrg         buf->writeByte(')');
134981418a27Smrg         visit((AttribDeclaration *)d);
135081418a27Smrg     }
135181418a27Smrg 
visit(ConditionalDeclaration * d)135281418a27Smrg     void visit(ConditionalDeclaration *d)
135381418a27Smrg     {
135481418a27Smrg         d->condition->accept(this);
135581418a27Smrg         if (d->decl || d->elsedecl)
135681418a27Smrg         {
135781418a27Smrg             buf->writenl();
135881418a27Smrg             buf->writeByte('{');
135981418a27Smrg             buf->writenl();
136081418a27Smrg             buf->level++;
136181418a27Smrg             if (d->decl)
136281418a27Smrg             {
136381418a27Smrg                 for (size_t i = 0; i < d->decl->dim; i++)
136481418a27Smrg                 {
136581418a27Smrg                     Dsymbol *de = (*d->decl)[i];
136681418a27Smrg                     de->accept(this);
136781418a27Smrg                 }
136881418a27Smrg             }
136981418a27Smrg             buf->level--;
137081418a27Smrg             buf->writeByte('}');
137181418a27Smrg             if (d->elsedecl)
137281418a27Smrg             {
137381418a27Smrg                 buf->writenl();
137481418a27Smrg                 buf->writestring("else");
137581418a27Smrg                 buf->writenl();
137681418a27Smrg                 buf->writeByte('{');
137781418a27Smrg                 buf->writenl();
137881418a27Smrg                 buf->level++;
137981418a27Smrg                 for (size_t i = 0; i < d->elsedecl->dim; i++)
138081418a27Smrg                 {
138181418a27Smrg                     Dsymbol *de = (*d->elsedecl)[i];
138281418a27Smrg                     de->accept(this);
138381418a27Smrg                 }
138481418a27Smrg                 buf->level--;
138581418a27Smrg                 buf->writeByte('}');
138681418a27Smrg             }
138781418a27Smrg         }
138881418a27Smrg         else
138981418a27Smrg             buf->writeByte(':');
139081418a27Smrg         buf->writenl();
139181418a27Smrg     }
139281418a27Smrg 
visit(ForwardingStatement * s)1393*dd083157Smrg     void visit(ForwardingStatement *s)
1394*dd083157Smrg     {
1395*dd083157Smrg         s->statement->accept(this);
1396*dd083157Smrg     }
1397*dd083157Smrg 
visit(StaticForeachDeclaration * s)1398*dd083157Smrg     void visit(StaticForeachDeclaration *s)
1399*dd083157Smrg     {
1400*dd083157Smrg         buf->writestring("static ");
1401*dd083157Smrg         if (s->sfe->aggrfe)
1402*dd083157Smrg         {
1403*dd083157Smrg             foreachWithoutBody(s->sfe->aggrfe);
1404*dd083157Smrg         }
1405*dd083157Smrg         else
1406*dd083157Smrg         {
1407*dd083157Smrg             assert(s->sfe->rangefe);
1408*dd083157Smrg             foreachRangeWithoutBody(s->sfe->rangefe);
1409*dd083157Smrg         }
1410*dd083157Smrg         buf->writeByte('{');
1411*dd083157Smrg         buf->writenl();
1412*dd083157Smrg         buf->level++;
1413*dd083157Smrg         visit((AttribDeclaration *)s);
1414*dd083157Smrg         buf->level--;
1415*dd083157Smrg         buf->writeByte('}');
1416*dd083157Smrg         buf->writenl();
1417*dd083157Smrg     }
1418*dd083157Smrg 
visit(CompileDeclaration * d)141981418a27Smrg     void visit(CompileDeclaration *d)
142081418a27Smrg     {
142181418a27Smrg         buf->writestring("mixin(");
142281418a27Smrg         d->exp->accept(this);
142381418a27Smrg         buf->writestring(");");
142481418a27Smrg         buf->writenl();
142581418a27Smrg     }
142681418a27Smrg 
visit(UserAttributeDeclaration * d)142781418a27Smrg     void visit(UserAttributeDeclaration *d)
142881418a27Smrg     {
142981418a27Smrg         buf->writestring("@(");
143081418a27Smrg         argsToBuffer(d->atts);
143181418a27Smrg         buf->writeByte(')');
143281418a27Smrg         visit((AttribDeclaration *)d);
143381418a27Smrg     }
143481418a27Smrg 
visit(TemplateDeclaration * d)143581418a27Smrg     void visit(TemplateDeclaration *d)
143681418a27Smrg     {
143781418a27Smrg         if ((hgs->hdrgen || hgs->fullDump) && visitEponymousMember(d))
143881418a27Smrg             return;
143981418a27Smrg 
144081418a27Smrg         if (hgs->ddoc)
144181418a27Smrg             buf->writestring(d->kind());
144281418a27Smrg         else
144381418a27Smrg             buf->writestring("template");
144481418a27Smrg         buf->writeByte(' ');
144581418a27Smrg         buf->writestring(d->ident->toChars());
144681418a27Smrg         buf->writeByte('(');
144781418a27Smrg         visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
144881418a27Smrg         buf->writeByte(')');
144981418a27Smrg         visitTemplateConstraint(d->constraint);
145081418a27Smrg 
145181418a27Smrg         if (hgs->hdrgen || hgs->fullDump)
145281418a27Smrg         {
145381418a27Smrg             hgs->tpltMember++;
145481418a27Smrg             buf->writenl();
145581418a27Smrg             buf->writeByte('{');
145681418a27Smrg             buf->writenl();
145781418a27Smrg             buf->level++;
145881418a27Smrg             for (size_t i = 0; i < d->members->dim; i++)
145981418a27Smrg             {
146081418a27Smrg                 Dsymbol *s = (*d->members)[i];
146181418a27Smrg                 s->accept(this);
146281418a27Smrg             }
146381418a27Smrg             buf->level--;
146481418a27Smrg             buf->writeByte('}');
146581418a27Smrg             buf->writenl();
146681418a27Smrg             hgs->tpltMember--;
146781418a27Smrg         }
146881418a27Smrg     }
146981418a27Smrg 
visitEponymousMember(TemplateDeclaration * d)147081418a27Smrg     bool visitEponymousMember(TemplateDeclaration *d)
147181418a27Smrg     {
147281418a27Smrg         if (!d->members || d->members->dim != 1)
147381418a27Smrg             return false;
147481418a27Smrg 
147581418a27Smrg         Dsymbol *onemember = (*d->members)[0];
147681418a27Smrg         if (onemember->ident != d->ident)
147781418a27Smrg             return false;
147881418a27Smrg 
147981418a27Smrg         if (FuncDeclaration *fd = onemember->isFuncDeclaration())
148081418a27Smrg         {
148181418a27Smrg             assert(fd->type);
148281418a27Smrg             if (stcToBuffer(buf, fd->storage_class))
148381418a27Smrg                 buf->writeByte(' ');
148481418a27Smrg             functionToBufferFull((TypeFunction *)fd->type, buf, d->ident, hgs, d);
148581418a27Smrg             visitTemplateConstraint(d->constraint);
148681418a27Smrg 
148781418a27Smrg             hgs->tpltMember++;
148881418a27Smrg             bodyToBuffer(fd);
148981418a27Smrg             hgs->tpltMember--;
149081418a27Smrg             return true;
149181418a27Smrg         }
149281418a27Smrg         if (AggregateDeclaration *ad = onemember->isAggregateDeclaration())
149381418a27Smrg         {
149481418a27Smrg             buf->writestring(ad->kind());
149581418a27Smrg             buf->writeByte(' ');
149681418a27Smrg             buf->writestring(ad->ident->toChars());
149781418a27Smrg             buf->writeByte('(');
149881418a27Smrg             visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
149981418a27Smrg             buf->writeByte(')');
150081418a27Smrg             visitTemplateConstraint(d->constraint);
150181418a27Smrg             visitBaseClasses(ad->isClassDeclaration());
150281418a27Smrg 
150381418a27Smrg             hgs->tpltMember++;
150481418a27Smrg             if (ad->members)
150581418a27Smrg             {
150681418a27Smrg                 buf->writenl();
150781418a27Smrg                 buf->writeByte('{');
150881418a27Smrg                 buf->writenl();
150981418a27Smrg                 buf->level++;
151081418a27Smrg                 for (size_t i = 0; i < ad->members->dim; i++)
151181418a27Smrg                 {
151281418a27Smrg                     Dsymbol *s = (*ad->members)[i];
151381418a27Smrg                     s->accept(this);
151481418a27Smrg                 }
151581418a27Smrg                 buf->level--;
151681418a27Smrg                 buf->writeByte('}');
151781418a27Smrg             }
151881418a27Smrg             else
151981418a27Smrg                 buf->writeByte(';');
152081418a27Smrg             buf->writenl();
152181418a27Smrg             hgs->tpltMember--;
152281418a27Smrg             return true;
152381418a27Smrg         }
152481418a27Smrg         if (VarDeclaration *vd = onemember->isVarDeclaration())
152581418a27Smrg         {
152681418a27Smrg             if (d->constraint)
152781418a27Smrg                 return false;
152881418a27Smrg 
152981418a27Smrg             if (stcToBuffer(buf, vd->storage_class))
153081418a27Smrg                 buf->writeByte(' ');
153181418a27Smrg             if (vd->type)
153281418a27Smrg                 typeToBuffer(vd->type, vd->ident);
153381418a27Smrg             else
153481418a27Smrg                 buf->writestring(vd->ident->toChars());
153581418a27Smrg 
153681418a27Smrg             buf->writeByte('(');
153781418a27Smrg             visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters);
153881418a27Smrg             buf->writeByte(')');
153981418a27Smrg 
154081418a27Smrg             if (vd->_init)
154181418a27Smrg             {
154281418a27Smrg                 buf->writestring(" = ");
154381418a27Smrg                 ExpInitializer *ie = vd->_init->isExpInitializer();
154481418a27Smrg                 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
154581418a27Smrg                     ((AssignExp *)ie->exp)->e2->accept(this);
154681418a27Smrg                 else
154781418a27Smrg                     vd->_init->accept(this);
154881418a27Smrg             }
154981418a27Smrg             buf->writeByte(';');
155081418a27Smrg             buf->writenl();
155181418a27Smrg             return true;
155281418a27Smrg         }
155381418a27Smrg 
155481418a27Smrg         return false;
155581418a27Smrg     }
visitTemplateParameters(TemplateParameters * parameters)155681418a27Smrg     void visitTemplateParameters(TemplateParameters *parameters)
155781418a27Smrg     {
155881418a27Smrg         if (!parameters || !parameters->dim)
155981418a27Smrg             return;
156081418a27Smrg         for (size_t i = 0; i < parameters->dim; i++)
156181418a27Smrg         {
156281418a27Smrg             TemplateParameter *p = (*parameters)[i];
156381418a27Smrg             if (i)
156481418a27Smrg                 buf->writestring(", ");
156581418a27Smrg             p->accept(this);
156681418a27Smrg         }
156781418a27Smrg     }
visitTemplateConstraint(Expression * constraint)156881418a27Smrg     void visitTemplateConstraint(Expression *constraint)
156981418a27Smrg     {
157081418a27Smrg         if (!constraint)
157181418a27Smrg             return;
157281418a27Smrg         buf->writestring(" if (");
157381418a27Smrg         constraint->accept(this);
157481418a27Smrg         buf->writeByte(')');
157581418a27Smrg     }
157681418a27Smrg 
visit(TemplateInstance * ti)157781418a27Smrg     void visit(TemplateInstance *ti)
157881418a27Smrg     {
157981418a27Smrg         buf->writestring(ti->name->toChars());
158081418a27Smrg         tiargsToBuffer(ti);
158181418a27Smrg 
158281418a27Smrg         if (hgs->fullDump)
158381418a27Smrg         {
158481418a27Smrg             buf->writenl();
158581418a27Smrg             if (ti->aliasdecl)
158681418a27Smrg             {
158781418a27Smrg                 // the ti.aliasDecl is the instantiated body
158881418a27Smrg                 // if we have it, print it.
158981418a27Smrg                 ti->aliasdecl->accept(this);
159081418a27Smrg             }
159181418a27Smrg         }
159281418a27Smrg     }
159381418a27Smrg 
visit(TemplateMixin * tm)159481418a27Smrg     void visit(TemplateMixin *tm)
159581418a27Smrg     {
159681418a27Smrg         buf->writestring("mixin ");
159781418a27Smrg 
159881418a27Smrg         typeToBuffer(tm->tqual, NULL);
159981418a27Smrg         tiargsToBuffer(tm);
160081418a27Smrg 
160181418a27Smrg         if (tm->ident && memcmp(tm->ident->toChars(), "__mixin", 7) != 0)
160281418a27Smrg         {
160381418a27Smrg             buf->writeByte(' ');
160481418a27Smrg             buf->writestring(tm->ident->toChars());
160581418a27Smrg         }
160681418a27Smrg         buf->writeByte(';');
160781418a27Smrg         buf->writenl();
160881418a27Smrg     }
160981418a27Smrg 
tiargsToBuffer(TemplateInstance * ti)161081418a27Smrg     void tiargsToBuffer(TemplateInstance *ti)
161181418a27Smrg     {
161281418a27Smrg         buf->writeByte('!');
161381418a27Smrg         if (ti->nest)
161481418a27Smrg         {
161581418a27Smrg             buf->writestring("(...)");
161681418a27Smrg             return;
161781418a27Smrg         }
161881418a27Smrg         if (!ti->tiargs)
161981418a27Smrg         {
162081418a27Smrg             buf->writestring("()");
162181418a27Smrg             return;
162281418a27Smrg         }
162381418a27Smrg 
162481418a27Smrg         if (ti->tiargs->dim == 1)
162581418a27Smrg         {
162681418a27Smrg             RootObject *oarg = (*ti->tiargs)[0];
162781418a27Smrg             if (Type *t = isType(oarg))
162881418a27Smrg             {
162981418a27Smrg                 if (t->equals(Type::tstring) ||
163081418a27Smrg                     t->equals(Type::twstring) ||
163181418a27Smrg                     t->equals(Type::tdstring) ||
163281418a27Smrg                     (t->mod == 0 &&
163381418a27Smrg                      (t->isTypeBasic() ||
163481418a27Smrg                       (t->ty == Tident && ((TypeIdentifier *)t)->idents.dim == 0))))
163581418a27Smrg                 {
163681418a27Smrg                     buf->writestring(t->toChars());
163781418a27Smrg                     return;
163881418a27Smrg                 }
163981418a27Smrg             }
164081418a27Smrg             else if (Expression *e = isExpression(oarg))
164181418a27Smrg             {
164281418a27Smrg                 if (e->op == TOKint64 ||
164381418a27Smrg                     e->op == TOKfloat64 ||
164481418a27Smrg                     e->op == TOKnull ||
164581418a27Smrg                     e->op == TOKstring ||
164681418a27Smrg                     e->op == TOKthis)
164781418a27Smrg                 {
164881418a27Smrg                     buf->writestring(e->toChars());
164981418a27Smrg                     return;
165081418a27Smrg                 }
165181418a27Smrg             }
165281418a27Smrg         }
165381418a27Smrg         buf->writeByte('(');
165481418a27Smrg         ti->nest++;
165581418a27Smrg         for (size_t i = 0; i < ti->tiargs->dim; i++)
165681418a27Smrg         {
165781418a27Smrg             RootObject *arg = (*ti->tiargs)[i];
165881418a27Smrg             if (i)
165981418a27Smrg                 buf->writestring(", ");
166081418a27Smrg             objectToBuffer(arg);
166181418a27Smrg         }
166281418a27Smrg         ti->nest--;
166381418a27Smrg         buf->writeByte(')');
166481418a27Smrg     }
166581418a27Smrg 
166681418a27Smrg     /****************************************
166781418a27Smrg      * This makes a 'pretty' version of the template arguments.
166881418a27Smrg      * It's analogous to genIdent() which makes a mangled version.
166981418a27Smrg      */
objectToBuffer(RootObject * oarg)167081418a27Smrg     void objectToBuffer(RootObject *oarg)
167181418a27Smrg     {
167281418a27Smrg         //printf("objectToBuffer()\n");
167381418a27Smrg 
167481418a27Smrg         /* The logic of this should match what genIdent() does. The _dynamic_cast()
167581418a27Smrg          * function relies on all the pretty strings to be unique for different classes
167681418a27Smrg          * (see Bugzilla 7375).
167781418a27Smrg          * Perhaps it would be better to demangle what genIdent() does.
167881418a27Smrg          */
167981418a27Smrg         if (Type *t = isType(oarg))
168081418a27Smrg         {
168181418a27Smrg             //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
168281418a27Smrg             typeToBuffer(t, NULL);
168381418a27Smrg         }
168481418a27Smrg         else if (Expression *e = isExpression(oarg))
168581418a27Smrg         {
168681418a27Smrg             if (e->op == TOKvar)
168781418a27Smrg                 e = e->optimize(WANTvalue);         // added to fix Bugzilla 7375
168881418a27Smrg             e->accept(this);
168981418a27Smrg         }
169081418a27Smrg         else if (Dsymbol *s = isDsymbol(oarg))
169181418a27Smrg         {
169281418a27Smrg             const char *p = s->ident ? s->ident->toChars() : s->toChars();
169381418a27Smrg             buf->writestring(p);
169481418a27Smrg         }
169581418a27Smrg         else if (Tuple *v = isTuple(oarg))
169681418a27Smrg         {
169781418a27Smrg             Objects *args = &v->objects;
169881418a27Smrg             for (size_t i = 0; i < args->dim; i++)
169981418a27Smrg             {
170081418a27Smrg                 RootObject *arg = (*args)[i];
170181418a27Smrg                 if (i)
170281418a27Smrg                     buf->writestring(", ");
170381418a27Smrg                 objectToBuffer(arg);
170481418a27Smrg             }
170581418a27Smrg         }
170681418a27Smrg         else if (!oarg)
170781418a27Smrg         {
170881418a27Smrg             buf->writestring("NULL");
170981418a27Smrg         }
171081418a27Smrg         else
171181418a27Smrg         {
171281418a27Smrg             assert(0);
171381418a27Smrg         }
171481418a27Smrg     }
171581418a27Smrg 
visit(EnumDeclaration * d)171681418a27Smrg     void visit(EnumDeclaration *d)
171781418a27Smrg     {
171881418a27Smrg         EnumDeclaration *oldInEnumDecl = inEnumDecl;
171981418a27Smrg         inEnumDecl = d;
172081418a27Smrg         buf->writestring("enum ");
172181418a27Smrg         if (d->ident)
172281418a27Smrg         {
172381418a27Smrg             buf->writestring(d->ident->toChars());
172481418a27Smrg             buf->writeByte(' ');
172581418a27Smrg         }
172681418a27Smrg         if (d->memtype)
172781418a27Smrg         {
172881418a27Smrg             buf->writestring(": ");
172981418a27Smrg             typeToBuffer(d->memtype, NULL);
173081418a27Smrg         }
173181418a27Smrg         if (!d->members)
173281418a27Smrg         {
173381418a27Smrg             buf->writeByte(';');
173481418a27Smrg             buf->writenl();
173581418a27Smrg             inEnumDecl = oldInEnumDecl;
173681418a27Smrg             return;
173781418a27Smrg         }
173881418a27Smrg         buf->writenl();
173981418a27Smrg         buf->writeByte('{');
174081418a27Smrg         buf->writenl();
174181418a27Smrg         buf->level++;
174281418a27Smrg         for (size_t i = 0; i < d->members->dim; i++)
174381418a27Smrg         {
174481418a27Smrg             EnumMember *em = (*d->members)[i]->isEnumMember();
174581418a27Smrg             if (!em)
174681418a27Smrg                 continue;
174781418a27Smrg             em->accept(this);
174881418a27Smrg             buf->writeByte(',');
174981418a27Smrg             buf->writenl();
175081418a27Smrg         }
175181418a27Smrg         buf->level--;
175281418a27Smrg         buf->writeByte('}');
175381418a27Smrg         buf->writenl();
175481418a27Smrg         inEnumDecl = oldInEnumDecl;
175581418a27Smrg     }
175681418a27Smrg 
visit(Nspace * d)175781418a27Smrg     void visit(Nspace *d)
175881418a27Smrg     {
175981418a27Smrg         buf->writestring("extern (C++, ");
176081418a27Smrg         buf->writestring(d->ident->toChars());
176181418a27Smrg         buf->writeByte(')');
176281418a27Smrg         buf->writenl();
176381418a27Smrg         buf->writeByte('{');
176481418a27Smrg         buf->writenl();
176581418a27Smrg         buf->level++;
176681418a27Smrg         for (size_t i = 0; i < d->members->dim; i++)
176781418a27Smrg         {
176881418a27Smrg             Dsymbol *s = (*d->members)[i];
176981418a27Smrg             s->accept(this);
177081418a27Smrg         }
177181418a27Smrg         buf->level--;
177281418a27Smrg         buf->writeByte('}');
177381418a27Smrg         buf->writenl();
177481418a27Smrg     }
177581418a27Smrg 
visit(StructDeclaration * d)177681418a27Smrg     void visit(StructDeclaration *d)
177781418a27Smrg     {
177881418a27Smrg         buf->printf("%s ", d->kind());
177981418a27Smrg         if (!d->isAnonymous())
178081418a27Smrg             buf->writestring(d->toChars());
178181418a27Smrg         if (!d->members)
178281418a27Smrg         {
178381418a27Smrg             buf->writeByte(';');
178481418a27Smrg             buf->writenl();
178581418a27Smrg             return;
178681418a27Smrg         }
178781418a27Smrg         buf->writenl();
178881418a27Smrg         buf->writeByte('{');
178981418a27Smrg         buf->writenl();
179081418a27Smrg         buf->level++;
179181418a27Smrg         for (size_t i = 0; i < d->members->dim; i++)
179281418a27Smrg         {
179381418a27Smrg             Dsymbol *s = (*d->members)[i];
179481418a27Smrg             s->accept(this);
179581418a27Smrg         }
179681418a27Smrg         buf->level--;
179781418a27Smrg         buf->writeByte('}');
179881418a27Smrg         buf->writenl();
179981418a27Smrg     }
180081418a27Smrg 
visit(ClassDeclaration * d)180181418a27Smrg     void visit(ClassDeclaration *d)
180281418a27Smrg     {
180381418a27Smrg         if (!d->isAnonymous())
180481418a27Smrg         {
180581418a27Smrg             buf->writestring(d->kind());
180681418a27Smrg             buf->writeByte(' ');
180781418a27Smrg             buf->writestring(d->ident->toChars());
180881418a27Smrg         }
180981418a27Smrg         visitBaseClasses(d);
181081418a27Smrg         if (d->members)
181181418a27Smrg         {
181281418a27Smrg             buf->writenl();
181381418a27Smrg             buf->writeByte('{');
181481418a27Smrg             buf->writenl();
181581418a27Smrg             buf->level++;
181681418a27Smrg             for (size_t i = 0; i < d->members->dim; i++)
181781418a27Smrg             {
181881418a27Smrg                 Dsymbol *s = (*d->members)[i];
181981418a27Smrg                 s->accept(this);
182081418a27Smrg             }
182181418a27Smrg             buf->level--;
182281418a27Smrg             buf->writeByte('}');
182381418a27Smrg         }
182481418a27Smrg         else
182581418a27Smrg             buf->writeByte(';');
182681418a27Smrg         buf->writenl();
182781418a27Smrg     }
182881418a27Smrg 
visitBaseClasses(ClassDeclaration * d)182981418a27Smrg     void visitBaseClasses(ClassDeclaration *d)
183081418a27Smrg     {
183181418a27Smrg         if (!d || !d->baseclasses->dim)
183281418a27Smrg             return;
183381418a27Smrg 
183481418a27Smrg         buf->writestring(" : ");
183581418a27Smrg         for (size_t i = 0; i < d->baseclasses->dim; i++)
183681418a27Smrg         {
183781418a27Smrg             if (i)
183881418a27Smrg                 buf->writestring(", ");
183981418a27Smrg             BaseClass *b = (*d->baseclasses)[i];
184081418a27Smrg             typeToBuffer(b->type, NULL);
184181418a27Smrg         }
184281418a27Smrg     }
184381418a27Smrg 
visit(AliasDeclaration * d)184481418a27Smrg     void visit(AliasDeclaration *d)
184581418a27Smrg     {
1846*dd083157Smrg         if (d->storage_class & STClocal)
1847*dd083157Smrg             return;
184881418a27Smrg         buf->writestring("alias ");
184981418a27Smrg         if (d->aliassym)
185081418a27Smrg         {
185181418a27Smrg             buf->writestring(d->ident->toChars());
185281418a27Smrg             buf->writestring(" = ");
185381418a27Smrg             if (stcToBuffer(buf, d->storage_class))
185481418a27Smrg                 buf->writeByte(' ');
185581418a27Smrg             d->aliassym->accept(this);
185681418a27Smrg         }
185781418a27Smrg         else if (d->type->ty == Tfunction)
185881418a27Smrg         {
185981418a27Smrg             if (stcToBuffer(buf, d->storage_class))
186081418a27Smrg                 buf->writeByte(' ');
186181418a27Smrg             typeToBuffer(d->type, d->ident);
186281418a27Smrg         }
186381418a27Smrg         else
186481418a27Smrg         {
186581418a27Smrg             declstring = (d->ident == Id::string || d->ident == Id::wstring || d->ident == Id::dstring);
186681418a27Smrg             buf->writestring(d->ident->toChars());
186781418a27Smrg             buf->writestring(" = ");
186881418a27Smrg             if (stcToBuffer(buf, d->storage_class))
186981418a27Smrg                 buf->writeByte(' ');
187081418a27Smrg             typeToBuffer(d->type, NULL);
187181418a27Smrg             declstring = false;
187281418a27Smrg         }
187381418a27Smrg         buf->writeByte(';');
187481418a27Smrg         buf->writenl();
187581418a27Smrg     }
187681418a27Smrg 
visit(VarDeclaration * d)187781418a27Smrg     void visit(VarDeclaration *d)
187881418a27Smrg     {
1879*dd083157Smrg         if (d->storage_class & STClocal)
1880*dd083157Smrg             return;
188181418a27Smrg         visitVarDecl(d, false);
188281418a27Smrg         buf->writeByte(';');
188381418a27Smrg         buf->writenl();
188481418a27Smrg     }
visitVarDecl(VarDeclaration * v,bool anywritten)188581418a27Smrg     void visitVarDecl(VarDeclaration *v, bool anywritten)
188681418a27Smrg     {
188781418a27Smrg         if (anywritten)
188881418a27Smrg         {
188981418a27Smrg             buf->writestring(", ");
189081418a27Smrg             buf->writestring(v->ident->toChars());
189181418a27Smrg         }
189281418a27Smrg         else
189381418a27Smrg         {
189481418a27Smrg             if (stcToBuffer(buf, v->storage_class))
189581418a27Smrg                 buf->writeByte(' ');
189681418a27Smrg             if (v->type)
189781418a27Smrg                 typeToBuffer(v->type, v->ident);
189881418a27Smrg             else
189981418a27Smrg                 buf->writestring(v->ident->toChars());
190081418a27Smrg         }
190181418a27Smrg         if (v->_init)
190281418a27Smrg         {
190381418a27Smrg             buf->writestring(" = ");
190481418a27Smrg             ExpInitializer *ie = v->_init->isExpInitializer();
190581418a27Smrg             if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit))
190681418a27Smrg                 ((AssignExp *)ie->exp)->e2->accept(this);
190781418a27Smrg             else
190881418a27Smrg                 v->_init->accept(this);
190981418a27Smrg         }
191081418a27Smrg     }
191181418a27Smrg 
visit(FuncDeclaration * f)191281418a27Smrg     void visit(FuncDeclaration *f)
191381418a27Smrg     {
191481418a27Smrg         //printf("FuncDeclaration::toCBuffer() '%s'\n", f->toChars());
191581418a27Smrg 
191681418a27Smrg         if (stcToBuffer(buf, f->storage_class))
191781418a27Smrg             buf->writeByte(' ');
191881418a27Smrg         TypeFunction *tf = (TypeFunction *)f->type;
191981418a27Smrg         typeToBuffer(tf, f->ident);
192081418a27Smrg         if (hgs->hdrgen)
192181418a27Smrg         {
192281418a27Smrg             // if the return type is missing (e.g. ref functions or auto)
192381418a27Smrg             if (!tf->next || f->storage_class & STCauto)
192481418a27Smrg             {
192581418a27Smrg                 hgs->autoMember++;
192681418a27Smrg                 bodyToBuffer(f);
192781418a27Smrg                 hgs->autoMember--;
192881418a27Smrg             }
192981418a27Smrg             else if (hgs->tpltMember == 0 && global.params.hdrStripPlainFunctions)
193081418a27Smrg             {
193181418a27Smrg                 buf->writeByte(';');
193281418a27Smrg                 buf->writenl();
193381418a27Smrg             }
193481418a27Smrg             else
193581418a27Smrg                 bodyToBuffer(f);
193681418a27Smrg         }
193781418a27Smrg         else
193881418a27Smrg             bodyToBuffer(f);
193981418a27Smrg     }
194081418a27Smrg 
bodyToBuffer(FuncDeclaration * f)194181418a27Smrg     void bodyToBuffer(FuncDeclaration *f)
194281418a27Smrg     {
194381418a27Smrg         if (!f->fbody || (hgs->hdrgen && global.params.hdrStripPlainFunctions && !hgs->autoMember && !hgs->tpltMember))
194481418a27Smrg         {
194581418a27Smrg             buf->writeByte(';');
194681418a27Smrg             buf->writenl();
194781418a27Smrg             return;
194881418a27Smrg         }
194981418a27Smrg 
195081418a27Smrg         int savetlpt = hgs->tpltMember;
195181418a27Smrg         int saveauto = hgs->autoMember;
195281418a27Smrg         hgs->tpltMember = 0;
195381418a27Smrg         hgs->autoMember = 0;
195481418a27Smrg 
195581418a27Smrg         buf->writenl();
195681418a27Smrg 
195781418a27Smrg         // in{}
195881418a27Smrg         if (f->frequire)
195981418a27Smrg         {
196081418a27Smrg             buf->writestring("in");
196181418a27Smrg             buf->writenl();
196281418a27Smrg             f->frequire->accept(this);
196381418a27Smrg         }
196481418a27Smrg 
196581418a27Smrg         // out{}
196681418a27Smrg         if (f->fensure)
196781418a27Smrg         {
196881418a27Smrg             buf->writestring("out");
196981418a27Smrg             if (f->outId)
197081418a27Smrg             {
197181418a27Smrg                 buf->writeByte('(');
197281418a27Smrg                 buf->writestring(f->outId->toChars());
197381418a27Smrg                 buf->writeByte(')');
197481418a27Smrg             }
197581418a27Smrg             buf->writenl();
197681418a27Smrg             f->fensure->accept(this);
197781418a27Smrg         }
197881418a27Smrg 
197981418a27Smrg         if (f->frequire || f->fensure)
198081418a27Smrg         {
198181418a27Smrg             buf->writestring("body");
198281418a27Smrg             buf->writenl();
198381418a27Smrg         }
198481418a27Smrg 
198581418a27Smrg         buf->writeByte('{');
198681418a27Smrg         buf->writenl();
198781418a27Smrg         buf->level++;
198881418a27Smrg         f->fbody->accept(this);
198981418a27Smrg         buf->level--;
199081418a27Smrg         buf->writeByte('}');
199181418a27Smrg         buf->writenl();
199281418a27Smrg 
199381418a27Smrg         hgs->tpltMember = savetlpt;
199481418a27Smrg         hgs->autoMember = saveauto;
199581418a27Smrg     }
199681418a27Smrg 
visit(FuncLiteralDeclaration * f)199781418a27Smrg     void visit(FuncLiteralDeclaration *f)
199881418a27Smrg     {
199981418a27Smrg         if (f->type->ty == Terror)
200081418a27Smrg         {
200181418a27Smrg             buf->writestring("__error");
200281418a27Smrg             return;
200381418a27Smrg         }
200481418a27Smrg 
200581418a27Smrg         if (f->tok != TOKreserved)
200681418a27Smrg         {
200781418a27Smrg             buf->writestring(f->kind());
200881418a27Smrg             buf->writeByte(' ');
200981418a27Smrg         }
201081418a27Smrg 
201181418a27Smrg         TypeFunction *tf = (TypeFunction *)f->type;
201281418a27Smrg         // Don't print tf->mod, tf->trust, and tf->linkage
201381418a27Smrg         if (!f->inferRetType && tf->next)
201481418a27Smrg             typeToBuffer(tf->next, NULL);
201581418a27Smrg         parametersToBuffer(tf->parameters, tf->varargs);
201681418a27Smrg 
201781418a27Smrg         CompoundStatement *cs = f->fbody->isCompoundStatement();
201881418a27Smrg         Statement *s1;
201981418a27Smrg         if (f->semanticRun >= PASSsemantic3done && cs)
202081418a27Smrg         {
202181418a27Smrg             s1 = (*cs->statements)[cs->statements->dim - 1];
202281418a27Smrg         }
202381418a27Smrg         else
202481418a27Smrg             s1 = !cs ? f->fbody : NULL;
202581418a27Smrg         ReturnStatement *rs = s1 ? s1->isReturnStatement() : NULL;
202681418a27Smrg         if (rs && rs->exp)
202781418a27Smrg         {
202881418a27Smrg             buf->writestring(" => ");
202981418a27Smrg             rs->exp->accept(this);
203081418a27Smrg         }
203181418a27Smrg         else
203281418a27Smrg         {
203381418a27Smrg             hgs->tpltMember++;
203481418a27Smrg             bodyToBuffer(f);
203581418a27Smrg             hgs->tpltMember--;
203681418a27Smrg         }
203781418a27Smrg     }
203881418a27Smrg 
visit(PostBlitDeclaration * d)203981418a27Smrg     void visit(PostBlitDeclaration *d)
204081418a27Smrg     {
204181418a27Smrg         if (stcToBuffer(buf, d->storage_class))
204281418a27Smrg              buf->writeByte(' ');
204381418a27Smrg         buf->writestring("this(this)");
204481418a27Smrg         bodyToBuffer(d);
204581418a27Smrg     }
204681418a27Smrg 
visit(DtorDeclaration * d)204781418a27Smrg     void visit(DtorDeclaration *d)
204881418a27Smrg     {
204981418a27Smrg         if (d->storage_class & STCtrusted)
205081418a27Smrg             buf->writestring("@trusted ");
205181418a27Smrg         if (d->storage_class & STCsafe)
205281418a27Smrg             buf->writestring("@safe ");
205381418a27Smrg         if (d->storage_class & STCnogc)
205481418a27Smrg             buf->writestring("@nogc ");
205581418a27Smrg         if (d->storage_class & STCdisable)
205681418a27Smrg             buf->writestring("@disable ");
205781418a27Smrg 
205881418a27Smrg         buf->writestring("~this()");
205981418a27Smrg         bodyToBuffer(d);
206081418a27Smrg     }
206181418a27Smrg 
visit(StaticCtorDeclaration * d)206281418a27Smrg     void visit(StaticCtorDeclaration *d)
206381418a27Smrg     {
206481418a27Smrg         if (stcToBuffer(buf, d->storage_class & ~STCstatic))
206581418a27Smrg             buf->writeByte(' ');
206681418a27Smrg         if (d->isSharedStaticCtorDeclaration())
206781418a27Smrg             buf->writestring("shared ");
206881418a27Smrg         buf->writestring("static this()");
206981418a27Smrg         if (hgs->hdrgen && !hgs->tpltMember)
207081418a27Smrg         {
207181418a27Smrg             buf->writeByte(';');
207281418a27Smrg             buf->writenl();
207381418a27Smrg         }
207481418a27Smrg         else
207581418a27Smrg             bodyToBuffer(d);
207681418a27Smrg     }
207781418a27Smrg 
visit(StaticDtorDeclaration * d)207881418a27Smrg     void visit(StaticDtorDeclaration *d)
207981418a27Smrg     {
208081418a27Smrg         if (hgs->hdrgen)
208181418a27Smrg             return;
208281418a27Smrg         if (stcToBuffer(buf, d->storage_class & ~STCstatic))
208381418a27Smrg             buf->writeByte(' ');
208481418a27Smrg         if (d->isSharedStaticDtorDeclaration())
208581418a27Smrg             buf->writestring("shared ");
208681418a27Smrg         buf->writestring("static ~this()");
208781418a27Smrg         bodyToBuffer(d);
208881418a27Smrg     }
208981418a27Smrg 
visit(InvariantDeclaration * d)209081418a27Smrg     void visit(InvariantDeclaration *d)
209181418a27Smrg     {
209281418a27Smrg         if (hgs->hdrgen)
209381418a27Smrg             return;
209481418a27Smrg         if (stcToBuffer(buf, d->storage_class))
209581418a27Smrg             buf->writeByte(' ');
209681418a27Smrg         buf->writestring("invariant");
209781418a27Smrg         bodyToBuffer(d);
209881418a27Smrg     }
209981418a27Smrg 
visit(UnitTestDeclaration * d)210081418a27Smrg     void visit(UnitTestDeclaration *d)
210181418a27Smrg     {
210281418a27Smrg         if (hgs->hdrgen)
210381418a27Smrg             return;
210481418a27Smrg         if (stcToBuffer(buf, d->storage_class))
210581418a27Smrg             buf->writeByte(' ');
210681418a27Smrg         buf->writestring("unittest");
210781418a27Smrg         bodyToBuffer(d);
210881418a27Smrg     }
210981418a27Smrg 
visit(NewDeclaration * d)211081418a27Smrg     void visit(NewDeclaration *d)
211181418a27Smrg     {
211281418a27Smrg         if (stcToBuffer(buf, d->storage_class & ~STCstatic))
211381418a27Smrg             buf->writeByte(' ');
211481418a27Smrg         buf->writestring("new");
211581418a27Smrg         parametersToBuffer(d->parameters, d->varargs);
211681418a27Smrg         bodyToBuffer(d);
211781418a27Smrg     }
211881418a27Smrg 
visit(DeleteDeclaration * d)211981418a27Smrg     void visit(DeleteDeclaration *d)
212081418a27Smrg     {
212181418a27Smrg         if (stcToBuffer(buf, d->storage_class & ~STCstatic))
212281418a27Smrg             buf->writeByte(' ');
212381418a27Smrg         buf->writestring("delete");
212481418a27Smrg         parametersToBuffer(d->parameters, 0);
212581418a27Smrg         bodyToBuffer(d);
212681418a27Smrg     }
212781418a27Smrg 
212881418a27Smrg     ////////////////////////////////////////////////////////////////////////////
212981418a27Smrg 
visit(ErrorInitializer *)213081418a27Smrg     void visit(ErrorInitializer *)
213181418a27Smrg     {
213281418a27Smrg         buf->writestring("__error__");
213381418a27Smrg     }
213481418a27Smrg 
visit(VoidInitializer *)213581418a27Smrg     void visit(VoidInitializer *)
213681418a27Smrg     {
213781418a27Smrg         buf->writestring("void");
213881418a27Smrg     }
213981418a27Smrg 
visit(StructInitializer * si)214081418a27Smrg     void visit(StructInitializer *si)
214181418a27Smrg     {
214281418a27Smrg         //printf("StructInitializer::toCBuffer()\n");
214381418a27Smrg         buf->writeByte('{');
214481418a27Smrg         for (size_t i = 0; i < si->field.dim; i++)
214581418a27Smrg         {
214681418a27Smrg             if (i)
214781418a27Smrg                 buf->writestring(", ");
214881418a27Smrg             if (Identifier *id = si->field[i])
214981418a27Smrg             {
215081418a27Smrg                 buf->writestring(id->toChars());
215181418a27Smrg                 buf->writeByte(':');
215281418a27Smrg             }
215381418a27Smrg             if (Initializer *iz = si->value[i])
215481418a27Smrg                 iz->accept(this);
215581418a27Smrg         }
215681418a27Smrg         buf->writeByte('}');
215781418a27Smrg     }
215881418a27Smrg 
visit(ArrayInitializer * ai)215981418a27Smrg     void visit(ArrayInitializer *ai)
216081418a27Smrg     {
216181418a27Smrg         buf->writeByte('[');
216281418a27Smrg         for (size_t i = 0; i < ai->index.dim; i++)
216381418a27Smrg         {
216481418a27Smrg             if (i)
216581418a27Smrg                 buf->writestring(", ");
216681418a27Smrg             if (Expression *ex = ai->index[i])
216781418a27Smrg             {
216881418a27Smrg                 ex->accept(this);
216981418a27Smrg                 buf->writeByte(':');
217081418a27Smrg             }
217181418a27Smrg             if (Initializer *iz = ai->value[i])
217281418a27Smrg                 iz->accept(this);
217381418a27Smrg         }
217481418a27Smrg         buf->writeByte(']');
217581418a27Smrg     }
217681418a27Smrg 
visit(ExpInitializer * ei)217781418a27Smrg     void visit(ExpInitializer *ei)
217881418a27Smrg     {
217981418a27Smrg         ei->exp->accept(this);
218081418a27Smrg     }
218181418a27Smrg 
218281418a27Smrg     ////////////////////////////////////////////////////////////////////////////
218381418a27Smrg 
218481418a27Smrg     /**************************************************
218581418a27Smrg      * Write out argument list to buf.
218681418a27Smrg      */
218781418a27Smrg     void argsToBuffer(Expressions *expressions, Expression *basis = NULL)
218881418a27Smrg     {
218981418a27Smrg         if (!expressions || !expressions->dim)
219081418a27Smrg             return;
219181418a27Smrg 
219281418a27Smrg         for (size_t i = 0; i < expressions->dim; i++)
219381418a27Smrg         {
219481418a27Smrg             Expression *el = (*expressions)[i];
219581418a27Smrg             if (i)
219681418a27Smrg                 buf->writestring(", ");
219781418a27Smrg             if (!el)
219881418a27Smrg                 el = basis;
219981418a27Smrg             if (el)
220081418a27Smrg                 expToBuffer(el, PREC_assign);
220181418a27Smrg         }
220281418a27Smrg     }
220381418a27Smrg 
sizeToBuffer(Expression * e)220481418a27Smrg     void sizeToBuffer(Expression *e)
220581418a27Smrg     {
220681418a27Smrg         if (e->type == Type::tsize_t)
220781418a27Smrg         {
220881418a27Smrg             Expression *ex = (e->op == TOKcast ? ((CastExp *)e)->e1 : e);
220981418a27Smrg             ex = ex->optimize(WANTvalue);
221081418a27Smrg 
221181418a27Smrg             dinteger_t uval = ex->op == TOKint64 ? ex->toInteger() : (dinteger_t)-1;
221281418a27Smrg             if ((sinteger_t)uval >= 0)
221381418a27Smrg             {
221481418a27Smrg                 dinteger_t sizemax;
2215*dd083157Smrg                 if (Target::ptrsize == 8)
221681418a27Smrg                     sizemax = 0xFFFFFFFFFFFFFFFFULL;
2217*dd083157Smrg                 else if (Target::ptrsize == 4)
2218*dd083157Smrg                     sizemax = 0xFFFFFFFFUL;
2219*dd083157Smrg                 else if (Target::ptrsize == 2)
2220*dd083157Smrg                     sizemax = 0xFFFFUL;
222181418a27Smrg                 else
222281418a27Smrg                     assert(0);
222381418a27Smrg                 if (uval <= sizemax && uval <= 0x7FFFFFFFFFFFFFFFULL)
222481418a27Smrg                 {
222581418a27Smrg                     buf->printf("%llu", uval);
222681418a27Smrg                     return;
222781418a27Smrg                 }
222881418a27Smrg             }
222981418a27Smrg         }
223081418a27Smrg         expToBuffer(e, PREC_assign);
223181418a27Smrg     }
223281418a27Smrg 
223381418a27Smrg     /**************************************************
223481418a27Smrg      * Write expression out to buf, but wrap it
223581418a27Smrg      * in ( ) if its precedence is less than pr.
223681418a27Smrg      */
expToBuffer(Expression * e,PREC pr)223781418a27Smrg     void expToBuffer(Expression *e, PREC pr)
223881418a27Smrg     {
223981418a27Smrg         assert(precedence[e->op] != PREC_zero);
224081418a27Smrg         assert(pr != PREC_zero);
224181418a27Smrg 
224281418a27Smrg         //if (precedence[e->op] == 0) e->print();
224381418a27Smrg         /* Despite precedence, we don't allow a<b<c expressions.
224481418a27Smrg          * They must be parenthesized.
224581418a27Smrg          */
224681418a27Smrg         if (precedence[e->op] < pr ||
224781418a27Smrg             (pr == PREC_rel && precedence[e->op] == pr))
224881418a27Smrg         {
224981418a27Smrg             buf->writeByte('(');
225081418a27Smrg             e->accept(this);
225181418a27Smrg             buf->writeByte(')');
225281418a27Smrg         }
225381418a27Smrg         else
225481418a27Smrg             e->accept(this);
225581418a27Smrg     }
225681418a27Smrg 
visit(Expression * e)225781418a27Smrg     void visit(Expression *e)
225881418a27Smrg     {
225981418a27Smrg         buf->writestring(Token::toChars(e->op));
226081418a27Smrg     }
226181418a27Smrg 
visit(IntegerExp * e)226281418a27Smrg     void visit(IntegerExp *e)
226381418a27Smrg     {
226481418a27Smrg         dinteger_t v = e->toInteger();
226581418a27Smrg 
226681418a27Smrg         if (e->type)
226781418a27Smrg         {
226881418a27Smrg             Type *t = e->type;
226981418a27Smrg         L1:
227081418a27Smrg             switch (t->ty)
227181418a27Smrg             {
227281418a27Smrg                 case Tenum:
227381418a27Smrg                 {
227481418a27Smrg                     TypeEnum *te = (TypeEnum *)t;
227581418a27Smrg                     if (hgs->fullDump)
227681418a27Smrg                     {
227781418a27Smrg                         EnumDeclaration *sym = te->sym;
227881418a27Smrg                         if (inEnumDecl != sym)
227981418a27Smrg                         {
228081418a27Smrg                             for (size_t i = 0; i < sym->members->dim; i++)
228181418a27Smrg                             {
228281418a27Smrg                                 EnumMember *em = (EnumMember *)(*sym->members)[i];
228381418a27Smrg                                 if (em->value()->toInteger() == v)
228481418a27Smrg                                 {
228581418a27Smrg                                     buf->printf("%s.%s", sym->toChars(), em->ident->toChars());
228681418a27Smrg                                     return;
228781418a27Smrg                                 }
228881418a27Smrg                             }
228981418a27Smrg                         }
229081418a27Smrg                     }
229181418a27Smrg                     buf->printf("cast(%s)", te->sym->toChars());
229281418a27Smrg                     t = te->sym->memtype;
229381418a27Smrg                     goto L1;
229481418a27Smrg                 }
229581418a27Smrg 
229681418a27Smrg                 case Twchar:        // BUG: need to cast(wchar)
229781418a27Smrg                 case Tdchar:        // BUG: need to cast(dchar)
229881418a27Smrg                     if ((uinteger_t)v > 0xFF)
229981418a27Smrg                     {
230081418a27Smrg                         buf->printf("'\\U%08x'", v);
230181418a27Smrg                         break;
230281418a27Smrg                     }
230381418a27Smrg                     /* fall through */
230481418a27Smrg                 case Tchar:
230581418a27Smrg                 {
230681418a27Smrg                     size_t o = buf->offset;
230781418a27Smrg                     if (v == '\'')
230881418a27Smrg                         buf->writestring("'\\''");
230981418a27Smrg                     else if (isprint((int)v) && v != '\\')
231081418a27Smrg                         buf->printf("'%c'", (int)v);
231181418a27Smrg                     else
231281418a27Smrg                         buf->printf("'\\x%02x'", (int)v);
231381418a27Smrg                     if (hgs->ddoc)
231481418a27Smrg                         escapeDdocString(buf, o);
231581418a27Smrg                     break;
231681418a27Smrg                 }
231781418a27Smrg 
231881418a27Smrg                 case Tint8:
231981418a27Smrg                     buf->writestring("cast(byte)");
232081418a27Smrg                     goto L2;
232181418a27Smrg 
232281418a27Smrg                 case Tint16:
232381418a27Smrg                     buf->writestring("cast(short)");
232481418a27Smrg                     goto L2;
232581418a27Smrg 
232681418a27Smrg                 case Tint32:
232781418a27Smrg                 L2:
232881418a27Smrg                     buf->printf("%d", (int)v);
232981418a27Smrg                     break;
233081418a27Smrg 
233181418a27Smrg                 case Tuns8:
233281418a27Smrg                     buf->writestring("cast(ubyte)");
233381418a27Smrg                     goto L3;
233481418a27Smrg 
233581418a27Smrg                 case Tuns16:
233681418a27Smrg                     buf->writestring("cast(ushort)");
233781418a27Smrg                     goto L3;
233881418a27Smrg 
233981418a27Smrg                 case Tuns32:
234081418a27Smrg                 L3:
234181418a27Smrg                     buf->printf("%uu", (unsigned)v);
234281418a27Smrg                     break;
234381418a27Smrg 
234481418a27Smrg                 case Tint64:
234581418a27Smrg                     buf->printf("%lldL", v);
234681418a27Smrg                     break;
234781418a27Smrg 
234881418a27Smrg                 case Tuns64:
234981418a27Smrg                 L4:
235081418a27Smrg                     buf->printf("%lluLU", v);
235181418a27Smrg                     break;
235281418a27Smrg 
235381418a27Smrg                 case Tbool:
235481418a27Smrg                     buf->writestring(v ? "true" : "false");
235581418a27Smrg                     break;
235681418a27Smrg 
235781418a27Smrg                 case Tpointer:
235881418a27Smrg                     buf->writestring("cast(");
235981418a27Smrg                     buf->writestring(t->toChars());
236081418a27Smrg                     buf->writeByte(')');
2361*dd083157Smrg                     if (Target::ptrsize == 8)
236281418a27Smrg                         goto L4;
236381418a27Smrg                     else
2364*dd083157Smrg                         goto L3;
236581418a27Smrg 
236681418a27Smrg                 default:
236781418a27Smrg                     /* This can happen if errors, such as
236881418a27Smrg                      * the type is painted on like in fromConstInitializer().
236981418a27Smrg                      */
237081418a27Smrg                     if (!global.errors)
237181418a27Smrg                     {
237281418a27Smrg                         assert(0);
237381418a27Smrg                     }
237481418a27Smrg                     break;
237581418a27Smrg             }
237681418a27Smrg         }
237781418a27Smrg         else if (v & 0x8000000000000000LL)
237881418a27Smrg             buf->printf("0x%llx", v);
237981418a27Smrg         else
238081418a27Smrg             buf->printf("%lld", v);
238181418a27Smrg     }
238281418a27Smrg 
visit(ErrorExp *)238381418a27Smrg     void visit(ErrorExp *)
238481418a27Smrg     {
238581418a27Smrg         buf->writestring("__error");
238681418a27Smrg     }
238781418a27Smrg 
floatToBuffer(Type * type,real_t value)238881418a27Smrg     void floatToBuffer(Type *type, real_t value)
238981418a27Smrg     {
239081418a27Smrg         /** sizeof(value)*3 is because each byte of mantissa is max
239181418a27Smrg         of 256 (3 characters). The string will be "-M.MMMMe-4932".
239281418a27Smrg         (ie, 8 chars more than mantissa). Plus one for trailing \0.
239381418a27Smrg         Plus one for rounding. */
239481418a27Smrg         const size_t BUFFER_LEN = sizeof(value) * 3 + 8 + 1 + 1;
239581418a27Smrg         char buffer[BUFFER_LEN];
239681418a27Smrg         memset(buffer, 0, BUFFER_LEN);
239781418a27Smrg         CTFloat::sprint(buffer, 'g', value);
239881418a27Smrg         assert(strlen(buffer) < BUFFER_LEN);
239981418a27Smrg 
240081418a27Smrg         if (hgs->hdrgen)
240181418a27Smrg         {
240281418a27Smrg             real_t r = CTFloat::parse(buffer);
240381418a27Smrg             if (r != value)                     // if exact duplication
240481418a27Smrg                 CTFloat::sprint(buffer, 'a', value);
240581418a27Smrg         }
240681418a27Smrg         buf->writestring(buffer);
240781418a27Smrg 
240881418a27Smrg         if (type)
240981418a27Smrg         {
241081418a27Smrg             Type *t = type->toBasetype();
241181418a27Smrg             switch (t->ty)
241281418a27Smrg             {
241381418a27Smrg                 case Tfloat32:
241481418a27Smrg                 case Timaginary32:
241581418a27Smrg                 case Tcomplex32:
241681418a27Smrg                     buf->writeByte('F');
241781418a27Smrg                     break;
241881418a27Smrg 
241981418a27Smrg                 case Tfloat80:
242081418a27Smrg                 case Timaginary80:
242181418a27Smrg                 case Tcomplex80:
242281418a27Smrg                     buf->writeByte('L');
242381418a27Smrg                     break;
242481418a27Smrg 
242581418a27Smrg                 default:
242681418a27Smrg                     break;
242781418a27Smrg             }
242881418a27Smrg             if (t->isimaginary())
242981418a27Smrg                 buf->writeByte('i');
243081418a27Smrg         }
243181418a27Smrg     }
243281418a27Smrg 
visit(RealExp * e)243381418a27Smrg     void visit(RealExp *e)
243481418a27Smrg     {
243581418a27Smrg         floatToBuffer(e->type, e->value);
243681418a27Smrg     }
243781418a27Smrg 
visit(ComplexExp * e)243881418a27Smrg     void visit(ComplexExp *e)
243981418a27Smrg     {
244081418a27Smrg         /* Print as:
244181418a27Smrg          *  (re+imi)
244281418a27Smrg          */
244381418a27Smrg         buf->writeByte('(');
244481418a27Smrg         floatToBuffer(e->type, creall(e->value));
244581418a27Smrg         buf->writeByte('+');
244681418a27Smrg         floatToBuffer(e->type, cimagl(e->value));
244781418a27Smrg         buf->writestring("i)");
244881418a27Smrg     }
244981418a27Smrg 
visit(IdentifierExp * e)245081418a27Smrg     void visit(IdentifierExp *e)
245181418a27Smrg     {
245281418a27Smrg         if (hgs->hdrgen || hgs->ddoc)
245381418a27Smrg             buf->writestring(e->ident->toHChars2());
245481418a27Smrg         else
245581418a27Smrg             buf->writestring(e->ident->toChars());
245681418a27Smrg     }
245781418a27Smrg 
visit(DsymbolExp * e)245881418a27Smrg     void visit(DsymbolExp *e)
245981418a27Smrg     {
246081418a27Smrg         buf->writestring(e->s->toChars());
246181418a27Smrg     }
246281418a27Smrg 
visit(ThisExp *)246381418a27Smrg     void visit(ThisExp *)
246481418a27Smrg     {
246581418a27Smrg         buf->writestring("this");
246681418a27Smrg     }
246781418a27Smrg 
visit(SuperExp *)246881418a27Smrg     void visit(SuperExp *)
246981418a27Smrg     {
247081418a27Smrg         buf->writestring("super");
247181418a27Smrg     }
247281418a27Smrg 
visit(NullExp *)247381418a27Smrg     void visit(NullExp *)
247481418a27Smrg     {
247581418a27Smrg         buf->writestring("null");
247681418a27Smrg     }
247781418a27Smrg 
visit(StringExp * e)247881418a27Smrg     void visit(StringExp *e)
247981418a27Smrg     {
248081418a27Smrg         buf->writeByte('"');
248181418a27Smrg         size_t o = buf->offset;
248281418a27Smrg         for (size_t i = 0; i < e->len; i++)
248381418a27Smrg         {
248481418a27Smrg             unsigned c = e->charAt(i);
248581418a27Smrg             switch (c)
248681418a27Smrg             {
248781418a27Smrg                 case '"':
248881418a27Smrg                 case '\\':
248981418a27Smrg                     buf->writeByte('\\');
249081418a27Smrg                     /* fall through */
249181418a27Smrg                 default:
249281418a27Smrg                     if (c <= 0xFF)
249381418a27Smrg                     {
249481418a27Smrg                         if (c <= 0x7F && isprint(c))
249581418a27Smrg                             buf->writeByte(c);
249681418a27Smrg                         else
249781418a27Smrg                             buf->printf("\\x%02x", c);
249881418a27Smrg                     }
249981418a27Smrg                     else if (c <= 0xFFFF)
250081418a27Smrg                         buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
250181418a27Smrg                     else
250281418a27Smrg                         buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
250381418a27Smrg                             c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
250481418a27Smrg                     break;
250581418a27Smrg             }
250681418a27Smrg         }
250781418a27Smrg         if (hgs->ddoc)
250881418a27Smrg             escapeDdocString(buf, o);
250981418a27Smrg         buf->writeByte('"');
251081418a27Smrg         if (e->postfix)
251181418a27Smrg             buf->writeByte(e->postfix);
251281418a27Smrg     }
251381418a27Smrg 
visit(ArrayLiteralExp * e)251481418a27Smrg     void visit(ArrayLiteralExp *e)
251581418a27Smrg     {
251681418a27Smrg         buf->writeByte('[');
251781418a27Smrg         argsToBuffer(e->elements, e->basis);
251881418a27Smrg         buf->writeByte(']');
251981418a27Smrg     }
252081418a27Smrg 
visit(AssocArrayLiteralExp * e)252181418a27Smrg     void visit(AssocArrayLiteralExp *e)
252281418a27Smrg     {
252381418a27Smrg         buf->writeByte('[');
252481418a27Smrg         for (size_t i = 0; i < e->keys->dim; i++)
252581418a27Smrg         {
252681418a27Smrg             Expression *key = (*e->keys)[i];
252781418a27Smrg             Expression *value = (*e->values)[i];
252881418a27Smrg 
252981418a27Smrg             if (i)
253081418a27Smrg                 buf->writestring(", ");
253181418a27Smrg             expToBuffer(key, PREC_assign);
253281418a27Smrg             buf->writeByte(':');
253381418a27Smrg             expToBuffer(value, PREC_assign);
253481418a27Smrg         }
253581418a27Smrg         buf->writeByte(']');
253681418a27Smrg     }
253781418a27Smrg 
visit(StructLiteralExp * e)253881418a27Smrg     void visit(StructLiteralExp *e)
253981418a27Smrg     {
254081418a27Smrg         buf->writestring(e->sd->toChars());
254181418a27Smrg         buf->writeByte('(');
254281418a27Smrg 
254381418a27Smrg         // CTFE can generate struct literals that contain an AddrExp pointing
254481418a27Smrg         // to themselves, need to avoid infinite recursion:
254581418a27Smrg         // struct S { this(int){ this.s = &this; } S* s; }
254681418a27Smrg         // const foo = new S(0);
254781418a27Smrg         if (e->stageflags & stageToCBuffer)
254881418a27Smrg             buf->writestring("<recursion>");
254981418a27Smrg         else
255081418a27Smrg         {
255181418a27Smrg             int old = e->stageflags;
255281418a27Smrg             e->stageflags |= stageToCBuffer;
255381418a27Smrg             argsToBuffer(e->elements);
255481418a27Smrg             e->stageflags = old;
255581418a27Smrg         }
255681418a27Smrg 
255781418a27Smrg         buf->writeByte(')');
255881418a27Smrg     }
255981418a27Smrg 
visit(TypeExp * e)256081418a27Smrg     void visit(TypeExp *e)
256181418a27Smrg     {
256281418a27Smrg         typeToBuffer(e->type, NULL);
256381418a27Smrg     }
256481418a27Smrg 
visit(ScopeExp * e)256581418a27Smrg     void visit(ScopeExp *e)
256681418a27Smrg     {
256781418a27Smrg         if (e->sds->isTemplateInstance())
256881418a27Smrg         {
256981418a27Smrg             e->sds->accept(this);
257081418a27Smrg         }
257181418a27Smrg         else if (hgs != NULL && hgs->ddoc)
257281418a27Smrg         {
257381418a27Smrg             // fixes bug 6491
257481418a27Smrg             Module *m = e->sds->isModule();
257581418a27Smrg             if (m)
257681418a27Smrg                 buf->writestring(m->md->toChars());
257781418a27Smrg             else
257881418a27Smrg                 buf->writestring(e->sds->toChars());
257981418a27Smrg         }
258081418a27Smrg         else
258181418a27Smrg         {
258281418a27Smrg             buf->writestring(e->sds->kind());
258381418a27Smrg             buf->writeByte(' ');
258481418a27Smrg             buf->writestring(e->sds->toChars());
258581418a27Smrg         }
258681418a27Smrg     }
258781418a27Smrg 
visit(TemplateExp * e)258881418a27Smrg     void visit(TemplateExp *e)
258981418a27Smrg     {
259081418a27Smrg         buf->writestring(e->td->toChars());
259181418a27Smrg     }
259281418a27Smrg 
visit(NewExp * e)259381418a27Smrg     void visit(NewExp *e)
259481418a27Smrg     {
259581418a27Smrg         if (e->thisexp)
259681418a27Smrg         {
259781418a27Smrg             expToBuffer(e->thisexp, PREC_primary);
259881418a27Smrg             buf->writeByte('.');
259981418a27Smrg         }
260081418a27Smrg         buf->writestring("new ");
260181418a27Smrg         if (e->newargs && e->newargs->dim)
260281418a27Smrg         {
260381418a27Smrg             buf->writeByte('(');
260481418a27Smrg             argsToBuffer(e->newargs);
260581418a27Smrg             buf->writeByte(')');
260681418a27Smrg         }
260781418a27Smrg         typeToBuffer(e->newtype, NULL);
260881418a27Smrg         if (e->arguments && e->arguments->dim)
260981418a27Smrg         {
261081418a27Smrg             buf->writeByte('(');
261181418a27Smrg             argsToBuffer(e->arguments);
261281418a27Smrg             buf->writeByte(')');
261381418a27Smrg         }
261481418a27Smrg     }
261581418a27Smrg 
visit(NewAnonClassExp * e)261681418a27Smrg     void visit(NewAnonClassExp *e)
261781418a27Smrg     {
261881418a27Smrg         if (e->thisexp)
261981418a27Smrg         {
262081418a27Smrg             expToBuffer(e->thisexp, PREC_primary);
262181418a27Smrg             buf->writeByte('.');
262281418a27Smrg         }
262381418a27Smrg         buf->writestring("new");
262481418a27Smrg         if (e->newargs && e->newargs->dim)
262581418a27Smrg         {
262681418a27Smrg             buf->writeByte('(');
262781418a27Smrg             argsToBuffer(e->newargs);
262881418a27Smrg             buf->writeByte(')');
262981418a27Smrg         }
263081418a27Smrg         buf->writestring(" class ");
263181418a27Smrg         if (e->arguments && e->arguments->dim)
263281418a27Smrg         {
263381418a27Smrg             buf->writeByte('(');
263481418a27Smrg             argsToBuffer(e->arguments);
263581418a27Smrg             buf->writeByte(')');
263681418a27Smrg         }
263781418a27Smrg         if (e->cd)
263881418a27Smrg             e->cd->accept(this);
263981418a27Smrg     }
264081418a27Smrg 
visit(SymOffExp * e)264181418a27Smrg     void visit(SymOffExp *e)
264281418a27Smrg     {
264381418a27Smrg         if (e->offset)
264481418a27Smrg             buf->printf("(& %s+%u)", e->var->toChars(), e->offset);
264581418a27Smrg         else if (e->var->isTypeInfoDeclaration())
264681418a27Smrg             buf->printf("%s", e->var->toChars());
264781418a27Smrg         else
264881418a27Smrg             buf->printf("& %s", e->var->toChars());
264981418a27Smrg     }
265081418a27Smrg 
visit(VarExp * e)265181418a27Smrg     void visit(VarExp *e)
265281418a27Smrg     {
265381418a27Smrg         buf->writestring(e->var->toChars());
265481418a27Smrg     }
265581418a27Smrg 
visit(OverExp * e)265681418a27Smrg     void visit(OverExp *e)
265781418a27Smrg     {
265881418a27Smrg         buf->writestring(e->vars->ident->toChars());
265981418a27Smrg     }
266081418a27Smrg 
visit(TupleExp * e)266181418a27Smrg     void visit(TupleExp *e)
266281418a27Smrg     {
266381418a27Smrg         if (e->e0)
266481418a27Smrg         {
266581418a27Smrg             buf->writeByte('(');
266681418a27Smrg             e->e0->accept(this);
266781418a27Smrg             buf->writestring(", tuple(");
266881418a27Smrg             argsToBuffer(e->exps);
266981418a27Smrg             buf->writestring("))");
267081418a27Smrg         }
267181418a27Smrg         else
267281418a27Smrg         {
267381418a27Smrg             buf->writestring("tuple(");
267481418a27Smrg             argsToBuffer(e->exps);
267581418a27Smrg             buf->writeByte(')');
267681418a27Smrg         }
267781418a27Smrg     }
267881418a27Smrg 
visit(FuncExp * e)267981418a27Smrg     void visit(FuncExp *e)
268081418a27Smrg     {
268181418a27Smrg         e->fd->accept(this);
268281418a27Smrg         //buf->writestring(e->fd->toChars());
268381418a27Smrg     }
268481418a27Smrg 
visit(DeclarationExp * e)268581418a27Smrg     void visit(DeclarationExp *e)
268681418a27Smrg     {
268781418a27Smrg         /* Normal dmd execution won't reach here - regular variable declarations
268881418a27Smrg          * are handled in visit(ExpStatement), so here would be used only when
268981418a27Smrg          * we'll directly call Expression::toChars() for debugging.
269081418a27Smrg          */
269181418a27Smrg         if (VarDeclaration *v = e->declaration->isVarDeclaration())
269281418a27Smrg         {
269381418a27Smrg             // For debugging use:
269481418a27Smrg             // - Avoid printing newline.
269581418a27Smrg             // - Intentionally use the format (Type var;)
269681418a27Smrg             //   which isn't correct as regular D code.
269781418a27Smrg             buf->writeByte('(');
269881418a27Smrg             visitVarDecl(v, false);
269981418a27Smrg             buf->writeByte(';');
270081418a27Smrg             buf->writeByte(')');
270181418a27Smrg         }
270281418a27Smrg         else
270381418a27Smrg             e->declaration->accept(this);
270481418a27Smrg     }
270581418a27Smrg 
visit(TypeidExp * e)270681418a27Smrg     void visit(TypeidExp *e)
270781418a27Smrg     {
270881418a27Smrg         buf->writestring("typeid(");
270981418a27Smrg         objectToBuffer(e->obj);
271081418a27Smrg         buf->writeByte(')');
271181418a27Smrg     }
271281418a27Smrg 
visit(TraitsExp * e)271381418a27Smrg     void visit(TraitsExp *e)
271481418a27Smrg     {
271581418a27Smrg         buf->writestring("__traits(");
2716*dd083157Smrg         if (e->ident)
271781418a27Smrg             buf->writestring(e->ident->toChars());
271881418a27Smrg         if (e->args)
271981418a27Smrg         {
272081418a27Smrg             for (size_t i = 0; i < e->args->dim; i++)
272181418a27Smrg             {
272281418a27Smrg                 RootObject *arg = (*e->args)[i];
272381418a27Smrg                 buf->writestring(", ");
272481418a27Smrg                 objectToBuffer(arg);
272581418a27Smrg             }
272681418a27Smrg         }
272781418a27Smrg         buf->writeByte(')');
272881418a27Smrg     }
272981418a27Smrg 
visit(HaltExp *)273081418a27Smrg     void visit(HaltExp *)
273181418a27Smrg     {
273281418a27Smrg         buf->writestring("halt");
273381418a27Smrg     }
273481418a27Smrg 
visit(IsExp * e)273581418a27Smrg     void visit(IsExp *e)
273681418a27Smrg     {
273781418a27Smrg         buf->writestring("is(");
273881418a27Smrg         typeToBuffer(e->targ, e->id);
273981418a27Smrg         if (e->tok2 != TOKreserved)
274081418a27Smrg         {
274181418a27Smrg             buf->printf(" %s %s", Token::toChars(e->tok), Token::toChars(e->tok2));
274281418a27Smrg         }
274381418a27Smrg         else if (e->tspec)
274481418a27Smrg         {
274581418a27Smrg             if (e->tok == TOKcolon)
274681418a27Smrg                 buf->writestring(" : ");
274781418a27Smrg             else
274881418a27Smrg                 buf->writestring(" == ");
274981418a27Smrg             typeToBuffer(e->tspec, NULL);
275081418a27Smrg         }
275181418a27Smrg         if (e->parameters && e->parameters->dim)
275281418a27Smrg         {
275381418a27Smrg             buf->writestring(", ");
275481418a27Smrg             visitTemplateParameters(e->parameters);
275581418a27Smrg         }
275681418a27Smrg         buf->writeByte(')');
275781418a27Smrg     }
275881418a27Smrg 
visit(UnaExp * e)275981418a27Smrg     void visit(UnaExp *e)
276081418a27Smrg     {
276181418a27Smrg         buf->writestring(Token::toChars(e->op));
276281418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
276381418a27Smrg     }
276481418a27Smrg 
visit(BinExp * e)276581418a27Smrg     void visit(BinExp *e)
276681418a27Smrg     {
276781418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
276881418a27Smrg         buf->writeByte(' ');
276981418a27Smrg         buf->writestring(Token::toChars(e->op));
277081418a27Smrg         buf->writeByte(' ');
277181418a27Smrg         expToBuffer(e->e2, (PREC)(precedence[e->op] + 1));
277281418a27Smrg     }
277381418a27Smrg 
visit(CompileExp * e)277481418a27Smrg     void visit(CompileExp *e)
277581418a27Smrg     {
277681418a27Smrg         buf->writestring("mixin(");
277781418a27Smrg         expToBuffer(e->e1, PREC_assign);
277881418a27Smrg         buf->writeByte(')');
277981418a27Smrg     }
278081418a27Smrg 
visit(ImportExp * e)278181418a27Smrg     void visit(ImportExp *e)
278281418a27Smrg     {
278381418a27Smrg         buf->writestring("import(");
278481418a27Smrg         expToBuffer(e->e1, PREC_assign);
278581418a27Smrg         buf->writeByte(')');
278681418a27Smrg     }
278781418a27Smrg 
visit(AssertExp * e)278881418a27Smrg     void visit(AssertExp *e)
278981418a27Smrg     {
279081418a27Smrg         buf->writestring("assert(");
279181418a27Smrg         expToBuffer(e->e1, PREC_assign);
279281418a27Smrg         if (e->msg)
279381418a27Smrg         {
279481418a27Smrg             buf->writestring(", ");
279581418a27Smrg             expToBuffer(e->msg, PREC_assign);
279681418a27Smrg         }
279781418a27Smrg         buf->writeByte(')');
279881418a27Smrg     }
279981418a27Smrg 
visit(DotIdExp * e)280081418a27Smrg     void visit(DotIdExp *e)
280181418a27Smrg     {
280281418a27Smrg         expToBuffer(e->e1, PREC_primary);
280381418a27Smrg         buf->writeByte('.');
280481418a27Smrg         buf->writestring(e->ident->toChars());
280581418a27Smrg     }
280681418a27Smrg 
visit(DotTemplateExp * e)280781418a27Smrg     void visit(DotTemplateExp *e)
280881418a27Smrg     {
280981418a27Smrg         expToBuffer(e->e1, PREC_primary);
281081418a27Smrg         buf->writeByte('.');
281181418a27Smrg         buf->writestring(e->td->toChars());
281281418a27Smrg     }
281381418a27Smrg 
visit(DotVarExp * e)281481418a27Smrg     void visit(DotVarExp *e)
281581418a27Smrg     {
281681418a27Smrg         expToBuffer(e->e1, PREC_primary);
281781418a27Smrg         buf->writeByte('.');
281881418a27Smrg         buf->writestring(e->var->toChars());
281981418a27Smrg     }
282081418a27Smrg 
visit(DotTemplateInstanceExp * e)282181418a27Smrg     void visit(DotTemplateInstanceExp *e)
282281418a27Smrg     {
282381418a27Smrg         expToBuffer(e->e1, PREC_primary);
282481418a27Smrg         buf->writeByte('.');
282581418a27Smrg         e->ti->accept(this);
282681418a27Smrg     }
282781418a27Smrg 
visit(DelegateExp * e)282881418a27Smrg     void visit(DelegateExp *e)
282981418a27Smrg     {
283081418a27Smrg         buf->writeByte('&');
283181418a27Smrg         if (!e->func->isNested())
283281418a27Smrg         {
283381418a27Smrg             expToBuffer(e->e1, PREC_primary);
283481418a27Smrg             buf->writeByte('.');
283581418a27Smrg         }
283681418a27Smrg         buf->writestring(e->func->toChars());
283781418a27Smrg     }
283881418a27Smrg 
visit(DotTypeExp * e)283981418a27Smrg     void visit(DotTypeExp *e)
284081418a27Smrg     {
284181418a27Smrg         expToBuffer(e->e1, PREC_primary);
284281418a27Smrg         buf->writeByte('.');
284381418a27Smrg         buf->writestring(e->sym->toChars());
284481418a27Smrg     }
284581418a27Smrg 
visit(CallExp * e)284681418a27Smrg     void visit(CallExp *e)
284781418a27Smrg     {
284881418a27Smrg         if (e->e1->op == TOKtype)
284981418a27Smrg         {
285081418a27Smrg             /* Avoid parens around type to prevent forbidden cast syntax:
285181418a27Smrg              *   (sometype)(arg1)
285281418a27Smrg              * This is ok since types in constructor calls
285381418a27Smrg              * can never depend on parens anyway
285481418a27Smrg              */
285581418a27Smrg             e->e1->accept(this);
285681418a27Smrg         }
285781418a27Smrg         else
285881418a27Smrg             expToBuffer(e->e1, precedence[e->op]);
285981418a27Smrg         buf->writeByte('(');
286081418a27Smrg         argsToBuffer(e->arguments);
286181418a27Smrg         buf->writeByte(')');
286281418a27Smrg     }
286381418a27Smrg 
visit(PtrExp * e)286481418a27Smrg     void visit(PtrExp *e)
286581418a27Smrg     {
286681418a27Smrg         buf->writeByte('*');
286781418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
286881418a27Smrg     }
286981418a27Smrg 
visit(DeleteExp * e)287081418a27Smrg     void visit(DeleteExp *e)
287181418a27Smrg     {
287281418a27Smrg         buf->writestring("delete ");
287381418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
287481418a27Smrg     }
287581418a27Smrg 
visit(CastExp * e)287681418a27Smrg     void visit(CastExp *e)
287781418a27Smrg     {
287881418a27Smrg         buf->writestring("cast(");
287981418a27Smrg         if (e->to)
288081418a27Smrg             typeToBuffer(e->to, NULL);
288181418a27Smrg         else
288281418a27Smrg         {
288381418a27Smrg             MODtoBuffer(buf, e->mod);
288481418a27Smrg         }
288581418a27Smrg         buf->writeByte(')');
288681418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
288781418a27Smrg     }
288881418a27Smrg 
visit(VectorExp * e)288981418a27Smrg     void visit(VectorExp *e)
289081418a27Smrg     {
289181418a27Smrg         buf->writestring("cast(");
289281418a27Smrg         typeToBuffer(e->to, NULL);
289381418a27Smrg         buf->writeByte(')');
289481418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
289581418a27Smrg     }
289681418a27Smrg 
visit(VectorArrayExp * e)289781418a27Smrg     void visit(VectorArrayExp *e)
289881418a27Smrg     {
289981418a27Smrg         expToBuffer(e->e1, PREC_primary);
290081418a27Smrg         buf->writestring(".array");
290181418a27Smrg     }
290281418a27Smrg 
visit(SliceExp * e)290381418a27Smrg     void visit(SliceExp *e)
290481418a27Smrg     {
290581418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
290681418a27Smrg         buf->writeByte('[');
290781418a27Smrg         if (e->upr || e->lwr)
290881418a27Smrg         {
290981418a27Smrg             if (e->lwr)
291081418a27Smrg                 sizeToBuffer(e->lwr);
291181418a27Smrg             else
291281418a27Smrg                 buf->writeByte('0');
291381418a27Smrg             buf->writestring("..");
291481418a27Smrg             if (e->upr)
291581418a27Smrg                 sizeToBuffer(e->upr);
291681418a27Smrg             else
291781418a27Smrg                 buf->writeByte('$');
291881418a27Smrg         }
291981418a27Smrg         buf->writeByte(']');
292081418a27Smrg     }
292181418a27Smrg 
visit(ArrayLengthExp * e)292281418a27Smrg     void visit(ArrayLengthExp *e)
292381418a27Smrg     {
292481418a27Smrg         expToBuffer(e->e1, PREC_primary);
292581418a27Smrg         buf->writestring(".length");
292681418a27Smrg     }
292781418a27Smrg 
visit(IntervalExp * e)292881418a27Smrg     void visit(IntervalExp *e)
292981418a27Smrg     {
293081418a27Smrg         expToBuffer(e->lwr, PREC_assign);
293181418a27Smrg         buf->writestring("..");
293281418a27Smrg         expToBuffer(e->upr, PREC_assign);
293381418a27Smrg     }
293481418a27Smrg 
visit(DelegatePtrExp * e)293581418a27Smrg     void visit(DelegatePtrExp *e)
293681418a27Smrg     {
293781418a27Smrg         expToBuffer(e->e1, PREC_primary);
293881418a27Smrg         buf->writestring(".ptr");
293981418a27Smrg     }
294081418a27Smrg 
visit(DelegateFuncptrExp * e)294181418a27Smrg     void visit(DelegateFuncptrExp *e)
294281418a27Smrg     {
294381418a27Smrg         expToBuffer(e->e1, PREC_primary);
294481418a27Smrg         buf->writestring(".funcptr");
294581418a27Smrg     }
294681418a27Smrg 
visit(ArrayExp * e)294781418a27Smrg     void visit(ArrayExp *e)
294881418a27Smrg     {
294981418a27Smrg         expToBuffer(e->e1, PREC_primary);
295081418a27Smrg         buf->writeByte('[');
295181418a27Smrg         argsToBuffer(e->arguments);
295281418a27Smrg         buf->writeByte(']');
295381418a27Smrg     }
295481418a27Smrg 
visit(DotExp * e)295581418a27Smrg     void visit(DotExp *e)
295681418a27Smrg     {
295781418a27Smrg         expToBuffer(e->e1, PREC_primary);
295881418a27Smrg         buf->writeByte('.');
295981418a27Smrg         expToBuffer(e->e2, PREC_primary);
296081418a27Smrg     }
296181418a27Smrg 
visit(IndexExp * e)296281418a27Smrg     void visit(IndexExp *e)
296381418a27Smrg     {
296481418a27Smrg         expToBuffer(e->e1, PREC_primary);
296581418a27Smrg         buf->writeByte('[');
296681418a27Smrg         sizeToBuffer(e->e2);
296781418a27Smrg         buf->writeByte(']');
296881418a27Smrg     }
296981418a27Smrg 
visit(PostExp * e)297081418a27Smrg     void visit(PostExp *e)
297181418a27Smrg     {
297281418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
297381418a27Smrg         buf->writestring(Token::toChars(e->op));
297481418a27Smrg     }
297581418a27Smrg 
visit(PreExp * e)297681418a27Smrg     void visit(PreExp *e)
297781418a27Smrg     {
297881418a27Smrg         buf->writestring(Token::toChars(e->op));
297981418a27Smrg         expToBuffer(e->e1, precedence[e->op]);
298081418a27Smrg     }
298181418a27Smrg 
visit(RemoveExp * e)298281418a27Smrg     void visit(RemoveExp *e)
298381418a27Smrg     {
298481418a27Smrg         expToBuffer(e->e1, PREC_primary);
298581418a27Smrg         buf->writestring(".remove(");
298681418a27Smrg         expToBuffer(e->e2, PREC_assign);
298781418a27Smrg         buf->writeByte(')');
298881418a27Smrg     }
298981418a27Smrg 
visit(CondExp * e)299081418a27Smrg     void visit(CondExp *e)
299181418a27Smrg     {
299281418a27Smrg         expToBuffer(e->econd, PREC_oror);
299381418a27Smrg         buf->writestring(" ? ");
299481418a27Smrg         expToBuffer(e->e1, PREC_expr);
299581418a27Smrg         buf->writestring(" : ");
299681418a27Smrg         expToBuffer(e->e2, PREC_cond);
299781418a27Smrg     }
299881418a27Smrg 
visit(DefaultInitExp * e)299981418a27Smrg     void visit(DefaultInitExp *e)
300081418a27Smrg     {
300181418a27Smrg         buf->writestring(Token::toChars(e->subop));
300281418a27Smrg     }
300381418a27Smrg 
visit(ClassReferenceExp * e)300481418a27Smrg     void visit(ClassReferenceExp *e)
300581418a27Smrg     {
300681418a27Smrg         buf->writestring(e->value->toChars());
300781418a27Smrg     }
300881418a27Smrg 
300981418a27Smrg     ////////////////////////////////////////////////////////////////////////////
301081418a27Smrg 
visit(TemplateTypeParameter * tp)301181418a27Smrg     void visit(TemplateTypeParameter *tp)
301281418a27Smrg     {
301381418a27Smrg         buf->writestring(tp->ident->toChars());
301481418a27Smrg         if (tp->specType)
301581418a27Smrg         {
301681418a27Smrg             buf->writestring(" : ");
301781418a27Smrg             typeToBuffer(tp->specType, NULL);
301881418a27Smrg         }
301981418a27Smrg         if (tp->defaultType)
302081418a27Smrg         {
302181418a27Smrg             buf->writestring(" = ");
302281418a27Smrg             typeToBuffer(tp->defaultType, NULL);
302381418a27Smrg         }
302481418a27Smrg     }
302581418a27Smrg 
visit(TemplateThisParameter * tp)302681418a27Smrg     void visit(TemplateThisParameter *tp)
302781418a27Smrg     {
302881418a27Smrg         buf->writestring("this ");
302981418a27Smrg         visit((TemplateTypeParameter *)tp);
303081418a27Smrg     }
303181418a27Smrg 
visit(TemplateAliasParameter * tp)303281418a27Smrg     void visit(TemplateAliasParameter *tp)
303381418a27Smrg     {
303481418a27Smrg         buf->writestring("alias ");
303581418a27Smrg         if (tp->specType)
303681418a27Smrg             typeToBuffer(tp->specType, tp->ident);
303781418a27Smrg         else
303881418a27Smrg             buf->writestring(tp->ident->toChars());
303981418a27Smrg         if (tp->specAlias)
304081418a27Smrg         {
304181418a27Smrg             buf->writestring(" : ");
304281418a27Smrg             objectToBuffer(tp->specAlias);
304381418a27Smrg         }
304481418a27Smrg         if (tp->defaultAlias)
304581418a27Smrg         {
304681418a27Smrg             buf->writestring(" = ");
304781418a27Smrg             objectToBuffer(tp->defaultAlias);
304881418a27Smrg         }
304981418a27Smrg     }
305081418a27Smrg 
visit(TemplateValueParameter * tp)305181418a27Smrg     void visit(TemplateValueParameter *tp)
305281418a27Smrg     {
305381418a27Smrg         typeToBuffer(tp->valType, tp->ident);
305481418a27Smrg         if (tp->specValue)
305581418a27Smrg         {
305681418a27Smrg             buf->writestring(" : ");
305781418a27Smrg             tp->specValue->accept(this);
305881418a27Smrg         }
305981418a27Smrg         if (tp->defaultValue)
306081418a27Smrg         {
306181418a27Smrg             buf->writestring(" = ");
306281418a27Smrg             tp->defaultValue->accept(this);
306381418a27Smrg         }
306481418a27Smrg     }
306581418a27Smrg 
visit(TemplateTupleParameter * tp)306681418a27Smrg     void visit(TemplateTupleParameter *tp)
306781418a27Smrg     {
306881418a27Smrg         buf->writestring(tp->ident->toChars());
306981418a27Smrg         buf->writestring("...");
307081418a27Smrg     }
307181418a27Smrg 
307281418a27Smrg     ////////////////////////////////////////////////////////////////////////////
307381418a27Smrg 
visit(DebugCondition * c)307481418a27Smrg     void visit(DebugCondition *c)
307581418a27Smrg     {
307681418a27Smrg         if (c->ident)
307781418a27Smrg             buf->printf("debug (%s)", c->ident->toChars());
307881418a27Smrg         else
307981418a27Smrg             buf->printf("debug (%u)", c->level);
308081418a27Smrg     }
308181418a27Smrg 
visit(VersionCondition * c)308281418a27Smrg     void visit(VersionCondition *c)
308381418a27Smrg     {
308481418a27Smrg         if (c->ident)
308581418a27Smrg             buf->printf("version (%s)", c->ident->toChars());
308681418a27Smrg         else
308781418a27Smrg             buf->printf("version (%u)", c->level);
308881418a27Smrg     }
308981418a27Smrg 
visit(StaticIfCondition * c)309081418a27Smrg     void visit(StaticIfCondition *c)
309181418a27Smrg     {
309281418a27Smrg         buf->writestring("static if (");
309381418a27Smrg         c->exp->accept(this);
309481418a27Smrg         buf->writeByte(')');
309581418a27Smrg     }
309681418a27Smrg 
309781418a27Smrg     ////////////////////////////////////////////////////////////////////////////
309881418a27Smrg 
visit(Parameter * p)309981418a27Smrg     void visit(Parameter *p)
310081418a27Smrg     {
310181418a27Smrg         if (p->storageClass & STCauto)
310281418a27Smrg             buf->writestring("auto ");
310381418a27Smrg 
310481418a27Smrg         if (p->storageClass & STCreturn)
310581418a27Smrg             buf->writestring("return ");
310681418a27Smrg 
310781418a27Smrg         if (p->storageClass & STCout)
310881418a27Smrg             buf->writestring("out ");
310981418a27Smrg         else if (p->storageClass & STCref)
311081418a27Smrg             buf->writestring("ref ");
311181418a27Smrg         else if (p->storageClass & STCin)
311281418a27Smrg             buf->writestring("in ");
311381418a27Smrg         else if (p->storageClass & STClazy)
311481418a27Smrg             buf->writestring("lazy ");
311581418a27Smrg         else if (p->storageClass & STCalias)
311681418a27Smrg             buf->writestring("alias ");
311781418a27Smrg 
311881418a27Smrg         StorageClass stc = p->storageClass;
311981418a27Smrg         if (p->type && p->type->mod & MODshared)
312081418a27Smrg             stc &= ~STCshared;
312181418a27Smrg 
312281418a27Smrg         if (stcToBuffer(buf, stc & (STCconst | STCimmutable | STCwild | STCshared | STCscope | STCscopeinferred)))
312381418a27Smrg             buf->writeByte(' ');
312481418a27Smrg 
312581418a27Smrg         if (p->storageClass & STCalias)
312681418a27Smrg         {
312781418a27Smrg             if (p->ident)
312881418a27Smrg                 buf->writestring(p->ident->toChars());
312981418a27Smrg         }
313081418a27Smrg         else if (p->type->ty == Tident &&
313181418a27Smrg                  strlen(((TypeIdentifier *)p->type)->ident->toChars()) > 3 &&
313281418a27Smrg                  strncmp(((TypeIdentifier *)p->type)->ident->toChars(), "__T", 3) == 0)
313381418a27Smrg         {
313481418a27Smrg             // print parameter name, instead of undetermined type parameter
313581418a27Smrg             buf->writestring(p->ident->toChars());
313681418a27Smrg         }
313781418a27Smrg         else
313881418a27Smrg             typeToBuffer(p->type, p->ident);
313981418a27Smrg         if (p->defaultArg)
314081418a27Smrg         {
314181418a27Smrg             buf->writestring(" = ");
314281418a27Smrg             p->defaultArg->accept(this);
314381418a27Smrg         }
314481418a27Smrg     }
314581418a27Smrg 
parametersToBuffer(Parameters * parameters,int varargs)314681418a27Smrg     void parametersToBuffer(Parameters *parameters, int varargs)
314781418a27Smrg     {
314881418a27Smrg         buf->writeByte('(');
314981418a27Smrg         if (parameters)
315081418a27Smrg         {
315181418a27Smrg             size_t dim = Parameter::dim(parameters);
315281418a27Smrg             for (size_t i = 0; i < dim; i++)
315381418a27Smrg             {
315481418a27Smrg                 if (i)
315581418a27Smrg                     buf->writestring(", ");
315681418a27Smrg                 Parameter *fparam = Parameter::getNth(parameters, i);
315781418a27Smrg                 fparam->accept(this);
315881418a27Smrg             }
315981418a27Smrg             if (varargs)
316081418a27Smrg             {
316181418a27Smrg                 if (parameters->dim && varargs == 1)
316281418a27Smrg                     buf->writestring(", ");
316381418a27Smrg                 buf->writestring("...");
316481418a27Smrg             }
316581418a27Smrg         }
316681418a27Smrg         buf->writeByte(')');
316781418a27Smrg     }
316881418a27Smrg 
visit(Module * m)316981418a27Smrg     void visit(Module *m)
317081418a27Smrg     {
317181418a27Smrg         if (m->md)
317281418a27Smrg         {
317381418a27Smrg             if (m->userAttribDecl)
317481418a27Smrg             {
317581418a27Smrg                 buf->writestring("@(");
317681418a27Smrg                 argsToBuffer(m->userAttribDecl->atts);
317781418a27Smrg                 buf->writeByte(')');
317881418a27Smrg                 buf->writenl();
317981418a27Smrg             }
318081418a27Smrg             if (m->md->isdeprecated)
318181418a27Smrg             {
318281418a27Smrg                 if (m->md->msg)
318381418a27Smrg                 {
318481418a27Smrg                     buf->writestring("deprecated(");
318581418a27Smrg                     m->md->msg->accept(this);
318681418a27Smrg                     buf->writestring(") ");
318781418a27Smrg                 }
318881418a27Smrg                 else
318981418a27Smrg                     buf->writestring("deprecated ");
319081418a27Smrg             }
319181418a27Smrg 
319281418a27Smrg             buf->writestring("module ");
319381418a27Smrg             buf->writestring(m->md->toChars());
319481418a27Smrg             buf->writeByte(';');
319581418a27Smrg             buf->writenl();
319681418a27Smrg         }
319781418a27Smrg         for (size_t i = 0; i < m->members->dim; i++)
319881418a27Smrg         {
319981418a27Smrg             Dsymbol *s = (*m->members)[i];
320081418a27Smrg             s->accept(this);
320181418a27Smrg         }
320281418a27Smrg     }
320381418a27Smrg };
320481418a27Smrg 
toCBuffer(Statement * s,OutBuffer * buf,HdrGenState * hgs)320581418a27Smrg void toCBuffer(Statement *s, OutBuffer *buf, HdrGenState *hgs)
320681418a27Smrg {
320781418a27Smrg     PrettyPrintVisitor v(buf, hgs);
320881418a27Smrg     s->accept(&v);
320981418a27Smrg }
321081418a27Smrg 
toCBuffer(Type * t,OutBuffer * buf,Identifier * ident,HdrGenState * hgs)321181418a27Smrg void toCBuffer(Type *t, OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
321281418a27Smrg {
321381418a27Smrg     PrettyPrintVisitor v(buf, hgs);
321481418a27Smrg     v.typeToBuffer(t, ident);
321581418a27Smrg }
321681418a27Smrg 
toCBuffer(Dsymbol * s,OutBuffer * buf,HdrGenState * hgs)321781418a27Smrg void toCBuffer(Dsymbol *s, OutBuffer *buf, HdrGenState *hgs)
321881418a27Smrg {
321981418a27Smrg     PrettyPrintVisitor v(buf, hgs);
322081418a27Smrg     s->accept(&v);
322181418a27Smrg }
322281418a27Smrg 
322381418a27Smrg // used from TemplateInstance::toChars() and TemplateMixin::toChars()
toCBufferInstance(TemplateInstance * ti,OutBuffer * buf,bool qualifyTypes)322481418a27Smrg void toCBufferInstance(TemplateInstance *ti, OutBuffer *buf, bool qualifyTypes)
322581418a27Smrg {
322681418a27Smrg     HdrGenState hgs;
322781418a27Smrg     hgs.fullQual = qualifyTypes;
322881418a27Smrg     PrettyPrintVisitor v(buf, &hgs);
322981418a27Smrg     v.visit(ti);
323081418a27Smrg }
323181418a27Smrg 
toCBuffer(Initializer * iz,OutBuffer * buf,HdrGenState * hgs)323281418a27Smrg void toCBuffer(Initializer *iz, OutBuffer *buf, HdrGenState *hgs)
323381418a27Smrg {
323481418a27Smrg     PrettyPrintVisitor v(buf, hgs);
323581418a27Smrg     iz->accept(&v);
323681418a27Smrg }
323781418a27Smrg 
stcToBuffer(OutBuffer * buf,StorageClass stc)323881418a27Smrg bool stcToBuffer(OutBuffer *buf, StorageClass stc)
323981418a27Smrg {
324081418a27Smrg     bool result = false;
324181418a27Smrg     if ((stc & (STCreturn | STCscope)) == (STCreturn | STCscope))
324281418a27Smrg         stc &= ~STCscope;
324381418a27Smrg     if (stc & STCscopeinferred)
324481418a27Smrg         stc &= ~(STCscope | STCscopeinferred);
324581418a27Smrg     while (stc)
324681418a27Smrg     {
324781418a27Smrg         const char *p = stcToChars(stc);
324881418a27Smrg         if (!p)
324981418a27Smrg             break;
325081418a27Smrg         if (!result)
325181418a27Smrg             result = true;
325281418a27Smrg         else
325381418a27Smrg             buf->writeByte(' ');
325481418a27Smrg         buf->writestring(p);
325581418a27Smrg     }
325681418a27Smrg     return result;
325781418a27Smrg }
325881418a27Smrg 
325981418a27Smrg /*************************************************
326081418a27Smrg  * Pick off one of the storage classes from stc,
326181418a27Smrg  * and return a pointer to a string representation of it.
326281418a27Smrg  * stc is reduced by the one picked.
326381418a27Smrg  */
stcToChars(StorageClass & stc)326481418a27Smrg const char *stcToChars(StorageClass& stc)
326581418a27Smrg {
326681418a27Smrg     struct SCstring
326781418a27Smrg     {
326881418a27Smrg         StorageClass stc;
326981418a27Smrg         TOK tok;
327081418a27Smrg         const char *id;
327181418a27Smrg     };
327281418a27Smrg 
327381418a27Smrg     static SCstring table[] =
327481418a27Smrg     {
327581418a27Smrg         { STCauto,         TOKauto,     NULL },
327681418a27Smrg         { STCscope,        TOKscope,    NULL },
327781418a27Smrg         { STCstatic,       TOKstatic,   NULL },
327881418a27Smrg         { STCextern,       TOKextern,   NULL },
327981418a27Smrg         { STCconst,        TOKconst,    NULL },
328081418a27Smrg         { STCfinal,        TOKfinal,    NULL },
328181418a27Smrg         { STCabstract,     TOKabstract, NULL },
328281418a27Smrg         { STCsynchronized, TOKsynchronized, NULL },
328381418a27Smrg         { STCdeprecated,   TOKdeprecated, NULL },
328481418a27Smrg         { STCoverride,     TOKoverride, NULL },
328581418a27Smrg         { STClazy,         TOKlazy,     NULL },
328681418a27Smrg         { STCalias,        TOKalias,    NULL },
328781418a27Smrg         { STCout,          TOKout,      NULL },
328881418a27Smrg         { STCin,           TOKin,       NULL },
328981418a27Smrg         { STCmanifest,     TOKenum,     NULL },
329081418a27Smrg         { STCimmutable,    TOKimmutable, NULL },
329181418a27Smrg         { STCshared,       TOKshared,   NULL },
329281418a27Smrg         { STCnothrow,      TOKnothrow,  NULL },
329381418a27Smrg         { STCwild,         TOKwild,     NULL },
329481418a27Smrg         { STCpure,         TOKpure,     NULL },
329581418a27Smrg         { STCref,          TOKref,      NULL },
329681418a27Smrg         { STCtls,          TOKreserved, NULL },
329781418a27Smrg         { STCgshared,      TOKgshared,  NULL },
329881418a27Smrg         { STCnogc,         TOKat,       "@nogc" },
329981418a27Smrg         { STCproperty,     TOKat,       "@property" },
330081418a27Smrg         { STCsafe,         TOKat,       "@safe" },
330181418a27Smrg         { STCtrusted,      TOKat,       "@trusted" },
330281418a27Smrg         { STCsystem,       TOKat,       "@system" },
330381418a27Smrg         { STCdisable,      TOKat,       "@disable" },
330481418a27Smrg         { STCfuture,       TOKat,       "@__future" },
3305*dd083157Smrg         { STClocal,        TOKat,       "__local" },
330681418a27Smrg         { 0,               TOKreserved, NULL }
330781418a27Smrg     };
330881418a27Smrg 
330981418a27Smrg     for (int i = 0; table[i].stc; i++)
331081418a27Smrg     {
331181418a27Smrg         StorageClass tbl = table[i].stc;
331281418a27Smrg         assert(tbl & STCStorageClass);
331381418a27Smrg         if (stc & tbl)
331481418a27Smrg         {
331581418a27Smrg             stc &= ~tbl;
331681418a27Smrg             if (tbl == STCtls)  // TOKtls was removed
331781418a27Smrg                 return "__thread";
331881418a27Smrg 
331981418a27Smrg             TOK tok = table[i].tok;
332081418a27Smrg             if (tok == TOKat)
332181418a27Smrg                 return table[i].id;
332281418a27Smrg             else
332381418a27Smrg                 return Token::toChars(tok);
332481418a27Smrg         }
332581418a27Smrg     }
332681418a27Smrg     //printf("stc = %llx\n", stc);
332781418a27Smrg     return NULL;
332881418a27Smrg }
332981418a27Smrg 
trustToBuffer(OutBuffer * buf,TRUST trust)333081418a27Smrg void trustToBuffer(OutBuffer *buf, TRUST trust)
333181418a27Smrg {
333281418a27Smrg     const char *p = trustToChars(trust);
333381418a27Smrg     if (p)
333481418a27Smrg         buf->writestring(p);
333581418a27Smrg }
333681418a27Smrg 
trustToChars(TRUST trust)333781418a27Smrg const char *trustToChars(TRUST trust)
333881418a27Smrg {
333981418a27Smrg     switch (trust)
334081418a27Smrg     {
334181418a27Smrg         case TRUSTdefault:  return NULL;
334281418a27Smrg         case TRUSTsystem:   return "@system";
334381418a27Smrg         case TRUSTtrusted:  return "@trusted";
334481418a27Smrg         case TRUSTsafe:     return "@safe";
334581418a27Smrg         default:            assert(0);
334681418a27Smrg     }
334781418a27Smrg     return NULL;    // never reached
334881418a27Smrg }
334981418a27Smrg 
linkageToBuffer(OutBuffer * buf,LINK linkage)335081418a27Smrg void linkageToBuffer(OutBuffer *buf, LINK linkage)
335181418a27Smrg {
335281418a27Smrg     const char *p = linkageToChars(linkage);
335381418a27Smrg     if (p)
335481418a27Smrg     {
335581418a27Smrg         buf->writestring("extern (");
335681418a27Smrg         buf->writestring(p);
335781418a27Smrg         buf->writeByte(')');
335881418a27Smrg     }
335981418a27Smrg }
336081418a27Smrg 
linkageToChars(LINK linkage)336181418a27Smrg const char *linkageToChars(LINK linkage)
336281418a27Smrg {
336381418a27Smrg     switch (linkage)
336481418a27Smrg     {
336581418a27Smrg         case LINKdefault:   return NULL;
336681418a27Smrg         case LINKd:         return "D";
336781418a27Smrg         case LINKc:         return "C";
336881418a27Smrg         case LINKcpp:       return "C++";
336981418a27Smrg         case LINKwindows:   return "Windows";
337081418a27Smrg         case LINKpascal:    return "Pascal";
337181418a27Smrg         case LINKobjc:      return "Objective-C";
337281418a27Smrg         case LINKsystem:    return "System";
337381418a27Smrg         default:            assert(0);
337481418a27Smrg     }
337581418a27Smrg     return NULL;    // never reached
337681418a27Smrg }
337781418a27Smrg 
protectionToBuffer(OutBuffer * buf,Prot prot)337881418a27Smrg void protectionToBuffer(OutBuffer *buf, Prot prot)
337981418a27Smrg {
338081418a27Smrg     const char *p = protectionToChars(prot.kind);
338181418a27Smrg     if (p)
338281418a27Smrg         buf->writestring(p);
338381418a27Smrg 
338481418a27Smrg     if (prot.kind == PROTpackage && prot.pkg)
338581418a27Smrg     {
338681418a27Smrg         buf->writeByte('(');
338781418a27Smrg         buf->writestring(prot.pkg->toPrettyChars(true));
338881418a27Smrg         buf->writeByte(')');
338981418a27Smrg     }
339081418a27Smrg }
339181418a27Smrg 
protectionToChars(PROTKIND kind)339281418a27Smrg const char *protectionToChars(PROTKIND kind)
339381418a27Smrg {
339481418a27Smrg     switch (kind)
339581418a27Smrg     {
339681418a27Smrg         case PROTundefined: return NULL;
339781418a27Smrg         case PROTnone:      return "none";
339881418a27Smrg         case PROTprivate:   return "private";
339981418a27Smrg         case PROTpackage:   return "package";
340081418a27Smrg         case PROTprotected: return "protected";
340181418a27Smrg         case PROTpublic:    return "public";
340281418a27Smrg         case PROTexport:    return "export";
340381418a27Smrg         default:            assert(0);
340481418a27Smrg     }
340581418a27Smrg     return NULL;    // never reached
340681418a27Smrg }
340781418a27Smrg 
340881418a27Smrg // Print the full function signature with correct ident, attributes and template args
functionToBufferFull(TypeFunction * tf,OutBuffer * buf,Identifier * ident,HdrGenState * hgs,TemplateDeclaration * td)340981418a27Smrg void functionToBufferFull(TypeFunction *tf, OutBuffer *buf, Identifier *ident,
341081418a27Smrg         HdrGenState* hgs, TemplateDeclaration *td)
341181418a27Smrg {
341281418a27Smrg     //printf("TypeFunction::toCBuffer() this = %p\n", this);
341381418a27Smrg     PrettyPrintVisitor v(buf, hgs);
341481418a27Smrg     v.visitFuncIdentWithPrefix(tf, ident, td);
341581418a27Smrg }
341681418a27Smrg 
341781418a27Smrg // ident is inserted before the argument list and will be "function" or "delegate" for a type
functionToBufferWithIdent(TypeFunction * tf,OutBuffer * buf,const char * ident)341881418a27Smrg void functionToBufferWithIdent(TypeFunction *tf, OutBuffer *buf, const char *ident)
341981418a27Smrg {
342081418a27Smrg     HdrGenState hgs;
342181418a27Smrg     PrettyPrintVisitor v(buf, &hgs);
342281418a27Smrg     v.visitFuncIdentWithPostfix(tf, ident);
342381418a27Smrg }
342481418a27Smrg 
toCBuffer(Expression * e,OutBuffer * buf,HdrGenState * hgs)342581418a27Smrg void toCBuffer(Expression *e, OutBuffer *buf, HdrGenState *hgs)
342681418a27Smrg {
342781418a27Smrg     PrettyPrintVisitor v(buf, hgs);
342881418a27Smrg     e->accept(&v);
342981418a27Smrg }
343081418a27Smrg 
343181418a27Smrg /**************************************************
343281418a27Smrg  * Write out argument types to buf.
343381418a27Smrg  */
argExpTypesToCBuffer(OutBuffer * buf,Expressions * arguments)343481418a27Smrg void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments)
343581418a27Smrg {
343681418a27Smrg     if (!arguments || !arguments->dim)
343781418a27Smrg         return;
343881418a27Smrg 
343981418a27Smrg     HdrGenState hgs;
344081418a27Smrg     PrettyPrintVisitor v(buf, &hgs);
344181418a27Smrg     for (size_t i = 0; i < arguments->dim; i++)
344281418a27Smrg     {
344381418a27Smrg         Expression *arg = (*arguments)[i];
344481418a27Smrg         if (i)
344581418a27Smrg             buf->writestring(", ");
344681418a27Smrg         v.typeToBuffer(arg->type, NULL);
344781418a27Smrg     }
344881418a27Smrg }
344981418a27Smrg 
toCBuffer(TemplateParameter * tp,OutBuffer * buf,HdrGenState * hgs)345081418a27Smrg void toCBuffer(TemplateParameter *tp, OutBuffer *buf, HdrGenState *hgs)
345181418a27Smrg {
345281418a27Smrg     PrettyPrintVisitor v(buf, hgs);
345381418a27Smrg     tp->accept(&v);
345481418a27Smrg }
345581418a27Smrg 
arrayObjectsToBuffer(OutBuffer * buf,Objects * objects)345681418a27Smrg void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects)
345781418a27Smrg {
345881418a27Smrg     if (!objects || !objects->dim)
345981418a27Smrg         return;
346081418a27Smrg 
346181418a27Smrg     HdrGenState hgs;
346281418a27Smrg     PrettyPrintVisitor v(buf, &hgs);
346381418a27Smrg     for (size_t i = 0; i < objects->dim; i++)
346481418a27Smrg     {
346581418a27Smrg         RootObject *o = (*objects)[i];
346681418a27Smrg         if (i)
346781418a27Smrg             buf->writestring(", ");
346881418a27Smrg         v.objectToBuffer(o);
346981418a27Smrg     }
347081418a27Smrg }
347181418a27Smrg 
parametersTypeToChars(Parameters * parameters,int varargs)347281418a27Smrg const char *parametersTypeToChars(Parameters *parameters, int varargs)
347381418a27Smrg {
347481418a27Smrg     OutBuffer buf;
347581418a27Smrg     HdrGenState hgs;
347681418a27Smrg     PrettyPrintVisitor v(&buf, &hgs);
347781418a27Smrg     v.parametersToBuffer(parameters, varargs);
347881418a27Smrg     return buf.extractString();
347981418a27Smrg }
3480