Skip to content

Commit 85d2c5f

Browse files
committed
Start/Stop trace API should print to llvm::errs() by default.
1 parent 0ebb4cc commit 85d2c5f

3 files changed

Lines changed: 75 additions & 12 deletions

File tree

lib/CppInterOp/Tracing.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,16 @@ std::string TraceInfo::writeToFile(const std::string& Version) {
6969
return std::string(Path);
7070
}
7171

72-
std::string TraceInfo::StartRegion() {
72+
std::string TraceInfo::StartRegion(bool WriteOnStdErr) {
7373
m_RegionStart = m_Log.size();
7474
m_InRegion = true;
75+
m_WriteOnStdErr = WriteOnStdErr;
76+
77+
// When streaming to stderr, skip creating a file.
78+
if (WriteOnStdErr) {
79+
m_RegionPath.clear();
80+
return "";
81+
}
7582

7683
llvm::SmallString<128> TmpDir;
7784
llvm::sys::path::system_temp_directory(/*ErasedOnReboot=*/true, TmpDir);
@@ -91,13 +98,18 @@ void TraceInfo::StopRegion(const std::string& Version) {
9198
return;
9299
m_InRegion = false;
93100

101+
// When streaming to stderr, there is no file to write.
102+
if (m_WriteOnStdErr)
103+
return;
104+
94105
std::error_code EC;
95106
llvm::raw_fd_ostream OS(m_RegionPath, EC);
96107
if (EC)
97108
return;
98109

99-
OS << "// CppInterOp trace region\n";
100110
std::string Ver = Version.empty() ? CppImpl::GetVersion() : Version;
111+
112+
OS << "// CppInterOp trace region\n";
101113
WriteVersionComment(OS, Ver);
102114
OS << "// Generated automatically.\n";
103115
OS << "#include <CppInterOp/CppInterOp.h>\n\n";

lib/CppInterOp/Tracing.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ class TraceInfo {
102102
return (it != m_HandleMap.end()) ? it->second : "nullptr";
103103
}
104104

105-
void appendToLog(const std::string& line) { m_Log.push_back(line); }
105+
void appendToLog(const std::string& line) {
106+
m_Log.push_back(line);
107+
if (m_InRegion && m_WriteOnStdErr)
108+
llvm::errs() << line << "\n";
109+
}
106110
const std::vector<std::string>& getLog() const { return m_Log; }
107111
std::string getLastLogEntry() const {
108112
return m_Log.empty() ? "" : m_Log.back();
@@ -113,13 +117,15 @@ class TraceInfo {
113117
CPPINTEROP_TRACE_API std::string writeToFile(const std::string& Version = "");
114118

115119
/// Begin a traced region. Returns the path where StopTracing will write.
116-
CPPINTEROP_TRACE_API std::string StartRegion();
120+
/// \param WriteOnStdErr if true, also emit the reproducer to stderr.
121+
CPPINTEROP_TRACE_API std::string StartRegion(bool WriteOnStdErr = true);
117122

118123
/// End the traced region and write only the region's entries to the file.
119124
CPPINTEROP_TRACE_API void StopRegion(const std::string& Version = "");
120125

121126
private:
122127
std::string m_RegionPath;
128+
bool m_WriteOnStdErr = false;
123129

124130
public:
125131
void clear() {
@@ -146,10 +152,11 @@ CPPINTEROP_TRACE_API void InitTracing();
146152

147153
/// Begin recording a traced region. If tracing is not yet active, activates
148154
/// it. Returns the path where StopTracing() will write the reproducer.
149-
inline std::string StartTracing() {
155+
/// \param WriteOnStdErr if true, also emit the reproducer to stderr on stop.
156+
inline std::string StartTracing(bool WriteOnStdErr = true) {
150157
if (!TraceInfo::TheTraceInfo)
151158
InitTracing();
152-
return TraceInfo::TheTraceInfo->StartRegion();
159+
return TraceInfo::TheTraceInfo->StartRegion(WriteOnStdErr);
153160
}
154161

155162
/// End the traced region and write the reproducer file containing only the

unittests/CppInterOp/TracingTests.cpp

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ TEST(StartTracingActivation, ActivatesIfNotActive) {
402402
TraceInfo::TheTraceInfo = nullptr;
403403

404404
// StartTracing should call InitTracing (covers line 151).
405-
std::string Path = CppInterOp::Tracing::StartTracing();
405+
std::string Path = CppInterOp::Tracing::StartTracing(/*WriteOnStdErr=*/false);
406406
ASSERT_NE(TraceInfo::TheTraceInfo, nullptr);
407407
ASSERT_FALSE(Path.empty());
408408

@@ -711,7 +711,7 @@ static std::string ReadFileToString(const std::string& path) {
711711
// This test reads source files from the build tree via CPPINTEROP_DIR.
712712
TEST_F(TracingTest, StartStopTracingWritesToFile) {
713713
// StartTracing begins recording; StopTracing writes the file.
714-
std::string Path = CppInterOp::Tracing::StartTracing();
714+
std::string Path = CppInterOp::Tracing::StartTracing(/*WriteOnStdErr=*/false);
715715
ASSERT_FALSE(Path.empty());
716716

717717
// Calls within the region are recorded.
@@ -734,7 +734,7 @@ TEST_F(TracingTest, OnlyRegionCallsAreRecorded) {
734734
// Calls before StartTracing should not appear.
735735
VoidFunc();
736736

737-
std::string Path = CppInterOp::Tracing::StartTracing();
737+
std::string Path = CppInterOp::Tracing::StartTracing(/*WriteOnStdErr=*/false);
738738
ASSERT_FALSE(Path.empty());
739739

740740
AnnotatedFunction(42);
@@ -767,7 +767,7 @@ TEST_F(TracingTest, StartTracingWithEnvVarNarrowsToRegion) {
767767
// This call is before the region.
768768
VoidFunc();
769769

770-
std::string Path = CppInterOp::Tracing::StartTracing();
770+
std::string Path = CppInterOp::Tracing::StartTracing(/*WriteOnStdErr=*/false);
771771
ASSERT_FALSE(Path.empty());
772772

773773
AnnotatedFunction(7);
@@ -786,11 +786,13 @@ TEST_F(TracingTest, StartTracingWithEnvVarNarrowsToRegion) {
786786

787787
TEST_F(TracingTest, MultipleStartStopRegions) {
788788
// Multiple regions should each produce their own file.
789-
std::string Path1 = CppInterOp::Tracing::StartTracing();
789+
std::string Path1 =
790+
CppInterOp::Tracing::StartTracing(/*WriteOnStdErr=*/false);
790791
AnnotatedFunction(1);
791792
CppInterOp::Tracing::StopTracing();
792793

793-
std::string Path2 = CppInterOp::Tracing::StartTracing();
794+
std::string Path2 =
795+
CppInterOp::Tracing::StartTracing(/*WriteOnStdErr=*/false);
794796
AnnotatedFunction(2);
795797
CppInterOp::Tracing::StopTracing();
796798

@@ -810,6 +812,48 @@ TEST_F(TracingTest, MultipleStartStopRegions) {
810812
llvm::sys::fs::remove(Path2);
811813
}
812814

815+
// ---------------------------------------------------------------------------
816+
// Tests: StartTracing WriteOnStdErr option
817+
// ---------------------------------------------------------------------------
818+
819+
TEST_F(TracingTest, WriteOnStdErrStreamsEntriesImmediately) {
820+
testing::internal::CaptureStderr();
821+
822+
// Default is WriteOnStdErr=true — no file is created.
823+
std::string Path = CppInterOp::Tracing::StartTracing();
824+
EXPECT_TRUE(Path.empty());
825+
826+
AnnotatedFunction(99);
827+
828+
// Capture stderr *before* StopTracing — the entry must already be there.
829+
std::string Mid = testing::internal::GetCapturedStderr();
830+
EXPECT_THAT(Mid, HasSubstr("Cpp::AnnotatedFunction(99)"))
831+
<< "Entry should appear on stderr immediately, not after StopTracing";
832+
833+
// Restart capture for the rest.
834+
testing::internal::CaptureStderr();
835+
VoidFunc();
836+
CppInterOp::Tracing::StopTracing("test-version");
837+
std::string Rest = testing::internal::GetCapturedStderr();
838+
EXPECT_THAT(Rest, HasSubstr("Cpp::VoidFunc()"));
839+
}
840+
841+
TEST_F(TracingTest, WriteToFileWhenStdErrDisabled) {
842+
std::string Path = CppInterOp::Tracing::StartTracing(/*WriteOnStdErr=*/false);
843+
ASSERT_FALSE(Path.empty());
844+
845+
AnnotatedFunction(77);
846+
847+
CppInterOp::Tracing::StopTracing();
848+
849+
// The file should contain the full reproducer.
850+
std::string FileContent = ReadFileToString(Path);
851+
EXPECT_THAT(FileContent, HasSubstr("#include <CppInterOp/CppInterOp.h>"));
852+
EXPECT_THAT(FileContent, HasSubstr("Cpp::AnnotatedFunction(77)"));
853+
854+
llvm::sys::fs::remove(Path);
855+
}
856+
813857
// ---------------------------------------------------------------------------
814858
// Tests: all CPPINTEROP_API functions must have INTEROP_TRACE
815859
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)