xref: /llvm-project/clang/unittests/Frontend/OutputStreamTest.cpp (revision df9a14d7bbf1180e4f1474254c9d7ed6bcb4ce55)
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