xref: /llvm-project/clang/unittests/Frontend/CompilerInstanceTest.cpp (revision df9a14d7bbf1180e4f1474254c9d7ed6bcb4ce55)
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