1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4  * written by Walter Bright
5  * http://www.digitalmars.com
6  * Distributed under the Boost Software License, Version 1.0.
7  * http://www.boost.org/LICENSE_1_0.txt
8  * https://github.com/dlang/dmd/blob/master/src/dmd/statement.h
9  */
10 
11 #pragma once
12 
13 #include "root/root.h"
14 
15 #include "arraytypes.h"
16 #include "dsymbol.h"
17 #include "visitor.h"
18 #include "tokens.h"
19 
20 struct OutBuffer;
21 struct Scope;
22 class Expression;
23 class LabelDsymbol;
24 class Identifier;
25 class IfStatement;
26 class ExpStatement;
27 class DefaultStatement;
28 class VarDeclaration;
29 class Condition;
30 class Module;
31 struct Token;
32 class ErrorStatement;
33 class ReturnStatement;
34 class CompoundStatement;
35 class Parameter;
36 class StaticAssert;
37 class AsmStatement;
38 class GotoStatement;
39 class ScopeStatement;
40 class TryCatchStatement;
41 class TryFinallyStatement;
42 class CaseStatement;
43 class DefaultStatement;
44 class LabelStatement;
45 class StaticForeach;
46 
47 // Back end
48 struct code;
49 
50 bool inferAggregate(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply);
51 bool inferApplyArgTypes(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply);
52 
53 /* How a statement exits; this is returned by blockExit()
54  */
55 enum BE
56 {
57     BEnone =     0,
58     BEfallthru = 1,
59     BEthrow =    2,
60     BEreturn =   4,
61     BEgoto =     8,
62     BEhalt =     0x10,
63     BEbreak =    0x20,
64     BEcontinue = 0x40,
65     BEerrthrow = 0x80,
66     BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt)
67 };
68 
69 class Statement : public RootObject
70 {
71 public:
72     Loc loc;
73 
74     Statement(Loc loc);
75     virtual Statement *syntaxCopy();
76 
77     void print();
78     const char *toChars();
79 
80     void error(const char *format, ...);
81     void warning(const char *format, ...);
82     void deprecation(const char *format, ...);
getRelatedLabeled()83     virtual Statement *getRelatedLabeled() { return this; }
84     virtual bool hasBreak();
85     virtual bool hasContinue();
86     bool usesEH();
87     bool comeFrom();
88     bool hasCode();
89     virtual Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
90     virtual Statements *flatten(Scope *sc);
91     virtual Statement *last();
92 
93     // Avoid dynamic_cast
isErrorStatement()94     virtual ErrorStatement *isErrorStatement() { return NULL; }
isScopeStatement()95     virtual ScopeStatement *isScopeStatement() { return NULL; }
isExpStatement()96     virtual ExpStatement *isExpStatement() { return NULL; }
isCompoundStatement()97     virtual CompoundStatement *isCompoundStatement() { return NULL; }
isReturnStatement()98     virtual ReturnStatement *isReturnStatement() { return NULL; }
isIfStatement()99     virtual IfStatement *isIfStatement() { return NULL; }
isCaseStatement()100     virtual CaseStatement *isCaseStatement() { return NULL; }
isDefaultStatement()101     virtual DefaultStatement *isDefaultStatement() { return NULL; }
isLabelStatement()102     virtual LabelStatement *isLabelStatement() { return NULL; }
isGotoDefaultStatement()103     virtual GotoDefaultStatement *isGotoDefaultStatement() { return NULL; }
isGotoCaseStatement()104     virtual GotoCaseStatement *isGotoCaseStatement() { return NULL; }
isBreakStatement()105     virtual BreakStatement *isBreakStatement() { return NULL; }
isDtorExpStatement()106     virtual DtorExpStatement *isDtorExpStatement() { return NULL; }
isForwardingStatement()107     virtual ForwardingStatement *isForwardingStatement() { return NULL; }
accept(Visitor * v)108     virtual void accept(Visitor *v) { v->visit(this); }
109 };
110 
111 /** Any Statement that fails semantic() or has a component that is an ErrorExp or
112  * a TypeError should return an ErrorStatement from semantic().
113  */
114 class ErrorStatement : public Statement
115 {
116 public:
117     ErrorStatement();
118     Statement *syntaxCopy();
119 
isErrorStatement()120     ErrorStatement *isErrorStatement() { return this; }
accept(Visitor * v)121     void accept(Visitor *v) { v->visit(this); }
122 };
123 
124 class PeelStatement : public Statement
125 {
126 public:
127     Statement *s;
128 
129     PeelStatement(Statement *s);
accept(Visitor * v)130     void accept(Visitor *v) { v->visit(this); }
131 };
132 
133 class ExpStatement : public Statement
134 {
135 public:
136     Expression *exp;
137 
138     ExpStatement(Loc loc, Expression *exp);
139     ExpStatement(Loc loc, Dsymbol *s);
140     static ExpStatement *create(Loc loc, Expression *exp);
141     Statement *syntaxCopy();
142     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
143     Statements *flatten(Scope *sc);
144 
isExpStatement()145     ExpStatement *isExpStatement() { return this; }
accept(Visitor * v)146     void accept(Visitor *v) { v->visit(this); }
147 };
148 
149 class DtorExpStatement : public ExpStatement
150 {
151 public:
152     /* Wraps an expression that is the destruction of 'var'
153      */
154 
155     VarDeclaration *var;
156 
157     DtorExpStatement(Loc loc, Expression *exp, VarDeclaration *v);
158     Statement *syntaxCopy();
accept(Visitor * v)159     void accept(Visitor *v) { v->visit(this); }
160 
isDtorExpStatement()161     DtorExpStatement *isDtorExpStatement() { return this; }
162 };
163 
164 class CompileStatement : public Statement
165 {
166 public:
167     Expression *exp;
168 
169     CompileStatement(Loc loc, Expression *exp);
170     Statement *syntaxCopy();
171     Statements *flatten(Scope *sc);
accept(Visitor * v)172     void accept(Visitor *v) { v->visit(this); }
173 };
174 
175 class CompoundStatement : public Statement
176 {
177 public:
178     Statements *statements;
179 
180     CompoundStatement(Loc loc, Statements *s);
181     CompoundStatement(Loc loc, Statement *s1);
182     CompoundStatement(Loc loc, Statement *s1, Statement *s2);
183     static CompoundStatement *create(Loc loc, Statement *s1, Statement *s2);
184     Statement *syntaxCopy();
185     Statements *flatten(Scope *sc);
186     ReturnStatement *isReturnStatement();
187     Statement *last();
188 
isCompoundStatement()189     CompoundStatement *isCompoundStatement() { return this; }
accept(Visitor * v)190     void accept(Visitor *v) { v->visit(this); }
191 };
192 
193 class CompoundDeclarationStatement : public CompoundStatement
194 {
195 public:
196     CompoundDeclarationStatement(Loc loc, Statements *s);
197     Statement *syntaxCopy();
accept(Visitor * v)198     void accept(Visitor *v) { v->visit(this); }
199 };
200 
201 /* The purpose of this is so that continue will go to the next
202  * of the statements, and break will go to the end of the statements.
203  */
204 class UnrolledLoopStatement : public Statement
205 {
206 public:
207     Statements *statements;
208 
209     UnrolledLoopStatement(Loc loc, Statements *statements);
210     Statement *syntaxCopy();
211     bool hasBreak();
212     bool hasContinue();
213 
accept(Visitor * v)214     void accept(Visitor *v) { v->visit(this); }
215 };
216 
217 class ScopeStatement : public Statement
218 {
219 public:
220     Statement *statement;
221     Loc endloc;                 // location of closing curly bracket
222 
223     ScopeStatement(Loc loc, Statement *s, Loc endloc);
224     Statement *syntaxCopy();
isScopeStatement()225     ScopeStatement *isScopeStatement() { return this; }
226     ReturnStatement *isReturnStatement();
227     bool hasBreak();
228     bool hasContinue();
229 
accept(Visitor * v)230     void accept(Visitor *v) { v->visit(this); }
231 };
232 
233 class ForwardingStatement : public Statement
234 {
235     ForwardingScopeDsymbol *sym;
236     Statement *statement;
237 
238     Statement *syntaxCopy();
239     Statement *getRelatedLabeled();
240     bool hasBreak();
241     bool hasContinue();
242     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally);
243     Statement *last();
244     Statements *flatten(Scope *sc);
isForwardingStatement()245     ForwardingStatement *isForwardingStatement() { return this; }
accept(Visitor * v)246     void accept(Visitor *v) { v->visit(this); }
247 };
248 
249 class WhileStatement : public Statement
250 {
251 public:
252     Expression *condition;
253     Statement *_body;
254     Loc endloc;                 // location of closing curly bracket
255 
256     WhileStatement(Loc loc, Expression *c, Statement *b, Loc endloc);
257     Statement *syntaxCopy();
258     bool hasBreak();
259     bool hasContinue();
260 
accept(Visitor * v)261     void accept(Visitor *v) { v->visit(this); }
262 };
263 
264 class DoStatement : public Statement
265 {
266 public:
267     Statement *_body;
268     Expression *condition;
269     Loc endloc;                 // location of ';' after while
270 
271     DoStatement(Loc loc, Statement *b, Expression *c, Loc endloc);
272     Statement *syntaxCopy();
273     bool hasBreak();
274     bool hasContinue();
275 
accept(Visitor * v)276     void accept(Visitor *v) { v->visit(this); }
277 };
278 
279 class ForStatement : public Statement
280 {
281 public:
282     Statement *_init;
283     Expression *condition;
284     Expression *increment;
285     Statement *_body;
286     Loc endloc;                 // location of closing curly bracket
287 
288     // When wrapped in try/finally clauses, this points to the outermost one,
289     // which may have an associated label. Internal break/continue statements
290     // treat that label as referring to this loop.
291     Statement *relatedLabeled;
292 
293     ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body, Loc endloc);
294     Statement *syntaxCopy();
295     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
getRelatedLabeled()296     Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; }
297     bool hasBreak();
298     bool hasContinue();
299 
accept(Visitor * v)300     void accept(Visitor *v) { v->visit(this); }
301 };
302 
303 class ForeachStatement : public Statement
304 {
305 public:
306     TOK op;                     // TOKforeach or TOKforeach_reverse
307     Parameters *parameters;     // array of Parameter*'s
308     Expression *aggr;
309     Statement *_body;
310     Loc endloc;                 // location of closing curly bracket
311 
312     VarDeclaration *key;
313     VarDeclaration *value;
314 
315     FuncDeclaration *func;      // function we're lexically in
316 
317     Statements *cases;          // put breaks, continues, gotos and returns here
318     ScopeStatements *gotos;     // forward referenced goto's go here
319 
320     ForeachStatement(Loc loc, TOK op, Parameters *parameters, Expression *aggr, Statement *body, Loc endloc);
321     Statement *syntaxCopy();
322     bool checkForArgTypes();
323     bool hasBreak();
324     bool hasContinue();
325 
accept(Visitor * v)326     void accept(Visitor *v) { v->visit(this); }
327 };
328 
329 class ForeachRangeStatement : public Statement
330 {
331 public:
332     TOK op;                     // TOKforeach or TOKforeach_reverse
333     Parameter *prm;             // loop index variable
334     Expression *lwr;
335     Expression *upr;
336     Statement *_body;
337     Loc endloc;                 // location of closing curly bracket
338 
339     VarDeclaration *key;
340 
341     ForeachRangeStatement(Loc loc, TOK op, Parameter *prm,
342         Expression *lwr, Expression *upr, Statement *body, Loc endloc);
343     Statement *syntaxCopy();
344     bool hasBreak();
345     bool hasContinue();
346 
accept(Visitor * v)347     void accept(Visitor *v) { v->visit(this); }
348 };
349 
350 class IfStatement : public Statement
351 {
352 public:
353     Parameter *prm;
354     Expression *condition;
355     Statement *ifbody;
356     Statement *elsebody;
357     Loc endloc;                 // location of closing curly bracket
358 
359     VarDeclaration *match;      // for MatchExpression results
360 
361     IfStatement(Loc loc, Parameter *prm, Expression *condition, Statement *ifbody, Statement *elsebody, Loc endloc);
362     Statement *syntaxCopy();
isIfStatement()363     IfStatement *isIfStatement() { return this; }
364 
accept(Visitor * v)365     void accept(Visitor *v) { v->visit(this); }
366 };
367 
368 class ConditionalStatement : public Statement
369 {
370 public:
371     Condition *condition;
372     Statement *ifbody;
373     Statement *elsebody;
374 
375     ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
376     Statement *syntaxCopy();
377     Statements *flatten(Scope *sc);
378 
accept(Visitor * v)379     void accept(Visitor *v) { v->visit(this); }
380 };
381 
382 class StaticForeachStatement : public Statement
383 {
384 public:
385     StaticForeach *sfe;
386 
387     Statement *syntaxCopy();
388     Statements *flatten(Scope *sc);
389 
accept(Visitor * v)390     void accept(Visitor *v) { v->visit(this); }
391 };
392 
393 class PragmaStatement : public Statement
394 {
395 public:
396     Identifier *ident;
397     Expressions *args;          // array of Expression's
398     Statement *_body;
399 
400     PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
401     Statement *syntaxCopy();
402 
accept(Visitor * v)403     void accept(Visitor *v) { v->visit(this); }
404 };
405 
406 class StaticAssertStatement : public Statement
407 {
408 public:
409     StaticAssert *sa;
410 
411     StaticAssertStatement(StaticAssert *sa);
412     Statement *syntaxCopy();
413 
accept(Visitor * v)414     void accept(Visitor *v) { v->visit(this); }
415 };
416 
417 class SwitchStatement : public Statement
418 {
419 public:
420     Expression *condition;
421     Statement *_body;
422     bool isFinal;
423 
424     DefaultStatement *sdefault;
425     TryFinallyStatement *tf;
426     GotoCaseStatements gotoCases;  // array of unresolved GotoCaseStatement's
427     CaseStatements *cases;         // array of CaseStatement's
428     int hasNoDefault;           // !=0 if no default statement
429     int hasVars;                // !=0 if has variable case values
430     VarDeclaration *lastVar;
431 
432     SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal);
433     Statement *syntaxCopy();
434     bool hasBreak();
435     bool checkLabel();
436 
accept(Visitor * v)437     void accept(Visitor *v) { v->visit(this); }
438 };
439 
440 class CaseStatement : public Statement
441 {
442 public:
443     Expression *exp;
444     Statement *statement;
445 
446     int index;          // which case it is (since we sort this)
447     VarDeclaration *lastVar;
448 
449     CaseStatement(Loc loc, Expression *exp, Statement *s);
450     Statement *syntaxCopy();
451     int compare(RootObject *obj);
isCaseStatement()452     CaseStatement *isCaseStatement() { return this; }
453 
accept(Visitor * v)454     void accept(Visitor *v) { v->visit(this); }
455 };
456 
457 
458 class CaseRangeStatement : public Statement
459 {
460 public:
461     Expression *first;
462     Expression *last;
463     Statement *statement;
464 
465     CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s);
466     Statement *syntaxCopy();
accept(Visitor * v)467     void accept(Visitor *v) { v->visit(this); }
468 };
469 
470 
471 class DefaultStatement : public Statement
472 {
473 public:
474     Statement *statement;
475     VarDeclaration *lastVar;
476 
477     DefaultStatement(Loc loc, Statement *s);
478     Statement *syntaxCopy();
isDefaultStatement()479     DefaultStatement *isDefaultStatement() { return this; }
480 
accept(Visitor * v)481     void accept(Visitor *v) { v->visit(this); }
482 };
483 
484 class GotoDefaultStatement : public Statement
485 {
486 public:
487     SwitchStatement *sw;
488 
489     GotoDefaultStatement(Loc loc);
490     Statement *syntaxCopy();
isGotoDefaultStatement()491     GotoDefaultStatement *isGotoDefaultStatement() { return this; }
492 
accept(Visitor * v)493     void accept(Visitor *v) { v->visit(this); }
494 };
495 
496 class GotoCaseStatement : public Statement
497 {
498 public:
499     Expression *exp;            // NULL, or which case to goto
500     CaseStatement *cs;          // case statement it resolves to
501 
502     GotoCaseStatement(Loc loc, Expression *exp);
503     Statement *syntaxCopy();
isGotoCaseStatement()504     GotoCaseStatement *isGotoCaseStatement() { return this; }
505 
accept(Visitor * v)506     void accept(Visitor *v) { v->visit(this); }
507 };
508 
509 class SwitchErrorStatement : public Statement
510 {
511 public:
512     SwitchErrorStatement(Loc loc);
513 
accept(Visitor * v)514     void accept(Visitor *v) { v->visit(this); }
515 };
516 
517 class ReturnStatement : public Statement
518 {
519 public:
520     Expression *exp;
521     size_t caseDim;
522 
523     ReturnStatement(Loc loc, Expression *exp);
524     Statement *syntaxCopy();
525 
isReturnStatement()526     ReturnStatement *isReturnStatement() { return this; }
accept(Visitor * v)527     void accept(Visitor *v) { v->visit(this); }
528 };
529 
530 class BreakStatement : public Statement
531 {
532 public:
533     Identifier *ident;
534 
535     BreakStatement(Loc loc, Identifier *ident);
536     Statement *syntaxCopy();
537 
isBreakStatement()538     BreakStatement *isBreakStatement() { return this; }
accept(Visitor * v)539     void accept(Visitor *v) { v->visit(this); }
540 };
541 
542 class ContinueStatement : public Statement
543 {
544 public:
545     Identifier *ident;
546 
547     ContinueStatement(Loc loc, Identifier *ident);
548     Statement *syntaxCopy();
549 
accept(Visitor * v)550     void accept(Visitor *v) { v->visit(this); }
551 };
552 
553 class SynchronizedStatement : public Statement
554 {
555 public:
556     Expression *exp;
557     Statement *_body;
558 
559     SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
560     Statement *syntaxCopy();
561     bool hasBreak();
562     bool hasContinue();
563 
accept(Visitor * v)564     void accept(Visitor *v) { v->visit(this); }
565 };
566 
567 class WithStatement : public Statement
568 {
569 public:
570     Expression *exp;
571     Statement *_body;
572     VarDeclaration *wthis;
573     Loc endloc;
574 
575     WithStatement(Loc loc, Expression *exp, Statement *body, Loc endloc);
576     Statement *syntaxCopy();
577 
accept(Visitor * v)578     void accept(Visitor *v) { v->visit(this); }
579 };
580 
581 class TryCatchStatement : public Statement
582 {
583 public:
584     Statement *_body;
585     Catches *catches;
586 
587     TryCatchStatement(Loc loc, Statement *body, Catches *catches);
588     Statement *syntaxCopy();
589     bool hasBreak();
590 
accept(Visitor * v)591     void accept(Visitor *v) { v->visit(this); }
592 };
593 
594 class Catch : public RootObject
595 {
596 public:
597     Loc loc;
598     Type *type;
599     Identifier *ident;
600     VarDeclaration *var;
601     Statement *handler;
602 
603     // set if semantic processing errors
604     bool errors;
605 
606     // was generated by the compiler,
607     // wasn't present in source code
608     bool internalCatch;
609 
610     Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
611     Catch *syntaxCopy();
612 };
613 
614 class TryFinallyStatement : public Statement
615 {
616 public:
617     Statement *_body;
618     Statement *finalbody;
619 
620     TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
621     static TryFinallyStatement *create(Loc loc, Statement *body, Statement *finalbody);
622     Statement *syntaxCopy();
623     bool hasBreak();
624     bool hasContinue();
625 
accept(Visitor * v)626     void accept(Visitor *v) { v->visit(this); }
627 };
628 
629 class OnScopeStatement : public Statement
630 {
631 public:
632     TOK tok;
633     Statement *statement;
634 
635     OnScopeStatement(Loc loc, TOK tok, Statement *statement);
636     Statement *syntaxCopy();
637     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
638 
accept(Visitor * v)639     void accept(Visitor *v) { v->visit(this); }
640 };
641 
642 class ThrowStatement : public Statement
643 {
644 public:
645     Expression *exp;
646     // was generated by the compiler,
647     // wasn't present in source code
648     bool internalThrow;
649 
650     ThrowStatement(Loc loc, Expression *exp);
651     Statement *syntaxCopy();
652 
accept(Visitor * v)653     void accept(Visitor *v) { v->visit(this); }
654 };
655 
656 class DebugStatement : public Statement
657 {
658 public:
659     Statement *statement;
660 
661     DebugStatement(Loc loc, Statement *statement);
662     Statement *syntaxCopy();
663     Statements *flatten(Scope *sc);
accept(Visitor * v)664     void accept(Visitor *v) { v->visit(this); }
665 };
666 
667 class GotoStatement : public Statement
668 {
669 public:
670     Identifier *ident;
671     LabelDsymbol *label;
672     TryFinallyStatement *tf;
673     OnScopeStatement *os;
674     VarDeclaration *lastVar;
675 
676     GotoStatement(Loc loc, Identifier *ident);
677     Statement *syntaxCopy();
678     bool checkLabel();
679 
accept(Visitor * v)680     void accept(Visitor *v) { v->visit(this); }
681 };
682 
683 class LabelStatement : public Statement
684 {
685 public:
686     Identifier *ident;
687     Statement *statement;
688     TryFinallyStatement *tf;
689     OnScopeStatement *os;
690     VarDeclaration *lastVar;
691     Statement *gotoTarget;      // interpret
692 
693     bool breaks;                // someone did a 'break ident'
694 
695     LabelStatement(Loc loc, Identifier *ident, Statement *statement);
696     Statement *syntaxCopy();
697     Statements *flatten(Scope *sc);
698     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
699 
isLabelStatement()700     LabelStatement *isLabelStatement() { return this; }
701 
accept(Visitor * v)702     void accept(Visitor *v) { v->visit(this); }
703 };
704 
705 class LabelDsymbol : public Dsymbol
706 {
707 public:
708     LabelStatement *statement;
709 
710     LabelDsymbol(Identifier *ident);
711     static LabelDsymbol *create(Identifier *ident);
712     LabelDsymbol *isLabel();
accept(Visitor * v)713     void accept(Visitor *v) { v->visit(this); }
714 };
715 
716 Statement* asmSemantic(AsmStatement *s, Scope *sc);
717 
718 class AsmStatement : public Statement
719 {
720 public:
721     Token *tokens;
722 
723     AsmStatement(Loc loc, Token *tokens);
724     Statement *syntaxCopy();
accept(Visitor * v)725     void accept(Visitor *v) { v->visit(this); }
726 };
727 
728 class InlineAsmStatement : public AsmStatement
729 {
730 public:
731     code *asmcode;
732     unsigned asmalign;          // alignment of this statement
733     unsigned regs;              // mask of registers modified (must match regm_t in back end)
734     bool refparam;              // true if function parameter is referenced
735     bool naked;                 // true if function is to be naked
736 
737     InlineAsmStatement(Loc loc, Token *tokens);
738     Statement *syntaxCopy();
accept(Visitor * v)739     void accept(Visitor *v) { v->visit(this); }
740 };
741 
742 // A GCC asm statement - assembler instructions with D expression operands
743 class GccAsmStatement : public AsmStatement
744 {
745 public:
746     StorageClass stc;           // attributes of the asm {} block
747     Expression *insn;           // string expression that is the template for assembler code
748     Expressions *args;          // input and output operands of the statement
749     unsigned outputargs;        // of the operands in 'args', the number of output operands
750     Identifiers *names;         // list of symbolic names for the operands
751     Expressions *constraints;   // list of string constants specifying constraints on operands
752     Expressions *clobbers;      // list of string constants specifying clobbers and scratch registers
753     Identifiers *labels;        // list of goto labels
754     GotoStatements *gotos;      // of the goto labels, the equivalent statements they represent
755 
756     GccAsmStatement(Loc loc, Token *tokens);
757     Statement *syntaxCopy();
accept(Visitor * v)758     void accept(Visitor *v) { v->visit(this); }
759 };
760 
761 // a complete asm {} block
762 class CompoundAsmStatement : public CompoundStatement
763 {
764 public:
765     StorageClass stc; // postfix attributes like nothrow/pure/@trusted
766 
767     CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc);
768     CompoundAsmStatement *syntaxCopy();
769     Statements *flatten(Scope *sc);
770 
accept(Visitor * v)771     void accept(Visitor *v) { v->visit(this); }
772 };
773 
774 class ImportStatement : public Statement
775 {
776 public:
777     Dsymbols *imports;          // Array of Import's
778 
779     ImportStatement(Loc loc, Dsymbols *imports);
780     Statement *syntaxCopy();
781 
accept(Visitor * v)782     void accept(Visitor *v) { v->visit(this); }
783 };
784