diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 9e88abbece7f2..8aee45b5dc644 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -287,9 +287,15 @@ static void collectVFSEntries(CompilerInstance &CI, void CompilerInstance::createVirtualFileSystem( IntrusiveRefCntPtr BaseFS, DiagnosticConsumer *DC) { + bool ShouldOwnClient = false; + if (!DC) { + DC = new DiagnosticConsumer; + ShouldOwnClient = true; + } + DiagnosticOptions DiagOpts; DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DC, - /*ShouldOwnClient=*/false); + ShouldOwnClient); VFS = createVFSFromCompilerInvocation(getInvocation(), Diags, std::move(BaseFS)); diff --git a/clang/unittests/Frontend/CompilerInstanceTest.cpp b/clang/unittests/Frontend/CompilerInstanceTest.cpp index 68578a93d75b5..41908e9c0f254 100644 --- a/clang/unittests/Frontend/CompilerInstanceTest.cpp +++ b/clang/unittests/Frontend/CompilerInstanceTest.cpp @@ -82,6 +82,17 @@ TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) { ASSERT_TRUE(Instance.getFileManager().getOptionalFileRef("vfs-virtual.file")); } +TEST(CompilerInstance, CreateVFSWithoutDiagnosticConsumer) { + auto Invocation = std::make_shared(); + Invocation->getHeaderSearchOpts().VFSOverlayFiles.push_back("/missing.yaml"); + auto BaseFS = llvm::makeIntrusiveRefCnt(); + CompilerInstance Instance(std::move(Invocation)); + // Check that omitting the DiagnosticConsumer doesn't crash (e.g. by + // dereferencing the null pointer). + ASSERT_NO_FATAL_FAILURE( + Instance.createVirtualFileSystem(std::move(BaseFS), /*DC=*/nullptr)); +} + TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) { DiagnosticOptions DiagOpts; // Tell the diagnostics engine to emit the diagnostic log to STDERR. This