diff options
Diffstat (limited to 'include/clang/AST/ExprObjC.h')
-rw-r--r-- | include/clang/AST/ExprObjC.h | 423 |
1 files changed, 312 insertions, 111 deletions
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 9c28be76e5..dfb842a3d0 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -344,151 +344,352 @@ public: }; class ObjCMessageExpr : public Expr { - // SubExprs - The receiver and arguments of the message expression. - Stmt **SubExprs; + /// \brief The number of arguments in the message send, not + /// including the receiver. + unsigned NumArgs : 16; + + /// \brief The kind of message send this is, which is one of the + /// ReceiverKind values. + /// + /// We pad this out to a byte to avoid excessive masking and shifting. + unsigned Kind : 8; + + /// \brief Whether we have an actual method prototype in \c + /// SelectorOrMethod. + /// + /// When non-zero, we have a method declaration; otherwise, we just + /// have a selector. + unsigned HasMethod : 8; + + /// \brief When the message expression is a send to 'super', this is + /// the location of the 'super' keyword. + SourceLocation SuperLoc; + + /// \brief Stores either the selector that this message is sending + /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer + /// referring to the method that we type-checked against. + uintptr_t SelectorOrMethod; + + /// \brief The source locations of the open and close square + /// brackets ('[' and ']', respectively). + SourceLocation LBracLoc, RBracLoc; + + ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0), + HasMethod(0), SelectorOrMethod(0) { } + + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + ObjCMessageExpr(QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Retrieve the pointer value of the ,essage receiver. + void *getReceiverPointer() const { + return *const_cast<void **>( + reinterpret_cast<const void * const*>(this + 1)); + } - // NumArgs - The number of arguments (not including the receiver) to the - // message expression. - unsigned NumArgs; + /// \brief Set the pointer value of the message receiver. + void setReceiverPointer(void *Value) { + *reinterpret_cast<void **>(this + 1) = Value; + } - /// \brief The location of the class name in a class message. - SourceLocation ClassNameLoc; +public: + /// \brief The kind of receiver this message is sending to. + enum ReceiverKind { + /// \brief The receiver is a class. + Class = 0, + /// \brief The receiver is an object instance. + Instance, + /// \brief The receiver is a superclass. + SuperClass, + /// \brief The receiver is the instance of the superclass object. + SuperInstance + }; - // A unigue name for this message. - Selector SelName; + /// \brief Create a message send to super. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param SuperLoc The location of the "super" keyword. + /// + /// \param IsInstanceSuper Whether this is an instance "super" + /// message (otherwise, it's a class "super" message). + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + SourceLocation SuperLoc, + bool IsInstanceSuper, + QualType SuperType, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create a class message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The type of the receiver, including + /// source-location information. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + TypeSourceInfo *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an instance message send. + /// + /// \param Context The ASTContext in which this expression will be created. + /// + /// \param T The result type of this message. + /// + /// \param LBrac The location of the open square bracket '['. + /// + /// \param Receiver The expression used to produce the object that + /// will receive this message. + /// + /// \param Sel The selector used to determine which method gets called. + /// + /// \param Method The Objective-C method against which this message + /// send was type-checked. May be NULL. + /// + /// \param Args The message send arguments. + /// + /// \param NumArgs The number of arguments. + /// + /// \param RBracLoc The location of the closing square bracket ']'. + static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + SourceLocation LBracLoc, + Expr *Receiver, + Selector Sel, + ObjCMethodDecl *Method, + Expr **Args, unsigned NumArgs, + SourceLocation RBracLoc); + + /// \brief Create an empty Objective-C message expression, to be + /// filled in by subsequent calls. + /// + /// \param Context The context in which the message send will be created. + /// + /// \param NumArgs The number of message arguments, not including + /// the receiver. + static ObjCMessageExpr *CreateEmpty(ASTContext &Context, unsigned NumArgs); + + /// \brief Determine the kind of receiver that this message is being + /// sent to. + ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } + + /// \brief Determine whether this is an instance message to either a + /// computed object or to super. + bool isInstanceMessage() const { + return getReceiverKind() == Instance || getReceiverKind() == SuperInstance; + } - // 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; + /// \brief Determine whether this is an class message to either a + /// specified class or to super. + bool isClassMessage() const { + return getReceiverKind() == Class || getReceiverKind() == SuperClass; + } - SourceLocation LBracloc, RBracloc; + /// \brief Returns the receiver of an instance message. + /// + /// \brief Returns the object expression for an instance message, or + /// NULL for a message that is not an instance message. + Expr *getInstanceReceiver() { + if (getReceiverKind() == Instance) + return static_cast<Expr *>(getReceiverPointer()); - // Constants for indexing into SubExprs. - enum { RECEIVER=0, ARGS_START=1 }; + return 0; + } + const Expr *getInstanceReceiver() const { + return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); + } - // Bit-swizzling flags. - enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 }; - unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; } + /// \brief Turn this message send into an instance message that + /// computes the receiver object with the given expression. + void setInstanceReceiver(Expr *rec) { + Kind = Instance; + setReceiverPointer(rec); + } + + /// \brief Returns the type of a class message send, or NULL if the + /// message is not a class message. + QualType getClassReceiver() const { + if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) + return TSInfo->getType(); + + return QualType(); + } -public: - /// This constructor is used to represent class messages where the - /// ObjCInterfaceDecl* of the receiver is not known. - ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, - SourceLocation clsNameLoc, 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(ASTContext &C, ObjCInterfaceDecl *cls, - SourceLocation clsNameLoc, Selector selInfo, - QualType retType, ObjCMethodDecl *methDecl, - SourceLocation LBrac, SourceLocation RBrac, - Expr **ArgExprs, unsigned NumArgs); - - // constructor for instance messages. - ObjCMessageExpr(ASTContext &C, 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) {} - - virtual void DoDestroy(ASTContext &C); - - /// 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<ObjCMessageExpr*>(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; } + /// \brief Returns a type-source information of a class message + /// send, or NULL if the message is not a class message. + TypeSourceInfo *getClassReceiverTypeInfo() const { + if (getReceiverKind() == Class) + return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); + return 0; + } - const ObjCMethodDecl *getMethodDecl() const { return MethodProto; } - ObjCMethodDecl *getMethodDecl() { return MethodProto; } - void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; } + void setClassReceiver(TypeSourceInfo *TSInfo) { + Kind = Class; + setReceiverPointer(TSInfo); + } + + /// \brief Retrieve the location of the 'super' keyword for a class + /// or instance message to 'super', otherwise an invalid source location. + SourceLocation getSuperLoc() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return SuperLoc; - /// \brief Describes the class receiver of a message send. - struct ClassInfo { - /// \brief The interface declaration for the class that is - /// receiving the message. May be NULL. - ObjCInterfaceDecl *Decl; + return SourceLocation(); + } - /// \brief The name of the class that is receiving the - /// message. This will never be NULL. - IdentifierInfo *Name; + /// \brief Retrieve the Objective-C interface to which this message + /// is being directed, if known. + /// + /// This routine cross-cuts all of the different kinds of message + /// sends to determine what the underlying (statically known) type + /// of the receiver will be; use \c getReceiverKind() to determine + /// whether the message is a class or an instance method, whether it + /// is a send to super or not, etc. + /// + /// \returns The Objective-C interface if known, otherwise NULL. + ObjCInterfaceDecl *getReceiverInterface() const; + + /// \brief Retrieve the type referred to by 'super'. + /// + /// The returned type will either be an ObjCInterfaceType (for an + /// class message to super) or an ObjCObjectPointerType that refers + /// to a class (for an instance message to super); + QualType getSuperType() const { + if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) + return QualType::getFromOpaquePtr(getReceiverPointer()); + + return QualType(); + } - /// \brief The source location of the class name. - SourceLocation Loc; + void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) { + Kind = IsInstanceSuper? SuperInstance : SuperClass; + SuperLoc = Loc; + setReceiverPointer(T.getAsOpaquePtr()); + } - ClassInfo() : Decl(0), Name(0), Loc() { } + Selector getSelector() const; - ClassInfo(ObjCInterfaceDecl *Decl, IdentifierInfo *Name, SourceLocation Loc) - : Decl(Decl), Name(Name), Loc(Loc) { } - }; + void setSelector(Selector S) { + HasMethod = false; + SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr()); + } - /// 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); + const ObjCMethodDecl *getMethodDecl() const { + if (HasMethod) + return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); - /// getClassName - For class methods, this returns the invoked class, - /// and returns NULL otherwise. For instance methods, use getReceiver. - IdentifierInfo *getClassName() const { - return getClassInfo().Name; + return 0; } - /// getNumArgs - Return the number of actual arguments to this call. + ObjCMethodDecl *getMethodDecl() { + if (HasMethod) + return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); + + return 0; + } + + void setMethodDecl(ObjCMethodDecl *MD) { + HasMethod = true; + SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); + } + + /// \brief Return the number of actual arguments in this message, + /// not counting the receiver. 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]; + + /// \brief Retrieve the arguments to this message, not including the + /// receiver. + Stmt **getArgs() { + return reinterpret_cast<Stmt **>(this + 1) + 1; + } + const Stmt * const *getArgs() const { + return reinterpret_cast<const Stmt * const *>(this + 1) + 1; } /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(getArgs()[Arg]); } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+ARGS_START]); + return cast<Expr>(getArgs()[Arg]); } /// setArg - Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); - SubExprs[Arg+ARGS_START] = ArgExpr; + getArgs()[Arg] = ArgExpr; } - SourceLocation getLeftLoc() const { return LBracloc; } - SourceLocation getRightLoc() const { return RBracloc; } + SourceLocation getLeftLoc() const { return LBracLoc; } + SourceLocation getRightLoc() const { return RBracLoc; } - void setLeftLoc(SourceLocation L) { LBracloc = L; } - void setRightLoc(SourceLocation L) { RBracloc = L; } + void setLeftLoc(SourceLocation L) { LBracLoc = L; } + void setRightLoc(SourceLocation L) { RBracLoc = L; } void setSourceRange(SourceRange R) { - LBracloc = R.getBegin(); - RBracloc = R.getEnd(); + LBracLoc = R.getBegin(); + RBracLoc = R.getEnd(); } virtual SourceRange getSourceRange() const { - return SourceRange(LBracloc, RBracloc); + return SourceRange(LBracLoc, RBracLoc); } static bool classof(const Stmt *T) { @@ -503,10 +704,10 @@ public: 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; } + arg_iterator arg_begin() { return getArgs(); } + arg_iterator arg_end() { return getArgs() + NumArgs; } + const_arg_iterator arg_begin() const { return (Stmt **)getArgs(); } + const_arg_iterator arg_end() const { return (Stmt **)getArgs() + NumArgs; } }; /// ObjCSuperExpr - Represents the "super" expression in Objective-C, |