aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Linder <scott@scottlinder.com>2019-10-21 19:04:56 +0000
committerScott Linder <scott@scottlinder.com>2019-10-21 19:04:56 +0000
commitfd456e42ad4108bc4feb14ba37a5c0cb267744a2 (patch)
tree98dfe40ac39ac0dc07232f13dcc57a7be605fe4b
parent03d35ab3ae600b0659dcb47c006d9d51925e427f (diff)
downloadclang-fd456e42ad4108bc4feb14ba37a5c0cb267744a2.tar.gz
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@375442 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Frontend/CompilerInstance.h24
-rw-r--r--lib/Frontend/CompilerInstance.cpp14
-rw-r--r--unittests/Frontend/OutputStreamTest.cpp55
3 files changed, 87 insertions, 6 deletions
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index eb49c53ff4..d15bdc4665 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -155,6 +155,12 @@ class CompilerInstance : public ModuleLoader {
/// One or more modules failed to build.
bool ModuleBuildFailed = false;
+ /// The stream for verbose output if owned, otherwise nullptr.
+ std::unique_ptr<raw_ostream> OwnedVerboseOutputStream;
+
+ /// The stream for verbose output.
+ raw_ostream *VerboseOutputStream = &llvm::errs();
+
/// Holds information about the output file.
///
/// If TempFilename is not empty we must rename it to Filename at the end.
@@ -217,9 +223,6 @@ public:
/// \param Act - The action to execute.
/// \return - True on success.
//
- // FIXME: This function should take the stream to write any debugging /
- // verbose output to as an argument.
- //
// FIXME: Eliminate the llvm_shutdown requirement, that should either be part
// of the context or else not CompilerInstance specific.
bool ExecuteAction(FrontendAction &Act);
@@ -350,6 +353,21 @@ public:
}
/// }
+ /// @name VerboseOutputStream
+ /// }
+
+ /// Replace the current stream for verbose output.
+ void setVerboseOutputStream(raw_ostream &Value);
+
+ /// Replace the current stream for verbose output.
+ void setVerboseOutputStream(std::unique_ptr<raw_ostream> Value);
+
+ /// Get the current stream for verbose output.
+ raw_ostream &getVerboseOutputStream() {
+ return *VerboseOutputStream;
+ }
+
+ /// }
/// @name Target Info
/// {
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index a01224f6e0..c409c07ff1 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -84,6 +84,16 @@ void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
Diagnostics = Value;
}
+void CompilerInstance::setVerboseOutputStream(raw_ostream &Value) {
+ OwnedVerboseOutputStream.release();
+ VerboseOutputStream = &Value;
+}
+
+void CompilerInstance::setVerboseOutputStream(std::unique_ptr<raw_ostream> Value) {
+ OwnedVerboseOutputStream.swap(Value);
+ VerboseOutputStream = OwnedVerboseOutputStream.get();
+}
+
void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
@@ -896,9 +906,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
// DesiredStackSpace available.
noteBottomOfStack();
- // FIXME: Take this as an argument, once all the APIs we used have moved to
- // taking it as an input instead of hard-coding llvm::errs.
- raw_ostream &OS = llvm::errs();
+ raw_ostream &OS = getVerboseOutputStream();
if (!Act.PrepareToExecute(*this))
return false;
diff --git a/unittests/Frontend/OutputStreamTest.cpp b/unittests/Frontend/OutputStreamTest.cpp
index a973582f5d..14537ecdc5 100644
--- a/unittests/Frontend/OutputStreamTest.cpp
+++ b/unittests/Frontend/OutputStreamTest.cpp
@@ -10,6 +10,7 @@
#include "clang/CodeGen/BackendUtil.h"
#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/FrontendTool/Utils.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "gtest/gtest.h"
@@ -43,4 +44,58 @@ TEST(FrontendOutputTests, TestOutputStream) {
EXPECT_TRUE(!IRBuffer.empty());
EXPECT_TRUE(StringRef(IRBuffer.data()).startswith("BC"));
}
+
+TEST(FrontendOutputTests, TestVerboseOutputStreamShared) {
+ auto Invocation = std::make_shared<CompilerInvocation>();
+ Invocation->getPreprocessorOpts().addRemappedFile(
+ "test.cc", MemoryBuffer::getMemBuffer("invalid").release());
+ Invocation->getFrontendOpts().Inputs.push_back(
+ FrontendInputFile("test.cc", Language::CXX));
+ Invocation->getFrontendOpts().ProgramAction = EmitBC;
+ Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
+ CompilerInstance Compiler;
+
+ std::string VerboseBuffer;
+ raw_string_ostream VerboseStream(VerboseBuffer);
+
+ Compiler.setInvocation(std::move(Invocation));
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ Compiler.createDiagnostics(
+ new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true);
+ Compiler.setVerboseOutputStream(VerboseStream);
+
+ bool Success = ExecuteCompilerInvocation(&Compiler);
+ EXPECT_FALSE(Success);
+ EXPECT_TRUE(!VerboseStream.str().empty());
+ EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated"));
+}
+
+TEST(FrontendOutputTests, TestVerboseOutputStreamOwned) {
+ std::string VerboseBuffer;
+ bool Success;
+ {
+ auto Invocation = std::make_shared<CompilerInvocation>();
+ Invocation->getPreprocessorOpts().addRemappedFile(
+ "test.cc", MemoryBuffer::getMemBuffer("invalid").release());
+ Invocation->getFrontendOpts().Inputs.push_back(
+ FrontendInputFile("test.cc", Language::CXX));
+ Invocation->getFrontendOpts().ProgramAction = EmitBC;
+ Invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
+ CompilerInstance Compiler;
+
+ std::unique_ptr<raw_ostream> VerboseStream =
+ std::make_unique<raw_string_ostream>(VerboseBuffer);
+
+ Compiler.setInvocation(std::move(Invocation));
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+ Compiler.createDiagnostics(
+ new TextDiagnosticPrinter(llvm::nulls(), &*DiagOpts), true);
+ Compiler.setVerboseOutputStream(std::move(VerboseStream));
+
+ Success = ExecuteCompilerInvocation(&Compiler);
+ }
+ EXPECT_FALSE(Success);
+ EXPECT_TRUE(!VerboseBuffer.empty());
+ EXPECT_TRUE(StringRef(VerboseBuffer.data()).contains("errors generated"));
+}
}