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"
16abc3d04eSRaphael Isemann #include "gtest/gtest.h"
17abc3d04eSRaphael Isemann
18abc3d04eSRaphael Isemann using namespace llvm;
19abc3d04eSRaphael Isemann using namespace clang;
20abc3d04eSRaphael Isemann
21abc3d04eSRaphael Isemann namespace {
22abc3d04eSRaphael Isemann
TEST(CompilerInstance,DefaultVFSOverlayFromInvocation)23abc3d04eSRaphael Isemann TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) {
24abc3d04eSRaphael Isemann // Create a temporary VFS overlay yaml file.
25abc3d04eSRaphael Isemann int FD;
26abc3d04eSRaphael Isemann SmallString<256> FileName;
27abc3d04eSRaphael Isemann ASSERT_FALSE(sys::fs::createTemporaryFile("vfs", "yaml", FD, FileName));
282590edf6SReid Kleckner ToolOutputFile File(FileName, FD);
29abc3d04eSRaphael Isemann
30abc3d04eSRaphael Isemann SmallString<256> CurrentPath;
31abc3d04eSRaphael Isemann sys::fs::current_path(CurrentPath);
32abc3d04eSRaphael Isemann sys::fs::make_absolute(CurrentPath, FileName);
33abc3d04eSRaphael Isemann
34abc3d04eSRaphael Isemann // Mount the VFS file itself on the path 'virtual.file'. Makes this test
35abc3d04eSRaphael Isemann // a bit shorter than creating a new dummy file just for this purpose.
36adcd0268SBenjamin Kramer const std::string CurrentPathStr = std::string(CurrentPath.str());
37adcd0268SBenjamin Kramer const std::string FileNameStr = std::string(FileName.str());
38abc3d04eSRaphael Isemann const char *VFSYaml = "{ 'version': 0, 'roots': [\n"
39abc3d04eSRaphael Isemann " { 'name': '%s',\n"
40abc3d04eSRaphael Isemann " 'type': 'directory',\n"
41abc3d04eSRaphael Isemann " 'contents': [\n"
42abc3d04eSRaphael Isemann " { 'name': 'vfs-virtual.file', 'type': 'file',\n"
43abc3d04eSRaphael Isemann " 'external-contents': '%s'\n"
44abc3d04eSRaphael Isemann " }\n"
45abc3d04eSRaphael Isemann " ]\n"
46abc3d04eSRaphael Isemann " }\n"
47abc3d04eSRaphael Isemann "]}\n";
48abc3d04eSRaphael Isemann File.os() << format(VFSYaml, CurrentPathStr.c_str(), FileName.c_str());
49abc3d04eSRaphael Isemann File.os().flush();
50abc3d04eSRaphael Isemann
51abc3d04eSRaphael Isemann // Create a CompilerInvocation that uses this overlay file.
52abc3d04eSRaphael Isemann const std::string VFSArg = "-ivfsoverlay" + FileNameStr;
53abc3d04eSRaphael Isemann const char *Args[] = {"clang", VFSArg.c_str(), "-xc++", "-"};
54abc3d04eSRaphael Isemann
55abc3d04eSRaphael Isemann IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
56abc3d04eSRaphael Isemann CompilerInstance::createDiagnostics(new DiagnosticOptions());
57abc3d04eSRaphael Isemann
58*499d0b96SSam McCall CreateInvocationOptions CIOpts;
59*499d0b96SSam McCall CIOpts.Diags = Diags;
60abc3d04eSRaphael Isemann std::shared_ptr<CompilerInvocation> CInvok =
61*499d0b96SSam McCall createInvocation(Args, std::move(CIOpts));
62abc3d04eSRaphael Isemann
63abc3d04eSRaphael Isemann if (!CInvok)
64abc3d04eSRaphael Isemann FAIL() << "could not create compiler invocation";
65abc3d04eSRaphael Isemann // Create a minimal CompilerInstance which should use the VFS we specified
66abc3d04eSRaphael Isemann // in the CompilerInvocation (as we don't explicitly set our own).
67abc3d04eSRaphael Isemann CompilerInstance Instance;
68abc3d04eSRaphael Isemann Instance.setDiagnostics(Diags.get());
69abc3d04eSRaphael Isemann Instance.setInvocation(CInvok);
70abc3d04eSRaphael Isemann Instance.createFileManager();
71abc3d04eSRaphael Isemann
72abc3d04eSRaphael Isemann // Check if the virtual file exists which means that our VFS is used by the
73abc3d04eSRaphael Isemann // CompilerInstance.
74abc3d04eSRaphael Isemann ASSERT_TRUE(Instance.getFileManager().getFile("vfs-virtual.file"));
75abc3d04eSRaphael Isemann }
76abc3d04eSRaphael Isemann
TEST(CompilerInstance,AllowDiagnosticLogWithUnownedDiagnosticConsumer)7788377d8dSAlex Lorenz TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) {
7888377d8dSAlex Lorenz auto DiagOpts = new DiagnosticOptions();
79514cfdb1SAlex Lorenz // Tell the diagnostics engine to emit the diagnostic log to STDERR. This
80514cfdb1SAlex Lorenz // ensures that a chained diagnostic consumer is created so that the test can
81514cfdb1SAlex Lorenz // exercise the unowned diagnostic consumer in a chained consumer.
82514cfdb1SAlex Lorenz DiagOpts->DiagnosticLogFile = "-";
8388377d8dSAlex Lorenz
8488377d8dSAlex Lorenz // Create the diagnostic engine with unowned consumer.
8588377d8dSAlex Lorenz std::string DiagnosticOutput;
8688377d8dSAlex Lorenz llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
872b3d49b6SJonas Devlieghere auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
8888377d8dSAlex Lorenz DiagnosticsOS, new DiagnosticOptions());
8988377d8dSAlex Lorenz CompilerInstance Instance;
9088377d8dSAlex Lorenz IntrusiveRefCntPtr<DiagnosticsEngine> Diags = Instance.createDiagnostics(
9188377d8dSAlex Lorenz DiagOpts, DiagPrinter.get(), /*ShouldOwnClient=*/false);
9288377d8dSAlex Lorenz
9388377d8dSAlex Lorenz Diags->Report(diag::err_expected) << "no crash";
9488377d8dSAlex Lorenz ASSERT_EQ(DiagnosticsOS.str(), "error: expected no crash\n");
9588377d8dSAlex Lorenz }
9688377d8dSAlex Lorenz
97abc3d04eSRaphael Isemann } // anonymous namespace
98