[cfe-commits] r111051 - in /cfe/trunk: include/clang/Frontend/ASTUnit.h include/clang/Sema/CodeCompleteConsumer.h include/clang/Sema/Sema.h lib/Frontend/ASTUnit.cpp lib/Sema/CodeCompleteConsumer.cpp lib/Sema/Sema.cpp lib/Sema/SemaCodeComplete.cpp test/Index/complete-macros.c tools/c-index-test/c-index-test.c tools/libclang/CIndex.cpp tools/libclang/CIndexCodeCompletion.cpp

Douglas Gregor dgregor at apple.com
Fri Aug 13 15:48:40 PDT 2010


Author: dgregor
Date: Fri Aug 13 17:48:40 2010
New Revision: 111051

URL: http://llvm.org/viewvc/llvm-project?rev=111051&view=rev
Log:
Implement caching of code-completion results for macro definitions
when the CXTranslationUnit_CacheCompletionResults option is given to
clang_parseTranslationUnit(). Essentially, we compute code-completion
results for macro definitions after we have parsed the file, then
store an ASTContext-agnostic version of those results (completion
string, cursor kind, priority, and active contexts) in the
ASTUnit. When performing code completion in that ASTUnit, we splice 
the macro definition results into the results provided by the actual
code-completion (which has had macros turned off) before libclang gets
those results. We use completion context information to only splice in
those results that make sense for that context.

With a completion involving all of the macros from Cocoa.h and a few other
system libraries (totally ~8500 macro definitions) living in a
precompiled header, we get about a 9% performance improvement from
code completion, since we no longer have to deserialize all of the
macro definitions from the precompiled header. 

Note that macro definitions are merely the canary; the cache is
designed to also support other top-level declarations, which should be
a bigger performance win. That optimization will be next.

Note also that there is no mechanism for determining when to throw
away the cache and recompute its contents.


Modified:
    cfe/trunk/include/clang/Frontend/ASTUnit.h
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-macros.c
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Fri Aug 13 17:48:40 2010
@@ -20,6 +20,7 @@
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/FileManager.h"
+#include "clang-c/Index.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/SmallVector.h"
@@ -198,6 +199,55 @@
   /// declarations parsed within the precompiled preamble.
   std::vector<pch::DeclID> TopLevelDeclsInPreamble;
 
+  ///
+  /// \defgroup CodeCompleteCaching Code-completion caching
+  ///
+  /// \{
+  ///
+
+  /// \brief Whether we should be caching code-completion results.
+  bool ShouldCacheCodeCompletionResults;
+  
+public:
+  /// \brief A cached code-completion result, which may be introduced in one of
+  /// many different contexts.
+  struct CachedCodeCompletionResult {
+    /// \brief The code-completion string corresponding to this completion
+    /// result.
+    CodeCompletionString *Completion;
+    
+    /// \brief A bitmask that indicates which code-completion contexts should
+    /// contain this completion result.
+    ///
+    /// The bits in the bitmask correspond to the values of 
+    /// CodeCompleteContext::Kind. To map from a completion context kind to a 
+    /// bit, subtract one from the completion context kind and shift 1 by that
+    /// number of bits. Many completions can occur in several different
+    /// contexts.
+    unsigned ShowInContexts;
+    
+    /// \brief The priority given to this code-completion result.
+    unsigned Priority;
+    
+    /// \brief The libclang cursor kind corresponding to this code-completion 
+    /// result.
+    CXCursorKind Kind;
+  };
+  
+private:
+  /// \brief The set of cached code-completion results.
+  std::vector<CachedCodeCompletionResult> CachedCompletionResults;
+  
+  /// \brief Cache any "global" code-completion results, so that we 
+  void CacheCodeCompletionResults();
+  
+  /// \brief Clear out and deallocate 
+  void ClearCachedCompletionResults();
+  
+  /// 
+  /// \}
+  ///
+  
   /// \brief The timers we've created from the various parses, reparses, etc.
   /// involved in this translation unit.
   std::vector<llvm::Timer *> Timers;
@@ -339,6 +389,21 @@
     return StoredDiagnostics; 
   }
 
