ExprObjC.h revision c2350e553b853ad00914faf23fa731e5fc4a8a5c
1//===--- ExprObjC.h - Classes for representing ObjC expressions -*- 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 ExprObjC interface and subclasses. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_AST_EXPROBJC_H 15#define LLVM_CLANG_AST_EXPROBJC_H 16 17#include "clang/AST/Expr.h" 18#include "clang/Basic/IdentifierTable.h" 19 20namespace clang { 21 class IdentifierInfo; 22 class ASTContext; 23 class ObjCMethodDecl; 24 class ObjCPropertyDecl; 25 26/// ObjCStringLiteral, used for Objective-C string literals 27/// i.e. @"foo". 28class ObjCStringLiteral : public Expr { 29 Stmt *String; 30 SourceLocation AtLoc; 31public: 32 ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) 33 : Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {} 34 explicit ObjCStringLiteral(EmptyShell Empty) 35 : Expr(ObjCStringLiteralClass, Empty) {} 36 37 StringLiteral *getString() { return cast<StringLiteral>(String); } 38 const StringLiteral *getString() const { return cast<StringLiteral>(String); } 39 void setString(StringLiteral *S) { String = S; } 40 41 SourceLocation getAtLoc() const { return AtLoc; } 42 void setAtLoc(SourceLocation L) { AtLoc = L; } 43 44 virtual SourceRange getSourceRange() const { 45 return SourceRange(AtLoc, String->getLocEnd()); 46 } 47 48 static bool classof(const Stmt *T) { 49 return T->getStmtClass() == ObjCStringLiteralClass; 50 } 51 static bool classof(const ObjCStringLiteral *) { return true; } 52 53 // Iterators 54 virtual child_iterator child_begin(); 55 virtual child_iterator child_end(); 56}; 57 58/// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type 59/// and behavior as StringLiteral except that the string initializer is obtained 60/// from ASTContext with the encoding type as an argument. 61class ObjCEncodeExpr : public Expr { 62 QualType EncType; 63 SourceLocation AtLoc, RParenLoc; 64public: 65 ObjCEncodeExpr(QualType T, QualType ET, 66 SourceLocation at, SourceLocation rp) 67 : Expr(ObjCEncodeExprClass, T, ET->isDependentType(), 68 ET->isDependentType()), EncType(ET), AtLoc(at), RParenLoc(rp) {} 69 70 explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} 71 72 73 SourceLocation getAtLoc() const { return AtLoc; } 74 void setAtLoc(SourceLocation L) { AtLoc = L; } 75 SourceLocation getRParenLoc() const { return RParenLoc; } 76 void setRParenLoc(SourceLocation L) { RParenLoc = L; } 77 78 QualType getEncodedType() const { return EncType; } 79 void setEncodedType(QualType T) { EncType = T; } 80 81 82 virtual SourceRange getSourceRange() const { 83 return SourceRange(AtLoc, RParenLoc); 84 } 85 86 static bool classof(const Stmt *T) { 87 return T->getStmtClass() == ObjCEncodeExprClass; 88 } 89 static bool classof(const ObjCEncodeExpr *) { return true; } 90 91 // Iterators 92 virtual child_iterator child_begin(); 93 virtual child_iterator child_end(); 94}; 95 96/// ObjCSelectorExpr used for @selector in Objective-C. 97class ObjCSelectorExpr : public Expr { 98 Selector SelName; 99 SourceLocation AtLoc, RParenLoc; 100public: 101 ObjCSelectorExpr(QualType T, Selector selInfo, 102 SourceLocation at, SourceLocation rp) 103 : Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at), 104 RParenLoc(rp){} 105 explicit ObjCSelectorExpr(EmptyShell Empty) 106 : Expr(ObjCSelectorExprClass, Empty) {} 107 108 Selector getSelector() const { return SelName; } 109 void setSelector(Selector S) { SelName = S; } 110 111 SourceLocation getAtLoc() const { return AtLoc; } 112 SourceLocation getRParenLoc() const { return RParenLoc; } 113 void setAtLoc(SourceLocation L) { AtLoc = L; } 114 void setRParenLoc(SourceLocation L) { RParenLoc = L; } 115 116 virtual SourceRange getSourceRange() const { 117 return SourceRange(AtLoc, RParenLoc); 118 } 119 120 /// getNumArgs - Return the number of actual arguments to this call. 121 unsigned getNumArgs() const { return SelName.getNumArgs(); } 122 123 static bool classof(const Stmt *T) { 124 return T->getStmtClass() == ObjCSelectorExprClass; 125 } 126 static bool classof(const ObjCSelectorExpr *) { return true; } 127 128 // Iterators 129 virtual child_iterator child_begin(); 130 virtual child_iterator child_end(); 131}; 132 133/// ObjCProtocolExpr used for protocol expression in Objective-C. This is used 134/// as: @protocol(foo), as in: 135/// obj conformsToProtocol:@protocol(foo)] 136/// The return type is "Protocol*". 137class ObjCProtocolExpr : public Expr { 138 ObjCProtocolDecl *TheProtocol; 139 SourceLocation AtLoc, RParenLoc; 140public: 141 ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, 142 SourceLocation at, SourceLocation rp) 143 : Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol), 144 AtLoc(at), RParenLoc(rp) {} 145 explicit ObjCProtocolExpr(EmptyShell Empty) 146 : Expr(ObjCProtocolExprClass, Empty) {} 147 148 ObjCProtocolDecl *getProtocol() const { return TheProtocol; } 149 void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } 150 151 SourceLocation getAtLoc() const { return AtLoc; } 152 SourceLocation getRParenLoc() const { return RParenLoc; } 153 void setAtLoc(SourceLocation L) { AtLoc = L; } 154 void setRParenLoc(SourceLocation L) { RParenLoc = L; } 155 156 virtual SourceRange getSourceRange() const { 157 return SourceRange(AtLoc, RParenLoc); 158 } 159 160 static bool classof(const Stmt *T) { 161 return T->getStmtClass() == ObjCProtocolExprClass; 162 } 163 static bool classof(const ObjCProtocolExpr *) { return true; } 164 165 // Iterators 166 virtual child_iterator child_begin(); 167 virtual child_iterator child_end(); 168}; 169 170/// ObjCIvarRefExpr - A reference to an ObjC instance variable. 171class ObjCIvarRefExpr : public Expr { 172 class ObjCIvarDecl *D; 173 SourceLocation Loc; 174 Stmt *Base; 175 bool IsArrow:1; // True if this is "X->F", false if this is "X.F". 176 bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). 177 178public: 179 ObjCIvarRefExpr(ObjCIvarDecl *d, 180 QualType t, SourceLocation l, Expr *base=0, 181 bool arrow = false, bool freeIvar = false) : 182 Expr(ObjCIvarRefExprClass, t, false, false), D(d), 183 Loc(l), Base(base), IsArrow(arrow), 184 IsFreeIvar(freeIvar) {} 185 186 explicit ObjCIvarRefExpr(EmptyShell Empty) 187 : Expr(ObjCIvarRefExprClass, Empty) {} 188 189 ObjCIvarDecl *getDecl() { return D; } 190 const ObjCIvarDecl *getDecl() const { return D; } 191 void setDecl(ObjCIvarDecl *d) { D = d; } 192 193 const Expr *getBase() const { return cast<Expr>(Base); } 194 Expr *getBase() { return cast<Expr>(Base); } 195 void setBase(Expr * base) { Base = base; } 196 197 bool isArrow() const { return IsArrow; } 198 bool isFreeIvar() const { return IsFreeIvar; } 199 void setIsArrow(bool A) { IsArrow = A; } 200 void setIsFreeIvar(bool A) { IsFreeIvar = A; } 201 202 SourceLocation getLocation() const { return Loc; } 203 void setLocation(SourceLocation L) { Loc = L; } 204 205 virtual SourceRange getSourceRange() const { 206 return isFreeIvar() ? SourceRange(Loc) 207 : SourceRange(getBase()->getLocStart(), Loc); 208 } 209 210 static bool classof(const Stmt *T) { 211 return T->getStmtClass() == ObjCIvarRefExprClass; 212 } 213 static bool classof(const ObjCIvarRefExpr *) { return true; } 214 215 // Iterators 216 virtual child_iterator child_begin(); 217 virtual child_iterator child_end(); 218}; 219 220/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC 221/// property. 222/// 223class ObjCPropertyRefExpr : public Expr { 224private: 225 ObjCPropertyDecl *AsProperty; 226 SourceLocation IdLoc; 227 Stmt *Base; 228public: 229 ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, 230 SourceLocation l, Expr *base) 231 : Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD), 232 IdLoc(l), Base(base) { 233 } 234 235 explicit ObjCPropertyRefExpr(EmptyShell Empty) 236 : Expr(ObjCPropertyRefExprClass, Empty) {} 237 238 ObjCPropertyDecl *getProperty() const { return AsProperty; } 239 void setProperty(ObjCPropertyDecl *D) { AsProperty = D; } 240 241 const Expr *getBase() const { return cast<Expr>(Base); } 242 Expr *getBase() { return cast<Expr>(Base); } 243 void setBase(Expr *base) { Base = base; } 244 245 SourceLocation getLocation() const { return IdLoc; } 246 void setLocation(SourceLocation L) { IdLoc = L; } 247 248 virtual SourceRange getSourceRange() const { 249 return SourceRange(getBase()->getLocStart(), IdLoc); 250 } 251 252 static bool classof(const Stmt *T) { 253 return T->getStmtClass() == ObjCPropertyRefExprClass; 254 } 255 static bool classof(const ObjCPropertyRefExpr *) { return true; } 256 257 // Iterators 258 virtual child_iterator child_begin(); 259 virtual child_iterator child_end(); 260}; 261 262/// ObjCImplicitSetterGetterRefExpr - A dot-syntax expression to access two 263/// methods; one to set a value to an 'ivar' (Setter) and the other to access 264/// an 'ivar' (Setter). 265/// An example for use of this AST is: 266/// @code 267/// @interface Test { } 268/// - (Test *)crash; 269/// - (void)setCrash: (Test*)value; 270/// @end 271/// void foo(Test *p1, Test *p2) 272/// { 273/// p2.crash = p1.crash; // Uses ObjCImplicitSetterGetterRefExpr AST 274/// } 275/// @endcode 276class ObjCImplicitSetterGetterRefExpr : public Expr { 277 /// Setter - Setter method user declared for setting its 'ivar' to a value 278 ObjCMethodDecl *Setter; 279 /// Getter - Getter method user declared for accessing 'ivar' it controls. 280 ObjCMethodDecl *Getter; 281 /// Location of the member in the dot syntax notation. This is location 282 /// of the getter method. 283 SourceLocation MemberLoc; 284 // FIXME: Swizzle these into a single pointer. 285 Stmt *Base; 286 ObjCInterfaceDecl *InterfaceDecl; 287 /// Location of the receiver class in the dot syntax notation 288 /// used to call a class method setter/getter. 289 SourceLocation ClassLoc; 290 291public: 292 ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, 293 QualType t, 294 ObjCMethodDecl *setter, 295 SourceLocation l, Expr *base) 296 : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), 297 Setter(setter), Getter(getter), MemberLoc(l), Base(base), 298 InterfaceDecl(0), ClassLoc(SourceLocation()) { 299 } 300 ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter, 301 QualType t, 302 ObjCMethodDecl *setter, 303 SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL) 304 : Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false), 305 Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), 306 ClassLoc(CL) { 307 } 308 explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty) 309 : Expr(ObjCImplicitSetterGetterRefExprClass, Empty){} 310 311 ObjCMethodDecl *getGetterMethod() const { return Getter; } 312 ObjCMethodDecl *getSetterMethod() const { return Setter; } 313 ObjCInterfaceDecl *getInterfaceDecl() const { return InterfaceDecl; } 314 void setGetterMethod(ObjCMethodDecl *D) { Getter = D; } 315 void setSetterMethod(ObjCMethodDecl *D) { Setter = D; } 316 void setInterfaceDecl(ObjCInterfaceDecl *D) { InterfaceDecl = D; } 317 318 virtual SourceRange getSourceRange() const { 319 if (Base) 320 return SourceRange(getBase()->getLocStart(), MemberLoc); 321 return SourceRange(ClassLoc, MemberLoc); 322 } 323 const Expr *getBase() const { return cast_or_null<Expr>(Base); } 324 Expr *getBase() { return cast_or_null<Expr>(Base); } 325 void setBase(Expr *base) { Base = base; } 326 327 SourceLocation getLocation() const { return MemberLoc; } 328 void setLocation(SourceLocation L) { MemberLoc = L; } 329 SourceLocation getClassLoc() const { return ClassLoc; } 330 void setClassLoc(SourceLocation L) { ClassLoc = L; } 331 332 static bool classof(const Stmt *T) { 333 return T->getStmtClass() == ObjCImplicitSetterGetterRefExprClass; 334 } 335 static bool classof(const ObjCImplicitSetterGetterRefExpr *) { return true; } 336 337 // Iterators 338 virtual child_iterator child_begin(); 339 virtual child_iterator child_end(); 340}; 341 342class ObjCMessageExpr : public Expr { 343 // SubExprs - The receiver and arguments of the message expression. 344 Stmt **SubExprs; 345 346 // NumArgs - The number of arguments (not including the receiver) to the 347 // message expression. 348 unsigned NumArgs; 349 350 /// \brief The location of the class name in a class message. 351 SourceLocation ClassNameLoc; 352 353 // A unigue name for this message. 354 Selector SelName; 355 356 // A method prototype for this message (optional). 357 // FIXME: Since method decls contain the selector, and most messages have a 358 // prototype, consider devising a scheme for unifying SelName/MethodProto. 359 ObjCMethodDecl *MethodProto; 360 361 SourceLocation LBracloc, RBracloc; 362 363 // Constants for indexing into SubExprs. 364 enum { RECEIVER=0, ARGS_START=1 }; 365 366 // Bit-swizzling flags. 367 enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; 368 unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } 369 370public: 371 /// This constructor is used to represent class messages where the 372 /// ObjCInterfaceDecl* of the receiver is not known. 373 ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, 374 SourceLocation clsNameLoc, Selector selInfo, 375 QualType retType, ObjCMethodDecl *methDecl, 376 SourceLocation LBrac, SourceLocation RBrac, 377 Expr **ArgExprs, unsigned NumArgs); 378 379 /// This constructor is used to represent class messages where the 380 /// ObjCInterfaceDecl* of the receiver is known. 381 // FIXME: clsName should be typed to ObjCInterfaceType 382 ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls, 383 SourceLocation clsNameLoc, Selector selInfo, 384 QualType retType, ObjCMethodDecl *methDecl, 385 SourceLocation LBrac, SourceLocation RBrac, 386 Expr **ArgExprs, unsigned NumArgs); 387 388 // constructor for instance messages. 389 ObjCMessageExpr(ASTContext &C, Expr *receiver, Selector selInfo, 390 QualType retType, ObjCMethodDecl *methDecl, 391 SourceLocation LBrac, SourceLocation RBrac, 392 Expr **ArgExprs, unsigned NumArgs); 393 394 explicit ObjCMessageExpr(EmptyShell Empty) 395 : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {} 396 397 virtual void DoDestroy(ASTContext &C); 398 399 /// getReceiver - Returns the receiver of the message expression. 400 /// This can be NULL if the message is for class methods. For 401 /// class methods, use getClassName. 402 /// FIXME: need to handle/detect 'super' usage within a class method. 403 Expr *getReceiver() { 404 uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; 405 return (x & Flags) == IsInstMeth ? (Expr*) x : 0; 406 } 407 const Expr *getReceiver() const { 408 return const_cast<ObjCMessageExpr*>(this)->getReceiver(); 409 } 410 // FIXME: need setters for different receiver types. 411 void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; } 412 Selector getSelector() const { return SelName; } 413 void setSelector(Selector S) { SelName = S; } 414 415 const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } 416 ObjCMethodDecl *getMethodDecl() { return MethodProto; } 417 void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; } 418 419 /// \brief Describes the class receiver of a message send. 420 struct ClassInfo { 421 /// \brief The interface declaration for the class that is 422 /// receiving the message. May be NULL. 423 ObjCInterfaceDecl *Decl; 424 425 /// \brief The name of the class that is receiving the 426 /// message. This will never be NULL. 427 IdentifierInfo *Name; 428 429 /// \brief The source location of the class name. 430 SourceLocation Loc; 431 432 ClassInfo() : Decl(0), Name(0), Loc() { } 433 434 ClassInfo(ObjCInterfaceDecl *Decl, IdentifierInfo *Name, SourceLocation Loc) 435 : Decl(Decl), Name(Name), Loc(Loc) { } 436 }; 437 438 /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl* 439 /// and IdentifierInfo* of the invoked class. Both can be NULL if this 440 /// is an instance message, and the ObjCInterfaceDecl* can be NULL if none 441 /// was available when this ObjCMessageExpr object was constructed. 442 ClassInfo getClassInfo() const; 443 void setClassInfo(const ClassInfo &C); 444 445 /// getClassName - For class methods, this returns the invoked class, 446 /// and returns NULL otherwise. For instance methods, use getReceiver. 447 IdentifierInfo *getClassName() const { 448 return getClassInfo().Name; 449 } 450 451 /// getNumArgs - Return the number of actual arguments to this call. 452 unsigned getNumArgs() const { return NumArgs; } 453 void setNumArgs(unsigned nArgs) { 454 NumArgs = nArgs; 455 // FIXME: should always allocate SubExprs via the ASTContext's 456 // allocator. 457 if (!SubExprs) 458 SubExprs = new Stmt* [NumArgs + 1]; 459 } 460 461 /// getArg - Return the specified argument. 462 Expr *getArg(unsigned Arg) { 463 assert(Arg < NumArgs && "Arg access out of range!"); 464 return cast<Expr>(SubExprs[Arg+ARGS_START]); 465 } 466 const Expr *getArg(unsigned Arg) const { 467 assert(Arg < NumArgs && "Arg access out of range!"); 468 return cast<Expr>(SubExprs[Arg+ARGS_START]); 469 } 470 /// setArg - Set the specified argument. 471 void setArg(unsigned Arg, Expr *ArgExpr) { 472 assert(Arg < NumArgs && "Arg access out of range!"); 473 SubExprs[Arg+ARGS_START] = ArgExpr; 474 } 475 476 SourceLocation getLeftLoc() const { return LBracloc; } 477 SourceLocation getRightLoc() const { return RBracloc; } 478 479 void setLeftLoc(SourceLocation L) { LBracloc = L; } 480 void setRightLoc(SourceLocation L) { RBracloc = L; } 481 482 void setSourceRange(SourceRange R) { 483 LBracloc = R.getBegin(); 484 RBracloc = R.getEnd(); 485 } 486 virtual SourceRange getSourceRange() const { 487 return SourceRange(LBracloc, RBracloc); 488 } 489 490 static bool classof(const Stmt *T) { 491 return T->getStmtClass() == ObjCMessageExprClass; 492 } 493 static bool classof(const ObjCMessageExpr *) { return true; } 494 495 // Iterators 496 virtual child_iterator child_begin(); 497 virtual child_iterator child_end(); 498 499 typedef ExprIterator arg_iterator; 500 typedef ConstExprIterator const_arg_iterator; 501 502 arg_iterator arg_begin() { return &SubExprs[ARGS_START]; } 503 arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; } 504 const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; } 505 const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; } 506}; 507 508/// ObjCSuperExpr - Represents the "super" expression in Objective-C, 509/// which refers to the object on which the current method is executing. 510class ObjCSuperExpr : public Expr { 511 SourceLocation Loc; 512public: 513 ObjCSuperExpr(SourceLocation L, QualType Type) 514 : Expr(ObjCSuperExprClass, Type, false, false), Loc(L) { } 515 explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {} 516 517 SourceLocation getLoc() const { return Loc; } 518 void setLoc(SourceLocation L) { Loc = L; } 519 520 virtual SourceRange getSourceRange() const { return SourceRange(Loc); } 521 522 static bool classof(const Stmt *T) { 523 return T->getStmtClass() == ObjCSuperExprClass; 524 } 525 static bool classof(const ObjCSuperExpr *) { return true; } 526 527 // Iterators 528 virtual child_iterator child_begin(); 529 virtual child_iterator child_end(); 530}; 531 532/// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. 533/// (similiar in spirit to MemberExpr). 534class ObjCIsaExpr : public Expr { 535 /// Base - the expression for the base object pointer. 536 Stmt *Base; 537 538 /// IsaMemberLoc - This is the location of the 'isa'. 539 SourceLocation IsaMemberLoc; 540 541 /// IsArrow - True if this is "X->F", false if this is "X.F". 542 bool IsArrow; 543public: 544 ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty) 545 : Expr(ObjCIsaExprClass, ty, false, false), 546 Base(base), IsaMemberLoc(l), IsArrow(isarrow) {} 547 548 /// \brief Build an empty expression. 549 explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) { } 550 551 void setBase(Expr *E) { Base = E; } 552 Expr *getBase() const { return cast<Expr>(Base); } 553 554 bool isArrow() const { return IsArrow; } 555 void setArrow(bool A) { IsArrow = A; } 556 557 /// getMemberLoc - Return the location of the "member", in X->F, it is the 558 /// location of 'F'. 559 SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } 560 void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } 561 562 virtual SourceRange getSourceRange() const { 563 return SourceRange(getBase()->getLocStart(), IsaMemberLoc); 564 } 565 566 virtual SourceLocation getExprLoc() const { return IsaMemberLoc; } 567 568 static bool classof(const Stmt *T) { 569 return T->getStmtClass() == ObjCIsaExprClass; 570 } 571 static bool classof(const ObjCIsaExpr *) { return true; } 572 573 // Iterators 574 virtual child_iterator child_begin(); 575 virtual child_iterator child_end(); 576}; 577 578} // end namespace clang 579 580#endif 581