aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ExprObjC.h423
-rw-r--r--include/clang/Checker/BugReporter/BugReporter.h1
-rw-r--r--lib/AST/Expr.cpp241
-rw-r--r--lib/AST/StmtDumper.cpp19
-rw-r--r--lib/AST/StmtPrinter.cpp18
-rw-r--r--lib/Checker/BasicObjCFoundationChecks.cpp41
-rw-r--r--lib/Checker/BugReporterVisitors.cpp10
-rw-r--r--lib/Checker/CFRefCount.cpp113
-rw-r--r--lib/Checker/CallAndMessageChecker.cpp12
-rw-r--r--lib/Checker/CheckObjCDealloc.cpp20
-rw-r--r--lib/Checker/GRExprEngine.cpp8
-rw-r--r--lib/Checker/NSAutoreleasePoolChecker.cpp2
-rw-r--r--lib/CodeGen/CGObjC.cpp39
-rw-r--r--lib/Frontend/PCHReaderStmt.cpp48
-rw-r--r--lib/Frontend/PCHWriterStmt.cpp35
-rw-r--r--lib/Frontend/RewriteObjC.cpp445
-rw-r--r--lib/Index/Analyzer.cpp79
-rw-r--r--lib/Sema/SemaCodeComplete.cpp25
-rw-r--r--lib/Sema/SemaExpr.cpp8
-rw-r--r--lib/Sema/SemaExprObjC.cpp191
-rw-r--r--tools/CIndex/CIndex.cpp6
21 files changed, 1117 insertions, 667 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,
diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h
index 6170342926..5b65d52a9a 100644
--- a/include/clang/Checker/BugReporter/BugReporter.h
+++ b/include/clang/Checker/BugReporter/BugReporter.h
@@ -458,7 +458,6 @@ public:
namespace bugreporter {
const Stmt *GetDerefExpr(const ExplodedNode *N);
-const Stmt *GetReceiverExpr(const ExplodedNode *N);
const Stmt *GetDenomExpr(const ExplodedNode *N);
const Stmt *GetCalleeExpr(const ExplodedNode *N);
const Stmt *GetRetValExpr(const ExplodedNode *N);
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 88b5b5e567..71e8d072e4 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2239,101 +2239,156 @@ void ExtVectorElementExpr::getEncodedElementAccess(
}
}
-// constructor for instance messages.
-ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, Expr *receiver,
- Selector selInfo,
- QualType retType, ObjCMethodDecl *mproto,
- SourceLocation LBrac, SourceLocation RBrac,
- Expr **ArgExprs, unsigned nargs)
- : Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo),
- MethodProto(mproto) {
- NumArgs = nargs;
- SubExprs = new (C) Stmt*[NumArgs+1];
- SubExprs[RECEIVER] = receiver;
- if (NumArgs) {
- for (unsigned i = 0; i != NumArgs; ++i)
- SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
- }
- LBracloc = LBrac;
- RBracloc = RBrac;
-}
-
-// constructor for class messages.
-// FIXME: clsName should be typed to ObjCInterfaceType
-ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName,
- SourceLocation clsNameLoc, Selector selInfo,
- QualType retType, ObjCMethodDecl *mproto,
- SourceLocation LBrac, SourceLocation RBrac,
- Expr **ArgExprs, unsigned nargs)
- : Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc),
- SelName(selInfo), MethodProto(mproto) {
- NumArgs = nargs;
- SubExprs = new (C) Stmt*[NumArgs+1];
- SubExprs[RECEIVER] = (Expr*) ((uintptr_t) clsName | IsClsMethDeclUnknown);
- if (NumArgs) {
- for (unsigned i = 0; i != NumArgs; ++i)
- SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
- }
- LBracloc = LBrac;
- RBracloc = RBrac;
-}
-
-// constructor for class messages.
-ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls,
- SourceLocation clsNameLoc, Selector selInfo,
- QualType retType,
- ObjCMethodDecl *mproto, SourceLocation LBrac,
- SourceLocation RBrac, Expr **ArgExprs,
- unsigned nargs)
- : Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc),
- SelName(selInfo), MethodProto(mproto)
+ObjCMessageExpr::ObjCMessageExpr(QualType T,
+ SourceLocation LBracLoc,
+ SourceLocation SuperLoc,
+ bool IsInstanceSuper,
+ QualType SuperType,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc)
+ : Expr(ObjCMessageExprClass, T, /*TypeDependent=*/false,
+ hasAnyValueDependentArguments(Args, NumArgs)),
+ NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass),
+ HasMethod(Method != 0), SuperLoc(SuperLoc),
+ SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
+ : Sel.getAsOpaquePtr())),
+ LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
- NumArgs = nargs;
- SubExprs = new (C) Stmt*[NumArgs+1];
- SubExprs[RECEIVER] = (Expr*) ((uintptr_t) cls | IsClsMethDeclKnown);
- if (NumArgs) {
- for (unsigned i = 0; i != NumArgs; ++i)
- SubExprs[i+ARGS_START] = static_cast<Expr *>(ArgExprs[i]);
- }
- LBracloc = LBrac;
- RBracloc = RBrac;
-}
+ setReceiverPointer(SuperType.getAsOpaquePtr());
+ if (NumArgs)
+ memcpy(getArgs(), Args, NumArgs * sizeof(Expr *));
+}
+
+ObjCMessageExpr::ObjCMessageExpr(QualType T,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc)
+ : Expr(ObjCMessageExprClass, T, T->isDependentType(),
+ (T->isDependentType() ||
+ hasAnyValueDependentArguments(Args, NumArgs))),
+ NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0),
+ SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
+ : Sel.getAsOpaquePtr())),
+ LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+{
+ setReceiverPointer(Receiver);
+ if (NumArgs)
+ memcpy(getArgs(), Args, NumArgs * sizeof(Expr *));
+}
+
+ObjCMessageExpr::ObjCMessageExpr(QualType T,
+ SourceLocation LBracLoc,
+ Expr *Receiver,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc)
+ : Expr(ObjCMessageExprClass, T, T->isDependentType(),
+ (T->isDependentType() ||
+ hasAnyValueDependentArguments(Args, NumArgs))),
+ NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0),
+ SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
+ : Sel.getAsOpaquePtr())),
+ LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+{
+ setReceiverPointer(Receiver);
+ if (NumArgs)
+ memcpy(getArgs(), Args, NumArgs * sizeof(Expr *));
+}
+
+ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
+ SourceLocation LBracLoc,
+ SourceLocation SuperLoc,
+ bool IsInstanceSuper,
+ QualType SuperType,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc) {
+ unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
+ NumArgs * sizeof(Expr *);
+ void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ return new (Mem) ObjCMessageExpr(T, LBracLoc, SuperLoc, IsInstanceSuper,
+ SuperType, Sel, Method, Args, NumArgs,
+ RBracLoc);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
+ SourceLocation LBracLoc,
+ TypeSourceInfo *Receiver,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc) {
+ unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
+ NumArgs * sizeof(Expr *);
+ void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args,
+ NumArgs, RBracLoc);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
+ SourceLocation LBracLoc,
+ Expr *Receiver,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RBracLoc) {
+ unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
+ NumArgs * sizeof(Expr *);
+ void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args,
+ NumArgs, RBracLoc);
+}
+
+ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context,
+ unsigned NumArgs) {
+ unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) +
+ NumArgs * sizeof(Expr *);
+ void *Mem = Context.Allocate(Size, llvm::AlignOf<ObjCMessageExpr>::Alignment);
+ return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs);
+}
+
+Selector ObjCMessageExpr::getSelector() const {
+ if (HasMethod)
+ return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod)
+ ->getSelector();
+ return Selector(SelectorOrMethod);
+}
+
+ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
+ switch (getReceiverKind()) {
+ case Instance:
+ if (const ObjCObjectPointerType *Ptr
+ = getInstanceReceiver()->getType()->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+ break;
-ObjCMessageExpr::ClassInfo ObjCMessageExpr::getClassInfo() const {
- uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
- switch (x & Flags) {
- default:
- assert(false && "Invalid ObjCMessageExpr.");
- case IsInstMeth:
- return ClassInfo(0, 0, SourceLocation());
- case IsClsMethDeclUnknown:
- return ClassInfo(0, (IdentifierInfo*) (x & ~Flags), ClassNameLoc);
- case IsClsMethDeclKnown: {
- ObjCInterfaceDecl* D = (ObjCInterfaceDecl*) (x & ~Flags);
- return ClassInfo(D, D->getIdentifier(), ClassNameLoc);
- }
- }
-}
+ case Class:
+ if (const ObjCInterfaceType *Iface
+ = getClassReceiver()->getAs<ObjCInterfaceType>())
+ return Iface->getDecl();
+ break;
-void ObjCMessageExpr::setClassInfo(const ObjCMessageExpr::ClassInfo &CI) {
- if (CI.Decl == 0 && CI.Name == 0) {
- SubExprs[RECEIVER] = (Expr*)((uintptr_t)0 | IsInstMeth);
- return;
- }
+ case SuperInstance:
+ if (const ObjCObjectPointerType *Ptr
+ = getSuperType()->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+ break;
- if (CI.Decl == 0)
- SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Name | IsClsMethDeclUnknown);
- else
- SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Decl | IsClsMethDeclKnown);
- ClassNameLoc = CI.Loc;
-}
+ case SuperClass:
+ if (const ObjCObjectPointerType *Iface
+ = getSuperType()->getAs<ObjCObjectPointerType>())
+ return Iface->getInterfaceDecl();
+ break;
+ }
-void ObjCMessageExpr::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- if (SubExprs)
- C.Deallocate(SubExprs);
- this->~ObjCMessageExpr();
- C.Deallocate((void*) this);
+ return 0;
}
bool ChooseExpr::isConditionTrue(ASTContext &C) const {
@@ -2809,10 +2864,12 @@ Stmt::child_iterator ObjCProtocolExpr::child_end() {
// ObjCMessageExpr
Stmt::child_iterator ObjCMessageExpr::child_begin() {
- return getReceiver() ? &SubExprs[0] : &SubExprs[0] + ARGS_START;
+ if (getReceiverKind() == Instance)
+ return reinterpret_cast<Stmt **>(this + 1);
+ return getArgs();
}
Stmt::child_iterator ObjCMessageExpr::child_end() {
- return &SubExprs[0]+ARGS_START+getNumArgs();
+ return getArgs() + getNumArgs();
}
// Blocks
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index 79f61f2bf3..05adc0292e 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -505,8 +505,23 @@ void StmtDumper::DumpCXXTemporary(CXXTemporary *Temporary) {
void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
DumpExpr(Node);
OS << " selector=" << Node->getSelector().getAsString();
- if (IdentifierInfo *clsName = Node->getClassName())
- OS << " class=" << clsName->getNameStart();
+ switch (Node->getReceiverKind()) {
+ case ObjCMessageExpr::Instance:
+ break;
+
+ case ObjCMessageExpr::Class:
+ OS << " class=";
+ DumpType(Node->getClassReceiver());
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ OS << " super (instance)";
+ break;
+
+ case ObjCMessageExpr::SuperClass:
+ OS << " super (class)";
+ break;
+ }
}
void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 44d475853d..a895b63a79 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1247,9 +1247,21 @@ void StmtPrinter::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
OS << "[";
- Expr *receiver = Mess->getReceiver();
- if (receiver) PrintExpr(receiver);
- else OS << Mess->getClassName()->getName();
+ switch (Mess->getReceiverKind()) {
+ case ObjCMessageExpr::Instance:
+ PrintExpr(Mess->getInstanceReceiver());
+ break;
+
+ case ObjCMessageExpr::Class:
+ OS << Mess->getClassReceiver().getAsString(Policy);
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ case ObjCMessageExpr::SuperClass:
+ OS << "Super";
+ break;
+ }
+
OS << ' ';
Selector selector = Mess->getSelector();
if (selector.isUnarySelector()) {
diff --git a/lib/Checker/BasicObjCFoundationChecks.cpp b/lib/Checker/BasicObjCFoundationChecks.cpp
index 810d0fbb99..e7275ca551 100644
--- a/