+  typedef std::vector<CachedCodeCompletionResult>::iterator
+    cached_completion_iterator;
+  
+  cached_completion_iterator cached_completion_begin() {
+    return CachedCompletionResults.begin();
+  }
+
+  cached_completion_iterator cached_completion_end() {
+    return CachedCompletionResults.end();
+  }
+
+  unsigned cached_completion_size() const { 
+    return CachedCompletionResults.size(); 
+  }
+  
   /// \brief Whether this AST represents a complete translation unit.
   ///
   /// If false, this AST is only a partial translation unit, e.g., one
@@ -380,7 +445,8 @@
                                              bool OnlyLocalDecls = false,
                                              bool CaptureDiagnostics = false,
                                              bool PrecompilePreamble = false,
-                                          bool CompleteTranslationUnit = true);
+                                          bool CompleteTranslationUnit = true,
+                                       bool CacheCodeCompletionResults = false);
 
   /// LoadFromCommandLine - Create an ASTUnit from a vector of command line
   /// arguments, which must specify exactly one source file.
@@ -405,7 +471,8 @@
                                       unsigned NumRemappedFiles = 0,
                                       bool CaptureDiagnostics = false,
                                       bool PrecompilePreamble = false,
-                                      bool CompleteTranslationUnit = true);
+                                      bool CompleteTranslationUnit = true,
+                                      bool CacheCodeCompletionResults = false);
   
   /// \brief Reparse the source files using the same command-line options that
   /// were originally used to produce this translation unit.

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Fri Aug 13 17:48:40 2010
@@ -16,6 +16,7 @@
 #include "clang/AST/Type.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "clang-c/Index.h"
 #include <memory>
 #include <string>
 
@@ -419,6 +420,9 @@
     /// \brief The priority of this particular code-completion result.
     unsigned Priority;
 
+    /// \brief The cursor kind that describes this result.
+    CXCursorKind CursorKind;
+    
     /// \brief Specifies which parameter (of a function, Objective-C method,
     /// macro, etc.) we should start with when formatting the result.
     unsigned StartParameter;
@@ -455,6 +459,7 @@
         Hidden(false), QualifierIsInformative(QualifierIsInformative),
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
         DeclaringEntity(false), Qualifier(Qualifier) { 
+      computeCursorKind();
     }
     
     /// \brief Build a result that refers to a keyword or symbol.
@@ -462,21 +467,29 @@
       : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), 
         StartParameter(0), Hidden(false), QualifierIsInformative(0), 
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        DeclaringEntity(false), Qualifier(0) { }
+        DeclaringEntity(false), Qualifier(0) {
+      computeCursorKind();
+    }
     
     /// \brief Build a result that refers to a macro.
     Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
-     : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0), 
-       Hidden(false), QualifierIsInformative(0), 
-       StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-       DeclaringEntity(false), Qualifier(0) { }
+      : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0), 
+        Hidden(false), QualifierIsInformative(0), 
+        StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+        DeclaringEntity(false), Qualifier(0) { 
+      computeCursorKind();
+    }
 
     /// \brief Build a result that refers to a pattern.
-    Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern)
+    Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern,
+           CXCursorKind CursorKind = CXCursor_NotImplemented)
       : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), 
-        StartParameter(0), Hidden(false), QualifierIsInformative(0), 
-        StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        DeclaringEntity(false), Qualifier(0) { }
+        CursorKind(CursorKind), StartParameter(0), Hidden(false), 
+        QualifierIsInformative(0), StartsNestedNameSpecifier(false), 
+        AllParametersAreInformative(false), DeclaringEntity(false), 
+        Qualifier(0) 
+    { 
+    }
     
     /// \brief Retrieve the declaration stored in this result.
     NamedDecl *getDeclaration() const {
@@ -505,6 +518,9 @@
     
     /// brief Determine a base priority for the given declaration.
     static unsigned getPriorityFromDecl(NamedDecl *ND);
+    
+  private:
+    void computeCursorKind();
   };
     
   class OverloadCandidate {
@@ -571,7 +587,8 @@
                                                 Sema &S) const;    
   };
   
-  CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { }
+  CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
+                           OutputIsBinary(false) { }
   
   CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
                        bool OutputIsBinary)

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Aug 13 17:48:40 2010
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_AST_SEMA_H
 
 #include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Sema/CXXFieldCollector.h"
 #include "clang/Sema/Overload.h"
 #include "clang/Sema/Template.h"
