Introduce a new libclang API to determine the parent context of a code
completion item. For example, if the code completion itself represents
a declaration in a namespace (say, std::vector), then this API
retrieves the cursor kind and name of the namespace (std). Implements
<rdar://problem/11121951>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153545 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 904585f..8d7d859 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -3543,6 +3543,26 @@
                               unsigned annotation_number);
 
 /**
+ * \brief Retrieve the parent context of the given completion string.
+ *
+ * The parent context of a completion string is the semantic parent of 
+ * the declaration (if any) that the code completion represents. For example,
+ * a code completion for an Objective-C method would have the method's class
+ * or protocol as its context.
+ *
+ * \param completion_string The code completion string whose parent is
+ * being queried.
+ *
+ * \param kind If non-NULL, will be set to the kind of the parent context,
+ * or CXCursor_NotImplemented if there is no context.
+ *
+ * \param Returns the name of the completion parent, e.g., "NSObject" if
+ * the completion string represents a method in the NSObject class.
+ */
+CINDEX_LINKAGE CXString
+clang_getCompletionParent(CXCompletionString completion_string,
+                          enum CXCursorKind *kind);
+/**
  * \brief Retrieve a completion string for an arbitrary declaration or macro
  * definition cursor.
  *
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 8d35ece..ff2ca87 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -434,17 +434,24 @@
   unsigned NumAnnotations : 16;
 
   /// \brief The priority of this code-completion string.
-  unsigned Priority : 30;
+  unsigned Priority : 16;
 
   /// \brief The availability of this code-completion result.
   unsigned Availability : 2;
 
+  /// \brief The kind of the parent context.
+  unsigned ParentKind : 14;
+  
+  /// \brief The name of the parent context.
+  StringRef ParentName;
+  
   CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT
   CodeCompletionString &operator=(const CodeCompletionString &); // DITTO
 
   CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
                        unsigned Priority, CXAvailabilityKind Availability,
-                       const char **Annotations, unsigned NumAnnotations);
+                       const char **Annotations, unsigned NumAnnotations,
+                       CXCursorKind ParentKind, StringRef ParentName);
   ~CodeCompletionString() { }
 
   friend class CodeCompletionBuilder;
@@ -477,6 +484,16 @@
   /// \brief Retrieve the annotation string specified by \c AnnotationNr.
   const char *getAnnotation(unsigned AnnotationNr) const;
 
+  /// \brief Retrieve parent context's cursor kind.
+  CXCursorKind getParentContextKind() const {
+    return (CXCursorKind)ParentKind;
+  }
+  
+  /// \brief Retrieve the name of the parent context.
+  StringRef getParentContextName() const {
+    return ParentName;
+  }
+  
   /// \brief Retrieve a string representation of the code completion string,
   /// which is mainly useful for debugging.
   std::string getAsString() const;
@@ -484,6 +501,8 @@
 
 /// \brief An allocator used specifically for the purpose of code completion.
 class CodeCompletionAllocator : public llvm::BumpPtrAllocator {
+  llvm::DenseMap<DeclContext *, StringRef> ParentNames;
+  
 public:
   /// \brief Copy the given string into this allocator.
   const char *CopyString(StringRef String);
@@ -500,6 +519,12 @@
   const char *CopyString(const std::string &String) {
     return CopyString(StringRef(String));
   }
+  
+  /// \brief Retrieve the mapping from known parent declaration contexts to
+  /// the (already copied) strings associated with each context.
+  llvm::DenseMap<DeclContext *, StringRef> &getParentNames() {
+    return ParentNames;
+  }
 };
 
 } // end namespace clang
@@ -521,7 +546,9 @@
   CodeCompletionAllocator &Allocator;
   unsigned Priority;
   CXAvailabilityKind Availability;
-
+  CXCursorKind ParentKind;
+  StringRef ParentName;
+  
   /// \brief The chunks stored in this string.
   SmallVector<Chunk, 4> Chunks;
 
@@ -529,12 +556,13 @@
 
 public:
   CodeCompletionBuilder(CodeCompletionAllocator &Allocator)
-    : Allocator(Allocator), Priority(0), Availability(CXAvailability_Available){
-  }
+    : Allocator(Allocator), Priority(0), Availability(CXAvailability_Available),
+      ParentKind(CXCursor_NotImplemented) { }
 
   CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
                         unsigned Priority, CXAvailabilityKind Availability)
-    : Allocator(Allocator), Priority(Priority), Availability(Availability) { }
+    : Allocator(Allocator), Priority(Priority), Availability(Availability),
+      ParentKind(CXCursor_NotImplemented) { }
 
   /// \brief Retrieve the allocator into which the code completion
   /// strings should be allocated.
@@ -570,6 +598,12 @@
   void AddChunk(CodeCompletionString::ChunkKind CK, const char *Text = "");
 
   void AddAnnotation(const char *A) { Annotations.push_back(A); }
+
+  /// \brief Add the parent context information to this code completion.
+  void addParentContext(DeclContext *DC);
+  
+  CXCursorKind getParentKind() const { return ParentKind; }
+  StringRef getParentName() const { return ParentName; }
 };
 
 /// \brief Captures a result of code completion.
@@ -586,11 +620,11 @@
   /// \brief The kind of result stored here.
   ResultKind Kind;
 
-  union {
-    /// \brief When Kind == RK_Declaration, the declaration we are referring
-    /// to.
-    NamedDecl *Declaration;
+  /// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are
+  /// referring to. In the latter case, the declaration might be NULL.
+  NamedDecl *Declaration;
 
+  union {
     /// \brief When Kind == RK_Keyword, the string representing the keyword
     /// or symbol's spelling.
     const char *Keyword;
@@ -655,7 +689,7 @@
 
   /// \brief Build a result that refers to a keyword or symbol.
   CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
-    : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
+    : Kind(RK_Keyword), Declaration(0), Keyword(Keyword), Priority(Priority),
       Availability(CXAvailability_Available),
       StartParameter(0), Hidden(false), QualifierIsInformative(0),
       StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
@@ -665,7 +699,7 @@
 
   /// \brief Build a result that refers to a macro.
   CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
-    : Kind(RK_Macro), Macro(Macro), Priority(Priority),
+    : Kind(RK_Macro), Declaration(0), Macro(Macro), Priority(Priority),
       Availability(CXAvailability_Available), StartParameter(0),
       Hidden(false), QualifierIsInformative(0),
       StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
@@ -677,8 +711,9 @@
   CodeCompletionResult(CodeCompletionString *Pattern,
                        unsigned Priority = CCP_CodePattern,
                        CXCursorKind CursorKind = CXCursor_NotImplemented,
-                   CXAvailabilityKind Availability = CXAvailability_Available)
-    : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
+                   CXAvailabilityKind Availability = CXAvailability_Available,
+                       NamedDecl *D = 0)
+    : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority),
       CursorKind(CursorKind), Availability(Availability), StartParameter(0),
       Hidden(false), QualifierIsInformative(0),
       StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
@@ -686,6 +721,18 @@
   {
   }
 
+  /// \brief Build a result that refers to a pattern with an associated
+  /// declaration.
+  CodeCompletionResult(CodeCompletionString *Pattern, NamedDecl *D,
+                       unsigned Priority)
+    : Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority),
+      Availability(CXAvailability_Available), StartParameter(0),
+      Hidden(false), QualifierIsInformative(false),
+      StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+      DeclaringEntity(false), Qualifier(0) {
+    computeCursorKindAndAvailability();
+  }  
+  
   /// \brief Retrieve the declaration stored in this result.
   NamedDecl *getDeclaration() const {
     assert(Kind == RK_Declaration && "Not a declaration result");
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 3b7113d..e476bfb 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -845,7 +845,7 @@
 }
 
 std::string NamedDecl::getQualifiedNameAsString() const {
-  return getQualifiedNameAsString(getASTContext().getLangOpts());
+  return getQualifiedNameAsString(getASTContext().getPrintingPolicy());
 }
 
 std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index caebe3a..dbc9b00 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -192,9 +192,12 @@
                                            unsigned Priority, 
                                            CXAvailabilityKind Availability,
                                            const char **Annotations,
-                                           unsigned NumAnnotations)
-  : NumChunks(NumChunks), NumAnnotations(NumAnnotations)
-  , Priority(Priority), Availability(Availability)
+                                           unsigned NumAnnotations,
+                                           CXCursorKind ParentKind,
+                                           StringRef ParentName)
+  : NumChunks(NumChunks), NumAnnotations(NumAnnotations),
+    Priority(Priority), Availability(Availability), ParentKind(ParentKind),
+    ParentName(ParentName)
 { 
   assert(NumChunks <= 0xffff);
   assert(NumAnnotations <= 0xffff);
@@ -272,7 +275,8 @@
   CodeCompletionString *Result 
     = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
                                      Priority, Availability,
-                                     Annotations.data(), Annotations.size());
+                                     Annotations.data(), Annotations.size(),
+                                     ParentKind, ParentName);
   Chunks.clear();
   return Result;
 }
@@ -311,6 +315,70 @@
   Chunks.push_back(Chunk(CK, Text));
 }
 
+void CodeCompletionBuilder::addParentContext(DeclContext *DC) {
+  if (DC->isTranslationUnit()) {
+    ParentKind = CXCursor_TranslationUnit;
+    return;
+  }
+  
+  if (DC->isFunctionOrMethod())
+    return;
+  
+  NamedDecl *ND = dyn_cast<NamedDecl>(DC);
+  if (!ND)
+    return;
+  
+  ParentKind = getCursorKindForDecl(ND);
+  
+  // Check whether we've already cached the parent name.
+  StringRef &CachedParentName = Allocator.getParentNames()[DC];
+  if (!CachedParentName.empty()) {
+    ParentName = CachedParentName;
+    return;
+  }
+
+  // Find the interesting names.
+  llvm::SmallVector<DeclContext *, 2> Contexts;
+  while (DC && !DC->isFunctionOrMethod()) {
+    if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
+      if (ND->getIdentifier())
+        Contexts.push_back(DC);
+    }
+    
+    DC = DC->getParent();
+  }
+
+  {
+    llvm::SmallString<128> S;
+    llvm::raw_svector_ostream OS(S);
+    bool First = true;
+    for (unsigned I = Contexts.size(); I != 0; --I) {
+      if (First)
+        First = false;
+      else {
+        OS << "::";
+      }
+      
+      DeclContext *CurDC = Contexts[I-1];
+      if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
+        CurDC = CatImpl->getCategoryDecl();
+      
+      if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
+        ObjCInterfaceDecl *Interface = Cat->getClassInterface();
+        if (!Interface)
+          return;
+        
+        OS << Interface->getName() << '(' << Cat->getName() << ')';
+      } else {
+        OS << cast<NamedDecl>(CurDC)->getName();
+      }
+    }
+    
+    ParentName = Allocator.CopyString(OS.str());
+    CachedParentName = ParentName;
+  }
+}
+
 unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
   if (!ND)
     return CCP_Unlikely;
@@ -444,6 +512,13 @@
 
 void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
   switch (Kind) {
+  case RK_Pattern:
+    if (!Declaration) {
+      // Do nothing: Patterns can come with cursor kinds!
+      break;
+    }
+    // Fall through
+      
   case RK_Declaration: {
     // Set the availability based on attributes.
     switch (getDeclAvailability(Declaration)) {
@@ -488,11 +563,7 @@
   case RK_Keyword:
     Availability = CXAvailability_Available;      
     CursorKind = CXCursor_NotImplemented;
-    break;
-      
-  case RK_Pattern:
-    // Do nothing: Patterns can come with cursor kinds!
-    break;
+    break;      
   }
 
   if (!Accessible)
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index b33c169..3fd66ec 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2454,6 +2454,13 @@
   if (Kind == RK_Pattern) {
     Pattern->Priority = Priority;
     Pattern->Availability = Availability;
+    
+    if (Declaration) {
+      Result.addParentContext(Declaration->getDeclContext());
+      Pattern->ParentKind = Result.getParentKind();
+      Pattern->ParentName = Result.getParentName();
+    }
+    
     return Pattern;
   }
   
@@ -2509,7 +2516,8 @@
   
   assert(Kind == RK_Declaration && "Missed a result kind?");
   NamedDecl *ND = Declaration;
-  
+  Result.addParentContext(ND->getDeclContext());
+                          
   if (StartsNestedNameSpecifier) {
     Result.AddTypedTextChunk(
                       Result.getAllocator().CopyString(ND->getNameAsString()));
@@ -3023,7 +3031,9 @@
     Builder.AddChunk(CodeCompletionString::CK_RightParen);
     Results.AddResult(CodeCompletionResult(Builder.TakeString(),
                                            CCP_SuperCompletion,
-                                           CXCursor_CXXMethod));
+                                           CXCursor_CXXMethod,
+                                           CXAvailability_Available,
+                                           Overridden));
     Results.Ignore(Overridden);
   }
 }
@@ -3342,28 +3352,8 @@
             Builder.AddTypedTextChunk(
                             Results.getAllocator().CopyString(Name->getName()));
             
-            CXAvailabilityKind Availability = CXAvailability_Available;
-            switch (M->getAvailability()) {
-            case AR_Available:
-            case AR_NotYetIntroduced:
-              Availability = CXAvailability_Available;      
-              break;
-              
-            case AR_Deprecated:
-              Availability = CXAvailability_Deprecated;
-              break;
-              
-            case AR_Unavailable:
-              Availability = CXAvailability_NotAvailable;
-              break;
-            }
-
-            Results.MaybeAddResult(Result(Builder.TakeString(),
-                                  CCP_MemberDeclaration + CCD_MethodAsProperty,
-                                          M->isInstanceMethod()
-                                            ? CXCursor_ObjCInstanceMethodDecl
-                                            : CXCursor_ObjCClassMethodDecl,
-                                          Availability),
+            Results.MaybeAddResult(Result(Builder.TakeString(), *M,
+                                  CCP_MemberDeclaration + CCD_MethodAsProperty),
                                           CurContext);
           }
     }
@@ -4028,7 +4018,8 @@
     // namespace to the list of results.
     Results.EnterNewScope();
     for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator 
-         NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
+              NS = OrigToLatest.begin(),
+           NSEnd = OrigToLatest.end();
          NS != NSEnd; ++NS)
       Results.AddResult(CodeCompletionResult(NS->second, 0),
                         CurContext, 0, false);
@@ -4188,7 +4179,9 @@
     Results.AddResult(CodeCompletionResult(Builder.TakeString(), 
                                    SawLastInitializer? CCP_NextInitializer
                                                      : CCP_MemberDeclaration,
-                                           CXCursor_MemberRef));
+                                           CXCursor_MemberRef,
+                                           CXAvailability_Available,
+                                           *Field));
     SawLastInitializer = false;
   }
   Results.ExitScope();
@@ -5057,10 +5050,8 @@
     }
   }
   
-  Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
-                                         SuperMethod->isInstanceMethod()
-                                           ? CXCursor_ObjCInstanceMethodDecl
-                                           : CXCursor_ObjCClassMethodDecl));
+  Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
+                                         CCP_SuperCompletion));
   return SuperMethod;
 }
                                    
@@ -6747,10 +6738,7 @@
     if (!M->second.second)
       Priority += CCD_InBaseClass;
     
-    Results.AddResult(Result(Builder.TakeString(), Priority, 
-                             Method->isInstanceMethod()
-                               ? CXCursor_ObjCInstanceMethodDecl
-                               : CXCursor_ObjCClassMethodDecl));
+    Results.AddResult(Result(Builder.TakeString(), Method, Priority));
   }
 
   // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of 
diff --git a/test/Index/complete-exprs.cpp b/test/Index/complete-exprs.cpp
index 6b7f2f9..de3aac5 100644
--- a/test/Index/complete-exprs.cpp
+++ b/test/Index/complete-exprs.cpp
@@ -34,6 +34,17 @@
 
 }
 
+namespace N {
+  int x;
+  class C {
+    int member;
+
+    int f(int param) {
+      return member;
+    }
+  };
+}
+
 // RUN: c-index-test -code-completion-at=%s:20:2 %s -std=c++0x | FileCheck -check-prefix=CHECK-CC1 %s
 // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:20:2 -std=c++0x %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: NotImplemented:{ResultType size_t}{TypedText alignof}{LeftParen (}{Placeholder type}{RightParen )} (40)
@@ -65,3 +76,9 @@
 
 // RUN: c-index-test -code-completion-at=%s:34:1 %s -std=c++0x | FileCheck -check-prefix=CHECK-CC4 %s
 // CHECK-CC4: NotImplemented:{ResultType const X *}{TypedText this} (40)
+
+// RUN: c-index-test -code-completion-at=%s:43:14 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5: FieldDecl:{ResultType int}{TypedText member} (8) (parent: ClassDecl 'N::C')
+// CHECK-CC5: ParmDecl:{ResultType int}{TypedText param} (8)
+// CHECK-CC5: StructDecl:{TypedText X} (50) (parent: TranslationUnit '(null)')
+// CHECK-CC5: VarDecl:{ResultType int}{TypedText x} (12) (parent: Namespace 'N')
diff --git a/test/Index/complete-method-decls.m b/test/Index/complete-method-decls.m
index 2ab1197..e26359c 100644
--- a/test/Index/complete-method-decls.m
+++ b/test/Index/complete-method-decls.m
@@ -69,11 +69,11 @@
 @end
 
 // RUN: c-index-test -code-completion-at=%s:17:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc}
-// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}
-// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}
-// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}
-// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{TypedText second:}{LeftParen (}{Text int}{RightParen )}{Text y}
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc} (40) (parent: ObjCProtocolDecl 'P1')
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getInt} (40) (parent: ObjCProtocolDecl 'P1')
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf} (40) (parent: ObjCProtocolDecl 'P1')
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x} (40) (parent: ObjCProtocolDecl 'P1')
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{TypedText second:}{LeftParen (}{Text int}{RightParen )}{Text y} (40) (parent: ObjCProtocolDecl 'P1')
 // RUN: c-index-test -code-completion-at=%s:17:7 %s | FileCheck -check-prefix=CHECK-CC2 %s
 // CHECK-CC2: ObjCInstanceMethodDecl:{TypedText abc}
 // CHECK-CC2-NEXT: ObjCInstanceMethodDecl:{TypedText getSelf}
@@ -94,8 +94,8 @@
 // CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{TypedText second:}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace  }{LeftBrace {}{VerticalSpace
 // CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText setValue}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{LeftBrace {}{VerticalSpace
 // RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:33:8 %s | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getInt}{HorizontalSpace  }{LeftBrace {}{VerticalSpace
-// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getSecondValue}{HorizontalSpace  }{LeftBrace {}{VerticalSpace
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getInt}{HorizontalSpace  }{LeftBrace {}{VerticalSpace  }{Text return}{HorizontalSpace  }{Placeholder expression}{SemiColon ;}{VerticalSpace  }{RightBrace }} (42) (parent: ObjCProtocolDecl 'P1')
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getSecondValue}{HorizontalSpace  }{LeftBrace {}{VerticalSpace  }{Text return}{HorizontalSpace  }{Placeholder expression}{SemiColon ;}{VerticalSpace  }{RightBrace }} (40) (parent: ObjCInterfaceDecl 'B')
 // CHECK-CC5-NOT: {TypedText getSelf}{HorizontalSpace  }{LeftBrace {}{VerticalSpace
 // CHECK-CC5: ObjCInstanceMethodDecl:{TypedText setValue}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace  }{LeftBrace {}{VerticalSpace
 // RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:37:7 %s | FileCheck -check-prefix=CHECK-CC6 %s
diff --git a/test/Index/complete-objc-message.m b/test/Index/complete-objc-message.m
index fc25ef8..1835c3e 100644
--- a/test/Index/complete-objc-message.m
+++ b/test/Index/complete-objc-message.m
@@ -190,11 +190,11 @@
 }
 
 // RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: {TypedText categoryClassMethod}
-// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace  }{TypedText withKeyword:}{Placeholder (int)}
-// CHECK-CC1: {TypedText classMethod2}
-// CHECK-CC1: {TypedText new}
-// CHECK-CC1: {TypedText protocolClassMethod}
+// CHECK-CC1: {TypedText categoryClassMethod} (35) (parent: ObjCCategoryDecl 'Foo(FooTestCategory)')
+// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace  }{TypedText withKeyword:}{Placeholder (int)} (35) (parent: ObjCInterfaceDecl 'Foo')
+// CHECK-CC1: {TypedText classMethod2} (35) (parent: ObjCInterfaceDecl 'Foo')
+// CHECK-CC1: {TypedText new} (35) (parent: ObjCInterfaceDecl 'Foo')
+// CHECK-CC1: {TypedText protocolClassMethod} (37) (parent: ObjCProtocolDecl 'FooTestProtocol')
 // CHECK-CC1: Completion contexts:
 // CHECK-CC1-NEXT: Objective-C class method
 // CHECK-CC1-NEXT: Container Kind: ObjCInterfaceDecl
@@ -309,7 +309,7 @@
 
 // RUN: c-index-test -code-completion-at=%s:170:16 %s | FileCheck -check-prefix=CHECK-CLASS-RESULT %s
 // CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method3} (35)
-// CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method4} (35)
+// CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method4} (35) (parent: ObjCCategoryDecl 'A(Cat)')
 
 // RUN: c-index-test -code-completion-at=%s:181:4 %s | FileCheck -check-prefix=CHECK-BLOCK-RECEIVER %s
 // CHECK-BLOCK-RECEIVER: ObjCInterfaceDecl:{TypedText A} (50)
diff --git a/test/Index/complete-qualified.cpp b/test/Index/complete-qualified.cpp
index 20f5105..f5c032c 100644
--- a/test/Index/complete-qualified.cpp
+++ b/test/Index/complete-qualified.cpp
@@ -14,7 +14,7 @@
   Foo::
 
 // RUN: c-index-test -code-completion-at=%s:14:8 %s -o - | FileCheck -check-prefix=CC1 %s
-// CHECK-CC1: FieldDecl:{ResultType C<Foo, class Bar>}{TypedText c} (35)
-// CHECK-CC1: ClassDecl:{TypedText Foo} (35)
-// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{LeftParen (}{Placeholder const Foo &}{RightParen )} (35)
-// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{LeftParen (}{RightParen )} (35)
+// CHECK-CC1: FieldDecl:{ResultType C<Foo, class Bar>}{TypedText c} (35) (parent: ClassDecl 'Foo')
+// CHECK-CC1: ClassDecl:{TypedText Foo} (35) (parent: ClassDecl 'Foo')
+// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{LeftParen (}{Placeholder const Foo &}{RightParen )} (35) (parent: ClassDecl 'Foo')
+// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{LeftParen (}{RightParen )} (35) (parent: ClassDecl 'Foo')
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 67de850..39bb8eb 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1082,7 +1082,9 @@
   FILE *file = (FILE *)client_data;
   CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind);
   unsigned annotationCount;
-
+  enum CXCursorKind ParentKind;
+  CXString ParentName;
+  
   fprintf(file, "%s:", clang_getCString(ks));
   clang_disposeString(ks);
 
@@ -1121,6 +1123,19 @@
     fprintf(file, ")");
   }
 
+  if (!getenv("CINDEXTEST_NO_COMPLETION_PARENTS")) {
+    ParentName = clang_getCompletionParent(completion_result->CompletionString,
+                                           &ParentKind);
+    if (ParentKind != CXCursor_NotImplemented) {
+      CXString KindSpelling = clang_getCursorKindSpelling(ParentKind);
+      fprintf(file, " (parent: %s '%s')",
+              clang_getCString(KindSpelling),
+              clang_getCString(ParentName));
+      clang_disposeString(KindSpelling);
+    }
+    clang_disposeString(ParentName);
+  }
+  
   fprintf(file, "\n");
 }
 
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 10f2411..1b4a7e4 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -213,7 +213,21 @@
                : createCXString((const char *) 0);
 }
 
-
+CXString
+clang_getCompletionParent(CXCompletionString completion_string,
+                          CXCursorKind *kind) {
+  if (kind)
+    *kind = CXCursor_NotImplemented;
+  
+  CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+  if (!CCStr)
+    return createCXString((const char *)0);
+  
+  if (kind)
+    *kind = CCStr->getParentContextKind();
+  return createCXString(CCStr->getParentContextName(), /*DupString=*/false);
+}
+  
 /// \brief The CXCodeCompleteResults structure we allocate internally;
 /// the client only sees the initial CXCodeCompleteResults structure.
 struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 1900ac8..afdb0c9 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -65,6 +65,7 @@
 clang_getCompletionChunkKind
 clang_getCompletionChunkText
 clang_getCompletionNumAnnotations
+clang_getCompletionParent
 clang_getCompletionPriority
 clang_getCursor
 clang_getCursorAvailability