Index: include/clang/Basic/LangOptions.h
===================================================================
--- include/clang/Basic/LangOptions.h	(revision 72260)
+++ include/clang/Basic/LangOptions.h	(working copy)
@@ -36,6 +36,8 @@
     
   unsigned ObjC1             : 1;  // Objective-C 1 support enabled.
   unsigned ObjC2             : 1;  // Objective-C 2 support enabled.
+  unsigned ObjCSenderDispatch: 1;  // Objective-C 2 three-dimensional dispatch
+                                   // enabled.
   unsigned ObjCNonFragileABI : 1;  // Objective-C modern abi enabled
     
   unsigned PascalStrings     : 1;  // Allow Pascal strings
Index: include/clang/Driver/Options.def
===================================================================
--- include/clang/Driver/Options.def	(revision 72260)
+++ include/clang/Driver/Options.def	(working copy)
@@ -424,6 +424,7 @@
 OPTION("-fobjc-gc", fobjc_gc, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fobjc-new-property", fobjc_new_property, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fobjc-nonfragile-abi", fobjc_nonfragile_abi, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fobjc-sender-dependent-dispatch", fobjc_sender_dependent_dispatch, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fobjc-tight-layout", fobjc_tight_layout, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fobjc", fobjc, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fomit-frame-pointer", fomit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0)
Index: tools/clang-cc/clang-cc.cpp
===================================================================
--- tools/clang-cc/clang-cc.cpp	(revision 72260)
+++ tools/clang-cc/clang-cc.cpp	(working copy)
@@ -445,6 +445,10 @@
                  llvm::cl::desc("Trap on integer overflow"),
                  llvm::cl::init(false));
 
+static llvm::cl::opt<bool>
+ObjCSenderDispatch("fobjc-sender-dependent-dispatch",
+				 llvm::cl::desc("Enable sender-dependent dispatch for"
+					 "Objective-C messages"), llvm::cl::init(false));
 
 /// InitializeBaseLanguage - Handle the -x foo options.
 static void InitializeBaseLanguage() {
@@ -827,6 +831,8 @@
 
   if (ObjCNonFragileABI)
     Options.ObjCNonFragileABI = 1;
+
+  Options.ObjCSenderDispatch = ObjCSenderDispatch;
   
   if (EmitAllDecls)
     Options.EmitAllDecls = 1;
Index: lib/Frontend/InitPreprocessor.cpp
===================================================================
--- lib/Frontend/InitPreprocessor.cpp	(revision 72260)
+++ lib/Frontend/InitPreprocessor.cpp	(working copy)
@@ -280,6 +280,9 @@
   if (LangOpts.ObjC2)
     DefineBuiltinMacro(Buf, "OBJC_NEW_PROPERTIES");
 
+  if (LangOpts.ObjCSenderDispatch)
+    DefineBuiltinMacro(Buf, "__OBJC_SENDER_AWARE_DISPATCH__");
+
   if (LangOpts.PascalStrings)
     DefineBuiltinMacro(Buf, "__PASCAL_STRINGS__");
 
Index: lib/CodeGen/CGObjCGNU.cpp
===================================================================
--- lib/CodeGen/CGObjCGNU.cpp	(revision 72260)
+++ lib/CodeGen/CGObjCGNU.cpp	(working copy)
@@ -417,8 +417,8 @@
   CallArgList ActualArgs;
 
   ActualArgs.push_back(
-	  std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), 
-	  CGF.getContext().getObjCIdType()));
+    std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), 
+    CGF.getContext().getObjCIdType()));
   ActualArgs.push_back(std::make_pair(RValue::get(cmd),
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
@@ -427,16 +427,37 @@
   const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
   const llvm::FunctionType *impType = Types.GetFunctionType(FnInfo, false);
 
+  llvm::Value *imp;
   std::vector<const llvm::Type*> Params;
   Params.push_back(Receiver->getType());
   Params.push_back(SelectorTy);
-  llvm::Constant *lookupFunction = 
-    CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+  // For sender-aware dispatch, we pass the sender as the third argument to a
+  // lookup function.  When sending messages from C code, the sender is nil.
+  // objc_msg_lookup_sender(id receiver, SEL selector, id sender);
+  if (CGM.getContext().getLangOptions().ObjCSenderDispatch) {
+    llvm::Value *self;
+
+    if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) {
+      self = CGF.LoadObjCSelf();
+    } else {
+      self = llvm::ConstantPointerNull::get(IdTy);
+    }
+    Params.push_back(self->getType());
+    llvm::Constant *lookupFunction = 
+      CGM.CreateRuntimeFunction(llvm::FunctionType::get(
           llvm::PointerType::getUnqual(impType), Params, true),
-        "objc_msg_lookup");
+        "objc_msg_lookup_sender");
 
-  llvm::Value *imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
+    imp = CGF.Builder.CreateCall3(lookupFunction, Receiver, cmd, self);
+  } else {
+    llvm::Constant *lookupFunction = 
+    CGM.CreateRuntimeFunction(llvm::FunctionType::get(
+        llvm::PointerType::getUnqual(impType), Params, true),
+      "objc_msg_lookup");
 
+    imp = CGF.Builder.CreateCall2(lookupFunction, Receiver, cmd);
+  }
+
   return CGF.EmitCall(FnInfo, imp, ActualArgs);
 }
 
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp	(revision 72260)
+++ lib/Driver/Tools.cpp	(working copy)
@@ -479,6 +479,7 @@
   Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
   Args.AddLastArg(CmdArgs, options::OPT_fobjc_gc_only);
   Args.AddLastArg(CmdArgs, options::OPT_fobjc_gc);
+  Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
   // FIXME: Should we remove this?
   Args.AddLastArg(CmdArgs, options::OPT_fobjc_nonfragile_abi);
   Args.AddLastArg(CmdArgs, options::OPT_fobjc_tight_layout);