@@ -46,7 +47,6 @@
 namespace clang {
   class ASTContext;
   class ASTConsumer;
-  class CodeCompleteConsumer;
   class Preprocessor;
   class Decl;
   class DeclContext;
@@ -4701,7 +4701,8 @@
                                                   TypeTy *ReturnType,
                                                   IdentifierInfo **SelIdents,
                                                   unsigned NumSelIdents);
-  
+  void GatherGlobalCodeCompletions(
+                  llvm::SmallVectorImpl<CodeCompleteConsumer::Result> &Results);
   //@}
 
   //===--------------------------------------------------------------------===//

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Fri Aug 13 17:48:40 2010
@@ -50,7 +50,8 @@
 ASTUnit::ASTUnit(bool _MainFileIsAST)
   : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST), 
     CompleteTranslationUnit(true), ConcurrencyCheckValue(CheckUnlocked), 
-    PreambleRebuildCounter(0), SavedMainFileBuffer(0) { 
+    PreambleRebuildCounter(0), SavedMainFileBuffer(0),
+    ShouldCacheCodeCompletionResults(false) { 
 }
 
 ASTUnit::~ASTUnit() {
@@ -75,6 +76,8 @@
   
   delete SavedMainFileBuffer;
   
+  ClearCachedCompletionResults();
+  
   for (unsigned I = 0, N = Timers.size(); I != N; ++I)
     delete Timers[I];
 }
@@ -85,6 +88,70 @@
   TemporaryFiles.clear();
 }
 
+void ASTUnit::CacheCodeCompletionResults() {
+  if (!TheSema)
+    return;
+  
+  llvm::Timer *CachingTimer = 0;
+  if (TimerGroup.get()) {
+    CachingTimer = new llvm::Timer("Cache global code completions", 
+                                   *TimerGroup);
+    CachingTimer->startTimer();
+    Timers.push_back(CachingTimer);
+  }
+
+  // Clear out the previous results.
+  ClearCachedCompletionResults();
+  
+  // Gather the set of global code completions.
+  typedef CodeCompleteConsumer::Result Result;
+  llvm::SmallVector<Result, 8> Results;
+  TheSema->GatherGlobalCodeCompletions(Results);
+  
+  // Translate global code completions into cached completions.
+  for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+    switch (Results[I].Kind) {
+    case Result::RK_Declaration:
+      // FIXME: Handle declarations!
+      break;
+      
+    case Result::RK_Keyword:
+    case Result::RK_Pattern:
+      // Ignore keywords and patterns; we don't care, since they are so
+      // easily regenerated.
+      break;
+      
+    case Result::RK_Macro: {
+      CachedCodeCompletionResult CachedResult;
+      CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
+      CachedResult.ShowInContexts
+        = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+        | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+        | (1 << (CodeCompletionContext::CCC_Statement - 1))
+        | (1 << (CodeCompletionContext::CCC_Expression - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+      CachedResult.Priority = Results[I].Priority;
+      CachedResult.Kind = Results[I].CursorKind;
+      CachedCompletionResults.push_back(CachedResult);
+      break;
+    }
+    }
+    Results[I].Destroy();
+  }
+
+  if (CachingTimer)
+    CachingTimer->stopTimer();
+}
+
+void ASTUnit::ClearCachedCompletionResults() {
+  for (unsigned I = 0, N = CachedCompletionResults.size(); I != N; ++I)
+    delete CachedCompletionResults[I].Completion;
+  CachedCompletionResults.clear();
+}
+
 namespace {
 
 /// \brief Gathers information from PCHReader that will be used to initialize
@@ -542,6 +609,12 @@
   Clang.takeDiagnosticClient();
   
   Invocation.reset(Clang.takeInvocation());
+  
+  // If we were asked to cache code-completion results and don't have any
+  // results yet, do so now.
+  if (ShouldCacheCodeCompletionResults && CachedCompletionResults.empty())
+    CacheCodeCompletionResults();
+  
   return false;
   
 error:
@@ -579,7 +652,6 @@
   if (P.createTemporaryFileOnDisk())
     return std::string();
   
-  fprintf(stderr, "Preamble file: %s\n", P.str().c_str());
   return P.str();
 }
 
@@ -1044,7 +1116,8 @@
                                              bool OnlyLocalDecls,
                                              bool CaptureDiagnostics,
                                              bool PrecompilePreamble,
-                                             bool CompleteTranslationUnit) {
+                                             bool CompleteTranslationUnit,
+                                             bool CacheCodeCompletionResults) {
   if (!Diags.getPtr()) {
     // No diagnostics engine was provided, so create our own diagnostics object
     // with the default options.
@@ -1059,6 +1132,7 @@
   AST->CaptureDiagnostics = CaptureDiagnostics;
   AST->OnlyLocalDecls = OnlyLocalDecls;
   AST->CompleteTranslationUnit = CompleteTranslationUnit;
+  AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
   AST->Invocation.reset(CI);
   CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
   
@@ -1097,7 +1171,8 @@
                                       unsigned NumRemappedFiles,
                                       bool CaptureDiagnostics,
                                       bool PrecompilePreamble,
-                                      bool CompleteTranslationUnit) {
+                                      bool CompleteTranslationUnit,
+                                      bool CacheCodeCompletionResults) {
   if (!Diags.getPtr()) {
     // No diagnostics engine was provided, so create our own diagnostics object
     // with the default options.
@@ -1159,7 +1234,8 @@
   CI->getFrontendOpts().DisableFree = true;
   return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
                                     CaptureDiagnostics, PrecompilePreamble,
-                                    CompleteTranslationUnit);
+                                    CompleteTranslationUnit,
+                                    CacheCodeCompletionResults);
 }
 
 bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
