Skip to content

Commit 87cb734

Browse files
committed
[Clang] Add VerboseOutputStream to CompilerInstance
Remove one instance of a hardcoded output stream in CompilerInstance::ExecuteAction. There are still other cases of output being hard-coded to standard streams in ExecuteCompilerInvocation, but this patch covers the case when no flags like -version or -help are passed, namely the "X warnings and Y errors generated." diagnostic. Differential Revision: https://reviews.llvm.org/D53768 llvm-svn: 375442
1 parent ca7f4d8 commit 87cb734

File tree

3 files changed

+87
-6
lines changed

3 files changed

+87
-6
lines changed

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ class CompilerInstance : public ModuleLoader {
155155
/// One or more modules failed to build.
156156
bool ModuleBuildFailed = false;
157157

158+
/// The stream for verbose output if owned, otherwise nullptr.
159+
std::unique_ptr<raw_ostream> OwnedVerboseOutputStream;
160+
161+
/// The stream for verbose output.
162+
raw_ostream *VerboseOutputStream = &llvm::errs();
163+
158164
/// Holds information about the output file.
159165
///
160166
/// If TempFilename is not empty we must rename it to Filename at the end.
@@ -217,9 +223,6 @@ class CompilerInstance : public ModuleLoader {
217223
/// \param Act - The action to execute.
218224
/// \return - True on success.
219225
//
220-
// FIXME: This function should take the stream to write any debugging /
221-
// verbose output to as an argument.
222-
//
223226
// FIXME: Eliminate the llvm_shutdown requirement, that should either be part
224227
// of the context or else not CompilerInstance specific.
225228
bool ExecuteAction(FrontendAction &Act);
@@ -349,6 +352,21 @@ class CompilerInstance : public ModuleLoader {
349352
return *Diagnostics->getClient();
350353
}
351354

355+
/// }
356+
/// @name VerboseOutputStream
357+
/// }
358+
359+
/// Replace the current stream for verbose output.
360+
void setVerboseOutputStream(raw_ostream &Value);
361+
362+
/// Replace the current stream for verbose output.
363+
void setVerboseOutputStream(std::unique_ptr<raw_ostream> Value);
364+
365+
/// Get the current stream for verbose output.
366+
raw_ostream &getVerboseOutputStream() {
367+
return *VerboseOutputStream;
368+
}
369+
352370
/// }
353371
/// @name Target Info
354372
/// {

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
8484
Diagnostics = Value;
8585
}
8686

87+
void CompilerInstance::setVerboseOutputStream(raw_ostream &Value) {
88+
OwnedVerboseOutputStream.release();
89+
VerboseOutputStream = &Value;
90+
}
91+
92+
void CompilerInstance::setVerboseOutputStream(std::unique_ptr<raw_ostream> Value) {
93+
OwnedVerboseOutputStream.swap(Value);
94+
VerboseOutputStream = OwnedVerboseOutputStream.get();
95+
}
96+
8797
void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
8898
void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
8999

@@ -896,9 +906,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
896906
// DesiredStackSpace available.
897907
noteBottomOfStack();
898908

899-
// FIXME: Take this as an argument, once all the APIs we used have moved to
900-
// taking it as an input instead of hard-coding llvm::errs.
901-
raw_ostream &OS = llvm::errs();
909+
raw_ostream &OS = getVerboseOutputStream();
902910

903911
if (!Act.PrepareToExecute(*this))
904912
return false;

clang/unittests/Frontend/OutputStreamTest.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "clang/CodeGen/BackendUtil.h"
1111
#include "clang/CodeGen/CodeGenAction.h"
1212
#include "clang/Frontend/CompilerInstance.h"
13+
#include "clang/Frontend/TextDiagnosticPrinter.h"
1314
#include "clang/FrontendTool/Utils.h"
1415
#include "clang/Lex/PreprocessorOptions.h"
1516
#include "gtest/gtest.h"
@@ -43,4 +44,58 @@ TEST(FrontendOutputTests, TestOutputStream) {
4344
EXPECT_TRUE(!IRBuffer.empty());
4445
EXPECT_TRUE(StringRef(IRBuffer.data()).startswith("BC"));
4546
}
47+
48+
TEST(FrontendOutputTests, TestVerboseOutputStreamShared) {
49+
auto Invocation = std::make_shared<CompilerInvocation>();
50+
Invocation->getPreprocessorOpts().addRemappedFile(
51+
"test.cc", MemoryBuffer::getMemBuffer("invalid").release());
52+
Invocation->getFrontendOpts().Inputs.push_back(
53+
FrontendInputFile("test.cc", Language::CXX));
54+
Invocation->getFrontendOpts().ProgramAction = EmitBC;
55+
Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
56+
CompilerInstance Compiler;
57+
58+
std::string VerboseBuffer;
59+
raw_string_ostream VerboseStream(VerboseBuffer);
60+
61+
Compiler.setInvocation(std::move(Invocation));
62+
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
63+
Compiler.createDiagnostics(
64+
new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true);
65+
Compiler.setVerboseOutputStream(VerboseStream);
66+
67+
bool Success = ExecuteCompilerInvocation(&Compiler);
68+
EXPECT_FALSE(Success);
69+
EXPECT_TRUE(!VerboseStream.str().empty());
70+
EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated"));
71+
}
72+
73+
TEST(FrontendOutputTests, TestVerboseOutputStreamOwned) {
74+
std::string VerboseBuffer;
75+
bool Success;
76+
{
77+
auto Invocation = std::make_shared<CompilerInvocation>();
78+
Invocation->getPreprocessorOpts().addRemappedFile(
79+
"test.cc", MemoryBuffer::getMemBuffer("invalid").release());
80+
Invocation->getFrontendOpts().Inputs.push_back(
81+
FrontendInputFile("test.cc", Language::CXX));
82+
Invocation->getFrontendOpts().ProgramAction = EmitBC;
83+
Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
84+
CompilerInstance Compiler;
85+
86+
std::unique_ptr<raw_ostream> VerboseStream =
87+
std::make_unique<raw_string_ostream>(VerboseBuffer);
88+
89+
Compiler.setInvocation(std::move(Invocation));
90+
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
91+
Compiler.createDiagnostics(
92+
new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true);
93+
Compiler.setVerboseOutputStream(std::move(VerboseStream));
94+
95+
Success = ExecuteCompilerInvocation(&Compiler);
96+
}
97+
EXPECT_FALSE(Success);
98+
EXPECT_TRUE(!VerboseBuffer.empty());
99+
EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated"));
100+
}
46101
}

0 commit comments

Comments
 (0)