aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-04-21 00:45:42 +0000
committerDouglas Gregor <dgregor@apple.com>2010-04-21 00:45:42 +0000
commit04badcf84c8d504d8491c7c7e29b58f52cb16640 (patch)
tree99dc6c7a506db47b8d998c0fa9807f10f770db34 /lib/AST/Expr.cpp
parent10dc0f8c355c6a726f206aefcb249cb2fafbce17 (diff)
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the actual receiver of the message, and pave the way for proper C++ support. The ObjCMessageExpr node represents four different kinds of message sends in a single AST node: 1) Send to a object instance described by an expression (e.g., [x method:5]) 2) Send to a class described by the class name (e.g., [NSString method:5]) 3) Send to a superclass class (e.g, [super method:5] in class method) 4) Send to a superclass instance (e.g., [super method:5] in instance method) Previously these four cases where tangled together. Now, they have more distinct representations. Specific changes: 1) Unchanged; the object instance is represented by an Expr*. 2) Previously stored the ObjCInterfaceDecl* referring to the class receiving the message. Now stores a TypeSourceInfo* so that we know how the class was spelled. This both maintains typedef information and opens the door for more complicated C++ types (e.g., dependent types). There was an alternative, unused representation of these sends by naming the class via an IdentifierInfo *. In practice, we either had an ObjCInterfaceDecl *, from which we would get the IdentifierInfo *, or we fell into the case below... 3) Previously represented by a class message whose IdentifierInfo * referred to "super". Sema and CodeGen would use isStr("super") to determine if they had a send to super. Now represented as a "class super" send, where we have both the location of the "super" keyword and the ObjCInterfaceDecl* of the superclass we're targetting (statically). 4) Previously represented by an instance message whose receiver is a an ObjCSuperExpr, which Sema and CodeGen would check for via isa<ObjCSuperExpr>(). Now represented as an "instance super" send, where we have both the location of the "super" keyword and the ObjCInterfaceDecl* of the superclass we're targetting (statically). Note that ObjCSuperExpr only has one remaining use in the AST, which is for "super.prop" references. The new representation of ObjCMessageExpr is 2 pointers smaller than the old one, since it combines more storage. It also eliminates a leak when we loaded message-send expressions from a precompiled header. The representation also feels much cleaner to me; comments welcome! This patch attempts to maintain the same semantics we previously had with Objective-C message sends. In several places, there are massive changes that boil down to simply replacing a nested-if structure such as: if (message has a receiver expression) { // instance message if (isa<ObjCSuperExpr>(...)) { // send to super } else { // send to an object } } else { // class message if (name->isStr("super")) { // class send to super } else { // send to class } } with a switch switch (E->getReceiverKind()) { case ObjCMessageExpr::SuperInstance: ... case ObjCMessageExpr::Instance: ... case ObjCMessageExpr::SuperClass: ... case ObjCMessageExpr::Class:... } There are quite a few places (particularly in the checkers) where send-to-super is effectively ignored. I've placed FIXMEs in most of them, and attempted to address send-to-super in a reasonable way. This could use some review. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101972 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r--lib/AST/Expr.cpp241
1 files changed, 149 insertions, 92 deletions
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