Index: test/Index/get-cursor-objc.m
===================================================================
--- test/Index/get-cursor-objc.m	(revision 0)
+++ test/Index/get-cursor-objc.m	(revision 0)
@@ -0,0 +1,51 @@
+#define nil (id)0
+
+@protocol TestProtocol
++ (id)protocolClassMethod;
+- (id)protocolInstanceMethod;
+- (id)protocolInstanceMethodThatCalculates:(int)i;
+@end
+
+@interface Foo <TestProtocol> {
+  void *isa;
+}
+
++ (id)classMethod:(void *)ptr forInt:(int)i;
+- (Foo *)copy;
++ (id)new;
+- (void)dealloc;
+- (id <TestProtocol>)objectThatRespondsToSelector:(SEL)selector;
+
+@end
+
+// RUN: c-index-test -cursor-at=%s:4:26 %s | FileCheck -check-prefix=CHECK-PROTOCOL-CLASS %s
+// CHECK-PROTOCOL-CLASS: ObjCClassMethodDecl=protocolClassMethod:4:1
+// CHECK-PROTOCOL-CLASS-NEXT: Completion string: {ResultType id}{TypedText protocolClassMethod}
+
+// RUN: c-index-test -cursor-at=%s:5:29 %s | FileCheck -check-prefix=CHECK-PROTOCOL-INST1 %s
+// CHECK-PROTOCOL-INST1: ObjCInstanceMethodDecl=protocolInstanceMethod:5:1
+// CHECK-PROTOCOL-INST1-NEXT: {ResultType id}{TypedText protocolInstanceMethod}
+
+// RUN: c-index-test -cursor-at=%s:6:50 %s | FileCheck -check-prefix=CHECK-PROTOCOL-INST2 %s
+// CHECK-PROTOCOL-INST2: ObjCInstanceMethodDecl=protocolInstanceMethodThatCalculates::6:1
+// CHECK-PROTOCOL-INST2-NEXT: {ResultType id}{TypedText protocolInstanceMethodThatCalculates:}{Placeholder (int)}
+
+// RUN: c-index-test -cursor-at=%s:10:3 %s | FileCheck -check-prefix=CHECK-IVAR %s
+// CHECK-IVAR: ObjCIvarDecl=isa:10:9 (Definition)
+// CHECK-IVAR-NEXT: Completion string: {ResultType void *}{TypedText isa}
+
+// RUN: c-index-test -cursor-at=%s:13:44 %s | FileCheck -check-prefix=CHECK-FOO-CLASS %s
+// CHECK-FOO-CLASS: ObjCClassMethodDecl=classMethod:forInt::13:1
+// CHECK-FOO-CLASS-NEXT: Completion string: {ResultType id}{TypedText classMethod:}{Placeholder (void *)}{HorizontalSpace  }{TypedText forInt:}{Placeholder (int)}
+
+// RUN: c-index-test -cursor-at=%s:14:14 %s | FileCheck -check-prefix=CHECK-FOO-COPY %s
+// CHECK-FOO-COPY: ObjCInstanceMethodDecl=copy:14:1
+// CHECK-FOO-COPY-NEXT: {ResultType Foo *}{TypedText copy}
+
+// RUN: c-index-test -cursor-at=%s:15:10 %s | FileCheck -check-prefix=CHECK-FOO-NEW %s
+// CHECK-FOO-NEW: ObjCClassMethodDecl=new:15:1
+// CHECK-FOO-NEW-NEXT: {ResultType id}{TypedText new}
+
+// RUN: c-index-test -cursor-at=%s:17:64 %s | FileCheck -check-prefix=CHECK-FOO-SEL %s
+// CHECK-FOO-SEL: ObjCInstanceMethodDecl=objectThatRespondsToSelector::17:1
+// CHECK-FOO-SEL-NEXT: {ResultType id<TestProtocol>}{TypedText objectThatRespondsToSelector:}{Placeholder (SEL)}
Index: test/Index/get-cursor.cpp
===================================================================
--- test/Index/get-cursor.cpp	(revision 136101)
+++ test/Index/get-cursor.cpp	(working copy)
@@ -35,6 +35,14 @@
   X foo;
 }
 
+// RUN: c-index-test -cursor-at=%s:6:4 %s | FileCheck -check-prefix=CHECK-COMPLETION-1 %s
+// CHECK-COMPLETION-1: CXXConstructor=X:6:3
+// CHECK-COMPLETION-1-NEXT: Completion string: {TypedText X}{LeftParen (}{Placeholder int}{Comma , }{Placeholder int}{RightParen )}
+
+// RUN: c-index-test -cursor-at=%s:31:16 %s | FileCheck -check-prefix=CHECK-COMPLETION-2 %s
+// CHECK-COMPLETION-2: CXXMethod=getAnotherX:31:5 (Definition)
+// CHECK-COMPLETION-2-NEXT: Completion string: {ResultType X}{TypedText getAnotherX}{LeftParen (}{RightParen )}
+
 // RUN: c-index-test -cursor-at=%s:12:20 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
 // RUN: c-index-test -cursor-at=%s:13:21 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
 // RUN: c-index-test -cursor-at=%s:13:28 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
@@ -68,3 +76,7 @@
 
 // RUN: c-index-test -cursor-at=%s:35:5 %s | FileCheck -check-prefix=CHECK-DECL %s
 // CHECK-DECL: VarDecl=foo:35:5
