//===--- ExprObjC.h - Classes for representing ObjC expressions -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the ExprObjC interface and subclasses. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXPROBJC_H #define LLVM_CLANG_AST_EXPROBJC_H #include "clang/AST/Expr.h" #include "clang/Basic/IdentifierTable.h" namespace clang { class IdentifierInfo; class ASTContext; class ObjCMethodDecl; class ObjCPropertyDecl; /// ObjCStringLiteral, used for Objective-C string literals /// i.e. @"foo". class ObjCStringLiteral : public Expr { Stmt *String; SourceLocation AtLoc; public: ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) : Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {} explicit ObjCStringLiteral(EmptyShell Empty) : Expr(ObjCStringLiteralClass, Empty) {} StringLiteral *getString() { return cast(String); } const StringLiteral *getString() const { return cast(String); } void setString(StringLiteral *S) { String = S; } SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, String->getLocEnd()); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCStringLiteralClass; } static bool classof(const ObjCStringLiteral *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ObjCEncodeExpr, used for @encode in Objective-C. @encode has the same type /// and behavior as StringLiteral except that the string initializer is obtained /// from ASTContext with the encoding type as an argument. class ObjCEncodeExpr : public Expr { QualType EncType; SourceLocation AtLoc, RParenLoc; public: ObjCEncodeExpr(QualType T, QualType ET, SourceLocation at, SourceLocation rp) : Expr(ObjCEncodeExprClass, T), EncType(ET), AtLoc(at), RParenLoc(rp) {} explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } QualType getEncodedType() const { return EncType; } void setEncodedType(QualType T) { EncType = T; } virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCEncodeExprClass; } static bool classof(const ObjCEncodeExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ObjCSelectorExpr used for @selector in Objective-C. class ObjCSelectorExpr : public Expr { Selector SelName; SourceLocation AtLoc, RParenLoc; public: ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, SourceLocation rp) : Expr(ObjCSelectorExprClass, T), SelName(selInfo), AtLoc(at), RParenLoc(rp){} explicit ObjCSelectorExpr(EmptyShell Empty) : Expr(ObjCSelectorExprClass, Empty) {} Selector getSelector() const { return SelName; } void setSelector(Selector S) { SelName = S; } SourceLocation getAtLoc() const { return AtLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return SelName.getNumArgs(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSelectorExprClass; } static bool classof(const ObjCSelectorExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ObjCProtocolExpr used for protocol expression in Objective-C. This is used /// as: @protocol(foo), as in: /// obj conformsToProtocol:@protocol(foo)] /// The return type is "Protocol*". class ObjCProtocolExpr : public Expr { ObjCProtocolDecl *Protocol; SourceLocation AtLoc, RParenLoc; public: ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, SourceLocation rp) : Expr(ObjCProtocolExprClass, T), Protocol(protocol), AtLoc(at), RParenLoc(rp) {} explicit ObjCProtocolExpr(EmptyShell Empty) : Expr(ObjCProtocolExprClass, Empty) {} ObjCProtocolDecl *getProtocol() const { return Protocol; } void setProtocol(ObjCProtocolDecl *P) { Protocol = P; } SourceLocation getAtLoc() const { return AtLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(AtLoc, RParenLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCProtocolExprClass; } static bool classof(const ObjCProtocolExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ObjCIvarRefExpr - A reference to an ObjC instance variable. class ObjCIvarRefExpr : public Expr { class ObjCIvarDecl *D; SourceLocation Loc; Stmt *Base; bool IsArrow:1; // True if this is "X->F", false if this is "X.F". bool IsFreeIvar:1; // True if ivar reference has no base (self assumed). public: ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, Expr *base=0, bool arrow = false, bool freeIvar = false) : Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow), IsFreeIvar(freeIvar) {} explicit ObjCIvarRefExpr(EmptyShell Empty) : Expr(ObjCIvarRefExprClass, Empty) {} ObjCIvarDecl *getDecl() { return D; } const ObjCIvarDecl *getDecl() const { return D; } void setDecl(ObjCIvarDecl *d) { D = d; } const Expr *getBase() const { return cast(Base); } Expr *getBase() { return cast(Base); } void setBase(Expr * base) { Base = base; } bool isArrow() const { return IsArrow; } bool isFreeIvar() const { return IsFreeIvar; } void setIsArrow(bool A) { IsArrow = A; } void setIsFreeIvar(bool A) { IsFreeIvar = A; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const { return isFreeIvar() ? SourceRange(Loc) : SourceRange(getBase()->getLocStart(), Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCIvarRefExprClass; } static bool classof(const ObjCIvarRefExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC /// property. /// class ObjCPropertyRefExpr : public Expr { private: ObjCPropertyDecl *AsProperty; SourceLocation IdLoc; Stmt *Base; public: ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, SourceLocation l, Expr *base) : Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) { } explicit ObjCPropertyRefExpr(EmptyShell Empty) : Expr(ObjCPropertyRefExprClass, Empty) {} ObjCPropertyDecl *getProperty() const { return AsProperty; } void setProperty(ObjCPropertyDecl *D) { AsProperty = D; } const Expr *getBase() const { return cast(Base); } Expr *getBase() { return cast(Base); } void setBase(Expr *base) { Base = base; } SourceLocation getLocation() const { return IdLoc; } void setLocation(SourceLocation L) { IdLoc = L; } virtual SourceRange getSourceRange() const { return SourceRange(getBase()->getLocStart(), IdLoc); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCPropertyRefExprClass; } static bool classof(const ObjCPropertyRefExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; /// ObjCKVCRefExpr - A dot-syntax expression to access "implicit" properties /// (i.e. methods following the property naming convention). KVC stands for /// Key Value Encoding, a generic concept for accessing or setting a 'Key' /// value for an object. /// class ObjCKVCRefExpr : public Expr { ObjCMethodDecl *Setter; ObjCMethodDecl *Getter; SourceLocation Loc; // FIXME: Swizzle these into a single pointer. Stmt *Base; ObjCInterfaceDecl *ClassProp; SourceLocation ClassLoc; public: ObjCKVCRefExpr(ObjCMethodDecl *getter, QualType t, ObjCMethodDecl *setter, SourceLocation l, Expr *base) : Expr(ObjCKVCRefExprClass, t), Setter(setter), Getter(getter), Loc(l), Base(base), ClassProp(0), ClassLoc(SourceLocation()) { } ObjCKVCRefExpr(ObjCMethodDecl *getter, QualType t, ObjCMethodDecl *setter, SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL) : Expr(ObjCKVCRefExprClass, t), Setter(setter), Getter(getter), Loc(l), Base(0), ClassProp(C), ClassLoc(CL) { } explicit ObjCKVCRefExpr(EmptyShell Empty) : Expr(ObjCKVCRefExprClass, Empty){} ObjCMethodDecl *getGetterMethod() const { return Getter; } ObjCMethodDecl *getSetterMethod() const { return Setter; } ObjCInterfaceDecl *getClassProp() const { return ClassProp; } void setGetterMethod(ObjCMethodDecl *D) { Getter = D; } void setSetterMethod(ObjCMethodDecl *D) { Setter = D; } void setClassProp(ObjCInterfaceDecl *D) { ClassProp = D; } virtual SourceRange getSourceRange() const { if (Base) return SourceRange(getBase()->getLocStart(), Loc); return SourceRange(ClassLoc, Loc); } const Expr *getBase() const { return cast_or_null(Base); } Expr *getBase() { return cast_or_null(Base); } void setBase(Expr *base) { Base = base; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } SourceLocation getClassLoc() const { return ClassLoc; } void setClassLoc(SourceLocation L) { ClassLoc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCKVCRefExprClass; } static bool classof(const ObjCKVCRefExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; class ObjCMessageExpr : public Expr { // SubExprs - The receiver and arguments of the message expression. Stmt **SubExprs; // NumArgs - The number of arguments (not including the receiver) to the // message expression. unsigned NumArgs; // A unigue name for this message. Selector SelName; // A method prototype for this message (optional). // FIXME: Since method decls contain the selector, and most messages have a // prototype, consider devising a scheme for unifying SelName/MethodProto. ObjCMethodDecl *MethodProto; SourceLocation LBracloc, RBracloc; // Constants for indexing into SubExprs. enum { RECEIVER=0, ARGS_START=1 }; // Bit-swizzling flags. enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } public: /// This constructor is used to represent class messages where the /// ObjCInterfaceDecl* of the receiver is not known. ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); /// This constructor is used to represent class messages where the /// ObjCInterfaceDecl* of the receiver is known. // FIXME: clsName should be typed to ObjCInterfaceType ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); // constructor for instance messages. ObjCMessageExpr(Expr *receiver, Selector selInfo, QualType retType, ObjCMethodDecl *methDecl, SourceLocation LBrac, SourceLocation RBrac, Expr **ArgExprs, unsigned NumArgs); explicit ObjCMessageExpr(EmptyShell Empty) : Expr(ObjCMessageExprClass, Empty), SubExprs(0), NumArgs(0) {} ~ObjCMessageExpr() { delete [] SubExprs; } /// getReceiver - Returns the receiver of the message expression. /// This can be NULL if the message is for class methods. For /// class methods, use getClassName. /// FIXME: need to handle/detect 'super' usage within a class method. Expr *getReceiver() { uintptr_t x = (uintptr_t) SubExprs[RECEIVER]; return (x & Flags) == IsInstMeth ? (Expr*) x : 0; } const Expr *getReceiver() const { return const_cast(this)->getReceiver(); } // FIXME: need setters for different receiver types. void setReceiver(Expr *rec) { SubExprs[RECEIVER] = rec; } Selector getSelector() const { return SelName; } void setSelector(Selector S) { SelName = S; } const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } ObjCMethodDecl *getMethodDecl() { return MethodProto; } void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; } typedef std::pair ClassInfo; /// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl* /// and IdentifierInfo* of the invoked class. Both can be NULL if this /// is an instance message, and the ObjCInterfaceDecl* can be NULL if none /// was available when this ObjCMessageExpr object was constructed. ClassInfo getClassInfo() const; void setClassInfo(const ClassInfo &C); /// getClassName - For class methods, this returns the invoked class, /// and returns NULL otherwise. For instance methods, use getReceiver. IdentifierInfo *getClassName() const { return getClassInfo().second; } /// getNumArgs - Return the number of actual arguments to this call. unsigned getNumArgs() const { return NumArgs; } void setNumArgs(unsigned nArgs) { NumArgs = nArgs; // FIXME: should always allocate SubExprs via the ASTContext's // allocator. if (!SubExprs) SubExprs = new Stmt* [NumArgs + 1]; } /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); return cast(SubExprs[Arg+ARGS_START]); } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); return cast(SubExprs[Arg+ARGS_START]); } /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); SubExprs[Arg+ARGS_START] = ArgExpr; } SourceLocation getLeftLoc() const { return LBracloc; } SourceLocation getRightLoc() const { return RBracloc; } void setLeftLoc(SourceLocation L) { LBracloc = L; } void setRightLoc(SourceLocation L) { RBracloc = L; } void setSourceRange(SourceRange R) { LBracloc = R.getBegin(); RBracloc = R.getEnd(); } virtual SourceRange getSourceRange() const { return SourceRange(LBracloc, RBracloc); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCMessageExprClass; } static bool classof(const ObjCMessageExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; arg_iterator arg_begin() { return &SubExprs[ARGS_START]; } arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; } const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; } const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; } }; /// ObjCSuperExpr - Represents the "super" expression in Objective-C, /// which refers to the object on which the current method is executing. class ObjCSuperExpr : public Expr { SourceLocation Loc; public: ObjCSuperExpr(SourceLocation L, QualType Type) : Expr(ObjCSuperExprClass, Type), Loc(L) { } explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {} SourceLocation getLoc() const { return Loc; } void setLoc(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const { return SourceRange(Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCSuperExprClass; } static bool classof(const ObjCSuperExpr *) { return true; } // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); }; } // end namespace clang #endif