@@ -1196,6 +1272,91 @@
   return Result;
 }
 
+//----------------------------------------------------------------------------//
+// Code completion
+//----------------------------------------------------------------------------//
+
+namespace {
+  /// \brief Code completion consumer that combines the cached code-completion
+  /// results from an ASTUnit with the code-completion results provided to it,
+  /// then passes the result on to 
+  class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
+    unsigned NormalContexts;
+    ASTUnit &AST;
+    CodeCompleteConsumer &Next;
+    
+  public:
+    AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
+                                  bool IncludeMacros, bool IncludeCodePatterns)
+      : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns,
+                             Next.isOutputBinary()), AST(AST), Next(Next) 
+    { 
+      // Compute the set of contexts in which we will look when we don't have
+      // any information about the specific context.
+      NormalContexts 
+        = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+        | (1 << (CodeCompletionContext::CCC_Statement - 1))
+        | (1 << (CodeCompletionContext::CCC_Expression - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+        | (1 << (CodeCompletionContext::CCC_MemberAccess - 1))
+        | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
+      
+      if (AST.getASTContext().getLangOptions().CPlusPlus)
+        NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1))
+                    | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
+                    | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+    }
+    
+    virtual void ProcessCodeCompleteResults(Sema &S, 
+                                            CodeCompletionContext Context,
+                                            Result *Results,
+                                            unsigned NumResults) { 
+      // Merge the results we were given with the results we cached.
+      bool AddedResult = false;
+      unsigned InContexts = 
+        (Context.getKind() == CodeCompletionContext::CCC_Other? NormalContexts
+                                              : (1 << (Context.getKind() - 1)));
+      typedef CodeCompleteConsumer::Result Result;
+      llvm::SmallVector<Result, 8> AllResults;
+      for (ASTUnit::cached_completion_iterator 
+               C = AST.cached_completion_begin(),
+            CEnd = AST.cached_completion_end();
+           C != CEnd; ++C) {
+        // If the context we are in matches any of the contexts we are 
+        // interested in, we'll add this result.
+        if ((C->ShowInContexts & InContexts) == 0)
+          continue;
+        
+        // If we haven't added any results previously, do so now.
+        if (!AddedResult) {
+          AllResults.insert(AllResults.end(), Results, Results + NumResults);
+          AddedResult = true;
+        }
+        
+        AllResults.push_back(Result(C->Completion, C->Priority, C->Kind));
+      }
+      
+      // If we did not add any cached completion results, just forward the
+      // results we were given to the next consumer.
+      if (!AddedResult) {
+        Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
+        return;
+      }
+      
+      Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
+                                      AllResults.size());
+    }
+    
+    virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+                                           OverloadCandidate *Candidates,
+                                           unsigned NumCandidates) { 
+      Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
+    }
+  };
+}
 void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
                            RemappedFile *RemappedFiles, 
                            unsigned NumRemappedFiles,
