https://github.com/anutosh491 updated 
https://github.com/llvm/llvm-project/pull/226056

>From e9f405061c36df91b8a9f8c138967eb8b5318e44 Mon Sep 17 00:00:00 2001
From: anutosh491 <[email protected]>
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        | 30 +++++++++++++
 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, 147 insertions(+), 38 deletions(-)

diff --git a/clang/include/clang/Frontend/CompilerInstance.h 
b/clang/include/clang/Frontend/CompilerInstance.h
index 21b83dfefa8426..791da205e3354f 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 adaa126024c3ca..12d2f2c745348c 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 c81c4445a29f95..071284c1149761 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 7649941a68b1cc..dc35b36fa06269 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 0fb94d8712e69f..fa25cc7aab645d 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 87abcd38c1a927..bf599ef9a11c25 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 512b28be5a544e..b32b43bd71f8a8 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 e894086b66e76d..2f2d0783c2a4a8 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 71307d1fe73076..66a23476a487b4 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 7b4633bfc9e7a3..8e3bbeca1c9cda 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,9 @@ 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 +43,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 11a5491dd35fb1..36e9c7dd2e9f97 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -21,11 +21,13 @@
 #include "clang/Tooling/ArgumentsAdjusters.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "clang/Tooling/JSONCompilationDatabase.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/STLExtras.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 841fe90515608e..f3bb68462c0d83 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 28401d674479cc..132d201643bb17 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 aded02c7b34027..b00f1587e8bfc4 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));

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to