diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp @@ -29,6 +29,10 @@ #include #include +// On Windows, the append function converts all inputs (pointers, iterators) +// to an intermediate path object, causing allocations in cases where no +// allocations are done on other platforms. + #include "test_macros.h" #include "test_iterators.h" #include "count_new.h" @@ -141,7 +145,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); Str RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS /= RHS; } assert(PathEq(LHS, E)); @@ -151,7 +155,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); StrView RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS /= RHS; } assert(PathEq(LHS, E)); @@ -161,7 +165,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); Ptr RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS /= RHS; } assert(PathEq(LHS, E)); @@ -170,7 +174,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); Ptr RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS.append(RHS, StrEnd(RHS)); } assert(PathEq(LHS, E)); @@ -189,7 +193,13 @@ // code_cvt conversions. // For "char" no allocations will be performed because no conversion is // required. + // On Windows, the append method is more complex and uses intermediate + // path objects, which causes extra allocations. +#ifdef _WIN32 + bool DisableAllocations = false; +#else bool DisableAllocations = std::is_same::value; +#endif { path LHS(L); PathReserve(LHS, ReserveSize); InputIter RHS(R); diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp @@ -29,6 +29,9 @@ #include #include +// On Windows, charset conversions cause allocations in the path class in +// cases where no allocations are done on other platforms. + #include "test_macros.h" #include "test_iterators.h" #include "count_new.h" @@ -51,7 +54,7 @@ path p; PathReserve(p, S.length() + 1); { // string provides a contiguous iterator. No allocation needed. - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); path& pref = (p = S); assert(&pref == &p); } @@ -63,7 +66,7 @@ const std::basic_string S(TestPath); path p; PathReserve(p, S.length() + 1); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); path& pref = p.assign(S); assert(&pref == &p); } @@ -77,7 +80,7 @@ path p; PathReserve(p, S.length() + 1); { // string provides a contiguous iterator. No allocation needed. - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); path& pref = (p = S); assert(&pref == &p); } @@ -89,7 +92,7 @@ const std::basic_string_view S(TestPath); path p; PathReserve(p, S.length() + 1); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); path& pref = p.assign(S); assert(&pref == &p); } @@ -104,7 +107,7 @@ { // char* pointers are contiguous and can be used with code_cvt directly. // no allocations needed. - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); path& pref = (p = TestPath); assert(&pref == &p); } @@ -114,7 +117,7 @@ { path p; PathReserve(p, Size + 1); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); path& pref = p.assign(TestPath); assert(&pref == &p); } @@ -124,7 +127,7 @@ { path p; PathReserve(p, Size + 1); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); path& pref = p.assign(TestPath, TestPathEnd); assert(&pref == &p); } diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp @@ -36,6 +36,9 @@ #include #include +// On Windows, charset conversions cause allocations in the path class in +// cases where no allocations are done on other platforms. + #include "test_macros.h" #include "test_iterators.h" #include "count_new.h" @@ -98,7 +101,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); Str RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS += RHS; } assert(LHS == E); @@ -108,7 +111,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); StrView RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS += RHS; } assert(LHS == E); @@ -118,7 +121,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); Ptr RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS += RHS; } assert(LHS == E); @@ -127,7 +130,7 @@ path LHS(L); PathReserve(LHS, ReserveSize); Ptr RHS(R); { - DisableAllocationGuard g; + TEST_NOT_WIN32(DisableAllocationGuard g); LHS.concat(RHS, StrEnd(RHS)); } assert(LHS == E); @@ -135,9 +138,9 @@ // input iterator - For non-native char types, appends needs to copy the // iterator range into a contiguous block of memory before it can perform the // code_cvt conversions. - // For "char" no allocations will be performed because no conversion is - // required. - bool DisableAllocations = std::is_same::value; + // For the path native type, no allocations will be performed because no + // conversion is required. + bool DisableAllocations = std::is_same::value; { path LHS(L); PathReserve(LHS, ReserveSize); InputIter RHS(R); diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.native.obs/string_alloc.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.native.obs/string_alloc.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.native.obs/string_alloc.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.native.obs/string_alloc.pass.cpp @@ -44,8 +44,18 @@ using Alloc = std::allocator; Ptr value = MS; const path p((const char*)MS); +#ifdef _WIN32 + // On Windows, charset conversions cause allocations outside of the + // provided allocator, but accessing the native type should work without + // extra allocations. + bool DisableAllocations = std::is_same::value; +#else + // On other platforms, these methods only use the provided allocator, and + // no extra allocations should be done. + bool DisableAllocations = true; +#endif { - DisableAllocationGuard g; + DisableAllocationGuard g(DisableAllocations); Str s = p.string(); assert(s == value); Str s2 = p.string(Alloc{}); @@ -56,7 +66,7 @@ { using Traits = std::char_traits; using AStr = std::basic_string; - DisableAllocationGuard g; + DisableAllocationGuard g(DisableAllocations); AStr s = p.string(); assert(s == value); assert(MAlloc::alloc_count == 0); @@ -66,7 +76,7 @@ { // Other allocator - provided copy using Traits = std::char_traits; using AStr = std::basic_string; - DisableAllocationGuard g; + DisableAllocationGuard g(DisableAllocations); MAlloc a; // don't allow another allocator to be default constructed. MAlloc::disable_default_constructor = true; @@ -94,10 +104,21 @@ } using MAlloc = malloc_allocator; MAlloc::reset(); +#ifdef _WIN32 + // On Windows, charset conversions cause allocations outside of the + // provided allocator, but accessing the native type should work without + // extra allocations. + bool DisableAllocations = std::is_same::value; +#else + // On other platforms, these methods only use the provided allocator, and + // no extra allocations should be done. + bool DisableAllocations = true; +#endif + { // Other allocator - default construct using Traits = std::char_traits; using AStr = std::basic_string; - DisableAllocationGuard g; + DisableAllocationGuard g(DisableAllocations); AStr s = p.string(); assert(s == value); assert(MAlloc::alloc_count > 0); @@ -107,7 +128,7 @@ { // Other allocator - provided copy using Traits = std::char_traits; using AStr = std::basic_string; - DisableAllocationGuard g; + DisableAllocationGuard g(DisableAllocations); MAlloc a; // don't allow another allocator to be default constructed. MAlloc::disable_default_constructor = true; diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -371,6 +371,12 @@ #define TEST_NOINLINE #endif +#ifdef _WIN32 +#define TEST_NOT_WIN32(...) ((void)0) +#else +#define TEST_NOT_WIN32(...) __VA_ARGS__ +#endif + #if defined(__GNUC__) #pragma GCC diagnostic pop #endif