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