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