@@ -1223,7 +1384,8 @@
   FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
   PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
 
-  FrontendOpts.ShowMacrosInCodeCompletion = IncludeMacros;
+  FrontendOpts.ShowMacrosInCodeCompletion
+    = IncludeMacros && CachedCompletionResults.empty();
   FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
   FrontendOpts.CodeCompletionAt.FileName = File;
   FrontendOpts.CodeCompletionAt.Line = Line;
@@ -1281,8 +1443,12 @@
     PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
                                      RemappedFiles[I].second);
   
-  // Use the code completion consumer we were given.
-  Clang.setCodeCompletionConsumer(&Consumer);
+  // Use the code completion consumer we were given, but adding any cached
+  // code-completion results.
+  AugmentedCodeCompleteConsumer 
+  AugmentedConsumer(*this, Consumer, FrontendOpts.ShowMacrosInCodeCompletion,
+                    FrontendOpts.ShowCodePatternsInCodeCompletion);
+  Clang.setCodeCompletionConsumer(&AugmentedConsumer);
 
   // If we have a precompiled preamble, try to use it. We only allow
   // the use of the precompiled preamble if we're if the completion

Modified: cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Fri Aug 13 17:48:40 2010
@@ -496,95 +496,109 @@
   }
 }
 
-namespace clang {
-  // FIXME: Used externally by CIndexCodeCompletion.cpp; this code
-  // will move there, eventually, when the CIndexCodeCompleteConsumer
-  // dies.
-  CXCursorKind 
-  getCursorKindForCompletionResult(const CodeCompleteConsumer::Result &R) {
-    typedef CodeCompleteConsumer::Result Result;
-    switch (R.Kind) {
-    case Result::RK_Declaration:
-      switch (R.Declaration->getKind()) {
-      case Decl::Record:
-      case Decl::CXXRecord:
-      case Decl::ClassTemplateSpecialization: {
-        RecordDecl *Record = cast<RecordDecl>(R.Declaration);
-        if (Record->isStruct())
-          return CXCursor_StructDecl;
-        else if (Record->isUnion())
-          return CXCursor_UnionDecl;
-        else
-          return CXCursor_ClassDecl;
-      }
-        
-      case Decl::ObjCMethod: {
-        ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
-        if (Method->isInstanceMethod())
-            return CXCursor_ObjCInstanceMethodDecl;
-        else
-          return CXCursor_ObjCClassMethodDecl;
-      }
-        
-      case Decl::Typedef:
-        return CXCursor_TypedefDecl;
-        
-      case Decl::Enum:
-        return CXCursor_EnumDecl;
-        
-      case Decl::Field:
-        return CXCursor_FieldDecl;
-        
-      case Decl::EnumConstant:
-        return CXCursor_EnumConstantDecl;
-        
-      case Decl::Function:
-      case Decl::CXXMethod:
-      case Decl::CXXConstructor:
-      case Decl::CXXDestructor:
-      case Decl::CXXConversion:
-        return CXCursor_FunctionDecl;
-        
-      case Decl::Var:
-        return CXCursor_VarDecl;
-        
-      case Decl::ParmVar:
-        return CXCursor_ParmDecl;
-        
-      case Decl::ObjCInterface:
-        return CXCursor_ObjCInterfaceDecl;
-        
-      case Decl::ObjCCategory:
-        return CXCursor_ObjCCategoryDecl;
-        
-      case Decl::ObjCProtocol:
-        return CXCursor_ObjCProtocolDecl;
-        
-      case Decl::ObjCProperty:
-        return CXCursor_ObjCPropertyDecl;
-        
-      case Decl::ObjCIvar:
-        return CXCursor_ObjCIvarDecl;
-        
-      case Decl::ObjCImplementation:
-        return CXCursor_ObjCImplementationDecl;
-        
-      case Decl::ObjCCategoryImpl:
-        return CXCursor_ObjCCategoryImplDecl;
-        
-      default:
-        break;
-      }
+void CodeCompleteConsumer::Result::computeCursorKind() {
+  switch (Kind) {
+  case RK_Declaration:
+    switch (Declaration->getKind()) {
+    case Decl::Record:
+    case Decl::CXXRecord:
+    case Decl::ClassTemplateSpecialization: {
+      RecordDecl *Record = cast<RecordDecl>(Declaration);
+      if (Record->isStruct())
+        CursorKind = CXCursor_StructDecl;
+      else if (Record->isUnion())
+        CursorKind = CXCursor_UnionDecl;
+      else
+        CursorKind = CXCursor_ClassDecl;
+      break;
+    }
+      
+    case Decl::ObjCMethod: {
+      ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Declaration);
+      if (Method->isInstanceMethod())
+          CursorKind = CXCursor_ObjCInstanceMethodDecl;
+      else
+        CursorKind = CXCursor_ObjCClassMethodDecl;
+      break;
+    }
+      
+    case Decl::Typedef:
+      CursorKind = CXCursor_TypedefDecl;
+      break;
+        
+    case Decl::Enum:
+      CursorKind = CXCursor_EnumDecl;
+      break;
+        
+    case Decl::Field:
+      CursorKind = CXCursor_FieldDecl;
+      break;
+        
+    case Decl::EnumConstant:
+      CursorKind = CXCursor_EnumConstantDecl;
+      break;      
+        
+    case Decl::Function:
+    case Decl::CXXMethod:
+    case Decl::CXXConstructor:
+    case Decl::CXXDestructor:
+    case Decl::CXXConversion:
+      CursorKind = CXCursor_FunctionDecl;
+      break;
+        
+    case Decl::Var:
+      CursorKind = CXCursor_VarDecl;
+      break;
+        
+    case Decl::ParmVar:
+      CursorKind = CXCursor_ParmDecl;
+      break;
+        
+    case Decl::ObjCInterface:
+      CursorKind = CXCursor_ObjCInterfaceDecl;
+      break;
+        
+    case Decl::ObjCCategory:
+      CursorKind = CXCursor_ObjCCategoryDecl;
+      break;
+        
+    case Decl::ObjCProtocol:
+      CursorKind = CXCursor_ObjCProtocolDecl;
       break;
 
-    case Result::RK_Macro:
-      return CXCursor_MacroDefinition;
-
-    case Result::RK_Keyword:
-    case Result::RK_Pattern:
-      return CXCursor_NotImplemented;
+    case Decl::ObjCProperty:
+      CursorKind = CXCursor_ObjCPropertyDecl;
+      break;
+        
+    case Decl::ObjCIvar:
+      CursorKind = CXCursor_ObjCIvarDecl;
+      break;
+        
+    case Decl::ObjCImplementation:
+      CursorKind = CXCursor_ObjCImplementationDecl;
+      break;
+        
+    case Decl::ObjCCategoryImpl:
+      CursorKind = CXCursor_ObjCCategoryImplDecl;
+      break;
+        
+    default:
+      CursorKind = CXCursor_NotImplemented;
+      break;
     }
-    return CXCursor_NotImplemented;
+    break;
+
+  case Result::RK_Macro:
+    CursorKind = CXCursor_MacroDefinition;
+    break;
+      
+  case Result::RK_Keyword:
+    CursorKind = CXCursor_NotImplemented;
+    break;
+      
+  case Result::RK_Pattern:
+    // Do nothing: Patterns can come with cursor kinds!
+    break;
   }
 }
 
@@ -595,7 +609,7 @@
                                                        unsigned NumResults) {
   // Print the results.
   for (unsigned I = 0; I != NumResults; ++I) {
-    WriteUnsigned(OS, getCursorKindForCompletionResult(Results[I]));
+    WriteUnsigned(OS, Results[I].CursorKind);
     WriteUnsigned(OS, Results[I].Priority);
     CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef);
     assert(CCS && "No code-completion string?");

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Aug 13 17:48:40 2010
@@ -269,8 +269,10 @@
                                           true)), 
                               UnusedFileScopedDecls.end());
 
