Index: include/clang/Frontend/ASTUnit.h =================================================================== --- include/clang/Frontend/ASTUnit.h +++ include/clang/Frontend/ASTUnit.h @@ -302,6 +302,9 @@ /// of that loading. It must be cleared when preamble is recreated. llvm::StringMap PreambleSrcLocCache; + /// The set of cached code-completion results. + std::vector CachedCompletionResults; + /// Counter that determines when we want to try building a /// precompiled preamble. /// @@ -319,6 +322,13 @@ /// This hash value is used to determine when we need to refresh the /// global code-completion cache after a rebuild of the precompiled preamble. unsigned PreambleTopLevelHashValue = 0; + + /// A string hash of the top-level declaration and macro definition + /// names processed the last time that we reparsed the file. + /// + /// This hash value is used to determine when we need to refresh the + /// global code-completion cache. + unsigned CompletionCacheTopLevelHashValue = 0; }; void initCache(); @@ -328,9 +338,9 @@ /// Retrieve the mapping from formatted type names to unique type /// identifiers. llvm::StringMap &getCachedCompletionTypes() { - return CachedCompletionTypes; + return CachedCompletionTypes; } - + /// Retrieve the allocator used to cache global code completions. std::shared_ptr getCachedCompletionAllocator() { @@ -353,24 +363,14 @@ std::unique_ptr CCTUInfo; - /// The set of cached code-completion results. - std::vector CachedCompletionResults; - /// A mapping from the formatted type name to a unique number for that /// type, which is used for type equality comparisons. llvm::StringMap CachedCompletionTypes; - - /// A string hash of the top-level declaration and macro definition - /// names processed the last time that we reparsed the file. - /// - /// This hash value is used to determine when we need to refresh the - /// global code-completion cache. - unsigned CompletionCacheTopLevelHashValue = 0; /// The current hash value for the top-level declaration and macro /// definition names unsigned CurrentTopLevelHashValue = 0; - + /// Bit used by CIndex to mark when a translation unit may be in an /// inconsistent state, and is not safe to free. unsigned UnsafeToFree : 1; @@ -629,22 +629,22 @@ stored_diag_iterator stored_diag_afterDriver_begin() { if (NumStoredDiagnosticsFromDriver > StoredDiagnostics.size()) NumStoredDiagnosticsFromDriver = 0; - return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver; + return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver; } using cached_completion_iterator = std::vector::iterator; - + cached_completion_iterator cached_completion_begin() { - return CachedCompletionResults.begin(); + return ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.begin(); } cached_completion_iterator cached_completion_end() { - return CachedCompletionResults.end(); + return ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.end(); } - unsigned cached_completion_size() const { - return CachedCompletionResults.size(); + unsigned cached_completion_size() const { + return ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.size(); } /// Returns an iterator range for the local preprocessing entities Index: lib/Frontend/ASTUnit.cpp =================================================================== --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -400,6 +400,7 @@ llvm::DenseMap CompletionTypes; CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel); + std::vector CachedCompletionResults; for (auto &R : Results) { switch (R.Kind) { case Result::RK_Declaration: { @@ -518,11 +519,15 @@ } // Save the current top-level hash value. - CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue; + StringRef MainFilePath = getMainFileName(); + std::lock_guard Lock(CacheMutex); + ASTUnitCacheMap[MainFilePath].CachedCompletionResults = std::move(CachedCompletionResults); + ASTUnitCacheMap[MainFilePath].CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue; } void ASTUnit::ClearCachedCompletionResults() { - CachedCompletionResults.clear(); + std::lock_guard Lock(CacheMutex); + ASTUnitCacheMap[getMainFileName()].CachedCompletionResults.clear(); CachedCompletionTypes.clear(); CachedCompletionAllocator = nullptr; } @@ -1430,7 +1435,7 @@ // entities the last time we rebuilt the preamble, clear out the completion // cache. if (NewPreambleTopLevelHashValue != PreambleTopLevelHashValue) { - CompletionCacheTopLevelHashValue = 0; + ASTUnitCacheMap[MainFilePath].CompletionCacheTopLevelHashValue = 0; PreambleTopLevelHashValue = NewPreambleTopLevelHashValue; } @@ -1891,11 +1896,16 @@ bool Result = Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS); - // If we're caching global code-completion results, and the top-level - // declarations have changed, clear out the code-completion cache. - if (!Result && ShouldCacheCodeCompletionResults && - CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue) - CacheCodeCompletionResults(); + { + std::lock_guard Lock(CacheMutex); + // If we're caching global code-completion results, and the top-level + // declarations have changed, clear out the code-completion cache. + if (!Result && ShouldCacheCodeCompletionResults && + CurrentTopLevelHashValue != + ASTUnitCacheMap[MainFilePath].CompletionCacheTopLevelHashValue) { + CacheCodeCompletionResults(); + } + } // We now need to clear out the completion info related to this translation // unit; it'll be recreated if necessary. @@ -2077,70 +2087,72 @@ llvm::StringSet HiddenNames; using Result = CodeCompletionResult; SmallVector 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) { - CalculateHiddenNames(Context, Results, NumResults, S.Context, - HiddenNames); - AllResults.insert(AllResults.end(), Results, Results + NumResults); - AddedResult = true; - } + { + std::lock_guard Lock(ASTUnit::getCacheMutex()); + 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; - // Determine whether this global completion result is hidden by a local - // completion result. If so, skip it. - if (C->Kind != CXCursor_MacroDefinition && - HiddenNames.count(C->Completion->getTypedText())) - continue; + // If we haven't added any results previously, do so now. + if (!AddedResult) { + CalculateHiddenNames(Context, Results, NumResults, S.Context, + HiddenNames); + AllResults.insert(AllResults.end(), Results, Results + NumResults); + AddedResult = true; + } + + // Determine whether this global completion result is hidden by a local + // completion result. If so, skip it. + if (C->Kind != CXCursor_MacroDefinition && + HiddenNames.count(C->Completion->getTypedText())) + continue; - // Adjust priority based on similar type classes. - unsigned Priority = C->Priority; - CodeCompletionString *Completion = C->Completion; - if (!Context.getPreferredType().isNull()) { - if (C->Kind == CXCursor_MacroDefinition) { - Priority = getMacroUsagePriority(C->Completion->getTypedText(), - S.getLangOpts(), - Context.getPreferredType()->isAnyPointerType()); - } else if (C->Type) { - CanQualType Expected - = S.Context.getCanonicalType( - Context.getPreferredType().getUnqualifiedType()); - SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected); - if (ExpectedSTC == C->TypeClass) { - // We know this type is similar; check for an exact match. - llvm::StringMap &CachedCompletionTypes - = AST.getCachedCompletionTypes(); - llvm::StringMap::iterator Pos - = CachedCompletionTypes.find(QualType(Expected).getAsString()); - if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type) - Priority /= CCF_ExactTypeMatch; - else - Priority /= CCF_SimilarTypeMatch; + // Adjust priority based on similar type classes. + unsigned Priority = C->Priority; + CodeCompletionString *Completion = C->Completion; + if (!Context.getPreferredType().isNull()) { + if (C->Kind == CXCursor_MacroDefinition) { + Priority = getMacroUsagePriority( + C->Completion->getTypedText(), S.getLangOpts(), + Context.getPreferredType()->isAnyPointerType()); + } else if (C->Type) { + CanQualType Expected = S.Context.getCanonicalType( + Context.getPreferredType().getUnqualifiedType()); + SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected); + if (ExpectedSTC == C->TypeClass) { + // We know this type is similar; check for an exact match. + llvm::StringMap &CachedCompletionTypes = + AST.getCachedCompletionTypes(); + llvm::StringMap::iterator Pos = + CachedCompletionTypes.find(QualType(Expected).getAsString()); + if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type) + Priority /= CCF_ExactTypeMatch; + else + Priority /= CCF_SimilarTypeMatch; + } } } - } - // Adjust the completion string, if required. - if (C->Kind == CXCursor_MacroDefinition && - Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) { - // Create a new code-completion string that just contains the - // macro name, without its arguments. - CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(), - CCP_CodePattern, C->Availability); - Builder.AddTypedTextChunk(C->Completion->getTypedText()); - Priority = CCP_CodePattern; - Completion = Builder.TakeString(); - } + // Adjust the completion string, if required. + if (C->Kind == CXCursor_MacroDefinition && + Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) { + // Create a new code-completion string that just contains the + // macro name, without its arguments. + CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(), + CCP_CodePattern, C->Availability); + Builder.AddTypedTextChunk(C->Completion->getTypedText()); + Priority = CCP_CodePattern; + Completion = Builder.TakeString(); + } - AllResults.push_back(Result(Completion, Priority, C->Kind, - C->Availability)); + AllResults.push_back( + Result(Completion, Priority, C->Kind, C->Availability)); + } } // If we did not add any cached completion results, just forward the @@ -2177,9 +2189,15 @@ PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts(); StringRef MainFilePath = getMainFileName(); - CodeCompleteOpts.IncludeMacros = IncludeMacros && - CachedCompletionResults.empty(); - CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty(); + { + std::lock_guard Lock(CacheMutex); + CodeCompleteOpts.IncludeMacros = + IncludeMacros && + ASTUnitCacheMap[MainFilePath].CachedCompletionResults.empty(); + CodeCompleteOpts.IncludeGlobals = + ASTUnitCacheMap[MainFilePath].CachedCompletionResults.empty(); + } + CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns; CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments; CodeCompleteOpts.LoadExternal = Consumer.loadExternal();