ObjCMessageExpr objects that represent messages to class methods now can contain the ObjCInterfaceDecl* of the target class if it was available when the ObjCMessageExpr object was constructed.  The original interfaces of the class has been preserved (requiring no functionality changes from clients), but now a "getClasSInfo" method returns both the ObjCInterfaceDecl* and IdentifierInfo* of the target class.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52676 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index e18c27c..cdbafde 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1131,7 +1131,7 @@
     MethodProto(mproto) {
   NumArgs = nargs;
   SubExprs = new Stmt*[NumArgs+1];
-  SubExprs[RECEIVER] = (Expr*) ((uintptr_t) clsName | 0x1);
+  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]);
@@ -1140,6 +1140,40 @@
   RBracloc = RBrac;
 }
 
+// constructor for class messages. 
+ObjCMessageExpr::ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
+                                 QualType retType, ObjCMethodDecl *mproto,
+                                 SourceLocation LBrac, SourceLocation RBrac,
+                                 Expr **ArgExprs, unsigned nargs)
+: Expr(ObjCMessageExprClass, retType), SelName(selInfo), 
+MethodProto(mproto) {
+  NumArgs = nargs;
+  SubExprs = new 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;
+}
+
+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);
+    case IsClsMethDeclUnknown:
+      return ClassInfo(0, (IdentifierInfo*) (x & ~Flags));
+    case IsClsMethDeclKnown: {
+      ObjCInterfaceDecl* D = (ObjCInterfaceDecl*) (x & ~Flags);
+      return ClassInfo(D, D->getIdentifier());
+    }
+  }
+}
+
 bool ChooseExpr::isConditionTrue(ASTContext &C) const {
   llvm::APSInt CondVal(32);
   bool IsConst = getCond()->isIntegerConstantExpr(CondVal, C);
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 1aed69e..c33efbd 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -202,8 +202,16 @@
         return true;
     }
   }
-  return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
-                             lbrac, rbrac, ArgExprs, NumArgs);
+
+  // If we have the ObjCInterfaceDecl* for the class that is receiving
+  // the message, use that to construct the ObjCMessageExpr.  Otherwise
+  // pass on the IdentifierInfo* for the class.
+  if (ClassDecl)
+    return new ObjCMessageExpr(ClassDecl, Sel, returnType, Method,
+                               lbrac, rbrac, ArgExprs, NumArgs);
+  else
+    return new ObjCMessageExpr(receiverName, Sel, returnType, Method,
+                               lbrac, rbrac, ArgExprs, NumArgs);
 }
 
 // ActOnInstanceMessage - used for both unary and keyword messages.