-  if (!CompleteTranslationUnit)
+  if (!CompleteTranslationUnit) {
+    TUScope = 0;
     return;
+  }
 
   // Check for #pragma weak identifiers that were never declared
   // FIXME: This will cause diagnostics to be emitted in a non-determinstic
@@ -340,6 +342,8 @@
       Diag((*I)->getLocation(), diag::warn_unused_variable)
             << cast<VarDecl>(*I)->getDeclName();
   }
+
+  TUScope = 0;
 }
 
 

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Aug 13 17:48:40 2010
@@ -4336,3 +4336,23 @@
                             CodeCompletionContext::CCC_Other,
                             Results.data(),Results.size());
 }
+
+void Sema::GatherGlobalCodeCompletions(
+                 llvm::SmallVectorImpl<CodeCompleteConsumer::Result> &Results) {
+  ResultBuilder Builder(*this);
+
+#if 0
+  // FIXME: We need a name lookup that means "look for everything", 
+  CodeCompletionDeclConsumer Consumer(Builder, 
+                                      Context.getTranslationUnitDecl());
+  LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupOrdinaryName, 
+                     Consumer);
+#endif
+  
+  if (!CodeCompleter || CodeCompleter->includeMacros())
+    AddMacroResults(PP, Builder);
+  
+  Results.clear();
+  Results.insert(Results.end(), 
+                 Builder.data(), Builder.data() + Builder.size());
+}