+
+// RUN: c-index-test -cursor-at=%s:21:3 %s | FileCheck -check-prefix=CHECK-MEMBER %s
+// CHECK-MEMBER: FieldDecl=member:21:7 (Definition)
+// CHECK-MEMBER-NEXT: Completion string: {ResultType int}{TypedText member}
Index: include/clang/Frontend/ASTUnit.h
===================================================================
--- include/clang/Frontend/ASTUnit.h	(revision 136101)
+++ include/clang/Frontend/ASTUnit.h	(working copy)
@@ -310,10 +310,24 @@
     return CachedCompletionAllocator;
   }
   
+  /// \brief Retrieve the allocator used to cache global code completions.
+  /// Creates the allocator if it doesn't already exist.
+  llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+  getCursorCompletionAllocator() {
+    if (!CursorCompletionAllocator.getPtr()) {
+      CursorCompletionAllocator = new GlobalCodeCompletionAllocator;
+    }
+    return CursorCompletionAllocator;
+  }
+  
 private:
   /// \brief Allocator used to store cached code completions.
   llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
     CachedCompletionAllocator;
+  
+  /// \brief Allocator used to store code completions for arbitrary cursors.
+  llvm::IntrusiveRefCntPtr<GlobalCodeCompletionAllocator>
+    CursorCompletionAllocator;
 
   /// \brief The set of cached code-completion results.
   std::vector<CachedCodeCompletionResult> CachedCompletionResults;
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h	(revision 136101)
+++ include/clang-c/Index.h	(working copy)
@@ -2897,6 +2897,18 @@
 clang_getCompletionAvailability(CXCompletionString completion_string);
 
 /**
+ * \brief Retrieve a completion string for an arbitrary declaration or macro
+ * definition cursor.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns A non-context-sensitive completion string for declaration and macro
+ * definition cursors, or NULL for other kinds of cursors.
+ */
+CINDEX_LINKAGE CXCompletionString
+clang_getCursorCompletionString(CXCursor cursor);
+  
+/**
  * \brief Contains the results of code-completion.
  *
  * This data structure contains the results of code completion, as
Index: tools/c-index-test/c-index-test.c
===================================================================
--- tools/c-index-test/c-index-test.c	(revision 136101)
+++ tools/c-index-test/c-index-test.c	(working copy)
@@ -1333,7 +1333,13 @@
                                clang_getLocation(TU, file, Locations[Loc].line,
                                                  Locations[Loc].column));
       if (I + 1 == Repeats) {
+        CXCompletionString completionString = clang_getCursorCompletionString(
+                                                                        Cursor);
         PrintCursor(TU, Cursor);
+        if (completionString != NULL) {
+          printf("\nCompletion string: ");
+          print_completion_string(completionString, stdout);
+        }
         printf("\n");
         free(Locations[Loc].filename);
       }
Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp	(revision 136101)
+++ tools/libclang/CXCursor.cpp	(working copy)
@@ -577,4 +577,40 @@
   entry = 1;
   return flag;
 }
+  
+CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
+  enum CXCursorKind kind = clang_getCursorKind(cursor);
+  if (clang_isDeclaration(kind)) {
+    Decl *decl = getCursorDecl(cursor);
+    if (isa<NamedDecl>(decl)) {
+      NamedDecl *namedDecl = (NamedDecl *)decl;
+      ASTUnit *unit = getCursorASTUnit(cursor);
+      if (unit->hasSema()) {
+        Sema &S = unit->getSema();
+        CodeCompletionAllocator *Allocator =
+                                  unit->getCursorCompletionAllocator().getPtr();
+        CodeCompletionResult Result(namedDecl);
+        CodeCompletionString *String = Result.CreateCodeCompletionString(S,
+                                                                    *Allocator);
+        return String;
+      }
+    }
+  }
+  else if (kind == CXCursor_MacroDefinition) {
+    MacroDefinition *definition = getCursorMacroDefinition(cursor);
+    const IdentifierInfo *MacroInfo = definition->getName();
+    ASTUnit *unit = getCursorASTUnit(cursor);
+    if (unit->hasSema()) {
+      Sema &S = unit->getSema();
+      CodeCompletionAllocator *Allocator =
+                                  unit->getCursorCompletionAllocator().getPtr();
+      CodeCompletionResult Result((IdentifierInfo *)MacroInfo);
+      CodeCompletionString *String = Result.CreateCodeCompletionString(S,
+                                                                    *Allocator);
+      return String;
+    }
+  }
+  return NULL;
+}
+  
 } // end: extern "C"
Index: tools/libclang/libclang.darwin.exports
===================================================================
--- tools/libclang/libclang.darwin.exports	(revision 136101)
+++ tools/libclang/libclang.darwin.exports	(working copy)
@@ -55,6 +55,7 @@
 _clang_getCompletionPriority
 _clang_getCursor
 _clang_getCursorAvailability
+_clang_getCursorCompletionString
 _clang_getCursorDefinition
 _clang_getCursorDisplayName
 _clang_getCursorExtent
Index: tools/libclang/libclang.exports
===================================================================
--- tools/libclang/libclang.exports	(revision 136101)
+++ tools/libclang/libclang.exports	(working copy)
@@ -55,6 +55,7 @@
 clang_getCompletionPriority
 clang_getCursor
 clang_getCursorAvailability
+clang_getCursorCompletionString
 clang_getCursorDefinition
 clang_getCursorDisplayName
 clang_getCursorExtent
Index: lib/Frontend/ASTUnit.cpp
===================================================================
--- lib/Frontend/ASTUnit.cpp	(revision 136101)
+++ lib/Frontend/ASTUnit.cpp	(working copy)
@@ -1903,6 +1903,10 @@
       CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
     CacheCodeCompletionResults();
 
+  // We now need to clear out the completion allocator for
+  // clang_getCursorCompletionString; it'll be recreated if necessary.
+  CursorCompletionAllocator = 0;
+  
   return Result;
 }
 
