Create and configure a CompilerInstance for scanning. If content is non-empty, it is used as remapped source for the main file.
| 272 | |
| 273 | /// Create and configure a CompilerInstance for scanning. |
| 274 | /// If content is non-empty, it is used as remapped source for the main file. |
| 275 | std::unique_ptr<clang::CompilerInstance> |
| 276 | create_scan_instance(llvm::ArrayRef<const char*> arguments, |
| 277 | llvm::StringRef directory, |
| 278 | llvm::StringRef content, |
| 279 | llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs) { |
| 280 | clang::DiagnosticOptions diag_opts; |
| 281 | auto diag_engine = clang::CompilerInstance::createDiagnostics(*vfs, |
| 282 | diag_opts, |
| 283 | new clang::IgnoringDiagConsumer(), |
| 284 | true); |
| 285 | |
| 286 | std::unique_ptr<clang::CompilerInvocation> invocation; |
| 287 | |
| 288 | bool is_cc1 = arguments.size() >= 2 && llvm::StringRef(arguments[1]) == "-cc1"; |
| 289 | if(is_cc1) { |
| 290 | invocation = std::make_unique<clang::CompilerInvocation>(); |
| 291 | if(!clang::CompilerInvocation::CreateFromArgs(*invocation, |
| 292 | llvm::ArrayRef(arguments).drop_front(2), |
| 293 | *diag_engine, |
| 294 | arguments[0])) { |
| 295 | return nullptr; |
| 296 | } |
| 297 | } else { |
| 298 | clang::CreateInvocationOptions options = { |
| 299 | .Diags = diag_engine, |
| 300 | .VFS = vfs, |
| 301 | .ProbePrecompiled = false, |
| 302 | }; |
| 303 | invocation = clang::createInvocation(arguments, options); |
| 304 | if(!invocation) { |
| 305 | return nullptr; |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | invocation->getFrontendOpts().DisableFree = false; |
| 310 | invocation->getFileSystemOpts().WorkingDir = directory.str(); |
| 311 | |
| 312 | if(!content.empty()) { |
| 313 | auto& inputs = invocation->getFrontendOpts().Inputs; |
| 314 | if(!inputs.empty()) { |
| 315 | auto main_file = inputs[0].getFile(); |
| 316 | // Use an overlay VFS to inject the remapped content. This ensures |
| 317 | // both the preprocessor and the DependencyDirectivesGetter see it. |
| 318 | auto overlay = llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(vfs); |
| 319 | auto mem_fs = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); |
| 320 | mem_fs->addFile(main_file, 0, llvm::MemoryBuffer::getMemBufferCopy(content, main_file)); |
| 321 | overlay->pushOverlay(std::move(mem_fs)); |
| 322 | vfs = std::move(overlay); |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | auto instance = std::make_unique<clang::CompilerInstance>(std::move(invocation)); |
| 327 | instance->setVirtualFileSystem(std::move(vfs)); |
| 328 | instance->createDiagnostics(new clang::IgnoringDiagConsumer(), true); |
| 329 | instance->getDiagnostics().setSuppressAllDiagnostics(true); |
| 330 | instance->createFileManager(); |
| 331 |
no test coverage detected