Modified: cfe/trunk/test/Index/complete-macros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-macros.c?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-macros.c (original)
+++ cfe/trunk/test/Index/complete-macros.c Fri Aug 13 17:48:40 2010
@@ -16,6 +16,7 @@
 }
 
 // RUN: c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: macro definition:{TypedText FOO}{LeftParen (}{Placeholder Arg1}{Comma , }{Placeholder Arg2}{RightParen )}
 // RUN: c-index-test -code-completion-at=%s:13:13 %s | FileCheck -check-prefix=CHECK-CC2 %s
 // RUN: c-index-test -code-completion-at=%s:14:8 %s | FileCheck -check-prefix=CHECK-CC2 %s

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Fri Aug 13 17:48:40 2010
@@ -34,6 +34,8 @@
 
   if (getenv("CINDEXTEST_EDITING"))
     options |= clang_defaultEditingTranslationUnitOptions();
+  if (getenv("CINDEXTEST_COMPLETION_CACHING"))
+    options |= CXTranslationUnit_CacheCompletionResults;
   
   return options;
 }

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Fri Aug 13 17:48:40 2010
@@ -1220,7 +1220,9 @@
   bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
   bool CompleteTranslationUnit
     = ((options & CXTranslationUnit_Incomplete) == 0);
-
+  bool CacheCodeCompetionResults
+    = options & CXTranslationUnit_CacheCompletionResults;
+  
   // Configure the diagnostics.
   DiagnosticOptions DiagOpts;
   llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
@@ -1276,7 +1278,8 @@
                                    RemappedFiles.size(),
                                    /*CaptureDiagnostics=*/true,
                                    PrecompilePreamble,
-                                   CompleteTranslationUnit));
+                                   CompleteTranslationUnit,
+                                   CacheCodeCompetionResults));
 
     if (NumErrors != Diags->getNumErrors()) {
       // Make sure to check that 'Unit' is non-NULL.

Modified: cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp?rev=111051&r1=111050&r2=111051&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexCodeCompletion.cpp Fri Aug 13 17:48:40 2010
@@ -541,14 +541,6 @@
 
 } // end extern "C"
 
-namespace clang {
-  // FIXME: defined in CodeCompleteConsumer.cpp, but should be a
-  // static function here.
-  CXCursorKind 
-  getCursorKindForCompletionResult(const CodeCompleteConsumer::Result &R);
-}
-
-
 namespace {
   class CaptureCompletionResults : public CodeCompleteConsumer {
     AllocatedCXCodeCompleteResults &AllocatedResults;
@@ -567,8 +559,7 @@
         CXStoredCodeCompletionString *StoredCompletion
           = new CXStoredCodeCompletionString(Results[I].Priority);
         (void)Results[I].CreateCodeCompletionString(S, StoredCompletion);
-        AllocatedResults.Results[I].CursorKind 
-          = getCursorKindForCompletionResult(Results[I]);
+        AllocatedResults.Results[I].CursorKind = Results[I].CursorKind;
         AllocatedResults.Results[I].CompletionString = StoredCompletion;
       }
     }





More information about the cfe-commits mailing list