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      bool isIfCtfeBlock();
     385  };
     386  
     387  class ConditionalStatement final : public Statement
     388  {
     389  public:
     390      Condition *condition;
     391      Statement *ifbody;
     392      Statement *elsebody;
     393  
     394      ConditionalStatement *syntaxCopy() override;
     395  
     396      void accept(Visitor *v) override { v->visit(this); }
     397  };
     398  
     399  class StaticForeachStatement final : public Statement
     400  {
     401  public:
     402      StaticForeach *sfe;
     403  
     404      StaticForeachStatement *syntaxCopy() override;
     405  
     406      void accept(Visitor *v) override { v->visit(this); }
     407  };
     408  
     409  class PragmaStatement final : public Statement
     410  {
     411  public:
     412      Identifier *ident;
     413      Expressions *args;          // array of Expression's
     414      Statement *_body;
     415  
     416      PragmaStatement *syntaxCopy() override;
     417  
     418      void accept(Visitor *v) override { v->visit(this); }
     419  };
     420  
     421  class StaticAssertStatement final : public Statement
     422  {
     423  public:
     424      StaticAssert *sa;
     425  
     426      StaticAssertStatement *syntaxCopy() override;
     427  
     428      void accept(Visitor *v) override { v->visit(this); }
     429  };
     430  
     431  class SwitchStatement final : public Statement
     432  {
     433  public:
     434      Expression *condition;
     435      Statement *_body;
     436      d_bool isFinal;
     437  
     438      DefaultStatement *sdefault;
     439      Statement *tryBody;            // set to TryCatchStatement or TryFinallyStatement if in _body portion
     440      TryFinallyStatement *tf;
     441      GotoCaseStatements gotoCases;  // array of unresolved GotoCaseStatement's
     442      CaseStatements *cases;         // array of CaseStatement's
     443      int hasNoDefault;           // !=0 if no default statement
     444      int hasVars;                // !=0 if has variable case values
     445      VarDeclaration *lastVar;
     446  
     447      SwitchStatement *syntaxCopy() override;
     448      bool hasBreak() const override;
     449  
     450      void accept(Visitor *v) override { v->visit(this); }
     451  };
     452  
     453  class CaseStatement final : public Statement
     454  {
     455  public:
     456      Expression *exp;
     457      Statement *statement;
     458  
     459      int index;          // which case it is (since we sort this)
     460      VarDeclaration *lastVar;
     461      void* extra;            // for use by Statement_toIR()
     462  
     463      CaseStatement *syntaxCopy() override;
     464  
     465      void accept(Visitor *v) override { v->visit(this); }
     466  };
     467  
     468  
     469  class CaseRangeStatement final : public Statement
     470  {
     471  public:
     472      Expression *first;
     473      Expression *last;
     474      Statement *statement;
     475  
     476      CaseRangeStatement *syntaxCopy() override;
     477      void accept(Visitor *v) override { v->visit(this); }
     478  };
     479  
     480  
     481  class DefaultStatement final : public Statement
     482  {
     483  public:
     484      Statement *statement;
     485      VarDeclaration *lastVar;
     486  
     487      DefaultStatement *syntaxCopy() override;
     488  
     489      void accept(Visitor *v) override { v->visit(this); }
     490  };
     491  
     492  class GotoDefaultStatement final : public Statement
     493  {
     494  public:
     495      SwitchStatement *sw;
     496  
     497      GotoDefaultStatement *syntaxCopy() override;
     498  
     499      void accept(Visitor *v) override { v->visit(this); }
     500  };
     501  
     502  class GotoCaseStatement final : public Statement
     503  {
     504  public:
     505      Expression *exp;            // NULL, or which case to goto
     506      CaseStatement *cs;          // case statement it resolves to
     507  
     508      GotoCaseStatement *syntaxCopy() override;
     509  
     510      void accept(Visitor *v) override { v->visit(this); }
     511  };
     512  
     513  class SwitchErrorStatement final : public Statement
     514  {
     515  public:
     516      Expression *exp;
     517  
     518      void accept(Visitor *v) override { v->visit(this); }
     519  };
     520  
     521  class ReturnStatement final : public Statement
     522  {
     523  public:
     524      Expression *exp;
     525      size_t caseDim;
     526  
     527      ReturnStatement *syntaxCopy() override;
     528  
     529      ReturnStatement *endsWithReturnStatement() override { return this; }
     530      void accept(Visitor *v) override { v->visit(this); }
     531  };
     532  
     533  class BreakStatement final : public Statement
     534  {
     535  public:
     536      Identifier *ident;
     537  
     538      BreakStatement *syntaxCopy() override;
     539  
     540      void accept(Visitor *v) override { v->visit(this); }
     541  };
     542  
     543  class ContinueStatement final : public Statement
     544  {
     545  public:
     546      Identifier *ident;
     547  
     548      ContinueStatement *syntaxCopy() override;
     549  
     550      void accept(Visitor *v) override { v->visit(this); }
     551  };
     552  
     553  class SynchronizedStatement final : public Statement
     554  {
     555  public:
     556      Expression *exp;
     557      Statement *_body;
     558  
     559      SynchronizedStatement *syntaxCopy() override;
     560      bool hasBreak() const override;
     561      bool hasContinue() const override;
     562  
     563      void accept(Visitor *v) override { v->visit(this); }
     564  };
     565  
     566  class WithStatement final : public Statement
     567  {
     568  public:
     569      Expression *exp;
     570      Statement *_body;
     571      VarDeclaration *wthis;
     572      Loc endloc;
     573  
     574      WithStatement *syntaxCopy() override;
     575  
     576      void accept(Visitor *v) override { v->visit(this); }
     577  };
     578  
     579  class TryCatchStatement final : public Statement
     580  {
     581  public:
     582      Statement *_body;
     583      Catches *catches;
     584  
     585      Statement *tryBody;   /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
     586  
     587      TryCatchStatement *syntaxCopy() override;
     588      bool hasBreak() const override;
     589  
     590      void accept(Visitor *v) override { v->visit(this); }
     591  };
     592  
     593  class Catch final : public RootObject
     594  {
     595  public:
     596      Loc loc;
     597      Type *type;
     598      Identifier *ident;
     599      Statement *handler;
     600  
     601      VarDeclaration *var;
     602      // set if semantic processing errors
     603      d_bool errors;
     604  
     605      // was generated by the compiler,
     606      // wasn't present in source code
     607      d_bool internalCatch;
     608  
     609      Catch *syntaxCopy();
     610  };
     611  
     612  class TryFinallyStatement final : public Statement
     613  {
     614  public:
     615      Statement *_body;
     616      Statement *finalbody;
     617  
     618      Statement *tryBody;   // set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
     619      d_bool bodyFallsThru;   // true if _body falls through to finally
     620  
     621      static TryFinallyStatement *create(const Loc &loc, Statement *body, Statement *finalbody);
     622      TryFinallyStatement *syntaxCopy() override;
     623      bool hasBreak() const override;
     624      bool hasContinue() const override;
     625  
     626      void accept(Visitor *v) override { v->visit(this); }
     627  };
     628  
     629  class ScopeGuardStatement final : public Statement
     630  {
     631  public:
     632      TOK tok;
     633      Statement *statement;
     634  
     635      ScopeGuardStatement *syntaxCopy() override;
     636  
     637      void accept(Visitor *v) override { v->visit(this); }
     638  };
     639  
     640  class ThrowStatement final : public Statement
     641  {
     642  public:
     643      Expression *exp;
     644      // was generated by the compiler,
     645      // wasn't present in source code
     646      d_bool internalThrow;
     647  
     648      ThrowStatement *syntaxCopy() override;
     649  
     650      void accept(Visitor *v) override { v->visit(this); }
     651  };
     652  
     653  class DebugStatement final : public Statement
     654  {
     655  public:
     656      Statement *statement;
     657  
     658      DebugStatement *syntaxCopy() override;
     659      void accept(Visitor *v) override { v->visit(this); }
     660  };
     661  
     662  class GotoStatement final : public Statement
     663  {
     664  public:
     665      Identifier *ident;
     666      LabelDsymbol *label;
     667      Statement *tryBody;   /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
     668      TryFinallyStatement *tf;
     669      ScopeGuardStatement *os;
     670      VarDeclaration *lastVar;
     671      d_bool inCtfeBlock;
     672      GotoStatement *syntaxCopy() override;
     673  
     674      void accept(Visitor *v) override { v->visit(this); }
     675  };
     676  
     677  class LabelStatement final : public Statement
     678  {
     679  public:
     680      Identifier *ident;
     681      Statement *statement;
     682      Statement *tryBody;   /// set to enclosing TryCatchStatement or TryFinallyStatement if in _body portion
     683      TryFinallyStatement *tf;
     684      ScopeGuardStatement *os;
     685      VarDeclaration *lastVar;
     686      Statement *gotoTarget;      // interpret
     687      void* extra;                // used by Statement_toIR()
     688      d_bool breaks;                // someone did a 'break ident'
     689      d_bool inCtfeBlock;
     690      LabelStatement *syntaxCopy() override;
     691  
     692      void accept(Visitor *v) override { v->visit(this); }
     693  };
     694  
     695  class LabelDsymbol final : public Dsymbol
     696  {
     697  public:
     698      LabelStatement *statement;
     699  
     700      d_bool deleted;           // set if rewritten to return in foreach delegate
     701      d_bool iasm;              // set if used by inline assembler
     702  
     703      static LabelDsymbol *create(Identifier *ident);
     704      LabelDsymbol *isLabel() override;
     705      void accept(Visitor *v) override { v->visit(this); }
     706  };
     707  
     708  Statement* asmSemantic(AsmStatement *s, Scope *sc);
     709  
     710  class AsmStatement : public Statement
     711  {
     712  public:
     713      Token *tokens;
     714  
     715      AsmStatement *syntaxCopy() override;
     716      void accept(Visitor *v) override { v->visit(this); }
     717  };
     718  
     719  class InlineAsmStatement final : public AsmStatement
     720  {
     721  public:
     722      code *asmcode;
     723      unsigned asmalign;          // alignment of this statement
     724      unsigned regs;              // mask of registers modified (must match regm_t in back end)
     725      d_bool refparam;              // true if function parameter is referenced
     726      d_bool naked;                 // true if function is to be naked
     727  
     728      InlineAsmStatement *syntaxCopy() override;
     729      void accept(Visitor *v) override { v->visit(this); }
     730  };
     731  
     732  // A GCC asm statement - assembler instructions with D expression operands
     733  class GccAsmStatement final : public AsmStatement
     734  {
     735  public:
     736      StorageClass stc;           // attributes of the asm {} block
     737      Expression *insn;           // string expression that is the template for assembler code
     738      Expressions *args;          // input and output operands of the statement
     739      unsigned outputargs;        // of the operands in 'args', the number of output operands
     740      Identifiers *names;         // list of symbolic names for the operands
     741      Expressions *constraints;   // list of string constants specifying constraints on operands
     742      Expressions *clobbers;      // list of string constants specifying clobbers and scratch registers
     743      Identifiers *labels;        // list of goto labels
     744      GotoStatements *gotos;      // of the goto labels, the equivalent statements they represent
     745  
     746      GccAsmStatement *syntaxCopy() override;
     747      void accept(Visitor *v) override { v->visit(this); }
     748  };
     749  
     750  // a complete asm {} block
     751  class CompoundAsmStatement final : public CompoundStatement
     752  {
     753  public:
     754      StorageClass stc; // postfix attributes like nothrow/pure/@trusted
     755  
     756      CompoundAsmStatement *syntaxCopy() override;
     757  
     758      void accept(Visitor *v) override { v->visit(this); }
     759  };
     760  
     761  class ImportStatement final : public Statement
     762  {
     763  public:
     764      Dsymbols *imports;          // Array of Import's
     765  
     766      ImportStatement *syntaxCopy() override;
     767  
     768      void accept(Visitor *v) override { v->visit(this); }
     769  };