Stmt.h revision 5f1b9e689fa5c101512aef99225f2afea1673449
1//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file defines the Stmt interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_STMT_H
15#define LLVM_CLANG_AST_STMT_H
16
17#include "llvm/Support/Casting.h"
18#include "llvm/Support/raw_ostream.h"
19#include "clang/Basic/SourceLocation.h"
20#include "clang/AST/StmtIterator.h"
21#include "clang/AST/DeclGroup.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/iterator.h"
24#include "clang/AST/ASTContext.h"
25#include <string>
26using llvm::dyn_cast_or_null;
27
28namespace clang {
29  class ASTContext;
30  class Expr;
31  class Decl;
32  class ParmVarDecl;
33  class QualType;
34  class IdentifierInfo;
35  class SourceManager;
36  class StringLiteral;
37  class SwitchStmt;
38  class PrinterHelper;
39
40  //===----------------------------------------------------------------------===//
41  // ExprIterator - Iterators for iterating over Stmt* arrays that contain
42  //  only Expr*.  This is needed because AST nodes use Stmt* arrays to store
43  //  references to children (to be compatible with StmtIterator).
44  //===----------------------------------------------------------------------===//
45
46  class Stmt;
47  class Expr;
48
49  class ExprIterator {
50    Stmt** I;
51  public:
52    ExprIterator(Stmt** i) : I(i) {}
53    ExprIterator() : I(0) {}
54    ExprIterator& operator++() { ++I; return *this; }
55    ExprIterator operator-(size_t i) { return I-i; }
56    ExprIterator operator+(size_t i) { return I+i; }
57    Expr* operator[](size_t idx);
58    // FIXME: Verify that this will correctly return a signed distance.
59    signed operator-(const ExprIterator& R) const { return I - R.I; }
60    Expr* operator*() const;
61    Expr* operator->() const;
62    bool operator==(const ExprIterator& R) const { return I == R.I; }
63    bool operator!=(const ExprIterator& R) const { return I != R.I; }
64    bool operator>(const ExprIterator& R) const { return I > R.I; }
65    bool operator>=(const ExprIterator& R) const { return I >= R.I; }
66  };
67
68  class ConstExprIterator {
69    Stmt* const * I;
70  public:
71    ConstExprIterator(Stmt* const* i) : I(i) {}
72    ConstExprIterator() : I(0) {}
73    ConstExprIterator& operator++() { ++I; return *this; }
74    ConstExprIterator operator+(size_t i) { return I+i; }
75    ConstExprIterator operator-(size_t i) { return I-i; }
76    const Expr * operator[](size_t idx) const;
77    signed operator-(const ConstExprIterator& R) const { return I - R.I; }
78    const Expr * operator*() const;
79    const Expr * operator->() const;
80    bool operator==(const ConstExprIterator& R) const { return I == R.I; }
81    bool operator!=(const ConstExprIterator& R) const { return I != R.I; }
82    bool operator>(const ConstExprIterator& R) const { return I > R.I; }
83    bool operator>=(const ConstExprIterator& R) const { return I >= R.I; }
84  };
85
86//===----------------------------------------------------------------------===//
87// AST classes for statements.
88//===----------------------------------------------------------------------===//
89
90/// Stmt - This represents one statement.
91///
92class Stmt {
93public:
94  enum StmtClass {
95    NoStmtClass = 0,
96#define STMT(CLASS, PARENT) CLASS##Class,
97#define FIRST_STMT(CLASS) firstStmtConstant = CLASS##Class,
98#define LAST_STMT(CLASS) lastStmtConstant = CLASS##Class,
99#define FIRST_EXPR(CLASS) firstExprConstant = CLASS##Class,
100#define LAST_EXPR(CLASS) lastExprConstant = CLASS##Class
101#include "clang/AST/StmtNodes.def"
102};
103private:
104  const StmtClass sClass;
105
106  // Make vanilla 'new' and 'delete' illegal for Stmts.
107protected:
108  void* operator new(size_t bytes) throw() {
109    assert(0 && "Stmts cannot be allocated with regular 'new'.");
110    return 0;
111  }
112  void operator delete(void* data) throw() {
113    assert(0 && "Stmts cannot be released with regular 'delete'.");
114  }
115
116public:
117  // Only allow allocation of Stmts using the allocator in ASTContext
118  // or by doing a placement new.
119  void* operator new(size_t bytes, ASTContext& C,
120                     unsigned alignment = 16) throw() {
121    return ::operator new(bytes, C, alignment);
122  }
123
124  void* operator new(size_t bytes, ASTContext* C,
125                     unsigned alignment = 16) throw() {
126    return ::operator new(bytes, *C, alignment);
127  }
128
129  void* operator new(size_t bytes, void* mem) throw() {
130    return mem;
131  }
132
133  void operator delete(void*, ASTContext&, unsigned) throw() { }
134  void operator delete(void*, ASTContext*, unsigned) throw() { }
135  void operator delete(void*, std::size_t) throw() { }
136  void operator delete(void*, void*) throw() { }
137
138public:
139  /// \brief A placeholder type used to construct an empty shell of a
140  /// type, that will be filled in later (e.g., by some
141  /// de-serialization).
142  struct EmptyShell { };
143
144protected:
145  /// DestroyChildren - Invoked by destructors of subclasses of Stmt to
146  ///  recursively release child AST nodes.
147  void DestroyChildren(ASTContext& Ctx);
148
149  /// \brief Construct an empty statement.
150  explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC) {
151    if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
152  }
153
154public:
155  Stmt(StmtClass SC) : sClass(SC) {
156    if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
157  }
158  virtual ~Stmt() {}
159
160  virtual void Destroy(ASTContext &Ctx);
161
162  StmtClass getStmtClass() const { return sClass; }
163  const char *getStmtClassName() const;
164
165  /// SourceLocation tokens are not useful in isolation - they are low level
166  /// value objects created/interpreted by SourceManager. We assume AST
167  /// clients will have a pointer to the respective SourceManager.
168  virtual SourceRange getSourceRange() const = 0;
169  SourceLocation getLocStart() const { return getSourceRange().getBegin(); }
170  SourceLocation getLocEnd() const { return getSourceRange().getEnd(); }
171
172  // global temp stats (until we have a per-module visitor)
173  static void addStmtClass(const StmtClass s);
174  static bool CollectingStats(bool enable=false);
175  static void PrintStats();
176
177  /// dump - This does a local dump of the specified AST fragment.  It dumps the
178  /// specified node and a few nodes underneath it, but not the whole subtree.
179  /// This is useful in a debugger.
180  void dump() const;
181  void dump(SourceManager &SM) const;
182
183  /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
184  void dumpAll() const;
185  void dumpAll(SourceManager &SM) const;
186
187  /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
188  /// back to its original source language syntax.
189  void dumpPretty() const;
190  void printPretty(llvm::raw_ostream &OS, PrinterHelper* = NULL, unsigned = 0,
191                   bool NoIndent=false) const;
192
193  /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz.  Only
194  ///   works on systems with GraphViz (Mac OS X) or dot+gv installed.
195  void viewAST() const;
196
197  // Implement isa<T> support.
198  static bool classof(const Stmt *) { return true; }
199
200  /// hasImplicitControlFlow - Some statements (e.g. short circuited operations)
201  ///  contain implicit control-flow in the order their subexpressions
202  ///  are evaluated.  This predicate returns true if this statement has
203  ///  such implicit control-flow.  Such statements are also specially handled
204  ///  within CFGs.
205  bool hasImplicitControlFlow() const;
206
207  /// Child Iterators: All subclasses must implement child_begin and child_end
208  ///  to permit easy iteration over the substatements/subexpessions of an
209  ///  AST node.  This permits easy iteration over all nodes in the AST.
210  typedef StmtIterator       child_iterator;
211  typedef ConstStmtIterator  const_child_iterator;
212
213  virtual child_iterator child_begin() = 0;
214  virtual child_iterator child_end()   = 0;
215
216  const_child_iterator child_begin() const {
217    return const_child_iterator(const_cast<Stmt*>(this)->child_begin());
218  }
219
220  const_child_iterator child_end() const {
221    return const_child_iterator(const_cast<Stmt*>(this)->child_end());
222  }
223};
224
225/// DeclStmt - Adaptor class for mixing declarations with statements and
226/// expressions. For example, CompoundStmt mixes statements, expressions
227/// and declarations (variables, types). Another example is ForStmt, where
228/// the first statement can be an expression or a declaration.
229///
230class DeclStmt : public Stmt {
231  DeclGroupRef DG;
232  SourceLocation StartLoc, EndLoc;
233public:
234  DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
235           SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
236                                    StartLoc(startLoc), EndLoc(endLoc) {}
237
238  /// \brief Build an empty declaration statement.
239  explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { }
240
241  virtual void Destroy(ASTContext& Ctx);
242
243  /// isSingleDecl - This method returns true if this DeclStmt refers
244  /// to a single Decl.
245  bool isSingleDecl() const {
246    return DG.isSingleDecl();
247  }
248
249  const Decl *getSingleDecl() const { return DG.getSingleDecl(); }
250  Decl *getSingleDecl() { return DG.getSingleDecl(); }
251
252  const DeclGroupRef getDeclGroup() const { return DG; }
253  DeclGroupRef getDeclGroup() { return DG; }
254  void setDeclGroup(DeclGroupRef DGR) { DG = DGR; }
255
256  SourceLocation getStartLoc() const { return StartLoc; }
257  void setStartLoc(SourceLocation L) { StartLoc = L; }
258  SourceLocation getEndLoc() const { return EndLoc; }
259  void setEndLoc(SourceLocation L) { EndLoc = L; }
260
261  SourceRange getSourceRange() const {
262    return SourceRange(StartLoc, EndLoc);
263  }
264
265  static bool classof(const Stmt *T) {
266    return T->getStmtClass() == DeclStmtClass;
267  }
268  static bool classof(const DeclStmt *) { return true; }
269
270  // Iterators over subexpressions.
271  virtual child_iterator child_begin();
272  virtual child_iterator child_end();
273
274  typedef DeclGroupRef::iterator decl_iterator;
275  typedef DeclGroupRef::const_iterator const_decl_iterator;
276
277  decl_iterator decl_begin() { return DG.begin(); }
278  decl_iterator decl_end() { return DG.end(); }
279  const_decl_iterator decl_begin() const { return DG.begin(); }
280  const_decl_iterator decl_end() const { return DG.end(); }
281};
282
283/// NullStmt - This is the null statement ";": C99 6.8.3p3.
284///
285class NullStmt : public Stmt {
286  SourceLocation SemiLoc;
287public:
288  NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {}
289
290  /// \brief Build an empty null statement.
291  explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) { }
292
293  NullStmt* Clone(ASTContext &C) const;
294
295  SourceLocation getSemiLoc() const { return SemiLoc; }
296  void setSemiLoc(SourceLocation L) { SemiLoc = L; }
297
298  virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); }
299
300  static bool classof(const Stmt *T) {
301    return T->getStmtClass() == NullStmtClass;
302  }
303  static bool classof(const NullStmt *) { return true; }
304
305  // Iterators
306  virtual child_iterator child_begin();
307  virtual child_iterator child_end();
308};
309
310/// CompoundStmt - This represents a group of statements like { stmt stmt }.
311///
312class CompoundStmt : public Stmt {
313  Stmt** Body;
314  unsigned NumStmts;
315  SourceLocation LBracLoc, RBracLoc;
316public:
317  CompoundStmt(ASTContext& C, Stmt **StmtStart, unsigned numStmts,
318                             SourceLocation LB, SourceLocation RB)
319  : Stmt(CompoundStmtClass), NumStmts(numStmts), LBracLoc(LB), RBracLoc(RB) {
320    if (NumStmts == 0) {
321      Body = 0;
322      return;
323    }
324
325    Body = new (C) Stmt*[NumStmts];
326    memcpy(Body, StmtStart, numStmts * sizeof(*Body));
327  }
328
329  // \brief Build an empty compound statement.
330  explicit CompoundStmt(EmptyShell Empty)
331    : Stmt(CompoundStmtClass, Empty), Body(0), NumStmts(0) { }
332
333  void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts);
334
335  bool body_empty() const { return NumStmts == 0; }
336  unsigned size() const { return NumStmts; }
337
338  typedef Stmt** body_iterator;
339  body_iterator body_begin() { return Body; }
340  body_iterator body_end() { return Body + NumStmts; }
341  Stmt *body_back() { return NumStmts ? Body[NumStmts-1] : 0; }
342
343  typedef Stmt* const * const_body_iterator;
344  const_body_iterator body_begin() const { return Body; }
345  const_body_iterator body_end() const { return Body + NumStmts; }
346  const Stmt *body_back() const { return NumStmts ? Body[NumStmts-1] : 0; }
347
348  typedef std::reverse_iterator<body_iterator> reverse_body_iterator;
349  reverse_body_iterator body_rbegin() {
350    return reverse_body_iterator(body_end());
351  }
352  reverse_body_iterator body_rend() {
353    return reverse_body_iterator(body_begin());
354  }
355
356  typedef std::reverse_iterator<const_body_iterator>
357          const_reverse_body_iterator;
358
359  const_reverse_body_iterator body_rbegin() const {
360    return const_reverse_body_iterator(body_end());
361  }
362
363  const_reverse_body_iterator body_rend() const {
364    return const_reverse_body_iterator(body_begin());
365  }
366
367  virtual SourceRange getSourceRange() const {
368    return SourceRange(LBracLoc, RBracLoc);
369  }
370
371  SourceLocation getLBracLoc() const { return LBracLoc; }
372  void setLBracLoc(SourceLocation L) { LBracLoc = L; }
373  SourceLocation getRBracLoc() const { return RBracLoc; }
374  void setRBracLoc(SourceLocation L) { RBracLoc = L; }
375
376  static bool classof(const Stmt *T) {
377    return T->getStmtClass() == CompoundStmtClass;
378  }
379  static bool classof(const CompoundStmt *) { return true; }
380
381  // Iterators
382  virtual child_iterator child_begin();
383  virtual child_iterator child_end();
384};
385
386// SwitchCase is the base class for CaseStmt and DefaultStmt,
387class SwitchCase : public Stmt {
388protected:
389  // A pointer to the following CaseStmt or DefaultStmt class,
390  // used by SwitchStmt.
391  SwitchCase *NextSwitchCase;
392
393  SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {}
394
395public:
396  const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
397
398  SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
399
400  void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
401
402  Stmt *getSubStmt() { return v_getSubStmt(); }
403
404  virtual SourceRange getSourceRange() const { return SourceRange(); }
405
406  static bool classof(const Stmt *T) {
407    return T->getStmtClass() == CaseStmtClass ||
408    T->getStmtClass() == DefaultStmtClass;
409  }
410  static bool classof(const SwitchCase *) { return true; }
411protected:
412  virtual Stmt* v_getSubStmt() = 0;
413};
414
415class CaseStmt : public SwitchCase {
416  enum { SUBSTMT, LHS, RHS, END_EXPR };
417  Stmt* SubExprs[END_EXPR];  // The expression for the RHS is Non-null for
418                             // GNU "case 1 ... 4" extension
419  SourceLocation CaseLoc;
420  SourceLocation EllipsisLoc;
421  SourceLocation ColonLoc;
422
423  virtual Stmt* v_getSubStmt() { return getSubStmt(); }
424public:
425  CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
426           SourceLocation ellipsisLoc, SourceLocation colonLoc)
427    : SwitchCase(CaseStmtClass) {
428    SubExprs[SUBSTMT] = 0;
429    SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
430    SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
431    CaseLoc = caseLoc;
432    EllipsisLoc = ellipsisLoc;
433    ColonLoc = colonLoc;
434  }
435
436  /// \brief Build an empty switch case statement.
437  explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass) { }
438
439  SourceLocation getCaseLoc() const { return CaseLoc; }
440  void setCaseLoc(SourceLocation L) { CaseLoc = L; }
441  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
442  void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; }
443  SourceLocation getColonLoc() const { return ColonLoc; }
444  void setColonLoc(SourceLocation L) { ColonLoc = L; }
445
446  Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
447  Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
448  Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
449
450  const Expr *getLHS() const {
451    return reinterpret_cast<const Expr*>(SubExprs[LHS]);
452  }
453  const Expr *getRHS() const {
454    return reinterpret_cast<const Expr*>(SubExprs[RHS]);
455  }
456  const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
457
458  void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
459  void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
460  void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
461
462
463  virtual SourceRange getSourceRange() const {
464    // Handle deeply nested case statements with iteration instead of recursion.
465    const CaseStmt *CS = this;
466    while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
467      CS = CS2;
468
469    return SourceRange(CaseLoc, CS->getSubStmt()->getLocEnd());
470  }
471  static bool classof(const Stmt *T) {
472    return T->getStmtClass() == CaseStmtClass;
473  }
474  static bool classof(const CaseStmt *) { return true; }
475
476  // Iterators
477  virtual child_iterator child_begin();
478  virtual child_iterator child_end();
479};
480
481class DefaultStmt : public SwitchCase {
482  Stmt* SubStmt;
483  SourceLocation DefaultLoc;
484  SourceLocation ColonLoc;
485  virtual Stmt* v_getSubStmt() { return getSubStmt(); }
486public:
487  DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
488    SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL),
489    ColonLoc(CL) {}
490
491  /// \brief Build an empty default statement.
492  explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { }
493
494  Stmt *getSubStmt() { return SubStmt; }
495  const Stmt *getSubStmt() const { return SubStmt; }
496  void setSubStmt(Stmt *S) { SubStmt = S; }
497
498  SourceLocation getDefaultLoc() const { return DefaultLoc; }
499  void setDefaultLoc(SourceLocation L) { DefaultLoc = L; }
500  SourceLocation getColonLoc() const { return ColonLoc; }
501  void setColonLoc(SourceLocation L) { ColonLoc = L; }
502
503  virtual SourceRange getSourceRange() const {
504    return SourceRange(DefaultLoc, SubStmt->getLocEnd());
505  }
506  static bool classof(const Stmt *T) {
507    return T->getStmtClass() == DefaultStmtClass;
508  }
509  static bool classof(const DefaultStmt *) { return true; }
510
511  // Iterators
512  virtual child_iterator child_begin();
513  virtual child_iterator child_end();
514};
515
516class LabelStmt : public Stmt {
517  IdentifierInfo *Label;
518  Stmt *SubStmt;
519  SourceLocation IdentLoc;
520public:
521  LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
522    : Stmt(LabelStmtClass), Label(label),
523      SubStmt(substmt), IdentLoc(IL) {}
524
525  // \brief Build an empty label statement.
526  explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
527
528  SourceLocation getIdentLoc() const { return IdentLoc; }
529  IdentifierInfo *getID() const { return Label; }
530  void setID(IdentifierInfo *II) { Label = II; }
531  const char *getName() const;
532  Stmt *getSubStmt() { return SubStmt; }
533  const Stmt *getSubStmt() const { return SubStmt; }
534  void setIdentLoc(SourceLocation L) { IdentLoc = L; }
535  void setSubStmt(Stmt *SS) { SubStmt = SS; }
536
537  virtual SourceRange getSourceRange() const {
538    return SourceRange(IdentLoc, SubStmt->getLocEnd());
539  }
540  static bool classof(const Stmt *T) {
541    return T->getStmtClass() == LabelStmtClass;
542  }
543  static bool classof(const LabelStmt *) { return true; }
544
545  // Iterators
546  virtual child_iterator child_begin();
547  virtual child_iterator child_end();
548};
549
550
551/// IfStmt - This represents an if/then/else.
552///
553class IfStmt : public Stmt {
554  enum { COND, THEN, ELSE, END_EXPR };
555  Stmt* SubExprs[END_EXPR];
556  SourceLocation IfLoc;
557  SourceLocation ElseLoc;
558public:
559  IfStmt(SourceLocation IL, Expr *cond, Stmt *then,
560         SourceLocation EL = SourceLocation(), Stmt *elsev = 0)
561    : Stmt(IfStmtClass)  {
562    SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
563    SubExprs[THEN] = then;
564    SubExprs[ELSE] = elsev;
565    IfLoc = IL;
566    ElseLoc = EL;
567  }
568
569  /// \brief Build an empty if/then/else statement
570  explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
571
572  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
573  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
574  const Stmt *getThen() const { return SubExprs[THEN]; }
575  void setThen(Stmt *S) { SubExprs[THEN] = S; }
576  const Stmt *getElse() const { return SubExprs[ELSE]; }
577  void setElse(Stmt *S) { SubExprs[ELSE] = S; }
578
579  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
580  Stmt *getThen() { return SubExprs[THEN]; }
581  Stmt *getElse() { return SubExprs[ELSE]; }
582
583  SourceLocation getIfLoc() const { return IfLoc; }
584  void setIfLoc(SourceLocation L) { IfLoc = L; }
585  SourceLocation getElseLoc() const { return ElseLoc; }
586  void setElseLoc(SourceLocation L) { ElseLoc = L; }
587
588  virtual SourceRange getSourceRange() const {
589    if (SubExprs[ELSE])
590      return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
591    else
592      return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd());
593  }
594
595  static bool classof(const Stmt *T) {
596    return T->getStmtClass() == IfStmtClass;
597  }
598  static bool classof(const IfStmt *) { return true; }
599
600  // Iterators
601  virtual child_iterator child_begin();
602  virtual child_iterator child_end();
603};
604
605/// SwitchStmt - This represents a 'switch' stmt.
606///
607class SwitchStmt : public Stmt {
608  enum { COND, BODY, END_EXPR };
609  Stmt* SubExprs[END_EXPR];
610  // This points to a linked list of case and default statements.
611  SwitchCase *FirstCase;
612  SourceLocation SwitchLoc;
613public:
614  SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) {
615      SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
616      SubExprs[BODY] = NULL;
617    }
618
619  /// \brief Build a empty switch statement.
620  explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { }
621
622  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
623  const Stmt *getBody() const { return SubExprs[BODY]; }
624  const SwitchCase *getSwitchCaseList() const { return FirstCase; }
625
626  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
627  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
628  Stmt *getBody() { return SubExprs[BODY]; }
629  void setBody(Stmt *S) { SubExprs[BODY] = S; }
630  SwitchCase *getSwitchCaseList() { return FirstCase; }
631  void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
632
633  SourceLocation getSwitchLoc() const { return SwitchLoc; }
634  void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
635
636  void setBody(Stmt *S, SourceLocation SL) {
637    SubExprs[BODY] = S;
638    SwitchLoc = SL;
639  }
640  void addSwitchCase(SwitchCase *SC) {
641    assert(!SC->getNextSwitchCase() && "case/default already added to a switch");
642    SC->setNextSwitchCase(FirstCase);
643    FirstCase = SC;
644  }
645  virtual SourceRange getSourceRange() const {
646    return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd());
647  }
648  static bool classof(const Stmt *T) {
649    return T->getStmtClass() == SwitchStmtClass;
650  }
651  static bool classof(const SwitchStmt *) { return true; }
652
653  // Iterators
654  virtual child_iterator child_begin();
655  virtual child_iterator child_end();
656};
657
658
659/// WhileStmt - This represents a 'while' stmt.
660///
661class WhileStmt : public Stmt {
662  enum { COND, BODY, END_EXPR };
663  Stmt* SubExprs[END_EXPR];
664  SourceLocation WhileLoc;
665public:
666  WhileStmt(Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) {
667    SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
668    SubExprs[BODY] = body;
669    WhileLoc = WL;
670  }
671
672  /// \brief Build an empty while statement.
673  explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { }
674
675  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
676  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
677  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
678  Stmt *getBody() { return SubExprs[BODY]; }
679  const Stmt *getBody() const { return SubExprs[BODY]; }
680  void setBody(Stmt *S) { SubExprs[BODY] = S; }
681
682  SourceLocation getWhileLoc() const { return WhileLoc; }
683  void setWhileLoc(SourceLocation L) { WhileLoc = L; }
684
685  virtual SourceRange getSourceRange() const {
686    return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd());
687  }
688  static bool classof(const Stmt *T) {
689    return T->getStmtClass() == WhileStmtClass;
690  }
691  static bool classof(const WhileStmt *) { return true; }
692
693  // Iterators
694  virtual child_iterator child_begin();
695  virtual child_iterator child_end();
696};
697
698/// DoStmt - This represents a 'do/while' stmt.
699///
700class DoStmt : public Stmt {
701  enum { COND, BODY, END_EXPR };
702  Stmt* SubExprs[END_EXPR];
703  SourceLocation DoLoc;
704  SourceLocation WhileLoc;
705
706public:
707  DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL)
708    : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL) {
709    SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
710    SubExprs[BODY] = body;
711    DoLoc = DL;
712    WhileLoc = WL;
713  }
714
715  /// \brief Build an empty do-while statement.
716  explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { }
717
718  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
719  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
720  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
721  Stmt *getBody() { return SubExprs[BODY]; }
722  const Stmt *getBody() const { return SubExprs[BODY]; }
723  void setBody(Stmt *S) { SubExprs[BODY] = S; }
724
725  SourceLocation getDoLoc() const { return DoLoc; }
726  void setDoLoc(SourceLocation L) { DoLoc = L; }
727  SourceLocation getWhileLoc() const { return WhileLoc; }
728  void setWhileLoc(SourceLocation L) { WhileLoc = L; }
729
730  virtual SourceRange getSourceRange() const {
731    return SourceRange(DoLoc, SubExprs[BODY]->getLocEnd());
732  }
733  static bool classof(const Stmt *T) {
734    return T->getStmtClass() == DoStmtClass;
735  }
736  static bool classof(const DoStmt *) { return true; }
737
738  // Iterators
739  virtual child_iterator child_begin();
740  virtual child_iterator child_end();
741};
742
743
744/// ForStmt - This represents a 'for (init;cond;inc)' stmt.  Note that any of
745/// the init/cond/inc parts of the ForStmt will be null if they were not
746/// specified in the source.
747///
748class ForStmt : public Stmt {
749  enum { INIT, COND, INC, BODY, END_EXPR };
750  Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
751  SourceLocation ForLoc;
752  SourceLocation LParenLoc, RParenLoc;
753
754public:
755  ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL,
756          SourceLocation LP, SourceLocation RP)
757    : Stmt(ForStmtClass) {
758    SubExprs[INIT] = Init;
759    SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
760    SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
761    SubExprs[BODY] = Body;
762    ForLoc = FL;
763    LParenLoc = LP;
764    RParenLoc = RP;
765  }
766
767  /// \brief Build an empty for statement.
768  explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
769
770  Stmt *getInit() { return SubExprs[INIT]; }
771  Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
772  Expr *getInc()  { return reinterpret_cast<Expr*>(SubExprs[INC]); }
773  Stmt *getBody() { return SubExprs[BODY]; }
774
775  const Stmt *getInit() const { return SubExprs[INIT]; }
776  const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
777  const Expr *getInc()  const { return reinterpret_cast<Expr*>(SubExprs[INC]); }
778  const Stmt *getBody() const { return SubExprs[BODY]; }
779
780  void setInit(Stmt *S) { SubExprs[INIT] = S; }
781  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
782  void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
783  void setBody(Stmt *S) { SubExprs[BODY] = S; }
784
785  SourceLocation getForLoc() const { return ForLoc; }
786  void setForLoc(SourceLocation L) { ForLoc = L; }
787  SourceLocation getLParenLoc() const { return LParenLoc; }
788  void setLParenLoc(SourceLocation L) { LParenLoc = L; }
789  SourceLocation getRParenLoc() const { return RParenLoc; }
790  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
791
792  virtual SourceRange getSourceRange() const {
793    return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd());
794  }
795  static bool classof(const Stmt *T) {
796    return T->getStmtClass() == ForStmtClass;
797  }
798  static bool classof(const ForStmt *) { return true; }
799
800  // Iterators
801  virtual child_iterator child_begin();
802  virtual child_iterator child_end();
803};
804
805/// GotoStmt - This represents a direct goto.
806///
807class GotoStmt : public Stmt {
808  LabelStmt *Label;
809  SourceLocation GotoLoc;
810  SourceLocation LabelLoc;
811public:
812  GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
813    : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
814
815  /// \brief Build an empty goto statement.
816  explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
817
818  LabelStmt *getLabel() const { return Label; }
819  void setLabel(LabelStmt *S) { Label = S; }
820
821  SourceLocation getGotoLoc() const { return GotoLoc; }
822  void setGotoLoc(SourceLocation L) { GotoLoc = L; }
823  SourceLocation getLabelLoc() const { return LabelLoc; }
824  void setLabelLoc(SourceLocation L) { LabelLoc = L; }
825
826  virtual SourceRange getSourceRange() const {
827    return SourceRange(GotoLoc, LabelLoc);
828  }
829  static bool classof(const Stmt *T) {
830    return T->getStmtClass() == GotoStmtClass;
831  }
832  static bool classof(const GotoStmt *) { return true; }
833
834  // Iterators
835  virtual child_iterator child_begin();
836  virtual child_iterator child_end();
837};
838
839/// IndirectGotoStmt - This represents an indirect goto.
840///
841class IndirectGotoStmt : public Stmt {
842  SourceLocation GotoLoc;
843  SourceLocation StarLoc;
844  Stmt *Target;
845public:
846  IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc,
847                   Expr *target)
848    : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
849      Target((Stmt*)target) {}
850
851  /// \brief Build an empty indirect goto statement.
852  explicit IndirectGotoStmt(EmptyShell Empty)
853    : Stmt(IndirectGotoStmtClass, Empty) { }
854
855  void setGotoLoc(SourceLocation L) { GotoLoc = L; }
856  SourceLocation getGotoLoc() const { return GotoLoc; }
857  void setStarLoc(SourceLocation L) { StarLoc = L; }
858  SourceLocation getStarLoc() const { return StarLoc; }
859
860  Expr *getTarget();
861  const Expr *getTarget() const;
862  void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
863
864  virtual SourceRange getSourceRange() const {
865    return SourceRange(GotoLoc, Target->getLocEnd());
866  }
867
868  static bool classof(const Stmt *T) {
869    return T->getStmtClass() == IndirectGotoStmtClass;
870  }
871  static bool classof(const IndirectGotoStmt *) { return true; }
872
873  // Iterators
874  virtual child_iterator child_begin();
875  virtual child_iterator child_end();
876};
877
878
879/// ContinueStmt - This represents a continue.
880///
881class ContinueStmt : public Stmt {
882  SourceLocation ContinueLoc;
883public:
884  ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {}
885
886  /// \brief Build an empty continue statement.
887  explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { }
888
889  SourceLocation getContinueLoc() const { return ContinueLoc; }
890  void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
891
892  virtual SourceRange getSourceRange() const {
893    return SourceRange(ContinueLoc);
894  }
895
896  ContinueStmt* Clone(ASTContext &C) const;
897
898  static bool classof(const Stmt *T) {
899    return T->getStmtClass() == ContinueStmtClass;
900  }
901  static bool classof(const ContinueStmt *) { return true; }
902
903  // Iterators
904  virtual child_iterator child_begin();
905  virtual child_iterator child_end();
906};
907
908/// BreakStmt - This represents a break.
909///
910class BreakStmt : public Stmt {
911  SourceLocation BreakLoc;
912public:
913  BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
914
915  /// \brief Build an empty break statement.
916  explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
917
918  SourceLocation getBreakLoc() const { return BreakLoc; }
919  void setBreakLoc(SourceLocation L) { BreakLoc = L; }
920
921  virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); }
922
923  BreakStmt* Clone(ASTContext &C) const;
924
925  static bool classof(const Stmt *T) {
926    return T->getStmtClass() == BreakStmtClass;
927  }
928  static bool classof(const BreakStmt *) { return true; }
929
930  // Iterators
931  virtual child_iterator child_begin();
932  virtual child_iterator child_end();
933};
934
935
936/// ReturnStmt - This represents a return, optionally of an expression:
937///   return;
938///   return 4;
939///
940/// Note that GCC allows return with no argument in a function declared to
941/// return a value, and it allows returning a value in functions declared to
942/// return void.  We explicitly model this in the AST, which means you can't
943/// depend on the return type of the function and the presence of an argument.
944///
945class ReturnStmt : public Stmt {
946  Stmt *RetExpr;
947  SourceLocation RetLoc;
948public:
949  ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass),
950    RetExpr((Stmt*) E), RetLoc(RL) {}
951
952  /// \brief Build an empty return expression.
953  explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }
954
955  const Expr *getRetValue() const;
956  Expr *getRetValue();
957  void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); }
958
959  SourceLocation getReturnLoc() const { return RetLoc; }
960  void setReturnLoc(SourceLocation L) { RetLoc = L; }
961
962  virtual SourceRange getSourceRange() const;
963
964  static bool classof(const Stmt *T) {
965    return T->getStmtClass() == ReturnStmtClass;
966  }
967  static bool classof(const ReturnStmt *) { return true; }
968
969  // Iterators
970  virtual child_iterator child_begin();
971  virtual child_iterator child_end();
972};
973
974/// AsmStmt - This represents a GNU inline-assembly statement extension.
975///
976class AsmStmt : public Stmt {
977  SourceLocation AsmLoc, RParenLoc;
978  StringLiteral *AsmStr;
979
980  bool IsSimple;
981  bool IsVolatile;
982
983  unsigned NumOutputs;
984  unsigned NumInputs;
985
986  llvm::SmallVector<std::string, 4> Names;
987  llvm::SmallVector<StringLiteral*, 4> Constraints;
988  llvm::SmallVector<Stmt*, 4> Exprs;
989
990  llvm::SmallVector<StringLiteral*, 4> Clobbers;
991public:
992  AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
993          unsigned numoutputs, unsigned numinputs,
994          std::string *names, StringLiteral **constraints,
995          Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
996          StringLiteral **clobbers, SourceLocation rparenloc);
997
998  /// \brief Build an empty inline-assembly statement.
999  explicit AsmStmt(EmptyShell Empty) : Stmt(AsmStmtClass, Empty) { }
1000
1001  SourceLocation getAsmLoc() const { return AsmLoc; }
1002  void setAsmLoc(SourceLocation L) { AsmLoc = L; }
1003  SourceLocation getRParenLoc() const { return RParenLoc; }
1004  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
1005
1006  bool isVolatile() const { return IsVolatile; }
1007  void setVolatile(bool V) { IsVolatile = V; }
1008  bool isSimple() const { return IsSimple; }
1009  void setSimple(bool V) { IsSimple = false; }
1010
1011  //===--- Asm String Analysis ---===//
1012
1013  const StringLiteral *getAsmString() const { return AsmStr; }
1014  StringLiteral *getAsmString() { return AsmStr; }
1015  void setAsmString(StringLiteral *E) { AsmStr = E; }
1016
1017  /// AsmStringPiece - this is part of a decomposed asm string specification
1018  /// (for use with the AnalyzeAsmString function below).  An asm string is
1019  /// considered to be a concatenation of these parts.
1020  class AsmStringPiece {
1021  public:
1022    enum Kind {
1023      String,  // String in .ll asm string form, "$" -> "$$" and "%%" -> "%".
1024      Operand  // Operand reference, with optional modifier %c4.
1025    };
1026  private:
1027    Kind MyKind;
1028    std::string Str;
1029    unsigned OperandNo;
1030  public:
1031    AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
1032    AsmStringPiece(unsigned OpNo, char Modifier)
1033      : MyKind(Operand), Str(), OperandNo(OpNo) {
1034      Str += Modifier;
1035    }
1036
1037    bool isString() const { return MyKind == String; }
1038    bool isOperand() const { return MyKind == Operand; }
1039
1040    const std::string &getString() const {
1041      assert(isString());
1042      return Str;
1043    }
1044
1045    unsigned getOperandNo() const {
1046      assert(isOperand());
1047      return OperandNo;
1048    }
1049
1050    /// getModifier - Get the modifier for this operand, if present.  This
1051    /// returns '\0' if there was no modifier.
1052    char getModifier() const {
1053      assert(isOperand());
1054      return Str[0];
1055    }
1056  };
1057
1058  /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
1059  /// it into pieces.  If the asm string is erroneous, emit errors and return
1060  /// true, otherwise return false.  This handles canonicalization and
1061  /// translation of strings from GCC syntax to LLVM IR syntax, and handles
1062  //// flattening of named references like %[foo] to Operand AsmStringPiece's.
1063  unsigned AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece> &Pieces,
1064                            ASTContext &C, unsigned &DiagOffs) const;
1065
1066
1067  //===--- Output operands ---===//
1068
1069  unsigned getNumOutputs() const { return NumOutputs; }
1070
1071  const std::string &getOutputName(unsigned i) const {
1072    return Names[i];
1073  }
1074
1075  /// getOutputConstraint - Return the constraint string for the specified
1076  /// output operand.  All output constraints are known to be non-empty (either
1077  /// '=' or '+').
1078  std::string getOutputConstraint(unsigned i) const;
1079
1080  const StringLiteral *getOutputConstraintLiteral(unsigned i) const {
1081    return Constraints[i];
1082  }
1083  StringLiteral *getOutputConstraintLiteral(unsigned i) {
1084    return Constraints[i];
1085  }
1086
1087
1088  Expr *getOutputExpr(unsigned i);
1089
1090  const Expr *getOutputExpr(unsigned i) const {
1091    return const_cast<AsmStmt*>(this)->getOutputExpr(i);
1092  }
1093
1094  /// isOutputPlusConstraint - Return true if the specified output constraint
1095  /// is a "+" constraint (which is both an input and an output) or false if it
1096  /// is an "=" constraint (just an output).
1097  bool isOutputPlusConstraint(unsigned i) const {
1098    return getOutputConstraint(i)[0] == '+';
1099  }
1100
1101  /// getNumPlusOperands - Return the number of output operands that have a "+"
1102  /// constraint.
1103  unsigned getNumPlusOperands() const;
1104
1105  //===--- Input operands ---===//
1106
1107  unsigned getNumInputs() const { return NumInputs; }
1108
1109  const std::string &getInputName(unsigned i) const {
1110    return Names[i + NumOutputs];
1111  }
1112
1113  /// getInputConstraint - Return the specified input constraint.  Unlike output
1114  /// constraints, these can be empty.
1115  std::string getInputConstraint(unsigned i) const;
1116
1117  const StringLiteral *getInputConstraintLiteral(unsigned i) const {
1118    return Constraints[i + NumOutputs];
1119  }
1120  StringLiteral *getInputConstraintLiteral(unsigned i) {
1121    return Constraints[i + NumOutputs];
1122  }
1123
1124
1125  Expr *getInputExpr(unsigned i);
1126
1127  const Expr *getInputExpr(unsigned i) const {
1128    return const_cast<AsmStmt*>(this)->getInputExpr(i);
1129  }
1130
1131  void setOutputsAndInputs(unsigned NumOutputs,
1132                           unsigned NumInputs,
1133                           const std::string *Names,
1134                           StringLiteral **Constraints,
1135                           Stmt **Exprs);
1136
1137  //===--- Other ---===//
1138
1139  /// getNamedOperand - Given a symbolic operand reference like %[foo],
1140  /// translate this into a numeric value needed to reference the same operand.
1141  /// This returns -1 if the operand name is invalid.
1142  int getNamedOperand(const std::string &SymbolicName) const;
1143
1144
1145
1146  unsigned getNumClobbers() const { return Clobbers.size(); }
1147  StringLiteral *getClobber(unsigned i) { return Clobbers[i]; }
1148  const StringLiteral *getClobber(unsigned i) const { return Clobbers[i]; }
1149  void setClobbers(StringLiteral **Clobbers, unsigned NumClobbers);
1150
1151  virtual SourceRange getSourceRange() const {
1152    return SourceRange(AsmLoc, RParenLoc);
1153  }
1154
1155  static bool classof(const Stmt *T) {return T->getStmtClass() == AsmStmtClass;}
1156  static bool classof(const AsmStmt *) { return true; }
1157
1158  // Input expr iterators.
1159
1160  typedef ExprIterator inputs_iterator;
1161  typedef ConstExprIterator const_inputs_iterator;
1162
1163  inputs_iterator begin_inputs() {
1164    return &Exprs[0] + NumOutputs;
1165  }
1166
1167  inputs_iterator end_inputs() {
1168    return  &Exprs[0] + NumOutputs + NumInputs;
1169  }
1170
1171  const_inputs_iterator begin_inputs() const {
1172    return &Exprs[0] + NumOutputs;
1173  }
1174
1175  const_inputs_iterator end_inputs() const {
1176    return  &Exprs[0] + NumOutputs + NumInputs;}
1177
1178  // Output expr iterators.
1179
1180  typedef ExprIterator outputs_iterator;
1181  typedef ConstExprIterator const_outputs_iterator;
1182
1183  outputs_iterator begin_outputs() { return &Exprs[0]; }
1184  outputs_iterator end_outputs() { return &Exprs[0] + NumOutputs; }
1185
1186  const_outputs_iterator begin_outputs() const { return &Exprs[0]; }
1187  const_outputs_iterator end_outputs() const { return &Exprs[0] + NumOutputs; }
1188
1189  // Input name iterator.
1190
1191  const std::string *begin_output_names() const {
1192    return &Names[0];
1193  }
1194
1195  const std::string *end_output_names() const {
1196    return &Names[0] + NumOutputs;
1197  }
1198
1199  // Child iterators
1200
1201  virtual child_iterator child_begin();
1202  virtual child_iterator child_end();
1203};
1204
1205}  // end namespace clang
1206
1207#endif
1208