[clang] [llvm] [LLVM][Clang] Add a configurable informational output stream (PR #226056)
Anutosh Bhat via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 01:09:20 PDT 2026
https://github.com/anutosh491 updated https://github.com/llvm/llvm-project/pull/226056
>From f0c8327893c57712a8bb2590bea4479c20239219 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Thu, 24 Sep 2026 13:28:00 +0530
Subject: [PATCH] [LLVM][Clang] Add a configurable informational output stream
---
.../include/clang/Frontend/CompilerInstance.h | 2 +-
clang/include/clang/Lex/HeaderSearch.h | 3 +-
clang/lib/Driver/Compilation.cpp | 2 +-
clang/lib/Driver/Driver.cpp | 16 +++----
clang/lib/Driver/ToolChains/Darwin.cpp | 8 ++--
clang/lib/Frontend/CompilerInstance.cpp | 3 +-
clang/lib/Interpreter/Interpreter.cpp | 2 +-
clang/lib/Lex/InitHeaderSearch.cpp | 43 +++++++++++--------
clang/lib/Tooling/Tooling.cpp | 6 +--
.../IncrementalCompilerBuilderTest.cpp | 29 +++++++++++++
clang/unittests/Tooling/ToolingTest.cpp | 33 ++++++++++++++
llvm/include/llvm/Support/raw_ostream.h | 13 ++++++
llvm/lib/Support/raw_ostream.cpp | 10 +++++
llvm/unittests/Support/raw_ostream_test.cpp | 14 ++++++
14 files changed, 146 insertions(+), 38 deletions(-)
diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index 21b83dfefa842..791da205e3354 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -187,7 +187,7 @@ class CompilerInstance : public ModuleLoader {
std::unique_ptr<raw_ostream> OwnedVerboseOutputStream;
/// The stream for verbose output.
- raw_ostream *VerboseOutputStream = &llvm::errs();
+ raw_ostream *VerboseOutputStream = &llvm::infos();
/// The list of active output files.
std::list<llvm::vfs::OutputFile> OutputFiles;
diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h
index adaa126024c3c..12d2f2c745348 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -1061,7 +1061,8 @@ class HeaderSearch {
void ApplyHeaderSearchOptions(HeaderSearch &HS,
const HeaderSearchOptions &HSOpts,
const LangOptions &Lang,
- const llvm::Triple &triple);
+ const llvm::Triple &triple,
+ llvm::raw_ostream *VerboseOutput = nullptr);
void normalizeModuleCachePath(FileManager &FileMgr, StringRef Path,
SmallVectorImpl<char> &NormalizedPath);
diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index c81c4445a29f9..071284c114976 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -168,7 +168,7 @@ int Compilation::ExecuteCommand(const Command &C,
bool LogOnly) const {
if ((getDriver().CCPrintOptions ||
getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
- raw_ostream *OS = &llvm::errs();
+ raw_ostream *OS = &llvm::infos();
std::unique_ptr<llvm::raw_fd_ostream> OwnedStream;
// Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 7649941a68b1c..dc35b36fa0626 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2405,7 +2405,7 @@ int Driver::ExecuteCompilation(
SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) {
if (C.getArgs().hasArg(options::OPT_fdriver_only)) {
if (C.getArgs().hasArg(options::OPT_v))
- C.getJobs().Print(llvm::errs(), "\n", true);
+ C.getJobs().Print(llvm::infos(), "\n", true);
C.ExecuteJobs(C.getJobs(), FailingCommands, /*LogOnly=*/true);
@@ -2418,7 +2418,7 @@ int Driver::ExecuteCompilation(
// Just print if -### was present.
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) {
- C.getJobs().Print(llvm::errs(), "\n", true);
+ C.getJobs().Print(llvm::infos(), "\n", true);
return Diags.hasErrorOccurred() ? 1 : 0;
}
@@ -2682,23 +2682,23 @@ bool Driver::HandleImmediateArgs(Compilation &C) {
C.getArgs().hasArg(options::OPT_print_supported_cpus) ||
C.getArgs().hasArg(options::OPT_print_supported_extensions) ||
C.getArgs().hasArg(options::OPT_print_enabled_extensions)) {
- PrintVersion(C, llvm::errs());
+ PrintVersion(C, llvm::infos());
SuppressMissingInputWarning = true;
}
if (C.getArgs().hasArg(options::OPT_v)) {
if (!SystemConfigDir.empty())
- llvm::errs() << "System configuration file directory: "
- << SystemConfigDir << "\n";
+ llvm::infos() << "System configuration file directory: "
+ << SystemConfigDir << "\n";
if (!UserConfigDir.empty())
- llvm::errs() << "User configuration file directory: "
- << UserConfigDir << "\n";
+ llvm::infos() << "User configuration file directory: " << UserConfigDir
+ << "\n";
}
const ToolChain &TC = C.getDefaultToolChain();
if (C.getArgs().hasArg(options::OPT_v))
- TC.printVerboseInfo(llvm::errs());
+ TC.printVerboseInfo(llvm::infos());
if (C.getArgs().hasArg(options::OPT_print_resource_dir)) {
llvm::outs() << ResourceDir << '\n';
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 0fb94d8712e69..fa25cc7aab645 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -3078,8 +3078,8 @@ void AppleMachO::AddClangCXXStdlibIncludeArgs(
addSystemInclude(DriverArgs, CC1Args, InstallBin);
return;
} else if (DriverArgs.hasArg(options::OPT_v)) {
- llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
- << "\"\n";
+ llvm::infos() << "ignoring nonexistent directory \"" << InstallBin
+ << "\"\n";
}
// Otherwise, check for (2)
@@ -3089,8 +3089,8 @@ void AppleMachO::AddClangCXXStdlibIncludeArgs(
addSystemInclude(DriverArgs, CC1Args, SysrootUsr);
return;
} else if (DriverArgs.hasArg(options::OPT_v)) {
- llvm::errs() << "ignoring nonexistent directory \"" << SysrootUsr
- << "\"\n";
+ llvm::infos() << "ignoring nonexistent directory \"" << SysrootUsr
+ << "\"\n";
}
// Otherwise, don't add any path.
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 87abcd38c1a92..bf599ef9a11c2 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -504,7 +504,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
HeaderSearchTriple = &PP->getAuxTargetInfo()->getTriple();
ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(),
- PP->getLangOpts(), *HeaderSearchTriple);
+ PP->getLangOpts(), *HeaderSearchTriple,
+ &getVerboseOutputStream());
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 512b28be5a544..b32b43bd71f8a 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -277,7 +277,7 @@ IncrementalCompilerBuilder::create(std::string TT,
return std::move(Err);
if (Compilation->getArgs().hasArg(options::OPT_v))
- Compilation->getJobs().Print(llvm::errs(), "\n", /*Quote=*/false);
+ Compilation->getJobs().Print(llvm::infos(), "\n", /*Quote=*/false);
auto ErrOrCC1Args = GetCC1Arguments(&Diags, Compilation.get());
if (auto Err = ErrOrCC1Args.takeError())
diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp
index e894086b66e76..2f2d0783c2a4a 100644
--- a/clang/lib/Lex/InitHeaderSearch.cpp
+++ b/clang/lib/Lex/InitHeaderSearch.cpp
@@ -47,13 +47,16 @@ class InitHeaderSearch {
std::vector<DirectoryLookupInfo> IncludePath;
std::vector<std::pair<std::string, bool> > SystemHeaderPrefixes;
HeaderSearch &Headers;
+ llvm::raw_ostream &VerboseOutput;
bool Verbose;
std::string IncludeSysroot;
bool HasSysroot;
public:
- InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot)
- : Headers(HS), Verbose(verbose), IncludeSysroot(std::string(sysroot)),
+ InitHeaderSearch(HeaderSearch &HS, bool verbose, StringRef sysroot,
+ llvm::raw_ostream &VerboseOutput)
+ : Headers(HS), VerboseOutput(VerboseOutput), Verbose(verbose),
+ IncludeSysroot(std::string(sysroot)),
HasSysroot(!(sysroot.empty() || sysroot == "/")) {}
/// Add the specified path to the specified group list, prefixing the sysroot
@@ -165,8 +168,8 @@ bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
}
if (Verbose)
- llvm::errs() << "ignoring nonexistent directory \""
- << MappedPathStr << "\"\n";
+ VerboseOutput << "ignoring nonexistent directory \"" << MappedPathStr
+ << "\"\n";
return false;
}
@@ -282,7 +285,8 @@ void InitHeaderSearch::AddDefaultIncludePaths(
/// remove the later (dead) ones. Returns the number of non-system headers
/// removed, which is used to update NumAngled.
static unsigned RemoveDuplicates(std::vector<DirectoryLookupInfo> &SearchList,
- unsigned First, bool Verbose) {
+ unsigned First, bool Verbose,
+ llvm::raw_ostream &VerboseOutput) {
llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenDirs;
llvm::SmallPtrSet<const DirectoryEntry *, 8> SeenFrameworkDirs;
llvm::SmallPtrSet<const HeaderMap *, 8> SeenHeaderMaps;
@@ -347,11 +351,11 @@ static unsigned RemoveDuplicates(std::vector<DirectoryLookupInfo> &SearchList,
}
if (Verbose) {
- llvm::errs() << "ignoring duplicate directory \""
- << CurEntry.getName() << "\"\n";
+ VerboseOutput << "ignoring duplicate directory \"" << CurEntry.getName()
+ << "\"\n";
if (DirToRemove != i)
- llvm::errs() << " as it is a non-system directory that duplicates "
- << "a system directory\n";
+ VerboseOutput << " as it is a non-system directory that duplicates "
+ << "a system directory\n";
}
if (DirToRemove != i)
++NonSystemRemoved;
@@ -397,14 +401,14 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
SearchList.push_back(Include);
// Deduplicate and remember index.
- RemoveDuplicates(SearchList, 0, Verbose);
+ RemoveDuplicates(SearchList, 0, Verbose, VerboseOutput);
unsigned NumQuoted = SearchList.size();
for (auto &Include : IncludePath)
if (Include.Group == Angled)
SearchList.push_back(Include);
- RemoveDuplicates(SearchList, NumQuoted, Verbose);
+ RemoveDuplicates(SearchList, NumQuoted, Verbose, VerboseOutput);
unsigned NumAngled = SearchList.size();
for (auto &Include : IncludePath)
@@ -423,7 +427,8 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
// Remove duplicates across both the Angled and System directories. GCC does
// this and failing to remove duplicates across these two groups breaks
// #include_next.
- unsigned NonSystemRemoved = RemoveDuplicates(SearchList, NumQuoted, Verbose);
+ unsigned NonSystemRemoved =
+ RemoveDuplicates(SearchList, NumQuoted, Verbose, VerboseOutput);
NumAngled -= NonSystemRemoved;
Headers.SetSearchPaths(extractLookups(SearchList), NumQuoted, NumAngled,
@@ -433,10 +438,10 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
// If verbose, print the list of directories that will be searched.
if (Verbose) {
- llvm::errs() << "#include \"...\" search starts here:\n";
+ VerboseOutput << "#include \"...\" search starts here:\n";
for (unsigned i = 0, e = SearchList.size(); i != e; ++i) {
if (i == NumQuoted)
- llvm::errs() << "#include <...> search starts here:\n";
+ VerboseOutput << "#include <...> search starts here:\n";
StringRef Name = SearchList[i].Lookup.getName();
const char *Suffix;
if (SearchList[i].Lookup.isNormalDir())
@@ -447,17 +452,19 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
assert(SearchList[i].Lookup.isHeaderMap() && "Unknown DirectoryLookup");
Suffix = " (headermap)";
}
- llvm::errs() << " " << Name << Suffix << "\n";
+ VerboseOutput << " " << Name << Suffix << "\n";
}
- llvm::errs() << "End of search list.\n";
+ VerboseOutput << "End of search list.\n";
}
}
void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
const HeaderSearchOptions &HSOpts,
const LangOptions &Lang,
- const llvm::Triple &Triple) {
- InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot);
+ const llvm::Triple &Triple,
+ llvm::raw_ostream *VerboseOutput) {
+ InitHeaderSearch Init(HS, HSOpts.Verbose, HSOpts.Sysroot,
+ VerboseOutput ? *VerboseOutput : llvm::infos());
// Add the user defined entries.
for (unsigned i = 0, e = HSOpts.UserEntries.size(); i != e; ++i) {
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 71307d1fe7307..66a23476a487b 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -431,9 +431,9 @@ bool ToolInvocation::runInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
// Show the invocation, with -v.
if (Invocation->getHeaderSearchOpts().Verbose) {
- llvm::errs() << "clang Invocation:\n";
- Compilation->getJobs().Print(llvm::errs(), "\n", true);
- llvm::errs() << "\n";
+ llvm::infos() << "clang Invocation:\n";
+ Compilation->getJobs().Print(llvm::infos(), "\n", true);
+ llvm::infos() << "\n";
}
return Action->runInvocation(std::move(Invocation), Files,
diff --git a/clang/unittests/Interpreter/IncrementalCompilerBuilderTest.cpp b/clang/unittests/Interpreter/IncrementalCompilerBuilderTest.cpp
index 7b4633bfc9e7a..9acf0db563dea 100644
--- a/clang/unittests/Interpreter/IncrementalCompilerBuilderTest.cpp
+++ b/clang/unittests/Interpreter/IncrementalCompilerBuilderTest.cpp
@@ -6,11 +6,15 @@
//
//===----------------------------------------------------------------------===//
+#include "InterpreterTestFixture.h"
+
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Interpreter/Interpreter.h"
#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -18,6 +22,8 @@ using namespace clang;
namespace {
+class IncrementalCompilerBuilderInfoStreamTest : public InterpreterTestBase {};
+
// Usually FrontendAction takes the raw pointers and wraps them back into
// unique_ptrs in InitializeFileRemapping()
static void cleanupRemappedFileBuffers(CompilerInstance &CI) {
@@ -36,6 +42,29 @@ TEST(IncrementalCompilerBuilder, SetCompilerArgs) {
cleanupRemappedFileBuffers(*CI);
}
+TEST_F(IncrementalCompilerBuilderInfoStreamTest, RoutesVerboseOutputToInfos) {
+ std::string Output;
+ llvm::raw_string_ostream OS(Output);
+ llvm::setInfoOutputStream(OS);
+ llvm::scope_exit ResetInfoOutput([] { llvm::resetInfoOutputStream(); });
+
+ std::vector<const char *> ClangArgv = {"-v", "-nostdinc", "-nostdinc++"};
+ auto CB = clang::IncrementalCompilerBuilder();
+ CB.SetCompilerArgs(ClangArgv);
+
+ auto CI = cantFail(CB.CreateCpp());
+ OS.flush();
+ EXPECT_NE(Output.find("clang version"), std::string::npos);
+ EXPECT_NE(Output.find("-cc1"), std::string::npos);
+
+ auto Interp = cantFail(clang::Interpreter::create(std::move(CI)));
+ OS.flush();
+ EXPECT_NE(Output.find("clang -cc1 version"), std::string::npos);
+ EXPECT_NE(Output.find("#include \"...\" search starts here:"),
+ std::string::npos);
+ EXPECT_NE(Output.find("End of search list."), std::string::npos);
+}
+
TEST(IncrementalCompilerBuilder, SetTargetTriple) {
// FIXME : This test doesn't current work for Emscripten builds.
// It should be possible to make it work.For details on how it fails and
diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp
index 11a5491dd35fb..f210bf1c69b3c 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -22,10 +22,12 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/JSONCompilationDatabase.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "gtest/gtest.h"
#include <algorithm>
@@ -226,6 +228,37 @@ TEST(ToolInvocation, TestMapVirtualFile) {
EXPECT_TRUE(Invocation.run());
}
+TEST(ToolInvocation, RoutesVerboseOutputToInfos) {
+ auto OverlayFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
+ llvm::vfs::getRealFileSystem());
+ auto InMemoryFileSystem =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+ auto Files = llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions(),
+ OverlayFileSystem);
+ InMemoryFileSystem->addFile("test.cpp", 0,
+ llvm::MemoryBuffer::getMemBuffer("int value;\n"));
+
+ std::string Output;
+ llvm::raw_string_ostream OS(Output);
+ llvm::setInfoOutputStream(OS);
+ llvm::scope_exit ResetInfoOutput([] { llvm::resetInfoOutputStream(); });
+
+ std::vector<std::string> Args = {"tool-executable", "-v", "-fsyntax-only",
+ "test.cpp"};
+ ToolInvocation Invocation(Args, std::make_unique<SyntaxOnlyAction>(),
+ Files.get());
+
+ EXPECT_TRUE(Invocation.run());
+ OS.flush();
+ EXPECT_NE(Output.find("clang version"), std::string::npos);
+ EXPECT_NE(Output.find("clang Invocation:"), std::string::npos);
+ EXPECT_NE(Output.find("-cc1"), std::string::npos);
+ EXPECT_NE(Output.find("clang -cc1 version"), std::string::npos);
+ EXPECT_NE(Output.find("End of search list."), std::string::npos);
+}
+
TEST(ToolInvocation, TestVirtualModulesCompilation) {
// FIXME: Currently, this only tests that we don't exit with an error if a
// mapped module.modulemap is found on the include path. In the future, expand
diff --git a/llvm/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h
index 841fe90515608..f3bb68462c0d8 100644
--- a/llvm/include/llvm/Support/raw_ostream.h
+++ b/llvm/include/llvm/Support/raw_ostream.h
@@ -619,6 +619,19 @@ LLVM_ABI raw_fd_ostream &outs();
/// expected place.
LLVM_ABI raw_fd_ostream &errs();
+/// This returns the stream used for informational output. By default it is
+/// wired to errs(), preserving the traditional command-line behavior. Hosts
+/// embedding LLVM may redirect it with setInfoOutputStream().
+LLVM_ABI raw_ostream &infos();
+
+/// Redirect informational output process-wide to \p OS. Configure this before
+/// concurrent use. The caller retains ownership and must ensure that \p OS
+/// outlives its use as the informational stream.
+LLVM_ABI void setInfoOutputStream(raw_ostream &OS);
+
+/// Restore the informational output stream to errs().
+LLVM_ABI void resetInfoOutputStream();
+
/// This returns a reference to a raw_ostream which simply discards output.
LLVM_ABI raw_ostream &nulls();
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 28401d674479c..132d201643bb1 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -898,6 +898,16 @@ raw_fd_ostream &llvm::errs() {
return S;
}
+static raw_ostream *InfoOutputStream;
+
+raw_ostream &llvm::infos() {
+ return InfoOutputStream ? *InfoOutputStream : errs();
+}
+
+void llvm::setInfoOutputStream(raw_ostream &OS) { InfoOutputStream = &OS; }
+
+void llvm::resetInfoOutputStream() { InfoOutputStream = nullptr; }
+
/// nulls() - This returns a reference to a raw_ostream which discards output.
raw_ostream &llvm::nulls() {
static raw_null_ostream S;
diff --git a/llvm/unittests/Support/raw_ostream_test.cpp b/llvm/unittests/Support/raw_ostream_test.cpp
index aded02c7b3402..b00f1587e8bfc 100644
--- a/llvm/unittests/Support/raw_ostream_test.cpp
+++ b/llvm/unittests/Support/raw_ostream_test.cpp
@@ -129,6 +129,20 @@ TEST(raw_ostreamTest, Types_Unbuffered) {
EXPECT_EQ("X", printToString(X{}));
}
+TEST(raw_ostreamTest, InfoOutputStream) {
+ EXPECT_EQ(&errs(), &infos());
+
+ std::string Str;
+ raw_string_ostream OS(Str);
+ setInfoOutputStream(OS);
+ infos() << "information";
+ OS.flush();
+ EXPECT_EQ("information", Str);
+
+ resetInfoOutputStream();
+ EXPECT_EQ(&errs(), &infos());
+}
+
TEST(raw_ostreamTest, BufferEdge) {
EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 1));
EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 2));
More information about the llvm-commits
mailing list