1 //===--- Compiler.cpp -------------------------------------------*- C++-*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===---------------------------------------------------------------------===// 9 #include "Compiler.h" 10 #include "clang/Basic/TargetInfo.h" 11 #include "clang/Lex/PreprocessorOptions.h" 12 13 namespace clang { 14 namespace clangd { 15 16 /// Creates a CompilerInstance from \p CI, with main buffer overriden to \p 17 /// Buffer and arguments to read the PCH from \p Preamble, if \p Preamble is not 18 /// null. Note that vfs::FileSystem inside returned instance may differ from \p 19 /// VFS if additional file remapping were set in command-line arguments. 20 /// On some errors, returns null. When non-null value is returned, it's expected 21 /// to be consumed by the FrontendAction as it will have a pointer to the \p 22 /// Buffer that will only be deleted if BeginSourceFile is called. 23 std::unique_ptr<CompilerInstance> 24 prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI, 25 const PrecompiledPreamble *Preamble, 26 std::unique_ptr<llvm::MemoryBuffer> Buffer, 27 std::shared_ptr<PCHContainerOperations> PCHs, 28 IntrusiveRefCntPtr<vfs::FileSystem> VFS, 29 DiagnosticConsumer &DiagsClient) { 30 assert(VFS && "VFS is null"); 31 assert(!CI->getPreprocessorOpts().RetainRemappedFileBuffers && 32 "Setting RetainRemappedFileBuffers to true will cause a memory leak " 33 "of ContentsBuffer"); 34 35 // NOTE: we use Buffer.get() when adding remapped files, so we have to make 36 // sure it will be released if no error is emitted. 37 if (Preamble) { 38 Preamble->AddImplicitPreamble(*CI, VFS, Buffer.get()); 39 } else { 40 CI->getPreprocessorOpts().addRemappedFile( 41 CI->getFrontendOpts().Inputs[0].getFile(), Buffer.get()); 42 } 43 44 auto Clang = llvm::make_unique<CompilerInstance>(PCHs); 45 Clang->setInvocation(std::move(CI)); 46 Clang->createDiagnostics(&DiagsClient, false); 47 48 if (auto VFSWithRemapping = createVFSFromCompilerInvocation( 49 Clang->getInvocation(), Clang->getDiagnostics(), VFS)) 50 VFS = VFSWithRemapping; 51 Clang->setVirtualFileSystem(VFS); 52 53 Clang->setTarget(TargetInfo::CreateTargetInfo( 54 Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); 55 if (!Clang->hasTarget()) 56 return nullptr; 57 58 // RemappedFileBuffers will handle the lifetime of the Buffer pointer, 59 // release it. 60 Buffer.release(); 61 return Clang; 62 } 63 64 } // namespace clangd 65 } // namespace clang 66