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 public:
236     ForwardingScopeDsymbol *sym;
237     Statement *statement;
238 
239     ForwardingStatement(Loc loc, ForwardingScopeDsymbol *sym, Statement *s);
240     ForwardingStatement(Loc loc, Statement *s);
241     Statement *syntaxCopy();
242     Statements *flatten(Scope *sc);
isForwardingStatement()243     ForwardingStatement *isForwardingStatement() { return this; }
accept(Visitor * v)244     void accept(Visitor *v) { v->visit(this); }
245 };
246 
247 class WhileStatement : public Statement
248 {
249 public:
250     Expression *condition;
251     Statement *_body;
252     Loc endloc;                 // location of closing curly bracket
253 
254     WhileStatement(Loc loc, Expression *c, Statement *b, Loc endloc);
255     Statement *syntaxCopy();
256     bool hasBreak();
257     bool hasContinue();
258 
accept(Visitor * v)259     void accept(Visitor *v) { v->visit(this); }
260 };
261 
262 class DoStatement : public Statement
263 {
264 public:
265     Statement *_body;
266     Expression *condition;
267     Loc endloc;                 // location of ';' after while
268 
269     DoStatement(Loc loc, Statement *b, Expression *c, Loc endloc);
270     Statement *syntaxCopy();
271     bool hasBreak();
272     bool hasContinue();
273 
accept(Visitor * v)274     void accept(Visitor *v) { v->visit(this); }
275 };
276 
277 class ForStatement : public Statement
278 {
279 public:
280     Statement *_init;
281     Expression *condition;
282     Expression *increment;
283     Statement *_body;
284     Loc endloc;                 // location of closing curly bracket
285 
286     // When wrapped in try/finally clauses, this points to the outermost one,
287     // which may have an associated label. Internal break/continue statements
288     // treat that label as referring to this loop.
289     Statement *relatedLabeled;
290 
291     ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body, Loc endloc);
292     Statement *syntaxCopy();
293     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
getRelatedLabeled()294     Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; }
295     bool hasBreak();
296     bool hasContinue();
297 
accept(Visitor * v)298     void accept(Visitor *v) { v->visit(this); }
299 };
300 
301 class ForeachStatement : public Statement
302 {
303 public:
304     TOK op;                     // TOKforeach or TOKforeach_reverse
305     Parameters *parameters;     // array of Parameter*'s
306     Expression *aggr;
307     Statement *_body;
308     Loc endloc;                 // location of closing curly bracket
309 
310     VarDeclaration *key;
311     VarDeclaration *value;
312 
313     FuncDeclaration *func;      // function we're lexically in
314 
315     Statements *cases;          // put breaks, continues, gotos and returns here
316     ScopeStatements *gotos;     // forward referenced goto's go here
317 
318     ForeachStatement(Loc loc, TOK op, Parameters *parameters, Expression *aggr, Statement *body, Loc endloc);
319     Statement *syntaxCopy();
320     bool checkForArgTypes();
321     bool hasBreak();
322     bool hasContinue();
323 
accept(Visitor * v)324     void accept(Visitor *v) { v->visit(this); }
325 };
326 
327 class ForeachRangeStatement : public Statement
328 {
329 public:
330     TOK op;                     // TOKforeach or TOKforeach_reverse
331     Parameter *prm;             // loop index variable
332     Expression *lwr;
333     Expression *upr;
334     Statement *_body;
335     Loc endloc;                 // location of closing curly bracket
336 
337     VarDeclaration *key;
338 
339     ForeachRangeStatement(Loc loc, TOK op, Parameter *prm,
340         Expression *lwr, Expression *upr, Statement *body, Loc endloc);
341     Statement *syntaxCopy();
342     bool hasBreak();
343     bool hasContinue();
344 
accept(Visitor * v)345     void accept(Visitor *v) { v->visit(this); }
346 };
347 
348 class IfStatement : public Statement
349 {
350 public:
351     Parameter *prm;
352     Expression *condition;
353     Statement *ifbody;
354     Statement *elsebody;
355     Loc endloc;                 // location of closing curly bracket
356 
357     VarDeclaration *match;      // for MatchExpression results
358 
359     IfStatement(Loc loc, Parameter *prm, Expression *condition, Statement *ifbody, Statement *elsebody, Loc endloc);
360     Statement *syntaxCopy();
isIfStatement()361     IfStatement *isIfStatement() { return this; }
362 
accept(Visitor * v)363     void accept(Visitor *v) { v->visit(this); }
364 };
365 
366 class ConditionalStatement : public Statement
367 {
368 public:
369     Condition *condition;
370     Statement *ifbody;
371     Statement *elsebody;
372 
373     ConditionalStatement(Loc loc, Condition *condition, Statement *ifbody, Statement *elsebody);
374     Statement *syntaxCopy();
375     Statements *flatten(Scope *sc);
376 
accept(Visitor * v)377     void accept(Visitor *v) { v->visit(this); }
378 };
379 
380 class StaticForeachStatement : public Statement
381 {
382 public:
383     StaticForeach *sfe;
384 
385     StaticForeachStatement(Loc loc, StaticForeach *sfe);
386     Statement *syntaxCopy();
387     Statements *flatten(Scope *sc);
388 
accept(Visitor * v)389     void accept(Visitor *v) { v->visit(this); }
390 };
391 
392 class PragmaStatement : public Statement
393 {
394 public:
395     Identifier *ident;
396     Expressions *args;          // array of Expression's
397     Statement *_body;
398 
399     PragmaStatement(Loc loc, Identifier *ident, Expressions *args, Statement *body);
400     Statement *syntaxCopy();
401 
accept(Visitor * v)402     void accept(Visitor *v) { v->visit(this); }
403 };
404 
405 class StaticAssertStatement : public Statement
406 {
407 public:
408     StaticAssert *sa;
409 
410     StaticAssertStatement(StaticAssert *sa);
411     Statement *syntaxCopy();
412 
accept(Visitor * v)413     void accept(Visitor *v) { v->visit(this); }
414 };
415 
416 class SwitchStatement : public Statement
417 {
418 public:
419     Expression *condition;
420     Statement *_body;
421     bool isFinal;
422 
423     DefaultStatement *sdefault;
424     TryFinallyStatement *tf;
425     GotoCaseStatements gotoCases;  // array of unresolved GotoCaseStatement's
426     CaseStatements *cases;         // array of CaseStatement's
427     int hasNoDefault;           // !=0 if no default statement
428     int hasVars;                // !=0 if has variable case values
429     VarDeclaration *lastVar;
430 
431     SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFinal);
432     Statement *syntaxCopy();
433     bool hasBreak();
434     bool checkLabel();
435 
accept(Visitor * v)436     void accept(Visitor *v) { v->visit(this); }
437 };
438 
439 class CaseStatement : public Statement
440 {
441 public:
442     Expression *exp;
443     Statement *statement;
444 
445     int index;          // which case it is (since we sort this)
446     VarDeclaration *lastVar;
447 
448     CaseStatement(Loc loc, Expression *exp, Statement *s);
449     Statement *syntaxCopy();
450     int compare(RootObject *obj);
isCaseStatement()451     CaseStatement *isCaseStatement() { return this; }
452 
accept(Visitor * v)453     void accept(Visitor *v) { v->visit(this); }
454 };
455 
456 
457 class CaseRangeStatement : public Statement
458 {
459 public:
460     Expression *first;
461     Expression *last;
462     Statement *statement;
463 
464     CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s);
465     Statement *syntaxCopy();
accept(Visitor * v)466     void accept(Visitor *v) { v->visit(this); }
467 };
468 
469 
470 class DefaultStatement : public Statement
471 {
472 public:
473     Statement *statement;
474     VarDeclaration *lastVar;
475 
476     DefaultStatement(Loc loc, Statement *s);
477     Statement *syntaxCopy();
isDefaultStatement()478     DefaultStatement *isDefaultStatement() { return this; }
479 
accept(Visitor * v)480     void accept(Visitor *v) { v->visit(this); }
481 };
482 
483 class GotoDefaultStatement : public Statement
484 {
485 public:
486     SwitchStatement *sw;
487 
488     GotoDefaultStatement(Loc loc);
489     Statement *syntaxCopy();
isGotoDefaultStatement()490     GotoDefaultStatement *isGotoDefaultStatement() { return this; }
491 
accept(Visitor * v)492     void accept(Visitor *v) { v->visit(this); }
493 };
494 
495 class GotoCaseStatement : public Statement
496 {
497 public:
498     Expression *exp;            // NULL, or which case to goto
499     CaseStatement *cs;          // case statement it resolves to
500 
501     GotoCaseStatement(Loc loc, Expression *exp);
502     Statement *syntaxCopy();
isGotoCaseStatement()503     GotoCaseStatement *isGotoCaseStatement() { return this; }
504 
accept(Visitor * v)505     void accept(Visitor *v) { v->visit(this); }
506 };
507 
508 class SwitchErrorStatement : public Statement
509 {
510 public:
511     SwitchErrorStatement(Loc loc);
512 
accept(Visitor * v)513     void accept(Visitor *v) { v->visit(this); }
514 };
515 
516 class ReturnStatement : public Statement
517 {
518 public:
519     Expression *exp;
520     size_t caseDim;
521 
522     ReturnStatement(Loc loc, Expression *exp);
523     Statement *syntaxCopy();
524 
isReturnStatement()525     ReturnStatement *isReturnStatement() { return this; }
accept(Visitor * v)526     void accept(Visitor *v) { v->visit(this); }
527 };
528 
529 class BreakStatement : public Statement
530 {
531 public:
532     Identifier *ident;
533 
534     BreakStatement(Loc loc, Identifier *ident);
535     Statement *syntaxCopy();
536 
isBreakStatement()537     BreakStatement *isBreakStatement() { return this; }
accept(Visitor * v)538     void accept(Visitor *v) { v->visit(this); }
539 };
540 
541 class ContinueStatement : public Statement
542 {
543 public:
544     Identifier *ident;
545 
546     ContinueStatement(Loc loc, Identifier *ident);
547     Statement *syntaxCopy();
548 
accept(Visitor * v)549     void accept(Visitor *v) { v->visit(this); }
550 };
551 
552 class SynchronizedStatement : public Statement
553 {
554 public:
555     Expression *exp;
556     Statement *_body;
557 
558     SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
559     Statement *syntaxCopy();
560     bool hasBreak();
561     bool hasContinue();
562 
accept(Visitor * v)563     void accept(Visitor *v) { v->visit(this); }
564 };
565 
566 class WithStatement : public Statement
567 {
568 public:
569     Expression *exp;
570     Statement *_body;
571     VarDeclaration *wthis;
572     Loc endloc;
573 
574     WithStatement(Loc loc, Expression *exp, Statement *body, Loc endloc);
575     Statement *syntaxCopy();
576 
accept(Visitor * v)577     void accept(Visitor *v) { v->visit(this); }
578 };
579 
580 class TryCatchStatement : public Statement
581 {
582 public:
583     Statement *_body;
584     Catches *catches;
585 
586     TryCatchStatement(Loc loc, Statement *body, Catches *catches);
587     Statement *syntaxCopy();
588     bool hasBreak();
589 
accept(Visitor * v)590     void accept(Visitor *v) { v->visit(this); }
591 };
592 
593 class Catch : public RootObject
594 {
595 public:
596     Loc loc;
597     Type *type;
598     Identifier *ident;
599     VarDeclaration *var;
600     Statement *handler;
601 
602     // set if semantic processing errors
603     bool errors;
604 
605     // was generated by the compiler,
606     // wasn't present in source code
607     bool internalCatch;
608 
609     Catch(Loc loc, Type *t, Identifier *id, Statement *handler);
610     Catch *syntaxCopy();
611 };
612 
613 class TryFinallyStatement : public Statement
614 {
615 public:
616     Statement *_body;
617     Statement *finalbody;
618 
619     TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
620     static TryFinallyStatement *create(Loc loc, Statement *body, Statement *finalbody);
621     Statement *syntaxCopy();
622     bool hasBreak();
623     bool hasContinue();
624 
accept(Visitor * v)625     void accept(Visitor *v) { v->visit(this); }
626 };
627 
628 class OnScopeStatement : public Statement
629 {
630 public:
631     TOK tok;
632     Statement *statement;
633 
634     OnScopeStatement(Loc loc, TOK tok, Statement *statement);
635     Statement *syntaxCopy();
636     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
637 
accept(Visitor * v)638     void accept(Visitor *v) { v->visit(this); }
639 };
640 
641 class ThrowStatement : public Statement
642 {
643 public:
644     Expression *exp;
645     // was generated by the compiler,
646     // wasn't present in source code
647     bool internalThrow;
648 
649     ThrowStatement(Loc loc, Expression *exp);
650     Statement *syntaxCopy();
651 
accept(Visitor * v)652     void accept(Visitor *v) { v->visit(this); }
653 };
654 
655 class DebugStatement : public Statement
656 {
657 public:
658     Statement *statement;
659 
660     DebugStatement(Loc loc, Statement *statement);
661     Statement *syntaxCopy();
662     Statements *flatten(Scope *sc);
accept(Visitor * v)663     void accept(Visitor *v) { v->visit(this); }
664 };
665 
666 class GotoStatement : public Statement
667 {
668 public:
669     Identifier *ident;
670     LabelDsymbol *label;
671     TryFinallyStatement *tf;
672     OnScopeStatement *os;
673     VarDeclaration *lastVar;
674 
675     GotoStatement(Loc loc, Identifier *ident);
676     Statement *syntaxCopy();
677     bool checkLabel();
678 
accept(Visitor * v)679     void accept(Visitor *v) { v->visit(this); }
680 };
681 
682 class LabelStatement : public Statement
683 {
684 public:
685     Identifier *ident;
686     Statement *statement;
687     TryFinallyStatement *tf;
688     OnScopeStatement *os;
689     VarDeclaration *lastVar;
690     Statement *gotoTarget;      // interpret
691 
692     bool breaks;                // someone did a 'break ident'
693 
694     LabelStatement(Loc loc, Identifier *ident, Statement *statement);
695     Statement *syntaxCopy();
696     Statements *flatten(Scope *sc);
697     Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally);
698 
isLabelStatement()699     LabelStatement *isLabelStatement() { return this; }
700 
accept(Visitor * v)701     void accept(Visitor *v) { v->visit(this); }
702 };
703 
704 class LabelDsymbol : public Dsymbol
705 {
706 public:
707     LabelStatement *statement;
708 
709     LabelDsymbol(Identifier *ident);
710     static LabelDsymbol *create(Identifier *ident);
711     LabelDsymbol *isLabel();
accept(Visitor * v)712     void accept(Visitor *v) { v->visit(this); }
713 };
714 
715 Statement* asmSemantic(AsmStatement *s, Scope *sc);
716 
717 class AsmStatement : public Statement
718 {
719 public:
720     Token *tokens;
721 
722     AsmStatement(Loc loc, Token *tokens);
723     Statement *syntaxCopy();
accept(Visitor * v)724     void accept(Visitor *v) { v->visit(this); }
725 };
726 
727 class InlineAsmStatement : public AsmStatement
728 {
729 public:
730     code *asmcode;
731     unsigned asmalign;          // alignment of this statement
732     unsigned regs;              // mask of registers modified (must match regm_t in back end)
733     bool refparam;              // true if function parameter is referenced
734     bool naked;                 // true if function is to be naked
735 
736     InlineAsmStatement(Loc loc, Token *tokens);
737     Statement *syntaxCopy();
accept(Visitor * v)738     void accept(Visitor *v) { v->visit(this); }
739 };
740 
741 // A GCC asm statement - assembler instructions with D expression operands
742 class GccAsmStatement : public AsmStatement
743 {
744 public:
745     StorageClass stc;           // attributes of the asm {} block
746     Expression *insn;           // string expression that is the template for assembler code
747     Expressions *args;          // input and output operands of the statement
748     unsigned outputargs;        // of the operands in 'args', the number of output operands
749     Identifiers *names;         // list of symbolic names for the operands
750     Expressions *constraints;   // list of string constants specifying constraints on operands
751     Expressions *clobbers;      // list of string constants specifying clobbers and scratch registers
752     Identifiers *labels;        // list of goto labels
753     GotoStatements *gotos;      // of the goto labels, the equivalent statements they represent
754 
755     GccAsmStatement(Loc loc, Token *tokens);
756     Statement *syntaxCopy();
accept(Visitor * v)757     void accept(Visitor *v) { v->visit(this); }
758 };
759 
760 // a complete asm {} block
761 class CompoundAsmStatement : public CompoundStatement
762 {
763 public:
764     StorageClass stc; // postfix attributes like nothrow/pure/@trusted
765 
766     CompoundAsmStatement(Loc loc, Statements *s, StorageClass stc);
767     CompoundAsmStatement *syntaxCopy();
768     Statements *flatten(Scope *sc);
769 
accept(Visitor * v)770     void accept(Visitor *v) { v->visit(this); }
771 };
772 
773 class ImportStatement : public Statement
774 {
775 public:
776     Dsymbols *imports;          // Array of Import's
777 
778     ImportStatement(Loc loc, Dsymbols *imports);
779     Statement *syntaxCopy();
780 
accept(Visitor * v)781     void accept(Visitor *v) { v->visit(this); }
782 };
783