1 //===- unittests/Frontend/OutputStreamTest.cpp --- FrontendAction 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 "clang/Basic/LangStandard.h" 10 #include "clang/CodeGen/BackendUtil.h" 11 #include "clang/CodeGen/CodeGenAction.h" 12 #include "clang/Frontend/CompilerInstance.h" 13 #include "clang/Frontend/TextDiagnosticPrinter.h" 14 #include "clang/FrontendTool/Utils.h" 15 #include "clang/Lex/PreprocessorOptions.h" 16 #include "llvm/Support/VirtualFileSystem.h" 17 #include "gtest/gtest.h" 18 19 using namespace llvm; 20 using namespace clang; 21 using namespace clang::frontend; 22 23 namespace { 24 25 TEST(FrontendOutputTests, TestOutputStream) { 26 auto Invocation = std::make_shared<CompilerInvocation>(); 27 Invocation->getPreprocessorOpts().addRemappedFile( 28 "test.cc", MemoryBuffer::getMemBuffer("").release()); 29 Invocation->getFrontendOpts().Inputs.push_back( 30 FrontendInputFile("test.cc", Language::CXX)); 31 Invocation->getFrontendOpts().ProgramAction = EmitBC; 32 Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; 33 CompilerInstance Compiler; 34 35 SmallVector<char, 256> IRBuffer; 36 std::unique_ptr<raw_pwrite_stream> IRStream( 37 new raw_svector_ostream(IRBuffer)); 38 39 Compiler.setOutputStream(std::move(IRStream)); 40 Compiler.setInvocation(std::move(Invocation)); 41 Compiler.createDiagnostics(*llvm::vfs::getRealFileSystem()); 42 43 bool Success = ExecuteCompilerInvocation(&Compiler); 44 EXPECT_TRUE(Success); 45 EXPECT_TRUE(!IRBuffer.empty()); 46 EXPECT_TRUE(StringRef(IRBuffer.data()).starts_with("BC")); 47 } 48 49 TEST(FrontendOutputTests, TestVerboseOutputStreamShared) { 50 auto Invocation = std::make_shared<CompilerInvocation>(); 51 Invocation->getPreprocessorOpts().addRemappedFile( 52 "test.cc", MemoryBuffer::getMemBuffer("invalid").release()); 53 Invocation->getFrontendOpts().Inputs.push_back( 54 FrontendInputFile("test.cc", Language::CXX)); 55 Invocation->getFrontendOpts().ProgramAction = EmitBC; 56 Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; 57 CompilerInstance Compiler; 58 59 std::string VerboseBuffer; 60 raw_string_ostream VerboseStream(VerboseBuffer); 61 62 Compiler.setOutputStream(std::make_unique<raw_null_ostream>()); 63 Compiler.setInvocation(std::move(Invocation)); 64 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 65 Compiler.createDiagnostics( 66 *llvm::vfs::getRealFileSystem(), 67 new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true); 68 Compiler.setVerboseOutputStream(VerboseStream); 69 70 bool Success = ExecuteCompilerInvocation(&Compiler); 71 EXPECT_FALSE(Success); 72 EXPECT_TRUE(!VerboseBuffer.empty()); 73 EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated")); 74 } 75 76 TEST(FrontendOutputTests, TestVerboseOutputStreamOwned) { 77 std::string VerboseBuffer; 78 bool Success; 79 { 80 auto Invocation = std::make_shared<CompilerInvocation>(); 81 Invocation->getPreprocessorOpts().addRemappedFile( 82 "test.cc", MemoryBuffer::getMemBuffer("invalid").release()); 83 Invocation->getFrontendOpts().Inputs.push_back( 84 FrontendInputFile("test.cc", Language::CXX)); 85 Invocation->getFrontendOpts().ProgramAction = EmitBC; 86 Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; 87 CompilerInstance Compiler; 88 89 std::unique_ptr<raw_ostream> VerboseStream = 90 std::make_unique<raw_string_ostream>(VerboseBuffer); 91 92 Compiler.setOutputStream(std::make_unique<raw_null_ostream>()); 93 Compiler.setInvocation(std::move(Invocation)); 94 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 95 Compiler.createDiagnostics( 96 *llvm::vfs::getRealFileSystem(), 97 new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true); 98 Compiler.setVerboseOutputStream(std::move(VerboseStream)); 99 100 Success = ExecuteCompilerInvocation(&Compiler); 101 } 102 EXPECT_FALSE(Success); 103 EXPECT_TRUE(!VerboseBuffer.empty()); 104 EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated")); 105 } 106 107 TEST(FrontendOutputTests, TestVerboseOutputStreamOwnedNotLeaked) { 108 CompilerInstance Compiler; 109 Compiler.setVerboseOutputStream(std::make_unique<raw_null_ostream>()); 110 111 // Trust leak sanitizer bots to catch a leak here. 112 Compiler.setVerboseOutputStream(llvm::nulls()); 113 } 114 115 } // anonymous namespace 116