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