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
16using namespace llvm;
17using namespace Fortran::frontend;
18
19namespace {
20
21TEST(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(result&: 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(path: inputFile);
62 if (ec)
63 FAIL() << "Failed to delete the test file";
64}
65
66TEST(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(diagnosticsOS.str(), "error: expected no crash\n");
94}
95} // namespace
96

source code of flang/unittests/Frontend/CompilerInstanceTest.cpp