StmtCXX.h revision 07cf58c96dc599d1c25dae4efd9445b6f5d3596c
1//===--- StmtCXX.h - Classes for representing C++ 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 C++ statement AST node classes.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_STMTCXX_H
15#define LLVM_CLANG_AST_STMTCXX_H
16
17#include "clang/AST/Stmt.h"
18#include "llvm/Support/Compiler.h"
19
20namespace clang {
21
22class VarDecl;
23
24/// CXXCatchStmt - This represents a C++ catch block.
25///
26class CXXCatchStmt : public Stmt {
27  SourceLocation CatchLoc;
28  /// The exception-declaration of the type.
29  VarDecl *ExceptionDecl;
30  /// The handler block.
31  Stmt *HandlerBlock;
32
33public:
34  CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
35  : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
36    HandlerBlock(handlerBlock) {}
37
38  CXXCatchStmt(EmptyShell Empty)
39  : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
40
41  SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; }
42  SourceLocation getLocEnd() const LLVM_READONLY {
43    return HandlerBlock->getLocEnd();
44  }
45
46  SourceLocation getCatchLoc() const { return CatchLoc; }
47  VarDecl *getExceptionDecl() const { return ExceptionDecl; }
48  QualType getCaughtType() const;
49  Stmt *getHandlerBlock() const { return HandlerBlock; }
50
51  static bool classof(const Stmt *T) {
52    return T->getStmtClass() == CXXCatchStmtClass;
53  }
54
55  child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); }
56
57  friend class ASTStmtReader;
58};
59
60/// CXXTryStmt - A C++ try block, including all handlers.
61///
62class CXXTryStmt : public Stmt {
63  SourceLocation TryLoc;
64  unsigned NumHandlers;
65
66  CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers);
67
68  CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
69    : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
70
71  Stmt const * const *getStmts() const {
72    return reinterpret_cast<Stmt const * const*>(this + 1);
73  }
74  Stmt **getStmts() {
75    return reinterpret_cast<Stmt **>(this + 1);
76  }
77
78public:
79  static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
80                            Stmt *tryBlock, ArrayRef<Stmt*> handlers);
81
82  static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
83                            unsigned numHandlers);
84
85  SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
86  SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
87
88  SourceLocation getTryLoc() const { return TryLoc; }
89  SourceLocation getEndLoc() const {
90    return getStmts()[NumHandlers]->getLocEnd();
91  }
92
93  CompoundStmt *getTryBlock() {
94    return llvm::cast<CompoundStmt>(getStmts()[0]);
95  }
96  const CompoundStmt *getTryBlock() const {
97    return llvm::cast<CompoundStmt>(getStmts()[0]);
98  }
99
100  unsigned getNumHandlers() const { return NumHandlers; }
101  CXXCatchStmt *getHandler(unsigned i) {
102    return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
103  }
104  const CXXCatchStmt *getHandler(unsigned i) const {
105    return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
106  }
107
108  static bool classof(const Stmt *T) {
109    return T->getStmtClass() == CXXTryStmtClass;
110  }
111
112  child_range children() {
113    return child_range(getStmts(), getStmts() + getNumHandlers() + 1);
114  }
115
116  friend class ASTStmtReader;
117};
118
119/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for
120/// statement, represented as 'for (range-declarator : range-expression)'.
121///
122/// This is stored in a partially-desugared form to allow full semantic
123/// analysis of the constituent components. The original syntactic components
124/// can be extracted using getLoopVariable and getRangeInit.
125class CXXForRangeStmt : public Stmt {
126  enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END };
127  // SubExprs[RANGE] is an expression or declstmt.
128  // SubExprs[COND] and SubExprs[INC] are expressions.
129  Stmt *SubExprs[END];
130  SourceLocation ForLoc;
131  SourceLocation ColonLoc;
132  SourceLocation RParenLoc;
133public:
134  CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd,
135                  Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body,
136                  SourceLocation FL, SourceLocation CL, SourceLocation RPL);
137  CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { }
138
139
140  VarDecl *getLoopVariable();
141  Expr *getRangeInit();
142
143  const VarDecl *getLoopVariable() const;
144  const Expr *getRangeInit() const;
145
146
147  DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); }
148  DeclStmt *getBeginEndStmt() {
149    return cast_or_null<DeclStmt>(SubExprs[BEGINEND]);
150  }
151  Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); }
152  Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); }
153  DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); }
154  Stmt *getBody() { return SubExprs[BODY]; }
155
156  const DeclStmt *getRangeStmt() const {
157    return cast<DeclStmt>(SubExprs[RANGE]);
158  }
159  const DeclStmt *getBeginEndStmt() const {
160    return cast_or_null<DeclStmt>(SubExprs[BEGINEND]);
161  }
162  const Expr *getCond() const {
163    return cast_or_null<Expr>(SubExprs[COND]);
164  }
165  const Expr *getInc() const {
166    return cast_or_null<Expr>(SubExprs[INC]);
167  }
168  const DeclStmt *getLoopVarStmt() const {
169    return cast<DeclStmt>(SubExprs[LOOPVAR]);
170  }
171  const Stmt *getBody() const { return SubExprs[BODY]; }
172
173  void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); }
174  void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; }
175  void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; }
176  void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
177  void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
178  void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; }
179  void setBody(Stmt *S) { SubExprs[BODY] = S; }
180
181
182  SourceLocation getForLoc() const { return ForLoc; }
183  void setForLoc(SourceLocation Loc) { ForLoc = Loc; }
184  SourceLocation getColonLoc() const { return ColonLoc; }
185  void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
186  SourceLocation getRParenLoc() const { return RParenLoc; }
187  void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; }
188
189  SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
190  SourceLocation getLocEnd() const LLVM_READONLY {
191    return SubExprs[BODY]->getLocEnd();
192  }
193
194  static bool classof(const Stmt *T) {
195    return T->getStmtClass() == CXXForRangeStmtClass;
196  }
197
198  // Iterators
199  child_range children() {
200    return child_range(&SubExprs[0], &SubExprs[END]);
201  }
202};
203
204/// \brief Representation of a Microsoft __if_exists or __if_not_exists
205/// statement with a dependent name.
206///
207/// The __if_exists statement can be used to include a sequence of statements
208/// in the program only when a particular dependent name does not exist. For
209/// example:
210///
211/// \code
212/// template<typename T>
213/// void call_foo(T &t) {
214///   __if_exists (T::foo) {
215///     t.foo(); // okay: only called when T::foo exists.
216///   }
217/// }
218/// \endcode
219///
220/// Similarly, the __if_not_exists statement can be used to include the
221/// statements when a particular name does not exist.
222///
223/// Note that this statement only captures __if_exists and __if_not_exists
224/// statements whose name is dependent. All non-dependent cases are handled
225/// directly in the parser, so that they don't introduce a new scope. Clang
226/// introduces scopes in the dependent case to keep names inside the compound
227/// statement from leaking out into the surround statements, which would
228/// compromise the template instantiation model. This behavior differs from
229/// Visual C++ (which never introduces a scope), but is a fairly reasonable
230/// approximation of the VC++ behavior.
231class MSDependentExistsStmt : public Stmt {
232  SourceLocation KeywordLoc;
233  bool IsIfExists;
234  NestedNameSpecifierLoc QualifierLoc;
235  DeclarationNameInfo NameInfo;
236  Stmt *SubStmt;
237
238  friend class ASTReader;
239  friend class ASTStmtReader;
240
241public:
242  MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists,
243                        NestedNameSpecifierLoc QualifierLoc,
244                        DeclarationNameInfo NameInfo,
245                        CompoundStmt *SubStmt)
246  : Stmt(MSDependentExistsStmtClass),
247    KeywordLoc(KeywordLoc), IsIfExists(IsIfExists),
248    QualifierLoc(QualifierLoc), NameInfo(NameInfo),
249    SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { }
250
251  /// \brief Retrieve the location of the __if_exists or __if_not_exists
252  /// keyword.
253  SourceLocation getKeywordLoc() const { return KeywordLoc; }
254
255  /// \brief Determine whether this is an __if_exists statement.
256  bool isIfExists() const { return IsIfExists; }
257
258  /// \brief Determine whether this is an __if_exists statement.
259  bool isIfNotExists() const { return !IsIfExists; }
260
261  /// \brief Retrieve the nested-name-specifier that qualifies this name, if
262  /// any.
263  NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
264
265  /// \brief Retrieve the name of the entity we're testing for, along with
266  /// location information
267  DeclarationNameInfo getNameInfo() const { return NameInfo; }
268
269  /// \brief Retrieve the compound statement that will be included in the
270  /// program only if the existence of the symbol matches the initial keyword.
271  CompoundStmt *getSubStmt() const {
272    return reinterpret_cast<CompoundStmt *>(SubStmt);
273  }
274
275  SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
276  SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
277
278  child_range children() {
279    return child_range(&SubStmt, &SubStmt+1);
280  }
281
282  static bool classof(const Stmt *T) {
283    return T->getStmtClass() == MSDependentExistsStmtClass;
284  }
285};
286
287}  // end namespace clang
288
289#endif
290