]> granicus.if.org Git - clang/commitdiff
Extend ObjCMessageExpr for class method sends with the source location
authorDouglas Gregor <dgregor@apple.com>
Mon, 8 Mar 2010 16:40:19 +0000 (16:40 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 8 Mar 2010 16:40:19 +0000 (16:40 +0000)
of the class name.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97943 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ExprObjC.h
lib/AST/Expr.cpp
lib/Checker/CFRefCount.cpp
lib/CodeGen/CGObjC.cpp
lib/Frontend/PCHReaderStmt.cpp
lib/Frontend/PCHWriterStmt.cpp
lib/Index/Analyzer.cpp
lib/Sema/SemaExprObjC.cpp
test/Index/c-index-getCursor-test.m
tools/CIndex/CIndex.cpp

index df39b535eb3e118dd77e1cedf982475956f5bed1..6f43973a3e1dcdb9725c8497a3a9ed251f62ac94 100644 (file)
@@ -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.
index a2914bc6bf4e1bacd34a6c3984c418268f5092f6..c08a3a26e1782d31c2eab587503d69681f447e56 100644 (file)
@@ -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) {
index ecb98a0496f08af230cfa2fad8f996c194da2157..9a76f6a2a3ad09a6151242bba97389e4005d170e 100644 (file)
@@ -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));
       }
 
index b62e6ed44366112f7eee67e4b06a83382bf2822d..3ff77f0170c1cf90dc510b5189a7f1dd153db0d5 100644 (file)
@@ -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.
index d123694d699d8b302ff267d0fbab058397da8f3f..7b94805d39991794d54aa20660d88539334fb828 100644 (file)
@@ -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);
   }
 
index a8cc9d6f459175405eb31ab2130f19e80e67591b..9a5417ca61020260d22609f8d715a5ae34818fd1 100644 (file)
@@ -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();
index fb3529d5405cf954f155ad8f6456999df397cdb9..7b414f2a9fb54f3f7cb79a74248357abf07ce687 100644 (file)
@@ -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;
index 3a05241c016b77a0334ed0102cbe8aaebf704165..c60455d8456c68603855d3e517ab14baea8e5e7b 100644 (file)
@@ -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.
index 197a7d41c57b92dfcc24f9ff44935a190e94eca3..8341b80a673f502625a7d79ce157f7dd51b5c229 100644 (file)
@@ -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
index 4ae2f806062f4d89ea0ebf8a077f33f09cabc72a..6fff18304386397f2566525c9856106592fb23ce 100644 (file)
@@ -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)))