| |
| /* Compiler implementation of the D programming language |
| * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved |
| * written by Walter Bright |
| * https://www.digitalmars.com |
| * Distributed under the Boost Software License, Version 1.0. |
| * https://www.boost.org/LICENSE_1_0.txt |
| * https://github.com/dlang/dmd/blob/master/src/dmd/statement.h |
| */ |
| |
| #pragma once |
| |
| #include "arraytypes.h" |
| #include "ast_node.h" |
| #include "dsymbol.h" |
| #include "visitor.h" |
| #include "tokens.h" |
| |
| struct Scope; |
| class Expression; |
| class LabelDsymbol; |
| class Identifier; |
| class IfStatement; |
| class ExpStatement; |
| class DefaultStatement; |
| class VarDeclaration; |
| class Condition; |
| class ErrorStatement; |
| class ReturnStatement; |
| class CompoundStatement; |
| class Parameter; |
| class StaticAssert; |
| class AsmStatement; |
| class GotoStatement; |
| class ScopeStatement; |
| class TryCatchStatement; |
| class TryFinallyStatement; |
| class CaseStatement; |
| class DefaultStatement; |
| class LabelStatement; |
| class StaticForeach; |
| |
| // Back end |
| struct code; |
| |
| /* How a statement exits; this is returned by blockExit() |
| */ |
| enum BE : int32_t |
| { |
| BEnone = 0, |
| BEfallthru = 1, |
| BEthrow = 2, |
| BEreturn = 4, |
| BEgoto = 8, |
| BEhalt = 0x10, |
| BEbreak = 0x20, |
| BEcontinue = 0x40, |
| BEerrthrow = 0x80, |
| BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt) |
| }; |
| |
| typedef unsigned char STMT; |
| enum |
| { |
| STMTerror, |
| STMTpeel, |
| STMTexp, STMTdtorExp, |
| STMTcompile, |
| STMTcompound, STMTcompoundDeclaration, STMTcompoundAsm, |
| STMTunrolledLoop, |
| STMTscope, |
| STMTforwarding, |
| STMTwhile, |
| STMTdo, |
| STMTfor, |
| STMTforeach, |
| STMTforeachRange, |
| STMTif, |
| STMTconditional, |
| STMTstaticForeach, |
| STMTpragma, |
| STMTstaticAssert, |
| STMTswitch, |
| STMTcase, |
| STMTcaseRange, |
| STMTdefault, |
| STMTgotoDefault, |
| STMTgotoCase, |
| STMTswitchError, |
| STMTreturn, |
| STMTbreak, |
| STMTcontinue, |
| STMTsynchronized, |
| STMTwith, |
| STMTtryCatch, |
| STMTtryFinally, |
| STMTscopeGuard, |
| STMTthrow, |
| STMTdebug, |
| STMTgoto, |
| STMTlabel, |
| STMTasm, STMTinlineAsm, STMTgccAsm, |
| STMTimport |
| }; |
| |
| class Statement : public ASTNode |
| { |
| public: |
| Loc loc; |
| STMT stmt; |
| |
| DYNCAST dyncast() const override final { return DYNCAST_STATEMENT; } |
| |
| virtual Statement *syntaxCopy(); |
| |
| const char *toChars() const override final; |
| |
| void error(const char *format, ...); |
| void warning(const char *format, ...); |
| void deprecation(const char *format, ...); |
| virtual Statement *getRelatedLabeled() { return this; } |
| virtual bool hasBreak() const; |
| virtual bool hasContinue() const; |
| bool usesEH(); |
| bool comeFrom(); |
| bool hasCode(); |
| virtual Statement *last(); |
| |
| virtual ReturnStatement *endsWithReturnStatement() { return NULL; } |
| |
| ErrorStatement *isErrorStatement() { return stmt == STMTerror ? (ErrorStatement*)this : NULL; } |
| ScopeStatement *isScopeStatement() { return stmt == STMTscope ? (ScopeStatement*)this : NULL; } |
| ExpStatement *isExpStatement() { return stmt == STMTexp ? (ExpStatement*)this : NULL; } |
| CompoundStatement *isCompoundStatement() { return stmt == STMTcompound ? (CompoundStatement*)this : NULL; } |
| ReturnStatement *isReturnStatement() { return stmt == STMTreturn ? (ReturnStatement*)this : NULL; } |
| IfStatement *isIfStatement() { return stmt == STMTif ? (IfStatement*)this : NULL; } |
| ConditionalStatement *isConditionalStatement() { return stmt == STMTconditional ? (ConditionalStatement*)this : NULL; } |
| StaticForeachStatement *isStaticForeachStatement() { return stmt == STMTstaticForeach ? (StaticForeachStatement*)this : NULL; } |
| CaseStatement *isCaseStatement() { return stmt == STMTcase ? (CaseStatement*)this : NULL; } |
| DefaultStatement *isDefaultStatement() { return stmt == STMTdefault ? (DefaultStatement*)this : NULL; } |
| LabelStatement *isLabelStatement() { return stmt == STMTlabel ? (LabelStatement*)this : NULL; } |
| GotoDefaultStatement *isGotoDefaultStatement() { return stmt == STMTgotoDefault ? (GotoDefaultStatement*)this : NULL; } |
| GotoCaseStatement *isGotoCaseStatement() { return stmt == STMTgotoCase ? (GotoCaseStatement*)this : NULL; } |
| BreakStatement *isBreakStatement() { return stmt == STMTbreak ? (BreakStatement*)this : NULL; } |
| DtorExpStatement *isDtorExpStatement() { return stmt == STMTdtorExp ? (DtorExpStatement*)this : NULL; } |
| CompileStatement *isCompileStatement() { return stmt == STMTcompile ? (CompileStatement*)this : NULL; } |
| ForwardingStatement *isForwardingStatement() { return stmt == STMTforwarding ? (ForwardingStatement*)this : NULL; } |
| DoStatement *isDoStatement() { return stmt == STMTdo ? (DoStatement*)this : NULL; } |
| ForStatement *isForStatement() { return stmt == STMTfor ? (ForStatement*)this : NULL; } |
| ForeachStatement *isForeachStatement() { return stmt == STMTforeach ? (ForeachStatement*)this : NULL; } |
| SwitchStatement *isSwitchStatement() { return stmt == STMTswitch ? (SwitchStatement*)this : NULL; } |
| ContinueStatement *isContinueStatement() { return stmt == STMTcontinue ? (ContinueStatement*)this : NULL; } |
| WithStatement *isWithStatement() { return stmt == STMTwith ? (WithStatement*)this : NULL; } |
| TryCatchStatement *isTryCatchStatement() { return stmt == STMTtryCatch ? (TryCatchStatement*)this : NULL; } |
| ThrowStatement *isThrowStatement() { return stmt == STMTthrow ? (ThrowStatement*)this : NULL; } |
| DebugStatement *isDebugStatement() { return stmt == STMTdebug ? (DebugStatement*)this : NULL; } |
| TryFinallyStatement *isTryFinallyStatement() { return stmt == STMTtryFinally ? (TryFinallyStatement*)this : NULL; } |
| ScopeGuardStatement *isScopeGuardStatement() { return stmt == STMTscopeGuard ? (ScopeGuardStatement*)this : NULL; } |
| SwitchErrorStatement *isSwitchErrorStatement() { return stmt == STMTswitchError ? (SwitchErrorStatement*)this : NULL; } |
| UnrolledLoopStatement *isUnrolledLoopStatement() { return stmt == STMTunrolledLoop ? (UnrolledLoopStatement*)this : NULL; } |
| ForeachRangeStatement *isForeachRangeStatement() { return stmt == STMTforeachRange ? (ForeachRangeStatement*)this : NULL; } |
| CompoundDeclarationStatement *isCompoundDeclarationStatement() { return stmt == STMTcompoundDeclaration ? (CompoundDeclarationStatement*)this : NULL; } |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /** Any Statement that fails semantic() or has a component that is an ErrorExp or |
| * a TypeError should return an ErrorStatement from semantic(). |
| */ |
| class ErrorStatement final : public Statement |
| { |
| public: |
| ErrorStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class PeelStatement final : public Statement |
| { |
| public: |
| Statement *s; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ExpStatement : public Statement |
| { |
| public: |
| Expression *exp; |
| |
| static ExpStatement *create(const Loc &loc, Expression *exp); |
| ExpStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class DtorExpStatement final : public ExpStatement |
| { |
| public: |
| /* Wraps an expression that is the destruction of 'var' |
| */ |
| |
| VarDeclaration *var; |
| |
| DtorExpStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class CompileStatement final : public Statement |
| { |
| public: |
| Expressions *exps; |
| |
| CompileStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class CompoundStatement : public Statement |
| { |
| public: |
| Statements *statements; |
| |
| static CompoundStatement *create(const Loc &loc, Statement *s1, Statement *s2); |
| CompoundStatement *syntaxCopy() override; |
| ReturnStatement *endsWithReturnStatement() override final; |
| Statement *last() override final; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class CompoundDeclarationStatement final : public CompoundStatement |
| { |
| public: |
| CompoundDeclarationStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* The purpose of this is so that continue will go to the next |
| * of the statements, and break will go to the end of the statements. |
| */ |
| class UnrolledLoopStatement final : public Statement |
| { |
| public: |
| Statements *statements; |
| |
| UnrolledLoopStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ScopeStatement final : public Statement |
| { |
| public: |
| Statement *statement; |
| Loc endloc; // location of closing curly bracket |
| |
| ScopeStatement *syntaxCopy() override; |
| ReturnStatement *endsWithReturnStatement() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ForwardingStatement final : public Statement |
| { |
| public: |
| ForwardingScopeDsymbol *sym; |
| Statement *statement; |
| |
| ForwardingStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class WhileStatement final : public Statement |
| { |
| public: |
| Parameter *param; |
| Expression *condition; |
| Statement *_body; |
| Loc endloc; // location of closing curly bracket |
| |
| WhileStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class DoStatement final : public Statement |
| { |
| public: |
| Statement *_body; |
| Expression *condition; |
| Loc endloc; // location of ';' after while |
| |
| DoStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ForStatement final : public Statement |
| { |
| public: |
| Statement *_init; |
| Expression *condition; |
| Expression *increment; |
| Statement *_body; |
| Loc endloc; // location of closing curly bracket |
| |
| // When wrapped in try/finally clauses, this points to the outermost one, |
| // which may have an associated label. Internal break/continue statements |
| // treat that label as referring to this loop. |
| Statement *relatedLabeled; |
| |
| ForStatement *syntaxCopy() override; |
| Statement *getRelatedLabeled() override { return relatedLabeled ? relatedLabeled : this; } |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ForeachStatement final : public Statement |
| { |
| public: |
| TOK op; // TOKforeach or TOKforeach_reverse |
| Parameters *parameters; // array of Parameter*'s |
| Expression *aggr; |
| Statement *_body; |
| Loc endloc; // location of closing curly bracket |
| |
| VarDeclaration *key; |
| VarDeclaration *value; |
| |
| FuncDeclaration *func; // function we're lexically in |
| |
| Statements *cases; // put breaks, continues, gotos and returns here |
| ScopeStatements *gotos; // forward referenced goto's go here |
| |
| ForeachStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ForeachRangeStatement final : public Statement |
| { |
| public: |
| TOK op; // TOKforeach or TOKforeach_reverse |
| Parameter *prm; // loop index variable |
| Expression *lwr; |
| Expression *upr; |
| Statement *_body; |
| Loc endloc; // location of closing curly bracket |
| |
| VarDeclaration *key; |
| |
| ForeachRangeStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class IfStatement final : public Statement |
| { |
| public: |
| Parameter *prm; |
| Expression *condition; |
| Statement *ifbody; |
| Statement *elsebody; |
| VarDeclaration *match; // for MatchExpression results |
| Loc endloc; // location of closing curly bracket |
| |
| IfStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| bool isIfCtfeBlock(); |
| }; |
| |
| class ConditionalStatement final : public Statement |
| { |
| public: |
| Condition *condition; |
| Statement *ifbody; |
| Statement *elsebody; |
| |
| ConditionalStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class StaticForeachStatement final : public Statement |
| { |
| public: |
| StaticForeach *sfe; |
| |
| StaticForeachStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class PragmaStatement final : public Statement |
| { |
| public: |
| Identifier *ident; |
| Expressions *args; // array of Expression's |
| Statement *_body; |
| |
| PragmaStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class StaticAssertStatement final : public Statement |
| { |
| public: |
| StaticAssert *sa; |
| |
| StaticAssertStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class SwitchStatement final : public Statement |
| { |
| public: |
| Expression *condition; |
| Statement *_body; |
| d_bool isFinal; |
| |
| DefaultStatement *sdefault; |
| Statement *tryBody; // set to TryCatchStatement or TryFinallyStatement if in _body portion |
| TryFinallyStatement *tf; |
| GotoCaseStatements gotoCases; // array of unresolved GotoCaseStatement's |
| CaseStatements *cases; // array of CaseStatement's |
| int hasNoDefault; // !=0 if no default statement |
| int hasVars; // !=0 if has variable case values |
| VarDeclaration *lastVar; |
| |
| SwitchStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class CaseStatement final : public Statement |
| { |
| public: |
| Expression *exp; |
| Statement *statement; |
| |
| int index; // which case it is (since we sort this) |
| VarDeclaration *lastVar; |
| void* extra; // for use by Statement_toIR() |
| |
| CaseStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| |
| class CaseRangeStatement final : public Statement |
| { |
| public: |
| Expression *first; |
| Expression *last; |
| Statement *statement; |
| |
| CaseRangeStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| |
| class DefaultStatement final : public Statement |
| { |
| public: |
| Statement *statement; |
| VarDeclaration *lastVar; |
| |
| DefaultStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class GotoDefaultStatement final : public Statement |
| { |
| public: |
| SwitchStatement *sw; |
| |
| GotoDefaultStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class GotoCaseStatement final : public Statement |
| { |
| public: |
| Expression *exp; // NULL, or which case to goto |
| CaseStatement *cs; // case statement it resolves to |
| |
| GotoCaseStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class SwitchErrorStatement final : public Statement |
| { |
| public: |
| Expression *exp; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ReturnStatement final : public Statement |
| { |
| public: |
| Expression *exp; |
| size_t caseDim; |
| |
| ReturnStatement *syntaxCopy() override; |
| |
| ReturnStatement *endsWithReturnStatement() override { return this; } |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class BreakStatement final : public Statement |
| { |
| public: |
| Identifier *ident; |
| |
| BreakStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ContinueStatement final : public Statement |
| { |
| public: |
| Identifier *ident; |
| |
| ContinueStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class SynchronizedStatement final : public Statement |
| { |
| public: |
| Expression *exp; |
| Statement *_body; |
| |
| SynchronizedStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class WithStatement final : public Statement |
| { |
| public: |
| Expression *exp; |
| Statement *_body; |
| VarDeclaration *wthis; |
| Loc endloc; |
| |
| WithStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class TryCatchStatement final : public Statement |
| { |
| public: |
| Statement *_body; |
| Catches *catches; |
| |
| Statement *tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion |
| |
| TryCatchStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class Catch final : public RootObject |
| { |
| public: |
| Loc loc; |
| Type *type; |
| Identifier *ident; |
| Statement *handler; |
| |
| VarDeclaration *var; |
| // set if semantic processing errors |
| d_bool errors; |
| |
| // was generated by the compiler, |
| // wasn't present in source code |
| d_bool internalCatch; |
| |
| Catch *syntaxCopy(); |
| }; |
| |
| class TryFinallyStatement final : public Statement |
| { |
| public: |
| Statement *_body; |
| Statement *finalbody; |
| |
| Statement *tryBody; // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion |
| d_bool bodyFallsThru; // true if _body falls through to finally |
| |
| static TryFinallyStatement *create(const Loc &loc, Statement *body, Statement *finalbody); |
| TryFinallyStatement *syntaxCopy() override; |
| bool hasBreak() const override; |
| bool hasContinue() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ScopeGuardStatement final : public Statement |
| { |
| public: |
| TOK tok; |
| Statement *statement; |
| |
| ScopeGuardStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ThrowStatement final : public Statement |
| { |
| public: |
| Expression *exp; |
| // was generated by the compiler, |
| // wasn't present in source code |
| d_bool internalThrow; |
| |
| ThrowStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class DebugStatement final : public Statement |
| { |
| public: |
| Statement *statement; |
| |
| DebugStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class GotoStatement final : public Statement |
| { |
| public: |
| Identifier *ident; |
| LabelDsymbol *label; |
| Statement *tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion |
| TryFinallyStatement *tf; |
| ScopeGuardStatement *os; |
| VarDeclaration *lastVar; |
| d_bool inCtfeBlock; |
| GotoStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class LabelStatement final : public Statement |
| { |
| public: |
| Identifier *ident; |
| Statement *statement; |
| Statement *tryBody; /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion |
| TryFinallyStatement *tf; |
| ScopeGuardStatement *os; |
| VarDeclaration *lastVar; |
| Statement *gotoTarget; // interpret |
| void* extra; // used by Statement_toIR() |
| d_bool breaks; // someone did a 'break ident' |
| d_bool inCtfeBlock; |
| LabelStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class LabelDsymbol final : public Dsymbol |
| { |
| public: |
| LabelStatement *statement; |
| |
| d_bool deleted; // set if rewritten to return in foreach delegate |
| d_bool iasm; // set if used by inline assembler |
| |
| static LabelDsymbol *create(Identifier *ident); |
| LabelDsymbol *isLabel() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| Statement* asmSemantic(AsmStatement *s, Scope *sc); |
| |
| class AsmStatement : public Statement |
| { |
| public: |
| Token *tokens; |
| |
| AsmStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class InlineAsmStatement final : public AsmStatement |
| { |
| public: |
| code *asmcode; |
| unsigned asmalign; // alignment of this statement |
| unsigned regs; // mask of registers modified (must match regm_t in back end) |
| d_bool refparam; // true if function parameter is referenced |
| d_bool naked; // true if function is to be naked |
| |
| InlineAsmStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| // A GCC asm statement - assembler instructions with D expression operands |
| class GccAsmStatement final : public AsmStatement |
| { |
| public: |
| StorageClass stc; // attributes of the asm {} block |
| Expression *insn; // string expression that is the template for assembler code |
| Expressions *args; // input and output operands of the statement |
| unsigned outputargs; // of the operands in 'args', the number of output operands |
| Identifiers *names; // list of symbolic names for the operands |
| Expressions *constraints; // list of string constants specifying constraints on operands |
| Expressions *clobbers; // list of string constants specifying clobbers and scratch registers |
| Identifiers *labels; // list of goto labels |
| GotoStatements *gotos; // of the goto labels, the equivalent statements they represent |
| |
| GccAsmStatement *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| // a complete asm {} block |
| class CompoundAsmStatement final : public CompoundStatement |
| { |
| public: |
| StorageClass stc; // postfix attributes like nothrow/pure/@trusted |
| |
| CompoundAsmStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class ImportStatement final : public Statement |
| { |
| public: |
| Dsymbols *imports; // Array of Import's |
| |
| ImportStatement *syntaxCopy() override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |