]> granicus.if.org Git - clang/commitdiff
Rework Sema code completion interface.
authorDaniel Dunbar <daniel@zuster.org>
Fri, 13 Nov 2009 08:58:20 +0000 (08:58 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Fri, 13 Nov 2009 08:58:20 +0000 (08:58 +0000)
 - Provide Sema in callbacks, instead of requiring it in constructor. This
   eliminates the need for a factory function. Clients now just pass the object
   to consume the results in directly.

 - CodeCompleteConsumer is cheap to construct, so building it whenever we are
   doing code completion is reasonable.

Doug, please review.

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

include/clang/Sema/CodeCompleteConsumer.h
include/clang/Sema/ParseAST.h
lib/Sema/CodeCompleteConsumer.cpp
lib/Sema/ParseAST.cpp
lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaCodeComplete.cpp
tools/clang-cc/clang-cc.cpp

index c436b398f99692b38aaa54769966e1ba0184982b..5d27b1a90fde77d6b0f7d63c4bec15d4d41b4f59 100644 (file)
@@ -373,17 +373,18 @@ public:
   /// \name Code-completion callbacks
   //@{
   /// \brief Process the finalized code-completion results.
-  virtual void ProcessCodeCompleteResults(Result *Results, 
+  virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
                                           unsigned NumResults) { }
-  
-  /// \brief Process the set of overload candidates.
+
+  /// \param S the semantic-analyzer object for which code-completion is being
+  /// done.
   ///
   /// \param CurrentArg the index of the current argument.
   ///
   /// \param Candidates an array of overload candidates.
   ///
   /// \param NumCandidates the number of overload candidates
-  virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+  virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                          OverloadCandidate *Candidates,
                                          unsigned NumCandidates) { }
   //@}
@@ -392,25 +393,21 @@ public:
 /// \brief A simple code-completion consumer that prints the results it 
 /// receives in a simple format.
 class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
-  /// \brief The semantic-analysis object to which this code-completion
-  /// consumer is attached.
-  Sema &SemaRef;
-  
   /// \brief The raw output stream.
   llvm::raw_ostream &OS;
     
 public:
   /// \brief Create a new printing code-completion consumer that prints its
   /// results to the given raw output stream.
-  PrintingCodeCompleteConsumer(Sema &S, bool IncludeMacros, 
+  PrintingCodeCompleteConsumer(bool IncludeMacros,
                                llvm::raw_ostream &OS)
-    : CodeCompleteConsumer(IncludeMacros), SemaRef(S), OS(OS) { }
+    : CodeCompleteConsumer(IncludeMacros), OS(OS) { }
   
   /// \brief Prints the finalized code-completion results.
-  virtual void ProcessCodeCompleteResults(Result *Results, 
+  virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
                                           unsigned NumResults);
   
-  virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+  virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                          OverloadCandidate *Candidates,
                                          unsigned NumCandidates);  
 };
@@ -418,10 +415,6 @@ public:
 /// \brief A code-completion consumer that prints the results it receives
 /// in a format that is parsable by the CIndex library.
 class CIndexCodeCompleteConsumer : public CodeCompleteConsumer {
-  /// \brief The semantic-analysis object to which this code-completion
-  /// consumer is attached.
-  Sema &SemaRef;
-  
   /// \brief The raw output stream.
   llvm::raw_ostream &OS;
   
@@ -429,14 +422,14 @@ public:
   /// \brief Create a new CIndex code-completion consumer that prints its
   /// results to the given raw output stream in a format readable to the CIndex
   /// library.
-  CIndexCodeCompleteConsumer(Sema &S, bool IncludeMacros, llvm::raw_ostream &OS)
-    : CodeCompleteConsumer(IncludeMacros), SemaRef(S), OS(OS) { }
+  CIndexCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS)
+    : CodeCompleteConsumer(IncludeMacros), OS(OS) { }
   
   /// \brief Prints the finalized code-completion results.
-  virtual void ProcessCodeCompleteResults(Result *Results, 
+  virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, 
                                           unsigned NumResults);
   
-  virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+  virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
                                          OverloadCandidate *Candidates,
                                          unsigned NumCandidates);  
 };
index 8a245d03cdaa32e5a390a0d41efadbf6d44706a2..f6cff2a023e63392781e273ddf54f32298da5485 100644 (file)
@@ -20,7 +20,7 @@ namespace clang {
   class ASTContext;
   class CodeCompleteConsumer;
   class Sema;
-  
+
   /// \brief Parse the entire file specified, notifying the ASTConsumer as
   /// the file is parsed.
   ///
@@ -30,11 +30,13 @@ namespace clang {
   /// \param CompleteTranslationUnit When true, the parsed file is
   /// considered to be a complete translation unit, and any
   /// end-of-translation-unit wrapup will be performed.
+  ///
+  /// \param CompletionConsumer If given, an object to consume code completion
+  /// results.
   void ParseAST(Preprocessor &pp, ASTConsumer *C,
                 ASTContext &Ctx, bool PrintStats = false,
                 bool CompleteTranslationUnit = true,
-           CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data) = 0,
-                void *CreateCodeCompleterData = 0);
+                CodeCompleteConsumer *CompletionConsumer = 0);
 
 }  // end namespace clang
 
index f94989ee7215f98db8671396daad960245dd28ef..3529ece25740bc3af34728596e71b23c426733c6 100644 (file)
@@ -508,7 +508,8 @@ CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
 CodeCompleteConsumer::~CodeCompleteConsumer() { }
 
 void 
-PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, 
+PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+                                                         Result *Results, 
                                                          unsigned NumResults) {
   // Print the results.
   for (unsigned I = 0; I != NumResults; ++I) {
@@ -552,7 +553,8 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
 }
 
 void 
-PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
+PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+                                                        unsigned CurrentArg,
                                               OverloadCandidate *Candidates,
                                                      unsigned NumCandidates) {
   for (unsigned I = 0; I != NumCandidates; ++I) {
@@ -570,7 +572,8 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
 }
 
 void 
-CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, 
+CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
+                                                       Result *Results, 
                                                        unsigned NumResults) {
   // Print the results.
   for (unsigned I = 0; I != NumResults; ++I) {
@@ -632,7 +635,8 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
 }
 
 void 
-CIndexCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
+CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
+                                                      unsigned CurrentArg,
                                                 OverloadCandidate *Candidates,
                                                        unsigned NumCandidates) {
   for (unsigned I = 0; I != NumCandidates; ++I) {
index d3f26d875cc4f3940853a34bd857a199347e1c9b..9afc8100c7eb6cb048203d1e6baf67c4126d97d3 100644 (file)
@@ -35,15 +35,14 @@ using namespace clang;
 void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
                      ASTContext &Ctx, bool PrintStats,
                      bool CompleteTranslationUnit,
-               CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data),
-                     void *CreateCodeCompleterData) {
+                     CodeCompleteConsumer *CompletionConsumer) {
   // Collect global stats on Decls/Stmts (until we have a module streamer).
   if (PrintStats) {
     Decl::CollectingStats(true);
     Stmt::CollectingStats(true);
   }
 
-  Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit);
+  Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer);
   Parser P(PP, S);
   PP.EnterMainSourceFile();
 
@@ -63,12 +62,6 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
     External->StartTranslationUnit(Consumer);
   }
 
-  CodeCompleteConsumer *CodeCompleter = 0;
-  if (CreateCodeCompleter) {
-    CodeCompleter = CreateCodeCompleter(S, CreateCodeCompleterData);
-    S.setCodeCompleteConsumer(CodeCompleter);
-  }
-  
   Parser::DeclGroupPtrTy ADecl;
 
   while (!P.ParseTopLevelDecl(ADecl)) {  // Not end of file.
@@ -87,9 +80,6 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
 
   Consumer->HandleTranslationUnit(Ctx);
 
-  if (CreateCodeCompleter)
-    delete CodeCompleter;
-  
   if (PrintStats) {
     fprintf(stderr, "\nSTATISTICS:\n");
     P.getActions().PrintStats();
index f6f572feec0a985280b97ee771c219ce262a1d5e..b2bbac8bc2a91acba067ffab57bc56f24d0e3742 100644 (file)
@@ -347,10 +347,11 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
 }
 
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
-           bool CompleteTranslationUnit)
+           bool CompleteTranslationUnit,
+           CodeCompleteConsumer *CodeCompleter)
   : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
-    ExternalSource(0), CodeCompleter(0), CurContext(0), 
+    ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 
     PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0),
     IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
     GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
index 4a6d01b4e24aa5ce493869e9926b07a1227c4a9f..2324a51650429ed87b0bebf128e0661bf8b34397 100644 (file)
@@ -373,7 +373,8 @@ public:
   bool isSelfExpr(Expr *RExpr);
 public:
   Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
-       bool CompleteTranslationUnit = true);
+       bool CompleteTranslationUnit = true,
+       CodeCompleteConsumer *CompletionConsumer = 0);
   ~Sema() {
     if (PackContext) FreePackedContext();
   }
@@ -3853,7 +3854,6 @@ public:
 
   /// \name Code completion
   //@{
-  void setCodeCompleteConsumer(CodeCompleteConsumer *CCC);
   virtual void CodeCompleteOrdinaryName(Scope *S);
   virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
                                                SourceLocation OpLoc,
index 072dfe9b73ad7d30cc16d9de11e8c902e2b2049e..84262a4c8f06b11fa25f4a00a0c7fe0e5a070061 100644 (file)
 
 using namespace clang;
 
-/// \brief Set the code-completion consumer for semantic analysis.
-void Sema::setCodeCompleteConsumer(CodeCompleteConsumer *CCC) {
-  assert(((CodeCompleter != 0) != (CCC != 0)) && 
-         "Already set or cleared a code-completion consumer?");
-  CodeCompleter = CCC;
-}
-
 namespace {
   /// \brief A container of code-completion results.
   class ResultBuilder {
@@ -1079,14 +1072,15 @@ static void AddMacroResults(Preprocessor &PP, unsigned Rank,
   Results.ExitScope();
 }
 
-static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter,
-                                      CodeCompleteConsumer::Result *Results,
-                                      unsigned NumResults) {
+static void HandleCodeCompleteResults(Sema *S,
+                                      CodeCompleteConsumer *CodeCompleter,
+                                     CodeCompleteConsumer::Result *Results,
+                                     unsigned NumResults) {
   // Sort the results by rank/kind/etc.
   std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult());
 
   if (CodeCompleter)
-    CodeCompleter->ProcessCodeCompleteResults(Results, NumResults);
+    CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults);
 }
 
 void Sema::CodeCompleteOrdinaryName(Scope *S) {
@@ -1095,7 +1089,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S) {
                                            0, CurContext, Results);
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
@@ -1120,46 +1114,46 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
   
   ResultBuilder Results(*this, &ResultBuilder::IsMember);
   unsigned NextRank = 0;
-  
-  if (const RecordType *Record = BaseType->getAs<RecordType>()) {
-    NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank, 
-                                          Record->getDecl(), Results);
-    
-    if (getLangOptions().CPlusPlus) {
-      if (!Results.empty()) {
-        // The "template" keyword can follow "->" or "." in the grammar.
-        // However, we only want to suggest the template keyword if something
-        // is dependent.
-        bool IsDependent = BaseType->isDependentType();
-        if (!IsDependent) {
-          for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
-            if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
-              IsDependent = Ctx->isDependentContext();
-              break;
-            }
-        }
-        
-        if (IsDependent)
-          Results.MaybeAddResult(Result("template", NextRank++));
+
+  // If this isn't a record type, we are done.
+  const RecordType *Record = BaseType->getAs<RecordType>();
+  if (!Record)
+    return;
+
+  NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
+                                        Record->getDecl(), Results);
+
+  if (getLangOptions().CPlusPlus) {
+    if (!Results.empty()) {
+      // The "template" keyword can follow "->" or "." in the grammar.
+      // However, we only want to suggest the template keyword if something
+      // is dependent.
+      bool IsDependent = BaseType->isDependentType();
+      if (!IsDependent) {
+        for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
+          if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
+            IsDependent = Ctx->isDependentContext();
+            break;
+          }
       }
-      
-      // We could have the start of a nested-name-specifier. Add those
-      // results as well.
-      Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
-      CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank, 
-                           CurContext, Results);
+
+      if (IsDependent)
+        Results.MaybeAddResult(Result("template", NextRank++));
     }
-    
-    // Add macros
-    if (CodeCompleter->includeMacros())
-      AddMacroResults(PP, NextRank, Results);
-    
-    // Hand off the results found for code completion.
-    HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
-    
-    // We're done!
-    return;
+
+    // We could have the start of a nested-name-specifier. Add those
+    // results as well.
+    Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+    CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
+                         CurContext, Results);
   }
+
+  // Add macros
+  if (CodeCompleter->includeMacros())
+    AddMacroResults(PP, NextRank, Results);
+
+  // Hand off the results found for code completion.
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
@@ -1201,7 +1195,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
   
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteCase(Scope *S) {
@@ -1280,7 +1274,7 @@ void Sema::CodeCompleteCase(Scope *S) {
   
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, 1, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 namespace {
@@ -1352,7 +1346,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
     if (Cand->Viable)
       Results.push_back(ResultCandidate(Cand->Function));
   }
-  CodeCompleter->ProcessOverloadCandidates(NumArgs, Results.data(), 
+  CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), 
                                            Results.size());
 }
 
@@ -1376,7 +1370,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,
   
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank + 1, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteUsing(Scope *S) {
@@ -1398,7 +1392,7 @@ void Sema::CodeCompleteUsing(Scope *S) {
   
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteUsingDirective(Scope *S) {
@@ -1414,7 +1408,7 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
   Results.ExitScope();
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteNamespaceDecl(Scope *S)  {
@@ -1450,7 +1444,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S)  {
   
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, 1, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteNamespaceAliasDecl(Scope *S)  {
@@ -1463,7 +1457,7 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S)  {
                                            0, CurContext, Results);
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteOperatorName(Scope *S) {
@@ -1495,7 +1489,7 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
   
   if (CodeCompleter->includeMacros())
     AddMacroResults(PP, NextRank, Results);
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { 
@@ -1523,7 +1517,7 @@ void Sema::CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) {
   if (!(Attributes & ObjCDeclSpec::DQ_PR_getter))
     Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0));
   Results.ExitScope();
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName) {
@@ -1574,7 +1568,7 @@ void Sema::CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName) {
   }
   Results.ExitScope();
   // This also suppresses remaining diagnostics.
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
 
 void Sema::CodeCompleteObjCInstanceMethod(Scope *S, ExprTy *Receiver) {
@@ -1634,5 +1628,5 @@ void Sema::CodeCompleteObjCInstanceMethod(Scope *S, ExprTy *Receiver) {
   }
   Results.ExitScope();
   // This also suppresses remaining diagnostics.
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());  
+  HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
 }
index b186f20ed53c8d5296ff592075dc140edb9f93a8..5092e1ab32865c8b4e8598938c2bc804153e5608 100644 (file)
@@ -210,19 +210,6 @@ std::string GetBuiltinIncludePath(const char *Argv0) {
   return P.str();
 }
 
-/// \brief Buld a new code-completion consumer that prints the results of
-/// code completion to standard output.
-static CodeCompleteConsumer *BuildPrintingCodeCompleter(Sema &S,
-                                                        void *UserData) {
-  const FrontendOptions &Opts = *(FrontendOptions*)UserData;
-  if (Opts.DebugCodeCompletionPrinter)
-    return new PrintingCodeCompleteConsumer(S, Opts.ShowMacrosInCodeCompletion,
-                                            llvm::outs());
-
-  return new CIndexCodeCompleteConsumer(S, Opts.ShowMacrosInCodeCompletion,
-                                        llvm::outs());
-}
-
 //===----------------------------------------------------------------------===//
 // Basic Parser driver
 //===----------------------------------------------------------------------===//
@@ -494,9 +481,7 @@ static void ProcessInputFile(CompilerInstance &CI, const std::string &InFile,
     if (InitializeSourceManager(PP, CI.getFrontendOpts(), InFile))
       return;
 
-    CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *) = 0;
-    void *CreateCodeCompleterData = (void*) &FEOpts;
-
+    llvm::OwningPtr<CodeCompleteConsumer> CCConsumer;
     if (!FEOpts.CodeCompletionAt.FileName.empty()) {
       // Tell the source manager to chop off the given file at a specific
       // line and column.
@@ -508,7 +493,14 @@ static void ProcessInputFile(CompilerInstance &CI, const std::string &InFile,
                                              FEOpts.CodeCompletionAt.Column);
 
         // Set up the creation routine for code-completion.
-        CreateCodeCompleter = BuildPrintingCodeCompleter;
+        if (FEOpts.DebugCodeCompletionPrinter)
+          CCConsumer.reset(
+            new PrintingCodeCompleteConsumer(FEOpts.ShowMacrosInCodeCompletion,
+                                             llvm::outs()));
+        else
+          CCConsumer.reset(
+            new CIndexCodeCompleteConsumer(FEOpts.ShowMacrosInCodeCompletion,
+                                           llvm::outs()));
       } else {
         PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
           << FEOpts.CodeCompletionAt.FileName;
@@ -518,7 +510,7 @@ static void ProcessInputFile(CompilerInstance &CI, const std::string &InFile,
     // Run the AST consumer action.
     ParseAST(PP, Consumer.get(), CI.getASTContext(), FEOpts.ShowStats,
              CompleteTranslationUnit,
-             CreateCodeCompleter, CreateCodeCompleterData);
+             CCConsumer.get());
   } else {
     // Initialize builtin info.
     PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),