diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp | 674 |
1 files changed, 392 insertions, 282 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp index 5b0a52c..032adf3 100644 --- a/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp +++ b/contrib/llvm/tools/clang/lib/Frontend/ASTUnit.cpp @@ -29,7 +29,6 @@ #include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/Utils.h" #include "clang/Serialization/ASTReader.h" -#include "clang/Serialization/ASTSerializationListener.h" #include "clang/Serialization/ASTWriter.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" @@ -45,6 +44,8 @@ #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Mutex.h" #include "llvm/Support/CrashRecoveryContext.h" #include <cstdlib> #include <cstdio> @@ -65,7 +66,7 @@ namespace { Start = TimeRecord::getCurrentTime(); } - void setOutput(const llvm::Twine &Output) { + void setOutput(const Twine &Output) { if (WantTiming) this->Output = Output.str(); } @@ -96,10 +97,9 @@ static llvm::sys::cas_flag ActiveASTUnitObjects; ASTUnit::ASTUnit(bool _MainFileIsAST) : OnlyLocalDecls(false), CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST), - CompleteTranslationUnit(true), WantTiming(getenv("LIBCLANG_TIMING")), + TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")), OwnsRemappedFileBuffers(true), NumStoredDiagnosticsFromDriver(0), - ConcurrencyCheckValue(CheckUnlocked), PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0), ShouldCacheCodeCompletionResults(false), NestedMacroExpansions(true), @@ -114,7 +114,6 @@ ASTUnit::ASTUnit(bool _MainFileIsAST) } ASTUnit::~ASTUnit() { - ConcurrencyCheckValue = CheckLocked; CleanTemporaryFiles(); if (!PreambleFile.empty()) llvm::sys::Path(PreambleFile).eraseFromDisk(); @@ -185,7 +184,7 @@ static unsigned getDeclShowContexts(NamedDecl *ND, // In Objective-C, you can only be a subclass of another Objective-C class if (isa<ObjCInterfaceDecl>(ND)) - Contexts |= (1 << (CodeCompletionContext::CCC_ObjCSuperclass - 1)); + Contexts |= (1 << (CodeCompletionContext::CCC_ObjCInterfaceName - 1)); // Deal with tag names. if (isa<EnumDecl>(ND)) { @@ -236,7 +235,7 @@ void ASTUnit::CacheCodeCompletionResults() { // Gather the set of global code completions. typedef CodeCompletionResult Result; - llvm::SmallVector<Result, 8> Results; + SmallVector<Result, 8> Results; CachedCompletionAllocator = new GlobalCodeCompletionAllocator; TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, Results); @@ -375,33 +374,61 @@ namespace { /// \brief Gathers information from ASTReader that will be used to initialize /// a Preprocessor. class ASTInfoCollector : public ASTReaderListener { + Preprocessor &PP; + ASTContext &Context; LangOptions &LangOpt; HeaderSearch &HSI; - std::string &TargetTriple; + llvm::IntrusiveRefCntPtr<TargetInfo> &Target; std::string &Predefines; unsigned &Counter; unsigned NumHeaderInfos; + bool InitializedLanguage; public: - ASTInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI, - std::string &TargetTriple, std::string &Predefines, + ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt, + HeaderSearch &HSI, + llvm::IntrusiveRefCntPtr<TargetInfo> &Target, + std::string &Predefines, unsigned &Counter) - : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple), - Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {} + : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), Target(Target), + Predefines(Predefines), Counter(Counter), NumHeaderInfos(0), + InitializedLanguage(false) {} virtual bool ReadLanguageOptions(const LangOptions &LangOpts) { + if (InitializedLanguage) + return false; + LangOpt = LangOpts; + + // Initialize the preprocessor. + PP.Initialize(*Target); + + // Initialize the ASTContext + Context.InitBuiltinTypes(*Target); + + InitializedLanguage = true; return false; } - virtual bool ReadTargetTriple(llvm::StringRef Triple) { - TargetTriple = Triple; + virtual bool ReadTargetTriple(StringRef Triple) { + // If we've already initialized the target, don't do it again. + if (Target) + return false; + + // FIXME: This is broken, we should store the TargetOptions in the AST file. + TargetOptions TargetOpts; + TargetOpts.ABI = ""; + TargetOpts.CXXABI = ""; + TargetOpts.CPU = ""; + TargetOpts.Features.clear(); + TargetOpts.Triple = Triple; + Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts); return false; } virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - llvm::StringRef OriginalFileName, + StringRef OriginalFileName, std::string &SuggestedPredefines, FileManager &FileMgr) { Predefines = Buffers[0].Data; @@ -420,28 +447,34 @@ public: } }; -class StoredDiagnosticClient : public DiagnosticClient { - llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags; +class StoredDiagnosticConsumer : public DiagnosticConsumer { + SmallVectorImpl<StoredDiagnostic> &StoredDiags; public: - explicit StoredDiagnosticClient( - llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags) + explicit StoredDiagnosticConsumer( + SmallVectorImpl<StoredDiagnostic> &StoredDiags) : StoredDiags(StoredDiags) { } - virtual void HandleDiagnostic(Diagnostic::Level Level, - const DiagnosticInfo &Info); + virtual void HandleDiagnostic(DiagnosticsEngine::Level Level, + const Diagnostic &Info); + + DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { + // Just drop any diagnostics that come from cloned consumers; they'll + // have different source managers anyway. + return new IgnoringDiagConsumer(); + } }; /// \brief RAII object that optionally captures diagnostics, if /// there is no diagnostic client to capture them already. class CaptureDroppedDiagnostics { - Diagnostic &Diags; - StoredDiagnosticClient Client; - DiagnosticClient *PreviousClient; + DiagnosticsEngine &Diags; + StoredDiagnosticConsumer Client; + DiagnosticConsumer *PreviousClient; public: - CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags, - llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags) + CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags, + SmallVectorImpl<StoredDiagnostic> &StoredDiags) : Diags(Diags), Client(StoredDiags), PreviousClient(0) { if (RequestCapture || Diags.getClient() == 0) { @@ -460,10 +493,10 @@ public: } // anonymous namespace -void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level, - const DiagnosticInfo &Info) { +void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level, + const Diagnostic &Info) { // Default implementation (Warnings/errors count). - DiagnosticClient::HandleDiagnostic(Level, Info); + DiagnosticConsumer::HandleDiagnostic(Level, Info); StoredDiags.push_back(StoredDiagnostic(Level, Info)); } @@ -472,37 +505,32 @@ const std::string &ASTUnit::getOriginalSourceFileName() { return OriginalSourceFile; } -const std::string &ASTUnit::getASTFileName() { - assert(isMainFileAST() && "Not an ASTUnit from an AST file!"); - return static_cast<ASTReader *>(Ctx->getExternalSource())->getFileName(); -} - -llvm::MemoryBuffer *ASTUnit::getBufferForFile(llvm::StringRef Filename, +llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { assert(FileMgr); return FileMgr->getBufferForFile(Filename, ErrorStr); } /// \brief Configure the diagnostics object for use with ASTUnit. -void ASTUnit::ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags, +void ASTUnit::ConfigureDiags(llvm::IntrusiveRefCntPtr<DiagnosticsEngine> &Diags, const char **ArgBegin, const char **ArgEnd, ASTUnit &AST, bool CaptureDiagnostics) { if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object // with the default options. DiagnosticOptions DiagOpts; - DiagnosticClient *Client = 0; + DiagnosticConsumer *Client = 0; if (CaptureDiagnostics) - Client = new StoredDiagnosticClient(AST.StoredDiagnostics); + Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics); Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd- ArgBegin, ArgBegin, Client); } else if (CaptureDiagnostics) { - Diags->setClient(new StoredDiagnosticClient(AST.StoredDiagnostics)); + Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics)); } } ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, - llvm::IntrusiveRefCntPtr<Diagnostic> Diags, + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls, RemappedFile *RemappedFiles, @@ -513,8 +541,8 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get()); - llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic, - llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> > + llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > DiagCleanup(Diags.getPtr()); ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics); @@ -576,25 +604,41 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, // Gather Info for preprocessor construction later on. - LangOptions LangInfo; HeaderSearch &HeaderInfo = *AST->HeaderInfo.get(); - std::string TargetTriple; std::string Predefines; unsigned Counter; llvm::OwningPtr<ASTReader> Reader; - Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(), - AST->getDiagnostics())); + AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts, + /*Target=*/0, AST->getSourceManager(), HeaderInfo, + *AST, + /*IILookup=*/0, + /*OwnsHeaderSearch=*/false, + /*DelayInitialization=*/true); + Preprocessor &PP = *AST->PP; + + AST->Ctx = new ASTContext(AST->ASTFileLangOpts, + AST->getSourceManager(), + /*Target=*/0, + PP.getIdentifierTable(), + PP.getSelectorTable(), + PP.getBuiltinInfo(), + /* size_reserve = */0, + /*DelayInitialization=*/true); + ASTContext &Context = *AST->Ctx; + + Reader.reset(new ASTReader(PP, Context)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTReader> ReaderCleanup(Reader.get()); - Reader->setListener(new ASTInfoCollector(LangInfo, HeaderInfo, TargetTriple, - Predefines, Counter)); + Reader->setListener(new ASTInfoCollector(*AST->PP, Context, + AST->ASTFileLangOpts, HeaderInfo, + AST->Target, Predefines, Counter)); - switch (Reader->ReadAST(Filename, ASTReader::MainFile)) { + switch (Reader->ReadAST(Filename, serialization::MK_MainFile)) { case ASTReader::Success: break; @@ -606,39 +650,8 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, AST->OriginalSourceFile = Reader->getOriginalSourceFile(); - // AST file loaded successfully. Now create the preprocessor. - - // Get information about the target being compiled for. - // - // FIXME: This is broken, we should store the TargetOptions in the AST file. - TargetOptions TargetOpts; - TargetOpts.ABI = ""; - TargetOpts.CXXABI = ""; - TargetOpts.CPU = ""; - TargetOpts.Features.clear(); - TargetOpts.Triple = TargetTriple; - AST->Target = TargetInfo::CreateTargetInfo(AST->getDiagnostics(), - TargetOpts); - AST->PP = new Preprocessor(AST->getDiagnostics(), LangInfo, *AST->Target, - AST->getSourceManager(), HeaderInfo); - Preprocessor &PP = *AST->PP; - PP.setPredefines(Reader->getSuggestedPredefines()); PP.setCounterValue(Counter); - Reader->setPreprocessor(PP); - - // Create and initialize the ASTContext. - - AST->Ctx = new ASTContext(LangInfo, - AST->getSourceManager(), - *AST->Target, - PP.getIdentifierTable(), - PP.getSelectorTable(), - PP.getBuiltinInfo(), - /* size_reserve = */0); - ASTContext &Context = *AST->Ctx; - - Reader->InitializeContext(Context); // Attach the AST reader to the AST context as an external AST // source, so that declarations will be deserialized from the @@ -710,10 +723,8 @@ void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { return; } - if (ObjCClassDecl *Class = llvm::dyn_cast<ObjCClassDecl>(D)) { - for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end(); - I != IEnd; ++I) - AddTopLevelDeclarationToHash(I->getInterface(), Hash); + if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(D)) { + AddTopLevelDeclarationToHash(Class->getForwardInterfaceDecl(), Hash); return; } } @@ -752,7 +763,7 @@ public: ASTUnit &Unit; virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile) { + StringRef InFile) { CI.getPreprocessor().addPPCallbacks( new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue())); return new TopLevelDeclTrackerConsumer(Unit, @@ -763,22 +774,20 @@ public: TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {} virtual bool hasCodeCompletionSupport() const { return false; } - virtual bool usesCompleteTranslationUnit() { - return Unit.isCompleteTranslationUnit(); + virtual TranslationUnitKind getTranslationUnitKind() { + return Unit.getTranslationUnitKind(); } }; -class PrecompilePreambleConsumer : public PCHGenerator, - public ASTSerializationListener { +class PrecompilePreambleConsumer : public PCHGenerator { ASTUnit &Unit; unsigned &Hash; std::vector<Decl *> TopLevelDecls; public: - PrecompilePreambleConsumer(ASTUnit &Unit, - const Preprocessor &PP, bool Chaining, - const char *isysroot, llvm::raw_ostream *Out) - : PCHGenerator(PP, "", Chaining, isysroot, Out), Unit(Unit), + PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP, + StringRef isysroot, raw_ostream *Out) + : PCHGenerator(PP, "", /*IsModule=*/false, isysroot, Out), Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()) { Hash = 0; } @@ -809,15 +818,6 @@ public: getWriter().getDeclID(TopLevelDecls[I])); } } - - virtual void SerializedPreprocessedEntity(PreprocessedEntity *Entity, - uint64_t Offset) { - Unit.addPreprocessedEntityFromPreamble(Offset); - } - - virtual ASTSerializationListener *GetASTSerializationListener() { - return this; - } }; class PrecompilePreambleAction : public ASTFrontendAction { @@ -827,27 +827,27 @@ public: explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {} virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile) { + StringRef InFile) { std::string Sysroot; std::string OutputFile; - llvm::raw_ostream *OS = 0; - bool Chaining; + raw_ostream *OS = 0; if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, - OS, Chaining)) + OS)) return 0; - const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? - Sysroot.c_str() : 0; + if (!CI.getFrontendOpts().RelocatablePCH) + Sysroot.clear(); + CI.getPreprocessor().addPPCallbacks( new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue())); - return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining, - isysroot, OS); + return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Sysroot, + OS); } virtual bool hasCodeCompletionSupport() const { return false; } virtual bool hasASTFileSupport() const { return false; } - virtual bool usesCompleteTranslationUnit() { return false; } + virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; } }; } @@ -873,7 +873,10 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(Clang.get()); - Clang->setInvocation(&*Invocation); + llvm::IntrusiveRefCntPtr<CompilerInvocation> + CCInvocation(new CompilerInvocation(*Invocation)); + + Clang->setInvocation(CCInvocation.getPtr()); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second; // Set up diagnostics, capturing any diagnostics that would @@ -913,16 +916,13 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { // Clear out old caches and data. TopLevelDecls.clear(); - PreprocessedEntities.clear(); CleanTemporaryFiles(); - PreprocessedEntitiesByFile.clear(); if (!OverrideMainBuffer) { StoredDiagnostics.erase( StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver, StoredDiagnostics.end()); TopLevelDeclsInPreamble.clear(); - PreprocessedEntitiesInPreamble.clear(); } // Create a file manager object to provide access to and cache the filesystem. @@ -936,13 +936,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts(); PreprocessorOpts.DetailedRecordIncludesNestedMacroExpansions = NestedMacroExpansions; - std::string PriorImplicitPCHInclude; if (OverrideMainBuffer) { PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer); PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size(); PreprocessorOpts.PrecompiledPreambleBytes.second = PreambleEndsAtStartOfLine; - PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude; PreprocessorOpts.ImplicitPCHInclude = PreambleFile; PreprocessorOpts.DisablePCHValidation = true; @@ -961,9 +959,6 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { // Keep track of the override buffer; SavedMainFileBuffer = OverrideMainBuffer; - } else { - PreprocessorOpts.PrecompiledPreambleBytes.first = 0; - PreprocessorOpts.PrecompiledPreambleBytes.second = false; } llvm::OwningPtr<TopLevelDeclTrackerAction> Act( @@ -976,7 +971,14 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second, Clang->getFrontendOpts().Inputs[0].first)) goto error; - + + if (OverrideMainBuffer) { + std::string ModName = PreambleFile; + TranslateStoredDiagnostics(Clang->getModuleManager(), ModName, + getSourceManager(), PreambleDiagnostics, + StoredDiagnostics); + } + Act->Execute(); // Steal the created target, context, and preprocessor. @@ -990,21 +992,11 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) { Act->EndSourceFile(); - // Remove the overridden buffer we used for the preamble. - if (OverrideMainBuffer) { - PreprocessorOpts.eraseRemappedFile( - PreprocessorOpts.remapped_file_buffer_end() - 1); - PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude; - } - return false; error: // Remove the overridden buffer we used for the preamble. if (OverrideMainBuffer) { - PreprocessorOpts.eraseRemappedFile( - PreprocessorOpts.remapped_file_buffer_end() - 1); - PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude; delete OverrideMainBuffer; SavedMainFileBuffer = 0; } @@ -1041,7 +1033,7 @@ static std::string GetPreamblePCHPath() { P.createDirectoryOnDisk(true); P.appendComponent("preamble"); P.appendSuffix("pch"); - if (P.createTemporaryFileOnDisk()) + if (P.makeUnique(/*reuse_current=*/false, /*ErrMsg*/0)) return std::string(); return P.str(); @@ -1118,12 +1110,14 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, CreatedBuffer = true; } - return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, MaxLines)); + return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, + Invocation.getLangOpts(), + MaxLines)); } static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old, unsigned NewSize, - llvm::StringRef NewName) { + StringRef NewName) { llvm::MemoryBuffer *Result = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName); memcpy(const_cast<char*>(Result->getBufferStart()), @@ -1170,7 +1164,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble = ComputePreamble(*PreambleInvocation, MaxLines, CreatedPreambleBuffer); - // If ComputePreamble() Take ownership of the + // If ComputePreamble() Take ownership of the preamble buffer. llvm::OwningPtr<llvm::MemoryBuffer> OwnedPreambleBuffer; if (CreatedPreambleBuffer) OwnedPreambleBuffer.reset(NewPreamble.first); @@ -1197,7 +1191,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( if (Preamble.size() == NewPreamble.second.first && PreambleEndsAtStartOfLine == NewPreamble.second.second && NewPreamble.first->getBufferSize() < PreambleReservedSize-2 && - memcmp(&Preamble[0], NewPreamble.first->getBufferStart(), + memcmp(Preamble.getBufferStart(), NewPreamble.first->getBufferStart(), NewPreamble.second.first) == 0) { // The preamble has not changed. We may be able to re-use the precompiled // preamble. @@ -1271,10 +1265,6 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( ProcessWarningOptions(getDiagnostics(), PreambleInvocation->getDiagnosticOpts()); getDiagnostics().setNumWarnings(NumWarningsInPreamble); - if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble) - StoredDiagnostics.erase( - StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble, - StoredDiagnostics.end()); // Create a version of the main file buffer that is padded to // buffer size we reserved when creating the preamble. @@ -1291,6 +1281,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // We can't reuse the previously-computed preamble. Build a new one. Preamble.clear(); + PreambleDiagnostics.clear(); llvm::sys::Path(PreambleFile).eraseFromDisk(); PreambleRebuildCounter = 1; } else if (!AllowRebuild) { @@ -1332,7 +1323,9 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // Save the preamble text for later; we'll need to compare against it for // subsequent reparses. - Preamble.assign(NewPreamble.first->getBufferStart(), + StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].second; + Preamble.assign(FileMgr->getFile(MainFilename), + NewPreamble.first->getBufferStart(), NewPreamble.first->getBufferStart() + NewPreamble.second.first); PreambleEndsAtStartOfLine = NewPreamble.second.second; @@ -1353,7 +1346,6 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( // Tell the compiler invocation to generate a temporary precompiled header. FrontendOpts.ProgramAction = frontend::GeneratePCH; - FrontendOpts.ChainedPCH = true; // FIXME: Generate the precompiled header into memory? FrontendOpts.OutputFile = PreamblePCHPath; PreprocessorOpts.PrecompiledPreambleBytes.first = 0; @@ -1406,8 +1398,6 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( StoredDiagnostics.end()); TopLevelDecls.clear(); TopLevelDeclsInPreamble.clear(); - PreprocessedEntities.clear(); - PreprocessedEntitiesInPreamble.clear(); // Create a file manager object to provide access to and cache the filesystem. Clang->setFileManager(new FileManager(Clang->getFileSystemOpts())); @@ -1438,17 +1428,24 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); Preamble.clear(); TopLevelDeclsInPreamble.clear(); - PreprocessedEntities.clear(); - PreprocessedEntitiesInPreamble.clear(); PreambleRebuildCounter = DefaultPreambleRebuildInterval; PreprocessorOpts.eraseRemappedFile( PreprocessorOpts.remapped_file_buffer_end() - 1); return 0; } + // Transfer any diagnostics generated when parsing the preamble into the set + // of preamble diagnostics. + PreambleDiagnostics.clear(); + PreambleDiagnostics.insert(PreambleDiagnostics.end(), + StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver, + StoredDiagnostics.end()); + StoredDiagnostics.erase( + StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver, + StoredDiagnostics.end()); + // Keep track of the preamble we precompiled. PreambleFile = FrontendOpts.OutputFile; - NumStoredDiagnosticsInPreamble = StoredDiagnostics.size(); NumWarningsInPreamble = getDiagnostics().getNumWarnings(); // Keep track of all of the files that the source manager knows about, @@ -1501,69 +1498,12 @@ void ASTUnit::RealizeTopLevelDeclsFromPreamble() { TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end()); } -void ASTUnit::RealizePreprocessedEntitiesFromPreamble() { - if (!PP) - return; - - PreprocessingRecord *PPRec = PP->getPreprocessingRecord(); - if (!PPRec) - return; - - ExternalPreprocessingRecordSource *External = PPRec->getExternalSource(); - if (!External) - return; - - for (unsigned I = 0, N = PreprocessedEntitiesInPreamble.size(); I != N; ++I) { - if (PreprocessedEntity *PE - = External->ReadPreprocessedEntityAtOffset( - PreprocessedEntitiesInPreamble[I])) - PreprocessedEntities.push_back(PE); - } - - if (PreprocessedEntities.empty()) - return; - - PreprocessedEntities.insert(PreprocessedEntities.end(), - PPRec->begin(true), PPRec->end(true)); -} - -ASTUnit::pp_entity_iterator ASTUnit::pp_entity_begin() { - if (!PreprocessedEntitiesInPreamble.empty() && - PreprocessedEntities.empty()) - RealizePreprocessedEntitiesFromPreamble(); - - if (PreprocessedEntities.empty()) - if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord()) - return PPRec->begin(true); - - return PreprocessedEntities.begin(); -} - -ASTUnit::pp_entity_iterator ASTUnit::pp_entity_end() { - if (!PreprocessedEntitiesInPreamble.empty() && - PreprocessedEntities.empty()) - RealizePreprocessedEntitiesFromPreamble(); - - if (PreprocessedEntities.empty()) - if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord()) - return PPRec->end(true); - - return PreprocessedEntities.end(); -} - -unsigned ASTUnit::getMaxPCHLevel() const { - if (!getOnlyLocalDecls()) - return Decl::MaxPCHLevel; - - return 0; -} - -llvm::StringRef ASTUnit::getMainFileName() const { +StringRef ASTUnit::getMainFileName() const { return Invocation->getFrontendOpts().Inputs[0].second; } ASTUnit *ASTUnit::create(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr<Diagnostic> Diags) { + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags) { llvm::OwningPtr<ASTUnit> AST; AST.reset(new ASTUnit(false)); ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics=*/false); @@ -1571,33 +1511,35 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI, AST->Invocation = CI; AST->FileSystemOpts = CI->getFileSystemOpts(); AST->FileMgr = new FileManager(AST->FileSystemOpts); - AST->SourceMgr = new SourceManager(*Diags, *AST->FileMgr); + AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr); return AST.take(); } ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr<Diagnostic> Diags, - ASTFrontendAction *Action) { + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + ASTFrontendAction *Action, + ASTUnit *Unit) { assert(CI && "A CompilerInvocation is required"); - // Create the AST unit. - llvm::OwningPtr<ASTUnit> AST; - AST.reset(new ASTUnit(false)); - ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics*/false); - AST->Diagnostics = Diags; + llvm::OwningPtr<ASTUnit> OwnAST; + ASTUnit *AST = Unit; + if (!AST) { + // Create the AST unit. + OwnAST.reset(create(CI, Diags)); + AST = OwnAST.get(); + } + AST->OnlyLocalDecls = false; AST->CaptureDiagnostics = false; - AST->CompleteTranslationUnit = Action ? Action->usesCompleteTranslationUnit() - : true; + AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete; AST->ShouldCacheCodeCompletionResults = false; - AST->Invocation = CI; // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> - ASTUnitCleanup(AST.get()); - llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic, - llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> > + ASTUnitCleanup(OwnAST.get()); + llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > DiagCleanup(Diags.getPtr()); // We'll manage file buffers ourselves. @@ -1643,9 +1585,6 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, "IR inputs not supported here!"); // Configure the various subsystems. - AST->FileSystemOpts = Clang->getFileSystemOpts(); - AST->FileMgr = new FileManager(AST->FileSystemOpts); - AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr); AST->TheSema.reset(); AST->Ctx = 0; AST->PP = 0; @@ -1686,7 +1625,10 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI, Act->EndSourceFile(); - return AST.take(); + if (OwnAST) + return OwnAST.take(); + else + return AST; } bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { @@ -1719,11 +1661,11 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { } ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, - llvm::IntrusiveRefCntPtr<Diagnostic> Diags, + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble, - bool CompleteTranslationUnit, + TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool NestedMacroExpansions) { // Create the AST unit. @@ -1733,7 +1675,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, AST->Diagnostics = Diags; AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; - AST->CompleteTranslationUnit = CompleteTranslationUnit; + AST->TUKind = TUKind; AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; AST->Invocation = CI; AST->NestedMacroExpansions = NestedMacroExpansions; @@ -1741,8 +1683,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get()); - llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic, - llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> > + llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > DiagCleanup(Diags.getPtr()); return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take(); @@ -1750,18 +1692,16 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI, ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, const char **ArgEnd, - llvm::IntrusiveRefCntPtr<Diagnostic> Diags, - llvm::StringRef ResourceFilesPath, + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, bool RemappedFilesKeepOriginalName, bool PrecompilePreamble, - bool CompleteTranslationUnit, + TranslationUnitKind TUKind, bool CacheCodeCompletionResults, - bool CXXPrecompilePreamble, - bool CXXChainedPCH, bool NestedMacroExpansions) { if (!Diags.getPtr()) { // No diagnostics engine was provided, so create our own diagnostics object @@ -1771,17 +1711,18 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, ArgBegin); } - llvm::SmallVector<StoredDiagnostic, 4> StoredDiagnostics; + SmallVector<StoredDiagnostic, 4> StoredDiagnostics; llvm::IntrusiveRefCntPtr<CompilerInvocation> CI; { + CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags, StoredDiagnostics); CI = clang::createInvocationFromCommandLine( - llvm::ArrayRef<const char *>(ArgBegin, ArgEnd-ArgBegin), - Diags); + llvm::makeArrayRef(ArgBegin, ArgEnd), + Diags); if (!CI) return 0; } @@ -1803,16 +1744,6 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; - // Check whether we should precompile the preamble and/or use chained PCH. - // FIXME: This is a temporary hack while we debug C++ chained PCH. - if (CI->getLangOpts().CPlusPlus) { - PrecompilePreamble = PrecompilePreamble && CXXPrecompilePreamble; - - if (PrecompilePreamble && !CXXChainedPCH && - !CI->getPreprocessorOpts().ImplicitPCHInclude.empty()) - PrecompilePreamble = false; - } - // Create the AST unit. llvm::OwningPtr<ASTUnit> AST; AST.reset(new ASTUnit(false)); @@ -1823,10 +1754,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, AST->FileMgr = new FileManager(AST->FileSystemOpts); AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; - AST->CompleteTranslationUnit = CompleteTranslationUnit; + AST->TUKind = TUKind; AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); - AST->NumStoredDiagnosticsInPreamble = StoredDiagnostics.size(); AST->StoredDiagnostics.swap(StoredDiagnostics); AST->Invocation = CI; AST->NestedMacroExpansions = NestedMacroExpansions; @@ -1837,8 +1767,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin, llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation, llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> > CICleanup(CI.getPtr()); - llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic, - llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> > + llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > DiagCleanup(Diags.getPtr()); return AST->LoadFromCompilerInvocation(PrecompilePreamble) ? 0 : AST.take(); @@ -1896,6 +1826,10 @@ bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) { CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue) CacheCodeCompletionResults(); + // We now need to clear out the completion allocator for + // clang_getCursorCompletionString; it'll be recreated if necessary. + CursorCompletionAllocator = 0; + return Result; } @@ -1985,7 +1919,7 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context, case CodeCompletionContext::CCC_Name: case CodeCompletionContext::CCC_PotentiallyQualifiedName: case CodeCompletionContext::CCC_ParenthesizedExpression: - case CodeCompletionContext::CCC_ObjCSuperclass: + case CodeCompletionContext::CCC_ObjCInterfaceName: break; case CodeCompletionContext::CCC_EnumTag: @@ -2052,12 +1986,11 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, bool AddedResult = false; unsigned InContexts = (Context.getKind() == CodeCompletionContext::CCC_Recovery? NormalContexts - : (1 << (Context.getKind() - 1))); - + : (1ULL << (Context.getKind() - 1))); // Contains the set of names that are hidden by "local" completion results. llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames; typedef CodeCompletionResult Result; - llvm::SmallVector<Result, 8> AllResults; + SmallVector<Result, 8> AllResults; for (ASTUnit::cached_completion_iterator C = AST.cached_completion_begin(), CEnd = AST.cached_completion_end(); @@ -2139,22 +2072,22 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, -void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, +void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, RemappedFile *RemappedFiles, unsigned NumRemappedFiles, bool IncludeMacros, bool IncludeCodePatterns, CodeCompleteConsumer &Consumer, - Diagnostic &Diag, LangOptions &LangOpts, + DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, FileManager &FileMgr, - llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, - llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) { + SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, + SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) { if (!Invocation) return; SimpleTimer CompletionTimer(WantTiming); CompletionTimer.setOutput("Code completion @ " + File + ":" + - llvm::Twine(Line) + ":" + llvm::Twine(Column)); + Twine(Line) + ":" + Twine(Column)); llvm::IntrusiveRefCntPtr<CompilerInvocation> CCInvocation(new CompilerInvocation(*Invocation)); @@ -2252,7 +2185,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, llvm::sys::PathWithStatus MainPath(OriginalSourceFile); if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus()) if (const FileStatus *MainStatus = MainPath.getFileStatus()) - if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID()) + if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID() && + Line > 1) OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*CCInvocation, false, Line - 1); @@ -2272,17 +2206,6 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, PreprocessorOpts.ImplicitPCHInclude = PreambleFile; PreprocessorOpts.DisablePCHValidation = true; - // The stored diagnostics have the old source manager. Copy them - // to our output set of stored diagnostics, updating the source - // manager to the one we were given. - for (unsigned I = NumStoredDiagnosticsFromDriver, - N = this->StoredDiagnostics.size(); - I < N; ++I) { - StoredDiagnostics.push_back(this->StoredDiagnostics[I]); - FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr); - StoredDiagnostics[I].setLocation(Loc); - } - OwnedBuffers.push_back(OverrideMainBuffer); } else { PreprocessorOpts.PrecompiledPreambleBytes.first = 0; @@ -2296,36 +2219,58 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, Act.reset(new SyntaxOnlyAction); if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second, Clang->getFrontendOpts().Inputs[0].first)) { + if (OverrideMainBuffer) { + std::string ModName = PreambleFile; + TranslateStoredDiagnostics(Clang->getModuleManager(), ModName, + getSourceManager(), PreambleDiagnostics, + StoredDiagnostics); + } Act->Execute(); Act->EndSourceFile(); } } -CXSaveError ASTUnit::Save(llvm::StringRef File) { +CXSaveError ASTUnit::Save(StringRef File) { if (getDiagnostics().hasUnrecoverableErrorOccurred()) return CXSaveError_TranslationErrors; - + + // Write to a temporary file and later rename it to the actual file, to avoid + // possible race conditions. + llvm::SmallString<128> TempPath; + TempPath = File; + TempPath += "-%%%%%%%%"; + int fd; + if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, + /*makeAbsolute=*/false)) + return CXSaveError_Unknown; + // FIXME: Can we somehow regenerate the stat cache here, or do we need to // unconditionally create a stat cache when we parse the file? - std::string ErrorInfo; - llvm::raw_fd_ostream Out(File.str().c_str(), ErrorInfo, - llvm::raw_fd_ostream::F_Binary); - if (!ErrorInfo.empty() || Out.has_error()) - return CXSaveError_Unknown; + llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true); serialize(Out); Out.close(); - return Out.has_error()? CXSaveError_Unknown : CXSaveError_None; + if (Out.has_error()) + return CXSaveError_Unknown; + + if (llvm::error_code ec = llvm::sys::fs::rename(TempPath.str(), File)) { + bool exists; + llvm::sys::fs::remove(TempPath.str(), exists); + return CXSaveError_Unknown; + } + + return CXSaveError_None; } -bool ASTUnit::serialize(llvm::raw_ostream &OS) { +bool ASTUnit::serialize(raw_ostream &OS) { if (getDiagnostics().hasErrorOccurred()) return true; std::vector<unsigned char> Buffer; llvm::BitstreamWriter Stream(Buffer); ASTWriter Writer(Stream); - Writer.WriteAST(getSema(), 0, std::string(), 0); + // FIXME: Handle modules + Writer.WriteAST(getSema(), 0, std::string(), /*IsModule=*/false, ""); // Write the generated bitstream to "Out". if (!Buffer.empty()) @@ -2333,3 +2278,168 @@ bool ASTUnit::serialize(llvm::raw_ostream &OS) { return false; } + +typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap; + +static void TranslateSLoc(SourceLocation &L, SLocRemap &Remap) { + unsigned Raw = L.getRawEncoding(); + const unsigned MacroBit = 1U << 31; + L = SourceLocation::getFromRawEncoding((Raw & MacroBit) | + ((Raw & ~MacroBit) + Remap.find(Raw & ~MacroBit)->second)); +} + +void ASTUnit::TranslateStoredDiagnostics( + ASTReader *MMan, + StringRef ModName, + SourceManager &SrcMgr, + const SmallVectorImpl<StoredDiagnostic> &Diags, + SmallVectorImpl<StoredDiagnostic> &Out) { + // The stored diagnostic has the old source manager in it; update + // the locations to refer into the new source manager. We also need to remap + // all the locations to the new view. This includes the diag location, any + // associated source ranges, and the source ranges of associated fix-its. + // FIXME: There should be a cleaner way to do this. + + SmallVector<StoredDiagnostic, 4> Result; + Result.reserve(Diags.size()); + assert(MMan && "Don't have a module manager"); + serialization::Module *Mod = MMan->ModuleMgr.lookup(ModName); + assert(Mod && "Don't have preamble module"); + SLocRemap &Remap = Mod->SLocRemap; + for (unsigned I = 0, N = Diags.size(); I != N; ++I) { + // Rebuild the StoredDiagnostic. + const StoredDiagnostic &SD = Diags[I]; + SourceLocation L = SD.getLocation(); + TranslateSLoc(L, Remap); + FullSourceLoc Loc(L, SrcMgr); + + SmallVector<CharSourceRange, 4> Ranges; + Ranges.reserve(SD.range_size()); + for (StoredDiagnostic::range_iterator I = SD.range_begin(), + E = SD.range_end(); + I != E; ++I) { + SourceLocation BL = I->getBegin(); + TranslateSLoc(BL, Remap); + SourceLocation EL = I->getEnd(); + TranslateSLoc(EL, Remap); + Ranges.push_back(CharSourceRange(SourceRange(BL, EL), I->isTokenRange())); + } + + SmallVector<FixItHint, 2> FixIts; + FixIts.reserve(SD.fixit_size()); + for (StoredDiagnostic::fixit_iterator I = SD.fixit_begin(), + E = SD.fixit_end(); + I != E; ++I) { + FixIts.push_back(FixItHint()); + FixItHint &FH = FixIts.back(); + FH.CodeToInsert = I->CodeToInsert; + SourceLocation BL = I->RemoveRange.getBegin(); + TranslateSLoc(BL, Remap); + SourceLocation EL = I->RemoveRange.getEnd(); + TranslateSLoc(EL, Remap); + FH.RemoveRange = CharSourceRange(SourceRange(BL, EL), + I->RemoveRange.isTokenRange()); + } + + Result.push_back(StoredDiagnostic(SD.getLevel(), SD.getID(), + SD.getMessage(), Loc, Ranges, FixIts)); + } + Result.swap(Out); +} + +SourceLocation ASTUnit::getLocation(const FileEntry *File, + unsigned Line, unsigned Col) const { + const SourceManager &SM = getSourceManager(); + SourceLocation Loc = SM.translateFileLineCol(File, Line, Col); + return SM.getMacroArgExpandedLocation(Loc); +} + +SourceLocation ASTUnit::getLocation(const FileEntry *File, + unsigned Offset) const { + const SourceManager &SM = getSourceManager(); + SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1); + return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset)); +} + +/// \brief If \arg Loc is a loaded location from the preamble, returns +/// the corresponding local location of the main file, otherwise it returns +/// \arg Loc. +SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) { + FileID PreambleID; + if (SourceMgr) + PreambleID = SourceMgr->getPreambleFileID(); + + if (Loc.isInvalid() || Preamble.empty() || PreambleID.isInvalid()) + return Loc; + + unsigned Offs; + if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble.size()) { + SourceLocation FileLoc + = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID()); + return FileLoc.getLocWithOffset(Offs); + } + + return Loc; +} + +/// \brief If \arg Loc is a local location of the main file but inside the +/// preamble chunk, returns the corresponding loaded location from the +/// preamble, otherwise it returns \arg Loc. +SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) { + FileID PreambleID; + if (SourceMgr) + PreambleID = SourceMgr->getPreambleFileID(); + + if (Loc.isInvalid() || Preamble.empty() || PreambleID.isInvalid()) + return Loc; + + unsigned Offs; + if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) && + Offs < Preamble.size()) { + SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID); + return FileLoc.getLocWithOffset(Offs); + } + + return Loc; +} + +void ASTUnit::PreambleData::countLines() const { + NumLines = 0; + if (empty()) + return; + + for (std::vector<char>::const_iterator + I = Buffer.begin(), E = Buffer.end(); I != E; ++I) { + if (*I == '\n') + ++NumLines; + } + if (Buffer.back() != '\n') + ++NumLines; +} + +#ifndef NDEBUG +ASTUnit::ConcurrencyState::ConcurrencyState() { + Mutex = new llvm::sys::MutexImpl(/*recursive=*/true); +} + +ASTUnit::ConcurrencyState::~ConcurrencyState() { + delete static_cast<llvm::sys::MutexImpl *>(Mutex); +} + +void ASTUnit::ConcurrencyState::start() { + bool acquired = static_cast<llvm::sys::MutexImpl *>(Mutex)->tryacquire(); + assert(acquired && "Concurrent access to ASTUnit!"); +} + +void ASTUnit::ConcurrencyState::finish() { + static_cast<llvm::sys::MutexImpl *>(Mutex)->release(); +} + +#else // NDEBUG + +ASTUnit::ConcurrencyState::ConcurrencyState() {} +ASTUnit::ConcurrencyState::~ConcurrencyState() {} +void ASTUnit::ConcurrencyState::start() {} +void ASTUnit::ConcurrencyState::finish() {} + +#endif |