17330f729Sjoerg //===- ASTUnit.cpp - ASTUnit utility --------------------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // ASTUnit Implementation.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
137330f729Sjoerg #include "clang/Frontend/ASTUnit.h"
147330f729Sjoerg #include "clang/AST/ASTConsumer.h"
157330f729Sjoerg #include "clang/AST/ASTContext.h"
167330f729Sjoerg #include "clang/AST/CommentCommandTraits.h"
177330f729Sjoerg #include "clang/AST/Decl.h"
187330f729Sjoerg #include "clang/AST/DeclBase.h"
197330f729Sjoerg #include "clang/AST/DeclCXX.h"
207330f729Sjoerg #include "clang/AST/DeclGroup.h"
217330f729Sjoerg #include "clang/AST/DeclObjC.h"
227330f729Sjoerg #include "clang/AST/DeclTemplate.h"
237330f729Sjoerg #include "clang/AST/DeclarationName.h"
247330f729Sjoerg #include "clang/AST/ExternalASTSource.h"
257330f729Sjoerg #include "clang/AST/PrettyPrinter.h"
267330f729Sjoerg #include "clang/AST/Type.h"
277330f729Sjoerg #include "clang/AST/TypeOrdering.h"
287330f729Sjoerg #include "clang/Basic/Diagnostic.h"
297330f729Sjoerg #include "clang/Basic/FileManager.h"
307330f729Sjoerg #include "clang/Basic/IdentifierTable.h"
317330f729Sjoerg #include "clang/Basic/LLVM.h"
327330f729Sjoerg #include "clang/Basic/LangOptions.h"
337330f729Sjoerg #include "clang/Basic/LangStandard.h"
347330f729Sjoerg #include "clang/Basic/Module.h"
357330f729Sjoerg #include "clang/Basic/SourceLocation.h"
367330f729Sjoerg #include "clang/Basic/SourceManager.h"
377330f729Sjoerg #include "clang/Basic/TargetInfo.h"
387330f729Sjoerg #include "clang/Basic/TargetOptions.h"
397330f729Sjoerg #include "clang/Frontend/CompilerInstance.h"
407330f729Sjoerg #include "clang/Frontend/CompilerInvocation.h"
417330f729Sjoerg #include "clang/Frontend/FrontendAction.h"
427330f729Sjoerg #include "clang/Frontend/FrontendActions.h"
437330f729Sjoerg #include "clang/Frontend/FrontendDiagnostic.h"
447330f729Sjoerg #include "clang/Frontend/FrontendOptions.h"
457330f729Sjoerg #include "clang/Frontend/MultiplexConsumer.h"
467330f729Sjoerg #include "clang/Frontend/PrecompiledPreamble.h"
477330f729Sjoerg #include "clang/Frontend/Utils.h"
487330f729Sjoerg #include "clang/Lex/HeaderSearch.h"
497330f729Sjoerg #include "clang/Lex/HeaderSearchOptions.h"
507330f729Sjoerg #include "clang/Lex/Lexer.h"
517330f729Sjoerg #include "clang/Lex/PPCallbacks.h"
527330f729Sjoerg #include "clang/Lex/PreprocessingRecord.h"
537330f729Sjoerg #include "clang/Lex/Preprocessor.h"
547330f729Sjoerg #include "clang/Lex/PreprocessorOptions.h"
557330f729Sjoerg #include "clang/Lex/Token.h"
567330f729Sjoerg #include "clang/Sema/CodeCompleteConsumer.h"
577330f729Sjoerg #include "clang/Sema/CodeCompleteOptions.h"
587330f729Sjoerg #include "clang/Sema/Sema.h"
597330f729Sjoerg #include "clang/Serialization/ASTBitCodes.h"
607330f729Sjoerg #include "clang/Serialization/ASTReader.h"
617330f729Sjoerg #include "clang/Serialization/ASTWriter.h"
627330f729Sjoerg #include "clang/Serialization/ContinuousRangeMap.h"
637330f729Sjoerg #include "clang/Serialization/InMemoryModuleCache.h"
64*e038c9c4Sjoerg #include "clang/Serialization/ModuleFile.h"
657330f729Sjoerg #include "clang/Serialization/PCHContainerOperations.h"
667330f729Sjoerg #include "llvm/ADT/ArrayRef.h"
677330f729Sjoerg #include "llvm/ADT/DenseMap.h"
687330f729Sjoerg #include "llvm/ADT/IntrusiveRefCntPtr.h"
697330f729Sjoerg #include "llvm/ADT/None.h"
707330f729Sjoerg #include "llvm/ADT/Optional.h"
717330f729Sjoerg #include "llvm/ADT/STLExtras.h"
72*e038c9c4Sjoerg #include "llvm/ADT/ScopeExit.h"
737330f729Sjoerg #include "llvm/ADT/SmallString.h"
747330f729Sjoerg #include "llvm/ADT/SmallVector.h"
757330f729Sjoerg #include "llvm/ADT/StringMap.h"
767330f729Sjoerg #include "llvm/ADT/StringRef.h"
777330f729Sjoerg #include "llvm/ADT/StringSet.h"
787330f729Sjoerg #include "llvm/ADT/Twine.h"
797330f729Sjoerg #include "llvm/ADT/iterator_range.h"
807330f729Sjoerg #include "llvm/Bitstream/BitstreamWriter.h"
817330f729Sjoerg #include "llvm/Support/Allocator.h"
827330f729Sjoerg #include "llvm/Support/Casting.h"
837330f729Sjoerg #include "llvm/Support/CrashRecoveryContext.h"
847330f729Sjoerg #include "llvm/Support/DJB.h"
857330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
867330f729Sjoerg #include "llvm/Support/ErrorOr.h"
877330f729Sjoerg #include "llvm/Support/FileSystem.h"
887330f729Sjoerg #include "llvm/Support/FileUtilities.h"
897330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
907330f729Sjoerg #include "llvm/Support/Timer.h"
917330f729Sjoerg #include "llvm/Support/VirtualFileSystem.h"
927330f729Sjoerg #include "llvm/Support/raw_ostream.h"
937330f729Sjoerg #include <algorithm>
947330f729Sjoerg #include <atomic>
957330f729Sjoerg #include <cassert>
967330f729Sjoerg #include <cstdint>
977330f729Sjoerg #include <cstdio>
987330f729Sjoerg #include <cstdlib>
997330f729Sjoerg #include <memory>
1007330f729Sjoerg #include <mutex>
1017330f729Sjoerg #include <string>
1027330f729Sjoerg #include <tuple>
1037330f729Sjoerg #include <utility>
1047330f729Sjoerg #include <vector>
1057330f729Sjoerg
1067330f729Sjoerg using namespace clang;
1077330f729Sjoerg
1087330f729Sjoerg using llvm::TimeRecord;
1097330f729Sjoerg
1107330f729Sjoerg namespace {
1117330f729Sjoerg
1127330f729Sjoerg class SimpleTimer {
1137330f729Sjoerg bool WantTiming;
1147330f729Sjoerg TimeRecord Start;
1157330f729Sjoerg std::string Output;
1167330f729Sjoerg
1177330f729Sjoerg public:
SimpleTimer(bool WantTiming)1187330f729Sjoerg explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {
1197330f729Sjoerg if (WantTiming)
1207330f729Sjoerg Start = TimeRecord::getCurrentTime();
1217330f729Sjoerg }
1227330f729Sjoerg
~SimpleTimer()1237330f729Sjoerg ~SimpleTimer() {
1247330f729Sjoerg if (WantTiming) {
1257330f729Sjoerg TimeRecord Elapsed = TimeRecord::getCurrentTime();
1267330f729Sjoerg Elapsed -= Start;
1277330f729Sjoerg llvm::errs() << Output << ':';
1287330f729Sjoerg Elapsed.print(Elapsed, llvm::errs());
1297330f729Sjoerg llvm::errs() << '\n';
1307330f729Sjoerg }
1317330f729Sjoerg }
1327330f729Sjoerg
setOutput(const Twine & Output)1337330f729Sjoerg void setOutput(const Twine &Output) {
1347330f729Sjoerg if (WantTiming)
1357330f729Sjoerg this->Output = Output.str();
1367330f729Sjoerg }
1377330f729Sjoerg };
1387330f729Sjoerg
1397330f729Sjoerg } // namespace
1407330f729Sjoerg
1417330f729Sjoerg template <class T>
valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val)1427330f729Sjoerg static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {
1437330f729Sjoerg if (!Val)
1447330f729Sjoerg return nullptr;
1457330f729Sjoerg return std::move(*Val);
1467330f729Sjoerg }
1477330f729Sjoerg
1487330f729Sjoerg template <class T>
moveOnNoError(llvm::ErrorOr<T> Val,T & Output)1497330f729Sjoerg static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {
1507330f729Sjoerg if (!Val)
1517330f729Sjoerg return false;
1527330f729Sjoerg Output = std::move(*Val);
1537330f729Sjoerg return true;
1547330f729Sjoerg }
1557330f729Sjoerg
1567330f729Sjoerg /// Get a source buffer for \p MainFilePath, handling all file-to-file
1577330f729Sjoerg /// and file-to-buffer remappings inside \p Invocation.
1587330f729Sjoerg static std::unique_ptr<llvm::MemoryBuffer>
getBufferForFileHandlingRemapping(const CompilerInvocation & Invocation,llvm::vfs::FileSystem * VFS,StringRef FilePath,bool isVolatile)1597330f729Sjoerg getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
1607330f729Sjoerg llvm::vfs::FileSystem *VFS,
1617330f729Sjoerg StringRef FilePath, bool isVolatile) {
1627330f729Sjoerg const auto &PreprocessorOpts = Invocation.getPreprocessorOpts();
1637330f729Sjoerg
1647330f729Sjoerg // Try to determine if the main file has been remapped, either from the
1657330f729Sjoerg // command line (to another file) or directly through the compiler
1667330f729Sjoerg // invocation (to a memory buffer).
1677330f729Sjoerg llvm::MemoryBuffer *Buffer = nullptr;
1687330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer> BufferOwner;
1697330f729Sjoerg auto FileStatus = VFS->status(FilePath);
1707330f729Sjoerg if (FileStatus) {
1717330f729Sjoerg llvm::sys::fs::UniqueID MainFileID = FileStatus->getUniqueID();
1727330f729Sjoerg
1737330f729Sjoerg // Check whether there is a file-file remapping of the main file
1747330f729Sjoerg for (const auto &RF : PreprocessorOpts.RemappedFiles) {
1757330f729Sjoerg std::string MPath(RF.first);
1767330f729Sjoerg auto MPathStatus = VFS->status(MPath);
1777330f729Sjoerg if (MPathStatus) {
1787330f729Sjoerg llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
1797330f729Sjoerg if (MainFileID == MID) {
1807330f729Sjoerg // We found a remapping. Try to load the resulting, remapped source.
1817330f729Sjoerg BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile));
1827330f729Sjoerg if (!BufferOwner)
1837330f729Sjoerg return nullptr;
1847330f729Sjoerg }
1857330f729Sjoerg }
1867330f729Sjoerg }
1877330f729Sjoerg
1887330f729Sjoerg // Check whether there is a file-buffer remapping. It supercedes the
1897330f729Sjoerg // file-file remapping.
1907330f729Sjoerg for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) {
1917330f729Sjoerg std::string MPath(RB.first);
1927330f729Sjoerg auto MPathStatus = VFS->status(MPath);
1937330f729Sjoerg if (MPathStatus) {
1947330f729Sjoerg llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID();
1957330f729Sjoerg if (MainFileID == MID) {
1967330f729Sjoerg // We found a remapping.
1977330f729Sjoerg BufferOwner.reset();
1987330f729Sjoerg Buffer = const_cast<llvm::MemoryBuffer *>(RB.second);
1997330f729Sjoerg }
2007330f729Sjoerg }
2017330f729Sjoerg }
2027330f729Sjoerg }
2037330f729Sjoerg
2047330f729Sjoerg // If the main source file was not remapped, load it now.
2057330f729Sjoerg if (!Buffer && !BufferOwner) {
2067330f729Sjoerg BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile));
2077330f729Sjoerg if (!BufferOwner)
2087330f729Sjoerg return nullptr;
2097330f729Sjoerg }
2107330f729Sjoerg
2117330f729Sjoerg if (BufferOwner)
2127330f729Sjoerg return BufferOwner;
2137330f729Sjoerg if (!Buffer)
2147330f729Sjoerg return nullptr;
2157330f729Sjoerg return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath);
2167330f729Sjoerg }
2177330f729Sjoerg
2187330f729Sjoerg struct ASTUnit::ASTWriterData {
2197330f729Sjoerg SmallString<128> Buffer;
2207330f729Sjoerg llvm::BitstreamWriter Stream;
2217330f729Sjoerg ASTWriter Writer;
2227330f729Sjoerg
ASTWriterDataASTUnit::ASTWriterData2237330f729Sjoerg ASTWriterData(InMemoryModuleCache &ModuleCache)
2247330f729Sjoerg : Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {}
2257330f729Sjoerg };
2267330f729Sjoerg
clearFileLevelDecls()2277330f729Sjoerg void ASTUnit::clearFileLevelDecls() {
228*e038c9c4Sjoerg FileDecls.clear();
2297330f729Sjoerg }
2307330f729Sjoerg
2317330f729Sjoerg /// After failing to build a precompiled preamble (due to
2327330f729Sjoerg /// errors in the source that occurs in the preamble), the number of
2337330f729Sjoerg /// reparses during which we'll skip even trying to precompile the
2347330f729Sjoerg /// preamble.
2357330f729Sjoerg const unsigned DefaultPreambleRebuildInterval = 5;
2367330f729Sjoerg
2377330f729Sjoerg /// Tracks the number of ASTUnit objects that are currently active.
2387330f729Sjoerg ///
2397330f729Sjoerg /// Used for debugging purposes only.
2407330f729Sjoerg static std::atomic<unsigned> ActiveASTUnitObjects;
2417330f729Sjoerg
ASTUnit(bool _MainFileIsAST)2427330f729Sjoerg ASTUnit::ASTUnit(bool _MainFileIsAST)
2437330f729Sjoerg : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")),
2447330f729Sjoerg ShouldCacheCodeCompletionResults(false),
2457330f729Sjoerg IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
2467330f729Sjoerg UnsafeToFree(false) {
2477330f729Sjoerg if (getenv("LIBCLANG_OBJTRACKING"))
2487330f729Sjoerg fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects);
2497330f729Sjoerg }
2507330f729Sjoerg
~ASTUnit()2517330f729Sjoerg ASTUnit::~ASTUnit() {
2527330f729Sjoerg // If we loaded from an AST file, balance out the BeginSourceFile call.
2537330f729Sjoerg if (MainFileIsAST && getDiagnostics().getClient()) {
2547330f729Sjoerg getDiagnostics().getClient()->EndSourceFile();
2557330f729Sjoerg }
2567330f729Sjoerg
2577330f729Sjoerg clearFileLevelDecls();
2587330f729Sjoerg
2597330f729Sjoerg // Free the buffers associated with remapped files. We are required to
2607330f729Sjoerg // perform this operation here because we explicitly request that the
2617330f729Sjoerg // compiler instance *not* free these buffers for each invocation of the
2627330f729Sjoerg // parser.
2637330f729Sjoerg if (Invocation && OwnsRemappedFileBuffers) {
2647330f729Sjoerg PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
2657330f729Sjoerg for (const auto &RB : PPOpts.RemappedFileBuffers)
2667330f729Sjoerg delete RB.second;
2677330f729Sjoerg }
2687330f729Sjoerg
2697330f729Sjoerg ClearCachedCompletionResults();
2707330f729Sjoerg
2717330f729Sjoerg if (getenv("LIBCLANG_OBJTRACKING"))
2727330f729Sjoerg fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects);
2737330f729Sjoerg }
2747330f729Sjoerg
setPreprocessor(std::shared_ptr<Preprocessor> PP)2757330f729Sjoerg void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
2767330f729Sjoerg this->PP = std::move(PP);
2777330f729Sjoerg }
2787330f729Sjoerg
enableSourceFileDiagnostics()2797330f729Sjoerg void ASTUnit::enableSourceFileDiagnostics() {
2807330f729Sjoerg assert(getDiagnostics().getClient() && Ctx &&
2817330f729Sjoerg "Bad context for source file");
2827330f729Sjoerg getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get());
2837330f729Sjoerg }
2847330f729Sjoerg
2857330f729Sjoerg /// Determine the set of code-completion contexts in which this
2867330f729Sjoerg /// declaration should be shown.
getDeclShowContexts(const NamedDecl * ND,const LangOptions & LangOpts,bool & IsNestedNameSpecifier)2877330f729Sjoerg static uint64_t getDeclShowContexts(const NamedDecl *ND,
2887330f729Sjoerg const LangOptions &LangOpts,
2897330f729Sjoerg bool &IsNestedNameSpecifier) {
2907330f729Sjoerg IsNestedNameSpecifier = false;
2917330f729Sjoerg
2927330f729Sjoerg if (isa<UsingShadowDecl>(ND))
2937330f729Sjoerg ND = ND->getUnderlyingDecl();
2947330f729Sjoerg if (!ND)
2957330f729Sjoerg return 0;
2967330f729Sjoerg
2977330f729Sjoerg uint64_t Contexts = 0;
2987330f729Sjoerg if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
2997330f729Sjoerg isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) ||
3007330f729Sjoerg isa<TypeAliasTemplateDecl>(ND)) {
3017330f729Sjoerg // Types can appear in these contexts.
3027330f729Sjoerg if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
3037330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel)
3047330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
3057330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
3067330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Statement)
3077330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Type)
3087330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
3097330f729Sjoerg
3107330f729Sjoerg // In C++, types can appear in expressions contexts (for functional casts).
3117330f729Sjoerg if (LangOpts.CPlusPlus)
3127330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
3137330f729Sjoerg
3147330f729Sjoerg // In Objective-C, message sends can send interfaces. In Objective-C++,
3157330f729Sjoerg // all types are available due to functional casts.
3167330f729Sjoerg if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
3177330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
3187330f729Sjoerg
3197330f729Sjoerg // In Objective-C, you can only be a subclass of another Objective-C class
3207330f729Sjoerg if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
3217330f729Sjoerg // Objective-C interfaces can be used in a class property expression.
3227330f729Sjoerg if (ID->getDefinition())
3237330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
3247330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
3257330f729Sjoerg }
3267330f729Sjoerg
3277330f729Sjoerg // Deal with tag names.
3287330f729Sjoerg if (isa<EnumDecl>(ND)) {
3297330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag);
3307330f729Sjoerg
3317330f729Sjoerg // Part of the nested-name-specifier in C++0x.
3327330f729Sjoerg if (LangOpts.CPlusPlus11)
3337330f729Sjoerg IsNestedNameSpecifier = true;
3347330f729Sjoerg } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) {
3357330f729Sjoerg if (Record->isUnion())
3367330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag);
3377330f729Sjoerg else
3387330f729Sjoerg Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
3397330f729Sjoerg
3407330f729Sjoerg if (LangOpts.CPlusPlus)
3417330f729Sjoerg IsNestedNameSpecifier = true;
3427330f729Sjoerg } else if (isa<ClassTemplateDecl>(ND))
3437330f729Sjoerg IsNestedNameSpecifier = true;
3447330f729Sjoerg } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
3457330f729Sjoerg // Values can appear in these contexts.
3467330f729Sjoerg Contexts = (1LL << CodeCompletionContext::CCC_Statement)
3477330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Expression)
3487330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
3497330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
3507330f729Sjoerg } else if (isa<ObjCProtocolDecl>(ND)) {
3517330f729Sjoerg Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName);
3527330f729Sjoerg } else if (isa<ObjCCategoryDecl>(ND)) {
3537330f729Sjoerg Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName);
3547330f729Sjoerg } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
3557330f729Sjoerg Contexts = (1LL << CodeCompletionContext::CCC_Namespace);
3567330f729Sjoerg
3577330f729Sjoerg // Part of the nested-name-specifier.
3587330f729Sjoerg IsNestedNameSpecifier = true;
3597330f729Sjoerg }
3607330f729Sjoerg
3617330f729Sjoerg return Contexts;
3627330f729Sjoerg }
3637330f729Sjoerg
CacheCodeCompletionResults()3647330f729Sjoerg void ASTUnit::CacheCodeCompletionResults() {
3657330f729Sjoerg if (!TheSema)
3667330f729Sjoerg return;
3677330f729Sjoerg
3687330f729Sjoerg SimpleTimer Timer(WantTiming);
3697330f729Sjoerg Timer.setOutput("Cache global code completions for " + getMainFileName());
3707330f729Sjoerg
3717330f729Sjoerg // Clear out the previous results.
3727330f729Sjoerg ClearCachedCompletionResults();
3737330f729Sjoerg
3747330f729Sjoerg // Gather the set of global code completions.
3757330f729Sjoerg using Result = CodeCompletionResult;
3767330f729Sjoerg SmallVector<Result, 8> Results;
3777330f729Sjoerg CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
3787330f729Sjoerg CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator);
3797330f729Sjoerg TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator,
3807330f729Sjoerg CCTUInfo, Results);
3817330f729Sjoerg
3827330f729Sjoerg // Translate global code completions into cached completions.
3837330f729Sjoerg llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
3847330f729Sjoerg CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel);
3857330f729Sjoerg
3867330f729Sjoerg for (auto &R : Results) {
3877330f729Sjoerg switch (R.Kind) {
3887330f729Sjoerg case Result::RK_Declaration: {
3897330f729Sjoerg bool IsNestedNameSpecifier = false;
3907330f729Sjoerg CachedCodeCompletionResult CachedResult;
3917330f729Sjoerg CachedResult.Completion = R.CreateCodeCompletionString(
3927330f729Sjoerg *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
3937330f729Sjoerg IncludeBriefCommentsInCodeCompletion);
3947330f729Sjoerg CachedResult.ShowInContexts = getDeclShowContexts(
3957330f729Sjoerg R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier);
3967330f729Sjoerg CachedResult.Priority = R.Priority;
3977330f729Sjoerg CachedResult.Kind = R.CursorKind;
3987330f729Sjoerg CachedResult.Availability = R.Availability;
3997330f729Sjoerg
4007330f729Sjoerg // Keep track of the type of this completion in an ASTContext-agnostic
4017330f729Sjoerg // way.
4027330f729Sjoerg QualType UsageType = getDeclUsageType(*Ctx, R.Declaration);
4037330f729Sjoerg if (UsageType.isNull()) {
4047330f729Sjoerg CachedResult.TypeClass = STC_Void;
4057330f729Sjoerg CachedResult.Type = 0;
4067330f729Sjoerg } else {
4077330f729Sjoerg CanQualType CanUsageType
4087330f729Sjoerg = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
4097330f729Sjoerg CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
4107330f729Sjoerg
4117330f729Sjoerg // Determine whether we have already seen this type. If so, we save
4127330f729Sjoerg // ourselves the work of formatting the type string by using the
4137330f729Sjoerg // temporary, CanQualType-based hash table to find the associated value.
4147330f729Sjoerg unsigned &TypeValue = CompletionTypes[CanUsageType];
4157330f729Sjoerg if (TypeValue == 0) {
4167330f729Sjoerg TypeValue = CompletionTypes.size();
4177330f729Sjoerg CachedCompletionTypes[QualType(CanUsageType).getAsString()]
4187330f729Sjoerg = TypeValue;
4197330f729Sjoerg }
4207330f729Sjoerg
4217330f729Sjoerg CachedResult.Type = TypeValue;
4227330f729Sjoerg }
4237330f729Sjoerg
4247330f729Sjoerg CachedCompletionResults.push_back(CachedResult);
4257330f729Sjoerg
4267330f729Sjoerg /// Handle nested-name-specifiers in C++.
4277330f729Sjoerg if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier &&
4287330f729Sjoerg !R.StartsNestedNameSpecifier) {
4297330f729Sjoerg // The contexts in which a nested-name-specifier can appear in C++.
4307330f729Sjoerg uint64_t NNSContexts
4317330f729Sjoerg = (1LL << CodeCompletionContext::CCC_TopLevel)
4327330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
4337330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
4347330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Statement)
4357330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Expression)
4367330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
4377330f729Sjoerg | (1LL << CodeCompletionContext::CCC_EnumTag)
4387330f729Sjoerg | (1LL << CodeCompletionContext::CCC_UnionTag)
4397330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ClassOrStructTag)
4407330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Type)
4417330f729Sjoerg | (1LL << CodeCompletionContext::CCC_SymbolOrNewName)
4427330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression);
4437330f729Sjoerg
4447330f729Sjoerg if (isa<NamespaceDecl>(R.Declaration) ||
4457330f729Sjoerg isa<NamespaceAliasDecl>(R.Declaration))
4467330f729Sjoerg NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace);
4477330f729Sjoerg
4487330f729Sjoerg if (uint64_t RemainingContexts
4497330f729Sjoerg = NNSContexts & ~CachedResult.ShowInContexts) {
4507330f729Sjoerg // If there any contexts where this completion can be a
4517330f729Sjoerg // nested-name-specifier but isn't already an option, create a
4527330f729Sjoerg // nested-name-specifier completion.
4537330f729Sjoerg R.StartsNestedNameSpecifier = true;
4547330f729Sjoerg CachedResult.Completion = R.CreateCodeCompletionString(
4557330f729Sjoerg *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
4567330f729Sjoerg IncludeBriefCommentsInCodeCompletion);
4577330f729Sjoerg CachedResult.ShowInContexts = RemainingContexts;
4587330f729Sjoerg CachedResult.Priority = CCP_NestedNameSpecifier;
4597330f729Sjoerg CachedResult.TypeClass = STC_Void;
4607330f729Sjoerg CachedResult.Type = 0;
4617330f729Sjoerg CachedCompletionResults.push_back(CachedResult);
4627330f729Sjoerg }
4637330f729Sjoerg }
4647330f729Sjoerg break;
4657330f729Sjoerg }
4667330f729Sjoerg
4677330f729Sjoerg case Result::RK_Keyword:
4687330f729Sjoerg case Result::RK_Pattern:
4697330f729Sjoerg // Ignore keywords and patterns; we don't care, since they are so
4707330f729Sjoerg // easily regenerated.
4717330f729Sjoerg break;
4727330f729Sjoerg
4737330f729Sjoerg case Result::RK_Macro: {
4747330f729Sjoerg CachedCodeCompletionResult CachedResult;
4757330f729Sjoerg CachedResult.Completion = R.CreateCodeCompletionString(
4767330f729Sjoerg *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo,
4777330f729Sjoerg IncludeBriefCommentsInCodeCompletion);
4787330f729Sjoerg CachedResult.ShowInContexts
4797330f729Sjoerg = (1LL << CodeCompletionContext::CCC_TopLevel)
4807330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCInterface)
4817330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
4827330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
4837330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ClassStructUnion)
4847330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Statement)
4857330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Expression)
4867330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
4877330f729Sjoerg | (1LL << CodeCompletionContext::CCC_MacroNameUse)
4887330f729Sjoerg | (1LL << CodeCompletionContext::CCC_PreprocessorExpression)
4897330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
4907330f729Sjoerg | (1LL << CodeCompletionContext::CCC_OtherWithMacros);
4917330f729Sjoerg
4927330f729Sjoerg CachedResult.Priority = R.Priority;
4937330f729Sjoerg CachedResult.Kind = R.CursorKind;
4947330f729Sjoerg CachedResult.Availability = R.Availability;
4957330f729Sjoerg CachedResult.TypeClass = STC_Void;
4967330f729Sjoerg CachedResult.Type = 0;
4977330f729Sjoerg CachedCompletionResults.push_back(CachedResult);
4987330f729Sjoerg break;
4997330f729Sjoerg }
5007330f729Sjoerg }
5017330f729Sjoerg }
5027330f729Sjoerg
5037330f729Sjoerg // Save the current top-level hash value.
5047330f729Sjoerg CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
5057330f729Sjoerg }
5067330f729Sjoerg
ClearCachedCompletionResults()5077330f729Sjoerg void ASTUnit::ClearCachedCompletionResults() {
5087330f729Sjoerg CachedCompletionResults.clear();
5097330f729Sjoerg CachedCompletionTypes.clear();
5107330f729Sjoerg CachedCompletionAllocator = nullptr;
5117330f729Sjoerg }
5127330f729Sjoerg
5137330f729Sjoerg namespace {
5147330f729Sjoerg
5157330f729Sjoerg /// Gathers information from ASTReader that will be used to initialize
5167330f729Sjoerg /// a Preprocessor.
5177330f729Sjoerg class ASTInfoCollector : public ASTReaderListener {
5187330f729Sjoerg Preprocessor &PP;
5197330f729Sjoerg ASTContext *Context;
5207330f729Sjoerg HeaderSearchOptions &HSOpts;
5217330f729Sjoerg PreprocessorOptions &PPOpts;
5227330f729Sjoerg LangOptions &LangOpt;
5237330f729Sjoerg std::shared_ptr<TargetOptions> &TargetOpts;
5247330f729Sjoerg IntrusiveRefCntPtr<TargetInfo> &Target;
5257330f729Sjoerg unsigned &Counter;
5267330f729Sjoerg bool InitializedLanguage = false;
5277330f729Sjoerg
5287330f729Sjoerg public:
ASTInfoCollector(Preprocessor & PP,ASTContext * Context,HeaderSearchOptions & HSOpts,PreprocessorOptions & PPOpts,LangOptions & LangOpt,std::shared_ptr<TargetOptions> & TargetOpts,IntrusiveRefCntPtr<TargetInfo> & Target,unsigned & Counter)5297330f729Sjoerg ASTInfoCollector(Preprocessor &PP, ASTContext *Context,
5307330f729Sjoerg HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts,
5317330f729Sjoerg LangOptions &LangOpt,
5327330f729Sjoerg std::shared_ptr<TargetOptions> &TargetOpts,
5337330f729Sjoerg IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter)
5347330f729Sjoerg : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts),
5357330f729Sjoerg LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target),
5367330f729Sjoerg Counter(Counter) {}
5377330f729Sjoerg
ReadLanguageOptions(const LangOptions & LangOpts,bool Complain,bool AllowCompatibleDifferences)5387330f729Sjoerg bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
5397330f729Sjoerg bool AllowCompatibleDifferences) override {
5407330f729Sjoerg if (InitializedLanguage)
5417330f729Sjoerg return false;
5427330f729Sjoerg
5437330f729Sjoerg LangOpt = LangOpts;
5447330f729Sjoerg InitializedLanguage = true;
5457330f729Sjoerg
5467330f729Sjoerg updated();
5477330f729Sjoerg return false;
5487330f729Sjoerg }
5497330f729Sjoerg
ReadHeaderSearchOptions(const HeaderSearchOptions & HSOpts,StringRef SpecificModuleCachePath,bool Complain)5507330f729Sjoerg bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
5517330f729Sjoerg StringRef SpecificModuleCachePath,
5527330f729Sjoerg bool Complain) override {
5537330f729Sjoerg this->HSOpts = HSOpts;
5547330f729Sjoerg return false;
5557330f729Sjoerg }
5567330f729Sjoerg
ReadPreprocessorOptions(const PreprocessorOptions & PPOpts,bool Complain,std::string & SuggestedPredefines)5577330f729Sjoerg bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain,
5587330f729Sjoerg std::string &SuggestedPredefines) override {
5597330f729Sjoerg this->PPOpts = PPOpts;
5607330f729Sjoerg return false;
5617330f729Sjoerg }
5627330f729Sjoerg
ReadTargetOptions(const TargetOptions & TargetOpts,bool Complain,bool AllowCompatibleDifferences)5637330f729Sjoerg bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain,
5647330f729Sjoerg bool AllowCompatibleDifferences) override {
5657330f729Sjoerg // If we've already initialized the target, don't do it again.
5667330f729Sjoerg if (Target)
5677330f729Sjoerg return false;
5687330f729Sjoerg
5697330f729Sjoerg this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts);
5707330f729Sjoerg Target =
5717330f729Sjoerg TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts);
5727330f729Sjoerg
5737330f729Sjoerg updated();
5747330f729Sjoerg return false;
5757330f729Sjoerg }
5767330f729Sjoerg
ReadCounter(const serialization::ModuleFile & M,unsigned Value)5777330f729Sjoerg void ReadCounter(const serialization::ModuleFile &M,
5787330f729Sjoerg unsigned Value) override {
5797330f729Sjoerg Counter = Value;
5807330f729Sjoerg }
5817330f729Sjoerg
5827330f729Sjoerg private:
updated()5837330f729Sjoerg void updated() {
5847330f729Sjoerg if (!Target || !InitializedLanguage)
5857330f729Sjoerg return;
5867330f729Sjoerg
5877330f729Sjoerg // Inform the target of the language options.
5887330f729Sjoerg //
5897330f729Sjoerg // FIXME: We shouldn't need to do this, the target should be immutable once
5907330f729Sjoerg // created. This complexity should be lifted elsewhere.
5917330f729Sjoerg Target->adjust(LangOpt);
5927330f729Sjoerg
5937330f729Sjoerg // Initialize the preprocessor.
5947330f729Sjoerg PP.Initialize(*Target);
5957330f729Sjoerg
5967330f729Sjoerg if (!Context)
5977330f729Sjoerg return;
5987330f729Sjoerg
5997330f729Sjoerg // Initialize the ASTContext
6007330f729Sjoerg Context->InitBuiltinTypes(*Target);
6017330f729Sjoerg
6027330f729Sjoerg // Adjust printing policy based on language options.
6037330f729Sjoerg Context->setPrintingPolicy(PrintingPolicy(LangOpt));
6047330f729Sjoerg
6057330f729Sjoerg // We didn't have access to the comment options when the ASTContext was
6067330f729Sjoerg // constructed, so register them now.
6077330f729Sjoerg Context->getCommentCommandTraits().registerCommentOptions(
6087330f729Sjoerg LangOpt.CommentOpts);
6097330f729Sjoerg }
6107330f729Sjoerg };
6117330f729Sjoerg
6127330f729Sjoerg /// Diagnostic consumer that saves each diagnostic it is given.
6137330f729Sjoerg class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {
6147330f729Sjoerg SmallVectorImpl<StoredDiagnostic> *StoredDiags;
6157330f729Sjoerg SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags;
6167330f729Sjoerg bool CaptureNonErrorsFromIncludes = true;
6177330f729Sjoerg const LangOptions *LangOpts = nullptr;
6187330f729Sjoerg SourceManager *SourceMgr = nullptr;
6197330f729Sjoerg
6207330f729Sjoerg public:
FilterAndStoreDiagnosticConsumer(SmallVectorImpl<StoredDiagnostic> * StoredDiags,SmallVectorImpl<ASTUnit::StandaloneDiagnostic> * StandaloneDiags,bool CaptureNonErrorsFromIncludes)6217330f729Sjoerg FilterAndStoreDiagnosticConsumer(
6227330f729Sjoerg SmallVectorImpl<StoredDiagnostic> *StoredDiags,
6237330f729Sjoerg SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags,
6247330f729Sjoerg bool CaptureNonErrorsFromIncludes)
6257330f729Sjoerg : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags),
6267330f729Sjoerg CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) {
6277330f729Sjoerg assert((StoredDiags || StandaloneDiags) &&
6287330f729Sjoerg "No output collections were passed to StoredDiagnosticConsumer.");
6297330f729Sjoerg }
6307330f729Sjoerg
BeginSourceFile(const LangOptions & LangOpts,const Preprocessor * PP=nullptr)6317330f729Sjoerg void BeginSourceFile(const LangOptions &LangOpts,
6327330f729Sjoerg const Preprocessor *PP = nullptr) override {
6337330f729Sjoerg this->LangOpts = &LangOpts;
6347330f729Sjoerg if (PP)
6357330f729Sjoerg SourceMgr = &PP->getSourceManager();
6367330f729Sjoerg }
6377330f729Sjoerg
6387330f729Sjoerg void HandleDiagnostic(DiagnosticsEngine::Level Level,
6397330f729Sjoerg const Diagnostic &Info) override;
6407330f729Sjoerg };
6417330f729Sjoerg
6427330f729Sjoerg /// RAII object that optionally captures and filters diagnostics, if
6437330f729Sjoerg /// there is no diagnostic client to capture them already.
6447330f729Sjoerg class CaptureDroppedDiagnostics {
6457330f729Sjoerg DiagnosticsEngine &Diags;
6467330f729Sjoerg FilterAndStoreDiagnosticConsumer Client;
6477330f729Sjoerg DiagnosticConsumer *PreviousClient = nullptr;
6487330f729Sjoerg std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
6497330f729Sjoerg
6507330f729Sjoerg public:
CaptureDroppedDiagnostics(CaptureDiagsKind CaptureDiagnostics,DiagnosticsEngine & Diags,SmallVectorImpl<StoredDiagnostic> * StoredDiags,SmallVectorImpl<ASTUnit::StandaloneDiagnostic> * StandaloneDiags)6517330f729Sjoerg CaptureDroppedDiagnostics(
6527330f729Sjoerg CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags,
6537330f729Sjoerg SmallVectorImpl<StoredDiagnostic> *StoredDiags,
6547330f729Sjoerg SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags)
6557330f729Sjoerg : Diags(Diags),
6567330f729Sjoerg Client(StoredDiags, StandaloneDiags,
6577330f729Sjoerg CaptureDiagnostics !=
6587330f729Sjoerg CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) {
6597330f729Sjoerg if (CaptureDiagnostics != CaptureDiagsKind::None ||
6607330f729Sjoerg Diags.getClient() == nullptr) {
6617330f729Sjoerg OwningPreviousClient = Diags.takeClient();
6627330f729Sjoerg PreviousClient = Diags.getClient();
6637330f729Sjoerg Diags.setClient(&Client, false);
6647330f729Sjoerg }
6657330f729Sjoerg }
6667330f729Sjoerg
~CaptureDroppedDiagnostics()6677330f729Sjoerg ~CaptureDroppedDiagnostics() {
6687330f729Sjoerg if (Diags.getClient() == &Client)
6697330f729Sjoerg Diags.setClient(PreviousClient, !!OwningPreviousClient.release());
6707330f729Sjoerg }
6717330f729Sjoerg };
6727330f729Sjoerg
6737330f729Sjoerg } // namespace
6747330f729Sjoerg
6757330f729Sjoerg static ASTUnit::StandaloneDiagnostic
6767330f729Sjoerg makeStandaloneDiagnostic(const LangOptions &LangOpts,
6777330f729Sjoerg const StoredDiagnostic &InDiag);
6787330f729Sjoerg
isInMainFile(const clang::Diagnostic & D)6797330f729Sjoerg static bool isInMainFile(const clang::Diagnostic &D) {
6807330f729Sjoerg if (!D.hasSourceManager() || !D.getLocation().isValid())
6817330f729Sjoerg return false;
6827330f729Sjoerg
6837330f729Sjoerg auto &M = D.getSourceManager();
6847330f729Sjoerg return M.isWrittenInMainFile(M.getExpansionLoc(D.getLocation()));
6857330f729Sjoerg }
6867330f729Sjoerg
HandleDiagnostic(DiagnosticsEngine::Level Level,const Diagnostic & Info)6877330f729Sjoerg void FilterAndStoreDiagnosticConsumer::HandleDiagnostic(
6887330f729Sjoerg DiagnosticsEngine::Level Level, const Diagnostic &Info) {
6897330f729Sjoerg // Default implementation (Warnings/errors count).
6907330f729Sjoerg DiagnosticConsumer::HandleDiagnostic(Level, Info);
6917330f729Sjoerg
6927330f729Sjoerg // Only record the diagnostic if it's part of the source manager we know
6937330f729Sjoerg // about. This effectively drops diagnostics from modules we're building.
6947330f729Sjoerg // FIXME: In the long run, ee don't want to drop source managers from modules.
6957330f729Sjoerg if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) {
6967330f729Sjoerg if (!CaptureNonErrorsFromIncludes && Level <= DiagnosticsEngine::Warning &&
6977330f729Sjoerg !isInMainFile(Info)) {
6987330f729Sjoerg return;
6997330f729Sjoerg }
7007330f729Sjoerg
7017330f729Sjoerg StoredDiagnostic *ResultDiag = nullptr;
7027330f729Sjoerg if (StoredDiags) {
7037330f729Sjoerg StoredDiags->emplace_back(Level, Info);
7047330f729Sjoerg ResultDiag = &StoredDiags->back();
7057330f729Sjoerg }
7067330f729Sjoerg
7077330f729Sjoerg if (StandaloneDiags) {
7087330f729Sjoerg llvm::Optional<StoredDiagnostic> StoredDiag = None;
7097330f729Sjoerg if (!ResultDiag) {
7107330f729Sjoerg StoredDiag.emplace(Level, Info);
7117330f729Sjoerg ResultDiag = StoredDiag.getPointer();
7127330f729Sjoerg }
7137330f729Sjoerg StandaloneDiags->push_back(
7147330f729Sjoerg makeStandaloneDiagnostic(*LangOpts, *ResultDiag));
7157330f729Sjoerg }
7167330f729Sjoerg }
7177330f729Sjoerg }
7187330f729Sjoerg
getASTReader() const7197330f729Sjoerg IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {
7207330f729Sjoerg return Reader;
7217330f729Sjoerg }
7227330f729Sjoerg
getASTMutationListener()7237330f729Sjoerg ASTMutationListener *ASTUnit::getASTMutationListener() {
7247330f729Sjoerg if (WriterData)
7257330f729Sjoerg return &WriterData->Writer;
7267330f729Sjoerg return nullptr;
7277330f729Sjoerg }
7287330f729Sjoerg
getDeserializationListener()7297330f729Sjoerg ASTDeserializationListener *ASTUnit::getDeserializationListener() {
7307330f729Sjoerg if (WriterData)
7317330f729Sjoerg return &WriterData->Writer;
7327330f729Sjoerg return nullptr;
7337330f729Sjoerg }
7347330f729Sjoerg
7357330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer>
getBufferForFile(StringRef Filename,std::string * ErrorStr)7367330f729Sjoerg ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {
7377330f729Sjoerg assert(FileMgr);
7387330f729Sjoerg auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile);
7397330f729Sjoerg if (Buffer)
7407330f729Sjoerg return std::move(*Buffer);
7417330f729Sjoerg if (ErrorStr)
7427330f729Sjoerg *ErrorStr = Buffer.getError().message();
7437330f729Sjoerg return nullptr;
7447330f729Sjoerg }
7457330f729Sjoerg
7467330f729Sjoerg /// Configure the diagnostics object for use with ASTUnit.
ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,ASTUnit & AST,CaptureDiagsKind CaptureDiagnostics)7477330f729Sjoerg void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
7487330f729Sjoerg ASTUnit &AST,
7497330f729Sjoerg CaptureDiagsKind CaptureDiagnostics) {
7507330f729Sjoerg assert(Diags.get() && "no DiagnosticsEngine was provided");
7517330f729Sjoerg if (CaptureDiagnostics != CaptureDiagsKind::None)
7527330f729Sjoerg Diags->setClient(new FilterAndStoreDiagnosticConsumer(
7537330f729Sjoerg &AST.StoredDiagnostics, nullptr,
7547330f729Sjoerg CaptureDiagnostics != CaptureDiagsKind::AllWithoutNonErrorsFromIncludes));
7557330f729Sjoerg }
7567330f729Sjoerg
LoadFromASTFile(const std::string & Filename,const PCHContainerReader & PCHContainerRdr,WhatToLoad ToLoad,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,const FileSystemOptions & FileSystemOpts,bool UseDebugInfo,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,bool AllowASTWithCompilerErrors,bool UserFilesAreVolatile)7577330f729Sjoerg std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
7587330f729Sjoerg const std::string &Filename, const PCHContainerReader &PCHContainerRdr,
7597330f729Sjoerg WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
7607330f729Sjoerg const FileSystemOptions &FileSystemOpts, bool UseDebugInfo,
761*e038c9c4Sjoerg bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
762*e038c9c4Sjoerg bool AllowASTWithCompilerErrors, bool UserFilesAreVolatile) {
7637330f729Sjoerg std::unique_ptr<ASTUnit> AST(new ASTUnit(true));
7647330f729Sjoerg
7657330f729Sjoerg // Recover resources if we crash before exiting this method.
7667330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
7677330f729Sjoerg ASTUnitCleanup(AST.get());
7687330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
7697330f729Sjoerg llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
7707330f729Sjoerg DiagCleanup(Diags.get());
7717330f729Sjoerg
7727330f729Sjoerg ConfigureDiags(Diags, *AST, CaptureDiagnostics);
7737330f729Sjoerg
7747330f729Sjoerg AST->LangOpts = std::make_shared<LangOptions>();
7757330f729Sjoerg AST->OnlyLocalDecls = OnlyLocalDecls;
7767330f729Sjoerg AST->CaptureDiagnostics = CaptureDiagnostics;
7777330f729Sjoerg AST->Diagnostics = Diags;
7787330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
7797330f729Sjoerg llvm::vfs::getRealFileSystem();
7807330f729Sjoerg AST->FileMgr = new FileManager(FileSystemOpts, VFS);
7817330f729Sjoerg AST->UserFilesAreVolatile = UserFilesAreVolatile;
7827330f729Sjoerg AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
7837330f729Sjoerg AST->getFileManager(),
7847330f729Sjoerg UserFilesAreVolatile);
7857330f729Sjoerg AST->ModuleCache = new InMemoryModuleCache;
7867330f729Sjoerg AST->HSOpts = std::make_shared<HeaderSearchOptions>();
787*e038c9c4Sjoerg AST->HSOpts->ModuleFormat = std::string(PCHContainerRdr.getFormat());
7887330f729Sjoerg AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts,
7897330f729Sjoerg AST->getSourceManager(),
7907330f729Sjoerg AST->getDiagnostics(),
7917330f729Sjoerg AST->getLangOpts(),
7927330f729Sjoerg /*Target=*/nullptr));
7937330f729Sjoerg AST->PPOpts = std::make_shared<PreprocessorOptions>();
7947330f729Sjoerg
7957330f729Sjoerg // Gather Info for preprocessor construction later on.
7967330f729Sjoerg
7977330f729Sjoerg HeaderSearch &HeaderInfo = *AST->HeaderInfo;
7987330f729Sjoerg unsigned Counter;
7997330f729Sjoerg
8007330f729Sjoerg AST->PP = std::make_shared<Preprocessor>(
8017330f729Sjoerg AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts,
8027330f729Sjoerg AST->getSourceManager(), HeaderInfo, AST->ModuleLoader,
8037330f729Sjoerg /*IILookup=*/nullptr,
8047330f729Sjoerg /*OwnsHeaderSearch=*/false);
8057330f729Sjoerg Preprocessor &PP = *AST->PP;
8067330f729Sjoerg
8077330f729Sjoerg if (ToLoad >= LoadASTOnly)
8087330f729Sjoerg AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(),
8097330f729Sjoerg PP.getIdentifierTable(), PP.getSelectorTable(),
8107330f729Sjoerg PP.getBuiltinInfo());
8117330f729Sjoerg
812*e038c9c4Sjoerg DisableValidationForModuleKind disableValid =
813*e038c9c4Sjoerg DisableValidationForModuleKind::None;
8147330f729Sjoerg if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION"))
815*e038c9c4Sjoerg disableValid = DisableValidationForModuleKind::All;
8167330f729Sjoerg AST->Reader = new ASTReader(
8177330f729Sjoerg PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {},
8187330f729Sjoerg /*isysroot=*/"",
819*e038c9c4Sjoerg /*DisableValidation=*/disableValid, AllowASTWithCompilerErrors);
8207330f729Sjoerg
8217330f729Sjoerg AST->Reader->setListener(std::make_unique<ASTInfoCollector>(
8227330f729Sjoerg *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts,
8237330f729Sjoerg AST->TargetOpts, AST->Target, Counter));
8247330f729Sjoerg
8257330f729Sjoerg // Attach the AST reader to the AST context as an external AST
8267330f729Sjoerg // source, so that declarations will be deserialized from the
8277330f729Sjoerg // AST file as needed.
8287330f729Sjoerg // We need the external source to be set up before we read the AST, because
8297330f729Sjoerg // eagerly-deserialized declarations may use it.
8307330f729Sjoerg if (AST->Ctx)
8317330f729Sjoerg AST->Ctx->setExternalSource(AST->Reader);
8327330f729Sjoerg
8337330f729Sjoerg switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,
8347330f729Sjoerg SourceLocation(), ASTReader::ARR_None)) {
8357330f729Sjoerg case ASTReader::Success:
8367330f729Sjoerg break;
8377330f729Sjoerg
8387330f729Sjoerg case ASTReader::Failure:
8397330f729Sjoerg case ASTReader::Missing:
8407330f729Sjoerg case ASTReader::OutOfDate:
8417330f729Sjoerg case ASTReader::VersionMismatch:
8427330f729Sjoerg case ASTReader::ConfigurationMismatch:
8437330f729Sjoerg case ASTReader::HadErrors:
8447330f729Sjoerg AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
8457330f729Sjoerg return nullptr;
8467330f729Sjoerg }
8477330f729Sjoerg
848*e038c9c4Sjoerg AST->OriginalSourceFile = std::string(AST->Reader->getOriginalSourceFile());
8497330f729Sjoerg
8507330f729Sjoerg PP.setCounterValue(Counter);
8517330f729Sjoerg
8527330f729Sjoerg // Create an AST consumer, even though it isn't used.
8537330f729Sjoerg if (ToLoad >= LoadASTOnly)
8547330f729Sjoerg AST->Consumer.reset(new ASTConsumer);
8557330f729Sjoerg
8567330f729Sjoerg // Create a semantic analysis object and tell the AST reader about it.
8577330f729Sjoerg if (ToLoad >= LoadEverything) {
8587330f729Sjoerg AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer));
8597330f729Sjoerg AST->TheSema->Initialize();
8607330f729Sjoerg AST->Reader->InitializeSema(*AST->TheSema);
8617330f729Sjoerg }
8627330f729Sjoerg
8637330f729Sjoerg // Tell the diagnostic client that we have started a source file.
8647330f729Sjoerg AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP);
8657330f729Sjoerg
8667330f729Sjoerg return AST;
8677330f729Sjoerg }
8687330f729Sjoerg
8697330f729Sjoerg /// Add the given macro to the hash of all top-level entities.
AddDefinedMacroToHash(const Token & MacroNameTok,unsigned & Hash)8707330f729Sjoerg static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {
8717330f729Sjoerg Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash);
8727330f729Sjoerg }
8737330f729Sjoerg
8747330f729Sjoerg namespace {
8757330f729Sjoerg
8767330f729Sjoerg /// Preprocessor callback class that updates a hash value with the names
8777330f729Sjoerg /// of all macros that have been defined by the translation unit.
8787330f729Sjoerg class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
8797330f729Sjoerg unsigned &Hash;
8807330f729Sjoerg
8817330f729Sjoerg public:
MacroDefinitionTrackerPPCallbacks(unsigned & Hash)8827330f729Sjoerg explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {}
8837330f729Sjoerg
MacroDefined(const Token & MacroNameTok,const MacroDirective * MD)8847330f729Sjoerg void MacroDefined(const Token &MacroNameTok,
8857330f729Sjoerg const MacroDirective *MD) override {
8867330f729Sjoerg AddDefinedMacroToHash(MacroNameTok, Hash);
8877330f729Sjoerg }
8887330f729Sjoerg };
8897330f729Sjoerg
8907330f729Sjoerg } // namespace
8917330f729Sjoerg
8927330f729Sjoerg /// Add the given declaration to the hash of all top-level entities.
AddTopLevelDeclarationToHash(Decl * D,unsigned & Hash)8937330f729Sjoerg static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
8947330f729Sjoerg if (!D)
8957330f729Sjoerg return;
8967330f729Sjoerg
8977330f729Sjoerg DeclContext *DC = D->getDeclContext();
8987330f729Sjoerg if (!DC)
8997330f729Sjoerg return;
9007330f729Sjoerg
9017330f729Sjoerg if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
9027330f729Sjoerg return;
9037330f729Sjoerg
9047330f729Sjoerg if (const auto *ND = dyn_cast<NamedDecl>(D)) {
9057330f729Sjoerg if (const auto *EnumD = dyn_cast<EnumDecl>(D)) {
9067330f729Sjoerg // For an unscoped enum include the enumerators in the hash since they
9077330f729Sjoerg // enter the top-level namespace.
9087330f729Sjoerg if (!EnumD->isScoped()) {
9097330f729Sjoerg for (const auto *EI : EnumD->enumerators()) {
9107330f729Sjoerg if (EI->getIdentifier())
9117330f729Sjoerg Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash);
9127330f729Sjoerg }
9137330f729Sjoerg }
9147330f729Sjoerg }
9157330f729Sjoerg
9167330f729Sjoerg if (ND->getIdentifier())
9177330f729Sjoerg Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash);
9187330f729Sjoerg else if (DeclarationName Name = ND->getDeclName()) {
9197330f729Sjoerg std::string NameStr = Name.getAsString();
9207330f729Sjoerg Hash = llvm::djbHash(NameStr, Hash);
9217330f729Sjoerg }
9227330f729Sjoerg return;
9237330f729Sjoerg }
9247330f729Sjoerg
9257330f729Sjoerg if (const auto *ImportD = dyn_cast<ImportDecl>(D)) {
9267330f729Sjoerg if (const Module *Mod = ImportD->getImportedModule()) {
9277330f729Sjoerg std::string ModName = Mod->getFullModuleName();
9287330f729Sjoerg Hash = llvm::djbHash(ModName, Hash);
9297330f729Sjoerg }
9307330f729Sjoerg return;
9317330f729Sjoerg }
9327330f729Sjoerg }
9337330f729Sjoerg
9347330f729Sjoerg namespace {
9357330f729Sjoerg
9367330f729Sjoerg class TopLevelDeclTrackerConsumer : public ASTConsumer {
9377330f729Sjoerg ASTUnit &Unit;
9387330f729Sjoerg unsigned &Hash;
9397330f729Sjoerg
9407330f729Sjoerg public:
TopLevelDeclTrackerConsumer(ASTUnit & _Unit,unsigned & Hash)9417330f729Sjoerg TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
9427330f729Sjoerg : Unit(_Unit), Hash(Hash) {
9437330f729Sjoerg Hash = 0;
9447330f729Sjoerg }
9457330f729Sjoerg
handleTopLevelDecl(Decl * D)9467330f729Sjoerg void handleTopLevelDecl(Decl *D) {
9477330f729Sjoerg if (!D)
9487330f729Sjoerg return;
9497330f729Sjoerg
9507330f729Sjoerg // FIXME: Currently ObjC method declarations are incorrectly being
9517330f729Sjoerg // reported as top-level declarations, even though their DeclContext
9527330f729Sjoerg // is the containing ObjC @interface/@implementation. This is a
9537330f729Sjoerg // fundamental problem in the parser right now.
9547330f729Sjoerg if (isa<ObjCMethodDecl>(D))
9557330f729Sjoerg return;
9567330f729Sjoerg
9577330f729Sjoerg AddTopLevelDeclarationToHash(D, Hash);
9587330f729Sjoerg Unit.addTopLevelDecl(D);
9597330f729Sjoerg
9607330f729Sjoerg handleFileLevelDecl(D);
9617330f729Sjoerg }
9627330f729Sjoerg
handleFileLevelDecl(Decl * D)9637330f729Sjoerg void handleFileLevelDecl(Decl *D) {
9647330f729Sjoerg Unit.addFileLevelDecl(D);
9657330f729Sjoerg if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
9667330f729Sjoerg for (auto *I : NSD->decls())
9677330f729Sjoerg handleFileLevelDecl(I);
9687330f729Sjoerg }
9697330f729Sjoerg }
9707330f729Sjoerg
HandleTopLevelDecl(DeclGroupRef D)9717330f729Sjoerg bool HandleTopLevelDecl(DeclGroupRef D) override {
9727330f729Sjoerg for (auto *TopLevelDecl : D)
9737330f729Sjoerg handleTopLevelDecl(TopLevelDecl);
9747330f729Sjoerg return true;
9757330f729Sjoerg }
9767330f729Sjoerg
9777330f729Sjoerg // We're not interested in "interesting" decls.
HandleInterestingDecl(DeclGroupRef)9787330f729Sjoerg void HandleInterestingDecl(DeclGroupRef) override {}
9797330f729Sjoerg
HandleTopLevelDeclInObjCContainer(DeclGroupRef D)9807330f729Sjoerg void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
9817330f729Sjoerg for (auto *TopLevelDecl : D)
9827330f729Sjoerg handleTopLevelDecl(TopLevelDecl);
9837330f729Sjoerg }
9847330f729Sjoerg
GetASTMutationListener()9857330f729Sjoerg ASTMutationListener *GetASTMutationListener() override {
9867330f729Sjoerg return Unit.getASTMutationListener();
9877330f729Sjoerg }
9887330f729Sjoerg
GetASTDeserializationListener()9897330f729Sjoerg ASTDeserializationListener *GetASTDeserializationListener() override {
9907330f729Sjoerg return Unit.getDeserializationListener();
9917330f729Sjoerg }
9927330f729Sjoerg };
9937330f729Sjoerg
9947330f729Sjoerg class TopLevelDeclTrackerAction : public ASTFrontendAction {
9957330f729Sjoerg public:
9967330f729Sjoerg ASTUnit &Unit;
9977330f729Sjoerg
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)9987330f729Sjoerg std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
9997330f729Sjoerg StringRef InFile) override {
10007330f729Sjoerg CI.getPreprocessor().addPPCallbacks(
10017330f729Sjoerg std::make_unique<MacroDefinitionTrackerPPCallbacks>(
10027330f729Sjoerg Unit.getCurrentTopLevelHashValue()));
10037330f729Sjoerg return std::make_unique<TopLevelDeclTrackerConsumer>(
10047330f729Sjoerg Unit, Unit.getCurrentTopLevelHashValue());
10057330f729Sjoerg }
10067330f729Sjoerg
10077330f729Sjoerg public:
TopLevelDeclTrackerAction(ASTUnit & _Unit)10087330f729Sjoerg TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
10097330f729Sjoerg
hasCodeCompletionSupport() const10107330f729Sjoerg bool hasCodeCompletionSupport() const override { return false; }
10117330f729Sjoerg
getTranslationUnitKind()10127330f729Sjoerg TranslationUnitKind getTranslationUnitKind() override {
10137330f729Sjoerg return Unit.getTranslationUnitKind();
10147330f729Sjoerg }
10157330f729Sjoerg };
10167330f729Sjoerg
10177330f729Sjoerg class ASTUnitPreambleCallbacks : public PreambleCallbacks {
10187330f729Sjoerg public:
getHash() const10197330f729Sjoerg unsigned getHash() const { return Hash; }
10207330f729Sjoerg
takeTopLevelDecls()10217330f729Sjoerg std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); }
10227330f729Sjoerg
takeTopLevelDeclIDs()10237330f729Sjoerg std::vector<serialization::DeclID> takeTopLevelDeclIDs() {
10247330f729Sjoerg return std::move(TopLevelDeclIDs);
10257330f729Sjoerg }
10267330f729Sjoerg
AfterPCHEmitted(ASTWriter & Writer)10277330f729Sjoerg void AfterPCHEmitted(ASTWriter &Writer) override {
10287330f729Sjoerg TopLevelDeclIDs.reserve(TopLevelDecls.size());
10297330f729Sjoerg for (const auto *D : TopLevelDecls) {
10307330f729Sjoerg // Invalid top-level decls may not have been serialized.
10317330f729Sjoerg if (D->isInvalidDecl())
10327330f729Sjoerg continue;
10337330f729Sjoerg TopLevelDeclIDs.push_back(Writer.getDeclID(D));
10347330f729Sjoerg }
10357330f729Sjoerg }
10367330f729Sjoerg
HandleTopLevelDecl(DeclGroupRef DG)10377330f729Sjoerg void HandleTopLevelDecl(DeclGroupRef DG) override {
10387330f729Sjoerg for (auto *D : DG) {
10397330f729Sjoerg // FIXME: Currently ObjC method declarations are incorrectly being
10407330f729Sjoerg // reported as top-level declarations, even though their DeclContext
10417330f729Sjoerg // is the containing ObjC @interface/@implementation. This is a
10427330f729Sjoerg // fundamental problem in the parser right now.
10437330f729Sjoerg if (isa<ObjCMethodDecl>(D))
10447330f729Sjoerg continue;
10457330f729Sjoerg AddTopLevelDeclarationToHash(D, Hash);
10467330f729Sjoerg TopLevelDecls.push_back(D);
10477330f729Sjoerg }
10487330f729Sjoerg }
10497330f729Sjoerg
createPPCallbacks()10507330f729Sjoerg std::unique_ptr<PPCallbacks> createPPCallbacks() override {
10517330f729Sjoerg return std::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash);
10527330f729Sjoerg }
10537330f729Sjoerg
10547330f729Sjoerg private:
10557330f729Sjoerg unsigned Hash = 0;
10567330f729Sjoerg std::vector<Decl *> TopLevelDecls;
10577330f729Sjoerg std::vector<serialization::DeclID> TopLevelDeclIDs;
10587330f729Sjoerg llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags;
10597330f729Sjoerg };
10607330f729Sjoerg
10617330f729Sjoerg } // namespace
10627330f729Sjoerg
isNonDriverDiag(const StoredDiagnostic & StoredDiag)10637330f729Sjoerg static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {
10647330f729Sjoerg return StoredDiag.getLocation().isValid();
10657330f729Sjoerg }
10667330f729Sjoerg
10677330f729Sjoerg static void
checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> & StoredDiags)10687330f729Sjoerg checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) {
10697330f729Sjoerg // Get rid of stored diagnostics except the ones from the driver which do not
10707330f729Sjoerg // have a source location.
10717330f729Sjoerg StoredDiags.erase(
10727330f729Sjoerg std::remove_if(StoredDiags.begin(), StoredDiags.end(), isNonDriverDiag),
10737330f729Sjoerg StoredDiags.end());
10747330f729Sjoerg }
10757330f729Sjoerg
checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> & StoredDiagnostics,SourceManager & SM)10767330f729Sjoerg static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
10777330f729Sjoerg StoredDiagnostics,
10787330f729Sjoerg SourceManager &SM) {
10797330f729Sjoerg // The stored diagnostic has the old source manager in it; update
10807330f729Sjoerg // the locations to refer into the new source manager. Since we've
10817330f729Sjoerg // been careful to make sure that the source manager's state
10827330f729Sjoerg // before and after are identical, so that we can reuse the source
10837330f729Sjoerg // location itself.
10847330f729Sjoerg for (auto &SD : StoredDiagnostics) {
10857330f729Sjoerg if (SD.getLocation().isValid()) {
10867330f729Sjoerg FullSourceLoc Loc(SD.getLocation(), SM);
10877330f729Sjoerg SD.setLocation(Loc);
10887330f729Sjoerg }
10897330f729Sjoerg }
10907330f729Sjoerg }
10917330f729Sjoerg
10927330f729Sjoerg /// Parse the source file into a translation unit using the given compiler
10937330f729Sjoerg /// invocation, replacing the current translation unit.
10947330f729Sjoerg ///
10957330f729Sjoerg /// \returns True if a failure occurred that causes the ASTUnit not to
10967330f729Sjoerg /// contain any translation-unit information, false otherwise.
Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)10977330f729Sjoerg bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
10987330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
10997330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
11007330f729Sjoerg if (!Invocation)
11017330f729Sjoerg return true;
11027330f729Sjoerg
11037330f729Sjoerg if (VFS && FileMgr)
11047330f729Sjoerg assert(VFS == &FileMgr->getVirtualFileSystem() &&
11057330f729Sjoerg "VFS passed to Parse and VFS in FileMgr are different");
11067330f729Sjoerg
11077330f729Sjoerg auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);
11087330f729Sjoerg if (OverrideMainBuffer) {
11097330f729Sjoerg assert(Preamble &&
11107330f729Sjoerg "No preamble was built, but OverrideMainBuffer is not null");
11117330f729Sjoerg Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get());
11127330f729Sjoerg // VFS may have changed...
11137330f729Sjoerg }
11147330f729Sjoerg
11157330f729Sjoerg // Create the compiler instance to use for building the AST.
11167330f729Sjoerg std::unique_ptr<CompilerInstance> Clang(
11177330f729Sjoerg new CompilerInstance(std::move(PCHContainerOps)));
11187330f729Sjoerg
1119*e038c9c4Sjoerg // Clean up on error, disengage it if the function returns successfully.
1120*e038c9c4Sjoerg auto CleanOnError = llvm::make_scope_exit([&]() {
1121*e038c9c4Sjoerg // Remove the overridden buffer we used for the preamble.
1122*e038c9c4Sjoerg SavedMainFileBuffer = nullptr;
1123*e038c9c4Sjoerg
1124*e038c9c4Sjoerg // Keep the ownership of the data in the ASTUnit because the client may
1125*e038c9c4Sjoerg // want to see the diagnostics.
1126*e038c9c4Sjoerg transferASTDataFromCompilerInstance(*Clang);
1127*e038c9c4Sjoerg FailedParseDiagnostics.swap(StoredDiagnostics);
1128*e038c9c4Sjoerg StoredDiagnostics.clear();
1129*e038c9c4Sjoerg NumStoredDiagnosticsFromDriver = 0;
1130*e038c9c4Sjoerg });
1131*e038c9c4Sjoerg
11327330f729Sjoerg // Ensure that Clang has a FileManager with the right VFS, which may have
11337330f729Sjoerg // changed above in AddImplicitPreamble. If VFS is nullptr, rely on
11347330f729Sjoerg // createFileManager to create one.
11357330f729Sjoerg if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS)
11367330f729Sjoerg Clang->setFileManager(&*FileMgr);
11377330f729Sjoerg else
11387330f729Sjoerg FileMgr = Clang->createFileManager(std::move(VFS));
11397330f729Sjoerg
11407330f729Sjoerg // Recover resources if we crash before exiting this method.
11417330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
11427330f729Sjoerg CICleanup(Clang.get());
11437330f729Sjoerg
11447330f729Sjoerg Clang->setInvocation(CCInvocation);
1145*e038c9c4Sjoerg OriginalSourceFile =
1146*e038c9c4Sjoerg std::string(Clang->getFrontendOpts().Inputs[0].getFile());
11477330f729Sjoerg
11487330f729Sjoerg // Set up diagnostics, capturing any diagnostics that would
11497330f729Sjoerg // otherwise be dropped.
11507330f729Sjoerg Clang->setDiagnostics(&getDiagnostics());
11517330f729Sjoerg
11527330f729Sjoerg // Create the target instance.
1153*e038c9c4Sjoerg if (!Clang->createTarget())
11547330f729Sjoerg return true;
11557330f729Sjoerg
11567330f729Sjoerg assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
11577330f729Sjoerg "Invocation must have exactly one source file!");
11587330f729Sjoerg assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
11597330f729Sjoerg InputKind::Source &&
11607330f729Sjoerg "FIXME: AST inputs not yet supported here!");
11617330f729Sjoerg assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
11627330f729Sjoerg Language::LLVM_IR &&
11637330f729Sjoerg "IR inputs not support here!");
11647330f729Sjoerg
11657330f729Sjoerg // Configure the various subsystems.
11667330f729Sjoerg LangOpts = Clang->getInvocation().LangOpts;
11677330f729Sjoerg FileSystemOpts = Clang->getFileSystemOpts();
11687330f729Sjoerg
11697330f729Sjoerg ResetForParse();
11707330f729Sjoerg
11717330f729Sjoerg SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
11727330f729Sjoerg UserFilesAreVolatile);
11737330f729Sjoerg if (!OverrideMainBuffer) {
11747330f729Sjoerg checkAndRemoveNonDriverDiags(StoredDiagnostics);
11757330f729Sjoerg TopLevelDeclsInPreamble.clear();
11767330f729Sjoerg }
11777330f729Sjoerg
11787330f729Sjoerg // Create the source manager.
11797330f729Sjoerg Clang->setSourceManager(&getSourceManager());
11807330f729Sjoerg
11817330f729Sjoerg // If the main file has been overridden due to the use of a preamble,
11827330f729Sjoerg // make that override happen and introduce the preamble.
11837330f729Sjoerg if (OverrideMainBuffer) {
11847330f729Sjoerg // The stored diagnostic has the old source manager in it; update
11857330f729Sjoerg // the locations to refer into the new source manager. Since we've
11867330f729Sjoerg // been careful to make sure that the source manager's state
11877330f729Sjoerg // before and after are identical, so that we can reuse the source
11887330f729Sjoerg // location itself.
11897330f729Sjoerg checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());
11907330f729Sjoerg
11917330f729Sjoerg // Keep track of the override buffer;
11927330f729Sjoerg SavedMainFileBuffer = std::move(OverrideMainBuffer);
11937330f729Sjoerg }
11947330f729Sjoerg
11957330f729Sjoerg std::unique_ptr<TopLevelDeclTrackerAction> Act(
11967330f729Sjoerg new TopLevelDeclTrackerAction(*this));
11977330f729Sjoerg
11987330f729Sjoerg // Recover resources if we crash before exiting this method.
11997330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
12007330f729Sjoerg ActCleanup(Act.get());
12017330f729Sjoerg
12027330f729Sjoerg if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
1203*e038c9c4Sjoerg return true;
12047330f729Sjoerg
12057330f729Sjoerg if (SavedMainFileBuffer)
12067330f729Sjoerg TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
12077330f729Sjoerg PreambleDiagnostics, StoredDiagnostics);
12087330f729Sjoerg else
12097330f729Sjoerg PreambleSrcLocCache.clear();
12107330f729Sjoerg
12117330f729Sjoerg if (llvm::Error Err = Act->Execute()) {
12127330f729Sjoerg consumeError(std::move(Err)); // FIXME this drops errors on the floor.
1213*e038c9c4Sjoerg return true;
12147330f729Sjoerg }
12157330f729Sjoerg
12167330f729Sjoerg transferASTDataFromCompilerInstance(*Clang);
12177330f729Sjoerg
12187330f729Sjoerg Act->EndSourceFile();
12197330f729Sjoerg
12207330f729Sjoerg FailedParseDiagnostics.clear();
12217330f729Sjoerg
1222*e038c9c4Sjoerg CleanOnError.release();
1223*e038c9c4Sjoerg
12247330f729Sjoerg return false;
12257330f729Sjoerg }
12267330f729Sjoerg
12277330f729Sjoerg static std::pair<unsigned, unsigned>
makeStandaloneRange(CharSourceRange Range,const SourceManager & SM,const LangOptions & LangOpts)12287330f729Sjoerg makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,
12297330f729Sjoerg const LangOptions &LangOpts) {
12307330f729Sjoerg CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts);
12317330f729Sjoerg unsigned Offset = SM.getFileOffset(FileRange.getBegin());
12327330f729Sjoerg unsigned EndOffset = SM.getFileOffset(FileRange.getEnd());
12337330f729Sjoerg return std::make_pair(Offset, EndOffset);
12347330f729Sjoerg }
12357330f729Sjoerg
makeStandaloneFixIt(const SourceManager & SM,const LangOptions & LangOpts,const FixItHint & InFix)12367330f729Sjoerg static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM,
12377330f729Sjoerg const LangOptions &LangOpts,
12387330f729Sjoerg const FixItHint &InFix) {
12397330f729Sjoerg ASTUnit::StandaloneFixIt OutFix;
12407330f729Sjoerg OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts);
12417330f729Sjoerg OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM,
12427330f729Sjoerg LangOpts);
12437330f729Sjoerg OutFix.CodeToInsert = InFix.CodeToInsert;
12447330f729Sjoerg OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions;
12457330f729Sjoerg return OutFix;
12467330f729Sjoerg }
12477330f729Sjoerg
12487330f729Sjoerg static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions & LangOpts,const StoredDiagnostic & InDiag)12497330f729Sjoerg makeStandaloneDiagnostic(const LangOptions &LangOpts,
12507330f729Sjoerg const StoredDiagnostic &InDiag) {
12517330f729Sjoerg ASTUnit::StandaloneDiagnostic OutDiag;
12527330f729Sjoerg OutDiag.ID = InDiag.getID();
12537330f729Sjoerg OutDiag.Level = InDiag.getLevel();
1254*e038c9c4Sjoerg OutDiag.Message = std::string(InDiag.getMessage());
12557330f729Sjoerg OutDiag.LocOffset = 0;
12567330f729Sjoerg if (InDiag.getLocation().isInvalid())
12577330f729Sjoerg return OutDiag;
12587330f729Sjoerg const SourceManager &SM = InDiag.getLocation().getManager();
12597330f729Sjoerg SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation());
1260*e038c9c4Sjoerg OutDiag.Filename = std::string(SM.getFilename(FileLoc));
12617330f729Sjoerg if (OutDiag.Filename.empty())
12627330f729Sjoerg return OutDiag;
12637330f729Sjoerg OutDiag.LocOffset = SM.getFileOffset(FileLoc);
12647330f729Sjoerg for (const auto &Range : InDiag.getRanges())
12657330f729Sjoerg OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts));
12667330f729Sjoerg for (const auto &FixIt : InDiag.getFixIts())
12677330f729Sjoerg OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt));
12687330f729Sjoerg
12697330f729Sjoerg return OutDiag;
12707330f729Sjoerg }
12717330f729Sjoerg
12727330f729Sjoerg /// Attempt to build or re-use a precompiled preamble when (re-)parsing
12737330f729Sjoerg /// the source file.
12747330f729Sjoerg ///
12757330f729Sjoerg /// This routine will compute the preamble of the main source file. If a
12767330f729Sjoerg /// non-trivial preamble is found, it will precompile that preamble into a
12777330f729Sjoerg /// precompiled header so that the precompiled preamble can be used to reduce
12787330f729Sjoerg /// reparsing time. If a precompiled preamble has already been constructed,
12797330f729Sjoerg /// this routine will determine if it is still valid and, if so, avoid
12807330f729Sjoerg /// rebuilding the precompiled preamble.
12817330f729Sjoerg ///
12827330f729Sjoerg /// \param AllowRebuild When true (the default), this routine is
12837330f729Sjoerg /// allowed to rebuild the precompiled preamble if it is found to be
12847330f729Sjoerg /// out-of-date.
12857330f729Sjoerg ///
12867330f729Sjoerg /// \param MaxLines When non-zero, the maximum number of lines that
12877330f729Sjoerg /// can occur within the preamble.
12887330f729Sjoerg ///
12897330f729Sjoerg /// \returns If the precompiled preamble can be used, returns a newly-allocated
12907330f729Sjoerg /// buffer that should be used in place of the main file when doing so.
12917330f729Sjoerg /// Otherwise, returns a NULL pointer.
12927330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer>
getMainBufferWithPrecompiledPreamble(std::shared_ptr<PCHContainerOperations> PCHContainerOps,CompilerInvocation & PreambleInvocationIn,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,bool AllowRebuild,unsigned MaxLines)12937330f729Sjoerg ASTUnit::getMainBufferWithPrecompiledPreamble(
12947330f729Sjoerg std::shared_ptr<PCHContainerOperations> PCHContainerOps,
12957330f729Sjoerg CompilerInvocation &PreambleInvocationIn,
12967330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild,
12977330f729Sjoerg unsigned MaxLines) {
12987330f729Sjoerg auto MainFilePath =
12997330f729Sjoerg PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile();
13007330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer =
13017330f729Sjoerg getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(),
13027330f729Sjoerg MainFilePath, UserFilesAreVolatile);
13037330f729Sjoerg if (!MainFileBuffer)
13047330f729Sjoerg return nullptr;
13057330f729Sjoerg
1306*e038c9c4Sjoerg PreambleBounds Bounds = ComputePreambleBounds(
1307*e038c9c4Sjoerg *PreambleInvocationIn.getLangOpts(), *MainFileBuffer, MaxLines);
13087330f729Sjoerg if (!Bounds.Size)
13097330f729Sjoerg return nullptr;
13107330f729Sjoerg
13117330f729Sjoerg if (Preamble) {
1312*e038c9c4Sjoerg if (Preamble->CanReuse(PreambleInvocationIn, *MainFileBuffer, Bounds,
1313*e038c9c4Sjoerg *VFS)) {
13147330f729Sjoerg // Okay! We can re-use the precompiled preamble.
13157330f729Sjoerg
13167330f729Sjoerg // Set the state of the diagnostic object to mimic its state
13177330f729Sjoerg // after parsing the preamble.
13187330f729Sjoerg getDiagnostics().Reset();
13197330f729Sjoerg ProcessWarningOptions(getDiagnostics(),
13207330f729Sjoerg PreambleInvocationIn.getDiagnosticOpts());
13217330f729Sjoerg getDiagnostics().setNumWarnings(NumWarningsInPreamble);
13227330f729Sjoerg
13237330f729Sjoerg PreambleRebuildCountdown = 1;
13247330f729Sjoerg return MainFileBuffer;
13257330f729Sjoerg } else {
13267330f729Sjoerg Preamble.reset();
13277330f729Sjoerg PreambleDiagnostics.clear();
13287330f729Sjoerg TopLevelDeclsInPreamble.clear();
13297330f729Sjoerg PreambleSrcLocCache.clear();
13307330f729Sjoerg PreambleRebuildCountdown = 1;
13317330f729Sjoerg }
13327330f729Sjoerg }
13337330f729Sjoerg
13347330f729Sjoerg // If the preamble rebuild counter > 1, it's because we previously
13357330f729Sjoerg // failed to build a preamble and we're not yet ready to try
13367330f729Sjoerg // again. Decrement the counter and return a failure.
13377330f729Sjoerg if (PreambleRebuildCountdown > 1) {
13387330f729Sjoerg --PreambleRebuildCountdown;
13397330f729Sjoerg return nullptr;
13407330f729Sjoerg }
13417330f729Sjoerg
13427330f729Sjoerg assert(!Preamble && "No Preamble should be stored at that point");
13437330f729Sjoerg // If we aren't allowed to rebuild the precompiled preamble, just
13447330f729Sjoerg // return now.
13457330f729Sjoerg if (!AllowRebuild)
13467330f729Sjoerg return nullptr;
13477330f729Sjoerg
13487330f729Sjoerg ++PreambleCounter;
13497330f729Sjoerg
13507330f729Sjoerg SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone;
13517330f729Sjoerg SmallVector<StoredDiagnostic, 4> NewPreambleDiags;
13527330f729Sjoerg ASTUnitPreambleCallbacks Callbacks;
13537330f729Sjoerg {
13547330f729Sjoerg llvm::Optional<CaptureDroppedDiagnostics> Capture;
13557330f729Sjoerg if (CaptureDiagnostics != CaptureDiagsKind::None)
13567330f729Sjoerg Capture.emplace(CaptureDiagnostics, *Diagnostics, &NewPreambleDiags,
13577330f729Sjoerg &NewPreambleDiagsStandalone);
13587330f729Sjoerg
13597330f729Sjoerg // We did not previously compute a preamble, or it can't be reused anyway.
13607330f729Sjoerg SimpleTimer PreambleTimer(WantTiming);
13617330f729Sjoerg PreambleTimer.setOutput("Precompiling preamble");
13627330f729Sjoerg
13637330f729Sjoerg const bool PreviousSkipFunctionBodies =
13647330f729Sjoerg PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies;
13657330f729Sjoerg if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble)
13667330f729Sjoerg PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true;
13677330f729Sjoerg
13687330f729Sjoerg llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build(
13697330f729Sjoerg PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS,
13707330f729Sjoerg PCHContainerOps, /*StoreInMemory=*/false, Callbacks);
13717330f729Sjoerg
13727330f729Sjoerg PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies =
13737330f729Sjoerg PreviousSkipFunctionBodies;
13747330f729Sjoerg
13757330f729Sjoerg if (NewPreamble) {
13767330f729Sjoerg Preamble = std::move(*NewPreamble);
13777330f729Sjoerg PreambleRebuildCountdown = 1;
13787330f729Sjoerg } else {
13797330f729Sjoerg switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) {
13807330f729Sjoerg case BuildPreambleError::CouldntCreateTempFile:
13817330f729Sjoerg // Try again next time.
13827330f729Sjoerg PreambleRebuildCountdown = 1;
13837330f729Sjoerg return nullptr;
13847330f729Sjoerg case BuildPreambleError::CouldntCreateTargetInfo:
13857330f729Sjoerg case BuildPreambleError::BeginSourceFileFailed:
13867330f729Sjoerg case BuildPreambleError::CouldntEmitPCH:
13877330f729Sjoerg case BuildPreambleError::BadInputs:
13887330f729Sjoerg // These erros are more likely to repeat, retry after some period.
13897330f729Sjoerg PreambleRebuildCountdown = DefaultPreambleRebuildInterval;
13907330f729Sjoerg return nullptr;
13917330f729Sjoerg }
13927330f729Sjoerg llvm_unreachable("unexpected BuildPreambleError");
13937330f729Sjoerg }
13947330f729Sjoerg }
13957330f729Sjoerg
13967330f729Sjoerg assert(Preamble && "Preamble wasn't built");
13977330f729Sjoerg
13987330f729Sjoerg TopLevelDecls.clear();
13997330f729Sjoerg TopLevelDeclsInPreamble = Callbacks.takeTopLevelDeclIDs();
14007330f729Sjoerg PreambleTopLevelHashValue = Callbacks.getHash();
14017330f729Sjoerg
14027330f729Sjoerg NumWarningsInPreamble = getDiagnostics().getNumWarnings();
14037330f729Sjoerg
14047330f729Sjoerg checkAndRemoveNonDriverDiags(NewPreambleDiags);
14057330f729Sjoerg StoredDiagnostics = std::move(NewPreambleDiags);
14067330f729Sjoerg PreambleDiagnostics = std::move(NewPreambleDiagsStandalone);
14077330f729Sjoerg
14087330f729Sjoerg // If the hash of top-level entities differs from the hash of the top-level
14097330f729Sjoerg // entities the last time we rebuilt the preamble, clear out the completion
14107330f729Sjoerg // cache.
14117330f729Sjoerg if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {
14127330f729Sjoerg CompletionCacheTopLevelHashValue = 0;
14137330f729Sjoerg PreambleTopLevelHashValue = CurrentTopLevelHashValue;
14147330f729Sjoerg }
14157330f729Sjoerg
14167330f729Sjoerg return MainFileBuffer;
14177330f729Sjoerg }
14187330f729Sjoerg
RealizeTopLevelDeclsFromPreamble()14197330f729Sjoerg void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
14207330f729Sjoerg assert(Preamble && "Should only be called when preamble was built");
14217330f729Sjoerg
14227330f729Sjoerg std::vector<Decl *> Resolved;
14237330f729Sjoerg Resolved.reserve(TopLevelDeclsInPreamble.size());
14247330f729Sjoerg ExternalASTSource &Source = *getASTContext().getExternalSource();
14257330f729Sjoerg for (const auto TopLevelDecl : TopLevelDeclsInPreamble) {
14267330f729Sjoerg // Resolve the declaration ID to an actual declaration, possibly
14277330f729Sjoerg // deserializing the declaration in the process.
14287330f729Sjoerg if (Decl *D = Source.GetExternalDecl(TopLevelDecl))
14297330f729Sjoerg Resolved.push_back(D);
14307330f729Sjoerg }
14317330f729Sjoerg TopLevelDeclsInPreamble.clear();
14327330f729Sjoerg TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
14337330f729Sjoerg }
14347330f729Sjoerg
transferASTDataFromCompilerInstance(CompilerInstance & CI)14357330f729Sjoerg void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
14367330f729Sjoerg // Steal the created target, context, and preprocessor if they have been
14377330f729Sjoerg // created.
14387330f729Sjoerg assert(CI.hasInvocation() && "missing invocation");
14397330f729Sjoerg LangOpts = CI.getInvocation().LangOpts;
14407330f729Sjoerg TheSema = CI.takeSema();
14417330f729Sjoerg Consumer = CI.takeASTConsumer();
14427330f729Sjoerg if (CI.hasASTContext())
14437330f729Sjoerg Ctx = &CI.getASTContext();
14447330f729Sjoerg if (CI.hasPreprocessor())
14457330f729Sjoerg PP = CI.getPreprocessorPtr();
14467330f729Sjoerg CI.setSourceManager(nullptr);
14477330f729Sjoerg CI.setFileManager(nullptr);
14487330f729Sjoerg if (CI.hasTarget())
14497330f729Sjoerg Target = &CI.getTarget();
1450*e038c9c4Sjoerg Reader = CI.getASTReader();
14517330f729Sjoerg HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
14527330f729Sjoerg }
14537330f729Sjoerg
getMainFileName() const14547330f729Sjoerg StringRef ASTUnit::getMainFileName() const {
14557330f729Sjoerg if (Invocation && !Invocation->getFrontendOpts().Inputs.empty()) {
14567330f729Sjoerg const FrontendInputFile &Input = Invocation->getFrontendOpts().Inputs[0];
14577330f729Sjoerg if (Input.isFile())
14587330f729Sjoerg return Input.getFile();
14597330f729Sjoerg else
1460*e038c9c4Sjoerg return Input.getBuffer().getBufferIdentifier();
14617330f729Sjoerg }
14627330f729Sjoerg
14637330f729Sjoerg if (SourceMgr) {
14647330f729Sjoerg if (const FileEntry *
14657330f729Sjoerg FE = SourceMgr->getFileEntryForID(SourceMgr->getMainFileID()))
14667330f729Sjoerg return FE->getName();
14677330f729Sjoerg }
14687330f729Sjoerg
14697330f729Sjoerg return {};
14707330f729Sjoerg }
14717330f729Sjoerg
getASTFileName() const14727330f729Sjoerg StringRef ASTUnit::getASTFileName() const {
14737330f729Sjoerg if (!isMainFileAST())
14747330f729Sjoerg return {};
14757330f729Sjoerg
14767330f729Sjoerg serialization::ModuleFile &
14777330f729Sjoerg Mod = Reader->getModuleManager().getPrimaryModule();
14787330f729Sjoerg return Mod.FileName;
14797330f729Sjoerg }
14807330f729Sjoerg
14817330f729Sjoerg std::unique_ptr<ASTUnit>
create(std::shared_ptr<CompilerInvocation> CI,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,CaptureDiagsKind CaptureDiagnostics,bool UserFilesAreVolatile)14827330f729Sjoerg ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
14837330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
14847330f729Sjoerg CaptureDiagsKind CaptureDiagnostics,
14857330f729Sjoerg bool UserFilesAreVolatile) {
14867330f729Sjoerg std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
14877330f729Sjoerg ConfigureDiags(Diags, *AST, CaptureDiagnostics);
14887330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
14897330f729Sjoerg createVFSFromCompilerInvocation(*CI, *Diags);
14907330f729Sjoerg AST->Diagnostics = Diags;
14917330f729Sjoerg AST->FileSystemOpts = CI->getFileSystemOpts();
14927330f729Sjoerg AST->Invocation = std::move(CI);
14937330f729Sjoerg AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
14947330f729Sjoerg AST->UserFilesAreVolatile = UserFilesAreVolatile;
14957330f729Sjoerg AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr,
14967330f729Sjoerg UserFilesAreVolatile);
14977330f729Sjoerg AST->ModuleCache = new InMemoryModuleCache;
14987330f729Sjoerg
14997330f729Sjoerg return AST;
15007330f729Sjoerg }
15017330f729Sjoerg
LoadFromCompilerInvocationAction(std::shared_ptr<CompilerInvocation> CI,std::shared_ptr<PCHContainerOperations> PCHContainerOps,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,FrontendAction * Action,ASTUnit * Unit,bool Persistent,StringRef ResourceFilesPath,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,unsigned PrecompilePreambleAfterNParses,bool CacheCodeCompletionResults,bool UserFilesAreVolatile,std::unique_ptr<ASTUnit> * ErrAST)15027330f729Sjoerg ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
15037330f729Sjoerg std::shared_ptr<CompilerInvocation> CI,
15047330f729Sjoerg std::shared_ptr<PCHContainerOperations> PCHContainerOps,
15057330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action,
15067330f729Sjoerg ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,
15077330f729Sjoerg bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
15087330f729Sjoerg unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults,
1509*e038c9c4Sjoerg bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {
15107330f729Sjoerg assert(CI && "A CompilerInvocation is required");
15117330f729Sjoerg
15127330f729Sjoerg std::unique_ptr<ASTUnit> OwnAST;
15137330f729Sjoerg ASTUnit *AST = Unit;
15147330f729Sjoerg if (!AST) {
15157330f729Sjoerg // Create the AST unit.
15167330f729Sjoerg OwnAST = create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile);
15177330f729Sjoerg AST = OwnAST.get();
15187330f729Sjoerg if (!AST)
15197330f729Sjoerg return nullptr;
15207330f729Sjoerg }
15217330f729Sjoerg
15227330f729Sjoerg if (!ResourceFilesPath.empty()) {
15237330f729Sjoerg // Override the resources path.
1524*e038c9c4Sjoerg CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);
15257330f729Sjoerg }
15267330f729Sjoerg AST->OnlyLocalDecls = OnlyLocalDecls;
15277330f729Sjoerg AST->CaptureDiagnostics = CaptureDiagnostics;
15287330f729Sjoerg if (PrecompilePreambleAfterNParses > 0)
15297330f729Sjoerg AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses;
15307330f729Sjoerg AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
15317330f729Sjoerg AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
1532*e038c9c4Sjoerg AST->IncludeBriefCommentsInCodeCompletion = false;
15337330f729Sjoerg
15347330f729Sjoerg // Recover resources if we crash before exiting this method.
15357330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
15367330f729Sjoerg ASTUnitCleanup(OwnAST.get());
15377330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
15387330f729Sjoerg llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
15397330f729Sjoerg DiagCleanup(Diags.get());
15407330f729Sjoerg
15417330f729Sjoerg // We'll manage file buffers ourselves.
15427330f729Sjoerg CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
15437330f729Sjoerg CI->getFrontendOpts().DisableFree = false;
15447330f729Sjoerg ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
15457330f729Sjoerg
15467330f729Sjoerg // Create the compiler instance to use for building the AST.
15477330f729Sjoerg std::unique_ptr<CompilerInstance> Clang(
15487330f729Sjoerg new CompilerInstance(std::move(PCHContainerOps)));
15497330f729Sjoerg
15507330f729Sjoerg // Recover resources if we crash before exiting this method.
15517330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
15527330f729Sjoerg CICleanup(Clang.get());
15537330f729Sjoerg
15547330f729Sjoerg Clang->setInvocation(std::move(CI));
1555*e038c9c4Sjoerg AST->OriginalSourceFile =
1556*e038c9c4Sjoerg std::string(Clang->getFrontendOpts().Inputs[0].getFile());
15577330f729Sjoerg
15587330f729Sjoerg // Set up diagnostics, capturing any diagnostics that would
15597330f729Sjoerg // otherwise be dropped.
15607330f729Sjoerg Clang->setDiagnostics(&AST->getDiagnostics());
15617330f729Sjoerg
15627330f729Sjoerg // Create the target instance.
1563*e038c9c4Sjoerg if (!Clang->createTarget())
15647330f729Sjoerg return nullptr;
15657330f729Sjoerg
15667330f729Sjoerg assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
15677330f729Sjoerg "Invocation must have exactly one source file!");
15687330f729Sjoerg assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
15697330f729Sjoerg InputKind::Source &&
15707330f729Sjoerg "FIXME: AST inputs not yet supported here!");
15717330f729Sjoerg assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
15727330f729Sjoerg Language::LLVM_IR &&
15737330f729Sjoerg "IR inputs not support here!");
15747330f729Sjoerg
15757330f729Sjoerg // Configure the various subsystems.
15767330f729Sjoerg AST->TheSema.reset();
15777330f729Sjoerg AST->Ctx = nullptr;
15787330f729Sjoerg AST->PP = nullptr;
15797330f729Sjoerg AST->Reader = nullptr;
15807330f729Sjoerg
15817330f729Sjoerg // Create a file manager object to provide access to and cache the filesystem.
15827330f729Sjoerg Clang->setFileManager(&AST->getFileManager());
15837330f729Sjoerg
15847330f729Sjoerg // Create the source manager.
15857330f729Sjoerg Clang->setSourceManager(&AST->getSourceManager());
15867330f729Sjoerg
15877330f729Sjoerg FrontendAction *Act = Action;
15887330f729Sjoerg
15897330f729Sjoerg std::unique_ptr<TopLevelDeclTrackerAction> TrackerAct;
15907330f729Sjoerg if (!Act) {
15917330f729Sjoerg TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));
15927330f729Sjoerg Act = TrackerAct.get();
15937330f729Sjoerg }
15947330f729Sjoerg
15957330f729Sjoerg // Recover resources if we crash before exiting this method.
15967330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
15977330f729Sjoerg ActCleanup(TrackerAct.get());
15987330f729Sjoerg
15997330f729Sjoerg if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
16007330f729Sjoerg AST->transferASTDataFromCompilerInstance(*Clang);
16017330f729Sjoerg if (OwnAST && ErrAST)
16027330f729Sjoerg ErrAST->swap(OwnAST);
16037330f729Sjoerg
16047330f729Sjoerg return nullptr;
16057330f729Sjoerg }
16067330f729Sjoerg
16077330f729Sjoerg if (Persistent && !TrackerAct) {
16087330f729Sjoerg Clang->getPreprocessor().addPPCallbacks(
16097330f729Sjoerg std::make_unique<MacroDefinitionTrackerPPCallbacks>(
16107330f729Sjoerg AST->getCurrentTopLevelHashValue()));
16117330f729Sjoerg std::vector<std::unique_ptr<ASTConsumer>> Consumers;
16127330f729Sjoerg if (Clang->hasASTConsumer())
16137330f729Sjoerg Consumers.push_back(Clang->takeASTConsumer());
16147330f729Sjoerg Consumers.push_back(std::make_unique<TopLevelDeclTrackerConsumer>(
16157330f729Sjoerg *AST, AST->getCurrentTopLevelHashValue()));
16167330f729Sjoerg Clang->setASTConsumer(
16177330f729Sjoerg std::make_unique<MultiplexConsumer>(std::move(Consumers)));
16187330f729Sjoerg }
16197330f729Sjoerg if (llvm::Error Err = Act->Execute()) {
16207330f729Sjoerg consumeError(std::move(Err)); // FIXME this drops errors on the floor.
16217330f729Sjoerg AST->transferASTDataFromCompilerInstance(*Clang);
16227330f729Sjoerg if (OwnAST && ErrAST)
16237330f729Sjoerg ErrAST->swap(OwnAST);
16247330f729Sjoerg
16257330f729Sjoerg return nullptr;
16267330f729Sjoerg }
16277330f729Sjoerg
16287330f729Sjoerg // Steal the created target, context, and preprocessor.
16297330f729Sjoerg AST->transferASTDataFromCompilerInstance(*Clang);
16307330f729Sjoerg
16317330f729Sjoerg Act->EndSourceFile();
16327330f729Sjoerg
16337330f729Sjoerg if (OwnAST)
16347330f729Sjoerg return OwnAST.release();
16357330f729Sjoerg else
16367330f729Sjoerg return AST;
16377330f729Sjoerg }
16387330f729Sjoerg
LoadFromCompilerInvocation(std::shared_ptr<PCHContainerOperations> PCHContainerOps,unsigned PrecompilePreambleAfterNParses,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)16397330f729Sjoerg bool ASTUnit::LoadFromCompilerInvocation(
16407330f729Sjoerg std::shared_ptr<PCHContainerOperations> PCHContainerOps,
16417330f729Sjoerg unsigned PrecompilePreambleAfterNParses,
16427330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
16437330f729Sjoerg if (!Invocation)
16447330f729Sjoerg return true;
16457330f729Sjoerg
16467330f729Sjoerg assert(VFS && "VFS is null");
16477330f729Sjoerg
16487330f729Sjoerg // We'll manage file buffers ourselves.
16497330f729Sjoerg Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
16507330f729Sjoerg Invocation->getFrontendOpts().DisableFree = false;
16517330f729Sjoerg getDiagnostics().Reset();
16527330f729Sjoerg ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
16537330f729Sjoerg
16547330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
16557330f729Sjoerg if (PrecompilePreambleAfterNParses > 0) {
16567330f729Sjoerg PreambleRebuildCountdown = PrecompilePreambleAfterNParses;
16577330f729Sjoerg OverrideMainBuffer =
16587330f729Sjoerg getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
16597330f729Sjoerg getDiagnostics().Reset();
16607330f729Sjoerg ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
16617330f729Sjoerg }
16627330f729Sjoerg
16637330f729Sjoerg SimpleTimer ParsingTimer(WantTiming);
16647330f729Sjoerg ParsingTimer.setOutput("Parsing " + getMainFileName());
16657330f729Sjoerg
16667330f729Sjoerg // Recover resources if we crash before exiting this method.
16677330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
16687330f729Sjoerg MemBufferCleanup(OverrideMainBuffer.get());
16697330f729Sjoerg
16707330f729Sjoerg return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
16717330f729Sjoerg }
16727330f729Sjoerg
LoadFromCompilerInvocation(std::shared_ptr<CompilerInvocation> CI,std::shared_ptr<PCHContainerOperations> PCHContainerOps,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,FileManager * FileMgr,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,unsigned PrecompilePreambleAfterNParses,TranslationUnitKind TUKind,bool CacheCodeCompletionResults,bool IncludeBriefCommentsInCodeCompletion,bool UserFilesAreVolatile)16737330f729Sjoerg std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
16747330f729Sjoerg std::shared_ptr<CompilerInvocation> CI,
16757330f729Sjoerg std::shared_ptr<PCHContainerOperations> PCHContainerOps,
16767330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,
16777330f729Sjoerg bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
16787330f729Sjoerg unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
16797330f729Sjoerg bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
16807330f729Sjoerg bool UserFilesAreVolatile) {
16817330f729Sjoerg // Create the AST unit.
16827330f729Sjoerg std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
16837330f729Sjoerg ConfigureDiags(Diags, *AST, CaptureDiagnostics);
16847330f729Sjoerg AST->Diagnostics = Diags;
16857330f729Sjoerg AST->OnlyLocalDecls = OnlyLocalDecls;
16867330f729Sjoerg AST->CaptureDiagnostics = CaptureDiagnostics;
16877330f729Sjoerg AST->TUKind = TUKind;
16887330f729Sjoerg AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
16897330f729Sjoerg AST->IncludeBriefCommentsInCodeCompletion
16907330f729Sjoerg = IncludeBriefCommentsInCodeCompletion;
16917330f729Sjoerg AST->Invocation = std::move(CI);
16927330f729Sjoerg AST->FileSystemOpts = FileMgr->getFileSystemOpts();
16937330f729Sjoerg AST->FileMgr = FileMgr;
16947330f729Sjoerg AST->UserFilesAreVolatile = UserFilesAreVolatile;
16957330f729Sjoerg
16967330f729Sjoerg // Recover resources if we crash before exiting this method.
16977330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
16987330f729Sjoerg ASTUnitCleanup(AST.get());
16997330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
17007330f729Sjoerg llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>>
17017330f729Sjoerg DiagCleanup(Diags.get());
17027330f729Sjoerg
17037330f729Sjoerg if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
17047330f729Sjoerg PrecompilePreambleAfterNParses,
17057330f729Sjoerg &AST->FileMgr->getVirtualFileSystem()))
17067330f729Sjoerg return nullptr;
17077330f729Sjoerg return AST;
17087330f729Sjoerg }
17097330f729Sjoerg
LoadFromCommandLine(const char ** ArgBegin,const char ** ArgEnd,std::shared_ptr<PCHContainerOperations> PCHContainerOps,IntrusiveRefCntPtr<DiagnosticsEngine> Diags,StringRef ResourceFilesPath,bool OnlyLocalDecls,CaptureDiagsKind CaptureDiagnostics,ArrayRef<RemappedFile> RemappedFiles,bool RemappedFilesKeepOriginalName,unsigned PrecompilePreambleAfterNParses,TranslationUnitKind TUKind,bool CacheCodeCompletionResults,bool IncludeBriefCommentsInCodeCompletion,bool AllowPCHWithCompilerErrors,SkipFunctionBodiesScope SkipFunctionBodies,bool SingleFileParse,bool UserFilesAreVolatile,bool ForSerialization,bool RetainExcludedConditionalBlocks,llvm::Optional<StringRef> ModuleFormat,std::unique_ptr<ASTUnit> * ErrAST,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)17107330f729Sjoerg ASTUnit *ASTUnit::LoadFromCommandLine(
17117330f729Sjoerg const char **ArgBegin, const char **ArgEnd,
17127330f729Sjoerg std::shared_ptr<PCHContainerOperations> PCHContainerOps,
17137330f729Sjoerg IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
17147330f729Sjoerg bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
17157330f729Sjoerg ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
17167330f729Sjoerg unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
17177330f729Sjoerg bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
17187330f729Sjoerg bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,
17197330f729Sjoerg bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
17207330f729Sjoerg bool RetainExcludedConditionalBlocks,
17217330f729Sjoerg llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST,
17227330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
17237330f729Sjoerg assert(Diags.get() && "no DiagnosticsEngine was provided");
17247330f729Sjoerg
17257330f729Sjoerg SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
17267330f729Sjoerg
17277330f729Sjoerg std::shared_ptr<CompilerInvocation> CI;
17287330f729Sjoerg
17297330f729Sjoerg {
17307330f729Sjoerg CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
17317330f729Sjoerg &StoredDiagnostics, nullptr);
17327330f729Sjoerg
17337330f729Sjoerg CI = createInvocationFromCommandLine(
17347330f729Sjoerg llvm::makeArrayRef(ArgBegin, ArgEnd), Diags, VFS);
17357330f729Sjoerg if (!CI)
17367330f729Sjoerg return nullptr;
17377330f729Sjoerg }
17387330f729Sjoerg
17397330f729Sjoerg // Override any files that need remapping
17407330f729Sjoerg for (const auto &RemappedFile : RemappedFiles) {
17417330f729Sjoerg CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
17427330f729Sjoerg RemappedFile.second);
17437330f729Sjoerg }
17447330f729Sjoerg PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
17457330f729Sjoerg PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
17467330f729Sjoerg PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
17477330f729Sjoerg PPOpts.SingleFileParseMode = SingleFileParse;
17487330f729Sjoerg PPOpts.RetainExcludedConditionalBlocks = RetainExcludedConditionalBlocks;
17497330f729Sjoerg
17507330f729Sjoerg // Override the resources path.
1751*e038c9c4Sjoerg CI->getHeaderSearchOpts().ResourceDir = std::string(ResourceFilesPath);
17527330f729Sjoerg
17537330f729Sjoerg CI->getFrontendOpts().SkipFunctionBodies =
17547330f729Sjoerg SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile;
17557330f729Sjoerg
17567330f729Sjoerg if (ModuleFormat)
1757*e038c9c4Sjoerg CI->getHeaderSearchOpts().ModuleFormat =
1758*e038c9c4Sjoerg std::string(ModuleFormat.getValue());
17597330f729Sjoerg
17607330f729Sjoerg // Create the AST unit.
17617330f729Sjoerg std::unique_ptr<ASTUnit> AST;
17627330f729Sjoerg AST.reset(new ASTUnit(false));
17637330f729Sjoerg AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
17647330f729Sjoerg AST->StoredDiagnostics.swap(StoredDiagnostics);
17657330f729Sjoerg ConfigureDiags(Diags, *AST, CaptureDiagnostics);
17667330f729Sjoerg AST->Diagnostics = Diags;
17677330f729Sjoerg AST->FileSystemOpts = CI->getFileSystemOpts();
17687330f729Sjoerg if (!VFS)
17697330f729Sjoerg VFS = llvm::vfs::getRealFileSystem();
17707330f729Sjoerg VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS);
17717330f729Sjoerg AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS);
17727330f729Sjoerg AST->ModuleCache = new InMemoryModuleCache;
17737330f729Sjoerg AST->OnlyLocalDecls = OnlyLocalDecls;
17747330f729Sjoerg AST->CaptureDiagnostics = CaptureDiagnostics;
17757330f729Sjoerg AST->TUKind = TUKind;
17767330f729Sjoerg AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
17777330f729Sjoerg AST->IncludeBriefCommentsInCodeCompletion
17787330f729Sjoerg = IncludeBriefCommentsInCodeCompletion;
17797330f729Sjoerg AST->UserFilesAreVolatile = UserFilesAreVolatile;
17807330f729Sjoerg AST->Invocation = CI;
17817330f729Sjoerg AST->SkipFunctionBodies = SkipFunctionBodies;
17827330f729Sjoerg if (ForSerialization)
17837330f729Sjoerg AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache));
17847330f729Sjoerg // Zero out now to ease cleanup during crash recovery.
17857330f729Sjoerg CI = nullptr;
17867330f729Sjoerg Diags = nullptr;
17877330f729Sjoerg
17887330f729Sjoerg // Recover resources if we crash before exiting this method.
17897330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
17907330f729Sjoerg ASTUnitCleanup(AST.get());
17917330f729Sjoerg
17927330f729Sjoerg if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps),
17937330f729Sjoerg PrecompilePreambleAfterNParses,
17947330f729Sjoerg VFS)) {
17957330f729Sjoerg // Some error occurred, if caller wants to examine diagnostics, pass it the
17967330f729Sjoerg // ASTUnit.
17977330f729Sjoerg if (ErrAST) {
17987330f729Sjoerg AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics);
17997330f729Sjoerg ErrAST->swap(AST);
18007330f729Sjoerg }
18017330f729Sjoerg return nullptr;
18027330f729Sjoerg }
18037330f729Sjoerg
18047330f729Sjoerg return AST.release();
18057330f729Sjoerg }
18067330f729Sjoerg
Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,ArrayRef<RemappedFile> RemappedFiles,IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)18077330f729Sjoerg bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
18087330f729Sjoerg ArrayRef<RemappedFile> RemappedFiles,
18097330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
18107330f729Sjoerg if (!Invocation)
18117330f729Sjoerg return true;
18127330f729Sjoerg
18137330f729Sjoerg if (!VFS) {
18147330f729Sjoerg assert(FileMgr && "FileMgr is null on Reparse call");
18157330f729Sjoerg VFS = &FileMgr->getVirtualFileSystem();
18167330f729Sjoerg }
18177330f729Sjoerg
18187330f729Sjoerg clearFileLevelDecls();
18197330f729Sjoerg
18207330f729Sjoerg SimpleTimer ParsingTimer(WantTiming);
18217330f729Sjoerg ParsingTimer.setOutput("Reparsing " + getMainFileName());
18227330f729Sjoerg
18237330f729Sjoerg // Remap files.
18247330f729Sjoerg PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
18257330f729Sjoerg for (const auto &RB : PPOpts.RemappedFileBuffers)
18267330f729Sjoerg delete RB.second;
18277330f729Sjoerg
18287330f729Sjoerg Invocation->getPreprocessorOpts().clearRemappedFiles();
18297330f729Sjoerg for (const auto &RemappedFile : RemappedFiles) {
18307330f729Sjoerg Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first,
18317330f729Sjoerg RemappedFile.second);
18327330f729Sjoerg }
18337330f729Sjoerg
18347330f729Sjoerg // If we have a preamble file lying around, or if we might try to
18357330f729Sjoerg // build a precompiled preamble, do so now.
18367330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
18377330f729Sjoerg if (Preamble || PreambleRebuildCountdown > 0)
18387330f729Sjoerg OverrideMainBuffer =
18397330f729Sjoerg getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS);
18407330f729Sjoerg
18417330f729Sjoerg // Clear out the diagnostics state.
18427330f729Sjoerg FileMgr.reset();
18437330f729Sjoerg getDiagnostics().Reset();
18447330f729Sjoerg ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
18457330f729Sjoerg if (OverrideMainBuffer)
18467330f729Sjoerg getDiagnostics().setNumWarnings(NumWarningsInPreamble);
18477330f729Sjoerg
18487330f729Sjoerg // Parse the sources
18497330f729Sjoerg bool Result =
18507330f729Sjoerg Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS);
18517330f729Sjoerg
18527330f729Sjoerg // If we're caching global code-completion results, and the top-level
18537330f729Sjoerg // declarations have changed, clear out the code-completion cache.
18547330f729Sjoerg if (!Result && ShouldCacheCodeCompletionResults &&
18557330f729Sjoerg CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
18567330f729Sjoerg CacheCodeCompletionResults();
18577330f729Sjoerg
18587330f729Sjoerg // We now need to clear out the completion info related to this translation
18597330f729Sjoerg // unit; it'll be recreated if necessary.
18607330f729Sjoerg CCTUInfo.reset();
18617330f729Sjoerg
18627330f729Sjoerg return Result;
18637330f729Sjoerg }
18647330f729Sjoerg
ResetForParse()18657330f729Sjoerg void ASTUnit::ResetForParse() {
18667330f729Sjoerg SavedMainFileBuffer.reset();
18677330f729Sjoerg
18687330f729Sjoerg SourceMgr.reset();
18697330f729Sjoerg TheSema.reset();
18707330f729Sjoerg Ctx.reset();
18717330f729Sjoerg PP.reset();
18727330f729Sjoerg Reader.reset();
18737330f729Sjoerg
18747330f729Sjoerg TopLevelDecls.clear();
18757330f729Sjoerg clearFileLevelDecls();
18767330f729Sjoerg }
18777330f729Sjoerg
18787330f729Sjoerg //----------------------------------------------------------------------------//
18797330f729Sjoerg // Code completion
18807330f729Sjoerg //----------------------------------------------------------------------------//
18817330f729Sjoerg
18827330f729Sjoerg namespace {
18837330f729Sjoerg
18847330f729Sjoerg /// Code completion consumer that combines the cached code-completion
18857330f729Sjoerg /// results from an ASTUnit with the code-completion results provided to it,
18867330f729Sjoerg /// then passes the result on to
18877330f729Sjoerg class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
18887330f729Sjoerg uint64_t NormalContexts;
18897330f729Sjoerg ASTUnit &AST;
18907330f729Sjoerg CodeCompleteConsumer &Next;
18917330f729Sjoerg
18927330f729Sjoerg public:
AugmentedCodeCompleteConsumer(ASTUnit & AST,CodeCompleteConsumer & Next,const CodeCompleteOptions & CodeCompleteOpts)18937330f729Sjoerg AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
18947330f729Sjoerg const CodeCompleteOptions &CodeCompleteOpts)
18957330f729Sjoerg : CodeCompleteConsumer(CodeCompleteOpts), AST(AST), Next(Next) {
18967330f729Sjoerg // Compute the set of contexts in which we will look when we don't have
18977330f729Sjoerg // any information about the specific context.
18987330f729Sjoerg NormalContexts
18997330f729Sjoerg = (1LL << CodeCompletionContext::CCC_TopLevel)
19007330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCInterface)
19017330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCImplementation)
19027330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCIvarList)
19037330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Statement)
19047330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Expression)
19057330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver)
19067330f729Sjoerg | (1LL << CodeCompletionContext::CCC_DotMemberAccess)
19077330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ArrowMemberAccess)
19087330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess)
19097330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ObjCProtocolName)
19107330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression)
19117330f729Sjoerg | (1LL << CodeCompletionContext::CCC_Recovery);
19127330f729Sjoerg
19137330f729Sjoerg if (AST.getASTContext().getLangOpts().CPlusPlus)
19147330f729Sjoerg NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag)
19157330f729Sjoerg | (1LL << CodeCompletionContext::CCC_UnionTag)
19167330f729Sjoerg | (1LL << CodeCompletionContext::CCC_ClassOrStructTag);
19177330f729Sjoerg }
19187330f729Sjoerg
19197330f729Sjoerg void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
19207330f729Sjoerg CodeCompletionResult *Results,
19217330f729Sjoerg unsigned NumResults) override;
19227330f729Sjoerg
ProcessOverloadCandidates(Sema & S,unsigned CurrentArg,OverloadCandidate * Candidates,unsigned NumCandidates,SourceLocation OpenParLoc)19237330f729Sjoerg void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
19247330f729Sjoerg OverloadCandidate *Candidates,
19257330f729Sjoerg unsigned NumCandidates,
19267330f729Sjoerg SourceLocation OpenParLoc) override {
19277330f729Sjoerg Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates,
19287330f729Sjoerg OpenParLoc);
19297330f729Sjoerg }
19307330f729Sjoerg
getAllocator()19317330f729Sjoerg CodeCompletionAllocator &getAllocator() override {
19327330f729Sjoerg return Next.getAllocator();
19337330f729Sjoerg }
19347330f729Sjoerg
getCodeCompletionTUInfo()19357330f729Sjoerg CodeCompletionTUInfo &getCodeCompletionTUInfo() override {
19367330f729Sjoerg return Next.getCodeCompletionTUInfo();
19377330f729Sjoerg }
19387330f729Sjoerg };
19397330f729Sjoerg
19407330f729Sjoerg } // namespace
19417330f729Sjoerg
19427330f729Sjoerg /// Helper function that computes which global names are hidden by the
19437330f729Sjoerg /// local code-completion results.
CalculateHiddenNames(const CodeCompletionContext & Context,CodeCompletionResult * Results,unsigned NumResults,ASTContext & Ctx,llvm::StringSet<llvm::BumpPtrAllocator> & HiddenNames)19447330f729Sjoerg static void CalculateHiddenNames(const CodeCompletionContext &Context,
19457330f729Sjoerg CodeCompletionResult *Results,
19467330f729Sjoerg unsigned NumResults,
19477330f729Sjoerg ASTContext &Ctx,
19487330f729Sjoerg llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){
19497330f729Sjoerg bool OnlyTagNames = false;
19507330f729Sjoerg switch (Context.getKind()) {
19517330f729Sjoerg case CodeCompletionContext::CCC_Recovery:
19527330f729Sjoerg case CodeCompletionContext::CCC_TopLevel:
19537330f729Sjoerg case CodeCompletionContext::CCC_ObjCInterface:
19547330f729Sjoerg case CodeCompletionContext::CCC_ObjCImplementation:
19557330f729Sjoerg case CodeCompletionContext::CCC_ObjCIvarList:
19567330f729Sjoerg case CodeCompletionContext::CCC_ClassStructUnion:
19577330f729Sjoerg case CodeCompletionContext::CCC_Statement:
19587330f729Sjoerg case CodeCompletionContext::CCC_Expression:
19597330f729Sjoerg case CodeCompletionContext::CCC_ObjCMessageReceiver:
19607330f729Sjoerg case CodeCompletionContext::CCC_DotMemberAccess:
19617330f729Sjoerg case CodeCompletionContext::CCC_ArrowMemberAccess:
19627330f729Sjoerg case CodeCompletionContext::CCC_ObjCPropertyAccess:
19637330f729Sjoerg case CodeCompletionContext::CCC_Namespace:
19647330f729Sjoerg case CodeCompletionContext::CCC_Type:
19657330f729Sjoerg case CodeCompletionContext::CCC_Symbol:
19667330f729Sjoerg case CodeCompletionContext::CCC_SymbolOrNewName:
19677330f729Sjoerg case CodeCompletionContext::CCC_ParenthesizedExpression:
19687330f729Sjoerg case CodeCompletionContext::CCC_ObjCInterfaceName:
19697330f729Sjoerg break;
19707330f729Sjoerg
19717330f729Sjoerg case CodeCompletionContext::CCC_EnumTag:
19727330f729Sjoerg case CodeCompletionContext::CCC_UnionTag:
19737330f729Sjoerg case CodeCompletionContext::CCC_ClassOrStructTag:
19747330f729Sjoerg OnlyTagNames = true;
19757330f729Sjoerg break;
19767330f729Sjoerg
19777330f729Sjoerg case CodeCompletionContext::CCC_ObjCProtocolName:
19787330f729Sjoerg case CodeCompletionContext::CCC_MacroName:
19797330f729Sjoerg case CodeCompletionContext::CCC_MacroNameUse:
19807330f729Sjoerg case CodeCompletionContext::CCC_PreprocessorExpression:
19817330f729Sjoerg case CodeCompletionContext::CCC_PreprocessorDirective:
19827330f729Sjoerg case CodeCompletionContext::CCC_NaturalLanguage:
19837330f729Sjoerg case CodeCompletionContext::CCC_SelectorName:
19847330f729Sjoerg case CodeCompletionContext::CCC_TypeQualifiers:
19857330f729Sjoerg case CodeCompletionContext::CCC_Other:
19867330f729Sjoerg case CodeCompletionContext::CCC_OtherWithMacros:
19877330f729Sjoerg case CodeCompletionContext::CCC_ObjCInstanceMessage:
19887330f729Sjoerg case CodeCompletionContext::CCC_ObjCClassMessage:
19897330f729Sjoerg case CodeCompletionContext::CCC_ObjCCategoryName:
19907330f729Sjoerg case CodeCompletionContext::CCC_IncludedFile:
19917330f729Sjoerg case CodeCompletionContext::CCC_NewName:
19927330f729Sjoerg // We're looking for nothing, or we're looking for names that cannot
19937330f729Sjoerg // be hidden.
19947330f729Sjoerg return;
19957330f729Sjoerg }
19967330f729Sjoerg
19977330f729Sjoerg using Result = CodeCompletionResult;
19987330f729Sjoerg for (unsigned I = 0; I != NumResults; ++I) {
19997330f729Sjoerg if (Results[I].Kind != Result::RK_Declaration)
20007330f729Sjoerg continue;
20017330f729Sjoerg
20027330f729Sjoerg unsigned IDNS
20037330f729Sjoerg = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
20047330f729Sjoerg
20057330f729Sjoerg bool Hiding = false;
20067330f729Sjoerg if (OnlyTagNames)
20077330f729Sjoerg Hiding = (IDNS & Decl::IDNS_Tag);
20087330f729Sjoerg else {
20097330f729Sjoerg unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
20107330f729Sjoerg Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
20117330f729Sjoerg Decl::IDNS_NonMemberOperator);
20127330f729Sjoerg if (Ctx.getLangOpts().CPlusPlus)
20137330f729Sjoerg HiddenIDNS |= Decl::IDNS_Tag;
20147330f729Sjoerg Hiding = (IDNS & HiddenIDNS);
20157330f729Sjoerg }
20167330f729Sjoerg
20177330f729Sjoerg if (!Hiding)
20187330f729Sjoerg continue;
20197330f729Sjoerg
20207330f729Sjoerg DeclarationName Name = Results[I].Declaration->getDeclName();
20217330f729Sjoerg if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
20227330f729Sjoerg HiddenNames.insert(Identifier->getName());
20237330f729Sjoerg else
20247330f729Sjoerg HiddenNames.insert(Name.getAsString());
20257330f729Sjoerg }
20267330f729Sjoerg }
20277330f729Sjoerg
ProcessCodeCompleteResults(Sema & S,CodeCompletionContext Context,CodeCompletionResult * Results,unsigned NumResults)20287330f729Sjoerg void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
20297330f729Sjoerg CodeCompletionContext Context,
20307330f729Sjoerg CodeCompletionResult *Results,
20317330f729Sjoerg unsigned NumResults) {
20327330f729Sjoerg // Merge the results we were given with the results we cached.
20337330f729Sjoerg bool AddedResult = false;
20347330f729Sjoerg uint64_t InContexts =
20357330f729Sjoerg Context.getKind() == CodeCompletionContext::CCC_Recovery
20367330f729Sjoerg ? NormalContexts : (1LL << Context.getKind());
20377330f729Sjoerg // Contains the set of names that are hidden by "local" completion results.
20387330f729Sjoerg llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
20397330f729Sjoerg using Result = CodeCompletionResult;
20407330f729Sjoerg SmallVector<Result, 8> AllResults;
20417330f729Sjoerg for (ASTUnit::cached_completion_iterator
20427330f729Sjoerg C = AST.cached_completion_begin(),
20437330f729Sjoerg CEnd = AST.cached_completion_end();
20447330f729Sjoerg C != CEnd; ++C) {
20457330f729Sjoerg // If the context we are in matches any of the contexts we are
20467330f729Sjoerg // interested in, we'll add this result.
20477330f729Sjoerg if ((C->ShowInContexts & InContexts) == 0)
20487330f729Sjoerg continue;
20497330f729Sjoerg
20507330f729Sjoerg // If we haven't added any results previously, do so now.
20517330f729Sjoerg if (!AddedResult) {
20527330f729Sjoerg CalculateHiddenNames(Context, Results, NumResults, S.Context,
20537330f729Sjoerg HiddenNames);
20547330f729Sjoerg AllResults.insert(AllResults.end(), Results, Results + NumResults);
20557330f729Sjoerg AddedResult = true;
20567330f729Sjoerg }
20577330f729Sjoerg
20587330f729Sjoerg // Determine whether this global completion result is hidden by a local
20597330f729Sjoerg // completion result. If so, skip it.
20607330f729Sjoerg if (C->Kind != CXCursor_MacroDefinition &&
20617330f729Sjoerg HiddenNames.count(C->Completion->getTypedText()))
20627330f729Sjoerg continue;
20637330f729Sjoerg
20647330f729Sjoerg // Adjust priority based on similar type classes.
20657330f729Sjoerg unsigned Priority = C->Priority;
20667330f729Sjoerg CodeCompletionString *Completion = C->Completion;
20677330f729Sjoerg if (!Context.getPreferredType().isNull()) {
20687330f729Sjoerg if (C->Kind == CXCursor_MacroDefinition) {
20697330f729Sjoerg Priority = getMacroUsagePriority(C->Completion->getTypedText(),
20707330f729Sjoerg S.getLangOpts(),
20717330f729Sjoerg Context.getPreferredType()->isAnyPointerType());
20727330f729Sjoerg } else if (C->Type) {
20737330f729Sjoerg CanQualType Expected
20747330f729Sjoerg = S.Context.getCanonicalType(
20757330f729Sjoerg Context.getPreferredType().getUnqualifiedType());
20767330f729Sjoerg SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
20777330f729Sjoerg if (ExpectedSTC == C->TypeClass) {
20787330f729Sjoerg // We know this type is similar; check for an exact match.
20797330f729Sjoerg llvm::StringMap<unsigned> &CachedCompletionTypes
20807330f729Sjoerg = AST.getCachedCompletionTypes();
20817330f729Sjoerg llvm::StringMap<unsigned>::iterator Pos
20827330f729Sjoerg = CachedCompletionTypes.find(QualType(Expected).getAsString());
20837330f729Sjoerg if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
20847330f729Sjoerg Priority /= CCF_ExactTypeMatch;
20857330f729Sjoerg else
20867330f729Sjoerg Priority /= CCF_SimilarTypeMatch;
20877330f729Sjoerg }
20887330f729Sjoerg }
20897330f729Sjoerg }
20907330f729Sjoerg
20917330f729Sjoerg // Adjust the completion string, if required.
20927330f729Sjoerg if (C->Kind == CXCursor_MacroDefinition &&
20937330f729Sjoerg Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
20947330f729Sjoerg // Create a new code-completion string that just contains the
20957330f729Sjoerg // macro name, without its arguments.
20967330f729Sjoerg CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(),
20977330f729Sjoerg CCP_CodePattern, C->Availability);
20987330f729Sjoerg Builder.AddTypedTextChunk(C->Completion->getTypedText());
20997330f729Sjoerg Priority = CCP_CodePattern;
21007330f729Sjoerg Completion = Builder.TakeString();
21017330f729Sjoerg }
21027330f729Sjoerg
21037330f729Sjoerg AllResults.push_back(Result(Completion, Priority, C->Kind,
21047330f729Sjoerg C->Availability));
21057330f729Sjoerg }
21067330f729Sjoerg
21077330f729Sjoerg // If we did not add any cached completion results, just forward the
21087330f729Sjoerg // results we were given to the next consumer.
21097330f729Sjoerg if (!AddedResult) {
21107330f729Sjoerg Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
21117330f729Sjoerg return;
21127330f729Sjoerg }
21137330f729Sjoerg
21147330f729Sjoerg Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
21157330f729Sjoerg AllResults.size());
21167330f729Sjoerg }
21177330f729Sjoerg
CodeComplete(StringRef File,unsigned Line,unsigned Column,ArrayRef<RemappedFile> RemappedFiles,bool IncludeMacros,bool IncludeCodePatterns,bool IncludeBriefComments,CodeCompleteConsumer & Consumer,std::shared_ptr<PCHContainerOperations> PCHContainerOps,DiagnosticsEngine & Diag,LangOptions & LangOpts,SourceManager & SourceMgr,FileManager & FileMgr,SmallVectorImpl<StoredDiagnostic> & StoredDiagnostics,SmallVectorImpl<const llvm::MemoryBuffer * > & OwnedBuffers)21187330f729Sjoerg void ASTUnit::CodeComplete(
21197330f729Sjoerg StringRef File, unsigned Line, unsigned Column,
21207330f729Sjoerg ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,
21217330f729Sjoerg bool IncludeCodePatterns, bool IncludeBriefComments,
21227330f729Sjoerg CodeCompleteConsumer &Consumer,
21237330f729Sjoerg std::shared_ptr<PCHContainerOperations> PCHContainerOps,
21247330f729Sjoerg DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,
21257330f729Sjoerg FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
21267330f729Sjoerg SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
21277330f729Sjoerg if (!Invocation)
21287330f729Sjoerg return;
21297330f729Sjoerg
21307330f729Sjoerg SimpleTimer CompletionTimer(WantTiming);
21317330f729Sjoerg CompletionTimer.setOutput("Code completion @ " + File + ":" +
21327330f729Sjoerg Twine(Line) + ":" + Twine(Column));
21337330f729Sjoerg
21347330f729Sjoerg auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation);
21357330f729Sjoerg
21367330f729Sjoerg FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();
21377330f729Sjoerg CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts;
21387330f729Sjoerg PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();
21397330f729Sjoerg
21407330f729Sjoerg CodeCompleteOpts.IncludeMacros = IncludeMacros &&
21417330f729Sjoerg CachedCompletionResults.empty();
21427330f729Sjoerg CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns;
21437330f729Sjoerg CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty();
21447330f729Sjoerg CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments;
21457330f729Sjoerg CodeCompleteOpts.LoadExternal = Consumer.loadExternal();
21467330f729Sjoerg CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts();
21477330f729Sjoerg
21487330f729Sjoerg assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion);
21497330f729Sjoerg
2150*e038c9c4Sjoerg FrontendOpts.CodeCompletionAt.FileName = std::string(File);
21517330f729Sjoerg FrontendOpts.CodeCompletionAt.Line = Line;
21527330f729Sjoerg FrontendOpts.CodeCompletionAt.Column = Column;
21537330f729Sjoerg
21547330f729Sjoerg // Set the language options appropriately.
21557330f729Sjoerg LangOpts = *CCInvocation->getLangOpts();
21567330f729Sjoerg
21577330f729Sjoerg // Spell-checking and warnings are wasteful during code-completion.
21587330f729Sjoerg LangOpts.SpellChecking = false;
21597330f729Sjoerg CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;
21607330f729Sjoerg
21617330f729Sjoerg std::unique_ptr<CompilerInstance> Clang(
21627330f729Sjoerg new CompilerInstance(PCHContainerOps));
21637330f729Sjoerg
21647330f729Sjoerg // Recover resources if we crash before exiting this method.
21657330f729Sjoerg llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
21667330f729Sjoerg CICleanup(Clang.get());
21677330f729Sjoerg
21687330f729Sjoerg auto &Inv = *CCInvocation;
21697330f729Sjoerg Clang->setInvocation(std::move(CCInvocation));
2170*e038c9c4Sjoerg OriginalSourceFile =
2171*e038c9c4Sjoerg std::string(Clang->getFrontendOpts().Inputs[0].getFile());
21727330f729Sjoerg
21737330f729Sjoerg // Set up diagnostics, capturing any diagnostics produced.
21747330f729Sjoerg Clang->setDiagnostics(&Diag);
21757330f729Sjoerg CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All,
21767330f729Sjoerg Clang->getDiagnostics(),
21777330f729Sjoerg &StoredDiagnostics, nullptr);
21787330f729Sjoerg ProcessWarningOptions(Diag, Inv.getDiagnosticOpts());
21797330f729Sjoerg
21807330f729Sjoerg // Create the target instance.
2181*e038c9c4Sjoerg if (!Clang->createTarget()) {
21827330f729Sjoerg Clang->setInvocation(nullptr);
21837330f729Sjoerg return;
21847330f729Sjoerg }
21857330f729Sjoerg
21867330f729Sjoerg assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
21877330f729Sjoerg "Invocation must have exactly one source file!");
21887330f729Sjoerg assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
21897330f729Sjoerg InputKind::Source &&
21907330f729Sjoerg "FIXME: AST inputs not yet supported here!");
21917330f729Sjoerg assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
21927330f729Sjoerg Language::LLVM_IR &&
21937330f729Sjoerg "IR inputs not support here!");
21947330f729Sjoerg
21957330f729Sjoerg // Use the source and file managers that we were given.
21967330f729Sjoerg Clang->setFileManager(&FileMgr);
21977330f729Sjoerg Clang->setSourceManager(&SourceMgr);
21987330f729Sjoerg
21997330f729Sjoerg // Remap files.
22007330f729Sjoerg PreprocessorOpts.clearRemappedFiles();
22017330f729Sjoerg PreprocessorOpts.RetainRemappedFileBuffers = true;
22027330f729Sjoerg for (const auto &RemappedFile : RemappedFiles) {
22037330f729Sjoerg PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second);
22047330f729Sjoerg OwnedBuffers.push_back(RemappedFile.second);
22057330f729Sjoerg }
22067330f729Sjoerg
22077330f729Sjoerg // Use the code completion consumer we were given, but adding any cached
22087330f729Sjoerg // code-completion results.
22097330f729Sjoerg AugmentedCodeCompleteConsumer *AugmentedConsumer
22107330f729Sjoerg = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts);
22117330f729Sjoerg Clang->setCodeCompletionConsumer(AugmentedConsumer);
22127330f729Sjoerg
2213*e038c9c4Sjoerg auto getUniqueID =
2214*e038c9c4Sjoerg [&FileMgr](StringRef Filename) -> Optional<llvm::sys::fs::UniqueID> {
2215*e038c9c4Sjoerg if (auto Status = FileMgr.getVirtualFileSystem().status(Filename))
2216*e038c9c4Sjoerg return Status->getUniqueID();
2217*e038c9c4Sjoerg return None;
2218*e038c9c4Sjoerg };
2219*e038c9c4Sjoerg
2220*e038c9c4Sjoerg auto hasSameUniqueID = [getUniqueID](StringRef LHS, StringRef RHS) {
2221*e038c9c4Sjoerg if (LHS == RHS)
2222*e038c9c4Sjoerg return true;
2223*e038c9c4Sjoerg if (auto LHSID = getUniqueID(LHS))
2224*e038c9c4Sjoerg if (auto RHSID = getUniqueID(RHS))
2225*e038c9c4Sjoerg return *LHSID == *RHSID;
2226*e038c9c4Sjoerg return false;
2227*e038c9c4Sjoerg };
2228*e038c9c4Sjoerg
22297330f729Sjoerg // If we have a precompiled preamble, try to use it. We only allow
22307330f729Sjoerg // the use of the precompiled preamble if we're if the completion
22317330f729Sjoerg // point is within the main file, after the end of the precompiled
22327330f729Sjoerg // preamble.
22337330f729Sjoerg std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
2234*e038c9c4Sjoerg if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) {
22357330f729Sjoerg OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(
2236*e038c9c4Sjoerg PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1);
22377330f729Sjoerg }
22387330f729Sjoerg
22397330f729Sjoerg // If the main file has been overridden due to the use of a preamble,
22407330f729Sjoerg // make that override happen and introduce the preamble.
22417330f729Sjoerg if (OverrideMainBuffer) {
22427330f729Sjoerg assert(Preamble &&
22437330f729Sjoerg "No preamble was built, but OverrideMainBuffer is not null");
22447330f729Sjoerg
22457330f729Sjoerg IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
22467330f729Sjoerg &FileMgr.getVirtualFileSystem();
22477330f729Sjoerg Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS,
22487330f729Sjoerg OverrideMainBuffer.get());
22497330f729Sjoerg // FIXME: there is no way to update VFS if it was changed by
22507330f729Sjoerg // AddImplicitPreamble as FileMgr is accepted as a parameter by this method.
22517330f729Sjoerg // We use on-disk preambles instead and rely on FileMgr's VFS to ensure the
22527330f729Sjoerg // PCH files are always readable.
22537330f729Sjoerg OwnedBuffers.push_back(OverrideMainBuffer.release());
22547330f729Sjoerg } else {
22557330f729Sjoerg PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
22567330f729Sjoerg PreprocessorOpts.PrecompiledPreambleBytes.second = false;
22577330f729Sjoerg }
22587330f729Sjoerg
22597330f729Sjoerg // Disable the preprocessing record if modules are not enabled.
22607330f729Sjoerg if (!Clang->getLangOpts().Modules)
22617330f729Sjoerg PreprocessorOpts.DetailedRecord = false;
22627330f729Sjoerg
22637330f729Sjoerg std::unique_ptr<SyntaxOnlyAction> Act;
22647330f729Sjoerg Act.reset(new SyntaxOnlyAction);
22657330f729Sjoerg if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
22667330f729Sjoerg if (llvm::Error Err = Act->Execute()) {
22677330f729Sjoerg consumeError(std::move(Err)); // FIXME this drops errors on the floor.
22687330f729Sjoerg }
22697330f729Sjoerg Act->EndSourceFile();
22707330f729Sjoerg }
22717330f729Sjoerg }
22727330f729Sjoerg
Save(StringRef File)22737330f729Sjoerg bool ASTUnit::Save(StringRef File) {
22747330f729Sjoerg if (HadModuleLoaderFatalFailure)
22757330f729Sjoerg return true;
22767330f729Sjoerg
22777330f729Sjoerg // Write to a temporary file and later rename it to the actual file, to avoid
22787330f729Sjoerg // possible race conditions.
22797330f729Sjoerg SmallString<128> TempPath;
22807330f729Sjoerg TempPath = File;
22817330f729Sjoerg TempPath += "-%%%%%%%%";
22827330f729Sjoerg // FIXME: Can we somehow regenerate the stat cache here, or do we need to
22837330f729Sjoerg // unconditionally create a stat cache when we parse the file?
22847330f729Sjoerg
22857330f729Sjoerg if (llvm::Error Err = llvm::writeFileAtomically(
22867330f729Sjoerg TempPath, File, [this](llvm::raw_ostream &Out) {
22877330f729Sjoerg return serialize(Out) ? llvm::make_error<llvm::StringError>(
22887330f729Sjoerg "ASTUnit serialization failed",
22897330f729Sjoerg llvm::inconvertibleErrorCode())
22907330f729Sjoerg : llvm::Error::success();
22917330f729Sjoerg })) {
22927330f729Sjoerg consumeError(std::move(Err));
22937330f729Sjoerg return true;
22947330f729Sjoerg }
22957330f729Sjoerg return false;
22967330f729Sjoerg }
22977330f729Sjoerg
serializeUnit(ASTWriter & Writer,SmallVectorImpl<char> & Buffer,Sema & S,bool hasErrors,raw_ostream & OS)22987330f729Sjoerg static bool serializeUnit(ASTWriter &Writer,
22997330f729Sjoerg SmallVectorImpl<char> &Buffer,
23007330f729Sjoerg Sema &S,
23017330f729Sjoerg bool hasErrors,
23027330f729Sjoerg raw_ostream &OS) {
23037330f729Sjoerg Writer.WriteAST(S, std::string(), nullptr, "", hasErrors);
23047330f729Sjoerg
23057330f729Sjoerg // Write the generated bitstream to "Out".
23067330f729Sjoerg if (!Buffer.empty())
23077330f729Sjoerg OS.write(Buffer.data(), Buffer.size());
23087330f729Sjoerg
23097330f729Sjoerg return false;
23107330f729Sjoerg }
23117330f729Sjoerg
serialize(raw_ostream & OS)23127330f729Sjoerg bool ASTUnit::serialize(raw_ostream &OS) {
23137330f729Sjoerg // For serialization we are lenient if the errors were only warn-as-error kind.
23147330f729Sjoerg bool hasErrors = getDiagnostics().hasUncompilableErrorOccurred();
23157330f729Sjoerg
23167330f729Sjoerg if (WriterData)
23177330f729Sjoerg return serializeUnit(WriterData->Writer, WriterData->Buffer,
23187330f729Sjoerg getSema(), hasErrors, OS);
23197330f729Sjoerg
23207330f729Sjoerg SmallString<128> Buffer;
23217330f729Sjoerg llvm::BitstreamWriter Stream(Buffer);
23227330f729Sjoerg InMemoryModuleCache ModuleCache;
23237330f729Sjoerg ASTWriter Writer(Stream, Buffer, ModuleCache, {});
23247330f729Sjoerg return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS);
23257330f729Sjoerg }
23267330f729Sjoerg
23277330f729Sjoerg using SLocRemap = ContinuousRangeMap<unsigned, int, 2>;
23287330f729Sjoerg
TranslateStoredDiagnostics(FileManager & FileMgr,SourceManager & SrcMgr,const SmallVectorImpl<StandaloneDiagnostic> & Diags,SmallVectorImpl<StoredDiagnostic> & Out)23297330f729Sjoerg void ASTUnit::TranslateStoredDiagnostics(
23307330f729Sjoerg FileManager &FileMgr,
23317330f729Sjoerg SourceManager &SrcMgr,
23327330f729Sjoerg const SmallVectorImpl<StandaloneDiagnostic> &Diags,
23337330f729Sjoerg SmallVectorImpl<StoredDiagnostic> &Out) {
23347330f729Sjoerg // Map the standalone diagnostic into the new source manager. We also need to
23357330f729Sjoerg // remap all the locations to the new view. This includes the diag location,
23367330f729Sjoerg // any associated source ranges, and the source ranges of associated fix-its.
23377330f729Sjoerg // FIXME: There should be a cleaner way to do this.
23387330f729Sjoerg SmallVector<StoredDiagnostic, 4> Result;
23397330f729Sjoerg Result.reserve(Diags.size());
23407330f729Sjoerg
23417330f729Sjoerg for (const auto &SD : Diags) {
23427330f729Sjoerg // Rebuild the StoredDiagnostic.
23437330f729Sjoerg if (SD.Filename.empty())
23447330f729Sjoerg continue;
23457330f729Sjoerg auto FE = FileMgr.getFile(SD.Filename);
23467330f729Sjoerg if (!FE)
23477330f729Sjoerg continue;
23487330f729Sjoerg SourceLocation FileLoc;
23497330f729Sjoerg auto ItFileID = PreambleSrcLocCache.find(SD.Filename);
23507330f729Sjoerg if (ItFileID == PreambleSrcLocCache.end()) {
23517330f729Sjoerg FileID FID = SrcMgr.translateFile(*FE);
23527330f729Sjoerg FileLoc = SrcMgr.getLocForStartOfFile(FID);
23537330f729Sjoerg PreambleSrcLocCache[SD.Filename] = FileLoc;
23547330f729Sjoerg } else {
23557330f729Sjoerg FileLoc = ItFileID->getValue();
23567330f729Sjoerg }
23577330f729Sjoerg
23587330f729Sjoerg if (FileLoc.isInvalid())
23597330f729Sjoerg continue;
23607330f729Sjoerg SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset);
23617330f729Sjoerg FullSourceLoc Loc(L, SrcMgr);
23627330f729Sjoerg
23637330f729Sjoerg SmallVector<CharSourceRange, 4> Ranges;
23647330f729Sjoerg Ranges.reserve(SD.Ranges.size());
23657330f729Sjoerg for (const auto &Range : SD.Ranges) {
23667330f729Sjoerg SourceLocation BL = FileLoc.getLocWithOffset(Range.first);
23677330f729Sjoerg SourceLocation EL = FileLoc.getLocWithOffset(Range.second);
23687330f729Sjoerg Ranges.push_back(CharSourceRange::getCharRange(BL, EL));
23697330f729Sjoerg }
23707330f729Sjoerg
23717330f729Sjoerg SmallVector<FixItHint, 2> FixIts;
23727330f729Sjoerg FixIts.reserve(SD.FixIts.size());
23737330f729Sjoerg for (const auto &FixIt : SD.FixIts) {
23747330f729Sjoerg FixIts.push_back(FixItHint());
23757330f729Sjoerg FixItHint &FH = FixIts.back();
23767330f729Sjoerg FH.CodeToInsert = FixIt.CodeToInsert;
23777330f729Sjoerg SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first);
23787330f729Sjoerg SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second);
23797330f729Sjoerg FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
23807330f729Sjoerg }
23817330f729Sjoerg
23827330f729Sjoerg Result.push_back(StoredDiagnostic(SD.Level, SD.ID,
23837330f729Sjoerg SD.Message, Loc, Ranges, FixIts));
23847330f729Sjoerg }
23857330f729Sjoerg Result.swap(Out);
23867330f729Sjoerg }
23877330f729Sjoerg
addFileLevelDecl(Decl * D)23887330f729Sjoerg void ASTUnit::addFileLevelDecl(Decl *D) {
23897330f729Sjoerg assert(D);
23907330f729Sjoerg
23917330f729Sjoerg // We only care about local declarations.
23927330f729Sjoerg if (D->isFromASTFile())
23937330f729Sjoerg return;
23947330f729Sjoerg
23957330f729Sjoerg SourceManager &SM = *SourceMgr;
23967330f729Sjoerg SourceLocation Loc = D->getLocation();
23977330f729Sjoerg if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc))
23987330f729Sjoerg return;
23997330f729Sjoerg
24007330f729Sjoerg // We only keep track of the file-level declarations of each file.
24017330f729Sjoerg if (!D->getLexicalDeclContext()->isFileContext())
24027330f729Sjoerg return;
24037330f729Sjoerg
24047330f729Sjoerg SourceLocation FileLoc = SM.getFileLoc(Loc);
24057330f729Sjoerg assert(SM.isLocalSourceLocation(FileLoc));
24067330f729Sjoerg FileID FID;
24077330f729Sjoerg unsigned Offset;
24087330f729Sjoerg std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);
24097330f729Sjoerg if (FID.isInvalid())
24107330f729Sjoerg return;
24117330f729Sjoerg
2412*e038c9c4Sjoerg std::unique_ptr<LocDeclsTy> &Decls = FileDecls[FID];
24137330f729Sjoerg if (!Decls)
2414*e038c9c4Sjoerg Decls = std::make_unique<LocDeclsTy>();
24157330f729Sjoerg
24167330f729Sjoerg std::pair<unsigned, Decl *> LocDecl(Offset, D);
24177330f729Sjoerg
24187330f729Sjoerg if (Decls->empty() || Decls->back().first <= Offset) {
24197330f729Sjoerg Decls->push_back(LocDecl);
24207330f729Sjoerg return;
24217330f729Sjoerg }
24227330f729Sjoerg
24237330f729Sjoerg LocDeclsTy::iterator I =
24247330f729Sjoerg llvm::upper_bound(*Decls, LocDecl, llvm::less_first());
24257330f729Sjoerg
24267330f729Sjoerg Decls->insert(I, LocDecl);
24277330f729Sjoerg }
24287330f729Sjoerg
findFileRegionDecls(FileID File,unsigned Offset,unsigned Length,SmallVectorImpl<Decl * > & Decls)24297330f729Sjoerg void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
24307330f729Sjoerg SmallVectorImpl<Decl *> &Decls) {
24317330f729Sjoerg if (File.isInvalid())
24327330f729Sjoerg return;
24337330f729Sjoerg
24347330f729Sjoerg if (SourceMgr->isLoadedFileID(File)) {
24357330f729Sjoerg assert(Ctx->getExternalSource() && "No external source!");
24367330f729Sjoerg return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length,
24377330f729Sjoerg Decls);
24387330f729Sjoerg }
24397330f729Sjoerg
24407330f729Sjoerg FileDeclsTy::iterator I = FileDecls.find(File);
24417330f729Sjoerg if (I == FileDecls.end())
24427330f729Sjoerg return;
24437330f729Sjoerg
24447330f729Sjoerg LocDeclsTy &LocDecls = *I->second;
24457330f729Sjoerg if (LocDecls.empty())
24467330f729Sjoerg return;
24477330f729Sjoerg
24487330f729Sjoerg LocDeclsTy::iterator BeginIt =
24497330f729Sjoerg llvm::partition_point(LocDecls, [=](std::pair<unsigned, Decl *> LD) {
24507330f729Sjoerg return LD.first < Offset;
24517330f729Sjoerg });
24527330f729Sjoerg if (BeginIt != LocDecls.begin())
24537330f729Sjoerg --BeginIt;
24547330f729Sjoerg
24557330f729Sjoerg // If we are pointing at a top-level decl inside an objc container, we need
24567330f729Sjoerg // to backtrack until we find it otherwise we will fail to report that the
24577330f729Sjoerg // region overlaps with an objc container.
24587330f729Sjoerg while (BeginIt != LocDecls.begin() &&
24597330f729Sjoerg BeginIt->second->isTopLevelDeclInObjCContainer())
24607330f729Sjoerg --BeginIt;
24617330f729Sjoerg
24627330f729Sjoerg LocDeclsTy::iterator EndIt = llvm::upper_bound(
24637330f729Sjoerg LocDecls, std::make_pair(Offset + Length, (Decl *)nullptr),
24647330f729Sjoerg llvm::less_first());
24657330f729Sjoerg if (EndIt != LocDecls.end())
24667330f729Sjoerg ++EndIt;
24677330f729Sjoerg
24687330f729Sjoerg for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt)
24697330f729Sjoerg Decls.push_back(DIt->second);
24707330f729Sjoerg }
24717330f729Sjoerg
getLocation(const FileEntry * File,unsigned Line,unsigned Col) const24727330f729Sjoerg SourceLocation ASTUnit::getLocation(const FileEntry *File,
24737330f729Sjoerg unsigned Line, unsigned Col) const {
24747330f729Sjoerg const SourceManager &SM = getSourceManager();
24757330f729Sjoerg SourceLocation Loc = SM.translateFileLineCol(File, Line, Col);
24767330f729Sjoerg return SM.getMacroArgExpandedLocation(Loc);
24777330f729Sjoerg }
24787330f729Sjoerg
getLocation(const FileEntry * File,unsigned Offset) const24797330f729Sjoerg SourceLocation ASTUnit::getLocation(const FileEntry *File,
24807330f729Sjoerg unsigned Offset) const {
24817330f729Sjoerg const SourceManager &SM = getSourceManager();
24827330f729Sjoerg SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1);
24837330f729Sjoerg return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
24847330f729Sjoerg }
24857330f729Sjoerg
24867330f729Sjoerg /// If \arg Loc is a loaded location from the preamble, returns
24877330f729Sjoerg /// the corresponding local location of the main file, otherwise it returns
24887330f729Sjoerg /// \arg Loc.
mapLocationFromPreamble(SourceLocation Loc) const24897330f729Sjoerg SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {
24907330f729Sjoerg FileID PreambleID;
24917330f729Sjoerg if (SourceMgr)
24927330f729Sjoerg PreambleID = SourceMgr->getPreambleFileID();
24937330f729Sjoerg
24947330f729Sjoerg if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())
24957330f729Sjoerg return Loc;
24967330f729Sjoerg
24977330f729Sjoerg unsigned Offs;
24987330f729Sjoerg if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble->getBounds().Size) {
24997330f729Sjoerg SourceLocation FileLoc
25007330f729Sjoerg = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID());
25017330f729Sjoerg return FileLoc.getLocWithOffset(Offs);
25027330f729Sjoerg }
25037330f729Sjoerg
25047330f729Sjoerg return Loc;
25057330f729Sjoerg }
25067330f729Sjoerg
25077330f729Sjoerg /// If \arg Loc is a local location of the main file but inside the
25087330f729Sjoerg /// preamble chunk, returns the corresponding loaded location from the
25097330f729Sjoerg /// preamble, otherwise it returns \arg Loc.
mapLocationToPreamble(SourceLocation Loc) const25107330f729Sjoerg SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const {
25117330f729Sjoerg FileID PreambleID;
25127330f729Sjoerg if (SourceMgr)
25137330f729Sjoerg PreambleID = SourceMgr->getPreambleFileID();
25147330f729Sjoerg
25157330f729Sjoerg if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid())
25167330f729Sjoerg return Loc;
25177330f729Sjoerg
25187330f729Sjoerg unsigned Offs;
25197330f729Sjoerg if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) &&
25207330f729Sjoerg Offs < Preamble->getBounds().Size) {
25217330f729Sjoerg SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID);
25227330f729Sjoerg return FileLoc.getLocWithOffset(Offs);
25237330f729Sjoerg }
25247330f729Sjoerg
25257330f729Sjoerg return Loc;
25267330f729Sjoerg }
25277330f729Sjoerg
isInPreambleFileID(SourceLocation Loc) const25287330f729Sjoerg bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {
25297330f729Sjoerg FileID FID;
25307330f729Sjoerg if (SourceMgr)
25317330f729Sjoerg FID = SourceMgr->getPreambleFileID();
25327330f729Sjoerg
25337330f729Sjoerg if (Loc.isInvalid() || FID.isInvalid())
25347330f729Sjoerg return false;
25357330f729Sjoerg
25367330f729Sjoerg return SourceMgr->isInFileID(Loc, FID);
25377330f729Sjoerg }
25387330f729Sjoerg
isInMainFileID(SourceLocation Loc) const25397330f729Sjoerg bool ASTUnit::isInMainFileID(SourceLocation Loc) const {
25407330f729Sjoerg FileID FID;
25417330f729Sjoerg if (SourceMgr)
25427330f729Sjoerg FID = SourceMgr->getMainFileID();
25437330f729Sjoerg
25447330f729Sjoerg if (Loc.isInvalid() || FID.isInvalid())
25457330f729Sjoerg return false;
25467330f729Sjoerg
25477330f729Sjoerg return SourceMgr->isInFileID(Loc, FID);
25487330f729Sjoerg }
25497330f729Sjoerg
getEndOfPreambleFileID() const25507330f729Sjoerg SourceLocation ASTUnit::getEndOfPreambleFileID() const {
25517330f729Sjoerg FileID FID;
25527330f729Sjoerg if (SourceMgr)
25537330f729Sjoerg FID = SourceMgr->getPreambleFileID();
25547330f729Sjoerg
25557330f729Sjoerg if (FID.isInvalid())
25567330f729Sjoerg return {};
25577330f729Sjoerg
25587330f729Sjoerg return SourceMgr->getLocForEndOfFile(FID);
25597330f729Sjoerg }
25607330f729Sjoerg
getStartOfMainFileID() const25617330f729Sjoerg SourceLocation ASTUnit::getStartOfMainFileID() const {
25627330f729Sjoerg FileID FID;
25637330f729Sjoerg if (SourceMgr)
25647330f729Sjoerg FID = SourceMgr->getMainFileID();
25657330f729Sjoerg
25667330f729Sjoerg if (FID.isInvalid())
25677330f729Sjoerg return {};
25687330f729Sjoerg
25697330f729Sjoerg return SourceMgr->getLocForStartOfFile(FID);
25707330f729Sjoerg }
25717330f729Sjoerg
25727330f729Sjoerg llvm::iterator_range<PreprocessingRecord::iterator>
getLocalPreprocessingEntities() const25737330f729Sjoerg ASTUnit::getLocalPreprocessingEntities() const {
25747330f729Sjoerg if (isMainFileAST()) {
25757330f729Sjoerg serialization::ModuleFile &
25767330f729Sjoerg Mod = Reader->getModuleManager().getPrimaryModule();
25777330f729Sjoerg return Reader->getModulePreprocessedEntities(Mod);
25787330f729Sjoerg }
25797330f729Sjoerg
25807330f729Sjoerg if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord())
25817330f729Sjoerg return llvm::make_range(PPRec->local_begin(), PPRec->local_end());
25827330f729Sjoerg
25837330f729Sjoerg return llvm::make_range(PreprocessingRecord::iterator(),
25847330f729Sjoerg PreprocessingRecord::iterator());
25857330f729Sjoerg }
25867330f729Sjoerg
visitLocalTopLevelDecls(void * context,DeclVisitorFn Fn)25877330f729Sjoerg bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {
25887330f729Sjoerg if (isMainFileAST()) {
25897330f729Sjoerg serialization::ModuleFile &
25907330f729Sjoerg Mod = Reader->getModuleManager().getPrimaryModule();
25917330f729Sjoerg for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) {
25927330f729Sjoerg if (!Fn(context, D))
25937330f729Sjoerg return false;
25947330f729Sjoerg }
25957330f729Sjoerg
25967330f729Sjoerg return true;
25977330f729Sjoerg }
25987330f729Sjoerg
25997330f729Sjoerg for (ASTUnit::top_level_iterator TL = top_level_begin(),
26007330f729Sjoerg TLEnd = top_level_end();
26017330f729Sjoerg TL != TLEnd; ++TL) {
26027330f729Sjoerg if (!Fn(context, *TL))
26037330f729Sjoerg return false;
26047330f729Sjoerg }
26057330f729Sjoerg
26067330f729Sjoerg return true;
26077330f729Sjoerg }
26087330f729Sjoerg
getPCHFile()26097330f729Sjoerg const FileEntry *ASTUnit::getPCHFile() {
26107330f729Sjoerg if (!Reader)
26117330f729Sjoerg return nullptr;
26127330f729Sjoerg
26137330f729Sjoerg serialization::ModuleFile *Mod = nullptr;
26147330f729Sjoerg Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) {
26157330f729Sjoerg switch (M.Kind) {
26167330f729Sjoerg case serialization::MK_ImplicitModule:
26177330f729Sjoerg case serialization::MK_ExplicitModule:
26187330f729Sjoerg case serialization::MK_PrebuiltModule:
26197330f729Sjoerg return true; // skip dependencies.
26207330f729Sjoerg case serialization::MK_PCH:
26217330f729Sjoerg Mod = &M;
26227330f729Sjoerg return true; // found it.
26237330f729Sjoerg case serialization::MK_Preamble:
26247330f729Sjoerg return false; // look in dependencies.
26257330f729Sjoerg case serialization::MK_MainFile:
26267330f729Sjoerg return false; // look in dependencies.
26277330f729Sjoerg }
26287330f729Sjoerg
26297330f729Sjoerg return true;
26307330f729Sjoerg });
26317330f729Sjoerg if (Mod)
26327330f729Sjoerg return Mod->File;
26337330f729Sjoerg
26347330f729Sjoerg return nullptr;
26357330f729Sjoerg }
26367330f729Sjoerg
isModuleFile() const26377330f729Sjoerg bool ASTUnit::isModuleFile() const {
26387330f729Sjoerg return isMainFileAST() && getLangOpts().isCompilingModule();
26397330f729Sjoerg }
26407330f729Sjoerg
getInputKind() const26417330f729Sjoerg InputKind ASTUnit::getInputKind() const {
26427330f729Sjoerg auto &LangOpts = getLangOpts();
26437330f729Sjoerg
26447330f729Sjoerg Language Lang;
26457330f729Sjoerg if (LangOpts.OpenCL)
26467330f729Sjoerg Lang = Language::OpenCL;
26477330f729Sjoerg else if (LangOpts.CUDA)
26487330f729Sjoerg Lang = Language::CUDA;
26497330f729Sjoerg else if (LangOpts.RenderScript)
26507330f729Sjoerg Lang = Language::RenderScript;
26517330f729Sjoerg else if (LangOpts.CPlusPlus)
26527330f729Sjoerg Lang = LangOpts.ObjC ? Language::ObjCXX : Language::CXX;
26537330f729Sjoerg else
26547330f729Sjoerg Lang = LangOpts.ObjC ? Language::ObjC : Language::C;
26557330f729Sjoerg
26567330f729Sjoerg InputKind::Format Fmt = InputKind::Source;
26577330f729Sjoerg if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap)
26587330f729Sjoerg Fmt = InputKind::ModuleMap;
26597330f729Sjoerg
26607330f729Sjoerg // We don't know if input was preprocessed. Assume not.
26617330f729Sjoerg bool PP = false;
26627330f729Sjoerg
26637330f729Sjoerg return InputKind(Lang, Fmt, PP);
26647330f729Sjoerg }
26657330f729Sjoerg
26667330f729Sjoerg #ifndef NDEBUG
ConcurrencyState()26677330f729Sjoerg ASTUnit::ConcurrencyState::ConcurrencyState() {
26687330f729Sjoerg Mutex = new std::recursive_mutex;
26697330f729Sjoerg }
26707330f729Sjoerg
~ConcurrencyState()26717330f729Sjoerg ASTUnit::ConcurrencyState::~ConcurrencyState() {
26727330f729Sjoerg delete static_cast<std::recursive_mutex *>(Mutex);
26737330f729Sjoerg }
26747330f729Sjoerg
start()26757330f729Sjoerg void ASTUnit::ConcurrencyState::start() {
26767330f729Sjoerg bool acquired = static_cast<std::recursive_mutex *>(Mutex)->try_lock();
26777330f729Sjoerg assert(acquired && "Concurrent access to ASTUnit!");
26787330f729Sjoerg }
26797330f729Sjoerg
finish()26807330f729Sjoerg void ASTUnit::ConcurrencyState::finish() {
26817330f729Sjoerg static_cast<std::recursive_mutex *>(Mutex)->unlock();
26827330f729Sjoerg }
26837330f729Sjoerg
26847330f729Sjoerg #else // NDEBUG
26857330f729Sjoerg
ConcurrencyState()26867330f729Sjoerg ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; }
~ConcurrencyState()26877330f729Sjoerg ASTUnit::ConcurrencyState::~ConcurrencyState() {}
start()26887330f729Sjoerg void ASTUnit::ConcurrencyState::start() {}
finish()26897330f729Sjoerg void ASTUnit::ConcurrencyState::finish() {}
26907330f729Sjoerg
26917330f729Sjoerg #endif // NDEBUG
2692