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
20struct OutBuffer;
21struct Scope;
22class Expression;
23class LabelDsymbol;
24class Identifier;
25class IfStatement;
26class ExpStatement;
27class DefaultStatement;
28class VarDeclaration;
29class Condition;
30class Module;
31struct Token;
32class ErrorStatement;
33class ReturnStatement;
34class CompoundStatement;
35class Parameter;
36class StaticAssert;
37class AsmStatement;
38class GotoStatement;
39class ScopeStatement;
40class TryCatchStatement;
41class TryFinallyStatement;
42class CaseStatement;
43class DefaultStatement;
44class LabelStatement;
45class StaticForeach;
46
47// Back end
48struct code;
49
50bool inferAggregate(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply);
51bool inferApplyArgTypes(ForeachStatement *fes, Scope *sc, Dsymbol *&sapply);
52
53/* How a statement exits; this is returned by blockExit()
54 */
55enum 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
69class Statement : public RootObject
70{
71public:
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, ...);
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
94    virtual ErrorStatement *isErrorStatement() { return NULL; }
95    virtual ScopeStatement *isScopeStatement() { return NULL; }
96    virtual ExpStatement *isExpStatement() { return NULL; }
97    virtual CompoundStatement *isCompoundStatement() { return NULL; }
98    virtual ReturnStatement *isReturnStatement() { return NULL; }
99    virtual IfStatement *isIfStatement() { return NULL; }
100    virtual CaseStatement *isCaseStatement() { return NULL; }
101    virtual DefaultStatement *isDefaultStatement() { return NULL; }
102    virtual LabelStatement *isLabelStatement() { return NULL; }
103    virtual GotoDefaultStatement *isGotoDefaultStatement() { return NULL; }
104    virtual GotoCaseStatement *isGotoCaseStatement() { return NULL; }
105    virtual BreakStatement *isBreakStatement() { return NULL; }
106    virtual DtorExpStatement *isDtorExpStatement() { return NULL; }
107    virtual ForwardingStatement *isForwardingStatement() { return NULL; }
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 */
114class ErrorStatement : public Statement
115{
116public:
117    ErrorStatement();
118    Statement *syntaxCopy();
119
120    ErrorStatement *isErrorStatement() { return this; }
121    void accept(Visitor *v) { v->visit(this); }
122};
123
124class PeelStatement : public Statement
125{
126public:
127    Statement *s;
128
129    PeelStatement(Statement *s);
130    void accept(Visitor *v) { v->visit(this); }
131};
132
133class ExpStatement : public Statement
134{
135public:
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
145    ExpStatement *isExpStatement() { return this; }
146    void accept(Visitor *v) { v->visit(this); }
147};
148
149class DtorExpStatement : public ExpStatement
150{
151public:
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();
159    void accept(Visitor *v) { v->visit(this); }
160
161    DtorExpStatement *isDtorExpStatement() { return this; }
162};
163
164class CompileStatement : public Statement
165{
166public:
167    Expression *exp;
168
169    CompileStatement(Loc loc, Expression *exp);
170    Statement *syntaxCopy();
171    Statements *flatten(Scope *sc);
172    void accept(Visitor *v) { v->visit(this); }
173};
174
175class CompoundStatement : public Statement
176{
177public:
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
189    CompoundStatement *isCompoundStatement() { return this; }
190    void accept(Visitor *v) { v->visit(this); }
191};
192
193class CompoundDeclarationStatement : public CompoundStatement
194{
195public:
196    CompoundDeclarationStatement(Loc loc, Statements *s);
197    Statement *syntaxCopy();
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 */
204class UnrolledLoopStatement : public Statement
205{
206public:
207    Statements *statements;
208
209    UnrolledLoopStatement(Loc loc, Statements *statements);
210    Statement *syntaxCopy();
211    bool hasBreak();
212    bool hasContinue();
213
214    void accept(Visitor *v) { v->visit(this); }
215};
216
217class ScopeStatement : public Statement
218{
219public:
220    Statement *statement;
221    Loc endloc;                 // location of closing curly bracket
222
223    ScopeStatement(Loc loc, Statement *s, Loc endloc);
224    Statement *syntaxCopy();
225    ScopeStatement *isScopeStatement() { return this; }
226    ReturnStatement *isReturnStatement();
227    bool hasBreak();
228    bool hasContinue();
229
230    void accept(Visitor *v) { v->visit(this); }
231};
232
233class ForwardingStatement : public Statement
234{
235public:
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);
243    ForwardingStatement *isForwardingStatement() { return this; }
244    void accept(Visitor *v) { v->visit(this); }
245};
246
247class WhileStatement : public Statement
248{
249public:
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
259    void accept(Visitor *v) { v->visit(this); }
260};
261
262class DoStatement : public Statement
263{
264public:
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
274    void accept(Visitor *v) { v->visit(this); }
275};
276
277class ForStatement : public Statement
278{
279public:
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);
294    Statement *getRelatedLabeled() { return relatedLabeled ? relatedLabeled : this; }
295    bool hasBreak();
296    bool hasContinue();
297
298    void accept(Visitor *v) { v->visit(this); }
299};
300
301class ForeachStatement : public Statement
302{
303public:
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
324    void accept(Visitor *v) { v->visit(this); }
325};
326
327class ForeachRangeStatement : public Statement
328{
329public:
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
345    void accept(Visitor *v) { v->visit(this); }
346};
347
348class IfStatement : public Statement
349{
350public:
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();
361    IfStatement *isIfStatement() { return this; }
362
363    void accept(Visitor *v) { v->visit(this); }
364};
365
366class ConditionalStatement : public Statement
367{
368public:
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
377    void accept(Visitor *v) { v->visit(this); }
378};
379
380class StaticForeachStatement : public Statement
381{
382public:
383    StaticForeach *sfe;
384
385    StaticForeachStatement(Loc loc, StaticForeach *sfe);
386    Statement *syntaxCopy();
387    Statements *flatten(Scope *sc);
388
389    void accept(Visitor *v) { v->visit(this); }
390};
391
392class PragmaStatement : public Statement
393{
394public:
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
402    void accept(Visitor *v) { v->visit(this); }
403};
404
405class StaticAssertStatement : public Statement
406{
407public:
408    StaticAssert *sa;
409
410    StaticAssertStatement(StaticAssert *sa);
411    Statement *syntaxCopy();
412
413    void accept(Visitor *v) { v->visit(this); }
414};
415
416class SwitchStatement : public Statement
417{
418public:
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
436    void accept(Visitor *v) { v->visit(this); }
437};
438
439class CaseStatement : public Statement
440{
441public:
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);
451    CaseStatement *isCaseStatement() { return this; }
452
453    void accept(Visitor *v) { v->visit(this); }
454};
455
456
457class CaseRangeStatement : public Statement
458{
459public:
460    Expression *first;
461    Expression *last;
462    Statement *statement;
463
464    CaseRangeStatement(Loc loc, Expression *first, Expression *last, Statement *s);
465    Statement *syntaxCopy();
466    void accept(Visitor *v) { v->visit(this); }
467};
468
469
470class DefaultStatement : public Statement
471{
472public:
473    Statement *statement;
474    VarDeclaration *lastVar;
475
476    DefaultStatement(Loc loc, Statement *s);
477    Statement *syntaxCopy();
478    DefaultStatement *isDefaultStatement() { return this; }
479
480    void accept(Visitor *v) { v->visit(this); }
481};
482
483class GotoDefaultStatement : public Statement
484{
485public:
486    SwitchStatement *sw;
487
488    GotoDefaultStatement(Loc loc);
489    Statement *syntaxCopy();
490    GotoDefaultStatement *isGotoDefaultStatement() { return this; }
491
492    void accept(Visitor *v) { v->visit(this); }
493};
494
495class GotoCaseStatement : public Statement
496{
497public:
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();
503    GotoCaseStatement *isGotoCaseStatement() { return this; }
504
505    void accept(Visitor *v) { v->visit(this); }
506};
507
508class SwitchErrorStatement : public Statement
509{
510public:
511    SwitchErrorStatement(Loc loc);
512
513    void accept(Visitor *v) { v->visit(this); }
514};
515
516class ReturnStatement : public Statement
517{
518public:
519    Expression *exp;
520    size_t caseDim;
521
522    ReturnStatement(Loc loc, Expression *exp);
523    Statement *syntaxCopy();
524
525    ReturnStatement *isReturnStatement() { return this; }
526    void accept(Visitor *v) { v->visit(this); }
527};
528
529class BreakStatement : public Statement
530{
531public:
532    Identifier *ident;
533
534    BreakStatement(Loc loc, Identifier *ident);
535    Statement *syntaxCopy();
536
537    BreakStatement *isBreakStatement() { return this; }
538    void accept(Visitor *v) { v->visit(this); }
539};
540
541class ContinueStatement : public Statement
542{
543public:
544    Identifier *ident;
545
546    ContinueStatement(Loc loc, Identifier *ident);
547    Statement *syntaxCopy();
548
549    void accept(Visitor *v) { v->visit(this); }
550};
551
552class SynchronizedStatement : public Statement
553{
554public:
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
563    void accept(Visitor *v) { v->visit(this); }
564};
565
566class WithStatement : public Statement
567{
568public:
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
577    void accept(Visitor *v) { v->visit(this); }
578};
579
580class TryCatchStatement : public Statement
581{
582public:
583    Statement *_body;
584    Catches *catches;
585
586    TryCatchStatement(Loc loc, Statement *body, Catches *catches);
587    Statement *syntaxCopy();
588    bool hasBreak();
589
590    void accept(Visitor *v) { v->visit(this); }
591};
592
593class Catch : public RootObject
594{
595public:
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
613class TryFinallyStatement : public Statement
614{
615public:
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
625    void accept(Visitor *v) { v->visit(this); }
626};
627
628class OnScopeStatement : public Statement
629{
630public:
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
638    void accept(Visitor *v) { v->visit(this); }
639};
640
641class ThrowStatement : public Statement
642{
643public:
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
652    void accept(Visitor *v) { v->visit(this); }
653};
654
655class DebugStatement : public Statement
656{
657public:
658    Statement *statement;
659
660    DebugStatement(Loc loc, Statement *statement);
661    Statement *syntaxCopy();
662    Statements *flatten(Scope *sc);
663    void accept(Visitor *v) { v->visit(this); }
664};
665
666class GotoStatement : public Statement
667{
668public:
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
679    void accept(Visitor *v) { v->visit(this); }
680};
681
682class LabelStatement : public Statement
683{
684public:
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
699    LabelStatement *isLabelStatement() { return this; }
700
701    void accept(Visitor *v) { v->visit(this); }
702};
703
704class LabelDsymbol : public Dsymbol
705{
706public:
707    LabelStatement *statement;
708
709    LabelDsymbol(Identifier *ident);
710    static LabelDsymbol *create(Identifier *ident);
711    LabelDsymbol *isLabel();
712    void accept(Visitor *v) { v->visit(this); }
713};
714
715Statement* asmSemantic(AsmStatement *s, Scope *sc);
716
717class AsmStatement : public Statement
718{
719public:
720    Token *tokens;
721
722    AsmStatement(Loc loc, Token *tokens);
723    Statement *syntaxCopy();
724    void accept(Visitor *v) { v->visit(this); }
725};
726
727class InlineAsmStatement : public AsmStatement
728{
729public:
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();
738    void accept(Visitor *v) { v->visit(this); }
739};
740
741// A GCC asm statement - assembler instructions with D expression operands
742class GccAsmStatement : public AsmStatement
743{
744public:
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();
757    void accept(Visitor *v) { v->visit(this); }
758};
759
760// a complete asm {} block
761class CompoundAsmStatement : public CompoundStatement
762{
763public:
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
770    void accept(Visitor *v) { v->visit(this); }
771};
772
773class ImportStatement : public Statement
774{
775public:
776    Dsymbols *imports;          // Array of Import's
777
778    ImportStatement(Loc loc, Dsymbols *imports);
779    Statement *syntaxCopy();
780
781    void accept(Visitor *v) { v->visit(this); }
782};
783