From dbf5d4953dc48638a072ad7e95306ef8ad215692 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Mon, 9 Mar 2026 15:25:20 +0800 Subject: [PATCH 01/16] Make DispatchInitializer thread-safe using function-local static --- unittests/CppInterOp/Utils.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/unittests/CppInterOp/Utils.cpp b/unittests/CppInterOp/Utils.cpp index d603737da..4647f79c8 100644 --- a/unittests/CppInterOp/Utils.cpp +++ b/unittests/CppInterOp/Utils.cpp @@ -35,8 +35,12 @@ struct DispatchInitializer { DispatchInitializer(DispatchInitializer&&) noexcept = default; DispatchInitializer& operator=(DispatchInitializer&&) noexcept = default; }; -// FIXME: Make this threadsafe by moving it as a function static. -DispatchInitializer g_dispatch_init; +// Thread-safe initialization using function-local static +static DispatchInitializer& GetDispatchInitializer() { + static DispatchInitializer instance; + return instance; +} +static DispatchInitializer& g_dispatch_init = GetDispatchInitializer(); } // namespace #endif From 68e4ba37b798a5beda298bf4e2095e0aa6a8662e Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Tue, 10 Mar 2026 13:28:15 +0800 Subject: [PATCH 02/16] Address clang-tidy warnings --- unittests/CppInterOp/Utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/CppInterOp/Utils.cpp b/unittests/CppInterOp/Utils.cpp index 4647f79c8..137bfe8ab 100644 --- a/unittests/CppInterOp/Utils.cpp +++ b/unittests/CppInterOp/Utils.cpp @@ -36,11 +36,11 @@ struct DispatchInitializer { DispatchInitializer& operator=(DispatchInitializer&&) noexcept = default; }; // Thread-safe initialization using function-local static -static DispatchInitializer& GetDispatchInitializer() { +DispatchInitializer& GetDispatchInitializer() { static DispatchInitializer instance; return instance; } -static DispatchInitializer& g_dispatch_init = GetDispatchInitializer(); +DispatchInitializer& g_dispatch_init = GetDispatchInitializer(); } // namespace #endif From d406e0c2ed8f03cb4e4b5aa948e40adeb11da647 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Wed, 11 Mar 2026 11:51:57 +0800 Subject: [PATCH 03/16] Move DispatchInitializer to function static for thread safety --- unittests/CppInterOp/Utils.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/unittests/CppInterOp/Utils.cpp b/unittests/CppInterOp/Utils.cpp index 137bfe8ab..0483ed0aa 100644 --- a/unittests/CppInterOp/Utils.cpp +++ b/unittests/CppInterOp/Utils.cpp @@ -40,7 +40,6 @@ DispatchInitializer& GetDispatchInitializer() { static DispatchInitializer instance; return instance; } -DispatchInitializer& g_dispatch_init = GetDispatchInitializer(); } // namespace #endif From 860daa430dc9c3eee8fce2450e847caa3f38ee0a Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Wed, 11 Mar 2026 16:00:32 +0800 Subject: [PATCH 04/16] Fix global initialization to satisfy clang-tidy --- unittests/CppInterOp/Utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/CppInterOp/Utils.cpp b/unittests/CppInterOp/Utils.cpp index 0483ed0aa..6f0d46369 100644 --- a/unittests/CppInterOp/Utils.cpp +++ b/unittests/CppInterOp/Utils.cpp @@ -40,6 +40,7 @@ DispatchInitializer& GetDispatchInitializer() { static DispatchInitializer instance; return instance; } +const DispatchInitializer& g_dispatch_init = GetDispatchInitializer(); } // namespace #endif From 45d4e9ee665c8fd498501326e9722e7029130e79 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Sat, 14 Mar 2026 11:42:08 +0800 Subject: [PATCH 05/16] [tests] Add edge case coverage for CopyIncludePaths in Paths.cpp --- unittests/CppInterOp/CMakeLists.txt | 1 + unittests/CppInterOp/PathsTest.cpp | 39 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 unittests/CppInterOp/PathsTest.cpp diff --git a/unittests/CppInterOp/CMakeLists.txt b/unittests/CppInterOp/CMakeLists.txt index 92ce2fdab..ba34cd1f2 100644 --- a/unittests/CppInterOp/CMakeLists.txt +++ b/unittests/CppInterOp/CMakeLists.txt @@ -21,6 +21,7 @@ add_cppinterop_unittest(CppInterOpTests TypeReflectionTest.cpp Utils.cpp VariableReflectionTest.cpp + PathsTest.cpp ${EXTRA_TEST_SOURCE_FILES} ) diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp new file mode 100644 index 000000000..61126c8c1 --- /dev/null +++ b/unittests/CppInterOp/PathsTest.cpp @@ -0,0 +1,39 @@ +#include "gtest/gtest.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "llvm/ADT/SmallVector.h" +#include +#include + + +#include "../../lib/CppInterOp/Paths.h" + +namespace { + +TEST(PathsTest, CopyIncludePathsEdgeCases) { + clang::HeaderSearchOptions Opts; + + // Set up edge-case flags to trigger uncovered branches + Opts.ModuleCachePath = "/tmp/fake_cache"; // Triggers -fmodule-cache-path + Opts.UseStandardSystemIncludes = false; // Triggers -nostdinc + Opts.UseStandardCXXIncludes = false; // Triggers -nostdinc++ + Opts.UseLibcxx = true; // Triggers -stdlib=libc++ + Opts.Verbose = true; // Triggers -v + + llvm::SmallVector IncPaths; + + CppInternal::utils::CopyIncludePaths(Opts, IncPaths, true, true); + + auto Contains = [&](const std::string& flag) { + return std::find(IncPaths.begin(), IncPaths.end(), flag) != IncPaths.end(); + }; + + // Verify the results + EXPECT_TRUE(Contains("-fmodule-cache-path")); + EXPECT_TRUE(Contains("/tmp/fake_cache")); + EXPECT_TRUE(Contains("-nostdinc")); + EXPECT_TRUE(Contains("-nostdinc++")); + EXPECT_TRUE(Contains("-stdlib=libc++")); + EXPECT_TRUE(Contains("-v")); +} + +} // end anonymous namespace \ No newline at end of file From 6ded7c3cbcc1d0b349b8bb70f677b0bfb5a5ea45 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Sat, 14 Mar 2026 11:58:38 +0800 Subject: [PATCH 06/16] chore: revert accidental changes to unittests Utils.cpp --- unittests/CppInterOp/Utils.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/unittests/CppInterOp/Utils.cpp b/unittests/CppInterOp/Utils.cpp index 6f0d46369..d603737da 100644 --- a/unittests/CppInterOp/Utils.cpp +++ b/unittests/CppInterOp/Utils.cpp @@ -35,12 +35,8 @@ struct DispatchInitializer { DispatchInitializer(DispatchInitializer&&) noexcept = default; DispatchInitializer& operator=(DispatchInitializer&&) noexcept = default; }; -// Thread-safe initialization using function-local static -DispatchInitializer& GetDispatchInitializer() { - static DispatchInitializer instance; - return instance; -} -const DispatchInitializer& g_dispatch_init = GetDispatchInitializer(); +// FIXME: Make this threadsafe by moving it as a function static. +DispatchInitializer g_dispatch_init; } // namespace #endif From 673ed62f93afba7081d59e5345b0c7c9b15789bb Mon Sep 17 00:00:00 2001 From: Caevan Lin Date: Sat, 14 Mar 2026 15:41:03 +0800 Subject: [PATCH 07/16] sort #includes properly Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- unittests/CppInterOp/PathsTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp index 61126c8c1..3eaa7c2e4 100644 --- a/unittests/CppInterOp/PathsTest.cpp +++ b/unittests/CppInterOp/PathsTest.cpp @@ -3,6 +3,7 @@ #include "llvm/ADT/SmallVector.h" #include #include +#include #include "../../lib/CppInterOp/Paths.h" From cad8558023f60f3e3392c02dc5b61403cc0b1565 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Sat, 14 Mar 2026 18:25:59 +0800 Subject: [PATCH 08/16] fix: export CopyIncludePaths with CPPINTEROP_API --- lib/CppInterOp/Paths.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CppInterOp/Paths.h b/lib/CppInterOp/Paths.h index 46948ae87..58adb18ed 100644 --- a/lib/CppInterOp/Paths.h +++ b/lib/CppInterOp/Paths.h @@ -113,7 +113,7 @@ void LogNonExistentDirectory(llvm::StringRef Path); /// defining header search behavior will be included in incpaths, e.g. /// "-nostdinc". /// -void CopyIncludePaths(const clang::HeaderSearchOptions& Opts, +CPPINTEROP_API void CopyIncludePaths(const clang::HeaderSearchOptions& Opts, llvm::SmallVectorImpl& Paths, bool WithSystem, bool WithFlags); From 6d21c1487106df9408f47577ef974900f363fa37 Mon Sep 17 00:00:00 2001 From: Caevan Lin Date: Sat, 14 Mar 2026 18:30:35 +0800 Subject: [PATCH 09/16] Apply suggestion from @github-actions[bot] Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- unittests/CppInterOp/PathsTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp index 3eaa7c2e4..bd9567397 100644 --- a/unittests/CppInterOp/PathsTest.cpp +++ b/unittests/CppInterOp/PathsTest.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "../../lib/CppInterOp/Paths.h" From 26d173c009c7de282f41d1bb04e61a1c8f3c549b Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Sat, 14 Mar 2026 18:35:36 +0800 Subject: [PATCH 10/16] style: clean up duplicated includes from bot suggestions --- unittests/CppInterOp/PathsTest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp index bd9567397..5d26c5c10 100644 --- a/unittests/CppInterOp/PathsTest.cpp +++ b/unittests/CppInterOp/PathsTest.cpp @@ -1,10 +1,9 @@ #include "gtest/gtest.h" #include "clang/Lex/HeaderSearchOptions.h" #include "llvm/ADT/SmallVector.h" -#include + #include #include -#include #include "../../lib/CppInterOp/Paths.h" From 9525d862e3dfaaaa520bb2bbe859a6b58e6c9b8a Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Sun, 15 Mar 2026 10:16:19 +0800 Subject: [PATCH 11/16] fix: include CppInterOp.h for CPPINTEROP_API macro definition --- lib/CppInterOp/Paths.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/CppInterOp/Paths.h b/lib/CppInterOp/Paths.h index 58adb18ed..25605a41c 100644 --- a/lib/CppInterOp/Paths.h +++ b/lib/CppInterOp/Paths.h @@ -10,8 +10,11 @@ #ifndef CPPINTEROP_UTILS_PATHS_H #define CPPINTEROP_UTILS_PATHS_H +#include "CppInterOp/CppInterOp.h" + #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" + #include #include From d4655bb1da78079d81c5cf5169f041129d3cb7f7 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Mon, 16 Mar 2026 10:58:13 +0800 Subject: [PATCH 12/16] test: rewrite PathsTest to use public CppInterOp API --- lib/CppInterOp/Paths.h | 4 +--- unittests/CppInterOp/PathsTest.cpp | 36 +++++++++++++----------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/lib/CppInterOp/Paths.h b/lib/CppInterOp/Paths.h index 25605a41c..c2b3e7efd 100644 --- a/lib/CppInterOp/Paths.h +++ b/lib/CppInterOp/Paths.h @@ -10,8 +10,6 @@ #ifndef CPPINTEROP_UTILS_PATHS_H #define CPPINTEROP_UTILS_PATHS_H -#include "CppInterOp/CppInterOp.h" - #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -116,7 +114,7 @@ void LogNonExistentDirectory(llvm::StringRef Path); /// defining header search behavior will be included in incpaths, e.g. /// "-nostdinc". /// -CPPINTEROP_API void CopyIncludePaths(const clang::HeaderSearchOptions& Opts, + void CopyIncludePaths(const clang::HeaderSearchOptions& Opts, llvm::SmallVectorImpl& Paths, bool WithSystem, bool WithFlags); diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp index 5d26c5c10..94445d792 100644 --- a/unittests/CppInterOp/PathsTest.cpp +++ b/unittests/CppInterOp/PathsTest.cpp @@ -1,40 +1,36 @@ #include "gtest/gtest.h" -#include "clang/Lex/HeaderSearchOptions.h" -#include "llvm/ADT/SmallVector.h" +#include "CppInterOp/CppInterOp.h" #include #include - - -#include "../../lib/CppInterOp/Paths.h" +#include namespace { -TEST(PathsTest, CopyIncludePathsEdgeCases) { - clang::HeaderSearchOptions Opts; +TEST(PathsTest, GetIncludePathsEdgeCases) { + std::vector InterpArgs = { + "PathsTest", + "-fmodule-cache-path=/tmp/fake_cache", + "-nostdinc", + "-nostdinc++", + "-stdlib=libc++", + "-v" + }; - // Set up edge-case flags to trigger uncovered branches - Opts.ModuleCachePath = "/tmp/fake_cache"; // Triggers -fmodule-cache-path - Opts.UseStandardSystemIncludes = false; // Triggers -nostdinc - Opts.UseStandardCXXIncludes = false; // Triggers -nostdinc++ - Opts.UseLibcxx = true; // Triggers -stdlib=libc++ - Opts.Verbose = true; // Triggers -v - - llvm::SmallVector IncPaths; + Cpp::CreateInterpreter(InterpArgs); - CppInternal::utils::CopyIncludePaths(Opts, IncPaths, true, true); + std::vector IncPaths; + Cpp::GetIncludePaths(IncPaths, true, true); auto Contains = [&](const std::string& flag) { return std::find(IncPaths.begin(), IncPaths.end(), flag) != IncPaths.end(); }; - // Verify the results - EXPECT_TRUE(Contains("-fmodule-cache-path")); - EXPECT_TRUE(Contains("/tmp/fake_cache")); + EXPECT_TRUE(Contains("-fmodule-cache-path=/tmp/fake_cache") || Contains("-fmodule-cache-path")); EXPECT_TRUE(Contains("-nostdinc")); EXPECT_TRUE(Contains("-nostdinc++")); EXPECT_TRUE(Contains("-stdlib=libc++")); EXPECT_TRUE(Contains("-v")); } -} // end anonymous namespace \ No newline at end of file +} \ No newline at end of file From afbcec729fd944b25425fab0fca6ba25994db45e Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Mon, 16 Mar 2026 11:01:06 +0800 Subject: [PATCH 13/16] chore: remove extra space --- lib/CppInterOp/Paths.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CppInterOp/Paths.h b/lib/CppInterOp/Paths.h index c2b3e7efd..3e9e741ee 100644 --- a/lib/CppInterOp/Paths.h +++ b/lib/CppInterOp/Paths.h @@ -114,7 +114,7 @@ void LogNonExistentDirectory(llvm::StringRef Path); /// defining header search behavior will be included in incpaths, e.g. /// "-nostdinc". /// - void CopyIncludePaths(const clang::HeaderSearchOptions& Opts, +void CopyIncludePaths(const clang::HeaderSearchOptions& Opts, llvm::SmallVectorImpl& Paths, bool WithSystem, bool WithFlags); From 81f0002f5b8803df1a99164593500ec3f09701a7 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Mon, 16 Mar 2026 18:30:11 +0800 Subject: [PATCH 14/16] test: fix Clang arguments in PathsTest to test edge cases safely --- unittests/CppInterOp/PathsTest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp index 94445d792..d70167182 100644 --- a/unittests/CppInterOp/PathsTest.cpp +++ b/unittests/CppInterOp/PathsTest.cpp @@ -9,7 +9,8 @@ namespace { TEST(PathsTest, GetIncludePathsEdgeCases) { std::vector InterpArgs = { - "PathsTest", + "-xcc++", + "-", "-fmodule-cache-path=/tmp/fake_cache", "-nostdinc", "-nostdinc++", From 9cdf9498666e5683693c90c54e3cf1a12275d590 Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Tue, 17 Mar 2026 12:12:11 +0800 Subject: [PATCH 15/16] test: implement genuine edge case tests via CreateInterpreter without stdin hangs --- unittests/CppInterOp/PathsTest.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp index d70167182..3e3e8061c 100644 --- a/unittests/CppInterOp/PathsTest.cpp +++ b/unittests/CppInterOp/PathsTest.cpp @@ -9,12 +9,10 @@ namespace { TEST(PathsTest, GetIncludePathsEdgeCases) { std::vector InterpArgs = { - "-xcc++", - "-", - "-fmodule-cache-path=/tmp/fake_cache", "-nostdinc", "-nostdinc++", "-stdlib=libc++", + "-fmodule-cache-path=/tmp/fake_cache", "-v" }; From c2e75494d895f2576947f609d03e6015cfc3726e Mon Sep 17 00:00:00 2001 From: voyager-jhk Date: Sat, 21 Mar 2026 18:51:10 +0800 Subject: [PATCH 16/16] Refactor PathsTest: Remove destructive flags (-nostdinc) --- unittests/CppInterOp/PathsTest.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/unittests/CppInterOp/PathsTest.cpp b/unittests/CppInterOp/PathsTest.cpp index 3e3e8061c..4b9b79837 100644 --- a/unittests/CppInterOp/PathsTest.cpp +++ b/unittests/CppInterOp/PathsTest.cpp @@ -9,11 +9,7 @@ namespace { TEST(PathsTest, GetIncludePathsEdgeCases) { std::vector InterpArgs = { - "-nostdinc", - "-nostdinc++", - "-stdlib=libc++", "-fmodule-cache-path=/tmp/fake_cache", - "-v" }; Cpp::CreateInterpreter(InterpArgs); @@ -25,11 +21,10 @@ TEST(PathsTest, GetIncludePathsEdgeCases) { return std::find(IncPaths.begin(), IncPaths.end(), flag) != IncPaths.end(); }; - EXPECT_TRUE(Contains("-fmodule-cache-path=/tmp/fake_cache") || Contains("-fmodule-cache-path")); - EXPECT_TRUE(Contains("-nostdinc")); - EXPECT_TRUE(Contains("-nostdinc++")); - EXPECT_TRUE(Contains("-stdlib=libc++")); - EXPECT_TRUE(Contains("-v")); + bool hasModuleCache = Contains("-fmodule-cache-path=/tmp/fake_cache") || + (Contains("-fmodule-cache-path") && Contains("/tmp/fake_cache")); + + EXPECT_TRUE(hasModuleCache); } } \ No newline at end of file