xref: /llvm-project/flang/unittests/Frontend/CompilerInstanceTest.cpp (revision d5dd7d230ecaf8242f4429a5e3653e16bf55bcd6)
1 //===- unittests/Frontend/CompilerInstanceTest.cpp - CI tests -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Frontend/CompilerInstance.h"
10 #include "flang/Frontend/TextDiagnosticPrinter.h"
11 #include "clang/Basic/DiagnosticOptions.h"
12 #include "llvm/Support/FileSystem.h"
13 
14 #include "gtest/gtest.h"
15 
16 using namespace llvm;
17 using namespace Fortran::frontend;
18 
19 namespace {
20 
21 TEST(CompilerInstance, SanityCheckForFileManager) {
22   const char *inputSource = "InputSourceFile";
23   std::string inputFile = "buffer-file-test.f";
24   std::error_code ec;
25 
26   // 1. Create the input file for the file manager
27   // AllSources (which is used to manage files inside every compiler instance),
28   // works with paths. This means that it requires a physical file. Create one.
29   std::unique_ptr<llvm::raw_fd_ostream> os{
30       new llvm::raw_fd_ostream(inputFile, ec, llvm::sys::fs::OF_None)};
31   if (ec)
32     FAIL() << "Failed to create the input file";
33 
34   // Populate the input file with the pre-defined input and flush it.
35   *(os) << inputSource;
36   os.reset();
37 
38   // Get the path of the input file
39   llvm::SmallString<64> cwd;
40   if (std::error_code ec = llvm::sys::fs::current_path(cwd))
41     FAIL() << "Failed to obtain the current working directory";
42   std::string testFilePath(cwd.c_str());
43   testFilePath += "/" + inputFile;
44 
45   // 2. Set up CompilerInstance (i.e. specify the input file)
46   std::string buf;
47   llvm::raw_string_ostream errorStream{buf};
48   CompilerInstance compInst;
49   const Fortran::parser::SourceFile *sf =
50       compInst.getAllSources().Open(testFilePath, errorStream);
51 
52   // 3. Verify the content of the input file
53   // This is just a sanity check to make sure that CompilerInstance is capable
54   // of reading input files.
55   llvm::ArrayRef<char> fileContent = sf->content();
56   EXPECT_FALSE(fileContent.size() == 0);
57   EXPECT_TRUE(
58       llvm::StringRef(fileContent.data()).starts_with("InputSourceFile"));
59 
60   // 4. Delete the test file
61   ec = llvm::sys::fs::remove(inputFile);
62   if (ec)
63     FAIL() << "Failed to delete the test file";
64 }
65 
66 TEST(CompilerInstance, AllowDiagnosticLogWithUnownedDiagnosticConsumer) {
67   // 1. Set-up a basic DiagnosticConsumer
68   std::string diagnosticOutput;
69   llvm::raw_string_ostream diagnosticsOS(diagnosticOutput);
70   auto diagPrinter = std::make_unique<Fortran::frontend::TextDiagnosticPrinter>(
71       diagnosticsOS, new clang::DiagnosticOptions());
72 
73   // 2. Create a CompilerInstance (to manage a DiagnosticEngine)
74   CompilerInstance compInst;
75 
76   // 3. Set-up DiagnosticOptions
77   auto diagOpts = new clang::DiagnosticOptions();
78   // Tell the diagnostics engine to emit the diagnostic log to STDERR. This
79   // ensures that a chained diagnostic consumer is created so that the test can
80   // exercise the unowned diagnostic consumer in a chained consumer.
81   diagOpts->DiagnosticLogFile = "-";
82 
83   // 4. Create a DiagnosticEngine with an unowned consumer
84   IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags =
85       compInst.createDiagnostics(diagOpts, diagPrinter.get(),
86           /*ShouldOwnClient=*/false);
87 
88   // 5. Report a diagnostic
89   diags->Report(clang::diag::err_expected) << "no crash";
90 
91   // 6. Verify that the reported diagnostic wasn't lost and did end up in the
92   // output stream
93   ASSERT_EQ(diagnosticOutput, "error: expected no crash\n");
94 }
95 } // namespace
96