2 * Generate $(LINK2 https://dlang.org/dmd-windows.html#interface-files, D interface files).
4 * Also used to convert AST nodes to D code in general, e.g. for error messages or `printf` debugging.
6 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/hdrgen.d, _hdrgen.d)
10 * Documentation: https://dlang.org/phobos/dmd_hdrgen.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/hdrgen.d
16 import core
.stdc
.ctype
;
17 import core
.stdc
.stdio
;
18 import core
.stdc
.string
;
21 import dmd
.arraytypes
;
27 import dmd
.declaration
;
36 import dmd
.expression
;
40 import dmd
.identifier
;
45 import dmd
.root
.complex
;
46 import dmd
.root
.ctfloat
;
47 import dmd
.common
.outbuffer
;
48 import dmd
.root
.rootobject
;
49 import dmd
.root
.string
;
51 import dmd
.staticassert
;
58 bool hdrgen
; /// true if generating header file
59 bool ddoc
; /// true if generating Ddoc file
60 bool fullDump
; /// true if generating a full AST dump file
62 bool fullQual
; /// fully qualify types when printing
69 bool declstring
; // set while declaring alias for string,wstring or dstring
70 EnumDeclaration inEnumDecl
;
73 enum TEST_EMIT_ALL
= 0;
75 /****************************************
76 * Generate a header (.di) file for Module m.
78 * m = Module to generate header for
79 * buf = buffer to write the data to
81 extern (C
++) void genhdrfile(Module m
, ref OutBuffer buf
)
84 buf
.printf("// D import file generated from '%s'", m
.srcfile
.toChars());
88 toCBuffer(m
, buf
, hgs
);
91 /***************************************
92 * Turn a Statement into a string suitable for printf.
95 * s = Statement to convert
99 public extern (C
++) const(char)* toChars(const Statement s
)
103 toCBuffer(s
, buf
, hgs
);
105 return buf
.extractSlice().ptr
;
108 public extern (C
++) const(char)* toChars(const Initializer i
)
112 toCBuffer(i
, buf
, hgs
);
113 return buf
.extractChars();
116 public const(char)[] toString(const Initializer i
)
120 toCBuffer(i
, buf
, hgs
);
121 return buf
.extractSlice();
125 * Dumps the full contents of module `m` to `buf`.
127 * buf = buffer to write to.
128 * m = module to visit all members of.
130 extern (C
++) void moduleToBuffer(ref OutBuffer buf
, Module m
)
134 toCBuffer(m
, buf
, hgs
);
137 void moduleToBuffer2(Module m
, ref OutBuffer buf
, HdrGenState
* hgs
)
141 if (m
.userAttribDecl
)
143 buf
.writestring("@(");
144 argsToBuffer(m
.userAttribDecl
.atts
, buf
, hgs
);
148 if (m
.md
.isdeprecated
)
152 buf
.writestring("deprecated(");
153 m
.md
.msg
.expressionToBuffer(buf
, hgs
);
154 buf
.writestring(") ");
157 buf
.writestring("deprecated ");
159 buf
.writestring("module ");
160 buf
.writestring(m
.md
.toChars());
165 foreach (s
; *m
.members
)
167 s
.dsymbolToBuffer(buf
, hgs
);
171 private void statementToBuffer(Statement s
, ref OutBuffer buf
, HdrGenState
* hgs
)
173 void visitDefaultCase(Statement s
)
175 printf("Statement::toCBuffer() %d\n", s
.stmt
);
176 assert(0, "unrecognized statement in statementToBuffer()");
179 void visitError(ErrorStatement s
)
181 buf
.writestring("__error__");
185 void visitExp(ExpStatement s
)
187 if (s
.exp
&& s
.exp
.op
== EXP
.declaration
&&
188 (cast(DeclarationExp
)s
.exp
).declaration
)
190 // bypass visit(DeclarationExp)
191 (cast(DeclarationExp
)s
.exp
).declaration
.dsymbolToBuffer(buf
, hgs
);
195 s
.exp
.expressionToBuffer(buf
, hgs
);
197 if (!hgs
.forStmtInit
)
201 void visitDtorExp(DtorExpStatement s
)
206 void visitMixin(MixinStatement s
)
208 buf
.writestring("mixin(");
209 argsToBuffer(s
.exps
, buf
, hgs
, null);
210 buf
.writestring(");");
211 if (!hgs
.forStmtInit
)
215 void visitCompound(CompoundStatement s
)
217 foreach (sx
; *s
.statements
)
220 sx
.statementToBuffer(buf
, hgs
);
224 void visitCompoundAsm(CompoundAsmStatement s
)
229 void visitCompoundDeclaration(CompoundDeclarationStatement s
)
231 bool anywritten
= false;
232 foreach (sx
; *s
.statements
)
234 auto ds = sx ? sx
.isExpStatement() : null;
235 if (ds && ds.exp
.isDeclarationExp())
237 auto d
= ds.exp
.isDeclarationExp().declaration
;
238 if (auto v
= d
.isVarDeclaration())
240 visitVarDecl(v
, anywritten
, buf
, *hgs
);
243 d
.dsymbolToBuffer(buf
, hgs
);
248 if (!hgs
.forStmtInit
)
252 void visitUnrolledLoop(UnrolledLoopStatement s
)
254 buf
.writestring("/*unrolled*/ {");
257 foreach (sx
; *s
.statements
)
260 sx
.statementToBuffer(buf
, hgs
);
267 void visitScope(ScopeStatement s
)
273 s
.statement
.statementToBuffer(buf
, hgs
);
279 void visitWhile(WhileStatement s
)
281 buf
.writestring("while (");
282 if (auto p
= s
.param
)
284 // Print condition assignment
285 StorageClass
stc = p
.storageClass
;
288 if (stcToBuffer(buf
, stc))
291 typeToBuffer(p
.type
, p
.ident
, buf
, hgs
);
293 buf
.writestring(p
.ident
.toString());
294 buf
.writestring(" = ");
296 s
.condition
.expressionToBuffer(buf
, hgs
);
300 s
._body
.statementToBuffer(buf
, hgs
);
303 void visitDo(DoStatement s
)
305 buf
.writestring("do");
308 s
._body
.statementToBuffer(buf
, hgs
);
309 buf
.writestring("while (");
310 s
.condition
.expressionToBuffer(buf
, hgs
);
311 buf
.writestring(");");
315 void visitFor(ForStatement s
)
317 buf
.writestring("for (");
321 s
._init
.statementToBuffer(buf
, hgs
);
329 s
.condition
.expressionToBuffer(buf
, hgs
);
335 s
.increment
.expressionToBuffer(buf
, hgs
);
343 s
._body
.statementToBuffer(buf
, hgs
);
349 void foreachWithoutBody(ForeachStatement s
)
351 buf
.writestring(Token
.toString(s
.op
));
352 buf
.writestring(" (");
353 foreach (i
, p
; *s
.parameters
)
356 buf
.writestring(", ");
357 if (stcToBuffer(buf
, p
.storageClass
))
360 typeToBuffer(p
.type
, p
.ident
, buf
, hgs
);
362 buf
.writestring(p
.ident
.toString());
364 buf
.writestring("; ");
365 s
.aggr
.expressionToBuffer(buf
, hgs
);
370 void visitForeach(ForeachStatement s
)
372 foreachWithoutBody(s
);
377 s
._body
.statementToBuffer(buf
, hgs
);
383 void foreachRangeWithoutBody(ForeachRangeStatement s
)
385 buf
.writestring(Token
.toString(s
.op
));
386 buf
.writestring(" (");
388 typeToBuffer(s
.prm
.type
, s
.prm
.ident
, buf
, hgs
);
390 buf
.writestring(s
.prm
.ident
.toString());
391 buf
.writestring("; ");
392 s
.lwr
.expressionToBuffer(buf
, hgs
);
393 buf
.writestring(" .. ");
394 s
.upr
.expressionToBuffer(buf
, hgs
);
399 void visitForeachRange(ForeachRangeStatement s
)
401 foreachRangeWithoutBody(s
);
406 s
._body
.statementToBuffer(buf
, hgs
);
412 void visitStaticForeach(StaticForeachStatement s
)
414 buf
.writestring("static ");
417 visitForeach(s
.sfe
.aggrfe
);
421 assert(s
.sfe
.rangefe
);
422 visitForeachRange(s
.sfe
.rangefe
);
426 void visitForwarding(ForwardingStatement s
)
428 s
.statement
.statementToBuffer(buf
, hgs
);
431 void visitIf(IfStatement s
)
433 buf
.writestring("if (");
434 if (Parameter p
= s
.prm
)
436 StorageClass
stc = p
.storageClass
;
439 if (stcToBuffer(buf
, stc))
442 typeToBuffer(p
.type
, p
.ident
, buf
, hgs
);
444 buf
.writestring(p
.ident
.toString());
445 buf
.writestring(" = ");
447 s
.condition
.expressionToBuffer(buf
, hgs
);
450 if (s
.ifbody
.isScopeStatement())
452 s
.ifbody
.statementToBuffer(buf
, hgs
);
457 s
.ifbody
.statementToBuffer(buf
, hgs
);
462 buf
.writestring("else");
463 if (!s
.elsebody
.isIfStatement())
471 if (s
.elsebody
.isScopeStatement() || s
.elsebody
.isIfStatement())
473 s
.elsebody
.statementToBuffer(buf
, hgs
);
478 s
.elsebody
.statementToBuffer(buf
, hgs
);
484 void visitConditional(ConditionalStatement s
)
486 s
.condition
.conditionToBuffer(buf
, hgs
);
492 s
.ifbody
.statementToBuffer(buf
, hgs
);
498 buf
.writestring("else");
503 s
.elsebody
.statementToBuffer(buf
, hgs
);
510 void visitPragma(PragmaStatement s
)
512 buf
.writestring("pragma (");
513 buf
.writestring(s
.ident
.toString());
514 if (s
.args
&& s
.args
.length
)
516 buf
.writestring(", ");
517 argsToBuffer(s
.args
, buf
, hgs
);
526 s
._body
.statementToBuffer(buf
, hgs
);
538 void visitStaticAssert(StaticAssertStatement s
)
540 s
.sa
.dsymbolToBuffer(buf
, hgs
);
543 void visitSwitch(SwitchStatement s
)
545 buf
.writestring(s
.isFinal ?
"final switch (" : "switch (");
546 if (auto p
= s
.param
)
548 // Print condition assignment
549 StorageClass
stc = p
.storageClass
;
552 if (stcToBuffer(buf
, stc))
555 typeToBuffer(p
.type
, p
.ident
, buf
, hgs
);
557 buf
.writestring(p
.ident
.toString());
558 buf
.writestring(" = ");
560 s
.condition
.expressionToBuffer(buf
, hgs
);
565 if (!s
._body
.isScopeStatement())
570 s
._body
.statementToBuffer(buf
, hgs
);
577 s
._body
.statementToBuffer(buf
, hgs
);
582 void visitCase(CaseStatement s
)
584 buf
.writestring("case ");
585 s
.exp
.expressionToBuffer(buf
, hgs
);
588 s
.statement
.statementToBuffer(buf
, hgs
);
591 void visitCaseRange(CaseRangeStatement s
)
593 buf
.writestring("case ");
594 s
.first
.expressionToBuffer(buf
, hgs
);
595 buf
.writestring(": .. case ");
596 s
.last
.expressionToBuffer(buf
, hgs
);
599 s
.statement
.statementToBuffer(buf
, hgs
);
602 void visitDefault(DefaultStatement s
)
604 buf
.writestring("default:");
606 s
.statement
.statementToBuffer(buf
, hgs
);
609 void visitGotoDefault(GotoDefaultStatement s
)
611 buf
.writestring("goto default;");
615 void visitGotoCase(GotoCaseStatement s
)
617 buf
.writestring("goto case");
621 s
.exp
.expressionToBuffer(buf
, hgs
);
627 void visitSwitchError(SwitchErrorStatement s
)
629 buf
.writestring("SwitchErrorStatement::toCBuffer()");
633 void visitReturn(ReturnStatement s
)
635 buf
.writestring("return ");
637 s
.exp
.expressionToBuffer(buf
, hgs
);
642 void visitBreak(BreakStatement s
)
644 buf
.writestring("break");
648 buf
.writestring(s
.ident
.toString());
654 void visitContinue(ContinueStatement s
)
656 buf
.writestring("continue");
660 buf
.writestring(s
.ident
.toString());
666 void visitSynchronized(SynchronizedStatement s
)
668 buf
.writestring("synchronized");
672 s
.exp
.expressionToBuffer(buf
, hgs
);
678 s
._body
.statementToBuffer(buf
, hgs
);
682 void visitWith(WithStatement s
)
684 buf
.writestring("with (");
685 s
.exp
.expressionToBuffer(buf
, hgs
);
686 buf
.writestring(")");
689 s
._body
.statementToBuffer(buf
, hgs
);
692 void visitTryCatch(TryCatchStatement s
)
694 buf
.writestring("try");
698 if (s
._body
.isScopeStatement())
700 s
._body
.statementToBuffer(buf
, hgs
);
705 s
._body
.statementToBuffer(buf
, hgs
);
709 foreach (c
; *s
.catches
)
711 buf
.writestring("catch");
715 typeToBuffer(c
.type
, c
.ident
, buf
, hgs
);
723 c
.handler
.statementToBuffer(buf
, hgs
);
730 void visitTryFinally(TryFinallyStatement s
)
732 buf
.writestring("try");
737 s
._body
.statementToBuffer(buf
, hgs
);
741 buf
.writestring("finally");
743 if (s
.finalbody
.isScopeStatement())
745 s
.finalbody
.statementToBuffer(buf
, hgs
);
750 s
.finalbody
.statementToBuffer(buf
, hgs
);
755 void visitScopeGuard(ScopeGuardStatement s
)
757 buf
.writestring(Token
.toString(s
.tok
));
760 s
.statement
.statementToBuffer(buf
, hgs
);
763 void visitThrow(ThrowStatement s
)
765 buf
.writestring("throw ");
766 s
.exp
.expressionToBuffer(buf
, hgs
);
771 void visitDebug(DebugStatement s
)
775 s
.statement
.statementToBuffer(buf
, hgs
);
779 void visitGoto(GotoStatement s
)
781 buf
.writestring("goto ");
782 buf
.writestring(s
.ident
.toString());
787 void visitLabel(LabelStatement s
)
789 buf
.writestring(s
.ident
.toString());
793 s
.statement
.statementToBuffer(buf
, hgs
);
796 void visitAsm(AsmStatement s
)
798 buf
.writestring("asm { ");
803 buf
.writestring(t
.toChars());
805 t
.value
!= TOK
.min
&&
806 t
.value
!= TOK
.comma
&& t
.next
.value
!= TOK
.comma
&&
807 t
.value
!= TOK
.leftBracket
&& t
.next
.value
!= TOK
.leftBracket
&&
808 t
.next
.value
!= TOK
.rightBracket
&&
809 t
.value
!= TOK
.leftParenthesis
&& t
.next
.value
!= TOK
.leftParenthesis
&&
810 t
.next
.value
!= TOK
.rightParenthesis
&&
811 t
.value
!= TOK
.dot
&& t
.next
.value
!= TOK
.dot
)
818 buf
.writestring("; }");
822 void visitInlineAsm(InlineAsmStatement s
)
827 void visitGccAsm(GccAsmStatement s
)
832 void visitImport(ImportStatement s
)
834 foreach (imp
; *s
.imports
)
836 imp
.dsymbolToBuffer(buf
, hgs
);
840 mixin VisitStatement
!void visit
;
841 visit
.VisitStatement(s
);
844 private void dsymbolToBuffer(Dsymbol s
, ref OutBuffer buf
, HdrGenState
* hgs
)
846 toCBuffer(s
, buf
, *hgs
);
849 void toCBuffer(Dsymbol s
, ref OutBuffer buf
, ref HdrGenState hgs
)
851 void visitDsymbol(Dsymbol s
)
853 buf
.writestring(s
.toChars());
856 void visitStaticAssert(StaticAssert s
)
858 buf
.writestring(s
.kind());
860 s
.exp
.expressionToBuffer(buf
, &hgs
);
863 foreach (m
; (*s
.msgs
)[])
865 buf
.writestring(", ");
866 m
.expressionToBuffer(buf
, &hgs
);
869 buf
.writestring(");");
873 void visitDebugSymbol(DebugSymbol s
)
875 buf
.writestring("debug = ");
877 buf
.writestring(s
.ident
.toString());
884 void visitVersionSymbol(VersionSymbol s
)
886 buf
.writestring("version = ");
888 buf
.writestring(s
.ident
.toString());
895 void visitEnumMember(EnumMember em
)
898 typeToBuffer(em
.type
, em
.ident
, buf
, &hgs
);
900 buf
.writestring(em
.ident
.toString());
903 buf
.writestring(" = ");
904 em
.value
.expressionToBuffer(buf
, &hgs
);
908 void visitImport(Import imp
)
910 if (hgs
.hdrgen
&& imp
.id
== Id
.object
)
911 return; // object is imported by default
913 buf
.writestring("static ");
914 buf
.writestring("import ");
917 buf
.printf("%s = ", imp
.aliasId
.toChars());
919 foreach (const pid
; imp
.packages
)
921 buf
.printf("%s.", pid
.toChars());
923 buf
.writestring(imp
.id
.toString());
924 if (imp
.names
.length
)
926 buf
.writestring(" : ");
927 foreach (const i
, const name
; imp
.names
)
930 buf
.writestring(", ");
931 const _alias
= imp
.aliases
[i
];
933 buf
.printf("%s = %s", _alias
.toChars(), name
.toChars());
935 buf
.writestring(name
.toChars());
942 void visitAliasThis(AliasThis d
)
944 buf
.writestring("alias ");
945 buf
.writestring(d
.ident
.toString());
946 buf
.writestring(" this;\n");
949 void visitAttribDeclaration(AttribDeclaration d
)
952 if (auto stcd
= d
.isStorageClassDeclaration
)
954 hasSTC
= stcToBuffer(buf
, stcd
.stc);
963 if (d
.decl
.length
== 0 ||
(hgs
.hdrgen
&& d
.decl
.length
== 1 && (*d
.decl
)[0].isUnitTestDeclaration()))
965 // hack for https://issues.dlang.org/show_bug.cgi?id=8081
966 if (hasSTC
) buf
.writeByte(' ');
967 buf
.writestring("{}");
969 else if (d
.decl
.length
== 1)
971 if (hasSTC
) buf
.writeByte(' ');
972 toCBuffer((*d
.decl
)[0], buf
, hgs
);
981 foreach (de; *d
.decl
)
982 toCBuffer(de, buf
, hgs
);
989 void visitStorageClassDeclaration(StorageClassDeclaration d
)
991 visitAttribDeclaration(d
);
994 void visitDeprecatedDeclaration(DeprecatedDeclaration d
)
996 buf
.writestring("deprecated(");
997 d
.msg
.expressionToBuffer(buf
, &hgs
);
998 buf
.writestring(") ");
999 visitAttribDeclaration(d
);
1002 void visitLinkDeclaration(LinkDeclaration d
)
1004 buf
.writestring("extern (");
1005 buf
.writestring(linkageToString(d
.linkage
));
1006 buf
.writestring(") ");
1007 visitAttribDeclaration(d
);
1010 void visitCPPMangleDeclaration(CPPMangleDeclaration d
)
1013 final switch (d
.cppmangle
)
1015 case CPPMANGLE
.asClass
:
1018 case CPPMANGLE
.asStruct
:
1024 buf
.writestring("extern (C++, ");
1026 buf
.writestring(") ");
1027 visitAttribDeclaration(d
);
1030 void visitVisibilityDeclaration(VisibilityDeclaration d
)
1032 visibilityToBuffer(buf
, d
.visibility
);
1033 AttribDeclaration ad
= cast(AttribDeclaration
)d
;
1034 if (ad
.decl
.length
<= 1)
1036 if (ad
.decl
.length
== 1 && (*ad
.decl
)[0].isVisibilityDeclaration
)
1037 visitAttribDeclaration((*ad
.decl
)[0].isVisibilityDeclaration
);
1039 visitAttribDeclaration(d
);
1042 void visitAlignDeclaration(AlignDeclaration d
)
1046 foreach (i
, exp
; (*d
.exps
)[])
1050 buf
.printf("align (%s)", exp
.toChars());
1052 if (d
.decl
&& d
.decl
.length
< 2)
1056 buf
.writestring("align ");
1058 visitAttribDeclaration(d
.isAttribDeclaration());
1061 void visitAnonDeclaration(AnonDeclaration d
)
1063 buf
.writestring(d
.isunion ?
"union" : "struct");
1065 buf
.writestring("{");
1070 foreach (de; *d
.decl
)
1071 toCBuffer(de, buf
, hgs
);
1074 buf
.writestring("}");
1078 void visitPragmaDeclaration(PragmaDeclaration d
)
1080 buf
.writestring("pragma (");
1081 buf
.writestring(d
.ident
.toString());
1082 if (d
.args
&& d
.args
.length
)
1084 buf
.writestring(", ");
1085 argsToBuffer(d
.args
, buf
, &hgs
);
1090 // https://issues.dlang.org/show_bug.cgi?id=14690
1091 // Unconditionally perform a full output dump
1092 // for `pragma(inline)` declarations.
1093 bool savedFullDump
= global
.params
.dihdr
.fullOutput
;
1094 if (d
.ident
== Id
.Pinline
)
1095 global
.params
.dihdr
.fullOutput
= true;
1097 visitAttribDeclaration(d
);
1098 global
.params
.dihdr
.fullOutput
= savedFullDump
;
1101 void visitConditionalDeclaration(ConditionalDeclaration d
)
1103 d
.condition
.conditionToBuffer(buf
, &hgs
);
1104 if (d
.decl || d
.elsedecl
)
1112 foreach (de; *d
.decl
)
1113 toCBuffer(de, buf
, hgs
);
1120 buf
.writestring("else");
1125 foreach (de; *d
.elsedecl
)
1126 toCBuffer(de, buf
, hgs
);
1136 void visitStaticForeachDeclaration(StaticForeachDeclaration s
)
1138 void foreachWithoutBody(ForeachStatement s
)
1140 buf
.writestring(Token
.toString(s
.op
));
1141 buf
.writestring(" (");
1142 foreach (i
, p
; *s
.parameters
)
1145 buf
.writestring(", ");
1146 if (stcToBuffer(buf
, p
.storageClass
))
1149 typeToBuffer(p
.type
, p
.ident
, buf
, &hgs
);
1151 buf
.writestring(p
.ident
.toString());
1153 buf
.writestring("; ");
1154 s
.aggr
.expressionToBuffer(buf
, &hgs
);
1159 void foreachRangeWithoutBody(ForeachRangeStatement s
)
1161 /* s.op ( prm ; lwr .. upr )
1163 buf
.writestring(Token
.toString(s
.op
));
1164 buf
.writestring(" (");
1166 typeToBuffer(s
.prm
.type
, s
.prm
.ident
, buf
, &hgs
);
1168 buf
.writestring(s
.prm
.ident
.toString());
1169 buf
.writestring("; ");
1170 s
.lwr
.expressionToBuffer(buf
, &hgs
);
1171 buf
.writestring(" .. ");
1172 s
.upr
.expressionToBuffer(buf
, &hgs
);
1177 buf
.writestring("static ");
1180 foreachWithoutBody(s
.sfe
.aggrfe
);
1184 assert(s
.sfe
.rangefe
);
1185 foreachRangeWithoutBody(s
.sfe
.rangefe
);
1190 visitAttribDeclaration(s
);
1197 void visitMixinDeclaration(MixinDeclaration d
)
1199 buf
.writestring("mixin(");
1200 argsToBuffer(d
.exps
, buf
, &hgs
, null);
1201 buf
.writestring(");");
1205 void visitUserAttributeDeclaration(UserAttributeDeclaration d
)
1207 buf
.writestring("@(");
1208 argsToBuffer(d
.atts
, buf
, &hgs
);
1210 visitAttribDeclaration(d
);
1213 void visitTemplateConstraint(Expression constraint
)
1217 buf
.writestring(" if (");
1218 constraint
.expressionToBuffer(buf
, &hgs
);
1222 /// Returns: whether `do` is needed to write the function body
1223 bool contractsToBuffer(FuncDeclaration f
)
1225 bool requireDo
= false;
1229 foreach (frequire
; *f
.frequires
)
1231 buf
.writestring("in");
1232 if (auto es
= frequire
.isExpStatement())
1234 assert(es
.exp
&& es
.exp
.op
== EXP
.assert_
);
1235 buf
.writestring(" (");
1236 (cast(AssertExp
)es
.exp
).e1
.expressionToBuffer(buf
, &hgs
);
1244 frequire
.statementToBuffer(buf
, &hgs
);
1252 foreach (fensure
; *f
.fensures
)
1254 buf
.writestring("out");
1255 if (auto es
= fensure
.ensure
.isExpStatement())
1257 assert(es
.exp
&& es
.exp
.op
== EXP
.assert_
);
1258 buf
.writestring(" (");
1261 buf
.writestring(fensure
.id
.toString());
1263 buf
.writestring("; ");
1264 (cast(AssertExp
)es
.exp
).e1
.expressionToBuffer(buf
, &hgs
);
1274 buf
.writestring(fensure
.id
.toString());
1278 fensure
.ensure
.statementToBuffer(buf
, &hgs
);
1286 void bodyToBuffer(FuncDeclaration f
)
1288 if (!f
.fbody ||
(hgs
.hdrgen
&& global
.params
.dihdr
.fullOutput
== false && !hgs
.autoMember
&& !hgs
.tpltMember
&& !hgs
.insideFuncBody
))
1290 if (!f
.fbody
&& (f
.fensures || f
.frequires
))
1293 contractsToBuffer(f
);
1300 // there is no way to know if a function is nested
1301 // or not after parsing. We need scope information
1302 // for that, which is avaible during semantic
1303 // analysis. To overcome that, a simple mechanism
1304 // is implemented: everytime we print a function
1305 // body (templated or not) we increment a counter.
1306 // We decredement the counter when we stop
1307 // printing the function body.
1308 ++hgs
.insideFuncBody
;
1309 scope(exit
) { --hgs
.insideFuncBody
; }
1311 const savetlpt
= hgs
.tpltMember
;
1312 const saveauto
= hgs
.autoMember
;
1316 bool requireDo
= contractsToBuffer(f
);
1320 buf
.writestring("do");
1326 f
.fbody
.statementToBuffer(buf
, &hgs
);
1330 hgs
.tpltMember
= savetlpt
;
1331 hgs
.autoMember
= saveauto
;
1334 void visitBaseClasses(ClassDeclaration d
)
1336 if (!d ||
!d
.baseclasses
.length
)
1338 if (!d
.isAnonymous())
1339 buf
.writestring(" : ");
1340 foreach (i
, b
; *d
.baseclasses
)
1343 buf
.writestring(", ");
1344 typeToBuffer(b
.type
, null, buf
, &hgs
);
1348 bool visitEponymousMember(TemplateDeclaration d
)
1350 if (!d
.members || d
.members
.length
!= 1)
1352 Dsymbol onemember
= (*d
.members
)[0];
1353 if (onemember
.ident
!= d
.ident
)
1355 if (FuncDeclaration fd
= onemember
.isFuncDeclaration())
1358 if (stcToBuffer(buf
, fd
.storage_class
))
1360 functionToBufferFull(cast(TypeFunction
)fd
.type
, buf
, d
.ident
, &hgs
, d
);
1361 visitTemplateConstraint(d
.constraint
);
1367 if (AggregateDeclaration ad
= onemember
.isAggregateDeclaration())
1369 buf
.writestring(ad
.kind());
1371 buf
.writestring(ad
.ident
.toString());
1373 visitTemplateParameters(hgs
.ddoc ? d
.origParameters
: d
.parameters
, buf
, hgs
);
1375 visitTemplateConstraint(d
.constraint
);
1376 visitBaseClasses(ad
.isClassDeclaration());
1384 foreach (s
; *ad
.members
)
1385 toCBuffer(s
, buf
, hgs
);
1395 if (VarDeclaration vd
= onemember
.isVarDeclaration())
1399 if (stcToBuffer(buf
, vd
.storage_class
))
1402 typeToBuffer(vd
.type
, vd
.ident
, buf
, &hgs
);
1404 buf
.writestring(vd
.ident
.toString());
1406 visitTemplateParameters(hgs
.ddoc ? d
.origParameters
: d
.parameters
, buf
, hgs
);
1410 buf
.writestring(" = ");
1411 ExpInitializer ie
= vd
._init
.isExpInitializer();
1412 if (ie
&& (ie
.exp
.op
== EXP
.construct || ie
.exp
.op
== EXP
.blit
))
1413 (cast(AssignExp
)ie
.exp
).e2
.expressionToBuffer(buf
, &hgs
);
1415 vd
._init
.initializerToBuffer(buf
, &hgs
);
1424 void visitTemplateDeclaration(TemplateDeclaration d
)
1428 // Should handle template functions for doc generation
1429 if (onemember
&& onemember
.isFuncDeclaration())
1430 buf
.writestring("foo ");
1432 if ((hgs
.hdrgen || hgs
.fullDump
) && visitEponymousMember(d
))
1435 buf
.writestring(d
.kind());
1437 buf
.writestring("template");
1439 buf
.writestring(d
.ident
.toString());
1441 visitTemplateParameters(hgs
.ddoc ? d
.origParameters
: d
.parameters
, buf
, hgs
);
1443 visitTemplateConstraint(d
.constraint
);
1444 if (hgs
.hdrgen || hgs
.fullDump
)
1451 foreach (s
; *d
.members
)
1452 toCBuffer(s
, buf
, hgs
);
1460 void visitTemplateInstance(TemplateInstance ti
)
1462 buf
.writestring(ti
.name
.toChars());
1463 tiargsToBuffer(ti
, buf
, &hgs
);
1468 dumpTemplateInstance(ti
, buf
, &hgs
);
1472 void visitTemplateMixin(TemplateMixin tm
)
1474 buf
.writestring("mixin ");
1475 typeToBuffer(tm
.tqual
, null, buf
, &hgs
);
1476 tiargsToBuffer(tm
, buf
, &hgs
);
1477 if (tm
.ident
&& memcmp(tm
.ident
.toChars(), cast(const(char)*)"__mixin", 7) != 0)
1480 buf
.writestring(tm
.ident
.toString());
1485 dumpTemplateInstance(tm
, buf
, &hgs
);
1488 void visitEnumDeclaration(EnumDeclaration d
)
1490 auto oldInEnumDecl
= hgs
.inEnumDecl
;
1491 scope(exit
) hgs
.inEnumDecl
= oldInEnumDecl
;
1493 buf
.writestring("enum ");
1496 buf
.writestring(d
.ident
.toString());
1500 buf
.writestring(" : ");
1501 typeToBuffer(d
.memtype
, null, buf
, &hgs
);
1513 foreach (em
; *d
.members
)
1517 toCBuffer(em
, buf
, hgs
);
1526 void visitNspace(Nspace d
)
1528 buf
.writestring("extern (C++, ");
1529 buf
.writestring(d
.ident
.toString());
1535 foreach (s
; *d
.members
)
1536 toCBuffer(s
, buf
, hgs
);
1542 void visitStructDeclaration(StructDeclaration d
)
1544 buf
.writestring(d
.kind());
1546 if (!d
.isAnonymous())
1547 buf
.writestring(d
.toChars());
1558 hgs
.insideAggregate
++;
1559 foreach (s
; *d
.members
)
1560 toCBuffer(s
, buf
, hgs
);
1561 hgs
.insideAggregate
--;
1567 void visitClassDeclaration(ClassDeclaration d
)
1569 if (!d
.isAnonymous())
1571 buf
.writestring(d
.kind());
1573 buf
.writestring(d
.ident
.toString());
1575 visitBaseClasses(d
);
1582 hgs
.insideAggregate
++;
1583 foreach (s
; *d
.members
)
1584 toCBuffer(s
, buf
, hgs
);
1585 hgs
.insideAggregate
--;
1594 void visitAliasDeclaration(AliasDeclaration d
)
1596 if (d
.storage_class
& STC
.local
)
1598 buf
.writestring("alias ");
1601 buf
.writestring(d
.ident
.toString());
1602 buf
.writestring(" = ");
1603 if (stcToBuffer(buf
, d
.storage_class
))
1606 https://issues.dlang.org/show_bug.cgi?id=23223
1607 https://issues.dlang.org/show_bug.cgi?id=23222
1608 This special case (initially just for modules) avoids some segfaults
1609 and nicer -vcg-ast output.
1611 if (d
.aliassym
.isModule())
1613 buf
.writestring(d
.aliassym
.ident
.toString());
1617 toCBuffer(d
.aliassym
, buf
, hgs
);
1620 else if (d
.type
.ty
== Tfunction
)
1622 if (stcToBuffer(buf
, d
.storage_class
))
1624 typeToBuffer(d
.type
, d
.ident
, buf
, &hgs
);
1628 hgs
.declstring
= (d
.ident
== Id
.string || d
.ident
== Id
.wstring || d
.ident
== Id
.dstring
);
1629 buf
.writestring(d
.ident
.toString());
1630 buf
.writestring(" = ");
1631 if (stcToBuffer(buf
, d
.storage_class
))
1633 typeToBuffer(d
.type
, null, buf
, &hgs
);
1634 hgs
.declstring
= false;
1640 void visitAliasAssign(AliasAssign d
)
1642 buf
.writestring(d
.ident
.toString());
1643 buf
.writestring(" = ");
1645 toCBuffer(d
.aliassym
, buf
, hgs
);
1647 typeToBuffer(d
.type
, null, buf
, &hgs
);
1652 void visitVarDeclaration(VarDeclaration d
)
1654 if (d
.storage_class
& STC
.local
)
1656 visitVarDecl(d
, false, buf
, hgs
);
1661 void visitFuncDeclaration(FuncDeclaration f
)
1663 //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars());
1664 if (stcToBuffer(buf
, f
.storage_class
))
1666 auto tf
= cast(TypeFunction
)f
.type
;
1667 typeToBuffer(tf
, f
.ident
, buf
, &hgs
);
1671 // if the return type is missing (e.g. ref functions or auto)
1672 // https://issues.dlang.org/show_bug.cgi?id=20090
1673 // constructors are an exception: they don't have an explicit return
1674 // type but we still don't output the body.
1675 if ((!f
.isCtorDeclaration() && !tf
.next
) || f
.storage_class
& STC
.auto_
)
1681 else if (hgs
.tpltMember
== 0 && global
.params
.dihdr
.fullOutput
== false && !hgs
.insideFuncBody
)
1685 // this can happen on interfaces / abstract functions, see `allowsContractWithoutBody`
1686 if (f
.fensures || f
.frequires
)
1688 contractsToBuffer(f
);
1700 void visitFuncLiteralDeclaration(FuncLiteralDeclaration f
)
1702 if (f
.type
.ty
== Terror
)
1704 buf
.writestring("__error");
1707 if (f
.tok
!= TOK
.reserved
)
1709 buf
.writestring(f
.kind());
1712 TypeFunction tf
= cast(TypeFunction
)f
.type
;
1714 if (!f
.inferRetType
&& tf
.next
)
1715 typeToBuffer(tf
.next
, null, buf
, &hgs
);
1716 parametersToBuffer(tf
.parameterList
, buf
, &hgs
);
1718 // https://issues.dlang.org/show_bug.cgi?id=20074
1719 void printAttribute(string
str)
1722 buf
.writestring(str);
1724 tf
.attributesApply(&printAttribute
);
1727 CompoundStatement cs
= f
.fbody
.isCompoundStatement();
1729 if (f
.semanticRun
>= PASS
.semantic3done
&& cs
)
1731 s1
= (*cs
.statements
)[cs
.statements
.length
- 1];
1734 s1
= !cs ? f
.fbody
: null;
1735 ReturnStatement rs
= s1 ? s1
.endsWithReturnStatement() : null;
1738 buf
.writestring(" => ");
1739 rs
.exp
.expressionToBuffer(buf
, &hgs
);
1749 void visitPostBlitDeclaration(PostBlitDeclaration d
)
1751 if (stcToBuffer(buf
, d
.storage_class
))
1753 buf
.writestring("this(this)");
1757 void visitDtorDeclaration(DtorDeclaration d
)
1759 if (stcToBuffer(buf
, d
.storage_class
))
1761 buf
.writestring("~this()");
1765 void visitStaticCtorDeclaration(StaticCtorDeclaration d
)
1767 if (stcToBuffer(buf
, d
.storage_class
& ~STC
.static_
))
1769 if (d
.isSharedStaticCtorDeclaration())
1770 buf
.writestring("shared ");
1771 buf
.writestring("static this()");
1772 if (hgs
.hdrgen
&& !hgs
.tpltMember
)
1781 void visitStaticDtorDeclaration(StaticDtorDeclaration d
)
1783 if (stcToBuffer(buf
, d
.storage_class
& ~STC
.static_
))
1785 if (d
.isSharedStaticDtorDeclaration())
1786 buf
.writestring("shared ");
1787 buf
.writestring("static ~this()");
1788 if (hgs
.hdrgen
&& !hgs
.tpltMember
)
1797 void visitInvariantDeclaration(InvariantDeclaration d
)
1801 if (stcToBuffer(buf
, d
.storage_class
))
1803 buf
.writestring("invariant");
1804 if(auto es
= d
.fbody
.isExpStatement())
1806 assert(es
.exp
&& es
.exp
.op
== EXP
.assert_
);
1807 buf
.writestring(" (");
1808 (cast(AssertExp
)es
.exp
).e1
.expressionToBuffer(buf
, &hgs
);
1809 buf
.writestring(");");
1818 void visitUnitTestDeclaration(UnitTestDeclaration d
)
1822 if (stcToBuffer(buf
, d
.storage_class
))
1824 buf
.writestring("unittest");
1828 void visitBitFieldDeclaration(BitFieldDeclaration d
)
1830 if (stcToBuffer(buf
, d
.storage_class
))
1832 Identifier id
= d
.isAnonymous() ?
null : d
.ident
;
1833 typeToBuffer(d
.type
, id
, buf
, &hgs
);
1834 buf
.writestring(" : ");
1835 d
.width
.expressionToBuffer(buf
, &hgs
);
1840 void visitNewDeclaration(NewDeclaration d
)
1842 if (stcToBuffer(buf
, d
.storage_class
& ~STC
.static_
))
1844 buf
.writestring("new();");
1847 void visitModule(Module m
)
1849 moduleToBuffer2(m
, buf
, &hgs
);
1853 final class DsymbolPrettyPrintVisitor
: Visitor
1855 alias visit
= Visitor
.visit
;
1859 void visit(Dsymbol s
) { visitDsymbol(s
); }
1860 void visit(StaticAssert s
) { visitStaticAssert(s
); }
1861 void visit(DebugSymbol s
) { visitDebugSymbol(s
); }
1862 void visit(VersionSymbol s
) { visitVersionSymbol(s
); }
1863 void visit(EnumMember em
) { visitEnumMember(em
); }
1864 void visit(Import imp
) { visitImport(imp
); }
1865 void visit(AliasThis d
) { visitAliasThis(d
); }
1866 void visit(AttribDeclaration d
) { visitAttribDeclaration(d
); }
1867 void visit(StorageClassDeclaration d
) { visitStorageClassDeclaration(d
); }
1868 void visit(DeprecatedDeclaration d
) { visitDeprecatedDeclaration(d
); }
1869 void visit(LinkDeclaration d
) { visitLinkDeclaration(d
); }
1870 void visit(CPPMangleDeclaration d
) { visitCPPMangleDeclaration(d
); }
1871 void visit(VisibilityDeclaration d
) { visitVisibilityDeclaration(d
); }
1872 void visit(AlignDeclaration d
) { visitAlignDeclaration(d
); }
1873 void visit(AnonDeclaration d
) { visitAnonDeclaration(d
); }
1874 void visit(PragmaDeclaration d
) { visitPragmaDeclaration(d
); }
1875 void visit(ConditionalDeclaration d
) { visitConditionalDeclaration(d
); }
1876 void visit(StaticForeachDeclaration s
) { visitStaticForeachDeclaration(s
); }
1877 void visit(MixinDeclaration d
) { visitMixinDeclaration(d
); }
1878 void visit(UserAttributeDeclaration d
) { visitUserAttributeDeclaration(d
); }
1879 void visit(TemplateDeclaration d
) { visitTemplateDeclaration(d
); }
1880 void visit(TemplateInstance ti
) { visitTemplateInstance(ti
); }
1881 void visit(TemplateMixin tm
) { visitTemplateMixin(tm
); }
1882 void visit(EnumDeclaration d
) { visitEnumDeclaration(d
); }
1883 void visit(Nspace d
) { visitNspace(d
); }
1884 void visit(StructDeclaration d
) { visitStructDeclaration(d
); }
1885 void visit(ClassDeclaration d
) { visitClassDeclaration(d
); }
1886 void visit(AliasDeclaration d
) { visitAliasDeclaration(d
); }
1887 void visit(AliasAssign d
) { visitAliasAssign(d
); }
1888 void visit(VarDeclaration d
) { visitVarDeclaration(d
); }
1889 void visit(FuncDeclaration f
) { visitFuncDeclaration(f
); }
1890 void visit(FuncLiteralDeclaration f
) { visitFuncLiteralDeclaration(f
); }
1891 void visit(PostBlitDeclaration d
) { visitPostBlitDeclaration(d
); }
1892 void visit(DtorDeclaration d
) { visitDtorDeclaration(d
); }
1893 void visit(StaticCtorDeclaration d
) { visitStaticCtorDeclaration(d
); }
1894 void visit(StaticDtorDeclaration d
) { visitStaticDtorDeclaration(d
); }
1895 void visit(InvariantDeclaration d
) { visitInvariantDeclaration(d
); }
1896 void visit(UnitTestDeclaration d
) { visitUnitTestDeclaration(d
); }
1897 void visit(BitFieldDeclaration d
) { visitBitFieldDeclaration(d
); }
1898 void visit(NewDeclaration d
) { visitNewDeclaration(d
); }
1899 void visit(Module m
) { visitModule(m
); }
1902 scope v
= new DsymbolPrettyPrintVisitor();
1907 /*****************************************
1908 * Pretty-print a template parameter list to a buffer.
1910 private void visitTemplateParameters(TemplateParameters
* parameters
, ref OutBuffer buf
, ref HdrGenState hgs
)
1914 foreach (i
, p
; *parameters
)
1917 buf
.writestring(", ");
1918 p
.templateParameterToBuffer(buf
, &hgs
);
1923 /*******************************************
1924 * Pretty-print a VarDeclaration to buf.
1926 private void visitVarDecl(VarDeclaration v
, bool anywritten
, ref OutBuffer buf
, ref HdrGenState hgs
)
1928 const bool isextern
= hgs
.hdrgen
&&
1929 !hgs
.insideFuncBody
&&
1931 !hgs
.insideAggregate
&&
1932 !(v
.storage_class
& STC
.manifest
);
1934 void vinit(VarDeclaration v
)
1936 auto ie
= v
._init
.isExpInitializer();
1937 if (ie
&& (ie
.exp
.op
== EXP
.construct || ie
.exp
.op
== EXP
.blit
))
1938 (cast(AssignExp
)ie
.exp
).e2
.expressionToBuffer(buf
, &hgs
);
1940 v
._init
.initializerToBuffer(buf
, &hgs
);
1945 buf
.writestring(", ");
1946 buf
.writestring(v
.ident
.toString());
1950 const bool useTypeof
= isextern
&& v
._init
&& !v
.type
;
1951 auto stc = v
.storage_class
;
1956 if (stcToBuffer(buf
, stc))
1959 typeToBuffer(v
.type
, v
.ident
, buf
, &hgs
);
1962 buf
.writestring("typeof(");
1964 buf
.writestring(") ");
1965 buf
.writestring(v
.ident
.toString());
1968 buf
.writestring(v
.ident
.toString());
1970 if (v
._init
&& !isextern
)
1972 buf
.writestring(" = ");
1978 /*********************************************
1979 * Print expression to buffer.
1981 private void expressionPrettyPrint(Expression e
, ref OutBuffer buf
, HdrGenState
* hgs
)
1983 void visit(Expression e
)
1985 buf
.writestring(EXPtoString(e
.op
));
1988 void visitInteger(IntegerExp e
)
1990 const dinteger_t v
= e
.toInteger();
1999 TypeEnum te
= cast(TypeEnum
)t
;
2001 if (sym
&& sym
.members
&& (!hgs
.inEnumDecl || hgs
.inEnumDecl
!= sym
))
2003 foreach (em
; *sym
.members
)
2005 if ((cast(EnumMember
)em
).value
.toInteger
== v
)
2007 buf
.printf("%s.%s", sym
.toChars(), em
.ident
.toChars());
2013 buf
.printf("cast(%s)", te
.sym
.toChars());
2021 const o
= buf
.length
;
2022 writeSingleCharLiteral(buf
, cast(dchar) v
);
2024 escapeDdocString(buf
, o
);
2028 buf
.writestring("cast(byte)");
2031 buf
.writestring("cast(short)");
2035 buf
.printf("%d", cast(int)v
);
2038 buf
.writestring("cast(ubyte)");
2041 buf
.writestring("cast(ushort)");
2044 buf
.printf("%uu", cast(uint)v
);
2049 // https://issues.dlang.org/show_bug.cgi?id=23173
2050 // This is a special case because - is not part of the
2051 // integer literal and 9223372036854775808L overflows a long
2052 buf
.writestring("cast(long)-9223372036854775808");
2056 buf
.printf("%lldL", v
);
2060 buf
.printf("%lluLU", v
);
2063 buf
.writestring(v ?
"true" : "false");
2066 buf
.writestring("cast(");
2067 buf
.writestring(t
.toChars());
2069 if (target
.ptrsize
== 8)
2071 else if (target
.ptrsize
== 4 ||
2072 target
.ptrsize
== 2)
2078 buf
.writestring("cast(void)0");
2082 /* This can happen if errors, such as
2083 * the type is painted on like in fromConstInitializer().
2092 else if (v
& 0x8000000000000000L
)
2093 buf
.printf("0x%llx", v
);
2098 void visitError(ErrorExp e
)
2100 buf
.writestring("__error");
2103 void visitVoidInit(VoidInitExp e
)
2105 buf
.writestring("void");
2108 void floatToBuffer(Type type
, real_t value
)
2110 .floatToBuffer(type
, value
, buf
, hgs
.hdrgen
);
2113 void visitReal(RealExp e
)
2115 floatToBuffer(e
.type
, e
.value
);
2118 void visitComplex(ComplexExp e
)
2124 floatToBuffer(e
.type
, creall(e
.value
));
2126 floatToBuffer(e
.type
, cimagl(e
.value
));
2127 buf
.writestring("i)");
2130 void visitIdentifier(IdentifierExp e
)
2132 if (hgs
.hdrgen || hgs
.ddoc
)
2133 buf
.writestring(e
.ident
.toHChars2());
2135 buf
.writestring(e
.ident
.toString());
2138 void visitDsymbol(DsymbolExp e
)
2140 buf
.writestring(e
.s
.toChars());
2143 void visitThis(ThisExp e
)
2145 buf
.writestring("this");
2148 void visitSuper(SuperExp e
)
2150 buf
.writestring("super");
2153 void visitNull(NullExp e
)
2155 buf
.writestring("null");
2158 void visitString(StringExp e
)
2161 const o
= buf
.length
;
2162 foreach (i
; 0 .. e
.len
)
2164 writeCharLiteral(buf
, e
.getCodeUnit(i
));
2167 escapeDdocString(buf
, o
);
2170 buf
.writeByte(e
.postfix
);
2173 void visitArrayLiteral(ArrayLiteralExp e
)
2176 argsToBuffer(e
.elements
, buf
, hgs
, e
.basis
);
2180 void visitAssocArrayLiteral(AssocArrayLiteralExp e
)
2183 foreach (i
, key
; *e
.keys
)
2186 buf
.writestring(", ");
2187 expToBuffer(key
, PREC
.assign
, buf
, hgs
);
2189 auto value
= (*e
.values
)[i
];
2190 expToBuffer(value
, PREC
.assign
, buf
, hgs
);
2195 void visitStructLiteral(StructLiteralExp e
)
2197 buf
.writestring(e
.sd
.toChars());
2199 // CTFE can generate struct literals that contain an AddrExp pointing
2200 // to themselves, need to avoid infinite recursion:
2201 // struct S { this(int){ this.s = &this; } S* s; }
2202 // const foo = new S(0);
2203 if (e
.stageflags
& stageToCBuffer
)
2204 buf
.writestring("<recursion>");
2207 const old
= e
.stageflags
;
2208 e
.stageflags |
= stageToCBuffer
;
2209 argsToBuffer(e
.elements
, buf
, hgs
);
2215 void visitCompoundLiteral(CompoundLiteralExp e
)
2218 typeToBuffer(e
.type
, null, buf
, hgs
);
2220 e
.initializer
.initializerToBuffer(buf
, hgs
);
2223 void visitType(TypeExp e
)
2225 typeToBuffer(e
.type
, null, buf
, hgs
);
2228 void visitScope(ScopeExp e
)
2230 if (e
.sds
.isTemplateInstance())
2232 e
.sds
.dsymbolToBuffer(buf
, hgs
);
2234 else if (hgs
!is null && hgs
.ddoc
)
2237 if (auto m
= e
.sds
.isModule())
2238 buf
.writestring(m
.md
.toChars());
2240 buf
.writestring(e
.sds
.toChars());
2244 buf
.writestring(e
.sds
.kind());
2246 buf
.writestring(e
.sds
.toChars());
2250 void visitTemplate(TemplateExp e
)
2252 buf
.writestring(e
.td
.toChars());
2255 void visitNew(NewExp e
)
2259 expToBuffer(e
.thisexp
, PREC
.primary
, buf
, hgs
);
2262 buf
.writestring("new ");
2263 typeToBuffer(e
.newtype
, null, buf
, hgs
);
2264 if (e
.arguments
&& e
.arguments
.length
)
2267 argsToBuffer(e
.arguments
, buf
, hgs
, null, e
.names
);
2272 void visitNewAnonClass(NewAnonClassExp e
)
2276 expToBuffer(e
.thisexp
, PREC
.primary
, buf
, hgs
);
2279 buf
.writestring("new");
2280 buf
.writestring(" class ");
2281 if (e
.arguments
&& e
.arguments
.length
)
2284 argsToBuffer(e
.arguments
, buf
, hgs
);
2288 e
.cd
.dsymbolToBuffer(buf
, hgs
);
2291 void visitSymOff(SymOffExp e
)
2294 buf
.printf("(& %s%+lld)", e
.var
.toChars(), e
.offset
);
2295 else if (e
.var
.isTypeInfoDeclaration())
2296 buf
.writestring(e
.var
.toChars());
2298 buf
.printf("& %s", e
.var
.toChars());
2301 void visitVar(VarExp e
)
2303 buf
.writestring(e
.var
.toChars());
2306 void visitOver(OverExp e
)
2308 buf
.writestring(e
.vars
.ident
.toString());
2311 void visitTuple(TupleExp e
)
2316 e
.e0
.expressionPrettyPrint(buf
, hgs
);
2317 buf
.writestring(", AliasSeq!(");
2318 argsToBuffer(e
.exps
, buf
, hgs
);
2319 buf
.writestring("))");
2323 buf
.writestring("AliasSeq!(");
2324 argsToBuffer(e
.exps
, buf
, hgs
);
2329 void visitFunc(FuncExp e
)
2331 e
.fd
.dsymbolToBuffer(buf
, hgs
);
2332 //buf.writestring(e.fd.toChars());
2335 void visitDeclaration(DeclarationExp e
)
2337 /* Normal dmd execution won't reach here - regular variable declarations
2338 * are handled in visit(ExpStatement), so here would be used only when
2339 * we'll directly call Expression.toChars() for debugging.
2343 if (auto var
= e
.declaration
.isVarDeclaration())
2345 // For debugging use:
2346 // - Avoid printing newline.
2347 // - Intentionally use the format (Type var;)
2348 // which isn't correct as regular D code.
2351 visitVarDecl(var
, false, buf
, *hgs
);
2356 else e
.declaration
.dsymbolToBuffer(buf
, hgs
);
2360 void visitTypeid(TypeidExp e
)
2362 buf
.writestring("typeid(");
2363 objectToBuffer(e
.obj
, buf
, hgs
);
2367 void visitTraits(TraitsExp e
)
2369 buf
.writestring("__traits(");
2371 buf
.writestring(e
.ident
.toString());
2374 foreach (arg
; *e
.args
)
2376 buf
.writestring(", ");
2377 objectToBuffer(arg
, buf
, hgs
);
2383 void visitHalt(HaltExp e
)
2385 buf
.writestring("halt");
2388 void visitIs(IsExp e
)
2390 buf
.writestring("is(");
2391 typeToBuffer(e
.targ
, e
.id
, buf
, hgs
);
2392 if (e
.tok2
!= TOK
.reserved
)
2394 buf
.printf(" %s %s", Token
.toChars(e
.tok
), Token
.toChars(e
.tok2
));
2398 if (e
.tok
== TOK
.colon
)
2399 buf
.writestring(" : ");
2401 buf
.writestring(" == ");
2402 typeToBuffer(e
.tspec
, null, buf
, hgs
);
2404 if (e
.parameters
&& e
.parameters
.length
)
2406 buf
.writestring(", ");
2407 visitTemplateParameters(e
.parameters
, buf
, *hgs
);
2412 void visitUna(UnaExp e
)
2414 buf
.writestring(EXPtoString(e
.op
));
2415 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2418 void visitLoweredAssignExp(LoweredAssignExp e
)
2420 if (global
.params
.vcg_ast
)
2422 expressionToBuffer(e
.lowering
, buf
, hgs
);
2426 visit(cast(BinExp
)e
);
2428 void visitBin(BinExp e
)
2430 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2432 buf
.writestring(EXPtoString(e
.op
));
2434 expToBuffer(e
.e2
, cast(PREC
)(precedence
[e
.op
] + 1), buf
, hgs
);
2437 void visitComma(CommaExp e
)
2439 // CommaExp is generated by the compiler so it shouldn't
2440 // appear in error messages or header files.
2441 // For now, this treats the case where the compiler
2442 // generates CommaExp for temporaries by calling
2443 // the `sideeffect.copyToTemp` function.
2444 auto ve
= e
.e2
.isVarExp();
2446 // not a CommaExp introduced for temporaries, go on
2448 if (!ve ||
!(ve
.var
.storage_class
& STC
.temp
))
2450 visitBin(cast(BinExp
)e
);
2454 // CommaExp that contain temporaries inserted via
2455 // `copyToTemp` are usually of the form
2456 // ((T __temp = exp), __tmp).
2457 // Asserts are here to easily spot
2458 // missing cases where CommaExp
2459 // are used for other constructs
2460 auto vd
= ve
.var
.isVarDeclaration();
2461 assert(vd
&& vd
._init
);
2463 if (auto ei
= vd
._init
.isExpInitializer())
2465 Expression commaExtract
;
2467 if (auto ce
= exp
.isConstructExp())
2468 commaExtract
= ce
.e2
;
2469 else if (auto se
= exp
.isStructLiteralExp())
2474 expToBuffer(commaExtract
, precedence
[exp
.op
], buf
, hgs
);
2479 // not one of the known cases, go on the old path
2480 visitBin(cast(BinExp
)e
);
2484 void visitMixin(MixinExp e
)
2486 buf
.writestring("mixin(");
2487 argsToBuffer(e
.exps
, buf
, hgs
, null);
2491 void visitImport(ImportExp e
)
2493 buf
.writestring("import(");
2494 expToBuffer(e
.e1
, PREC
.assign
, buf
, hgs
);
2498 void visitAssert(AssertExp e
)
2500 buf
.writestring("assert(");
2501 expToBuffer(e
.e1
, PREC
.assign
, buf
, hgs
);
2504 buf
.writestring(", ");
2505 expToBuffer(e
.msg
, PREC
.assign
, buf
, hgs
);
2510 void visitThrow(ThrowExp e
)
2512 buf
.writestring("throw ");
2513 expToBuffer(e
.e1
, PREC
.unary
, buf
, hgs
);
2516 void visitDotId(DotIdExp e
)
2518 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2520 buf
.writestring("->");
2523 buf
.writestring(e
.ident
.toString());
2526 void visitDotTemplate(DotTemplateExp e
)
2528 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2530 buf
.writestring(e
.td
.toChars());
2533 void visitDotVar(DotVarExp e
)
2535 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2537 buf
.writestring(e
.var
.toChars());
2540 void visitDotTemplateInstance(DotTemplateInstanceExp e
)
2542 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2544 e
.ti
.dsymbolToBuffer(buf
, hgs
);
2547 void visitDelegate(DelegateExp e
)
2550 if (!e
.func
.isNested() || e
.func
.needThis())
2552 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2555 buf
.writestring(e
.func
.toChars());
2558 void visitDotType(DotTypeExp e
)
2560 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2562 buf
.writestring(e
.sym
.toChars());
2565 void visitCall(CallExp e
)
2567 if (e
.e1
.op
== EXP
.type
)
2569 /* Avoid parens around type to prevent forbidden cast syntax:
2571 * This is ok since types in constructor calls
2572 * can never depend on parens anyway
2574 e
.e1
.expressionPrettyPrint(buf
, hgs
);
2577 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2579 argsToBuffer(e
.arguments
, buf
, hgs
, null, e
.names
);
2583 void visitPtr(PtrExp e
)
2586 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2589 void visitDelete(DeleteExp e
)
2591 buf
.writestring("delete ");
2592 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2595 void visitCast(CastExp e
)
2597 buf
.writestring("cast(");
2599 typeToBuffer(e
.to
, null, buf
, hgs
);
2602 MODtoBuffer(buf
, e
.mod
);
2605 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2608 void visitVector(VectorExp e
)
2610 buf
.writestring("cast(");
2611 typeToBuffer(e
.to
, null, buf
, hgs
);
2613 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2616 void visitVectorArray(VectorArrayExp e
)
2618 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2619 buf
.writestring(".array");
2622 void visitSlice(SliceExp e
)
2624 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2629 sizeToBuffer(e
.lwr
, buf
, hgs
);
2632 buf
.writestring("..");
2634 sizeToBuffer(e
.upr
, buf
, hgs
);
2641 void visitArrayLength(ArrayLengthExp e
)
2643 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2644 buf
.writestring(".length");
2647 void visitInterval(IntervalExp e
)
2649 expToBuffer(e
.lwr
, PREC
.assign
, buf
, hgs
);
2650 buf
.writestring("..");
2651 expToBuffer(e
.upr
, PREC
.assign
, buf
, hgs
);
2654 void visitDelegatePtr(DelegatePtrExp e
)
2656 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2657 buf
.writestring(".ptr");
2660 void visitDelegateFuncptr(DelegateFuncptrExp e
)
2662 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2663 buf
.writestring(".funcptr");
2666 void visitArray(ArrayExp e
)
2668 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2670 argsToBuffer(e
.arguments
, buf
, hgs
);
2674 void visitDot(DotExp e
)
2676 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2678 expToBuffer(e
.e2
, PREC
.primary
, buf
, hgs
);
2681 void visitIndex(IndexExp e
)
2683 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2685 sizeToBuffer(e
.e2
, buf
, hgs
);
2689 void visitPost(PostExp e
)
2691 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2692 buf
.writestring(EXPtoString(e
.op
));
2695 void visitPre(PreExp e
)
2697 buf
.writestring(EXPtoString(e
.op
));
2698 expToBuffer(e
.e1
, precedence
[e
.op
], buf
, hgs
);
2701 void visitRemove(RemoveExp e
)
2703 expToBuffer(e
.e1
, PREC
.primary
, buf
, hgs
);
2704 buf
.writestring(".remove(");
2705 expToBuffer(e
.e2
, PREC
.assign
, buf
, hgs
);
2709 void visitCond(CondExp e
)
2711 expToBuffer(e
.econd
, PREC
.oror
, buf
, hgs
);
2712 buf
.writestring(" ? ");
2713 expToBuffer(e
.e1
, PREC
.expr
, buf
, hgs
);
2714 buf
.writestring(" : ");
2715 expToBuffer(e
.e2
, PREC
.cond
, buf
, hgs
);
2718 void visitDefaultInit(DefaultInitExp e
)
2720 buf
.writestring(EXPtoString(e
.op
));
2723 void visitClassReference(ClassReferenceExp e
)
2725 buf
.writestring(e
.value
.toChars());
2731 if (auto be
= e
.isBinExp())
2732 return visitBin(be
);
2733 else if (auto ue
= e
.isUnaExp())
2734 return visitUna(ue
);
2735 else if (auto de = e
.isDefaultInitExp())
2736 return visitDefaultInit(e
.isDefaultInitExp());
2739 case EXP
.int64
: return visitInteger(e
.isIntegerExp());
2740 case EXP
.error
: return visitError(e
.isErrorExp());
2741 case EXP
.void_
: return visitVoidInit(e
.isVoidInitExp());
2742 case EXP
.float64
: return visitReal(e
.isRealExp());
2743 case EXP
.complex80
: return visitComplex(e
.isComplexExp());
2744 case EXP
.identifier
: return visitIdentifier(e
.isIdentifierExp());
2745 case EXP
.dSymbol
: return visitDsymbol(e
.isDsymbolExp());
2746 case EXP
.this_
: return visitThis(e
.isThisExp());
2747 case EXP
.super_
: return visitSuper(e
.isSuperExp());
2748 case EXP
.null_
: return visitNull(e
.isNullExp());
2749 case EXP
.string_
: return visitString(e
.isStringExp());
2750 case EXP
.arrayLiteral
: return visitArrayLiteral(e
.isArrayLiteralExp());
2751 case EXP
.assocArrayLiteral
: return visitAssocArrayLiteral(e
.isAssocArrayLiteralExp());
2752 case EXP
.structLiteral
: return visitStructLiteral(e
.isStructLiteralExp());
2753 case EXP
.compoundLiteral
: return visitCompoundLiteral(e
.isCompoundLiteralExp());
2754 case EXP
.type
: return visitType(e
.isTypeExp());
2755 case EXP
.scope_
: return visitScope(e
.isScopeExp());
2756 case EXP
.template_
: return visitTemplate(e
.isTemplateExp());
2757 case EXP
.new_
: return visitNew(e
.isNewExp());
2758 case EXP
.newAnonymousClass
: return visitNewAnonClass(e
.isNewAnonClassExp());
2759 case EXP
.symbolOffset
: return visitSymOff(e
.isSymOffExp());
2760 case EXP
.variable
: return visitVar(e
.isVarExp());
2761 case EXP
.overloadSet
: return visitOver(e
.isOverExp());
2762 case EXP
.tuple
: return visitTuple(e
.isTupleExp());
2763 case EXP
.function_
: return visitFunc(e
.isFuncExp());
2764 case EXP
.declaration
: return visitDeclaration(e
.isDeclarationExp());
2765 case EXP
.typeid_
: return visitTypeid(e
.isTypeidExp());
2766 case EXP
.traits
: return visitTraits(e
.isTraitsExp());
2767 case EXP
.halt
: return visitHalt(e
.isHaltExp());
2768 case EXP
.is_
: return visitIs(e
.isExp());
2769 case EXP
.comma
: return visitComma(e
.isCommaExp());
2770 case EXP
.mixin_
: return visitMixin(e
.isMixinExp());
2771 case EXP
.import_
: return visitImport(e
.isImportExp());
2772 case EXP
.assert_
: return visitAssert(e
.isAssertExp());
2773 case EXP
.throw_
: return visitThrow(e
.isThrowExp());
2774 case EXP
.dotIdentifier
: return visitDotId(e
.isDotIdExp());
2775 case EXP
.dotTemplateDeclaration
: return visitDotTemplate(e
.isDotTemplateExp());
2776 case EXP
.dotVariable
: return visitDotVar(e
.isDotVarExp());
2777 case EXP
.dotTemplateInstance
: return visitDotTemplateInstance(e
.isDotTemplateInstanceExp());
2778 case EXP
.delegate_
: return visitDelegate(e
.isDelegateExp());
2779 case EXP
.dotType
: return visitDotType(e
.isDotTypeExp());
2780 case EXP
.call: return visitCall(e
.isCallExp());
2781 case EXP
.star
: return visitPtr(e
.isPtrExp());
2782 case EXP
.delete_
: return visitDelete(e
.isDeleteExp());
2783 case EXP
.cast_
: return visitCast(e
.isCastExp());
2784 case EXP
.vector
: return visitVector(e
.isVectorExp());
2785 case EXP
.vectorArray
: return visitVectorArray(e
.isVectorArrayExp());
2786 case EXP
.slice
: return visitSlice(e
.isSliceExp());
2787 case EXP
.arrayLength
: return visitArrayLength(e
.isArrayLengthExp());
2788 case EXP
.interval
: return visitInterval(e
.isIntervalExp());
2789 case EXP
.delegatePointer
: return visitDelegatePtr(e
.isDelegatePtrExp());
2790 case EXP
.delegateFunctionPointer
: return visitDelegateFuncptr(e
.isDelegateFuncptrExp());
2791 case EXP
.array
: return visitArray(e
.isArrayExp());
2792 case EXP
.dot
: return visitDot(e
.isDotExp());
2793 case EXP
.index
: return visitIndex(e
.isIndexExp());
2794 case EXP
.minusMinus
:
2795 case EXP
.plusPlus
: return visitPost(e
.isPostExp());
2796 case EXP
.preMinusMinus
:
2797 case EXP
.prePlusPlus
: return visitPre(e
.isPreExp());
2798 case EXP
.remove
: return visitRemove(e
.isRemoveExp());
2799 case EXP
.question
: return visitCond(e
.isCondExp());
2800 case EXP
.classReference
: return visitClassReference(e
.isClassReferenceExp());
2801 case EXP
.loweredAssignExp
: return visitLoweredAssignExp(e
.isLoweredAssignExp());
2806 * Formats `value` as a literal of type `type` into `buf`.
2809 * type = literal type (e.g. Tfloat)
2810 * value = value to print
2811 * buf = target buffer
2812 * allowHex = whether hex floating point literals may be used
2813 * for greater accuracy
2815 void floatToBuffer(Type type
, const real_t value
, ref OutBuffer buf
, const bool allowHex
)
2817 /** sizeof(value)*3 is because each byte of mantissa is max
2818 of 256 (3 characters). The string will be "-M.MMMMe-4932".
2819 (ie, 8 chars more than mantissa). Plus one for trailing \0.
2820 Plus one for rounding. */
2821 const(size_t
) BUFFER_LEN
= value
.sizeof
* 3 + 8 + 1 + 1;
2822 char[BUFFER_LEN
] buffer
= void;
2823 CTFloat
.sprint(buffer
.ptr
, BUFFER_LEN
, 'g', value
);
2824 assert(strlen(buffer
.ptr
) < BUFFER_LEN
);
2828 real_t r
= CTFloat
.parse(buffer
.ptr
, isOutOfRange
);
2829 //assert(!isOutOfRange); // test/compilable/test22725.c asserts here
2830 if (r
!= value
) // if exact duplication
2831 CTFloat
.sprint(buffer
.ptr
, BUFFER_LEN
, 'a', value
);
2833 buf
.writestring(buffer
.ptr
);
2834 if (buffer
.ptr
[strlen(buffer
.ptr
) - 1] == '.')
2835 buf
.remove(buf
.length() - 1, 1);
2839 Type t
= type
.toBasetype();
2855 if (t
.isimaginary())
2860 private void templateParameterToBuffer(TemplateParameter tp
, ref OutBuffer buf
, HdrGenState
* hgs
)
2862 scope v
= new TemplateParameterPrettyPrintVisitor(&buf
, hgs
);
2866 private extern (C
++) final class TemplateParameterPrettyPrintVisitor
: Visitor
2868 alias visit
= Visitor
.visit
;
2873 extern (D
) this(OutBuffer
* buf
, HdrGenState
* hgs
) scope @safe
2879 override void visit(TemplateTypeParameter tp
)
2881 buf
.writestring(tp
.ident
.toString());
2884 buf
.writestring(" : ");
2885 typeToBuffer(tp
.specType
, null, *buf
, hgs
);
2889 buf
.writestring(" = ");
2890 typeToBuffer(tp
.defaultType
, null, *buf
, hgs
);
2894 override void visit(TemplateThisParameter tp
)
2896 buf
.writestring("this ");
2897 visit(cast(TemplateTypeParameter
)tp
);
2900 override void visit(TemplateAliasParameter tp
)
2902 buf
.writestring("alias ");
2904 typeToBuffer(tp
.specType
, tp
.ident
, *buf
, hgs
);
2906 buf
.writestring(tp
.ident
.toString());
2909 buf
.writestring(" : ");
2910 objectToBuffer(tp
.specAlias
, *buf
, hgs
);
2912 if (tp
.defaultAlias
)
2914 buf
.writestring(" = ");
2915 objectToBuffer(tp
.defaultAlias
, *buf
, hgs
);
2919 override void visit(TemplateValueParameter tp
)
2921 typeToBuffer(tp
.valType
, tp
.ident
, *buf
, hgs
);
2924 buf
.writestring(" : ");
2925 tp
.specValue
.expressionToBuffer(*buf
, hgs
);
2927 if (tp
.defaultValue
)
2929 buf
.writestring(" = ");
2930 tp
.defaultValue
.expressionToBuffer(*buf
, hgs
);
2934 override void visit(TemplateTupleParameter tp
)
2936 buf
.writestring(tp
.ident
.toString());
2937 buf
.writestring("...");
2941 private void conditionToBuffer(Condition c
, ref OutBuffer buf
, HdrGenState
* hgs
)
2943 scope v
= new ConditionPrettyPrintVisitor(&buf
, hgs
);
2947 private extern (C
++) final class ConditionPrettyPrintVisitor
: Visitor
2949 alias visit
= Visitor
.visit
;
2954 extern (D
) this(OutBuffer
* buf
, HdrGenState
* hgs
) scope @safe
2960 override void visit(DebugCondition c
)
2962 buf
.writestring("debug (");
2964 buf
.writestring(c
.ident
.toString());
2970 override void visit(VersionCondition c
)
2972 buf
.writestring("version (");
2974 buf
.writestring(c
.ident
.toString());
2980 override void visit(StaticIfCondition c
)
2982 buf
.writestring("static if (");
2983 c
.exp
.expressionToBuffer(*buf
, hgs
);
2988 void toCBuffer(const Statement s
, ref OutBuffer buf
, ref HdrGenState hgs
)
2990 (cast()s
).statementToBuffer(buf
, &hgs
);
2993 void toCBuffer(const Type t
, ref OutBuffer buf
, const Identifier ident
, ref HdrGenState hgs
)
2995 typeToBuffer(cast() t
, ident
, buf
, &hgs
);
2998 // used from TemplateInstance::toChars() and TemplateMixin::toChars()
2999 void toCBufferInstance(const TemplateInstance ti
, ref OutBuffer buf
, bool qualifyTypes
= false)
3002 hgs
.fullQual
= qualifyTypes
;
3004 buf
.writestring(ti
.name
.toChars());
3005 tiargsToBuffer(cast() ti
, buf
, &hgs
);
3008 void toCBuffer(const Initializer iz
, ref OutBuffer buf
, ref HdrGenState hgs
)
3010 initializerToBuffer(cast() iz
, buf
, &hgs
);
3013 bool stcToBuffer(ref OutBuffer buf
, StorageClass
stc) @safe
3015 //printf("stc: %llx\n", stc);
3016 bool result
= false;
3018 if (stc & STC
.scopeinferred
)
3020 //buf.writestring("scope-inferred ");
3021 stc &= ~(STC
.scope_ | STC
.scopeinferred
);
3023 if (stc & STC
.returninferred
)
3025 //buf.writestring((stc & STC.returnScope) ? "return-scope-inferred " : "return-ref-inferred ");
3026 stc &= ~(STC
.return_ | STC
.returninferred
);
3029 /* Put scope ref return into a standard order
3032 const isout
= (stc & STC
.out_
) != 0;
3033 //printf("bsr = %d %llx\n", buildScopeRef(stc), stc);
3034 final switch (buildScopeRef(stc))
3037 case ScopeRef
.Scope
:
3039 case ScopeRef
.Return
:
3042 case ScopeRef
.ReturnScope
: rrs
= "return scope"; goto L1
;
3043 case ScopeRef
.ReturnRef
: rrs
= isout ?
"return out" : "return ref"; goto L1
;
3044 case ScopeRef
.RefScope
: rrs
= isout ?
"out scope" : "ref scope"; goto L1
;
3045 case ScopeRef
.ReturnRef_Scope
: rrs
= isout ?
"return out scope" : "return ref scope"; goto L1
;
3046 case ScopeRef
.Ref_ReturnScope
: rrs
= isout ?
"out return scope" : "ref return scope"; goto L1
;
3048 buf
.writestring(rrs
);
3050 stc &= ~(STC
.out_ | STC
.scope_ | STC
.ref_ | STC
.return_
);
3056 const s
= stcToString(stc);
3068 /*************************************************
3069 * Pick off one of the storage classes from stc,
3070 * and return a string representation of it.
3071 * stc is reduced by the one picked.
3073 string
stcToString(ref StorageClass
stc) @safe
3075 static struct SCstring
3081 // Note: The identifier needs to be `\0` terminated
3082 // as some code assumes it (e.g. when printing error messages)
3083 static immutable SCstring
[] table
=
3085 SCstring(STC
.auto_
, Token
.toString(TOK
.auto_
)),
3086 SCstring(STC
.scope_
, Token
.toString(TOK
.scope_
)),
3087 SCstring(STC
.static_
, Token
.toString(TOK
.static_
)),
3088 SCstring(STC
.extern_
, Token
.toString(TOK
.extern_
)),
3089 SCstring(STC
.const_
, Token
.toString(TOK
.const_
)),
3090 SCstring(STC
.final_
, Token
.toString(TOK
.final_
)),
3091 SCstring(STC
.abstract_
, Token
.toString(TOK
.abstract_
)),
3092 SCstring(STC
.synchronized_
, Token
.toString(TOK
.synchronized_
)),
3093 SCstring(STC
.deprecated_
, Token
.toString(TOK
.deprecated_
)),
3094 SCstring(STC
.override_
, Token
.toString(TOK
.override_
)),
3095 SCstring(STC
.lazy_
, Token
.toString(TOK
.lazy_
)),
3096 SCstring(STC
.alias_
, Token
.toString(TOK
.alias_
)),
3097 SCstring(STC
.out_
, Token
.toString(TOK
.out_
)),
3098 SCstring(STC
.in_
, Token
.toString(TOK
.in_
)),
3099 SCstring(STC
.manifest
, Token
.toString(TOK
.enum_
)),
3100 SCstring(STC
.immutable_
, Token
.toString(TOK
.immutable_
)),
3101 SCstring(STC
.shared_
, Token
.toString(TOK
.shared_
)),
3102 SCstring(STC
.nothrow_
, Token
.toString(TOK
.nothrow_
)),
3103 SCstring(STC
.wild
, Token
.toString(TOK
.inout_
)),
3104 SCstring(STC
.pure_
, Token
.toString(TOK
.pure_
)),
3105 SCstring(STC
.ref_
, Token
.toString(TOK
.ref_
)),
3106 SCstring(STC
.return_
, Token
.toString(TOK
.return_
)),
3107 SCstring(STC
.gshared
, Token
.toString(TOK
.gshared
)),
3108 SCstring(STC
.nogc
, "@nogc"),
3109 SCstring(STC
.live
, "@live"),
3110 SCstring(STC
.property
, "@property"),
3111 SCstring(STC
.safe
, "@safe"),
3112 SCstring(STC
.trusted
, "@trusted"),
3113 SCstring(STC
.system
, "@system"),
3114 SCstring(STC
.disable
, "@disable"),
3115 SCstring(STC
.future
, "@__future"),
3116 SCstring(STC
.local
, "__local"),
3118 foreach (ref entry
; table
)
3120 const StorageClass tbl
= entry
.stc;
3121 assert(tbl
& STC
.visibleStorageClasses
);
3128 //printf("stc = %llx\n", stc);
3132 private void linkageToBuffer(ref OutBuffer buf
, LINK linkage
) @safe
3134 const s
= linkageToString(linkage
);
3137 buf
.writestring("extern (");
3143 const(char)* linkageToChars(LINK linkage
)
3145 /// Works because we return a literal
3146 return linkageToString(linkage
).ptr
;
3149 string
linkageToString(LINK linkage
) pure nothrow @safe
3153 immutable string
[7] a
= [
3158 windows
: "Windows",
3159 objc
: "Objective-C",
3160 system
: "System" ];
3165 void visibilityToBuffer(ref OutBuffer buf
, Visibility vis
)
3167 buf
.writestring(visibilityToString(vis
.kind
));
3168 if (vis
.kind
== Visibility
.Kind
.package_
&& vis
.pkg
)
3171 buf
.writestring(vis
.pkg
.toPrettyChars(true));
3178 * a human readable representation of `kind`
3180 const(char)* visibilityToChars(Visibility
.Kind kind
)
3182 // Null terminated because we return a literal
3183 return visibilityToString(kind
).ptr
;
3187 extern (D
) string
visibilityToString(Visibility
.Kind kind
) nothrow pure @safe
3189 with (Visibility
.Kind
)
3191 immutable string
[7] a
= [
3193 private_
: "private",
3194 package_
: "package",
3195 protected_
: "protected",
3197 export_
: "export" ];
3202 // Print the full function signature with correct ident, attributes and template args
3203 void functionToBufferFull(TypeFunction tf
, ref OutBuffer buf
, const Identifier ident
, HdrGenState
* hgs
, TemplateDeclaration td
)
3205 //printf("TypeFunction::toCBuffer() this = %p\n", this);
3206 visitFuncIdentWithPrefix(tf
, ident
, td
, buf
, hgs
);
3209 // ident is inserted before the argument list and will be "function" or "delegate" for a type
3210 void functionToBufferWithIdent(TypeFunction tf
, ref OutBuffer buf
, const(char)* ident
, bool isStatic
)
3213 visitFuncIdentWithPostfix(tf
, ident
.toDString(), buf
, &hgs
, isStatic
);
3216 void toCBuffer(const Expression e
, ref OutBuffer buf
, ref HdrGenState hgs
)
3218 expressionPrettyPrint(cast()e
, buf
, &hgs
);
3221 /**************************************************
3222 * Write out argument types to buf.
3224 void argExpTypesToCBuffer(ref OutBuffer buf
, Expressions
* arguments
)
3226 if (!arguments ||
!arguments
.length
)
3229 foreach (i
, arg
; *arguments
)
3232 buf
.writestring(", ");
3233 typeToBuffer(arg
.type
, null, buf
, &hgs
);
3237 void toCBuffer(const TemplateParameter tp
, ref OutBuffer buf
, ref HdrGenState hgs
)
3239 scope v
= new TemplateParameterPrettyPrintVisitor(&buf
, &hgs
);
3240 (cast() tp
).accept(v
);
3243 void arrayObjectsToBuffer(ref OutBuffer buf
, Objects
* objects
)
3245 if (!objects ||
!objects
.length
)
3248 foreach (i
, o
; *objects
)
3251 buf
.writestring(", ");
3252 objectToBuffer(o
, buf
, &hgs
);
3256 /*************************************************************
3257 * Pretty print function parameters.
3259 * pl = parameter list to print
3260 * Returns: Null-terminated string representing parameters.
3262 extern (C
++) const(char)* parametersTypeToChars(ParameterList pl
)
3266 parametersToBuffer(pl
, buf
, &hgs
);
3267 return buf
.extractChars();
3270 /*************************************************************
3271 * Pretty print function parameter.
3273 * parameter = parameter to print.
3274 * tf = TypeFunction which holds parameter.
3275 * fullQual = whether to fully qualify types.
3276 * Returns: Null-terminated string representing parameters.
3278 const(char)* parameterToChars(Parameter parameter
, TypeFunction tf
, bool fullQual
)
3282 hgs
.fullQual
= fullQual
;
3284 parameterToBuffer(parameter
, buf
, &hgs
);
3286 if (tf
.parameterList
.varargs
== VarArg
.typesafe
&& parameter
== tf
.parameterList
[tf
.parameterList
.parameters
.length
- 1])
3288 buf
.writestring("...");
3290 return buf
.extractChars();
3294 /*************************************************
3295 * Write ParameterList to buffer.
3297 * pl = parameter list to serialize
3298 * buf = buffer to write it to
3302 private void parametersToBuffer(ParameterList pl
, ref OutBuffer buf
, HdrGenState
* hgs
)
3305 foreach (i
; 0 .. pl
.length
)
3308 buf
.writestring(", ");
3309 pl
[i
].parameterToBuffer(buf
, hgs
);
3311 final switch (pl
.varargs
)
3314 case VarArg
.KRvariadic
:
3317 case VarArg
.variadic
:
3319 buf
.writestring(", ");
3321 if (stcToBuffer(buf
, pl
.stc))
3323 goto case VarArg
.typesafe
;
3325 case VarArg
.typesafe
:
3326 buf
.writestring("...");
3333 /***********************************************************
3334 * Write parameter `p` to buffer `buf`.
3336 * p = parameter to serialize
3337 * buf = buffer to write it to
3340 private void parameterToBuffer(Parameter p
, ref OutBuffer buf
, HdrGenState
* hgs
)
3342 if (p
.userAttribDecl
)
3346 bool isAnonymous
= p
.userAttribDecl
.atts
.length
> 0 && !(*p
.userAttribDecl
.atts
)[0].isCallExp();
3350 argsToBuffer(p
.userAttribDecl
.atts
, buf
, hgs
);
3356 if (p
.storageClass
& STC
.auto_
)
3357 buf
.writestring("auto ");
3359 StorageClass
stc = p
.storageClass
;
3360 if (p
.storageClass
& STC
.in_
)
3362 buf
.writestring("in ");
3363 if (global
.params
.previewIn
&& p
.storageClass
& STC
.ref_
)
3366 else if (p
.storageClass
& STC
.lazy_
)
3367 buf
.writestring("lazy ");
3368 else if (p
.storageClass
& STC
.alias_
)
3369 buf
.writestring("alias ");
3371 if (p
.type
&& p
.type
.mod
& MODFlags
.shared_
)
3372 stc &= ~STC
.shared_
;
3374 if (stcToBuffer(buf
, stc & (STC
.const_ | STC
.immutable_ | STC
.wild | STC
.shared_ |
3375 STC
.return_ | STC
.returninferred | STC
.scope_ | STC
.scopeinferred | STC
.out_ | STC
.ref_ | STC
.returnScope
)))
3378 if (p
.storageClass
& STC
.alias_
)
3381 buf
.writestring(p
.ident
.toString());
3383 else if (p
.type
.ty
== Tident
&&
3384 (cast(TypeIdentifier
)p
.type
).ident
.toString().length
> 3 &&
3385 strncmp((cast(TypeIdentifier
)p
.type
).ident
.toChars(), "__T", 3) == 0)
3387 // print parameter name, instead of undetermined type parameter
3388 buf
.writestring(p
.ident
.toString());
3392 typeToBuffer(p
.type
, p
.ident
, buf
, hgs
, (stc & STC
.in_
) ? MODFlags
.const_
: 0);
3397 buf
.writestring(" = ");
3398 p
.defaultArg
.expToBuffer(PREC
.assign
, buf
, hgs
);
3403 /**************************************************
3404 * Write out argument list to buf.
3406 * expressions = argument list
3407 * buf = buffer to write to
3409 * basis = replace `null`s in argument list with this expression (for sparse array literals)
3410 * names = if non-null, use these as the names for the arguments
3412 private void argsToBuffer(Expressions
* expressions
, ref OutBuffer buf
, HdrGenState
* hgs
, Expression basis
= null, Identifiers
* names
= null)
3414 if (!expressions ||
!expressions
.length
)
3418 foreach (i
, el
; *expressions
)
3421 buf
.writestring(", ");
3423 if (names
&& i
< names
.length
&& (*names
)[i
])
3425 buf
.writestring((*names
)[i
].toString());
3426 buf
.writestring(": ");
3431 expToBuffer(el
, PREC
.assign
, buf
, hgs
);
3436 // Sparse style formatting, for debug use only
3437 // [0..length: basis, 1: e1, 5: e5]
3440 buf
.writestring("0..");
3441 buf
.print(expressions
.length
);
3442 buf
.writestring(": ");
3443 expToBuffer(basis
, PREC
.assign
, buf
, hgs
);
3445 foreach (i
, el
; *expressions
)
3451 buf
.writestring(", ");
3453 buf
.writestring(": ");
3456 buf
.writestring(", ");
3457 expToBuffer(el
, PREC
.assign
, buf
, hgs
);
3463 private void sizeToBuffer(Expression e
, ref OutBuffer buf
, HdrGenState
* hgs
)
3465 if (e
.type
== Type
.tsize_t
)
3467 Expression ex
= (e
.op
== EXP
.cast_ ?
(cast(CastExp
)e
).e1
: e
);
3468 ex
= ex
.optimize(WANTvalue
);
3469 const dinteger_t uval
= ex
.op
== EXP
.int64 ? ex
.toInteger() : cast(dinteger_t
)-1;
3470 if (cast(sinteger_t
)uval
>= 0)
3472 dinteger_t sizemax
= void;
3473 if (target
.ptrsize
== 8)
3474 sizemax
= 0xFFFFFFFFFFFFFFFFUL
;
3475 else if (target
.ptrsize
== 4)
3476 sizemax
= 0xFFFFFFFFU
;
3477 else if (target
.ptrsize
== 2)
3481 if (uval
<= sizemax
&& uval
<= 0x7FFFFFFFFFFFFFFFUL
)
3488 expToBuffer(e
, PREC
.assign
, buf
, hgs
);
3491 private void expressionToBuffer(Expression e
, ref OutBuffer buf
, HdrGenState
* hgs
)
3493 expressionPrettyPrint(e
, buf
, hgs
);
3496 /**************************************************
3497 * Write expression out to buf, but wrap it
3498 * in ( ) if its precedence is less than pr.
3500 private void expToBuffer(Expression e
, PREC pr
, ref OutBuffer buf
, HdrGenState
* hgs
)
3504 if (precedence
[e
.op
] == PREC
.zero
)
3505 printf("precedence not defined for token '%s'\n", EXPtoString(e
.op
).ptr
);
3509 buf
.writestring("<FF>");
3512 assert(precedence
[e
.op
] != PREC
.zero
);
3513 assert(pr
!= PREC
.zero
);
3514 /* Despite precedence, we don't allow a<b<c expressions.
3515 * They must be parenthesized.
3517 if (precedence
[e
.op
] < pr ||
(pr
== PREC
.rel
&& precedence
[e
.op
] == pr
)
3518 ||
(pr
>= PREC
.or && pr
<= PREC
.and && precedence
[e
.op
] == PREC
.rel
))
3521 e
.expressionToBuffer(buf
, hgs
);
3526 e
.expressionToBuffer(buf
, hgs
);
3531 /**************************************************
3532 * An entry point to pretty-print type.
3534 private void typeToBuffer(Type t
, const Identifier ident
, ref OutBuffer buf
, HdrGenState
* hgs
,
3537 if (auto tf
= t
.isTypeFunction())
3539 visitFuncIdentWithPrefix(tf
, ident
, null, buf
, hgs
);
3542 visitWithMask(t
, modMask
, buf
, hgs
);
3546 buf
.writestring(ident
.toString());
3550 private void visitWithMask(Type t
, ubyte modMask
, ref OutBuffer buf
, HdrGenState
* hgs
)
3552 // Tuples and functions don't use the type constructor syntax
3553 if (modMask
== t
.mod || t
.ty
== Tfunction || t
.ty
== Ttuple
)
3555 typeToBufferx(t
, buf
, hgs
);
3559 ubyte m
= t
.mod
& ~(t
.mod
& modMask
);
3560 if (m
& MODFlags
.shared_
)
3562 MODtoBuffer(buf
, MODFlags
.shared_
);
3565 if (m
& MODFlags
.wild
)
3567 MODtoBuffer(buf
, MODFlags
.wild
);
3570 if (m
& (MODFlags
.const_ | MODFlags
.immutable_
))
3572 MODtoBuffer(buf
, m
& (MODFlags
.const_ | MODFlags
.immutable_
));
3575 typeToBufferx(t
, buf
, hgs
);
3576 if (m
& (MODFlags
.const_ | MODFlags
.immutable_
))
3578 if (m
& MODFlags
.wild
)
3580 if (m
& MODFlags
.shared_
)
3586 private void dumpTemplateInstance(TemplateInstance ti
, ref OutBuffer buf
, HdrGenState
* hgs
)
3594 ti
.aliasdecl
.dsymbolToBuffer(buf
, hgs
);
3597 else if (ti
.members
)
3599 foreach(m
;*ti
.members
)
3600 m
.dsymbolToBuffer(buf
, hgs
);
3609 private void tiargsToBuffer(TemplateInstance ti
, ref OutBuffer buf
, HdrGenState
* hgs
)
3614 buf
.writestring("(...)");
3619 buf
.writestring("()");
3622 if (ti
.tiargs
.length
== 1)
3624 RootObject oarg
= (*ti
.tiargs
)[0];
3625 if (Type t
= isType(oarg
))
3627 if (t
.equals(Type
.tstring
) || t
.equals(Type
.twstring
) || t
.equals(Type
.tdstring
) || t
.mod
== 0 && (t
.isTypeBasic() || t
.ty
== Tident
&& (cast(TypeIdentifier
)t
).idents
.length
== 0))
3629 buf
.writestring(t
.toChars());
3633 else if (Expression e
= isExpression(oarg
))
3635 if (e
.op
== EXP
.int64 || e
.op
== EXP
.float64 || e
.op
== EXP
.null_ || e
.op
== EXP
.string_ || e
.op
== EXP
.this_
)
3637 buf
.writestring(e
.toChars());
3644 foreach (i
, arg
; *ti
.tiargs
)
3647 buf
.writestring(", ");
3648 objectToBuffer(arg
, buf
, hgs
);
3654 /****************************************
3655 * This makes a 'pretty' version of the template arguments.
3656 * It's analogous to genIdent() which makes a mangled version.
3658 private void objectToBuffer(RootObject oarg
, ref OutBuffer buf
, HdrGenState
* hgs
)
3660 //printf("objectToBuffer()\n");
3661 /* The logic of this should match what genIdent() does. The _dynamic_cast()
3662 * function relies on all the pretty strings to be unique for different classes
3663 * See https://issues.dlang.org/show_bug.cgi?id=7375
3664 * Perhaps it would be better to demangle what genIdent() does.
3666 if (auto t
= isType(oarg
))
3668 //printf("\tt: %s ty = %d\n", t.toChars(), t.ty);
3669 typeToBuffer(t
, null, buf
, hgs
);
3671 else if (auto e
= isExpression(oarg
))
3673 if (e
.op
== EXP
.variable
)
3674 e
= e
.optimize(WANTvalue
); // added to fix https://issues.dlang.org/show_bug.cgi?id=7375
3675 expToBuffer(e
, PREC
.assign
, buf
, hgs
);
3677 else if (Dsymbol s
= isDsymbol(oarg
))
3679 const p
= s
.ident ? s
.ident
.toChars() : s
.toChars();
3682 else if (auto v
= isTuple(oarg
))
3684 auto args
= &v
.objects
;
3685 foreach (i
, arg
; *args
)
3688 buf
.writestring(", ");
3689 objectToBuffer(arg
, buf
, hgs
);
3692 else if (auto p
= isParameter(oarg
))
3694 parameterToBuffer(p
, buf
, hgs
);
3698 buf
.writestring("NULL");
3704 printf("bad Object = %p\n", oarg
);
3711 private void visitFuncIdentWithPostfix(TypeFunction t
, const char[] ident
, ref OutBuffer buf
, HdrGenState
* hgs
, bool isStatic
)
3715 t
.inuse
= 2; // flag error to caller
3719 if (t
.linkage
> LINK
.d
&& hgs
.ddoc
!= 1 && !hgs
.hdrgen
)
3721 linkageToBuffer(buf
, t
.linkage
);
3724 if (t
.linkage
== LINK
.objc
&& isStatic
)
3725 buf
.write("static ");
3728 typeToBuffer(t
.next
, null, buf
, hgs
);
3733 buf
.writestring("auto ");
3735 buf
.writestring(ident
);
3736 parametersToBuffer(t
.parameterList
, buf
, hgs
);
3737 /* Use postfix style for attributes
3742 MODtoBuffer(buf
, t
.mod
);
3748 buf
.writestring(str);
3750 t
.attributesApply(&dg
);
3755 private void visitFuncIdentWithPrefix(TypeFunction t
, const Identifier ident
, TemplateDeclaration td
,
3756 ref OutBuffer buf
, HdrGenState
* hgs
)
3760 t
.inuse
= 2; // flag error to caller
3765 /* Use 'storage class' (prefix) style for attributes
3769 MODtoBuffer(buf
, t
.mod
);
3773 void ignoreReturn(string
str)
3775 if (str != "return")
3777 // don't write 'ref' for ctors
3778 if ((ident
== Id
.ctor
) && str == "ref")
3780 buf
.writestring(str);
3784 t
.attributesApply(&ignoreReturn
);
3786 if (t
.linkage
> LINK
.d
&& hgs
.ddoc
!= 1 && !hgs
.hdrgen
)
3788 linkageToBuffer(buf
, t
.linkage
);
3791 if (ident
&& ident
.toHChars2() != ident
.toChars())
3793 // Don't print return type for ctor, dtor, unittest, etc
3797 typeToBuffer(t
.next
, null, buf
, hgs
);
3802 buf
.writestring("auto ");
3804 buf
.writestring(ident
.toHChars2());
3808 foreach (i
, p
; *td
.origParameters
)
3811 buf
.writestring(", ");
3812 p
.templateParameterToBuffer(buf
, hgs
);
3816 parametersToBuffer(t
.parameterList
, buf
, hgs
);
3819 buf
.writestring(" return");
3825 private void initializerToBuffer(Initializer inx
, ref OutBuffer buf
, HdrGenState
* hgs
)
3827 void visitError(ErrorInitializer iz
)
3829 buf
.writestring("__error__");
3832 void visitVoid(VoidInitializer iz
)
3834 buf
.writestring("void");
3837 void visitStruct(StructInitializer si
)
3839 //printf("StructInitializer::toCBuffer()\n");
3841 foreach (i
, const id
; si
.field
)
3844 buf
.writestring(", ");
3847 buf
.writestring(id
.toString());
3850 if (auto iz
= si
.value
[i
])
3851 initializerToBuffer(iz
, buf
, hgs
);
3856 void visitArray(ArrayInitializer ai
)
3859 foreach (i
, ex
; ai
.index
)
3862 buf
.writestring(", ");
3865 ex
.expressionToBuffer(buf
, hgs
);
3868 if (auto iz
= ai
.value
[i
])
3869 initializerToBuffer(iz
, buf
, hgs
);
3874 void visitExp(ExpInitializer ei
)
3876 ei
.exp
.expressionToBuffer(buf
, hgs
);
3879 void visitC(CInitializer ci
)
3882 foreach (i
, ref DesigInit
di; ci
.initializerList
)
3885 buf
.writestring(", ");
3886 if (di.designatorList
)
3888 foreach (ref Designator d
; (*di.designatorList
)[])
3893 toCBuffer(d
.exp
, buf
, *hgs
);
3899 buf
.writestring(d
.ident
.toString());
3904 initializerToBuffer(di.initializer
, buf
, hgs
);
3909 mixin VisitInitializer
!void visit
;
3910 visit
.VisitInitializer(inx
);
3914 private void typeToBufferx(Type t
, ref OutBuffer buf
, HdrGenState
* hgs
)
3916 void visitType(Type t
)
3918 printf("t = %p, ty = %d\n", t
, t
.ty
);
3922 void visitError(TypeError t
)
3924 buf
.writestring("_error_");
3927 void visitBasic(TypeBasic t
)
3929 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
3930 buf
.writestring(t
.dstring
);
3933 void visitTraits(TypeTraits t
)
3935 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
3936 t
.exp
.expressionToBuffer(buf
, hgs
);
3939 void visitVector(TypeVector t
)
3941 //printf("TypeVector::toCBuffer2(t.mod = %d)\n", t.mod);
3942 buf
.writestring("__vector(");
3943 visitWithMask(t
.basetype
, t
.mod
, buf
, hgs
);
3944 buf
.writestring(")");
3947 void visitSArray(TypeSArray t
)
3949 visitWithMask(t
.next
, t
.mod
, buf
, hgs
);
3951 sizeToBuffer(t
.dim
, buf
, hgs
);
3955 void visitDArray(TypeDArray t
)
3957 Type ut
= t
.castMod(0);
3960 if (ut
.equals(Type
.tstring
))
3961 buf
.writestring("string");
3962 else if (ut
.equals(Type
.twstring
))
3963 buf
.writestring("wstring");
3964 else if (ut
.equals(Type
.tdstring
))
3965 buf
.writestring("dstring");
3969 visitWithMask(t
.next
, t
.mod
, buf
, hgs
);
3970 buf
.writestring("[]");
3974 void visitAArray(TypeAArray t
)
3976 visitWithMask(t
.next
, t
.mod
, buf
, hgs
);
3978 visitWithMask(t
.index
, 0, buf
, hgs
);
3982 void visitPointer(TypePointer t
)
3984 //printf("TypePointer::toCBuffer2() next = %d\n", t.next.ty);
3985 if (t
.next
.ty
== Tfunction
)
3986 visitFuncIdentWithPostfix(cast(TypeFunction
)t
.next
, "function", buf
, hgs
, false);
3989 visitWithMask(t
.next
, t
.mod
, buf
, hgs
);
3994 void visitReference(TypeReference t
)
3996 visitWithMask(t
.next
, t
.mod
, buf
, hgs
);
4000 void visitFunction(TypeFunction t
)
4002 //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t.isref);
4003 visitFuncIdentWithPostfix(t
, null, buf
, hgs
, false);
4006 void visitDelegate(TypeDelegate t
)
4008 visitFuncIdentWithPostfix(cast(TypeFunction
)t
.next
, "delegate", buf
, hgs
, false);
4011 void visitTypeQualifiedHelper(TypeQualified t
)
4013 foreach (id
; t
.idents
)
4015 switch (id
.dyncast()) with (DYNCAST
)
4019 TemplateInstance ti
= cast(TemplateInstance
)id
;
4020 ti
.dsymbolToBuffer(buf
, hgs
);
4024 (cast(Expression
)id
).expressionToBuffer(buf
, hgs
);
4029 typeToBufferx(cast(Type
)id
, buf
, hgs
);
4034 buf
.writestring(id
.toString());
4039 void visitIdentifier(TypeIdentifier t
)
4041 buf
.writestring(t
.ident
.toString());
4042 visitTypeQualifiedHelper(t
);
4045 void visitInstance(TypeInstance t
)
4047 t
.tempinst
.dsymbolToBuffer(buf
, hgs
);
4048 visitTypeQualifiedHelper(t
);
4051 void visitTypeof(TypeTypeof t
)
4053 buf
.writestring("typeof(");
4054 t
.exp
.expressionToBuffer(buf
, hgs
);
4056 visitTypeQualifiedHelper(t
);
4059 void visitReturn(TypeReturn t
)
4061 buf
.writestring("typeof(return)");
4062 visitTypeQualifiedHelper(t
);
4065 void visitEnum(TypeEnum t
)
4067 buf
.writestring(hgs
.fullQual ? t
.sym
.toPrettyChars() : t
.sym
.toChars());
4070 void visitStruct(TypeStruct t
)
4072 // https://issues.dlang.org/show_bug.cgi?id=13776
4073 // Don't use ti.toAlias() to avoid forward reference error
4074 // while printing messages.
4075 TemplateInstance ti
= t
.sym
.parent ? t
.sym
.parent
.isTemplateInstance() : null;
4076 if (ti
&& ti
.aliasdecl
== t
.sym
)
4077 buf
.writestring(hgs
.fullQual ? ti
.toPrettyChars() : ti
.toChars());
4079 buf
.writestring(hgs
.fullQual ? t
.sym
.toPrettyChars() : t
.sym
.toChars());
4082 void visitClass(TypeClass t
)
4084 // https://issues.dlang.org/show_bug.cgi?id=13776
4085 // Don't use ti.toAlias() to avoid forward reference error
4086 // while printing messages.
4087 TemplateInstance ti
= t
.sym
.parent ? t
.sym
.parent
.isTemplateInstance() : null;
4088 if (ti
&& ti
.aliasdecl
== t
.sym
)
4089 buf
.writestring(hgs
.fullQual ? ti
.toPrettyChars() : ti
.toChars());
4091 buf
.writestring(hgs
.fullQual ? t
.sym
.toPrettyChars() : t
.sym
.toChars());
4094 void visitTag(TypeTag t
)
4096 if (t
.mod
& MODFlags
.const_
)
4097 buf
.writestring("const ");
4098 buf
.writestring(Token
.toChars(t
.tok
));
4101 buf
.writestring(t
.id
.toChars());
4102 if (t
.tok
== TOK
.enum_
&& t
.base
&& t
.base
.ty
!= TY
.Tint32
)
4104 buf
.writestring(" : ");
4105 visitWithMask(t
.base
, t
.mod
, buf
, hgs
);
4109 void visitTuple(TypeTuple t
)
4111 parametersToBuffer(ParameterList(t
.arguments
, VarArg
.none
), buf
, hgs
);
4114 void visitSlice(TypeSlice t
)
4116 visitWithMask(t
.next
, t
.mod
, buf
, hgs
);
4118 sizeToBuffer(t
.lwr
, buf
, hgs
);
4119 buf
.writestring(" .. ");
4120 sizeToBuffer(t
.upr
, buf
, hgs
);
4124 void visitNull(TypeNull t
)
4126 buf
.writestring("typeof(null)");
4129 void visitMixin(TypeMixin t
)
4131 buf
.writestring("mixin(");
4132 argsToBuffer(t
.exps
, buf
, hgs
, null);
4136 void visitNoreturn(TypeNoreturn t
)
4138 buf
.writestring("noreturn");
4144 default: return t
.isTypeBasic() ?
4145 visitBasic(cast(TypeBasic
)t
) :
4148 case Terror
: return visitError(cast(TypeError
)t
);
4149 case Ttraits
: return visitTraits(cast(TypeTraits
)t
);
4150 case Tvector
: return visitVector(cast(TypeVector
)t
);
4151 case Tsarray
: return visitSArray(cast(TypeSArray
)t
);
4152 case Tarray
: return visitDArray(cast(TypeDArray
)t
);
4153 case Taarray
: return visitAArray(cast(TypeAArray
)t
);
4154 case Tpointer
: return visitPointer(cast(TypePointer
)t
);
4155 case Treference
: return visitReference(cast(TypeReference
)t
);
4156 case Tfunction
: return visitFunction(cast(TypeFunction
)t
);
4157 case Tdelegate
: return visitDelegate(cast(TypeDelegate
)t
);
4158 case Tident
: return visitIdentifier(cast(TypeIdentifier
)t
);
4159 case Tinstance
: return visitInstance(cast(TypeInstance
)t
);
4160 case Ttypeof
: return visitTypeof(cast(TypeTypeof
)t
);
4161 case Treturn
: return visitReturn(cast(TypeReturn
)t
);
4162 case Tenum
: return visitEnum(cast(TypeEnum
)t
);
4163 case Tstruct
: return visitStruct(cast(TypeStruct
)t
);
4164 case Tclass
: return visitClass(cast(TypeClass
)t
);
4165 case Ttuple
: return visitTuple (cast(TypeTuple
)t
);
4166 case Tslice
: return visitSlice(cast(TypeSlice
)t
);
4167 case Tnull
: return visitNull(cast(TypeNull
)t
);
4168 case Tmixin
: return visitMixin(cast(TypeMixin
)t
);
4169 case Tnoreturn
: return visitNoreturn(cast(TypeNoreturn
)t
);
4170 case Ttag
: return visitTag(cast(TypeTag
)t
);
4174 /****************************************
4175 * Convert EXP to char*.
4178 string
EXPtoString(EXP op
)
4180 static immutable char*[EXP
.max
+ 1] strings
=
4183 EXP
.error
: "error",
4184 EXP
.objcClassReference
: "class",
4186 EXP
.mixin_
: "mixin",
4188 EXP
.import_
: "import",
4189 EXP
.dotVariable
: "dotvar",
4190 EXP
.scope_
: "scope",
4191 EXP
.identifier
: "identifier",
4193 EXP
.super_
: "super",
4195 EXP
.float64
: "double",
4196 EXP
.complex80
: "creal",
4198 EXP
.string_
: "string",
4199 EXP
.arrayLiteral
: "arrayliteral",
4200 EXP
.assocArrayLiteral
: "assocarrayliteral",
4201 EXP
.classReference
: "classreference",
4202 EXP
.file
: "__FILE__",
4203 EXP
.fileFullPath
: "__FILE_FULL_PATH__",
4204 EXP
.line
: "__LINE__",
4205 EXP
.moduleString
: "__MODULE__",
4206 EXP
.functionString
: "__FUNCTION__",
4207 EXP
.prettyFunction
: "__PRETTY_FUNCTION__",
4208 EXP
.typeid_
: "typeid",
4210 EXP
.assert_
: "assert",
4212 EXP
.template_
: "template",
4213 EXP
.dSymbol
: "symbol",
4214 EXP
.function_
: "function",
4215 EXP
.variable
: "var",
4216 EXP
.symbolOffset
: "symoff",
4217 EXP
.structLiteral
: "structLiteral",
4218 EXP
.compoundLiteral
: "compoundliteral",
4219 EXP
.arrayLength
: "arraylength",
4220 EXP
.delegatePointer
: "delegateptr",
4221 EXP
.delegateFunctionPointer
: "delegatefuncptr",
4222 EXP
.remove
: "remove",
4223 EXP
.tuple
: "sequence",
4224 EXP
.traits
: "__traits",
4225 EXP
.overloadSet
: "__overloadset",
4227 EXP
.vectorArray
: "vectorarray",
4228 EXP
._Generic
: "_Generic",
4231 EXP
.dotTemplateInstance
: "dotti",
4232 EXP
.dotIdentifier
: "dotid",
4233 EXP
.dotTemplateDeclaration
: "dottd",
4235 EXP
.dotType
: "dottype",
4236 EXP
.plusPlus
: "++",
4237 EXP
.minusMinus
: "--",
4238 EXP
.prePlusPlus
: "++",
4239 EXP
.preMinusMinus
: "--",
4245 EXP
.delegate_
: "delegate",
4252 EXP
.delete_
: "delete",
4254 EXP
.newAnonymousClass
: "newanonclass",
4257 EXP
.vector
: "__vector",
4266 EXP
.concatenate
: "~",
4268 EXP
.leftShift
: "<<",
4269 EXP
.rightShift
: ">>",
4270 EXP
.unsignedRightShift
: ">>>",
4273 EXP
.lessOrEqual
: "<=",
4274 EXP
.greaterThan
: ">",
4275 EXP
.greaterOrEqual
: ">=",
4279 EXP
.notEqual
: "!=",
4280 EXP
.identity
: "is",
4281 EXP
.notIdentity
: "!is",
4293 EXP
.construct
: "=",
4295 EXP
.addAssign
: "+=",
4296 EXP
.minAssign
: "-=",
4297 EXP
.concatenateAssign
: "~=",
4298 EXP
.concatenateElemAssign
: "~=",
4299 EXP
.concatenateDcharAssign
: "~=",
4300 EXP
.mulAssign
: "*=",
4301 EXP
.divAssign
: "/=",
4302 EXP
.modAssign
: "%=",
4303 EXP
.powAssign
: "^^=",
4304 EXP
.leftShiftAssign
: "<<=",
4305 EXP
.rightShiftAssign
: ">>=",
4306 EXP
.unsignedRightShiftAssign
: ">>>=",
4307 EXP
.andAssign
: "&=",
4308 EXP
.orAssign
: "|=",
4309 EXP
.xorAssign
: "^=",
4312 EXP
.declaration
: "declaration",
4314 EXP
.interval
: "interval",
4315 EXP
.loweredAssignExp
: "="
4317 const p
= strings
[op
];
4320 printf("error: EXP %d has no string\n", op
);
4325 return p
[0 .. strlen(p
)];