1abc3d04eSRaphael Isemann //===- unittests/Frontend/CompilerInstanceTest.cpp - CI tests -------------===// 2abc3d04eSRaphael Isemann // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6abc3d04eSRaphael Isemann // 7abc3d04eSRaphael Isemann //===----------------------------------------------------------------------===// 8abc3d04eSRaphael Isemann 9abc3d04eSRaphael Isemann #include "clang/Frontend/CompilerInstance.h" 10e08464fbSReid Kleckner #include "clang/Basic/FileManager.h" 11abc3d04eSRaphael Isemann #include "clang/Frontend/CompilerInvocation.h" 1288377d8dSAlex Lorenz #include "clang/Frontend/TextDiagnosticPrinter.h" 13abc3d04eSRaphael Isemann #include "llvm/Support/FileSystem.h" 14abc3d04eSRaphael Isemann #include "llvm/Support/Format.h" 15abc3d04eSRaphael Isemann #include "llvm/Support/ToolOutputFile.h" 16*df9a14d7SKadir Cetinkaya #include "llvm/Support/VirtualFileSystem.h" 17abc3d04eSRaphael Isemann #include "gtest/gtest.h" 18abc3d04eSRaphael Isemann 19abc3d04eSRaphael Isemann using namespace llvm; 20abc3d04eSRaphael Isemann using namespace clang; 21abc3d04eSRaphael Isemann 22abc3d04eSRaphael Isemann namespace { 23abc3d04eSRaphael Isemann 24abc3d04eSRaphael Isemann TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) { 25abc3d04eSRaphael Isemann // Create a temporary VFS overlay yaml file. 26abc3d04eSRaphael Isemann int FD; 27abc3d04eSRaphael Isemann SmallString<256> FileName; 28abc3d04eSRaphael Isemann ASSERT_FALSE(sys::fs::createTemporaryFile("vfs", "yaml", FD, FileName)); 292590edf6SReid Kleckner ToolOutputFile File(FileName, FD); 30abc3d04eSRaphael Isemann 31abc3d04eSRaphael Isemann SmallString<256> CurrentPath; 32abc3d04eSRaphael Isemann sys::fs::current_path(CurrentPath); 33abc3d04eSRaphael Isemann sys::fs::make_absolute(CurrentPath, FileName); 34abc3d04eSRaphael Isemann 35abc3d04eSRaphael Isemann // Mount the VFS file itself on the path 'virtual.file'. Makes this test 36abc3d04eSRaphael Isemann // a bit shorter than creating a new dummy file just for this purpose. 37adcd0268SBenjamin Kramer const std::string CurrentPathStr = std::string(CurrentPath.str()); 38adcd0268SBenjamin Kramer const std::string FileNameStr = std::string(FileName.str()); 39abc3d04eSRaphael Isemann const char *VFSYaml = "{ 'version': 0, 'roots': [\n" 40abc3d04eSRaphael Isemann " { 'name': '%s',\n" 41abc3d04eSRaphael Isemann " 'type': 'directory',\n" 42abc3d04eSRaphael Isemann " 'contents': [\n" 43abc3d04eSRaphael Isemann " { 'name': 'vfs-virtual.file', 'type': 'file',\n" 44abc3d04eSRaphael Isemann " 'external-contents': '%s'\n" 45abc3d04eSRaphael Isemann " }\n" 46abc3d04eSRaphael Isemann " ]\n" 47abc3d04eSRaphael Isemann " }\n" 48abc3d04eSRaphael Isemann "]}\n"; 49abc3d04eSRaphael Isemann File.os() << format(VFSYaml, CurrentPathStr.c_str(), FileName.c_str()); 50abc3d04eSRaphael Isemann File.os().flush(); 51abc3d04eSRaphael Isemann 52abc3d04eSRaphael Isemann // Create a CompilerInvocation that uses this overlay file. 53abc3d04eSRaphael Isemann const std::string VFSArg = "-ivfsoverlay" + FileNameStr; 54abc3d04eSRaphael Isemann const char *Args[] = {"clang", VFSArg.c_str(), "-xc++", "-"}; 55abc3d04eSRaphael Isemann 56abc3d04eSRaphael Isemann IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 57*df9a14d7SKadir Cetinkaya CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), 58*df9a14d7SKadir Cetinkaya new DiagnosticOptions()); 59abc3d04eSRaphael Isemann 60499d0b96SSam McCall CreateInvocationOptions CIOpts; 61499d0b96SSam McCall CIOpts.Diags = Diags; 62abc3d04eSRaphael Isemann std::shared_ptr<CompilerInvocation> CInvok = 63499d0b96SSam McCall createInvocation(Args, std::move(CIOpts)); 64abc3d04eSRaphael Isemann 65abc3d04eSRaphael Isemann if (!CInvok) 66abc3d04eSRaphael Isemann FAIL() << "could not create compiler invocation"; 67abc3d04eSRaphael Isemann // Create a minimal CompilerInstance which should use the VFS we specified 68abc3d04eSRaphael Isemann // in the CompilerInvocation (as we don't explicitly set our own). 69abc3d04eSRaphael Isemann CompilerInstance Instance; 70abc3d04eSRaphael Isemann Instance.setDiagnostics(Diags.get()); 71abc3d04eSRaphael Isemann Instance.setInvocation(CInvok); 72abc3d04eSRaphael Isemann Instance.createFileManager(); 73abc3d04eSRaphael Isemann 74abc3d04eSRaphael Isemann // Check if the virtual file exists which means that our VFS is used by the 75abc3d04eSRaphael Isemann // CompilerInstance. 76b1aea98cSJan Svoboda ASSERT_TRUE(Instance.getFileManager().getOptionalFileRef("vfs-virtual.file")); 77abc3d04eSRaphael Isemann } 78abc3d04eSRaphael Isemann 7988377d8dSAlex Lorenz TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) { 8088377d8dSAlex Lorenz auto DiagOpts = new DiagnosticOptions(); 81514cfdb1SAlex Lorenz // Tell the diagnostics engine to emit the diagnostic log to STDERR. This 82514cfdb1SAlex Lorenz // ensures that a chained diagnostic consumer is created so that the test can 83514cfdb1SAlex Lorenz // exercise the unowned diagnostic consumer in a chained consumer. 84514cfdb1SAlex Lorenz DiagOpts->DiagnosticLogFile = "-"; 8588377d8dSAlex Lorenz 8688377d8dSAlex Lorenz // Create the diagnostic engine with unowned consumer. 8788377d8dSAlex Lorenz std::string DiagnosticOutput; 8888377d8dSAlex Lorenz llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput); 892b3d49b6SJonas Devlieghere auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>( 9088377d8dSAlex Lorenz DiagnosticsOS, new DiagnosticOptions()); 9188377d8dSAlex Lorenz CompilerInstance Instance; 92*df9a14d7SKadir Cetinkaya IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 93*df9a14d7SKadir Cetinkaya Instance.createDiagnostics(*llvm::vfs::getRealFileSystem(), DiagOpts, 94*df9a14d7SKadir Cetinkaya DiagPrinter.get(), /*ShouldOwnClient=*/false); 9588377d8dSAlex Lorenz 9688377d8dSAlex Lorenz Diags->Report(diag::err_expected) << "no crash"; 979e211744SYoungsuk Kim ASSERT_EQ(DiagnosticOutput, "error: expected no crash\n"); 9888377d8dSAlex Lorenz } 9988377d8dSAlex Lorenz 100abc3d04eSRaphael Isemann } // anonymous namespace 101