Stmt.h revision 8e74c93ddaa8268a999e1b25c723dc1984a434b4
1//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by Chris Lattner and is distributed under 6// the University of Illinois Open Source 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 "clang/Basic/SourceLocation.h" 18#include "llvm/ADT/SmallVector.h" 19#include "llvm/ADT/iterator" 20#include <iosfwd> 21 22namespace clang { 23 class Expr; 24 class Decl; 25 class ScopedDecl; 26 class IdentifierInfo; 27 class SourceManager; 28 class SwitchStmt; 29 class PrinterHelper; 30 31/// Stmt - This represents one statement. 32/// 33class Stmt { 34public: 35 enum StmtClass { 36#define STMT(N, CLASS, PARENT) CLASS##Class = N, 37#define FIRST_STMT(N) firstStmtConstant = N, 38#define LAST_STMT(N) lastStmtConstant = N, 39#define FIRST_EXPR(N) firstExprConstant = N, 40#define LAST_EXPR(N) lastExprConstant = N 41#include "clang/AST/StmtNodes.def" 42}; 43private: 44 const StmtClass sClass; 45public: 46 Stmt(StmtClass SC) : sClass(SC) { 47 if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); 48 } 49 virtual ~Stmt() {} 50 51 StmtClass getStmtClass() const { return sClass; } 52 const char *getStmtClassName() const; 53 54 /// SourceLocation tokens are not useful in isolation - they are low level 55 /// value objects created/interpreted by SourceManager. We assume AST 56 /// clients will have a pointer to the respective SourceManager. 57 virtual SourceRange getSourceRange() const = 0; 58 SourceLocation getLocStart() const { return getSourceRange().Begin(); } 59 SourceLocation getLocEnd() const { return getSourceRange().End(); } 60 61 // global temp stats (until we have a per-module visitor) 62 static void addStmtClass(const StmtClass s); 63 static bool CollectingStats(bool enable=false); 64 static void PrintStats(); 65 66 /// dump - This does a local dump of the specified AST fragment. It dumps the 67 /// specified node and a few nodes underneath it, but not the whole subtree. 68 /// This is useful in a debugger. 69 void dump() const; 70 void dump(SourceManager &SM) const; 71 72 /// dumpAll - This does a dump of the specified AST fragment and all subtrees. 73 void dumpAll() const; 74 void dumpAll(SourceManager &SM) const; 75 76 /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST 77 /// back to its original source language syntax. 78 void dumpPretty() const; 79 void printPretty(std::ostream &OS, PrinterHelper* = NULL) const; 80 81 // Implement isa<T> support. 82 static bool classof(const Stmt *) { return true; } 83 84 /// Child Iterators: All subclasses must implement child_begin and child_end 85 /// to permit easy iteration over the substatements/subexpessions of an 86 /// AST node. This permits easy iteration over all nodes in the AST. 87 typedef Stmt** child_iterator; 88 typedef Stmt* const * const_child_iterator; 89 90 typedef std::reverse_iterator<child_iterator> 91 reverse_child_iterator; 92 typedef std::reverse_iterator<const_child_iterator> 93 const_reverse_child_iterator; 94 95 virtual child_iterator child_begin() = 0; 96 virtual child_iterator child_end() = 0; 97 98 const_child_iterator child_begin() const { 99 return (child_iterator) const_cast<Stmt*>(this)->child_begin(); 100 } 101 102 const_child_iterator child_end() const { 103 return (child_iterator) const_cast<Stmt*>(this)->child_end(); 104 } 105 106 reverse_child_iterator child_rbegin() { 107 return reverse_child_iterator(child_end()); 108 } 109 110 reverse_child_iterator child_rend() { 111 return reverse_child_iterator(child_begin()); 112 } 113 114 const_reverse_child_iterator child_rbegin() const { 115 return const_reverse_child_iterator(child_end()); 116 } 117 118 const_reverse_child_iterator child_rend() const { 119 return const_reverse_child_iterator(child_begin()); 120 } 121}; 122 123/// DeclStmt - Adaptor class for mixing declarations with statements and 124/// expressions. For example, CompoundStmt mixes statements, expressions 125/// and declarations (variables, types). Another example is ForStmt, where 126/// the first statement can be an expression or a declaration. 127/// 128class DeclStmt : public Stmt { 129 ScopedDecl *TheDecl; 130public: 131 DeclStmt(ScopedDecl *D) : Stmt(DeclStmtClass), TheDecl(D) {} 132 133 const ScopedDecl *getDecl() const { return TheDecl; } 134 ScopedDecl *getDecl() { return TheDecl; } 135 136 virtual SourceRange getSourceRange() const { return SourceRange(); } 137 138 static bool classof(const Stmt *T) { 139 return T->getStmtClass() == DeclStmtClass; 140 } 141 static bool classof(const DeclStmt *) { return true; } 142 143 // Iterators 144 virtual child_iterator child_begin(); 145 virtual child_iterator child_end(); 146}; 147 148/// NullStmt - This is the null statement ";": C99 6.8.3p3. 149/// 150class NullStmt : public Stmt { 151 SourceLocation SemiLoc; 152public: 153 NullStmt(SourceLocation L) : Stmt(NullStmtClass), SemiLoc(L) {} 154 155 SourceLocation getSemiLoc() const { return SemiLoc; } 156 157 virtual SourceRange getSourceRange() const { return SourceRange(SemiLoc); } 158 159 static bool classof(const Stmt *T) { 160 return T->getStmtClass() == NullStmtClass; 161 } 162 static bool classof(const NullStmt *) { return true; } 163 164 // Iterators 165 virtual child_iterator child_begin(); 166 virtual child_iterator child_end(); 167}; 168 169/// CompoundStmt - This represents a group of statements like { stmt stmt }. 170/// 171class CompoundStmt : public Stmt { 172 llvm::SmallVector<Stmt*, 16> Body; 173 SourceLocation LBracLoc, RBracLoc; 174public: 175 CompoundStmt(Stmt **StmtStart, unsigned NumStmts, 176 SourceLocation LB, SourceLocation RB) 177 : Stmt(CompoundStmtClass), Body(StmtStart, StmtStart+NumStmts), 178 LBracLoc(LB), RBracLoc(RB) {} 179 180 bool body_empty() const { return Body.empty(); } 181 182 typedef llvm::SmallVector<Stmt*, 16>::iterator body_iterator; 183 body_iterator body_begin() { return Body.begin(); } 184 body_iterator body_end() { return Body.end(); } 185 Stmt *body_back() { return Body.back(); } 186 187 typedef llvm::SmallVector<Stmt*, 16>::const_iterator const_body_iterator; 188 const_body_iterator body_begin() const { return Body.begin(); } 189 const_body_iterator body_end() const { return Body.end(); } 190 const Stmt *body_back() const { return Body.back(); } 191 192 typedef llvm::SmallVector<Stmt*, 16>::reverse_iterator reverse_body_iterator; 193 reverse_body_iterator body_rbegin() { return Body.rbegin(); } 194 reverse_body_iterator body_rend() { return Body.rend(); } 195 196 typedef llvm::SmallVector<Stmt*, 16>::const_reverse_iterator 197 const_reverse_body_iterator; 198 const_reverse_body_iterator body_rbegin() const { return Body.rbegin(); } 199 const_reverse_body_iterator body_rend() const { return Body.rend(); } 200 201 void push_back(Stmt *S) { Body.push_back(S); } 202 203 virtual SourceRange getSourceRange() const { 204 return SourceRange(LBracLoc, RBracLoc); 205 } 206 static bool classof(const Stmt *T) { 207 return T->getStmtClass() == CompoundStmtClass; 208 } 209 static bool classof(const CompoundStmt *) { return true; } 210 211 // Iterators 212 virtual child_iterator child_begin(); 213 virtual child_iterator child_end(); 214}; 215 216// SwitchCase is the base class for CaseStmt and DefaultStmt, 217class SwitchCase : public Stmt { 218 // A pointer to the following CaseStmt or DefaultStmt class, 219 // used by SwitchStmt. 220 SwitchCase *NextSwitchCase; 221protected: 222 SwitchCase(StmtClass SC) : Stmt(SC), NextSwitchCase(0) {} 223 224public: 225 const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } 226 227 SwitchCase *getNextSwitchCase() { return NextSwitchCase; } 228 229 void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } 230 231 virtual Stmt* v_getSubStmt() = 0; 232 Stmt *getSubStmt() { return v_getSubStmt(); } 233 234 virtual SourceRange getSourceRange() const { return SourceRange(); } 235 236 static bool classof(const Stmt *T) { 237 return T->getStmtClass() == CaseStmtClass || 238 T->getStmtClass() == DefaultStmtClass; 239 } 240 static bool classof(const SwitchCase *) { return true; } 241}; 242 243class CaseStmt : public SwitchCase { 244 enum { SUBSTMT, LHS, RHS, END_EXPR }; 245 Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for 246 // GNU "case 1 ... 4" extension 247 SourceLocation CaseLoc; 248public: 249 CaseStmt(Expr *lhs, Expr *rhs, Stmt *substmt, SourceLocation caseLoc) 250 : SwitchCase(CaseStmtClass) { 251 SubExprs[SUBSTMT] = substmt; 252 SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs); 253 SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs); 254 CaseLoc = caseLoc; 255 } 256 257 Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); } 258 Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); } 259 Stmt *getSubStmt() { return SubExprs[SUBSTMT]; } 260 virtual Stmt* v_getSubStmt() { return getSubStmt(); } 261 262 virtual SourceRange getSourceRange() const { 263 return SourceRange(CaseLoc, SubExprs[SUBSTMT]->getLocEnd()); 264 } 265 static bool classof(const Stmt *T) { 266 return T->getStmtClass() == CaseStmtClass; 267 } 268 static bool classof(const CaseStmt *) { return true; } 269 270 // Iterators 271 virtual child_iterator child_begin(); 272 virtual child_iterator child_end(); 273}; 274 275class DefaultStmt : public SwitchCase { 276 Stmt* SubStmt; 277 SourceLocation DefaultLoc; 278public: 279 DefaultStmt(SourceLocation DL, Stmt *substmt) : 280 SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL) {} 281 282 Stmt *getSubStmt() { return SubStmt; } 283 virtual Stmt* v_getSubStmt() { return getSubStmt(); } 284 285 SourceLocation getDefaultLoc() const { return DefaultLoc; } 286 287 virtual SourceRange getSourceRange() const { 288 return SourceRange(DefaultLoc, SubStmt->getLocEnd()); 289 } 290 static bool classof(const Stmt *T) { 291 return T->getStmtClass() == DefaultStmtClass; 292 } 293 static bool classof(const DefaultStmt *) { return true; } 294 295 // Iterators 296 virtual child_iterator child_begin(); 297 virtual child_iterator child_end(); 298}; 299 300class LabelStmt : public Stmt { 301 IdentifierInfo *Label; 302 Stmt *SubStmt; 303 SourceLocation IdentLoc; 304public: 305 LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt) 306 : Stmt(LabelStmtClass), Label(label), 307 SubStmt(substmt), IdentLoc(IL) {} 308 309 SourceLocation getIdentLoc() const { return IdentLoc; } 310 IdentifierInfo *getID() const { return Label; } 311 const char *getName() const; 312 Stmt *getSubStmt() { return SubStmt; } 313 const Stmt *getSubStmt() const { return SubStmt; } 314 315 void setIdentLoc(SourceLocation L) { IdentLoc = L; } 316 void setSubStmt(Stmt *SS) { SubStmt = SS; } 317 318 virtual SourceRange getSourceRange() const { 319 return SourceRange(IdentLoc, SubStmt->getLocEnd()); 320 } 321 static bool classof(const Stmt *T) { 322 return T->getStmtClass() == LabelStmtClass; 323 } 324 static bool classof(const LabelStmt *) { return true; } 325 326 // Iterators 327 virtual child_iterator child_begin(); 328 virtual child_iterator child_end(); 329}; 330 331 332/// IfStmt - This represents an if/then/else. 333/// 334class IfStmt : public Stmt { 335 enum { COND, THEN, ELSE, END_EXPR }; 336 Stmt* SubExprs[END_EXPR]; 337 SourceLocation IfLoc; 338public: 339 IfStmt(SourceLocation IL, Expr *cond, Stmt *then, Stmt *elsev = 0) 340 : Stmt(IfStmtClass) { 341 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 342 SubExprs[THEN] = then; 343 SubExprs[ELSE] = elsev; 344 IfLoc = IL; 345 } 346 347 const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} 348 const Stmt *getThen() const { return SubExprs[THEN]; } 349 const Stmt *getElse() const { return SubExprs[ELSE]; } 350 351 Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } 352 Stmt *getThen() { return SubExprs[THEN]; } 353 Stmt *getElse() { return SubExprs[ELSE]; } 354 355 virtual SourceRange getSourceRange() const { 356 if (SubExprs[ELSE]) 357 return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd()); 358 else 359 return SourceRange(IfLoc, SubExprs[THEN]->getLocEnd()); 360 } 361 362 static bool classof(const Stmt *T) { 363 return T->getStmtClass() == IfStmtClass; 364 } 365 static bool classof(const IfStmt *) { return true; } 366 367 // Iterators 368 virtual child_iterator child_begin(); 369 virtual child_iterator child_end(); 370}; 371 372/// SwitchStmt - This represents a 'switch' stmt. 373/// 374class SwitchStmt : public Stmt { 375 enum { COND, BODY, END_EXPR }; 376 Stmt* SubExprs[END_EXPR]; 377 // This points to a linked list of case and default statements. 378 SwitchCase *FirstCase; 379 SourceLocation SwitchLoc; 380public: 381 SwitchStmt(Expr *cond) : Stmt(SwitchStmtClass), FirstCase(0) { 382 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 383 SubExprs[BODY] = NULL; 384 } 385 386 const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} 387 const Stmt *getBody() const { return SubExprs[BODY]; } 388 const SwitchCase *getSwitchCaseList() const { return FirstCase; } 389 390 Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);} 391 Stmt *getBody() { return SubExprs[BODY]; } 392 SwitchCase *getSwitchCaseList() { return FirstCase; } 393 394 void setBody(Stmt *S, SourceLocation SL) { 395 SubExprs[BODY] = S; 396 SwitchLoc = SL; 397 } 398 void addSwitchCase(SwitchCase *SC) { 399 if (FirstCase) 400 SC->setNextSwitchCase(FirstCase); 401 402 FirstCase = SC; 403 } 404 virtual SourceRange getSourceRange() const { 405 return SourceRange(SwitchLoc, SubExprs[BODY]->getLocEnd()); 406 } 407 static bool classof(const Stmt *T) { 408 return T->getStmtClass() == SwitchStmtClass; 409 } 410 static bool classof(const SwitchStmt *) { return true; } 411 412 // Iterators 413 virtual child_iterator child_begin(); 414 virtual child_iterator child_end(); 415}; 416 417 418/// WhileStmt - This represents a 'while' stmt. 419/// 420class WhileStmt : public Stmt { 421 enum { COND, BODY, END_EXPR }; 422 Stmt* SubExprs[END_EXPR]; 423 SourceLocation WhileLoc; 424public: 425 WhileStmt(Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) { 426 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 427 SubExprs[BODY] = body; 428 WhileLoc = WL; 429 } 430 431 Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } 432 const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} 433 Stmt *getBody() { return SubExprs[BODY]; } 434 const Stmt *getBody() const { return SubExprs[BODY]; } 435 436 virtual SourceRange getSourceRange() const { 437 return SourceRange(WhileLoc, SubExprs[BODY]->getLocEnd()); 438 } 439 static bool classof(const Stmt *T) { 440 return T->getStmtClass() == WhileStmtClass; 441 } 442 static bool classof(const WhileStmt *) { return true; } 443 444 // Iterators 445 virtual child_iterator child_begin(); 446 virtual child_iterator child_end(); 447}; 448 449/// DoStmt - This represents a 'do/while' stmt. 450/// 451class DoStmt : public Stmt { 452 enum { COND, BODY, END_EXPR }; 453 Stmt* SubExprs[END_EXPR]; 454 SourceLocation DoLoc; 455public: 456 DoStmt(Stmt *body, Expr *cond, SourceLocation DL) 457 : Stmt(DoStmtClass), DoLoc(DL) { 458 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 459 SubExprs[BODY] = body; 460 DoLoc = DL; 461 } 462 463 Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } 464 const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} 465 Stmt *getBody() { return SubExprs[BODY]; } 466 const Stmt *getBody() const { return SubExprs[BODY]; } 467 468 virtual SourceRange getSourceRange() const { 469 return SourceRange(DoLoc, SubExprs[BODY]->getLocEnd()); 470 } 471 static bool classof(const Stmt *T) { 472 return T->getStmtClass() == DoStmtClass; 473 } 474 static bool classof(const DoStmt *) { return true; } 475 476 // Iterators 477 virtual child_iterator child_begin(); 478 virtual child_iterator child_end(); 479}; 480 481 482/// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of 483/// the init/cond/inc parts of the ForStmt will be null if they were not 484/// specified in the source. 485/// 486class ForStmt : public Stmt { 487 enum { INIT, COND, INC, BODY, END_EXPR }; 488 Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. 489 SourceLocation ForLoc; 490public: 491 ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL) 492 : Stmt(ForStmtClass) { 493 SubExprs[INIT] = Init; 494 SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); 495 SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); 496 SubExprs[BODY] = Body; 497 ForLoc = FL; 498 } 499 500 Stmt *getInit() { return SubExprs[INIT]; } 501 Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } 502 Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } 503 Stmt *getBody() { return SubExprs[BODY]; } 504 505 const Stmt *getInit() const { return SubExprs[INIT]; } 506 const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} 507 const Expr *getInc() const { return reinterpret_cast<Expr*>(SubExprs[INC]); } 508 const Stmt *getBody() const { return SubExprs[BODY]; } 509 510 virtual SourceRange getSourceRange() const { 511 return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); 512 } 513 static bool classof(const Stmt *T) { 514 return T->getStmtClass() == ForStmtClass; 515 } 516 static bool classof(const ForStmt *) { return true; } 517 518 // Iterators 519 virtual child_iterator child_begin(); 520 virtual child_iterator child_end(); 521}; 522 523/// GotoStmt - This represents a direct goto. 524/// 525class GotoStmt : public Stmt { 526 LabelStmt *Label; 527 SourceLocation GotoLoc; 528 SourceLocation LabelLoc; 529public: 530 GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL) 531 : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} 532 533 LabelStmt *getLabel() const { return Label; } 534 535 virtual SourceRange getSourceRange() const { 536 return SourceRange(GotoLoc, LabelLoc); 537 } 538 static bool classof(const Stmt *T) { 539 return T->getStmtClass() == GotoStmtClass; 540 } 541 static bool classof(const GotoStmt *) { return true; } 542 543 // Iterators 544 virtual child_iterator child_begin(); 545 virtual child_iterator child_end(); 546}; 547 548/// IndirectGotoStmt - This represents an indirect goto. 549/// 550class IndirectGotoStmt : public Stmt { 551 Expr *Target; 552public: 553 IndirectGotoStmt(Expr *target) : Stmt(IndirectGotoStmtClass), Target(target){} 554 555 Expr *getTarget() { return Target; } 556 const Expr *getTarget() const { return Target; } 557 558 virtual SourceRange getSourceRange() const { return SourceRange(); } 559 560 static bool classof(const Stmt *T) { 561 return T->getStmtClass() == IndirectGotoStmtClass; 562 } 563 static bool classof(const IndirectGotoStmt *) { return true; } 564 565 // Iterators 566 virtual child_iterator child_begin(); 567 virtual child_iterator child_end(); 568}; 569 570 571/// ContinueStmt - This represents a continue. 572/// 573class ContinueStmt : public Stmt { 574 SourceLocation ContinueLoc; 575public: 576 ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} 577 578 virtual SourceRange getSourceRange() const { 579 return SourceRange(ContinueLoc); 580 } 581 static bool classof(const Stmt *T) { 582 return T->getStmtClass() == ContinueStmtClass; 583 } 584 static bool classof(const ContinueStmt *) { return true; } 585 586 // Iterators 587 virtual child_iterator child_begin(); 588 virtual child_iterator child_end(); 589}; 590 591/// BreakStmt - This represents a break. 592/// 593class BreakStmt : public Stmt { 594 SourceLocation BreakLoc; 595public: 596 BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {} 597 598 virtual SourceRange getSourceRange() const { return SourceRange(BreakLoc); } 599 600 static bool classof(const Stmt *T) { 601 return T->getStmtClass() == BreakStmtClass; 602 } 603 static bool classof(const BreakStmt *) { return true; } 604 605 // Iterators 606 virtual child_iterator child_begin(); 607 virtual child_iterator child_end(); 608}; 609 610 611/// ReturnStmt - This represents a return, optionally of an expression. 612/// 613class ReturnStmt : public Stmt { 614 Expr *RetExpr; 615 SourceLocation RetLoc; 616public: 617 ReturnStmt(SourceLocation RL, Expr *E = 0) : Stmt(ReturnStmtClass), 618 RetExpr(E), RetLoc(RL) {} 619 620 const Expr *getRetValue() const { return RetExpr; } 621 Expr *getRetValue() { return RetExpr; } 622 623 virtual SourceRange getSourceRange() const; 624 625 static bool classof(const Stmt *T) { 626 return T->getStmtClass() == ReturnStmtClass; 627 } 628 static bool classof(const ReturnStmt *) { return true; } 629 630 // Iterators 631 virtual child_iterator child_begin(); 632 virtual child_iterator child_end(); 633}; 634 635} // end namespace clang 636 637#endif 638