forked from OSchip/llvm-project
Extend ObjCMessageExpr for class method sends with the source location
of the class name. llvm-svn: 97943
This commit is contained in:
parent
12852d9521
commit
de4827dd34
|
@ -347,6 +347,9 @@ class ObjCMessageExpr : public Expr {
|
|||
// message expression.
|
||||
unsigned NumArgs;
|
||||
|
||||
/// \brief The location of the class name in a class message.
|
||||
SourceLocation ClassNameLoc;
|
||||
|
||||
// A unigue name for this message.
|
||||
Selector SelName;
|
||||
|
||||
|
@ -367,7 +370,8 @@ class ObjCMessageExpr : public Expr {
|
|||
public:
|
||||
/// This constructor is used to represent class messages where the
|
||||
/// ObjCInterfaceDecl* of the receiver is not known.
|
||||
ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName, Selector selInfo,
|
||||
ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName,
|
||||
SourceLocation clsNameLoc, Selector selInfo,
|
||||
QualType retType, ObjCMethodDecl *methDecl,
|
||||
SourceLocation LBrac, SourceLocation RBrac,
|
||||
Expr **ArgExprs, unsigned NumArgs);
|
||||
|
@ -375,7 +379,8 @@ public:
|
|||
/// 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, Selector selInfo,
|
||||
ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls,
|
||||
SourceLocation clsNameLoc, Selector selInfo,
|
||||
QualType retType, ObjCMethodDecl *methDecl,
|
||||
SourceLocation LBrac, SourceLocation RBrac,
|
||||
Expr **ArgExprs, unsigned NumArgs);
|
||||
|
@ -411,7 +416,24 @@ public:
|
|||
ObjCMethodDecl *getMethodDecl() { return MethodProto; }
|
||||
void setMethodDecl(ObjCMethodDecl *MD) { MethodProto = MD; }
|
||||
|
||||
typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;
|
||||
/// \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;
|
||||
|
||||
/// \brief The name of the class that is receiving the
|
||||
/// message. This will never be NULL.
|
||||
IdentifierInfo *Name;
|
||||
|
||||
/// \brief The source location of the class name.
|
||||
SourceLocation Loc;
|
||||
|
||||
ClassInfo() : Decl(0), Name(0), Loc() { }
|
||||
|
||||
ClassInfo(ObjCInterfaceDecl *Decl, IdentifierInfo *Name, SourceLocation Loc)
|
||||
: Decl(Decl), Name(Name), Loc(Loc) { }
|
||||
};
|
||||
|
||||
/// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
|
||||
/// and IdentifierInfo* of the invoked class. Both can be NULL if this
|
||||
|
@ -423,7 +445,7 @@ public:
|
|||
/// getClassName - For class methods, this returns the invoked class,
|
||||
/// and returns NULL otherwise. For instance methods, use getReceiver.
|
||||
IdentifierInfo *getClassName() const {
|
||||
return getClassInfo().second;
|
||||
return getClassInfo().Name;
|
||||
}
|
||||
|
||||
/// getNumArgs - Return the number of actual arguments to this call.
|
||||
|
|
|
@ -2115,12 +2115,12 @@ ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, Expr *receiver,
|
|||
// constructor for class messages.
|
||||
// FIXME: clsName should be typed to ObjCInterfaceType
|
||||
ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName,
|
||||
Selector selInfo, QualType retType,
|
||||
ObjCMethodDecl *mproto,
|
||||
SourceLocation clsNameLoc, Selector selInfo,
|
||||
QualType retType, ObjCMethodDecl *mproto,
|
||||
SourceLocation LBrac, SourceLocation RBrac,
|
||||
Expr **ArgExprs, unsigned nargs)
|
||||
: Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo),
|
||||
MethodProto(mproto) {
|
||||
: 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);
|
||||
|
@ -2134,12 +2134,14 @@ ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, IdentifierInfo *clsName,
|
|||
|
||||
// constructor for class messages.
|
||||
ObjCMessageExpr::ObjCMessageExpr(ASTContext &C, ObjCInterfaceDecl *cls,
|
||||
Selector selInfo, QualType retType,
|
||||
SourceLocation clsNameLoc, Selector selInfo,
|
||||
QualType retType,
|
||||
ObjCMethodDecl *mproto, SourceLocation LBrac,
|
||||
SourceLocation RBrac, Expr **ArgExprs,
|
||||
unsigned nargs)
|
||||
: Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo),
|
||||
MethodProto(mproto) {
|
||||
: Expr(ObjCMessageExprClass, retType, false, false), ClassNameLoc(clsNameLoc),
|
||||
SelName(selInfo), MethodProto(mproto)
|
||||
{
|
||||
NumArgs = nargs;
|
||||
SubExprs = new (C) Stmt*[NumArgs+1];
|
||||
SubExprs[RECEIVER] = (Expr*) ((uintptr_t) cls | IsClsMethDeclKnown);
|
||||
|
@ -2157,23 +2159,27 @@ ObjCMessageExpr::ClassInfo ObjCMessageExpr::getClassInfo() const {
|
|||
default:
|
||||
assert(false && "Invalid ObjCMessageExpr.");
|
||||
case IsInstMeth:
|
||||
return ClassInfo(0, 0);
|
||||
return ClassInfo(0, 0, SourceLocation());
|
||||
case IsClsMethDeclUnknown:
|
||||
return ClassInfo(0, (IdentifierInfo*) (x & ~Flags));
|
||||
return ClassInfo(0, (IdentifierInfo*) (x & ~Flags), ClassNameLoc);
|
||||
case IsClsMethDeclKnown: {
|
||||
ObjCInterfaceDecl* D = (ObjCInterfaceDecl*) (x & ~Flags);
|
||||
return ClassInfo(D, D->getIdentifier());
|
||||
return ClassInfo(D, D->getIdentifier(), ClassNameLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjCMessageExpr::setClassInfo(const ObjCMessageExpr::ClassInfo &CI) {
|
||||
if (CI.first == 0 && CI.second == 0)
|
||||
if (CI.Decl == 0 && CI.Name == 0) {
|
||||
SubExprs[RECEIVER] = (Expr*)((uintptr_t)0 | IsInstMeth);
|
||||
else if (CI.first == 0)
|
||||
SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.second | IsClsMethDeclUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CI.Decl == 0)
|
||||
SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Name | IsClsMethDeclUnknown);
|
||||
else
|
||||
SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.first | IsClsMethDeclKnown);
|
||||
SubExprs[RECEIVER] = (Expr*)((uintptr_t)CI.Decl | IsClsMethDeclKnown);
|
||||
ClassNameLoc = CI.Loc;
|
||||
}
|
||||
|
||||
void ObjCMessageExpr::DoDestroy(ASTContext &C) {
|
||||
|
|
|
@ -853,7 +853,7 @@ public:
|
|||
|
||||
RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME) {
|
||||
return getClassMethodSummary(ME->getSelector(), ME->getClassName(),
|
||||
ME->getClassInfo().first,
|
||||
ME->getClassInfo().Decl,
|
||||
ME->getMethodDecl(), ME->getType());
|
||||
}
|
||||
|
||||
|
@ -2511,7 +2511,7 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
|
|||
// id, id<...>, or Class. If we have an ObjCInterfaceDecl, we know this
|
||||
// is a call to a class method whose type we can resolve. In such
|
||||
// cases, promote the return type to XXX* (where XXX is the class).
|
||||
const ObjCInterfaceDecl *D = ME->getClassInfo().first;
|
||||
const ObjCInterfaceDecl *D = ME->getClassInfo().Decl;
|
||||
return !D ? RetTy : Ctx.getPointerType(Ctx.getObjCInterfaceType(D));
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) {
|
|||
// Find the receiver
|
||||
llvm::Value *Receiver;
|
||||
if (!ReceiverExpr) {
|
||||
const ObjCInterfaceDecl *OID = E->getClassInfo().first;
|
||||
const ObjCInterfaceDecl *OID = E->getClassInfo().Decl;
|
||||
|
||||
// Very special case, super send in class method. The receiver is
|
||||
// self (the class object) and the send uses super semantics.
|
||||
|
|
|
@ -792,8 +792,9 @@ unsigned PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
|||
cast_or_null<Expr>(StmtStack[StmtStack.size() - E->getNumArgs() - 1]));
|
||||
if (!E->getReceiver()) {
|
||||
ObjCMessageExpr::ClassInfo CI;
|
||||
CI.first = cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]));
|
||||
CI.second = Reader.GetIdentifierInfo(Record, Idx);
|
||||
CI.Decl = cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]));
|
||||
CI.Name = Reader.GetIdentifierInfo(Record, Idx);
|
||||
CI.Loc = SourceLocation::getFromRawEncoding(Record[Idx++]);
|
||||
E->setClassInfo(CI);
|
||||
}
|
||||
|
||||
|
|
|
@ -720,8 +720,9 @@ void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
|||
|
||||
if (!E->getReceiver()) {
|
||||
ObjCMessageExpr::ClassInfo CI = E->getClassInfo();
|
||||
Writer.AddDeclRef(CI.first, Record);
|
||||
Writer.AddIdentifierRef(CI.second, Record);
|
||||
Writer.AddDeclRef(CI.Decl, Record);
|
||||
Writer.AddIdentifierRef(CI.Name, Record);
|
||||
Writer.AddSourceLocation(CI.Loc, Record);
|
||||
}
|
||||
|
||||
for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
|
||||
|
|
|
@ -177,7 +177,7 @@ public:
|
|||
if (IsInstanceMethod)
|
||||
return false;
|
||||
|
||||
MsgD = Msg->getClassInfo().first;
|
||||
MsgD = Msg->getClassInfo().Decl;
|
||||
// FIXME: Case when we only have an identifier.
|
||||
assert(MsgD && "Identifier only");
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ public:
|
|||
while (true) {
|
||||
if (Msg->getReceiver() == 0) {
|
||||
CanBeClassMethod = true;
|
||||
MsgD = Msg->getClassInfo().first;
|
||||
MsgD = Msg->getClassInfo().Decl;
|
||||
// FIXME: Case when we only have an identifier.
|
||||
assert(MsgD && "Identifier only");
|
||||
break;
|
||||
|
|
|
@ -470,13 +470,13 @@ Sema::ExprResult Sema::ActOnClassMessage(
|
|||
// now, we simply pass the "super" identifier through (which isn't consistent
|
||||
// with instance methods.
|
||||
if (isSuper)
|
||||
return new (Context) ObjCMessageExpr(Context, receiverName, Sel, returnType,
|
||||
Method, lbrac, rbrac, ArgExprs,
|
||||
NumArgs);
|
||||
return new (Context) ObjCMessageExpr(Context, receiverName, receiverLoc,
|
||||
Sel, returnType, Method, lbrac, rbrac,
|
||||
ArgExprs, NumArgs);
|
||||
else
|
||||
return new (Context) ObjCMessageExpr(Context, ClassDecl, Sel, returnType,
|
||||
Method, lbrac, rbrac, ArgExprs,
|
||||
NumArgs);
|
||||
return new (Context) ObjCMessageExpr(Context, ClassDecl, receiverLoc,
|
||||
Sel, returnType, Method, lbrac, rbrac,
|
||||
ArgExprs, NumArgs);
|
||||
}
|
||||
|
||||
// ActOnInstanceMessage - used for both unary and keyword messages.
|
||||
|
|
|
@ -120,7 +120,9 @@ int main (int argc, const char * argv[]) {
|
|||
// CHECK: [47:4 - 47:6] VarDecl=c:47:12 (Definition)
|
||||
// CHECK: [47:6 - 47:10] ObjCProtocolRef=SubP:27:1
|
||||
// CHECK: [47:10 - 47:16] VarDecl=c:47:12 (Definition)
|
||||
// CHECK: [47:16 - 47:26] ObjCMessageExpr=fooC:8:1
|
||||
// CHECK: [47:16 - 47:17] ObjCMessageExpr=fooC:8:1
|
||||
// CHECK: [47:17 - 47:20] ObjCClassRef=Foo:3:12
|
||||
// CHECK: [47:20 - 47:26] ObjCMessageExpr=fooC:8:1
|
||||
// CHECK: [47:26 - 47:27] UnexposedStmt=
|
||||
// CHECK: [47:27 - 48:2] UnexposedStmt=
|
||||
// CHECK: [48:2 - 48:4] TypeRef=id:0:0
|
||||
|
|
|
@ -315,6 +315,7 @@ public:
|
|||
bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
|
||||
bool VisitExplicitCastExpr(ExplicitCastExpr *E);
|
||||
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
|
||||
bool VisitObjCMessageExpr(ObjCMessageExpr *E);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
@ -901,6 +902,14 @@ bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
|
|||
return VisitExpr(E);
|
||||
}
|
||||
|
||||
bool CursorVisitor::VisitObjCMessageExpr(ObjCMessageExpr *E) {
|
||||
ObjCMessageExpr::ClassInfo CI = E->getClassInfo();
|
||||
if (CI.Decl && Visit(MakeCursorObjCClassRef(CI.Decl, CI.Loc, TU)))
|
||||
return true;
|
||||
|
||||
return VisitExpr(E);
|
||||
}
|
||||
|
||||
bool CursorVisitor::VisitAttributes(Decl *D) {
|
||||
for (const Attr *A = D->getAttrs(); A; A = A->getNext())
|
||||
if (Visit(MakeCXCursor(A, D, TU)))
|
||||
|
|
Loading…
Reference in New Issue