From 2baf519ac42147c9a4e48ed82da73969e5bcbdd0 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 12 Mar 2021 01:15:08 -0800 Subject: [PATCH 001/305] Filter non WinRT types out of the cache (#888) * Populate winmd cache with only WinRT types * Update to latest WinMD library and filter incremental visualizer loads --- cppwinrt/cppwinrt.vcxproj | 4 ++-- cppwinrt/main.cpp | 2 +- cppwinrt/packages.config | 2 +- natvis/cppwinrt_visualizer.cpp | 4 ++-- natvis/cppwinrtvisualizer.vcxproj | 4 ++-- natvis/packages.config | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index d63b2ce54..2ddeea321 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -1,6 +1,6 @@ - + Debug @@ -356,6 +356,6 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index c0a2721cd..79880dfab 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -260,7 +260,7 @@ Where is one or more of: } process_args(args); - cache c{ get_files_to_cache() }; + cache c{ get_files_to_cache(), [](TypeDef const& type) { return type.Flags().WindowsRuntime(); } }; remove_foundation_types(c); build_filters(c); settings.base = settings.base || (!settings.component && settings.projection_filter.empty()); diff --git a/cppwinrt/packages.config b/cppwinrt/packages.config index ca579bc7e..518e14678 100644 --- a/cppwinrt/packages.config +++ b/cppwinrt/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index b5ddf6438..1e2539910 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -105,7 +105,7 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie if (std::find(db_files.begin(), db_files.end(), path_string) == db_files.end()) { - db->add_database(path_string); + db->add_database(path_string, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); }); db_files.push_back(path_string); } } @@ -165,7 +165,7 @@ cppwinrt_visualizer::cppwinrt_visualizer() db_files.push_back(file.path().string()); } } - db.reset(new cache(db_files)); + db.reset(new cache(db_files, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); })); } catch (...) { diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index 3662a89bc..ae9721002 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -1,6 +1,6 @@ - + Debug @@ -261,6 +261,6 @@ - + \ No newline at end of file diff --git a/natvis/packages.config b/natvis/packages.config index d3148d18d..23e5fb359 100644 --- a/natvis/packages.config +++ b/natvis/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file From 0cd75f40d3d5fc8385c30dc261bc85d02c6d2cb7 Mon Sep 17 00:00:00 2001 From: Alexander Sklar Date: Fri, 12 Mar 2021 05:56:53 -0800 Subject: [PATCH 002/305] use app manifest (#882) --- cppwinrt/app.manifest | 8 ++++++++ cppwinrt/cppwinrt.vcxproj | 6 ++++++ cppwinrt/cppwinrt.vcxproj.filters | 3 +++ cppwinrt/main.cpp | 3 --- 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 cppwinrt/app.manifest diff --git a/cppwinrt/app.manifest b/cppwinrt/app.manifest new file mode 100644 index 000000000..16b477c20 --- /dev/null +++ b/cppwinrt/app.manifest @@ -0,0 +1,8 @@ + + + + + true + + + \ No newline at end of file diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 2ddeea321..ee4fd3f3a 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -111,6 +111,9 @@ + + + 15.0 {D613FB39-5035-4043-91E2-BAB323908AF4} @@ -265,6 +268,9 @@ + + app.manifest;%(AdditionalManifestFiles) + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 21fabf0f2..7720e5dfc 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -175,4 +175,7 @@ + + + \ No newline at end of file diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 79880dfab..4c61daf8d 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -8,7 +8,6 @@ #include "component_writers.h" #include "file_writers.h" #include "type_writers.h" -#include namespace cppwinrt { @@ -375,7 +374,5 @@ Where is one or more of: int main(int const argc, char** argv) { - // Dynamically enable long path support - ((unsigned char*)(NtCurrentTeb()->ProcessEnvironmentBlock))[3] |= 0x80; return cppwinrt::run(argc, argv); } From c70d9382d647bf7545610346000d92a29951987c Mon Sep 17 00:00:00 2001 From: Arthur Biancarelli Date: Fri, 12 Mar 2021 17:28:26 +0100 Subject: [PATCH 003/305] Fix support for x86 builds with Clang (#889) --- strings/base_coroutine_threadpool.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 7cdeb9514..699c39eef 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -85,21 +85,24 @@ namespace winrt::impl check_hresult(context->ContextCallback(resume_apartment_callback, &args, guid_of(), 5, nullptr)); } + struct threadpool_resume + { + threadpool_resume(com_ptr const& context, coroutine_handle<> handle) : + m_context(context), m_handle(handle) { } + com_ptr m_context; + coroutine_handle<> m_handle; + }; + + inline void __stdcall fallback_submit_threadpool_callback(void*, void* p) noexcept + { + std::unique_ptr state{ static_cast(p) }; + resume_apartment_sync(state->m_context, state->m_handle); + } + inline void resume_apartment_on_threadpool(com_ptr const& context, coroutine_handle<> handle) { - struct threadpool_resume - { - threadpool_resume(com_ptr const& context, coroutine_handle<> handle) : - m_context(context), m_handle(handle) { } - com_ptr m_context; - coroutine_handle<> m_handle; - }; auto state = std::make_unique(context, handle); - submit_threadpool_callback([](void*, void* p) - { - std::unique_ptr state{ static_cast(p) }; - resume_apartment_sync(state->m_context, state->m_handle); - }, state.get()); + submit_threadpool_callback(fallback_submit_threadpool_callback, state.get()); state.release(); } From d61cb159be7b0a31ae8e82970aabedf9fcb2fda9 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Thu, 18 Mar 2021 06:42:39 -0700 Subject: [PATCH 004/305] Use compiler-specific WINRT_IMPL_NOINLINE macro for noinline functions (#893) --- strings/base_activation.h | 4 ++-- strings/base_com_ptr.h | 2 +- strings/base_error.h | 6 +++--- strings/base_macros.h | 8 ++++++++ strings/base_windows.h | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index 704caf805..6cb312581 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -26,7 +26,7 @@ namespace winrt::impl template - __declspec(noinline) hresult get_runtime_activation_factory_impl(param::hstring const& name, winrt::guid const& guid, void** result) noexcept + WINRT_IMPL_NOINLINE hresult get_runtime_activation_factory_impl(param::hstring const& name, winrt::guid const& guid, void** result) noexcept { if (winrt_activation_handler) { @@ -339,7 +339,7 @@ namespace winrt::impl struct factory_cache_entry : factory_cache_entry_base { template - __declspec(noinline) auto call(F&& callback) + WINRT_IMPL_NOINLINE auto call(F&& callback) { #ifdef WINRT_DIAGNOSTICS get_diagnostics_info().add_factory(); diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 82b082387..d8b86d2c8 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -214,7 +214,7 @@ WINRT_EXPORT namespace winrt } } - __declspec(noinline) void unconditional_release_ref() noexcept + WINRT_IMPL_NOINLINE void unconditional_release_ref() noexcept { std::exchange(m_ptr, {})->Release(); } diff --git a/strings/base_error.h b/strings/base_error.h index 3bd58b7b2..7330e05a6 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -433,7 +433,7 @@ WINRT_EXPORT namespace winrt hresult_canceled(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi) {} }; - [[noreturn]] inline __declspec(noinline) void throw_hresult(hresult const result) + [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result) { if (winrt_throw_hresult_handler) { @@ -513,7 +513,7 @@ WINRT_EXPORT namespace winrt throw hresult_error(result, take_ownership_from_abi); } - inline __declspec(noinline) hresult to_hresult() noexcept + inline WINRT_IMPL_NOINLINE hresult to_hresult() noexcept { if (winrt_to_hresult_handler) { @@ -546,7 +546,7 @@ WINRT_EXPORT namespace winrt } } - inline __declspec(noinline) hstring to_message() + inline WINRT_IMPL_NOINLINE hstring to_message() { if (winrt_to_message_handler) { diff --git a/strings/base_macros.h b/strings/base_macros.h index 37fcc1a88..92f746699 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -45,6 +45,14 @@ #undef _WINDOWS_NUMERICS_END_NAMESPACE_ #endif +#if defined(_MSC_VER) +#define WINRT_IMPL_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) +#define WINRT_IMPL_NOINLINE __attribute__((noinline)) +#else +#define WINRT_IMPL_NOINLINE +#endif + #ifdef __IUnknown_INTERFACE_DEFINED__ #define WINRT_IMPL_IUNKNOWN_DEFINED #endif diff --git a/strings/base_windows.h b/strings/base_windows.h index 006131c2f..6da4c394a 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -257,7 +257,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } } - __declspec(noinline) void unconditional_release_ref() noexcept + WINRT_IMPL_NOINLINE void unconditional_release_ref() noexcept { std::exchange(m_ptr, {})->Release(); } From 1502e293d6e8f0a2c017431f6cf186d1551202fe Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 22 Mar 2021 06:04:24 -0700 Subject: [PATCH 005/305] Restore Win7 compat by using old versions of threadpool functions (#895) --- strings/base_coroutine_threadpool.h | 12 ++++++------ strings/base_extern.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 699c39eef..5b1ab421b 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -414,7 +414,7 @@ WINRT_EXPORT namespace winrt m_handle = handle; m_timer.attach(check_pointer(WINRT_IMPL_CreateThreadpoolTimer(callback, this, nullptr))); int64_t relative_count = -m_duration.count(); - WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), &relative_count, 0, 0); + WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); state expected = state::idle; if (!m_state.compare_exchange_strong(expected, state::pending, std::memory_order_release)) @@ -435,10 +435,10 @@ WINRT_EXPORT namespace winrt void fire_immediately() noexcept { - if (WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), nullptr, 0, 0)) + if (WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), nullptr, 0, 0)) { int64_t now = 0; - WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), &now, 0, 0); + WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); } } @@ -513,7 +513,7 @@ WINRT_EXPORT namespace winrt m_wait.attach(check_pointer(WINRT_IMPL_CreateThreadpoolWait(callback, this, nullptr))); int64_t relative_count = -m_timeout.count(); int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; - WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), m_handle, file_time, nullptr); + WINRT_IMPL_SetThreadpoolWait(m_wait.get(), m_handle, file_time); state expected = state::idle; if (!m_state.compare_exchange_strong(expected, state::pending, std::memory_order_release)) @@ -535,10 +535,10 @@ WINRT_EXPORT namespace winrt void fire_immediately() noexcept { - if (WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), nullptr, nullptr, nullptr)) + if (WINRT_IMPL_SetThreadpoolWait(m_wait.get(), nullptr, nullptr)) { int64_t now = 0; - WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now, nullptr); + WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); } } diff --git a/strings/base_extern.h b/strings/base_extern.h index 9fa9bf44e..7d31186d8 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -65,10 +65,10 @@ extern "C" int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept; winrt::impl::ptp_timer __stdcall WINRT_IMPL_CreateThreadpoolTimer(void(__stdcall *callback)(void*, void* context, void*), void* context, void*) noexcept; - int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept; + int32_t __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept; void __stdcall WINRT_IMPL_CloseThreadpoolTimer(winrt::impl::ptp_timer timer) noexcept; winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, uint32_t result), void* context, void*) noexcept; - int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait wait, void* handle, void* timeout, void* reserved) noexcept; + int32_t __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept; void __stdcall WINRT_IMPL_CloseThreadpoolWait(winrt::impl::ptp_wait wait) noexcept; winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept; void __stdcall WINRT_IMPL_StartThreadpoolIo(winrt::impl::ptp_io io) noexcept; @@ -149,10 +149,10 @@ WINRT_IMPL_LINK(WaitForSingleObject, 8) WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12) WINRT_IMPL_LINK(CreateThreadpoolTimer, 12) -WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16) +WINRT_IMPL_LINK(SetThreadpoolTimer, 16) WINRT_IMPL_LINK(CloseThreadpoolTimer, 4) WINRT_IMPL_LINK(CreateThreadpoolWait, 12) -WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16) +WINRT_IMPL_LINK(SetThreadpoolWait, 12) WINRT_IMPL_LINK(CloseThreadpoolWait, 4) WINRT_IMPL_LINK(CreateThreadpoolIo, 16) WINRT_IMPL_LINK(StartThreadpoolIo, 4) From ede68ed9e78d5ec53110c462fe687be4ea2a5bf7 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Tue, 23 Mar 2021 06:01:15 -0700 Subject: [PATCH 006/305] Allow capturing from a raw pointer (#896) --- strings/base_com_ptr.h | 83 +++++++++++++++------------- test/old_tests/UnitTests/capture.cpp | 25 +++++++++ 2 files changed, 70 insertions(+), 38 deletions(-) diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index d8b86d2c8..ed6bf0089 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -1,4 +1,28 @@ +WINRT_EXPORT namespace winrt +{ + template + struct com_ptr; +} + +namespace winrt::impl +{ + template + int32_t capture_to(void**result, F function, Args&& ...args) + { + return function(args..., guid_of(), result); + } + + template || std::is_union_v, int> = 0> + int32_t capture_to(void** result, O* object, M method, Args&& ...args) + { + return (object->*method)(args..., guid_of(), result); + } + + template + int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args); +} + WINRT_EXPORT namespace winrt { template @@ -162,28 +186,16 @@ WINRT_EXPORT namespace winrt *other = m_ptr; } - template - bool try_capture(F function, Args&&...args) - { - return function(args..., guid_of(), put_void()) >= 0; - } - - template - bool try_capture(com_ptr const& object, M method, Args&&...args) - { - return (object.get()->*(method))(args..., guid_of(), put_void()) >= 0; - } - - template - void capture(F function, Args&&...args) + template + bool try_capture(Args&&...args) { - check_hresult(function(args..., guid_of(), put_void())); + return impl::capture_to(put_void(), std::forward(args)...) >= 0; } - template - void capture(com_ptr const& object, M method, Args&&...args) + template + void capture(Args&&...args) { - check_hresult((object.get()->*(method))(args..., guid_of(), put_void())); + check_hresult(impl::capture_to(put_void(), std::forward(args)...)); } private: @@ -225,33 +237,19 @@ WINRT_EXPORT namespace winrt type* m_ptr{}; }; - template - impl::com_ref try_capture(F function, Args&& ...args) + template + impl::com_ref try_capture(Args&& ...args) { void* result{}; - function(args..., guid_of(), &result); + impl::capture_to(&result, std::forward(args)...); return { result, take_ownership_from_abi }; } - template - impl::com_ref try_capture(com_ptr const& object, M method, Args&& ...args) - { - void* result{}; - (object.get()->*(method))(args..., guid_of(), &result); - return { result, take_ownership_from_abi }; - } - template - impl::com_ref capture(F function, Args&& ...args) - { - void* result{}; - check_hresult(function(args..., guid_of(), &result)); - return { result, take_ownership_from_abi }; - } - template - impl::com_ref capture(com_ptr const& object, M method, Args && ...args) + template + impl::com_ref capture(Args&& ...args) { void* result{}; - check_hresult((object.get()->*(method))(args..., guid_of(), &result)); + check_hresult(impl::capture_to(&result, std::forward(args)...)); return { result, take_ownership_from_abi }; } @@ -340,6 +338,15 @@ WINRT_EXPORT namespace winrt } } +namespace winrt::impl +{ + template + int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) + { + return (object.get()->*(method))(args..., guid_of(), result); + } +} + template void** IID_PPV_ARGS_Helper(winrt::com_ptr* ptr) noexcept { diff --git a/test/old_tests/UnitTests/capture.cpp b/test/old_tests/UnitTests/capture.cpp index d1c4e41de..936f5ed77 100644 --- a/test/old_tests/UnitTests/capture.cpp +++ b/test/old_tests/UnitTests/capture.cpp @@ -39,46 +39,71 @@ HRESULT __stdcall CreateCapture(int value, GUID const& iid, void** object) noexc TEST_CASE("capture") { + // Capture from global function. com_ptr a = capture(CreateCapture, 10); REQUIRE(a->GetValue() == 10); a = nullptr; a.capture(CreateCapture, 20); REQUIRE(a->GetValue() == 20); + // Capture from com_ptr + method. auto b = capture(a, &ICapture::CreateMemberCapture, 30); REQUIRE(b->GetValue() == 30); b = nullptr; b.capture(a, &ICapture::CreateMemberCapture, 40); REQUIRE(b->GetValue() == 40); + // Capture from raw pointer + method. + b = nullptr; + b = capture(a.get(), &ICapture::CreateMemberCapture, 30); + REQUIRE(b->GetValue() == 30); + b = nullptr; + b.capture(a.get(), &ICapture::CreateMemberCapture, 40); + REQUIRE(b->GetValue() == 40); + com_ptr d; REQUIRE_THROWS_AS(capture(CreateCapture, 0), hresult_no_interface); REQUIRE_THROWS_AS(d.capture(CreateCapture, 0), hresult_no_interface); REQUIRE_THROWS_AS(capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface); REQUIRE_THROWS_AS(d.capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface); + REQUIRE_THROWS_AS(capture(a.get(), &ICapture::CreateMemberCapture, 0), hresult_no_interface); + REQUIRE_THROWS_AS(d.capture(a.get(), &ICapture::CreateMemberCapture, 0), hresult_no_interface); } TEST_CASE("try_capture") { // Identical to the "capture" test above, just with different // error handling. + + // Capture from global function. com_ptr a = try_capture(CreateCapture, 10); REQUIRE(a->GetValue() == 10); a = nullptr; REQUIRE(a.try_capture(CreateCapture, 20)); REQUIRE(a->GetValue() == 20); + // Capture from com_ptr + method. auto b = try_capture(a, &ICapture::CreateMemberCapture, 30); REQUIRE(b->GetValue() == 30); b = nullptr; REQUIRE(b.try_capture(a, &ICapture::CreateMemberCapture, 40)); REQUIRE(b->GetValue() == 40); + // Capture from raw pointer + method. + b = nullptr; + b = try_capture(a.get(), &ICapture::CreateMemberCapture, 30); + REQUIRE(b->GetValue() == 30); + b = nullptr; + b.try_capture(a.get(), &ICapture::CreateMemberCapture, 40); + REQUIRE(b->GetValue() == 40); + com_ptr d; REQUIRE(!try_capture(CreateCapture, 0)); REQUIRE(!d.try_capture(CreateCapture, 0)); REQUIRE(!try_capture(a, &ICapture::CreateMemberCapture, 0)); REQUIRE(!d.try_capture(a, &ICapture::CreateMemberCapture, 0)); + REQUIRE(!try_capture(a.get(), &ICapture::CreateMemberCapture, 0)); + REQUIRE(!d.try_capture(a.get(), &ICapture::CreateMemberCapture, 0)); } From 37f0c4ed8745f78c4d5e0f96f6bc4b6499457f6a Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Tue, 23 Mar 2021 06:02:13 -0700 Subject: [PATCH 007/305] Restore Win7 functionality (more correctly this time) (#898) --- strings/base_activation.h | 2 +- strings/base_agile_ref.h | 6 +++--- strings/base_coroutine_threadpool.h | 19 +++++++++++++++++-- strings/base_error.h | 4 ++-- strings/base_events.h | 2 +- strings/base_extern.h | 4 ++-- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index 6cb312581..a54c9e23b 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -34,7 +34,7 @@ namespace winrt::impl } static int32_t(__stdcall * handler)(void* classId, winrt::guid const& iid, void** factory) noexcept; - impl::load_runtime_function("RoGetActivationFactory", handler, fallback_RoGetActivationFactory); + impl::load_runtime_function(L"combase.dll", "RoGetActivationFactory", handler, fallback_RoGetActivationFactory); hresult hr = handler(*(void**)(&name), guid, result); if (hr == impl::error_not_initialized) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index 610db8ac9..62be3c5e0 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -122,14 +122,14 @@ namespace winrt::impl }; template - void load_runtime_function(char const* name, F& result, L fallback) noexcept + void load_runtime_function(wchar_t const* library, char const* name, F& result, L fallback) noexcept { if (result) { return; } - result = reinterpret_cast(WINRT_IMPL_GetProcAddress(WINRT_IMPL_LoadLibraryW(L"combase.dll"), name)); + result = reinterpret_cast(WINRT_IMPL_GetProcAddress(WINRT_IMPL_LoadLibraryW(library), name)); if (result) { @@ -167,7 +167,7 @@ namespace winrt::impl inline hresult get_agile_reference(winrt::guid const& iid, void* object, void** reference) noexcept { static int32_t(__stdcall * handler)(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept; - load_runtime_function("RoGetAgileReference", handler, fallback_RoGetAgileReference); + load_runtime_function(L"combase.dll", "RoGetAgileReference", handler, fallback_RoGetAgileReference); return handler(0, iid, object, reference); } } diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 5b1ab421b..4ea37bf75 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -433,9 +433,17 @@ WINRT_EXPORT namespace winrt private: + static int32_t __stdcall fallback_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept + { + return 0; // pretend timer has already triggered and a callback is on its way + } + void fire_immediately() noexcept { - if (WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), nullptr, 0, 0)) + static int32_t(__stdcall* handler)(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept; + impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolTimerEx", handler, fallback_SetThreadpoolTimerEx); + + if (handler(m_timer.get(), nullptr, 0, 0)) { int64_t now = 0; WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); @@ -532,10 +540,17 @@ WINRT_EXPORT namespace winrt } private: + static int32_t __stdcall fallback_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept + { + return 0; // pretend wait has already triggered and a callback is on its way + } void fire_immediately() noexcept { - if (WINRT_IMPL_SetThreadpoolWait(m_wait.get(), nullptr, nullptr)) + static int32_t(__stdcall* handler)(winrt::impl::ptp_wait, void*, void*, void*) noexcept; + impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolWaitEx", handler, fallback_SetThreadpoolWaitEx); + + if (handler(m_wait.get(), nullptr, nullptr, nullptr)) { int64_t now = 0; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); diff --git a/strings/base_error.h b/strings/base_error.h index 7330e05a6..c2db6d1ba 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -312,7 +312,7 @@ WINRT_EXPORT namespace winrt void originate(hresult const code, void* message) noexcept { static int32_t(__stdcall* handler)(int32_t error, void* message, void* exception) noexcept; - impl::load_runtime_function("RoOriginateLanguageException", handler, fallback_RoOriginateLanguageException); + impl::load_runtime_function(L"combase.dll", "RoOriginateLanguageException", handler, fallback_RoOriginateLanguageException); WINRT_VERIFY(handler(code, message, nullptr)); com_ptr info; @@ -625,7 +625,7 @@ WINRT_EXPORT namespace winrt [[noreturn]] inline void terminate() noexcept { static void(__stdcall * handler)(int32_t) noexcept; - impl::load_runtime_function("RoFailFastWithErrorContext", handler, impl::fallback_RoFailFastWithErrorContext); + impl::load_runtime_function(L"combase.dll", "RoFailFastWithErrorContext", handler, impl::fallback_RoFailFastWithErrorContext); handler(to_hresult()); abort(); } diff --git a/strings/base_events.h b/strings/base_events.h index a26b5bce2..3b53fa06f 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -352,7 +352,7 @@ namespace winrt::impl int32_t const code = to_hresult(); static int32_t(__stdcall * handler)(int32_t, int32_t, void*) noexcept; - impl::load_runtime_function("RoTransformError", handler, fallback_RoTransformError); + impl::load_runtime_function(L"combase.dll", "RoTransformError", handler, fallback_RoTransformError); handler(code, 0, nullptr); if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED diff --git a/strings/base_extern.h b/strings/base_extern.h index 7d31186d8..7782f3bcb 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -65,10 +65,10 @@ extern "C" int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept; winrt::impl::ptp_timer __stdcall WINRT_IMPL_CreateThreadpoolTimer(void(__stdcall *callback)(void*, void* context, void*), void* context, void*) noexcept; - int32_t __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept; + void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept; void __stdcall WINRT_IMPL_CloseThreadpoolTimer(winrt::impl::ptp_timer timer) noexcept; winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, uint32_t result), void* context, void*) noexcept; - int32_t __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept; + void __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept; void __stdcall WINRT_IMPL_CloseThreadpoolWait(winrt::impl::ptp_wait wait) noexcept; winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept; void __stdcall WINRT_IMPL_StartThreadpoolIo(winrt::impl::ptp_io io) noexcept; From 2073422028bb260b1ffaba720b3e46bce937600f Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Fri, 26 Mar 2021 10:35:11 -0700 Subject: [PATCH 008/305] Add support for boxing and unboxing most kinds of arrays (#903) --- strings/base_reference_produce.h | 183 +++++++++++++++++++++++++++++-- test/test/box_array.cpp | 56 ++++++++++ test/test/test.vcxproj | 1 + 3 files changed, 232 insertions(+), 8 deletions(-) create mode 100644 test/test/box_array.cpp diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 868b1c353..8228cbc4c 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -111,90 +111,105 @@ namespace winrt::impl struct reference_traits { static auto make(T const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(float value) { return Windows::Foundation::PropertyValue::CreateSingle(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(double value) { return Windows::Foundation::PropertyValue::CreateDouble(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(char16_t value) { return Windows::Foundation::PropertyValue::CreateChar16(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(bool value) { return Windows::Foundation::PropertyValue::CreateBoolean(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(hstring const& value) { return Windows::Foundation::PropertyValue::CreateString(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(Windows::Foundation::IInspectable const& value) { return Windows::Foundation::PropertyValue::CreateInspectable(value); } + using itf = Windows::Foundation::IInspectable; }; template <> struct reference_traits { static auto make(guid const& value) { return Windows::Foundation::PropertyValue::CreateGuid(value); } + using itf = Windows::Foundation::IReference; }; #ifdef WINRT_IMPL_IUNKNOWN_DEFINED @@ -202,6 +217,7 @@ namespace winrt::impl struct reference_traits { static auto make(GUID const& value) { return Windows::Foundation::PropertyValue::CreateGuid(value); } + using itf = Windows::Foundation::IReference; }; #endif @@ -209,30 +225,177 @@ namespace winrt::impl struct reference_traits { static auto make(Windows::Foundation::DateTime value) { return Windows::Foundation::PropertyValue::CreateDateTime(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(Windows::Foundation::TimeSpan value) { return Windows::Foundation::PropertyValue::CreateTimeSpan(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(Windows::Foundation::Point const& value) { return Windows::Foundation::PropertyValue::CreatePoint(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(Windows::Foundation::Size const& value) { return Windows::Foundation::PropertyValue::CreateSize(value); } + using itf = Windows::Foundation::IReference; }; template <> struct reference_traits { static auto make(Windows::Foundation::Rect const& value) { return Windows::Foundation::PropertyValue::CreateRect(value); } + using itf = Windows::Foundation::IReference; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateSingleArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateDoubleArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateChar16Array(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateBooleanArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateStringArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInspectableArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + +#ifdef WINRT_IMPL_IUNKNOWN_DEFINED + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(reinterpret_cast const&>(value)); } + using itf = Windows::Foundation::IReferenceArray; + }; +#endif + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateDateTimeArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateTimeSpanArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreatePointArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateSizeArray(value); } + using itf = Windows::Foundation::IReferenceArray; + }; + + template <> + struct reference_traits> + { + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateRectArray(value); } + using itf = Windows::Foundation::IReferenceArray; }; } @@ -282,14 +445,16 @@ namespace winrt::impl } } #ifdef WINRT_IMPL_IUNKNOWN_DEFINED - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v>) { - return value.template as>().Value(); + T result; + reinterpret_cast&>(result) = value.template as::itf>().Value(); + return result; } #endif else { - return value.template as>().Value(); + return value.template as::itf>().Value(); } } @@ -309,17 +474,19 @@ namespace winrt::impl } } #ifdef WINRT_IMPL_IUNKNOWN_DEFINED - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v>) { - if (auto temp = value.template try_as>()) + if (auto temp = value.template try_as::itf>()) { - return temp.Value(); + T result; + reinterpret_cast&>(result) = temp.Value(); + return result; } } #endif else { - if (auto temp = value.template try_as>()) + if (auto temp = value.template try_as::itf>()) { return temp.Value(); } @@ -416,5 +583,5 @@ WINRT_EXPORT namespace winrt } template - using optional = Windows::Foundation::IReference; + using optional = typename impl::reference_traits::itf; } diff --git a/test/test/box_array.cpp b/test/test/box_array.cpp new file mode 100644 index 000000000..1c5b4a966 --- /dev/null +++ b/test/test/box_array.cpp @@ -0,0 +1,56 @@ +#include "pch.h" + +namespace +{ + template + void Verify(T const& otherValue) + { + T defaultValue{}; + winrt::com_array ary{ otherValue, defaultValue }; + auto box = winrt::box_value(ary); + winrt::com_array unbox = box.try_as>().value(); + REQUIRE(unbox.size() == 2); + REQUIRE(unbox.at(0) == otherValue); + REQUIRE(unbox.at(1) == defaultValue); + unbox = box.as>(); + REQUIRE(unbox.size() == 2); + REQUIRE(unbox.at(0) == otherValue); + REQUIRE(unbox.at(1) == defaultValue); + if constexpr (!std::is_same_v) + { + unbox = box.as>>().Value(); + REQUIRE(unbox.size() == 2); + REQUIRE(unbox.at(0) == otherValue); + REQUIRE(unbox.at(1) == defaultValue); + } + unbox = winrt::unbox_value>(box); + REQUIRE(unbox.size() == 2); + REQUIRE(unbox.at(0) == otherValue); + REQUIRE(unbox.at(1) == defaultValue); + // Cannot use unbox_value_or with arrays because com_array is not copyable. + // unbox = winrt::unbox_value_or(box, winrt::com_array{}); + } +} +TEST_CASE("box_array") +{ + Verify(42); + Verify(42); + Verify(42); + Verify(42); + Verify(42); + Verify(42); + Verify(42); + Verify(42); + Verify(42); + Verify(42); + Verify(true); + Verify(L"42"); + Verify(winrt::Windows::Foundation::Uri{ L"https://www.microsoft.com/" }); + Verify({ 1,2,3, {4,5,6,7,8,9,10,11} }); + Verify(winrt::guid{ 1,2,3, {4,5,6,7,8,9,10,11} }); + Verify((winrt::Windows::Foundation::DateTime::max)()); + Verify((winrt::Windows::Foundation::TimeSpan::max)()); + Verify({ 1,1 }); + Verify({ 1,1 }); + Verify({ 1,1,1,1 }); +} \ No newline at end of file diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index e0f2cebe0..9823e1624 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -296,6 +296,7 @@ + From 1935608ceb28860f2e89451eed84230b4dd69646 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 26 Mar 2021 11:56:02 -0700 Subject: [PATCH 009/305] Support nested Windows namespace (#904) --- cppwinrt/code_writers.h | 18 +++++++++--------- cppwinrt/component_writers.h | 4 ++-- cppwinrt/type_writers.h | 2 +- test/test_component/Windows.Class.cpp | 15 +++++++++++++++ test/test_component/Windows.Class.h | 19 +++++++++++++++++++ test/test_component/test_component.idl | 10 ++++++++++ test/test_component/test_component.vcxproj | 2 ++ 7 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 test/test_component/Windows.Class.cpp create mode 100644 test/test_component/Windows.Class.h diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 422be0541..5817abb64 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1619,7 +1619,7 @@ namespace cppwinrt else if (optional) { auto format = R"( if (%) *% = nullptr; - Windows::Foundation::IInspectable winrt_impl_%; + winrt::Windows::Foundation::IInspectable winrt_impl_%; )"; w.write(format, param_name, param_name, param_name); @@ -1961,7 +1961,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (!found) { - w.write(", Windows::Foundation::IInspectable"); + w.write(", winrt::Windows::Foundation::IInspectable"); } } @@ -2314,11 +2314,11 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (empty(generics)) { auto format = R"( struct __declspec(empty_bases) % : - Windows::Foundation::IInspectable, + winrt::Windows::Foundation::IInspectable, impl::consume_t<%>% { %(std::nullptr_t = nullptr) noexcept {} - %(void* ptr, take_ownership_from_abi_t) noexcept : Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} + %(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} %(% const&) noexcept = default; %(%&&) noexcept = default; %& operator=(% const&) & noexcept = default; @@ -2349,11 +2349,11 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable auto format = R"( template <%> struct __declspec(empty_bases) % : - Windows::Foundation::IInspectable, + winrt::Windows::Foundation::IInspectable, impl::consume_t<%>% {% %(std::nullptr_t = nullptr) noexcept {} - %(void* ptr, take_ownership_from_abi_t) noexcept : Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} + %(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} %(% const&) noexcept = default; %(%&&) noexcept = default; %& operator=(% const&) & noexcept = default; @@ -2925,7 +2925,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable auto format = R"( inline %::%(%) { - Windows::Foundation::IInspectable %, %; + winrt::Windows::Foundation::IInspectable %, %; *this = % { return f.%(%%%, %); }); } )"; @@ -3056,7 +3056,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (has_fastabi(type)) { format = R"( inline %::%() : - %(impl::call_factory_cast<%(*)(Windows::Foundation::IActivationFactory const&), %>([](Windows::Foundation::IActivationFactory const& f) { return impl::fast_activate<%>(f); })) + %(impl::call_factory_cast<%(*)(winrt::Windows::Foundation::IActivationFactory const&), %>([](winrt::Windows::Foundation::IActivationFactory const& f) { return impl::fast_activate<%>(f); })) { } )"; @@ -3064,7 +3064,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable else { format = R"( inline %::%() : - %(impl::call_factory_cast<%(*)(Windows::Foundation::IActivationFactory const&), %>([](Windows::Foundation::IActivationFactory const& f) { return f.template ActivateInstance<%>(); })) + %(impl::call_factory_cast<%(*)(winrt::Windows::Foundation::IActivationFactory const&), %>([](winrt::Windows::Foundation::IActivationFactory const& f) { return f.template ActivateInstance<%>(); })) { } )"; diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index a2e755a48..b8894f8f4 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -347,7 +347,7 @@ catch (...) { return winrt::to_hresult(); } if (!default_constructor) { - w.write(R"( [[noreturn]] Windows::Foundation::IInspectable ActivateInstance() const + w.write(R"( [[noreturn]] winrt::Windows::Foundation::IInspectable ActivateInstance() const { throw hresult_not_implemented(); } @@ -831,7 +831,7 @@ catch (...) { return winrt::to_hresult(); } auto format = R"(namespace winrt::@::factory_implementation { template - struct __declspec(empty_bases) %T : implements + struct __declspec(empty_bases) %T : implements { using instance_type = @::%; diff --git a/cppwinrt/type_writers.h b/cppwinrt/type_writers.h index c05505db2..0f3ca983e 100644 --- a/cppwinrt/type_writers.h +++ b/cppwinrt/type_writers.h @@ -504,7 +504,7 @@ namespace cppwinrt } else { - write("Windows::Foundation::IInspectable"); + write("winrt::Windows::Foundation::IInspectable"); } } else diff --git a/test/test_component/Windows.Class.cpp b/test/test_component/Windows.Class.cpp new file mode 100644 index 000000000..bbed99356 --- /dev/null +++ b/test/test_component/Windows.Class.cpp @@ -0,0 +1,15 @@ +#include "pch.h" +#include "Windows.Class.h" +#include "Windows.Class.g.cpp" + +namespace winrt::test_component::Windows::implementation +{ + void Class::StaticMethod() + { + throw hresult_not_implemented(); + } + void Class::Method() + { + throw hresult_not_implemented(); + } +} diff --git a/test/test_component/Windows.Class.h b/test/test_component/Windows.Class.h new file mode 100644 index 000000000..f720364f1 --- /dev/null +++ b/test/test_component/Windows.Class.h @@ -0,0 +1,19 @@ +#pragma once +#include "Windows.Class.g.h" + +namespace winrt::test_component::Windows::implementation +{ + struct Class : ClassT + { + Class() = default; + + static void StaticMethod(); + void Method(); + }; +} +namespace winrt::test_component::Windows::factory_implementation +{ + struct Class : ClassT + { + }; +} diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index a7a86a447..b3455f362 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -277,4 +277,14 @@ namespace test_component } } } + + namespace Windows + { + runtimeclass Class + { + Class(); + static void StaticMethod(); + void Method(); + } + } } diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index ef66896e9..171c859e9 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -620,6 +620,7 @@ + @@ -628,6 +629,7 @@ + From 122b732393d2f916367c06fd026f79d8ac4cee43 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 26 Mar 2021 13:59:04 -0700 Subject: [PATCH 010/305] Windows test (#905) --- cppwinrt/code_writers.h | 4 ++-- cppwinrt/type_writers.h | 24 ++++++++++++------------ test/test_component/Windows.Class.cpp | 4 ++-- test/test_component/Windows.Class.h | 4 ++-- test/test_component/test_component.idl | 11 +++++++++-- 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 5817abb64..37f5f4327 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2111,7 +2111,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable D& shim() noexcept { return *static_cast(this); } D const& shim() const noexcept { return *static_cast(this); } public: - using % = winrt::%; + using % = %; % }; )"; @@ -3207,7 +3207,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable { auto generics = type.GenericParam(); - w.write(" template<%> struct hash : winrt::impl::hash_base {};\n", + w.write(" template<%> struct hash<%> : winrt::impl::hash_base {};\n", bind(generics), type); } diff --git a/cppwinrt/type_writers.h b/cppwinrt/type_writers.h index 0f3ca983e..a41b3086c 100644 --- a/cppwinrt/type_writers.h +++ b/cppwinrt/type_writers.h @@ -273,7 +273,7 @@ namespace cppwinrt if (!empty(generics)) { - write("@::%<%>", ns, remove_tick(name), bind_list(", ", generics)); + write("winrt::@::%<%>", ns, remove_tick(name), bind_list(", ", generics)); return; } @@ -301,7 +301,7 @@ namespace cppwinrt else if (name == "Vector3") { name = "float3"; } else if (name == "Vector4") { name = "float4"; } - write("@::%", ns, name); + write("winrt::@::%", ns, name); } else if (category == category::struct_type) { @@ -311,7 +311,7 @@ namespace cppwinrt } else if ((name == "Point" || name == "Size" || name == "Rect") && ns == "Windows.Foundation") { - write("@::%", ns, name); + write("winrt::@::%", ns, name); } else if (delegate_types) { @@ -343,11 +343,11 @@ namespace cppwinrt else if (name == "Vector3") { name = "float3"; } else if (name == "Vector4") { name = "float4"; } - write("@::%", ns, name); + write("winrt::@::%", ns, name); } else { - write("@::%", ns, name); + write("winrt::@::%", ns, name); } } } @@ -400,14 +400,14 @@ namespace cppwinrt if (consume_types) { - static constexpr std::string_view iterable("Windows::Foundation::Collections::IIterable<"sv); - static constexpr std::string_view vector_view("Windows::Foundation::Collections::IVectorView<"sv); - static constexpr std::string_view map_view("Windows::Foundation::Collections::IMapView<"sv); - static constexpr std::string_view vector("Windows::Foundation::Collections::IVector<"sv); - static constexpr std::string_view map("Windows::Foundation::Collections::IMap<"sv); + static constexpr std::string_view iterable("winrt::Windows::Foundation::Collections::IIterable<"sv); + static constexpr std::string_view vector_view("winrt::Windows::Foundation::Collections::IVectorView<"sv); + static constexpr std::string_view map_view("winrt::Windows::Foundation::Collections::IMapView<"sv); + static constexpr std::string_view vector("winrt::Windows::Foundation::Collections::IVector<"sv); + static constexpr std::string_view map("winrt::Windows::Foundation::Collections::IMap<"sv); consume_types = false; - auto full_name = write_temp("@::%<%>", ns, name, bind_list(", ", type.GenericArgs())); + auto full_name = write_temp("winrt::@::%<%>", ns, name, bind_list(", ", type.GenericArgs())); consume_types = true; if (starts_with(full_name, iterable)) @@ -459,7 +459,7 @@ namespace cppwinrt } else { - write("@::%<%>", ns, name, bind_list(", ", type.GenericArgs())); + write("winrt::@::%<%>", ns, name, bind_list(", ", type.GenericArgs())); } } } diff --git a/test/test_component/Windows.Class.cpp b/test/test_component/Windows.Class.cpp index bbed99356..483ebaa50 100644 --- a/test/test_component/Windows.Class.cpp +++ b/test/test_component/Windows.Class.cpp @@ -4,11 +4,11 @@ namespace winrt::test_component::Windows::implementation { - void Class::StaticMethod() + void Class::StaticMethod(winrt::test_component::Windows::Struct const&) { throw hresult_not_implemented(); } - void Class::Method() + void Class::Method(winrt::Windows::Foundation::Uri const&) { throw hresult_not_implemented(); } diff --git a/test/test_component/Windows.Class.h b/test/test_component/Windows.Class.h index f720364f1..b1ddc72d8 100644 --- a/test/test_component/Windows.Class.h +++ b/test/test_component/Windows.Class.h @@ -7,8 +7,8 @@ namespace winrt::test_component::Windows::implementation { Class() = default; - static void StaticMethod(); - void Method(); + static void StaticMethod(winrt::test_component::Windows::Struct const& param); + void Method(winrt::Windows::Foundation::Uri const& param); }; } namespace winrt::test_component::Windows::factory_implementation diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index b3455f362..a3274e4c3 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -280,11 +280,18 @@ namespace test_component namespace Windows { + struct Struct + { + Windows.Foundation.Rect rect; + Windows.Foundation.Numerics.Matrix3x2 matrix; + Windows.Foundation.IReference ref_rect; + }; + runtimeclass Class { Class(); - static void StaticMethod(); - void Method(); + static void StaticMethod(Struct param); + void Method(Windows.Foundation.Uri param); } } } From 8684e147718fc635447898dddfb15435cafb8cd2 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 29 Mar 2021 13:47:25 -0400 Subject: [PATCH 011/305] C++20 ranges support (#900) --- build_test_all.cmd | 1 + cppwinrt.sln | 22 ++ cppwinrt/code_writers.h | 44 +++- cppwinrt/cppwinrt.vcxproj | 1 + cppwinrt/cppwinrt.vcxproj.filters | 3 + cppwinrt/file_writers.h | 1 + run_tests.cmd | 1 + strings/base_collections.h | 171 +--------------- strings/base_iterator.h | 189 +++++++++++++++++ strings/base_xaml_typename.h | 11 + test/test/fast_iterator.cpp | 11 + test/test_cpp20/main.cpp | 16 ++ test/test_cpp20/pch.cpp | 1 + test/test_cpp20/pch.h | 12 ++ test/test_cpp20/ranges.cpp | 48 +++++ test/test_cpp20/test_cpp20.vcxproj | 316 +++++++++++++++++++++++++++++ 16 files changed, 679 insertions(+), 169 deletions(-) create mode 100644 strings/base_iterator.h create mode 100644 test/test_cpp20/main.cpp create mode 100644 test/test_cpp20/pch.cpp create mode 100644 test/test_cpp20/pch.h create mode 100644 test/test_cpp20/ranges.cpp create mode 100644 test/test_cpp20/test_cpp20.vcxproj diff --git a/build_test_all.cmd b/build_test_all.cmd index 4529372f1..13a68f6c9 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -27,6 +27,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%, call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_win7 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_slow diff --git a/cppwinrt.sln b/cppwinrt.sln index 3189d1555..d2141707c 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -103,6 +103,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp20\test_cpp20.vcxproj", "{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -435,6 +440,22 @@ Global {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.Build.0 = Release|x64 {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.ActiveCfg = Release|Win32 {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.Build.0 = Release|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.Build.0 = Debug|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.ActiveCfg = Debug|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.Build.0 = Debug|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.ActiveCfg = Debug|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.Build.0 = Debug|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.ActiveCfg = Release|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.Build.0 = Release|ARM + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.ActiveCfg = Release|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.Build.0 = Release|ARM64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.ActiveCfg = Release|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.Build.0 = Release|x64 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.ActiveCfg = Release|Win32 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -457,6 +478,7 @@ Global {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {2EF696B9-7F4A-410F-AE5C-5301565C0F08} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 37f5f4327..51c77a156 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1283,13 +1283,18 @@ namespace cppwinrt static_cast(*this) = nullptr; } - return *this; + return static_cast(*this); } auto operator*() const { return Current(); } + + void operator++(int) + { + ++(*this); + } )"); } else if (type_name == "Windows.Storage.Streams.IBuffer") @@ -1313,13 +1318,18 @@ namespace cppwinrt static_cast(*this) = nullptr; } - return *this; + return static_cast(*this); } T operator*() const { return Current(); } + + void operator++(int) + { + ++(*this); + } )"); } else if (type_name == "Windows.Foundation.Collections.IKeyValuePair`2") @@ -1415,6 +1425,20 @@ namespace cppwinrt { w.write(R"( auto get() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; +)"); + } + else if (type_name == "Windows.Foundation.Collections.IIterable`1") + { + w.write(R"( + auto begin() const; + auto end() const; +)"); + } + else if (type_name == "Windows.UI.Xaml.Interop.IBindableIterable") + { + w.write(R"( + auto begin() const; + auto end() const; )"); } } @@ -1426,11 +1450,23 @@ namespace cppwinrt if (type_name == "Windows.Foundation.Collections.IIterator`1") { w.write(R"( + using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = T; using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; + using pointer = void; + using reference = T; +)"); + } + else if (type_name == "Windows.UI.Xaml.Interop.IBindableIterator") + { + w.write(R"( + using iterator_concept = std::input_iterator_tag; + using iterator_category = std::input_iterator_tag; + using value_type = Windows::Foundation::IInspectable; + using difference_type = ptrdiff_t; + using pointer = void; + using reference = Windows::Foundation::IInspectable; )"); } else if (type_name == "Windows.Foundation.IReference`1") diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index ee4fd3f3a..73a5288ec 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -68,6 +68,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 7720e5dfc..7caab56a8 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -163,6 +163,9 @@ strings + + strings + diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index c210b6f47..c91b1de91 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -38,6 +38,7 @@ namespace cppwinrt w.write(strings::base_chrono); w.write(strings::base_security); w.write(strings::base_std_hash); + w.write(strings::base_iterator); w.write(strings::base_coroutine_threadpool); w.write(strings::base_natvis); w.write(strings::base_version); diff --git a/run_tests.cmd b/run_tests.cmd index d63741994..9cdbeb4b3 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Debug call :run_test test +call :run_test test_cpp20 call :run_test test_win7 call :run_test test_fast call :run_test test_slow diff --git a/strings/base_collections.h b/strings/base_collections.h index afb70494b..cba0864b3 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -3,174 +3,15 @@ namespace winrt::impl { namespace wfc = Windows::Foundation::Collections; - template - struct fast_iterator + template + auto consume_Windows_Foundation_Collections_IIterable::begin() const { - using iterator_category = std::input_iterator_tag; - using value_type = decltype(std::declval().GetAt(0)); - using difference_type = ptrdiff_t; - using pointer = value_type*; - using reference = value_type; - - fast_iterator() noexcept : m_collection(nullptr), m_index(0) {} - - fast_iterator(T const& collection, uint32_t const index) noexcept : - m_collection(&collection), - m_index(index) - {} - - fast_iterator& operator++() noexcept - { - ++m_index; - return*this; - } - - fast_iterator operator++(int) noexcept - { - auto previous = *this; - ++m_index; - return previous; - } - - fast_iterator& operator--() noexcept - { - --m_index; - return*this; - } - - fast_iterator operator--(int) noexcept - { - auto previous = *this; - --m_index; - return previous; - } - - fast_iterator& operator+=(difference_type n) noexcept - { - m_index += static_cast(n); - return*this; - } - - fast_iterator operator+(difference_type n) const noexcept - { - return fast_iterator(*this) += n; - } - - fast_iterator& operator-=(difference_type n) noexcept - { - return *this += -n; - } - - fast_iterator operator-(difference_type n) const noexcept - { - return *this + -n; - } - - difference_type operator-(fast_iterator const& other) const noexcept - { - return static_cast(m_index) - static_cast(other.m_index); - } - - reference operator*() const - { - return m_collection->GetAt(m_index); - } - - reference operator[](difference_type n) const - { - return m_collection->GetAt(m_index + static_cast(n)); - } - - bool operator==(fast_iterator const& other) const noexcept - { - WINRT_ASSERT(m_collection == other.m_collection); - return m_index == other.m_index; - } - - bool operator<(fast_iterator const& other) const noexcept - { - WINRT_ASSERT(m_collection == other.m_collection); - return m_index < other.m_index; - } - - bool operator!=(fast_iterator const& other) const noexcept - { - return !(*this == other); - } - - bool operator>(fast_iterator const& other) const noexcept - { - return !(*this < other); - } - - bool operator<=(fast_iterator const& other) const noexcept - { - return !(*this > other); - } - - bool operator>=(fast_iterator const& other) const noexcept - { - return !(*this < other); - } - - private: - - T const* m_collection{}; - uint32_t m_index{}; - }; - - template - class has_GetAt - { - template ().GetAt(0))> static constexpr bool get_value(int) { return true; } - template static constexpr bool get_value(...) { return false; } - - public: - - static constexpr bool value = get_value(0); - }; - - template ::value, int> = 0> - auto begin(T const& collection) -> decltype(collection.First()) - { - auto result = collection.First(); - - if (!result.HasCurrent()) - { - return {}; - } - - return result; - } - - template ::value, int> = 0> - auto end([[maybe_unused]] T const& collection) noexcept -> decltype(collection.First()) - { - return {}; + return get_begin_iterator(static_cast(*this)); } - - template ::value, int> = 0> - fast_iterator begin(T const& collection) noexcept - { - return { collection, 0 }; - } - - template ::value, int> = 0> - fast_iterator end(T const& collection) - { - return { collection, collection.Size() }; - } - - template ::value, int> = 0> - auto rbegin(T const& collection) - { - return std::make_reverse_iterator(end(collection)); - } - - template ::value, int> = 0> - auto rend(T const& collection) + template + auto consume_Windows_Foundation_Collections_IIterable::end() const { - return std::make_reverse_iterator(begin(collection)); + return get_end_iterator(static_cast(*this)); } template diff --git a/strings/base_iterator.h b/strings/base_iterator.h new file mode 100644 index 000000000..b0ad7836d --- /dev/null +++ b/strings/base_iterator.h @@ -0,0 +1,189 @@ + +namespace winrt::impl +{ + template + struct fast_iterator + { + using iterator_concept = std::random_access_iterator_tag; + using iterator_category = std::input_iterator_tag; + using value_type = decltype(std::declval().GetAt(0)); + using difference_type = ptrdiff_t; + using pointer = void; + using reference = value_type; + + fast_iterator() noexcept = default; + + fast_iterator(T const& collection, uint32_t const index) noexcept : + m_collection(&collection), + m_index(index) + {} + + fast_iterator& operator++() noexcept + { + ++m_index; + return *this; + } + + fast_iterator operator++(int) noexcept + { + auto previous = *this; + ++m_index; + return previous; + } + + fast_iterator& operator--() noexcept + { + --m_index; + return *this; + } + + fast_iterator operator--(int) noexcept + { + auto previous = *this; + --m_index; + return previous; + } + + fast_iterator& operator+=(difference_type n) noexcept + { + m_index += static_cast(n); + return *this; + } + + fast_iterator operator+(difference_type n) const noexcept + { + return fast_iterator(*this) += n; + } + + fast_iterator& operator-=(difference_type n) noexcept + { + return *this += -n; + } + + fast_iterator operator-(difference_type n) const noexcept + { + return *this + -n; + } + + difference_type operator-(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return static_cast(m_index) - static_cast(other.m_index); + } + + reference operator*() const + { + return m_collection->GetAt(m_index); + } + + reference operator[](difference_type n) const + { + return m_collection->GetAt(m_index + static_cast(n)); + } + + bool operator==(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return m_index == other.m_index; + } + + bool operator<(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return m_index < other.m_index; + } + + bool operator>(fast_iterator const& other) const noexcept + { + WINRT_ASSERT(m_collection == other.m_collection); + return m_index > other.m_index; + } + + bool operator!=(fast_iterator const& other) const noexcept + { + return !(*this == other); + } + + bool operator<=(fast_iterator const& other) const noexcept + { + return !(*this > other); + } + + bool operator>=(fast_iterator const& other) const noexcept + { + return !(*this < other); + } + + friend fast_iterator operator+(difference_type n, fast_iterator it) noexcept + { + return it + n; + } + + friend fast_iterator operator-(difference_type n, fast_iterator it) noexcept + { + return it - n; + } + + private: + + T const* m_collection = nullptr; + uint32_t m_index = 0; + }; + + template + class has_GetAt + { + template ().GetAt(0))> static constexpr bool get_value(int) { return true; } + template static constexpr bool get_value(...) { return false; } + + public: + + static constexpr bool value = get_value(0); + }; + + template ::value, int> = 0> + auto get_begin_iterator(T const& collection) -> decltype(collection.First()) + { + auto result = collection.First(); + + if (!result.HasCurrent()) + { + return {}; + } + + return result; + } + + template ::value, int> = 0> + auto get_end_iterator([[maybe_unused]] T const& collection) noexcept -> decltype(collection.First()) + { + return {}; + } + + template ::value, int> = 0> + fast_iterator get_begin_iterator(T const& collection) noexcept + { + return { collection, 0 }; + } + + template ::value, int> = 0> + fast_iterator get_end_iterator(T const& collection) + { + return { collection, collection.Size() }; + } + + template ::value, int> = 0> + auto rbegin(T const& collection) + { + return std::make_reverse_iterator(get_end_iterator(collection)); + } + + template ::value, int> = 0> + auto rend(T const& collection) + { + return std::make_reverse_iterator(get_begin_iterator(collection)); + } + + using std::begin; + using std::end; +} diff --git a/strings/base_xaml_typename.h b/strings/base_xaml_typename.h index 4912649a2..4a782fc72 100644 --- a/strings/base_xaml_typename.h +++ b/strings/base_xaml_typename.h @@ -125,6 +125,17 @@ namespace winrt::impl { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; + + template + auto consume_Windows_UI_Xaml_Interop_IBindableIterable::begin() const + { + return get_begin_iterator(static_cast(*this)); + } + template + auto consume_Windows_UI_Xaml_Interop_IBindableIterable::end() const + { + return get_end_iterator(static_cast(*this)); + } } WINRT_EXPORT namespace winrt diff --git a/test/test/fast_iterator.cpp b/test/test/fast_iterator.cpp index 169b427c1..71ed6a918 100644 --- a/test/test/fast_iterator.cpp +++ b/test/test/fast_iterator.cpp @@ -44,8 +44,19 @@ TEST_CASE("fast_iterator") REQUIRE(value == 9); REQUIRE(vbegin[2] == 4); REQUIRE(vbegin + 2 > vbegin); + REQUIRE(2 + vbegin > vbegin); + REQUIRE(2 - (vbegin + 4) > vbegin); REQUIRE(vbegin < vbegin + 2); REQUIRE(vbegin + 2 - 2 == vbegin); REQUIRE(end(v) - begin(v) == v.Size()); + REQUIRE((begin(v) + 3)[-1] == 4); + } + { + // ensure that importing std::begin and std::end does not break existing code + using std::begin; + using std::end; + + auto v = winrt::single_threaded_vector({ 9, 5, 4, 1, 1, 3 }); + REQUIRE(std::is_heap(begin(v), end(v))); } } diff --git a/test/test_cpp20/main.cpp b/test/test_cpp20/main.cpp new file mode 100644 index 000000000..7873e4ee7 --- /dev/null +++ b/test/test_cpp20/main.cpp @@ -0,0 +1,16 @@ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#include "winrt/base.h" + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_cpp20/pch.cpp b/test/test_cpp20/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_cpp20/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_cpp20/pch.h b/test/test_cpp20/pch.h new file mode 100644 index 000000000..ea74230cc --- /dev/null +++ b/test/test_cpp20/pch.h @@ -0,0 +1,12 @@ +#pragma once + +#pragma warning(4: 4458) // ensure we compile clean with this warning enabled + +#define WINRT_LEAN_AND_MEAN +#include +#include "winrt/Windows.Foundation.Collections.h" +#include "winrt/Windows.Foundation.Numerics.h" +#include +#include "catch.hpp" + +using namespace std::literals; diff --git a/test/test_cpp20/ranges.cpp b/test/test_cpp20/ranges.cpp new file mode 100644 index 000000000..9bf88a579 --- /dev/null +++ b/test/test_cpp20/ranges.cpp @@ -0,0 +1,48 @@ +#include "pch.h" +#include +#include + +TEST_CASE("ranges") +{ + { + // random-access range algorithms + auto v = winrt::single_threaded_vector({ 9, 8, 9, 6, 5, 8, 9, 3, 5, 3, 5, 3, 4, 7, 2, 1, 2, 3, 1 }); + + const bool result = std::ranges::is_heap(v); + + REQUIRE((result == true)); + } + { + // bidirectional range views + auto v = winrt::single_threaded_vector({ 1, 2, 3 }); + + std::vector result; + for (const int i : v | std::views::reverse) + { + result.push_back(i); + } + + REQUIRE((result == std::vector{ 3, 2, 1 })); + } + { + // input range algorithms + // decay to IIterable is important, we want to test the non-fast iterators. + winrt::Windows::Foundation::Collections::IIterable iterable = winrt::single_threaded_vector({ 2, 3, 1 }); + + const int result = (std::ranges::max)(iterable); + REQUIRE((result == 3)); + } + { + // input range views + // decay to IIterable is important, we want to test the non-fast iterators. + winrt::Windows::Foundation::Collections::IIterable iterable = winrt::single_threaded_vector({ 1, 2, 3 }); + + std::vector result; + for (const int i : iterable | std::views::transform([](int i) { return i * 2; })) + { + result.push_back(i); + } + + REQUIRE((result == std::vector{ 2, 4, 6 })); + } +} diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj new file mode 100644 index 000000000..485218a0f --- /dev/null +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} + unittests + test_cpp20 + 10.0 + + + + Application + true + + + Application + true + + + Application + true + + + Application + false + true + + + Application + false + true + + + Application + false + true + + + Application + true + + + Application + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(OutDir)temp\$(ProjectName)\ + + + + + $(OutDir)temp\$(ProjectName)\ + + + $(OutDir)temp\$(ProjectName)\ + + + $(OutDir)temp\$(ProjectName)\ + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + stdcpplatest + + + Console + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + stdcpplatest + + + Console + true + true + + + + + + + + + + + + + + + + NotUsing + + + Create + + + + + + + \ No newline at end of file From 5e1b063525ef3cc96506859f564c1cef6fa521c0 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 29 Mar 2021 12:43:32 -0700 Subject: [PATCH 012/305] IReference operators need to go into the level-1 header (#906) --- cppwinrt/code_writers.h | 21 +++++++++++---------- cppwinrt/cppwinrt.vcxproj | 1 + cppwinrt/cppwinrt.vcxproj.filters | 3 +++ cppwinrt/file_writers.h | 3 ++- strings/base_reference_produce.h | 28 ---------------------------- strings/base_reference_produce_1.h | 25 +++++++++++++++++++++++++ 6 files changed, 42 insertions(+), 39 deletions(-) create mode 100644 strings/base_reference_produce_1.h diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 51c77a156..9bed6b968 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3248,19 +3248,12 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable type); } - static void write_namespace_special(writer& w, std::string_view const& namespace_name, cache const& c) + static void write_namespace_special(writer& w, std::string_view const& namespace_name) { if (namespace_name == "Windows.Foundation") { - if (c.find("Windows.Foundation.PropertyValue")) - { - w.write(strings::base_reference_produce); - } - if (c.find("Windows.Foundation.Deferral")) - { - w.write(strings::base_deferral); - } - + w.write(strings::base_reference_produce); + w.write(strings::base_deferral); w.write(strings::base_coroutine_foundation); } else if (namespace_name == "Windows.Foundation.Collections") @@ -3292,4 +3285,12 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable w.write(strings::base_xaml_typename); } } + + static void write_namespace_special_1(writer& w, std::string_view const& namespace_name) + { + if (namespace_name == "Windows.Foundation") + { + w.write(strings::base_reference_produce_1); + } + } } diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 73a5288ec..054dfaf73 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -75,6 +75,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 7caab56a8..26c1fdafd 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -115,6 +115,9 @@ strings + + strings + strings diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index c91b1de91..8dfd6f09d 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -127,6 +127,7 @@ namespace cppwinrt auto wrap_type = wrap_type_namespace(w, ns); w.write_each(members.interfaces); } + write_namespace_special_1(w, ns); write_close_file_guard(w); w.swap(); @@ -201,7 +202,7 @@ namespace cppwinrt w.write_each(members.classes); } - write_namespace_special(w, ns, c); + write_namespace_special(w, ns); write_close_file_guard(w); w.swap(); diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 8228cbc4c..1965efc7a 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -397,35 +397,7 @@ namespace winrt::impl static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateRectArray(value); } using itf = Windows::Foundation::IReferenceArray; }; -} - -WINRT_EXPORT namespace winrt::Windows::Foundation -{ - template - bool operator==(IReference const& left, IReference const& right) - { - if (get_abi(left) == get_abi(right)) - { - return true; - } - - if (!left || !right) - { - return false; - } - return left.Value() == right.Value(); - } - - template - bool operator!=(IReference const& left, IReference const& right) - { - return !(left == right); - } -} - -namespace winrt::impl -{ template T unbox_value_type(From&& value) { diff --git a/strings/base_reference_produce_1.h b/strings/base_reference_produce_1.h new file mode 100644 index 000000000..7c5143821 --- /dev/null +++ b/strings/base_reference_produce_1.h @@ -0,0 +1,25 @@ + +WINRT_EXPORT namespace winrt::Windows::Foundation +{ + template + bool operator==(IReference const& left, IReference const& right) + { + if (get_abi(left) == get_abi(right)) + { + return true; + } + + if (!left || !right) + { + return false; + } + + return left.Value() == right.Value(); + } + + template + bool operator!=(IReference const& left, IReference const& right) + { + return !(left == right); + } +} From 7c89d29345336a57dfd7d286f4984ffbbbe5c598 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Wed, 31 Mar 2021 06:29:14 -0700 Subject: [PATCH 013/305] Clean more specific output files. (#838) --- nuget/Microsoft.Windows.CppWinRT.targets | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 64d1f4bd5..e5d533823 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -124,12 +124,9 @@ Copyright (C) Microsoft Corporation. All rights reserved. <_FilesToDelete Remove="@(_FilesToDelete)"/> <_FilesToDelete Include="$(GeneratedFilesDir)**"/> - <_FilesToDelete Include="$(OutDir)*.winmd"/> - <_FilesToDelete Include="$(IntDir)*.winmd"/> - <_FilesToDelete Include="$(IntDir)*.idl"/> - <_FilesToDelete Include="$(IntDir)*.rsp"/> <_FilesToDelete Include="$(CppWinRTMergedDir)**"/> <_FilesToDelete Include="$(CppWinRTUnmergedDir)**"/> + <_FilesToDelete Include="$(CppWinRTProjectWinMD)"/> @@ -600,6 +597,10 @@ $(XamlMetaDataProviderPch) SkipUnchangedFiles="$(CppWinRTSkipUnchangedFiles)" SourceFiles="@(_MdMergedOutput)" DestinationFiles="@(_MdMergedOutput->'$(OutDir)%(Filename)%(Extension)')" /> + + + + PreventSdkUapPropsAssignment - + true From 464e59198c2046125d8ee5a8cc6ff1739097345f Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Thu, 1 Apr 2021 08:57:58 -0400 Subject: [PATCH 015/305] Implement support for noexcept overridable methods (#910) --- cppwinrt/code_writers.h | 6 ++++-- test/old_tests/Composable/Base.cpp | 10 ++++++++++ test/old_tests/Composable/Base.h | 2 ++ test/old_tests/Composable/Composable.idl | 11 +++++++++++ test/old_tests/UnitTests/Composable.cpp | 18 ++++++++++++++++++ 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 9bed6b968..9c18557e7 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1905,7 +1905,7 @@ namespace cppwinrt static void write_dispatch_overridable_method(writer& w, MethodDef const& method) { - auto format = R"( auto %(%) + auto format = R"( auto %(%)% { if (auto overridable = this->shim_overridable()) { @@ -1921,6 +1921,7 @@ namespace cppwinrt w.write(format, get_name(method), bind(signature), + is_noexcept(method) ? " noexcept" : "", get_name(method), bind(signature), get_name(method), @@ -1950,7 +1951,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable static void write_interface_override_method(writer& w, MethodDef const& method, std::string_view const& interface_name) { - auto format = R"( template WINRT_IMPL_AUTO(%) %T::%(%) const + auto format = R"( template WINRT_IMPL_AUTO(%) %T::%(%) const% { return shim().template try_as<%>().%(%); } @@ -1964,6 +1965,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable interface_name, method_name, bind(signature), + is_noexcept(method) ? " noexcept" : "", interface_name, method_name, bind(signature)); diff --git a/test/old_tests/Composable/Base.cpp b/test/old_tests/Composable/Base.cpp index 61e4c93fa..77ded2403 100644 --- a/test/old_tests/Composable/Base.cpp +++ b/test/old_tests/Composable/Base.cpp @@ -21,6 +21,11 @@ namespace winrt::Composable::implementation return overridable().OverridableVirtualMethod(); } + int32_t Base::CallOverridableNoexceptMethod() noexcept + { + return overridable().OverridableNoexceptMethod(); + } + hstring Base::OverridableMethod() { return L"Base::OverridableMethod"; @@ -31,6 +36,11 @@ namespace winrt::Composable::implementation return L"Base::OverridableVirtualMethod"; } + int32_t Base::OverridableNoexceptMethod() noexcept + { + return 42; + } + hstring Base::Name() const { return m_name; diff --git a/test/old_tests/Composable/Base.h b/test/old_tests/Composable/Base.h index 8ca2b32c1..bbc05d820 100644 --- a/test/old_tests/Composable/Base.h +++ b/test/old_tests/Composable/Base.h @@ -14,8 +14,10 @@ namespace winrt::Composable::implementation virtual hstring VirtualMethod(); hstring CallOverridableMethod(); hstring CallOverridableVirtualMethod(); + int32_t CallOverridableNoexceptMethod() noexcept; hstring OverridableMethod() ; virtual hstring OverridableVirtualMethod(); + int32_t OverridableNoexceptMethod() noexcept; hstring Name() const; diff --git a/test/old_tests/Composable/Composable.idl b/test/old_tests/Composable/Composable.idl index 7e7e04cdb..83e0c5868 100644 --- a/test/old_tests/Composable/Composable.idl +++ b/test/old_tests/Composable/Composable.idl @@ -1,5 +1,14 @@ import "Windows.Foundation.idl"; +namespace Windows.Foundation.Metadata +{ + [attributeusage(target_method, target_property)] + [attributename("noexcept2")] + attribute NoExceptionAttribute + { + } +} + namespace Composable { runtimeclass Base; @@ -11,6 +20,7 @@ namespace Composable HRESULT VirtualMethod([out, retval] HSTRING* value); HRESULT CallOverridableMethod([out, retval] HSTRING* value); HRESULT CallOverridableVirtualMethod([out, retval] HSTRING* value); + [noexcept2] HRESULT CallOverridableNoexceptMethod([out, retval] int* value); [propget] HRESULT Name([out, retval] HSTRING* value); }; @@ -27,6 +37,7 @@ namespace Composable { HRESULT OverridableMethod([out, retval] HSTRING* value); HRESULT OverridableVirtualMethod([out, retval] HSTRING* value); + [noexcept2] HRESULT OverridableNoexceptMethod([out, retval] int* value); }; [version(1.0), uuid(5f3996e1-3cf7-4716-9a3d-11eb5d32caff), exclusiveto(Derived)] diff --git a/test/old_tests/UnitTests/Composable.cpp b/test/old_tests/UnitTests/Composable.cpp index 3213aff26..56fc97e1c 100644 --- a/test/old_tests/UnitTests/Composable.cpp +++ b/test/old_tests/UnitTests/Composable.cpp @@ -13,12 +13,14 @@ namespace constexpr auto Base_VirtualMethod{ L"Base::VirtualMethod"sv }; constexpr auto Base_OverridableMethod{ L"Base::OverridableMethod"sv }; constexpr auto Base_OverridableVirtualMethod{ L"Base::OverridableVirtualMethod"sv }; + constexpr auto Base_OverridableNoexceptMethod{ 42 }; constexpr auto Derived_VirtualMethod{ L"Derived::VirtualMethod"sv }; constexpr auto Derived_OverridableVirtualMethod{ L"Derived::OverridableVirtualMethod"sv }; constexpr auto OverriddenBase_OverridableMethod{ L"OverriddenBase::OverridableMethod"sv }; constexpr auto OverriddenBase_OverridableVirtualMethod{ L"OverriddenBase::OverridableVirtualMethod"sv }; + constexpr auto OverriddenBase_OverridableNoexceptMethod{ 1337 }; } TEST_CASE("Composable.Base") @@ -27,6 +29,7 @@ TEST_CASE("Composable.Base") REQUIRE(base.VirtualMethod() == Base_VirtualMethod); REQUIRE(base.CallOverridableMethod() == Base_OverridableMethod); REQUIRE(base.CallOverridableVirtualMethod() == Base_OverridableVirtualMethod); + REQUIRE(base.CallOverridableNoexceptMethod() == Base_OverridableNoexceptMethod); } TEST_CASE("Composable.OverriddenBase") @@ -39,6 +42,7 @@ TEST_CASE("Composable.OverriddenBase") REQUIRE(object.VirtualMethod() == Base_VirtualMethod); REQUIRE(object.CallOverridableMethod() == Base_OverridableMethod); REQUIRE(object.CallOverridableVirtualMethod() == Base_OverridableVirtualMethod); + REQUIRE(object.CallOverridableNoexceptMethod() == Base_OverridableNoexceptMethod); } { struct OverriddenBase : BaseT @@ -52,15 +56,22 @@ TEST_CASE("Composable.OverriddenBase") { return hstring(OverriddenBase_OverridableVirtualMethod); } + + int32_t OverridableNoexceptMethod() const noexcept + { + return OverriddenBase_OverridableNoexceptMethod; + } }; auto object = make(); REQUIRE(object.VirtualMethod() == Base_VirtualMethod); REQUIRE(object.CallOverridableMethod() == OverriddenBase_OverridableMethod); REQUIRE(object.CallOverridableVirtualMethod() == OverriddenBase_OverridableVirtualMethod); + REQUIRE(object.CallOverridableNoexceptMethod() == OverriddenBase_OverridableNoexceptMethod); } { const std::wstring OverridableMethodResult = std::wstring(OverriddenBase_OverridableMethod) + L"=>" + Base_OverridableMethod.data(); const std::wstring OverridableVirtualMethodResult = std::wstring(OverriddenBase_OverridableVirtualMethod) + L"=>" + Base_OverridableVirtualMethod.data(); + const int32_t OverridableNoexceptMethodResult = OverriddenBase_OverridableNoexceptMethod + Base_OverridableNoexceptMethod; struct OverriddenBase : BaseT { @@ -73,11 +84,17 @@ TEST_CASE("Composable.OverriddenBase") { return OverriddenBase_OverridableVirtualMethod + L"=>" + BaseT::OverridableVirtualMethod(); } + + int32_t OverridableNoexceptMethod() const noexcept + { + return OverriddenBase_OverridableNoexceptMethod + BaseT::OverridableNoexceptMethod(); + } }; auto object = make(); REQUIRE(object.VirtualMethod() == Base_VirtualMethod); REQUIRE(object.CallOverridableMethod() == OverridableMethodResult); REQUIRE(object.CallOverridableVirtualMethod() == OverridableVirtualMethodResult); + REQUIRE(object.CallOverridableNoexceptMethod() == OverridableNoexceptMethodResult); } } @@ -88,6 +105,7 @@ TEST_CASE("Composable.Derived") REQUIRE(obj.VirtualMethod() == Derived_VirtualMethod); REQUIRE(obj.CallOverridableMethod() == Base_OverridableMethod); REQUIRE(obj.CallOverridableVirtualMethod() == Derived_OverridableVirtualMethod); + REQUIRE(obj.CallOverridableNoexceptMethod() == Base_OverridableNoexceptMethod); } namespace From b52df71e57875658ab4a37298c566e6373dd0fcc Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Sat, 3 Apr 2021 08:45:17 -0700 Subject: [PATCH 016/305] Factories no longer default to no_weak_ref (#913) --- strings/base_implements.h | 5 +---- test/old_tests/UnitTests/weak.cpp | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index d23c54e20..bc44b27f6 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1041,8 +1041,6 @@ namespace winrt::impl return Windows::Foundation::TrustLevel::BaseTrust; } - using is_factory = std::disjunction...>; - private: class has_final_release @@ -1057,7 +1055,7 @@ namespace winrt::impl using is_agile = std::negation...>>; using is_inspectable = std::disjunction...>; - using is_weak_ref_source = std::conjunction, std::negation...>>>; + using is_weak_ref_source = std::conjunction...>>>; using use_module_lock = std::negation...>>; using weak_ref_t = impl::weak_ref; @@ -1333,7 +1331,6 @@ WINRT_EXPORT namespace winrt using base_type = typename impl::base_implements::type; using root_implements_type = typename base_type::root_implements_type; - using is_factory = typename root_implements_type::is_factory; using base_type::base_type; diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index 394c36213..3c1701943 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -150,7 +150,7 @@ TEST_CASE("weak,QI") { IActivationFactory object = make(); REQUIRE(object.try_as()); - REQUIRE(!object.try_as()); + REQUIRE(object.try_as()); } SECTION("no_weak_ref") From 3d80b918d9cb85b52f777a282af8b3dbeaea09ae Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Sat, 3 Apr 2021 18:11:14 -0700 Subject: [PATCH 017/305] Natvis support for hresult_error and array_view (#914) --- natvis/cppwinrt.natvis | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/natvis/cppwinrt.natvis b/natvis/cppwinrt.natvis index 0b96d027d..de9cff59c 100644 --- a/natvis/cppwinrt.natvis +++ b/natvis/cppwinrt.natvis @@ -20,6 +20,15 @@ null + + {{size = {m_size}, {m_data,[m_size]}}} + + + m_size + m_data + + + {m_ptr} @@ -33,6 +42,9 @@ {value,hr} + + {m_code} + {m_handle.m_value,sh} m_handle.m_value,sh From 08db5ed38077fa72e62845977a73ef3ee96603fb Mon Sep 17 00:00:00 2001 From: Julien Brianceau <5746498+jbrianceau@users.noreply.github.com> Date: Wed, 7 Apr 2021 17:16:17 +0200 Subject: [PATCH 018/305] Fix few typos in comments (#917) --- test/nuget/ConsoleApplication1/readme.txt | 2 +- test/test/velocity.cpp | 2 +- test/test_win7/velocity.cpp | 2 +- vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate | 2 +- .../VC/Windows Desktop/ConsoleApplication/readme.txt | 2 +- .../VC/Windows Desktop/WindowsApplication/readme.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/nuget/ConsoleApplication1/readme.txt b/test/nuget/ConsoleApplication1/readme.txt index 706ccef4d..403138c7e 100644 --- a/test/nuget/ConsoleApplication1/readme.txt +++ b/test/nuget/ConsoleApplication1/readme.txt @@ -7,7 +7,7 @@ classes directly from standard C++, using platform projection headers generated from Windows SDK metadata files. Steps to generate and consume SDK platform projection: -1. Build project initally to generate platform projection headers into +1. Build project initially to generate platform projection headers into your Generated Files folder. 2. Include a projection namespace header in your pch.h, such as . diff --git a/test/test/velocity.cpp b/test/test/velocity.cpp index 0c5ba5370..11b11c1d7 100644 --- a/test/test/velocity.cpp +++ b/test/test/velocity.cpp @@ -6,7 +6,7 @@ using namespace test_component::Velocity; TEST_CASE("velocity") { - // This interface is always disabled but shows up in the type sytem + // This interface is always disabled but shows up in the type system // if it is present in the winmd. IInterface1 a; REQUIRE(a == nullptr); diff --git a/test/test_win7/velocity.cpp b/test/test_win7/velocity.cpp index 0c5ba5370..11b11c1d7 100644 --- a/test/test_win7/velocity.cpp +++ b/test/test_win7/velocity.cpp @@ -6,7 +6,7 @@ using namespace test_component::Velocity; TEST_CASE("velocity") { - // This interface is always disabled but shows up in the type sytem + // This interface is always disabled but shows up in the type system // if it is present in the winmd. IInterface1 a; REQUIRE(a == nullptr); diff --git a/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate b/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate index 2a85b6f8e..47699df6d 100644 --- a/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate +++ b/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate @@ -2,7 +2,7 @@ ViewModel View Model (C++/WinRT) - An empty interface defintion suitable for XAML data binding, for a C++/WinRT Universal Windows Platform (UWP) app + An empty interface definition suitable for XAML data binding, for a C++/WinRT Universal Windows Platform (UWP) app VC 10 microsoft.Windows.CppWinRT.ViewModel diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/readme.txt b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/readme.txt index 29c419928..96dffd53b 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/readme.txt +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/readme.txt @@ -7,7 +7,7 @@ classes directly from standard C++, using platform projection headers generated from Windows SDK metadata files. Steps to generate and consume SDK platform projection: -1. Build project initally to generate platform projection headers into +1. Build project initially to generate platform projection headers into your Generated Files folder. 2. Include a projection namespace header in your pch.h, such as . diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/readme.txt b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/readme.txt index 29c419928..96dffd53b 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/readme.txt +++ b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/readme.txt @@ -7,7 +7,7 @@ classes directly from standard C++, using platform projection headers generated from Windows SDK metadata files. Steps to generate and consume SDK platform projection: -1. Build project initally to generate platform projection headers into +1. Build project initially to generate platform projection headers into your Generated Files folder. 2. Include a projection namespace header in your pch.h, such as . From 5a2a796c097eb8529fa11863ecdd5467756e919f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 8 Apr 2021 10:39:21 -0700 Subject: [PATCH 019/305] Use correct default output folder (#920) --- cppwinrt/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 4c61daf8d..1b26659a3 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -90,7 +90,7 @@ Where is one or more of: settings.license = args.exists("license"); settings.brackets = args.exists("brackets"); - path output_folder = args.value("output"); + path output_folder = args.value("output", "."); create_directories(output_folder / "winrt/impl"); settings.output_folder = canonical(output_folder).string(); settings.output_folder += '\\'; From 342edc5290086334366881faf8c4564bba00625b Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 8 Apr 2021 11:55:59 -0700 Subject: [PATCH 020/305] Inline internal error codes (#922) --- strings/base_types.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/strings/base_types.h b/strings/base_types.h index 254f490b6..751b949b3 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -222,22 +222,22 @@ namespace winrt::impl using trust_level_type = Windows::Foundation::TrustLevel; #endif - constexpr hresult error_ok{ 0 }; // S_OK - constexpr hresult error_fail{ static_cast(0x80004005) }; // E_FAIL - constexpr hresult error_access_denied{ static_cast(0x80070005) }; // E_ACCESSDENIED - constexpr hresult error_wrong_thread{ static_cast(0x8001010E) }; // RPC_E_WRONG_THREAD - constexpr hresult error_not_implemented{ static_cast(0x80004001) }; // E_NOTIMPL - constexpr hresult error_invalid_argument{ static_cast(0x80070057) }; // E_INVALIDARG - constexpr hresult error_out_of_bounds{ static_cast(0x8000000B) }; // E_BOUNDS - constexpr hresult error_no_interface{ static_cast(0x80004002) }; // E_NOINTERFACE - constexpr hresult error_class_not_available{ static_cast(0x80040111) }; // CLASS_E_CLASSNOTAVAILABLE - constexpr hresult error_class_not_registered{ static_cast(0x80040154) }; // REGDB_E_CLASSNOTREG - constexpr hresult error_changed_state{ static_cast(0x8000000C) }; // E_CHANGED_STATE - constexpr hresult error_illegal_method_call{ static_cast(0x8000000E) }; // E_ILLEGAL_METHOD_CALL - constexpr hresult error_illegal_state_change{ static_cast(0x8000000D) }; // E_ILLEGAL_STATE_CHANGE - constexpr hresult error_illegal_delegate_assignment{ static_cast(0x80000018) }; // E_ILLEGAL_DELEGATE_ASSIGNMENT - constexpr hresult error_canceled{ static_cast(0x800704C7) }; // HRESULT_FROM_WIN32(ERROR_CANCELLED) - constexpr hresult error_bad_alloc{ static_cast(0x8007000E) }; // E_OUTOFMEMORY - constexpr hresult error_not_initialized{ static_cast(0x800401F0) }; // CO_E_NOTINITIALIZED - constexpr hresult error_file_not_found{ static_cast(0x80070002) }; // HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) + inline constexpr hresult error_ok{ 0 }; // S_OK + inline constexpr hresult error_fail{ static_cast(0x80004005) }; // E_FAIL + inline constexpr hresult error_access_denied{ static_cast(0x80070005) }; // E_ACCESSDENIED + inline constexpr hresult error_wrong_thread{ static_cast(0x8001010E) }; // RPC_E_WRONG_THREAD + inline constexpr hresult error_not_implemented{ static_cast(0x80004001) }; // E_NOTIMPL + inline constexpr hresult error_invalid_argument{ static_cast(0x80070057) }; // E_INVALIDARG + inline constexpr hresult error_out_of_bounds{ static_cast(0x8000000B) }; // E_BOUNDS + inline constexpr hresult error_no_interface{ static_cast(0x80004002) }; // E_NOINTERFACE + inline constexpr hresult error_class_not_available{ static_cast(0x80040111) }; // CLASS_E_CLASSNOTAVAILABLE + inline constexpr hresult error_class_not_registered{ static_cast(0x80040154) }; // REGDB_E_CLASSNOTREG + inline constexpr hresult error_changed_state{ static_cast(0x8000000C) }; // E_CHANGED_STATE + inline constexpr hresult error_illegal_method_call{ static_cast(0x8000000E) }; // E_ILLEGAL_METHOD_CALL + inline constexpr hresult error_illegal_state_change{ static_cast(0x8000000D) }; // E_ILLEGAL_STATE_CHANGE + inline constexpr hresult error_illegal_delegate_assignment{ static_cast(0x80000018) }; // E_ILLEGAL_DELEGATE_ASSIGNMENT + inline constexpr hresult error_canceled{ static_cast(0x800704C7) }; // HRESULT_FROM_WIN32(ERROR_CANCELLED) + inline constexpr hresult error_bad_alloc{ static_cast(0x8007000E) }; // E_OUTOFMEMORY + inline constexpr hresult error_not_initialized{ static_cast(0x800401F0) }; // CO_E_NOTINITIALIZED + inline constexpr hresult error_file_not_found{ static_cast(0x80070002) }; // HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) } From 18670d249d019ccb860853b753f23a3f5fbbacb6 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Tue, 27 Apr 2021 09:54:33 -0700 Subject: [PATCH 021/305] Runtime class name for bare IInspectable should not be "Object" (#930) --- strings/base_implements.h | 9 +++++++++ .../UnitTests/IInspectable_GetRuntimeClassName.cpp | 2 +- test/old_tests/UnitTests/constexpr.cpp | 1 + test/old_tests/UnitTests/produce.cpp | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index bc44b27f6..a763da424 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -430,6 +430,15 @@ namespace winrt::impl } }; + template <> + struct runtime_class_name + { + static hstring get() + { + return {}; + } + }; + template struct producer { diff --git a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp index 6b0d7550b..7db7ed869 100644 --- a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp +++ b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp @@ -28,7 +28,7 @@ TEST_CASE("Test_GetRuntimeClassName_NoOverride") { Windows::Foundation::IInspectable i = make(); - REQUIRE(get_class_name(i) == L"Object"); + REQUIRE(get_class_name(i) == L""); } TEST_CASE("Test_GetRuntimeClassName_Override") diff --git a/test/old_tests/UnitTests/constexpr.cpp b/test/old_tests/UnitTests/constexpr.cpp index 22478af2f..a881a2659 100644 --- a/test/old_tests/UnitTests/constexpr.cpp +++ b/test/old_tests/UnitTests/constexpr.cpp @@ -35,6 +35,7 @@ TEST_CASE("constexpr") REQUIRE(winrt::guid_of() == winrt::guid(__uuidof(::IInspectable))); REQUIRE(winrt::guid_of() == winrt::guid(__uuidof(midl_container))); REQUIRE(winrt::name_of() == L"Object"sv); + REQUIRE(winrt::name_of>() == L"Windows.Foundation.IAsyncOperation`1"sv); REQUIRE(winrt::name_of() == midl_container::z_get_rc_name_impl()); diff --git a/test/old_tests/UnitTests/produce.cpp b/test/old_tests/UnitTests/produce.cpp index 5ceab4d0c..403f0df2b 100644 --- a/test/old_tests/UnitTests/produce.cpp +++ b/test/old_tests/UnitTests/produce.cpp @@ -133,7 +133,7 @@ struct produce_IInspectable_RuntimeClassName : implements(); - REQUIRE(get_class_name(without) == L"Object"); + REQUIRE(get_class_name(without) == L""); Windows::Foundation::IInspectable with = make(); REQUIRE(get_class_name(with) == L"produce_IInspectable_RuntimeClassName"); From 969ea267c1063e63a7c5e7a6d2481c7241772c09 Mon Sep 17 00:00:00 2001 From: Chris Guzak Date: Mon, 3 May 2021 07:55:33 -0700 Subject: [PATCH 022/305] Update .targets file to support local servers (#860) (#934) --- nuget/Microsoft.Windows.CppWinRT.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index e5d533823..829d30f9a 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -250,7 +250,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. $([System.IO.Path]::GetFileName('$(CppWinRTProjectWinMD)')) true - $(WinMDImplementationPath)$(TargetName)$(TargetExt) + $(WinMDImplementationPath)$(TargetName)$(TargetExt) winmd true $(MSBuildProjectName) From d9fe8d8b24e1cde856db589c0d3cc1fe7f2d7e64 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 3 May 2021 11:23:27 -0700 Subject: [PATCH 023/305] Use separate vsixmanifest files for Component and Standalone deployments (#909) * Use separate vsixmanifest files for Component and Standalone deployments * Remove prerequisite from Component VSIX * Keep empty element * Component VSIX now depends on Inbox CppWinRT "component" Co-authored-by: Kenny Kerr --- vsix/Component/source.extension.vsixmanifest | 34 +++++++++++++++++++ .../source.extension.vsixmanifest | 0 vsix/vsix.csproj | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 vsix/Component/source.extension.vsixmanifest rename vsix/{ => Standalone}/source.extension.vsixmanifest (100%) diff --git a/vsix/Component/source.extension.vsixmanifest b/vsix/Component/source.extension.vsixmanifest new file mode 100644 index 000000000..177f525a2 --- /dev/null +++ b/vsix/Component/source.extension.vsixmanifest @@ -0,0 +1,34 @@ + + + + + Microsoft.Windows.CppWinRT + C++/WinRT + Tools for authoring and consuming Windows Runtime classes in standard C++. + https://go.microsoft.com/fwlink/?linkid=869449 + LICENSE + https://docs.microsoft.com/windows/uwp/cpp-and-winrt-apis/intro-to-using-cpp-with-winrt + https://docs.microsoft.com/windows/uwp/cpp-and-winrt-apis/faq + cppwinrt.ico + cppwinrt.png + WinRT, C++, cppwinrt, native + + + + + + + + + + + + + + + + + + + + diff --git a/vsix/source.extension.vsixmanifest b/vsix/Standalone/source.extension.vsixmanifest similarity index 100% rename from vsix/source.extension.vsixmanifest rename to vsix/Standalone/source.extension.vsixmanifest diff --git a/vsix/vsix.csproj b/vsix/vsix.csproj index 9279dee1a..4596b6cd1 100644 --- a/vsix/vsix.csproj +++ b/vsix/vsix.csproj @@ -106,7 +106,7 @@ x64\%(Filename)%(Extension) true - + Designer From 2e05b07d3195ba50ecb19acba8ab1084e6b7dc9f Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 4 May 2021 13:09:38 -0700 Subject: [PATCH 024/305] Add switch to disable merge validation to support certain test scenarios (#936) * Add switch to disable merge validation to support certain test scenarios * made condition explicitly check 'true' --- nuget/Microsoft.Windows.CppWinRT.targets | 3 ++- nuget/readme.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 829d30f9a..4e51c070c 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -561,7 +561,8 @@ $(XamlMetaDataProviderPch) - <_MdMergeParameters>-v @(CppWinRTMdMergeMetadataDirectories->'-metadata_dir "%(RelativeDir)."', ' ') + <_MdMergeParameters Condition="'$(CppWinRTMergeNoValidate)'!='true'">-v + <_MdMergeParameters>$(_MdMergeParameters) @(CppWinRTMdMergeMetadataDirectories->'-metadata_dir "%(RelativeDir)."', ' ') <_MdMergeParameters>$(_MdMergeParameters) @(CppWinRTMdMergeInputs->'-i "%(Identity)"', ' ') <_MdMergeParameters>$(_MdMergeParameters) -o "$(CppWinRTMergedDir.TrimEnd('\'))" -partial $(_MdMergeDepth) diff --git a/nuget/readme.md b/nuget/readme.md index 4a33b8eb6..566a4fd18 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -61,6 +61,7 @@ C++/WinRT behavior can be customized with these project properties: | CppWinRTVerbosity | low \| *normal \| high | Sets the [importance](https://docs.microsoft.com/en-us/visualstudio/msbuild/message-task?view=vs-2017) of C++/WinRT build messages (see below) | | CppWinRTNamespaceMergeDepth | *1 | Sets the depth of namespace merging (Xaml apps require 1) | | CppWinRTRootNamespaceAutoMerge | true \| *false | Sets the namespace merge depth to be the length of the root namespace | +| CppWinRTMergeNoValidate | true \| *false | Disables mdmerge validation | | CppWinRTUsePrefixes | *true \| false | Uses a dotted prefix namespace convention (versus a nested folder convention) | | CppWinRTPath | ...\cppwinrt.exe | NuGet package-relative path to cppwinrt.exe, for custom build rule invocation | | CppWinRTParameters | "" | Custom cppwinrt.exe command-line parameters (be sure to append to existing) | From 1c4b5f558dd90b30c1e1c183d608c317c3139df6 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 5 May 2021 17:23:46 -0700 Subject: [PATCH 025/305] Ingest updated Microsoft.Windows.WinMD to fix bug around "-exclude" (#937) * Ingest updated Microsoft.Windows.WinMD to fix bug around "-exclude" option. * Clean up weirdness from VS updating the NuGet --- cppwinrt/cppwinrt.vcxproj | 8 ++++---- cppwinrt/packages.config | 2 +- natvis/cppwinrtvisualizer.vcxproj | 4 ++-- natvis/packages.config | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 054dfaf73..0f8d398fb 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -1,6 +1,6 @@ - + Debug @@ -111,10 +111,10 @@ - + - + 15.0 @@ -364,6 +364,6 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/cppwinrt/packages.config b/cppwinrt/packages.config index 518e14678..135710d6e 100644 --- a/cppwinrt/packages.config +++ b/cppwinrt/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index ae9721002..7e399d184 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -1,6 +1,6 @@ - + Debug @@ -261,6 +261,6 @@ - + \ No newline at end of file diff --git a/natvis/packages.config b/natvis/packages.config index 23e5fb359..32ce6c838 100644 --- a/natvis/packages.config +++ b/natvis/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file From d6bbe13deea4bb3e616c0b2331fd8de884ee05eb Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Wed, 19 May 2021 20:43:42 -0700 Subject: [PATCH 026/305] Make the v142 toolset the default. (#946) * Update ConsoleApplication.vcxproj * Update WindowsApplication.vcxproj * Update BlankApp.vcxproj * Update CoreApp.vcxproj * Update StaticLibrary.vcxproj * Update WindowsRuntimeComponent.vcxproj * Update BlankApp.vcxproj * Update CoreApp.vcxproj * Update StaticLibrary.vcxproj --- .../ConsoleApplication/ConsoleApplication.vcxproj | 6 +++--- .../WindowsApplication/WindowsApplication.vcxproj | 6 +++--- .../VC/Windows Universal/BlankApp/BlankApp.vcxproj | 8 ++++---- .../VC/Windows Universal/CoreApp/CoreApp.vcxproj | 6 +++--- .../Windows Universal/StaticLibrary/StaticLibrary.vcxproj | 8 ++++---- .../WindowsRuntimeComponent.vcxproj | 8 ++++---- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj index 6e7a77f72..302bb4a04 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj @@ -33,9 +33,9 @@ Application - v140 + v142 v141 - v142 + v140 Unicode @@ -116,4 +116,4 @@ - \ No newline at end of file + diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj index 8071fbd46..bdf0cb871 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj @@ -33,9 +33,9 @@ Application - v140 + v142 v141 - v142 + v140 Unicode @@ -113,4 +113,4 @@ - \ No newline at end of file + diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index 84012a7c8..84359111e 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -53,9 +53,9 @@ Application - v140 - v141 - v142 + v142 + v141 + v140 Unicode @@ -167,4 +167,4 @@ - \ No newline at end of file + diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index 8b378de41..7bd74e746 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -52,9 +52,9 @@ Application - v140 - v141 - v142 + v142 + v141 + v140 Unicode diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index b381cf528..2a7d1fd83 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -54,9 +54,9 @@ StaticLibrary - v140 - v141 - v142 + v142 + v141 + v140 Unicode false @@ -142,4 +142,4 @@ - \ No newline at end of file + diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 859b5af80..d9152bbf9 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -53,9 +53,9 @@ DynamicLibrary - v140 - v141 - v142 + v142 + v141 + v140 Unicode false @@ -144,4 +144,4 @@ - \ No newline at end of file + From 0d94a2e275bc9a5ecd87fc114a06882ca8ccadf3 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Thu, 20 May 2021 10:07:56 -0700 Subject: [PATCH 027/305] Project templates should not set DisableSpecificWarnings to empty. (#949) * Project templates should not set DisableSpecificWarning to empty. Setting this to empty prevents the use of Directory.Build.props to disable specific warnings solution-wide. * Update WindowsRuntimeComponent.vcxproj * Update CoreApp.vcxproj * Update BlankApp.vcxproj --- .../VC/Windows Universal/BlankApp/BlankApp.vcxproj | 1 - .../VC/Windows Universal/CoreApp/CoreApp.vcxproj | 1 - .../VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj | 1 - .../WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj | 1 - 4 files changed, 4 deletions(-) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index 84359111e..b74002063 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -86,7 +86,6 @@ %(AdditionalOptions) /bigobj /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) - WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index 7bd74e746..246a3eeaa 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -83,7 +83,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index 2a7d1fd83..935ec08d0 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -91,7 +91,6 @@ %(AdditionalOptions) /bigobj /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) - WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index d9152bbf9..784a8e8c9 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -90,7 +90,6 @@ %(AdditionalOptions) /bigobj /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) From f204e39d293c3c54dc1df65f05ed6a9c650ac6b1 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Thu, 20 May 2021 13:38:08 -0700 Subject: [PATCH 028/305] Add #pragma once in addition to header guard (#948) --- cppwinrt/code_writers.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 9c18557e7..4b4fa8229 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -69,6 +69,8 @@ namespace cppwinrt static void write_open_file_guard(writer& w, std::string_view const& file_name, char impl = 0) { + write_include_guard(w); + std::string mangled_name; for (auto&& c : file_name) From 06ae44406d339f7e2887ed7b8f61e9edbde4b6a0 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 14 Jun 2021 09:15:55 -0700 Subject: [PATCH 029/305] Add deduction guides for agile_ref and weak_ref (#955) --- strings/base_agile_ref.h | 4 +++- strings/base_weak_ref.h | 2 ++ test/old_tests/UnitTests/weak.cpp | 6 ++++++ test/test/agile_ref.cpp | 6 ++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index 62be3c5e0..f76f6b0c2 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -209,8 +209,10 @@ WINRT_EXPORT namespace winrt com_ptr m_ref; }; + template agile_ref(T const&)->agile_ref>; + template - agile_ref make_agile(T const& object) + agile_ref> make_agile(T const& object) { return object; } diff --git a/strings/base_weak_ref.h b/strings/base_weak_ref.h index 3b3570dfb..24fe8fb91 100644 --- a/strings/base_weak_ref.h +++ b/strings/base_weak_ref.h @@ -61,6 +61,8 @@ WINRT_EXPORT namespace winrt com_ptr m_ref; }; + template weak_ref(T const&)->weak_ref>; + template struct impl::abi> : impl::abi> { diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index 3c1701943..650b6ae0f 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -98,6 +98,12 @@ TEST_CASE("weak,source") IStringable b = w.get(); REQUIRE(b.ToString() == L"Weak"); } + + // Verify that deduction guides work. + static_assert(std::is_same_v, decltype(weak_ref(IStringable()))>); + static_assert(std::is_same_v, decltype(weak_ref(std::declval()))>); + static_assert(std::is_same_v, decltype(weak_ref(com_ptr<::IPersist>()))>); + static_assert(std::is_same_v, decltype(make_weak(com_ptr<::IPersist>()))>); } TEST_CASE("weak,nullptr") diff --git a/test/test/agile_ref.cpp b/test/test/agile_ref.cpp index e0ab43a34..3cc2792d0 100644 --- a/test/test/agile_ref.cpp +++ b/test/test/agile_ref.cpp @@ -51,4 +51,10 @@ TEST_CASE("agile_ref") agile_ref empty; IStringable object = empty.get(); REQUIRE(object == nullptr); + + // Verify that deduction guides work. + static_assert(std::is_same_v, decltype(agile_ref(object))>); + static_assert(std::is_same_v, decltype(agile_ref(std::declval()))>); + static_assert(std::is_same_v, decltype(agile_ref(com_ptr<::IPersist>()))>); + static_assert(std::is_same_v, decltype(make_agile(com_ptr<::IPersist>()))>); } From 7ddfc798e34bff89d3da8a5b704f1103f1ec2a7f Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 14 Jun 2021 09:16:35 -0700 Subject: [PATCH 030/305] Improve diagnostics when implements<> is used incorectly (#959) --- strings/base_implements.h | 1 + 1 file changed, 1 insertion(+) diff --git a/strings/base_implements.h b/strings/base_implements.h index a763da424..7bc85220b 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1437,6 +1437,7 @@ WINRT_EXPORT namespace winrt hstring GetRuntimeClassName() const override { + static_assert(std::is_base_of_v, "Class must derive from implements<> or ClassT<> where the first template parameter is the derived class name, e.g. struct D : implements"); return impl::runtime_class_name::type>::get(); } From 9e4fdedbe496bc42d94fb77c43245cbb6cf9bd71 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 18 Jun 2021 11:30:58 -0700 Subject: [PATCH 031/305] Adds synchronous option to avoid I/O issues in batch builds (#961) --- cppwinrt/main.cpp | 2 ++ cppwinrt/task_group.h | 19 ++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 1b26659a3..eab187d6a 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -38,6 +38,7 @@ namespace cppwinrt { "brackets", 0, 0 }, // Use angle brackets for #includes (defaults to quotes) { "fastabi", 0, 0 }, // Enable support for the Fast ABI { "ignore_velocity", 0, 0 }, // Ignore feature staging metadata and always include implementations + { "synchronous", 0, 0 }, // Instructs cppwinrt to run on a single thread to avoid file system issues in batch builds }; static void print_usage(writer& w) @@ -290,6 +291,7 @@ Where is one or more of: w.flush_to_console(); task_group group; + group.synchronous(args.exists("synchronous")); writer ixx; write_preamble(ixx); ixx.write("module;\n"); diff --git a/cppwinrt/task_group.h b/cppwinrt/task_group.h index 4e5d94b5f..800b8eb40 100644 --- a/cppwinrt/task_group.h +++ b/cppwinrt/task_group.h @@ -17,14 +17,22 @@ namespace cppwinrt } } + void synchronous(bool synchronous) noexcept + { + m_synchronous = synchronous; + } + template void add(T&& callback) { -#if defined(_DEBUG) - callback(); -#else - m_tasks.push_back(std::async(std::forward(callback))); -#endif + if (m_synchronous) + { + callback(); + } + else + { + m_tasks.push_back(std::async(std::forward(callback))); + } } void get() @@ -45,5 +53,6 @@ namespace cppwinrt private: std::vector> m_tasks; + bool m_synchronous{}; }; } From b0b9bf74363546b76d63592fe4a32d1a7e6bfded Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 21 Jun 2021 10:43:55 -0500 Subject: [PATCH 032/305] Add IMemoryBufferByteAccess accessor (#956) --- cppwinrt/code_writers.h | 12 ++++++++++++ strings/base_abi.h | 6 ++++++ test/test/memory_buffer.cpp | 17 +++++++++++++++++ test/test/test.vcxproj | 1 + 4 files changed, 36 insertions(+) create mode 100644 test/test/memory_buffer.cpp diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 4b4fa8229..95a2fa59e 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1308,6 +1308,18 @@ namespace cppwinrt static_cast(*this).template as()->Buffer(&data); return data; } +)"); + } + else if (type_name == "Windows.Foundation.IMemoryBufferReference") + { + w.write(R"( + auto data() const + { + uint8_t* data{}; + uint32_t capacity{}; + check_hresult(static_cast(*this).template as()->GetBuffer(&data, &capacity)); + return data; + } )"); } else if (type_name == "Windows.Foundation.Collections.IIterator`1") diff --git a/strings/base_abi.h b/strings/base_abi.h index 6a88266b9..b14e8d85f 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -127,6 +127,11 @@ namespace winrt::impl virtual int32_t __stdcall Buffer(uint8_t** value) noexcept = 0; }; + struct __declspec(novtable) IMemoryBufferByteAccess : unknown_abi + { + virtual int32_t __stdcall GetBuffer(uint8_t** value, uint32_t* capacity) noexcept = 0; + }; + template <> struct abi { using type = int64_t; @@ -155,4 +160,5 @@ namespace winrt::impl template <> inline constexpr guid guid_v{ 0x000001da, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } }; template <> inline constexpr guid guid_v{ 0x0000013E, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } }; template <> inline constexpr guid guid_v{ 0x905a0fef, 0xbc53, 0x11df, { 0x8c,0x49,0x00,0x1e,0x4f,0xc6,0x86,0xda } }; + template <> inline constexpr guid guid_v{ 0x5b0d3235, 0x4dba, 0x4d44, { 0x86,0x5e,0x8f,0x1d,0x0e,0x4f,0xd0,0x4d } }; } diff --git a/test/test/memory_buffer.cpp b/test/test/memory_buffer.cpp new file mode 100644 index 000000000..583d5f978 --- /dev/null +++ b/test/test/memory_buffer.cpp @@ -0,0 +1,17 @@ +#include "pch.h" +#include "catch.hpp" + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("memory_buffer") +{ + MemoryBuffer buffer{ 3 }; + auto reference = buffer.CreateReference(); + uint8_t* ptr = reference.data(); + ptr[0] = 1; + ptr[1] = 2; + ptr[2] = 3; + REQUIRE(ptr != nullptr); + REQUIRE(reference.Capacity() == 3); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 9823e1624..3d9ad5f40 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -398,6 +398,7 @@ NotUsing + NotUsing NotUsing From fb3e9897ad15dd44cff2ec0f7e273878d7b0fe67 Mon Sep 17 00:00:00 2001 From: Jaiganesh Kumaran Date: Tue, 22 Jun 2021 20:39:42 +0530 Subject: [PATCH 033/305] Add starts_with and ends_with to hstring (#952) --- strings/base_string.h | 32 ++++++++++++++++++++++++++++++ test/test_cpp20/hstring.cpp | 13 ++++++++++++ test/test_cpp20/test_cpp20.vcxproj | 1 + 3 files changed, 46 insertions(+) create mode 100644 test/test_cpp20/hstring.cpp diff --git a/strings/base_string.h b/strings/base_string.h index f99a049f0..b9fada8d2 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -326,7 +326,39 @@ WINRT_EXPORT namespace winrt { return rend(); } + +#if __cpp_lib_starts_ends_with + bool starts_with(wchar_t const value) const noexcept + { + return operator std::wstring_view().starts_with(value); + } + + bool starts_with(std::wstring_view const another) const noexcept + { + return operator std::wstring_view().starts_with(another); + } + + bool starts_with(const wchar_t* const pointer) const noexcept + { + return operator std::wstring_view().starts_with(pointer); + } + bool ends_with(wchar_t const value) const noexcept + { + return operator std::wstring_view().ends_with(value); + } + + bool ends_with(std::wstring_view const another) const noexcept + { + return operator std::wstring_view().ends_with(another); + } + + bool ends_with(const wchar_t* const pointer) const noexcept + { + return operator std::wstring_view().ends_with(pointer); + } +#endif + bool empty() const noexcept { return !m_handle; diff --git a/test/test_cpp20/hstring.cpp b/test/test_cpp20/hstring.cpp new file mode 100644 index 000000000..2f2033185 --- /dev/null +++ b/test/test_cpp20/hstring.cpp @@ -0,0 +1,13 @@ +#include "pch.h" + +TEST_CASE("hstring") +{ + winrt::hstring text = L"C++/WinRT rocks!"; + std::wstring_view textView = text; + REQUIRE(!text.starts_with(L"C++/CX")); + REQUIRE(!textView.starts_with(L"C++/CX")); + REQUIRE(text.starts_with(L"C++/WinRT") == textView.starts_with(L"C++/WinRT")); + REQUIRE(text.ends_with(L"rocks!")); + REQUIRE(textView.ends_with(L"rocks!")); + REQUIRE(text.ends_with(L"rocks!") == textView.ends_with(L"rocks!")); +} \ No newline at end of file diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 485218a0f..00035dc2e 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -302,6 +302,7 @@ + NotUsing From 186f53ee4288499889db683c2b7a8061afd9c2fb Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Thu, 24 Jun 2021 12:42:43 -0700 Subject: [PATCH 034/305] IReference operators in level-1 header should be forward declarations (#965) --- strings/base_reference_produce.h | 28 +++++++++++++++++++ strings/base_reference_produce_1.h | 20 ++----------- .../test_component_no_pch.idl | 7 +++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 1965efc7a..8228cbc4c 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -397,7 +397,35 @@ namespace winrt::impl static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateRectArray(value); } using itf = Windows::Foundation::IReferenceArray; }; +} + +WINRT_EXPORT namespace winrt::Windows::Foundation +{ + template + bool operator==(IReference const& left, IReference const& right) + { + if (get_abi(left) == get_abi(right)) + { + return true; + } + + if (!left || !right) + { + return false; + } + return left.Value() == right.Value(); + } + + template + bool operator!=(IReference const& left, IReference const& right) + { + return !(left == right); + } +} + +namespace winrt::impl +{ template T unbox_value_type(From&& value) { diff --git a/strings/base_reference_produce_1.h b/strings/base_reference_produce_1.h index 7c5143821..0eb9b4b70 100644 --- a/strings/base_reference_produce_1.h +++ b/strings/base_reference_produce_1.h @@ -2,24 +2,8 @@ WINRT_EXPORT namespace winrt::Windows::Foundation { template - bool operator==(IReference const& left, IReference const& right) - { - if (get_abi(left) == get_abi(right)) - { - return true; - } - - if (!left || !right) - { - return false; - } - - return left.Value() == right.Value(); - } + bool operator==(IReference const& left, IReference const& right); template - bool operator!=(IReference const& left, IReference const& right) - { - return !(left == right); - } + bool operator!=(IReference const& left, IReference const& right); } diff --git a/test/test_component_no_pch/test_component_no_pch.idl b/test/test_component_no_pch/test_component_no_pch.idl index 11e5cbebc..b576313c8 100644 --- a/test/test_component_no_pch/test_component_no_pch.idl +++ b/test/test_component_no_pch/test_component_no_pch.idl @@ -33,4 +33,11 @@ namespace test_component_no_pch Int32 Second; }; } + + // This structure verifies that the structure can at least be declared + // (but perhaps not meaningfully consumed) without having first included Windows.Foundation.h. + struct StructWithReference + { + Windows.Foundation.IReference OptionalValue; + }; } From 933a28b223e43f89c1d7c38a6aab09d8f38e039a Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 28 Jun 2021 07:23:49 -0700 Subject: [PATCH 035/305] Fix delegates with return value passed as fptr or {p,mfptr} (#966) --- strings/base_delegate.h | 4 ++-- test/test/delegate.cpp | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/strings/base_delegate.h b/strings/base_delegate.h index fa1484dd2..1ba8b4d69 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -162,11 +162,11 @@ namespace winrt::impl {} template delegate_base(F* handler) : - delegate_base([=](auto&& ... args) { handler(args...); }) + delegate_base([=](auto&& ... args) { return handler(args...); }) {} template delegate_base(O* object, M method) : - delegate_base([=](auto&& ... args) { ((*object).*(method))(args...); }) + delegate_base([=](auto&& ... args) { return ((*object).*(method))(args...); }) {} template delegate_base(com_ptr&& object, M method) : diff --git a/test/test/delegate.cpp b/test/test/delegate.cpp index bade55060..083c244d5 100644 --- a/test/test/delegate.cpp +++ b/test/test/delegate.cpp @@ -69,4 +69,48 @@ TEST_CASE("delegate") delegate d = [](int a, int b) {return a + b; }; REQUIRE(d(4, 5) == 9); } + + // void(int*) with function pointer + { + struct S + { + static void Invoke(int* p) { *p = 123; } + }; + int value = 0; + delegate d = &S::Invoke; + d(&value); + REQUIRE(value == 123); + } + + // void(int*) with object and method pointer + { + struct S + { + void Invoke(int* p) { *p = 123; } + } s; + delegate d{ &s, &S::Invoke }; + int value = 0; + d(&value); + REQUIRE(value == 123); + } + + // int() with function pointer + { + struct S + { + static int Value() { return 123; } + }; + delegate d = &S::Value; + REQUIRE(d() == 123); + } + + // int() with object and method pointer + { + struct S + { + int Value() { return 123; } + } s; + delegate d{ &s, &S::Value }; + REQUIRE(d() == 123); + } } From 8fb1e2147ef5b49985f205c71254eabee5757963 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 29 Jun 2021 23:08:18 -0700 Subject: [PATCH 036/305] Ingest updated winmd library to fix include/exclude regression (#969) --- cppwinrt/cppwinrt.vcxproj | 4 ++-- cppwinrt/packages.config | 2 +- natvis/cppwinrtvisualizer.vcxproj | 4 ++-- natvis/packages.config | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 0f8d398fb..d4768df66 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -1,6 +1,6 @@ - + Debug @@ -364,6 +364,6 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - + \ No newline at end of file diff --git a/cppwinrt/packages.config b/cppwinrt/packages.config index 135710d6e..9b3264e46 100644 --- a/cppwinrt/packages.config +++ b/cppwinrt/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index 7e399d184..9f058f036 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -1,6 +1,6 @@ - + Debug @@ -261,6 +261,6 @@ - + \ No newline at end of file diff --git a/natvis/packages.config b/natvis/packages.config index 32ce6c838..356e82f7f 100644 --- a/natvis/packages.config +++ b/natvis/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file From 837ac89ca52f00e2ef1fdd8c0009c801c5f8176f Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Wed, 30 Jun 2021 09:43:31 -0700 Subject: [PATCH 037/305] check_hresult returns the hresult as a convenience (#971) --- strings/base_error.h | 3 ++- strings/base_meta.h | 2 +- test/old_tests/UnitTests/hresult_error.cpp | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/strings/base_error.h b/strings/base_error.h index c2db6d1ba..45ed39cd3 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -576,12 +576,13 @@ WINRT_EXPORT namespace winrt throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError())); } - inline void check_hresult(hresult const result) + inline hresult check_hresult(hresult const result) { if (result < 0) { throw_hresult(result); } + return result; } template diff --git a/strings/base_meta.h b/strings/base_meta.h index d2b386442..9c18a84f0 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -1,7 +1,7 @@ WINRT_EXPORT namespace winrt { - void check_hresult(hresult const result); + hresult check_hresult(hresult const result); hresult to_hresult() noexcept; template diff --git a/test/old_tests/UnitTests/hresult_error.cpp b/test/old_tests/UnitTests/hresult_error.cpp index 206e06ef5..b9db219f4 100644 --- a/test/old_tests/UnitTests/hresult_error.cpp +++ b/test/old_tests/UnitTests/hresult_error.cpp @@ -10,7 +10,7 @@ TEST_CASE("hresult,S_OK") { // This won't throw - check_hresult(S_OK); + REQUIRE(check_hresult(S_OK) == S_OK); } TEST_CASE("hresult,S_FALSE") @@ -18,7 +18,7 @@ TEST_CASE("hresult,S_FALSE") // This won't throw (unless you define WINRT_STRICT_HRESULT) #ifndef WINRT_STRICT_HRESULT - check_hresult(S_FALSE); + REQUIRE(check_hresult(S_FALSE) == S_FALSE); #else try { From 634d6275579dc8e5c373a6fbc89d9f4f4eefa9a4 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 1 Jul 2021 10:51:56 -0700 Subject: [PATCH 038/305] Update VSIX to work with Dev17 (#968) * Update VSIX to work with Dev17 * Newline in vxismanifest --- vsix/Standalone/source.extension.vsixmanifest | 25 +++++++++--- vsix/packages.config | 2 +- vsix/vsix.csproj | 38 +++++++++++-------- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/vsix/Standalone/source.extension.vsixmanifest b/vsix/Standalone/source.extension.vsixmanifest index 4dc229ae9..68aa7665c 100644 --- a/vsix/Standalone/source.extension.vsixmanifest +++ b/vsix/Standalone/source.extension.vsixmanifest @@ -14,9 +14,24 @@ WinRT, C++, cppwinrt, native - - - + + x86 + + + amd64 + + + x86 + + + amd64 + + + x86 + + + amd64 + @@ -29,7 +44,7 @@ - - + + diff --git a/vsix/packages.config b/vsix/packages.config index c38f5c6f2..5df989c6b 100644 --- a/vsix/packages.config +++ b/vsix/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/vsix/vsix.csproj b/vsix/vsix.csproj index 4596b6cd1..048928a4e 100644 --- a/vsix/vsix.csproj +++ b/vsix/vsix.csproj @@ -1,6 +1,6 @@  - + 15.0 @@ -51,39 +51,48 @@ true - VCTargets + Microsoft\VC\v160 + MSBuild true - VCTargets + Microsoft\VC\v160\Platforms\ARM\ImportBefore + MSBuild true - VCTargets + Microsoft\VC\v160\Platforms\ARM64\ImportBefore + MSBuild true - VCTargets + Microsoft\VC\v160\Platforms\Win32\ImportBefore + MSBuild true - VCTargets + Microsoft\VC\v160\Platforms\x64\ImportBefore + MSBuild true - VCTargets + Application Type\Windows Store\10.0\Platforms\ARM\ImportAfter + MSBuild true - VCTargets + Application Type\Windows Store\10.0\Platforms\ARM64\ImportAfter + MSBuild true - VCTargets + Application Type\Windows Store\10.0\Platforms\Win32\ImportAfter + MSBuild true - VCTargets + Application Type\Windows Store\10.0\Platforms\x64\ImportAfter + MSBuild true @@ -109,6 +118,7 @@ Designer + @@ -117,9 +127,6 @@ true - - Designer - @@ -130,8 +137,8 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + @@ -163,4 +170,5 @@ + \ No newline at end of file From 7e730e7652a42754bd0384feb7c84d5484daff2e Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 7 Jul 2021 07:14:04 -0700 Subject: [PATCH 039/305] Revert "Prevent inadvertent assignment to temporary object" (#976) --- cppwinrt/code_writers.h | 66 ++----------------------- strings/base_activation.h | 4 -- strings/base_array.h | 2 +- strings/base_com_ptr.h | 8 +-- strings/base_events.h | 6 +-- strings/base_handle.h | 2 +- strings/base_security.h | 2 +- strings/base_string.h | 12 ++--- strings/base_windows.h | 10 ++-- test/old_tests/UnitTests/properties.cpp | 46 ----------------- 10 files changed, 22 insertions(+), 136 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 95a2fa59e..df4d66564 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2371,10 +2371,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable { %(std::nullptr_t = nullptr) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} - %(% const&) noexcept = default; - %(%&&) noexcept = default; - %& operator=(% const&) & noexcept = default; - %& operator=(%&&) & noexcept = default; %% }; )"; @@ -2384,14 +2380,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable bind(type), type_name, type_name, - type_name, // %(T const&) - type_name, // T(% const&) - type_name, // %(T&&) - type_name, // T(%&&) - type_name, // %& operator=(T const&) - type_name, // T& operator=(% const&) - type_name, // %& operator=(T&&) - type_name, // T& operator=(%&&) bind(type), bind(type)); } @@ -2406,10 +2394,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable {% %(std::nullptr_t = nullptr) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IInspectable(ptr, take_ownership_from_abi) {} - %(% const&) noexcept = default; - %(%&&) noexcept = default; - %& operator=(% const&) & noexcept = default; - %& operator=(%&&) & noexcept = default; %% }; )"; @@ -2421,14 +2405,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable bind(generics), type_name, type_name, - type_name, // %(T const&) - type_name, // T(% const&) - type_name, // %(T&&) - type_name, // T(%&&) - type_name, // %& operator=(T const&) - type_name, // T& operator=(% const&) - type_name, // %& operator=(T&&) - type_name, // T& operator=(%&&) bind(type), bind(type)); } @@ -2454,10 +2430,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable {% %(std::nullptr_t = nullptr) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : Windows::Foundation::IUnknown(ptr, take_ownership_from_abi) {} - %(% const&) noexcept = default; - %(%&&) noexcept = default; - %& operator=(% const&) & noexcept = default; - %& operator=(%&&) & noexcept = default; template %(L lambda); template %(F* function); template %(O* object, M method); @@ -2470,18 +2442,10 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable method_signature signature{ get_delegate_method(type) }; w.write(format, - type_name, // struct % + type_name, bind(generics), type_name, type_name, - type_name, // %(T const&) - type_name, // T(% const&) - type_name, // %(T&&) - type_name, // T(%&&) - type_name, // %& operator=(T const&) - type_name, // T& operator=(% const&) - type_name, // %& operator=(T&&) - type_name, // T& operator=(%&&) type_name, type_name, type_name, @@ -3155,11 +3119,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable { %(std::nullptr_t) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : %(ptr, take_ownership_from_abi) {} -% %(% const&) noexcept = default; - %(%&&) noexcept = default; - %& operator=(% const&) & noexcept = default; - %& operator=(%&&) & noexcept = default; -%% }; +%%% }; )"; w.write(format, @@ -3171,14 +3131,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable type_name, base_type, bind(type, factories), - type_name, // %(T const&) - type_name, // T(% const&) - type_name, // %(T%&) - type_name, // T(%&&) - type_name, // %& operator=(T const&) - type_name, // T& operator=(% const&) - type_name, // %& operator=(T&&) - type_name, // T& operator=(%&&) bind(type), bind_each(factories, type)); } @@ -3192,11 +3144,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable { %(std::nullptr_t) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : %(ptr, take_ownership_from_abi) {} -% %(% const&) noexcept = default; - %(%&&) noexcept = default; - %& operator=(% const&) & noexcept = default; - %& operator=(%&&) & noexcept = default; -%% }; +%%% }; )"; w.write(format, @@ -3207,14 +3155,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable type_name, base_type, bind(type, factories), - type_name, // %(T const&) - type_name, // T(% const&) - type_name, // %(T%&) - type_name, // T(%&&) - type_name, // %& operator=(T const&) - type_name, // T& operator=(% const&) - type_name, // %& operator=(T&&) - type_name, // T& operator=(%&&) bind(type), bind_each(factories, type)); } diff --git a/strings/base_activation.h b/strings/base_activation.h index a54c9e23b..942b3b342 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -523,10 +523,6 @@ WINRT_EXPORT namespace winrt { IActivationFactory(std::nullptr_t = nullptr) noexcept {} IActivationFactory(void* ptr, take_ownership_from_abi_t) noexcept : IInspectable(ptr, take_ownership_from_abi) {} - IActivationFactory(IActivationFactory const&) noexcept = default; - IActivationFactory(IActivationFactory&&) noexcept = default; - IActivationFactory& operator=(IActivationFactory const&) & noexcept = default; - IActivationFactory& operator=(IActivationFactory&&) & noexcept = default; template T ActivateInstance() const diff --git a/strings/base_array.h b/strings/base_array.h index 06e53a5b8..5f0904efe 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -295,7 +295,7 @@ WINRT_EXPORT namespace winrt other.m_size = 0; } - com_array& operator=(com_array&& other) & noexcept + com_array& operator=(com_array&& other) noexcept { clear(); this->m_data = other.m_data; diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index ed6bf0089..1c7536e0f 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -57,13 +57,13 @@ WINRT_EXPORT namespace winrt release_ref(); } - com_ptr& operator=(com_ptr const& other) & noexcept + com_ptr& operator=(com_ptr const& other) noexcept { copy_ref(other.m_ptr); return*this; } - com_ptr& operator=(com_ptr&& other) & noexcept + com_ptr& operator=(com_ptr&& other) noexcept { if (this != &other) { @@ -75,14 +75,14 @@ WINRT_EXPORT namespace winrt } template - com_ptr& operator=(com_ptr const& other) & noexcept + com_ptr& operator=(com_ptr const& other) noexcept { copy_ref(other.m_ptr); return*this; } template - com_ptr& operator=(com_ptr&& other) & noexcept + com_ptr& operator=(com_ptr&& other) noexcept { release_ref(); m_ptr = std::exchange(other.m_ptr, {}); diff --git a/strings/base_events.h b/strings/base_events.h index 3b53fa06f..8b4edb060 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -29,7 +29,7 @@ WINRT_EXPORT namespace winrt event_revoker& operator=(event_revoker const&) = delete; event_revoker(event_revoker&&) noexcept = default; - event_revoker& operator=(event_revoker&& other) & noexcept + event_revoker& operator=(event_revoker&& other) noexcept { if (this != &other) { @@ -84,7 +84,7 @@ WINRT_EXPORT namespace winrt factory_event_revoker& operator=(factory_event_revoker const&) = delete; factory_event_revoker(factory_event_revoker&&) noexcept = default; - factory_event_revoker& operator=(factory_event_revoker&& other) & noexcept + factory_event_revoker& operator=(factory_event_revoker&& other) noexcept { if (this != &other) { @@ -140,7 +140,7 @@ namespace winrt::impl event_revoker& operator=(event_revoker const&) = delete; event_revoker(event_revoker&&) noexcept = default; - event_revoker& operator=(event_revoker&& other) & noexcept + event_revoker& operator=(event_revoker&& other) noexcept { event_revoker(std::move(other)).swap(*this); return *this; diff --git a/strings/base_handle.h b/strings/base_handle.h index 1cd5b4d82..60eec8be0 100644 --- a/strings/base_handle.h +++ b/strings/base_handle.h @@ -16,7 +16,7 @@ WINRT_EXPORT namespace winrt { } - handle_type& operator=(handle_type&& other) & noexcept + handle_type& operator=(handle_type&& other) noexcept { if (this != &other) { diff --git a/strings/base_security.h b/strings/base_security.h index 18c6f7d61..8160f11ad 100644 --- a/strings/base_security.h +++ b/strings/base_security.h @@ -55,7 +55,7 @@ WINRT_EXPORT namespace winrt access_token() = default; access_token(access_token&& other) = default; - access_token& operator=(access_token&& other) & = default; + access_token& operator=(access_token&& other) = default; access_token impersonate() const { diff --git a/strings/base_string.h b/strings/base_string.h index b9fada8d2..f50403c41 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -179,16 +179,16 @@ WINRT_EXPORT namespace winrt m_handle(impl::duplicate_hstring(value.m_handle.get())) {} - hstring& operator=(hstring const& value) & + hstring& operator=(hstring const& value) { m_handle.attach(impl::duplicate_hstring(value.m_handle.get())); return*this; } hstring(hstring&&) noexcept = default; - hstring& operator=(hstring&&) & = default; + hstring& operator=(hstring&&) = default; hstring(std::nullptr_t) = delete; - hstring& operator=(std::nullptr_t) & = delete; + hstring& operator=(std::nullptr_t) = delete; hstring(std::initializer_list value) : hstring(value.begin(), static_cast(value.size())) @@ -206,17 +206,17 @@ WINRT_EXPORT namespace winrt hstring(value.data(), static_cast(value.size())) {} - hstring& operator=(std::wstring_view const& value) & + hstring& operator=(std::wstring_view const& value) { return *this = hstring{ value }; } - hstring& operator=(wchar_t const* const value) & + hstring& operator=(wchar_t const* const value) { return *this = hstring{ value }; } - hstring& operator=(std::initializer_list value) & + hstring& operator=(std::initializer_list value) { return *this = hstring{ value }; } diff --git a/strings/base_windows.h b/strings/base_windows.h index 6da4c394a..3800af1b1 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -161,7 +161,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation release_ref(); } - IUnknown& operator=(IUnknown const& other) & noexcept + IUnknown& operator=(IUnknown const& other) noexcept { if (this != &other) { @@ -173,7 +173,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return*this; } - IUnknown& operator=(IUnknown&& other) & noexcept + IUnknown& operator=(IUnknown&& other) noexcept { if (this != &other) { @@ -189,7 +189,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return nullptr != m_ptr; } - IUnknown& operator=(std::nullptr_t) & noexcept + IUnknown& operator=(std::nullptr_t) noexcept { release_ref(); return*this; @@ -425,9 +425,5 @@ WINRT_EXPORT namespace winrt::Windows::Foundation { IInspectable(std::nullptr_t = nullptr) noexcept {} IInspectable(void* ptr, take_ownership_from_abi_t) noexcept : IUnknown(ptr, take_ownership_from_abi) {} - IInspectable(IInspectable const&) noexcept = default; - IInspectable(IInspectable&&) noexcept = default; - IInspectable& operator=(IInspectable const&) & noexcept = default; - IInspectable& operator=(IInspectable&&) & noexcept = default; }; } diff --git a/test/old_tests/UnitTests/properties.cpp b/test/old_tests/UnitTests/properties.cpp index da219fbb8..ff17a0324 100644 --- a/test/old_tests/UnitTests/properties.cpp +++ b/test/old_tests/UnitTests/properties.cpp @@ -44,50 +44,4 @@ TEST_CASE("properties") REQUIRE_THROWS_AS(e.Name(L"throw"), hresult_invalid_argument); REQUIRE_THROWS_AS(e.Name(), hresult_invalid_argument); - -} - -namespace -{ - // Make sure that statements like - // - // e.Name() = L"Fred"; // intended e.Name(L"Fred"); - // e.Uri() = newUri; // intended e.Uri(newUri); - // - // are not valid. These are common beginner errors when - // trying to set Windows Runtime properties. - - template - struct validate_rvalue_operations - { - // Make sure we didn't damage default constructor. - static_assert(std::is_default_constructible_v == default_constructible); - - // Make sure we didn't damage other constructors. - static_assert((std::is_constructible_v && ...)); - - // Make sure we didn't damage copy and move constructors. - static_assert(std::is_copy_constructible_v); - static_assert(std::is_move_constructible_v); - - // Make sure rvalue assignment is disallowed, but lvalue is still okay. - static_assert(!std::is_assignable_v); - static_assert((!std::is_assignable_v && ...)); - static_assert(std::is_assignable_v); - static_assert((std::is_assignable_v && ...)); - - constexpr static bool validate() - { - // Dummy method. Exists only to force instantiation of type so the static_assert's will fire. - return true; - } - }; - - static_assert(validate_rvalue_operations::validate()); - static_assert(validate_rvalue_operations::validate()); - static_assert(validate_rvalue_operations::validate()); - static_assert(validate_rvalue_operations, true, std::nullptr_t>::validate()); - static_assert(validate_rvalue_operations, true, std::nullptr_t>::validate()); - static_assert(validate_rvalue_operations::validate()); - static_assert(validate_rvalue_operations::validate()); } From 54c1097dac93759058e8abf29b337ca70c307148 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Thu, 8 Jul 2021 12:26:54 -0700 Subject: [PATCH 040/305] Fix target override as it doesn't work when the target import order changes. (#977) * Fix target override as it doesn't work when the target import order changes. * Fix mismatch. * Minor updates. --- nuget/Microsoft.Windows.CppWinRT.targets | 38 +++++-------------- test/nuget/TestApp/TestApp.vcxproj | 4 +- .../TestRuntimeComponent1.vcxproj | 2 - .../TestRuntimeComponent2.vcxproj | 2 - .../TestRuntimeComponent3.vcxproj | 2 - .../TestRuntimeComponentEmpty.vcxproj | 2 - 6 files changed, 11 insertions(+), 39 deletions(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 4e51c070c..37d58f151 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -75,7 +75,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. $(AfterMidlTargets); GetCppWinRTMdMergeInputs; CppWinRTMergeProjectWinMDInputs; - GetResolvedWinMD; + CppWinRTGetResolvedWinMD; CppWinRTCopyWinMDToOutputDirectory; @@ -104,6 +104,12 @@ Copyright (C) Microsoft Corporation. All rights reserved. $(CleanDependsOn);CppWinRTClean + + $(GetTargetPathDependsOn);CppWinRTGetResolvedWinMD + + + $(GetPackagingOutputsDependsOn);CppWinRTGetResolvedWinMD + @@ -202,7 +208,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. - - - - - - - true - - - - - $([System.IO.Path]::GetFileName('%(Link.WindowsMetadataFile)')) - true - - - - $(WinMDImplementationPath)$(TargetName)$(TargetExt) - winmd - true - $(ConfigurationType) - - - - - diff --git a/test/nuget/TestApp/TestApp.vcxproj b/test/nuget/TestApp/TestApp.vcxproj index 1fd086156..894993ff4 100644 --- a/test/nuget/TestApp/TestApp.vcxproj +++ b/test/nuget/TestApp/TestApp.vcxproj @@ -13,7 +13,7 @@ true Windows Store 10.0 - 10.0.18362.0 + 10.0.19041.0 10.0.17134.0 @@ -76,8 +76,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) diff --git a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj index 69fc368a5..ddd17f254 100644 --- a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj +++ b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj @@ -80,8 +80,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) 28204 _WINRT_DLL;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj index 6c4e26fdc..7a7803a82 100644 --- a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj +++ b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj @@ -81,8 +81,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) 28204 _WINRT_DLL;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj index 0ce50a574..e1eb6e53d 100644 --- a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj +++ b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj @@ -81,8 +81,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) 28204 _WINRT_DLL;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj index 274e6f474..073c8fd0c 100644 --- a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj +++ b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj @@ -81,8 +81,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) 28204 _WINRT_DLL;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) From 74240c8cd6c9e55a44aab4c0cf451ff23e8c42a6 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Fri, 9 Jul 2021 10:43:12 -0700 Subject: [PATCH 041/305] Ensure we don't override XamlLanguage if it's already set. (#979) When NuGet imports the props as part of PackageReference, it easy to end up in situations where the project file defines XamlLanguage before the C++/WinRT props are imported. We shouldn't override if the value is already set. --- nuget/Microsoft.Windows.CppWinRT.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.props b/nuget/Microsoft.Windows.CppWinRT.props index 398ada50b..d7e2c652c 100644 --- a/nuget/Microsoft.Windows.CppWinRT.props +++ b/nuget/Microsoft.Windows.CppWinRT.props @@ -17,7 +17,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. true true false - CppWinRT + CppWinRT true true From c97862759284e786f8c4e1c11cd09d89bf90c553 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Wed, 14 Jul 2021 09:00:56 -0700 Subject: [PATCH 042/305] Ensure the Xaml designer can find out WinMD (#982) --- nuget/Microsoft.Windows.CppWinRT.targets | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 37d58f151..16d0b020d 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -216,12 +216,12 @@ Copyright (C) Microsoft Corporation. All rights reserved. - + There is no good way to hook GetResolvedWinMD so we use BeforeTargets. --> From 00bc3b8f593790a157078181830c80e2639d112b Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 21 Jul 2021 15:47:20 -0700 Subject: [PATCH 043/305] Harden put functions against misuse (#986) --- strings/base_com_ptr.h | 2 +- strings/base_handle.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 1c7536e0f..66dd2c9e7 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -111,7 +111,7 @@ WINRT_EXPORT namespace winrt type** put() noexcept { - WINRT_ASSERT(m_ptr == nullptr); + release_ref(); return &m_ptr; } diff --git a/strings/base_handle.h b/strings/base_handle.h index 60eec8be0..7a65af7b3 100644 --- a/strings/base_handle.h +++ b/strings/base_handle.h @@ -52,7 +52,7 @@ WINRT_EXPORT namespace winrt type* put() noexcept { - WINRT_ASSERT(m_value == T::invalid()); + close(); return &m_value; } From a6124b2d028dc241ff18fe8f26f48ee2c0c2b084 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 26 Jul 2021 14:12:45 -0700 Subject: [PATCH 044/305] Fix cyclic dependency error when upgrading VS 2022 (#989) --- vsix/Component/source.extension.vsixmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsix/Component/source.extension.vsixmanifest b/vsix/Component/source.extension.vsixmanifest index 177f525a2..ca40a96e6 100644 --- a/vsix/Component/source.extension.vsixmanifest +++ b/vsix/Component/source.extension.vsixmanifest @@ -29,6 +29,6 @@ - + From 20f0962c684609b53e1fd96f3b5c11f32942b5a1 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Tue, 3 Aug 2021 14:02:03 -0400 Subject: [PATCH 045/305] Use v143 toolset on VS 2022 (#994) * Use v143 toolset on VS 2022 Visual Studio 2022 introduces a new toolset version, so we should use it for increased standards compliance and new features * Remove trailing whitespaces --- .../ConsoleApplication/ConsoleApplication.vcxproj | 7 ++++--- .../WindowsApplication/WindowsApplication.vcxproj | 7 ++++--- .../VC/Windows Universal/BlankApp/BlankApp.vcxproj | 3 ++- .../VC/Windows Universal/CoreApp/CoreApp.vcxproj | 3 ++- .../Windows Universal/StaticLibrary/StaticLibrary.vcxproj | 3 ++- .../WindowsRuntimeComponent.vcxproj | 3 ++- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj index 302bb4a04..ad52af212 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj @@ -33,9 +33,10 @@ Application - v142 - v141 - v140 + v143 + v142 + v141 + v140 Unicode diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj index bdf0cb871..8b8cb03ce 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj @@ -33,9 +33,10 @@ Application - v142 - v141 - v140 + v143 + v142 + v141 + v140 Unicode diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index b74002063..c16e81b1a 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -53,7 +53,8 @@ Application - v142 + v143 + v142 v141 v140 Unicode diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index 246a3eeaa..d2f2b002a 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -52,7 +52,8 @@ Application - v142 + v143 + v142 v141 v140 Unicode diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index 935ec08d0..c2ad28031 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -54,7 +54,8 @@ StaticLibrary - v142 + v143 + v142 v141 v140 Unicode diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 784a8e8c9..e0dd19cb4 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -53,7 +53,8 @@ DynamicLibrary - v142 + v143 + v142 v141 v140 Unicode From 4ba22a67d7fb24d2ae0c0472d3cdaaeb4b013465 Mon Sep 17 00:00:00 2001 From: David Fields Date: Tue, 3 Aug 2021 22:20:58 -0700 Subject: [PATCH 046/305] Use throw rather than abort() for guid parse failures (#992) * Use throw rather than abort() for guid parse failures Make `winrt::guid("...")` more useful at runtime by throwing on failure instead of aborting the program. * Remove noexcept, add tests * Revert operator== changes, revise tests Co-authored-by: Kenny Kerr --- strings/base_types.h | 16 ++++++++-------- test/test/guid.cpp | 29 +++++++++++++++++++++++++++++ test/test/test.vcxproj | 1 + 3 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 test/test/guid.cpp diff --git a/strings/base_types.h b/strings/base_types.h index 751b949b3..70e97fbb7 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -20,7 +20,7 @@ namespace winrt::impl }; template - constexpr uint8_t hex_to_uint(T const c) noexcept + constexpr uint8_t hex_to_uint(T const c) { if (c >= '0' && c <= '9') { @@ -36,22 +36,22 @@ namespace winrt::impl } else { - abort(); + throw std::invalid_argument("Character is not a hexadecimal digit"); } } template - constexpr uint8_t hex_to_uint8(T const a, T const b) noexcept + constexpr uint8_t hex_to_uint8(T const a, T const b) { return (hex_to_uint(a) << 4) | hex_to_uint(b); } - constexpr uint16_t uint8_to_uint16(uint8_t a, uint8_t b) noexcept + constexpr uint16_t uint8_to_uint16(uint8_t a, uint8_t b) { return (static_cast(a) << 8) | static_cast(b); } - constexpr uint32_t uint8_to_uint32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) noexcept + constexpr uint32_t uint8_to_uint32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { return (static_cast(uint8_to_uint16(a, b)) << 16) | static_cast(uint8_to_uint16(c, d)); @@ -85,11 +85,11 @@ WINRT_EXPORT namespace winrt private: template - static constexpr guid parse(TStringView const value) noexcept + static constexpr guid parse(TStringView const value) { if (value.size() != 36 || value[8] != '-' || value[13] != '-' || value[18] != '-' || value[23] != '-') { - abort(); + throw std::invalid_argument("value is not a valid GUID string"); } return @@ -179,7 +179,7 @@ WINRT_EXPORT namespace winrt { return !(left == right); } - + inline bool operator<(guid const& left, guid const& right) noexcept { return memcmp(&left, &right, sizeof(left)) < 0; diff --git a/test/test/guid.cpp b/test/test/guid.cpp new file mode 100644 index 000000000..b3edbc570 --- /dev/null +++ b/test/test/guid.cpp @@ -0,0 +1,29 @@ +#include "pch.h" + +TEST_CASE("guid") +{ + constexpr winrt::guid expected{ 0x00112233, 0x4455, 0x6677, { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } }; + + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data1 == expected.Data1); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data2 == expected.Data2); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data3 == expected.Data3); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[0] == expected.Data4[0]); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[1] == expected.Data4[1]); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[2] == expected.Data4[2]); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[3] == expected.Data4[3]); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[4] == expected.Data4[4]); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[5] == expected.Data4[5]); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[6] == expected.Data4[6]); + STATIC_REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff").Data4[7] == expected.Data4[7]); + + REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff") == expected); + REQUIRE(winrt::guid({ "{00112233-4455-6677-8899-aabbccddeeff}" + 1, 36 }) == expected); + + REQUIRE_THROWS_AS(winrt::guid(""), std::invalid_argument); + REQUIRE_THROWS_AS(winrt::guid("not a guid"), std::invalid_argument); + REQUIRE_THROWS_AS(winrt::guid("same length string that's not a guid"), std::invalid_argument); + REQUIRE_THROWS_AS(winrt::guid("too long string that's also not a guid"), std::invalid_argument); + REQUIRE_THROWS_AS(winrt::guid("00112233-4455-6677-8899-aabbccddeeff with extra"), std::invalid_argument); + REQUIRE_THROWS_AS(winrt::guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), std::invalid_argument); + REQUIRE_THROWS_AS(winrt::guid("{00112233-4455-6677-8899-aabbccddeeff}"), std::invalid_argument); +} \ No newline at end of file diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 3d9ad5f40..ed6e934bd 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -335,6 +335,7 @@ + From 4366357db991bda7bb615dedabdb3637cc93e9e5 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Thu, 19 Aug 2021 10:13:45 -0700 Subject: [PATCH 047/305] Some uses of `co_await` were not protected by `WINRT_IMPL_COROUTINES` (#1002) --- strings/base_coroutine_foundation.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 943e640ed..d7e325b9e 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -127,6 +127,7 @@ namespace winrt::impl } }; +#ifdef WINRT_IMPL_COROUTINES template struct await_adapter : enable_await_cancellation { @@ -177,6 +178,7 @@ namespace winrt::impl } } }; +#endif template auto consume_Windows_Foundation_IAsyncAction::get() const @@ -793,6 +795,7 @@ namespace std::experimental WINRT_EXPORT namespace winrt { +#ifdef WINRT_IMPL_COROUTINES template Windows::Foundation::IAsyncAction when_all(T... async) { @@ -838,4 +841,5 @@ WINRT_EXPORT namespace winrt impl::check_status_canceled(shared->status); co_return shared->result.GetResults(); } +#endif } From 8f40198d622ff13daca84eb284b2ec810171c4f8 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 25 Aug 2021 09:16:01 -0700 Subject: [PATCH 048/305] Fix edge case in nested Windows namespace (#1004) --- cppwinrt/code_writers.h | 4 ++-- test/test_component/test_component.idl | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index df4d66564..6c909fbe1 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2426,10 +2426,10 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable w.write(format, bind(generics)); } - auto format = R"( struct % : Windows::Foundation::IUnknown + auto format = R"( struct % : winrt::Windows::Foundation::IUnknown {% %(std::nullptr_t = nullptr) noexcept {} - %(void* ptr, take_ownership_from_abi_t) noexcept : Windows::Foundation::IUnknown(ptr, take_ownership_from_abi) {} + %(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Foundation::IUnknown(ptr, take_ownership_from_abi) {} template %(L lambda); template %(F* function); template %(O* object, M method); diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index a3274e4c3..f3cba16e0 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -293,5 +293,7 @@ namespace test_component static void StaticMethod(Struct param); void Method(Windows.Foundation.Uri param); } + + delegate void Delegate(); } } From f2f08f72b66a9fe18dfedd272e224ba109811f4e Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Wed, 25 Aug 2021 12:16:19 -0400 Subject: [PATCH 049/305] Ignore errors during manual unregistration (#1005) --- cppwinrt.props | 5 +++++ cppwinrt/code_writers.h | 14 +++++++++++++- test/old_tests/UnitTests/event_consume.cpp | 4 ++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cppwinrt.props b/cppwinrt.props index b313ffd04..7e1b5a0a9 100644 --- a/cppwinrt.props +++ b/cppwinrt.props @@ -12,6 +12,11 @@ 10.0 + + v143 + 10.0 + + + DependsOnTargets="CppWinRTGetBuildingMidl;GetCppWinRTProjectWinMDReferences;$(CppWinRTComputeGenerateWindowsMetadataDependsOn)"> - true - true + true + true @@ -345,12 +353,12 @@ Copyright (C) Microsoft Corporation. All rights reserved. + DependsOnTargets="CppWinRTGetBuildingMidl;CppWinRTResolveReferences" + Returns="@(CppWinRTMdMergeMetadataDirectories);@(CppWinRTMdMergeInputs)"> <_MdMergeInputs Remove="@(_MdMergeInputs)"/> - <_MdMergeInputs Include="@(Midl)"> - %(Midl.OutputDirectory)%(Midl.MetadataFileName) + <_MdMergeInputs Include="@(_BuildingMidl)"> + %(_BuildingMidl.OutputDirectory)%(_BuildingMidl.MetadataFileName) $(CppWinRTProjectWinMD) + + $(MSBuildThisFileDirectory)..\ + $(MSBuildThisFileDirectory) + + + \ No newline at end of file From 2f1e651329cb9915d556433d35a49099747c1f92 Mon Sep 17 00:00:00 2001 From: "Peter Torr (MSFT)" Date: Mon, 25 Oct 2021 10:54:16 -0700 Subject: [PATCH 066/305] Update comments written by component_writers.h (#1043) --- cppwinrt/component_writers.h | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index b8894f8f4..45970c538 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -988,9 +988,24 @@ namespace winrt::@::implementation static void write_generated_static_assert(writer& w) { auto format = R"( -// Note: Remove this static_assert after copying these generated source files to your project. -// This assertion exists to avoid compiling these generated source files directly. -static_assert(false, "Do not compile generated C++/WinRT source files directly"); +// WARNING: This file is automatically generated by a tool. Do not directly +// add this file to your project, as any changes you make will be lost. +// This file is a stub you can use as a starting point for your implementation. +// +// To add a copy of this file to your project: +// 1. Copy this file from its original location to the location where you store +// your other source files (e.g. the project root). +// 2. Add the copied file to your project. In Visual Studio, you can use +// Project -> Add Existing Item. +// 3. Delete this comment and the 'static_assert' (below) from the copied file. +// Do not modify the original file. +// +// To update an existing file in your project: +// 1. Copy the relevant changes from this file and merge them into the copy +// you made previously. +// +// This assertion helps prevent accidental modification of generated files. +static_assert(false, "This file is generated by a tool and will be overwritten. Open this error and view the comment for assistance."); )"; w.write(format); @@ -1206,4 +1221,4 @@ namespace winrt::@::implementation slot); } } -} \ No newline at end of file +} From eab5d4bf88719dcc1ee7f654cbee69fc6f6878ea Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Thu, 28 Oct 2021 15:41:25 -0700 Subject: [PATCH 067/305] Evaluate ExcludedFromBuild inline (#1051) --- nuget/Microsoft.Windows.CppWinRT.targets | 25 +++++++++++------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 9cb426448..e0e2fe91a 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -190,24 +190,21 @@ Copyright (C) Microsoft Corporation. All rights reserved. - - - <_BuildingMidl Include="@(Midl)" Condition="'%(Midl.ExcludedFromBuild)' != 'true'" /> - - - + DependsOnTargets="GetCppWinRTProjectWinMDReferences;CppWinRTComputeXamlGeneratedMidlInputs;$(CppWinRTComputeGenerateWindowsMetadataDependsOn)"> + + + <_IncludedIdlForComputeGenerateWindowsMetadata Remove="@(_IncludedIdlForComputeGenerateWindowsMetadata)" /> + <_IncludedIdlForComputeGenerateWindowsMetadata Include="@(Midl)" Condition="'%(Midl.ExcludedFromBuild)' != 'true'" /> + - true - true + true + true @@ -353,12 +350,12 @@ Copyright (C) Microsoft Corporation. All rights reserved. <_MdMergeInputs Remove="@(_MdMergeInputs)"/> - <_MdMergeInputs Include="@(_BuildingMidl)"> - %(_BuildingMidl.OutputDirectory)%(_BuildingMidl.MetadataFileName) + <_MdMergeInputs Include="@(Midl)" Condition="'%(Midl.ExcludedFromBuild)' != 'true'"> + %(Midl.OutputDirectory)%(Midl.MetadataFileName) $(CppWinRTProjectWinMD) - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) - - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) @@ -138,4 +134,4 @@ - \ No newline at end of file + diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index 42ce830b6..c94b507ee 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -82,10 +82,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) - - WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) @@ -145,4 +141,4 @@ - \ No newline at end of file + diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index c16e81b1a..af2b41932 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -1,4 +1,4 @@ - + true @@ -85,8 +85,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index c2ad28031..77cc1e005 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -90,8 +90,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index e0dd19cb4..55a39d0dd 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -89,8 +89,6 @@ $(IntDir)pch.pch Level4 %(AdditionalOptions) /bigobj - - /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) From 4d5c5ae3de386ce1f18c3410a27b9ceb40aa524d Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 2 Dec 2021 12:04:55 -0800 Subject: [PATCH 071/305] Lay groundwork for localizing VSIX templates and remove Dev15 build cruft (#1060) * Lay groundwork for localization * Change both VSIX definitions to AnyCPU * Remove obsolete props/targets from VSIX * Consolidate template update logic into Extension.targets * Convert to SDK-style project * Add placeholder resx files * Keep target framework out of output path to avoid pipeline churn --- build_vsix.cmd | 2 +- .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../Component/source.extension.vsixmanifest | 3 + .../Standalone/source.extension.vsixmanifest | 3 + vsix/Dev16/VSPackage.cs | 55 +++++ vsix/Dev16/vsix.Dev16.csproj | 209 +++++++++--------- .../Component/source.extension.vsixmanifest | 3 + .../Standalone/source.extension.vsixmanifest | 3 + vsix/Dev17/VSPackage.cs | 55 +++++ vsix/Dev17/vsix.Dev17.csproj | 173 +++++++-------- vsix/Directory.Build.Props | 26 ++- vsix/Extension.targets | 47 ++++ .../BlankPage/cppwinrt_BlankPage.vstemplate | 4 +- .../cppwinrt_BlankUserControl.vstemplate | 4 +- .../ViewModel/cppwinrt_ViewModel.vstemplate | 4 +- vsix/Microsoft.Cpp.CppWinRT.props | 21 -- .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../ImportAfter/Microsoft.Cpp.CppWinRT.props | 11 - .../cppwinrt_ConsoleApplication.vstemplate | 4 +- .../cppwinrt_WindowsApplication.vstemplate | 4 +- .../BlankApp/cppwinrt_BlankApp.vstemplate | 4 +- .../CoreApp/cppwinrt_CoreApp.vstemplate | 4 +- .../cppwinrt_StaticLibrary.vstemplate | 4 +- ...ppwinrt_WindowsRuntimeComponent.vstemplate | 4 +- vsix/Resources/VSPackage.cs-CZ.resx | 131 +++++++++++ vsix/Resources/VSPackage.de-DE.resx | 131 +++++++++++ vsix/Resources/VSPackage.en-US.resx | 131 +++++++++++ vsix/Resources/VSPackage.es-ES.resx | 131 +++++++++++ vsix/Resources/VSPackage.fr-FR.resx | 131 +++++++++++ vsix/Resources/VSPackage.it-IT.resx | 131 +++++++++++ vsix/Resources/VSPackage.ja-JP.resx | 131 +++++++++++ vsix/Resources/VSPackage.ko-KR.resx | 131 +++++++++++ vsix/Resources/VSPackage.pl-PL.resx | 131 +++++++++++ vsix/Resources/VSPackage.pt-BR.resx | 131 +++++++++++ vsix/Resources/VSPackage.resx | 185 ++++++++++++++++ vsix/Resources/VSPackage.ru-RU.resx | 131 +++++++++++ vsix/Resources/VSPackage.tr-TR.resx | 131 +++++++++++ vsix/Resources/VSPackage.zh-CN.resx | 131 +++++++++++ vsix/Resources/VSPackage.zh-TW.resx | 131 +++++++++++ vsix/vsix.sln | 8 +- 45 files changed, 2416 insertions(+), 335 deletions(-) delete mode 100644 vsix/Application Type/Windows Store/10.0/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props delete mode 100644 vsix/Application Type/Windows Store/10.0/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props delete mode 100644 vsix/Application Type/Windows Store/10.0/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props delete mode 100644 vsix/Application Type/Windows Store/10.0/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props create mode 100644 vsix/Dev16/VSPackage.cs create mode 100644 vsix/Dev17/VSPackage.cs create mode 100644 vsix/Extension.targets delete mode 100644 vsix/Microsoft.Cpp.CppWinRT.props delete mode 100644 vsix/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props delete mode 100644 vsix/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props delete mode 100644 vsix/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props delete mode 100644 vsix/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props create mode 100644 vsix/Resources/VSPackage.cs-CZ.resx create mode 100644 vsix/Resources/VSPackage.de-DE.resx create mode 100644 vsix/Resources/VSPackage.en-US.resx create mode 100644 vsix/Resources/VSPackage.es-ES.resx create mode 100644 vsix/Resources/VSPackage.fr-FR.resx create mode 100644 vsix/Resources/VSPackage.it-IT.resx create mode 100644 vsix/Resources/VSPackage.ja-JP.resx create mode 100644 vsix/Resources/VSPackage.ko-KR.resx create mode 100644 vsix/Resources/VSPackage.pl-PL.resx create mode 100644 vsix/Resources/VSPackage.pt-BR.resx create mode 100644 vsix/Resources/VSPackage.resx create mode 100644 vsix/Resources/VSPackage.ru-RU.resx create mode 100644 vsix/Resources/VSPackage.tr-TR.resx create mode 100644 vsix/Resources/VSPackage.zh-CN.resx create mode 100644 vsix/Resources/VSPackage.zh-TW.resx diff --git a/build_vsix.cmd b/build_vsix.cmd index ef9c9d870..ba2f75f31 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -33,4 +33,4 @@ rem Build nuget .nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%this_dir%_build\arm\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed rem Build vsix -call msbuild /restore /p:Configuration=%target_configuration%,Platform=x86,Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln +call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln diff --git a/vsix/Application Type/Windows Store/10.0/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Application Type/Windows Store/10.0/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Application Type/Windows Store/10.0/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/Application Type/Windows Store/10.0/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Application Type/Windows Store/10.0/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Application Type/Windows Store/10.0/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/Application Type/Windows Store/10.0/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Application Type/Windows Store/10.0/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Application Type/Windows Store/10.0/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/Application Type/Windows Store/10.0/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Application Type/Windows Store/10.0/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Application Type/Windows Store/10.0/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/Dev16/Component/source.extension.vsixmanifest b/vsix/Dev16/Component/source.extension.vsixmanifest index 31e70dda2..afd96cf1f 100644 --- a/vsix/Dev16/Component/source.extension.vsixmanifest +++ b/vsix/Dev16/Component/source.extension.vsixmanifest @@ -22,6 +22,9 @@ + + + diff --git a/vsix/Dev16/Standalone/source.extension.vsixmanifest b/vsix/Dev16/Standalone/source.extension.vsixmanifest index 83eebd662..e3c2ac995 100644 --- a/vsix/Dev16/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev16/Standalone/source.extension.vsixmanifest @@ -22,6 +22,9 @@ + + + diff --git a/vsix/Dev16/VSPackage.cs b/vsix/Dev16/VSPackage.cs new file mode 100644 index 000000000..1a29a4908 --- /dev/null +++ b/vsix/Dev16/VSPackage.cs @@ -0,0 +1,55 @@ +using Microsoft.VisualStudio.Shell; +using System; +using System.Runtime.InteropServices; +using System.Threading; +using Task = System.Threading.Tasks.Task; + +namespace Microsoft.Windows.CppWinRT +{ + /// + /// This is the class that implements the package exposed by this assembly. + /// + /// + /// + /// The minimum requirement for a class to be considered a valid package for Visual Studio + /// is to implement the IVsPackage interface and register itself with the shell. + /// This package uses the helper classes defined inside the Managed Package Framework (MPF) + /// to do it: it derives from the Package class that provides the implementation of the + /// IVsPackage interface and uses the registration attributes defined in the framework to + /// register itself and its components with the shell. These attributes tell the pkgdef creation + /// utility what data to put into .pkgdef file. + /// + /// + /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. + /// + /// + [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [Guid(VSPackage.PackageGuidString)] + public sealed class VSPackage : AsyncPackage + { + /// + /// VSPackage GUID string. + /// + /// NOTE: This MUST match the MSBuild property 'PackageGuidString' defined in the .csproj + /// + public const string PackageGuidString = "65AB6475-E73B-40DB-B2B2-2DDACC320433"; + + #region Package Members + + /// + /// Initialization of the package; this method is called right after the package is sited, so this is the place + /// where you can put all the initialization code that rely on services provided by VisualStudio. + /// + /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down. + /// A provider for progress updates. + /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method. + protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) + { + // When initialized asynchronously, the current thread may be a background thread at this point. + // Do any initialization that requires the UI thread after switching to the UI thread. + await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + } + + #endregion + } +} diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index 84500cc26..6c1c2f1eb 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -1,102 +1,46 @@  - + + - 15.0 - - - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - true + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + false + {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA} + Library + Properties + Microsoft.Windows.CppWinRT + Microsoft.Windows.CppWinRT + net472 + true + true + false + false + true + + {65AB6475-E73B-40DB-B2B2-2DDACC320433} + $(Deployment)\source.extension.vsixmanifest - + true - bin\x86\Debug\$(Deployment)\ + bin\Debug\$(Deployment)\ DEBUG;TRACE full - x86 prompt MinimumRecommendedRules.ruleset - - bin\x86\Release\$(Deployment)\ + + bin\Release\$(Deployment)\ TRACE true pdbonly - x86 prompt MinimumRecommendedRules.ruleset - - - Release - x86 - 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - false - Standalone - {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA} - Library - Properties - Microsoft.Windows.CppWinRT - Microsoft.Windows.CppWinRT - v4.5.2 - false - false - false - false - false - false - true - %(Filename)%(Extension) true - - Microsoft\VC\v160 - MSBuild - true - - - Microsoft\VC\v160\Platforms\ARM\ImportBefore - MSBuild - true - - - Microsoft\VC\v160\Platforms\ARM64\ImportBefore - MSBuild - true - - - Microsoft\VC\v160\Platforms\Win32\ImportBefore - MSBuild - true - - - Microsoft\VC\v160\Platforms\x64\ImportBefore - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\ARM\ImportAfter - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\ARM64\ImportAfter - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\Win32\ImportAfter - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\x64\ImportAfter - MSBuild - true - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg true @@ -135,40 +79,89 @@ + + 16.10.31321.278 + compile; build; native; contentfiles; analyzers; buildtransitive + 17.0.1619-preview1 runtime; build; native; contentfiles; analyzers; buildtransitive all - + + + Resources\VSPackage.resx + + + + + Resources\VSPackage.cs-CZ.resx + + + + + Resources\VSPackage.de-DE.resx + + + + + Resources\VSPackage.es-ES.resx + + + + + Resources\VSPackage.fr-FR.resx + + + + + Resources\VSPackage.it-IT.resx + + + + + Resources\VSPackage.ja-JP.resx + + + + + Resources\VSPackage.ko-KR.resx + + + + + Resources\VSPackage.pl-PL.resx + + + + + Resources\VSPackage.pt-BR.resx + + + + + Resources\VSPackage.ru-RU.resx + + + + + Resources\VSPackage.tr-TR.resx + + + + + Resources\VSPackage.zh-CN.resx + + + + + Resources\VSPackage.zh-TW.resx + + + + + - - - - - - - - - - - - $(MSBuildProjectDirectory)\$(OutDir)%(RecursiveDir) - - - - - - - - true - false - %(RecursiveDir) - - - - - - + \ No newline at end of file diff --git a/vsix/Dev17/Component/source.extension.vsixmanifest b/vsix/Dev17/Component/source.extension.vsixmanifest index fcb101d54..bcbfa9c8b 100644 --- a/vsix/Dev17/Component/source.extension.vsixmanifest +++ b/vsix/Dev17/Component/source.extension.vsixmanifest @@ -28,6 +28,9 @@ + + + diff --git a/vsix/Dev17/Standalone/source.extension.vsixmanifest b/vsix/Dev17/Standalone/source.extension.vsixmanifest index 687d34172..56ea4b86f 100644 --- a/vsix/Dev17/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev17/Standalone/source.extension.vsixmanifest @@ -28,6 +28,9 @@ + + + diff --git a/vsix/Dev17/VSPackage.cs b/vsix/Dev17/VSPackage.cs new file mode 100644 index 000000000..12ffe0348 --- /dev/null +++ b/vsix/Dev17/VSPackage.cs @@ -0,0 +1,55 @@ +using Microsoft.VisualStudio.Shell; +using System; +using System.Runtime.InteropServices; +using System.Threading; +using Task = System.Threading.Tasks.Task; + +namespace Microsoft.Windows.CppWinRT +{ + /// + /// This is the class that implements the package exposed by this assembly. + /// + /// + /// + /// The minimum requirement for a class to be considered a valid package for Visual Studio + /// is to implement the IVsPackage interface and register itself with the shell. + /// This package uses the helper classes defined inside the Managed Package Framework (MPF) + /// to do it: it derives from the Package class that provides the implementation of the + /// IVsPackage interface and uses the registration attributes defined in the framework to + /// register itself and its components with the shell. These attributes tell the pkgdef creation + /// utility what data to put into .pkgdef file. + /// + /// + /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. + /// + /// + [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] + [Guid(VSPackage.PackageGuidString)] + public sealed class VSPackage : AsyncPackage + { + /// + /// VSPackage GUID string. + /// + /// NOTE: This MUST match the MSBuild property 'PackageGuidString' defined in the .csproj + /// + public const string PackageGuidString = "680FA95B-2E0E-4526-8531-F7450D7FE317"; + + #region Package Members + + /// + /// Initialization of the package; this method is called right after the package is sited, so this is the place + /// where you can put all the initialization code that rely on services provided by VisualStudio. + /// + /// A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down. + /// A provider for progress updates. + /// A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method. + protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress) + { + // When initialized asynchronously, the current thread may be a background thread at this point. + // Do any initialization that requires the UI thread after switching to the UI thread. + await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); + } + + #endregion + } +} diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index ecc1d615c..22c7fc2f2 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -1,31 +1,26 @@  - + + - 16.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - Debug - AnyCPU 2.0 {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} {3D56768C-78A5-4340-99AE-C728F3C75C1D} Library Properties - Microsoft.Windows.CppWinRT.Dev17 + Microsoft.Windows.CppWinRT Microsoft.Windows.CppWinRT.Dev17 - v4.7.2 - false - false + net472 + true + true false false - false - false Program $(DevEnvDir)devenv.exe /rootsuffix Exp true + + {680FA95B-2E0E-4526-8531-F7450D7FE317} + $(Deployment)\source.extension.vsixmanifest true @@ -49,51 +44,6 @@ %(Filename)%(Extension) true - - Microsoft\VC\v160 - MSBuild - true - - - Microsoft\VC\v160\Platforms\ARM\ImportBefore - MSBuild - true - - - Microsoft\VC\v160\Platforms\ARM64\ImportBefore - MSBuild - true - - - Microsoft\VC\v160\Platforms\Win32\ImportBefore - MSBuild - true - - - Microsoft\VC\v160\Platforms\x64\ImportBefore - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\ARM\ImportAfter - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\ARM64\ImportAfter - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\Win32\ImportAfter - MSBuild - true - - - Application Type\Windows Store\10.0\Platforms\x64\ImportAfter - MSBuild - true - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg true @@ -129,6 +79,7 @@ + @@ -140,38 +91,80 @@ all + - + + Resources\VSPackage.resx + + + + + Resources\VSPackage.cs-CZ.resx + + + + + Resources\VSPackage.de-DE.resx + + + + + Resources\VSPackage.es-ES.resx + + + + + Resources\VSPackage.fr-FR.resx + + + + + Resources\VSPackage.it-IT.resx + + + + + Resources\VSPackage.ja-JP.resx + + + + + Resources\VSPackage.ko-KR.resx + + + + + Resources\VSPackage.pl-PL.resx + + + + + Resources\VSPackage.pt-BR.resx + + + + + Resources\VSPackage.ru-RU.resx + + + + + Resources\VSPackage.tr-TR.resx + + + + + Resources\VSPackage.zh-CN.resx + + + + + Resources\VSPackage.zh-TW.resx + + + - + - - - - - - - - - - - - $(MSBuildProjectDirectory)\$(OutDir)%(RecursiveDir) - - - - - - - - true - false - %(RecursiveDir) - - - - - - - + \ No newline at end of file diff --git a/vsix/Directory.Build.Props b/vsix/Directory.Build.Props index 43dc9c92d..4bd0f8a6f 100644 --- a/vsix/Directory.Build.Props +++ b/vsix/Directory.Build.Props @@ -1,10 +1,26 @@ - - - $(MSBuildThisFileDirectory)..\ - $(MSBuildThisFileDirectory) - + + Standalone + + + + + $(MSBuildThisFileDirectory)..\ + $(MSBuildThisFileDirectory) + + + + Release + AnyCPU + false + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + true + win + true + false + \ No newline at end of file diff --git a/vsix/Extension.targets b/vsix/Extension.targets new file mode 100644 index 000000000..7a7b6c2b8 --- /dev/null +++ b/vsix/Extension.targets @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + $(MSBuildProjectDirectory)\$(OutDir)%(RecursiveDir) + + + + + + + + + + + + + + + + + + + + + true + false + %(RecursiveDir) + + + + + + + \ No newline at end of file diff --git a/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate b/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate index 325ce0b2c..672d43b2f 100644 --- a/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate +++ b/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate @@ -1,8 +1,8 @@ BlankPage - Blank Page (C++/WinRT) - A single page with no predefined layout, for a C++/WinRT Universal Windows Platform (UWP) app + + VC 10 microsoft.Windows.CppWinRT.BlankPage diff --git a/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate b/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate index 2e271ff86..e872ae3e0 100644 --- a/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate +++ b/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate @@ -1,8 +1,8 @@ BlankUserControl - Blank User Control (C++/WinRT) - A blank user control with no predefined layout, for a C++/WinRT Universal Windows Platform (UWP) app + + VC 10 microsoft.Windows.CppWinRT.BlankUserControl diff --git a/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate b/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate index 47699df6d..5e5a5dbdd 100644 --- a/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate +++ b/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate @@ -1,8 +1,8 @@ ViewModel - View Model (C++/WinRT) - An empty interface definition suitable for XAML data binding, for a C++/WinRT Universal Windows Platform (UWP) app + + VC 10 microsoft.Windows.CppWinRT.ViewModel diff --git a/vsix/Microsoft.Cpp.CppWinRT.props b/vsix/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 7bb7adb6a..000000000 --- a/vsix/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - false - true - false - - - - - - - diff --git a/vsix/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Platforms/ARM/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Platforms/ARM64/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Platforms/Win32/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props b/vsix/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props deleted file mode 100644 index 75cb347b7..000000000 --- a/vsix/Platforms/x64/ImportAfter/Microsoft.Cpp.CppWinRT.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/cppwinrt_ConsoleApplication.vstemplate b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/cppwinrt_ConsoleApplication.vstemplate index 07ff29751..747463a4a 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/cppwinrt_ConsoleApplication.vstemplate +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/cppwinrt_ConsoleApplication.vstemplate @@ -1,7 +1,7 @@ - Windows Console Application (C++/WinRT) - A project for creating a C++/WinRT Windows console application + + VC 4000 microsoft.Windows.CppWinRT.ConsoleApplication diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/cppwinrt_WindowsApplication.vstemplate b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/cppwinrt_WindowsApplication.vstemplate index 04023bb11..881e36cf6 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/cppwinrt_WindowsApplication.vstemplate +++ b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/cppwinrt_WindowsApplication.vstemplate @@ -1,7 +1,7 @@ - Windows Desktop Application (C++/WinRT) - A project for creating a C++/WinRT Windows desktop application + + VC 4000 microsoft.Windows.CppWinRT.WindowsApplication diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/cppwinrt_BlankApp.vstemplate b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/cppwinrt_BlankApp.vstemplate index a77c8a043..9fb9bec42 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/cppwinrt_BlankApp.vstemplate +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/cppwinrt_BlankApp.vstemplate @@ -1,7 +1,7 @@ - Blank App (C++/WinRT) - A project for a single page C++/WinRT Universal Windows Platform (UWP) app with no predefined layout + + VC 1000 microsoft.Windows.CppWinRT.BlankApp diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/cppwinrt_CoreApp.vstemplate b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/cppwinrt_CoreApp.vstemplate index c896067e2..f218c3342 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/cppwinrt_CoreApp.vstemplate +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/cppwinrt_CoreApp.vstemplate @@ -1,7 +1,7 @@ - Core App (C++/WinRT) - A project for a C++/WinRT Universal Windows Platform (UWP) app directly implementing CoreApplication + + VC 2000 microsoft.Windows.CppWinRT.CoreApp diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/cppwinrt_StaticLibrary.vstemplate b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/cppwinrt_StaticLibrary.vstemplate index 7eda1ca29..8dbe05d86 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/cppwinrt_StaticLibrary.vstemplate +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/cppwinrt_StaticLibrary.vstemplate @@ -1,7 +1,7 @@ - Static Library (C++/WinRT) - A project for a C++/WinRT Static Library that can be used by a Universal Windows Platform app + + VC 3000 microsoft.Windows.CppWinRT.StaticLibrary diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/cppwinrt_WindowsRuntimeComponent.vstemplate b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/cppwinrt_WindowsRuntimeComponent.vstemplate index ed111f821..7c72a64c8 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/cppwinrt_WindowsRuntimeComponent.vstemplate +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/cppwinrt_WindowsRuntimeComponent.vstemplate @@ -1,7 +1,7 @@ - Windows Runtime Component (C++/WinRT) - A project for a C++/WinRT Windows Runtime component that can be used by a Universal Windows Platform app + + VC 3000 microsoft.Windows.CppWinRT.WindowsRuntimeComponent diff --git a/vsix/Resources/VSPackage.cs-CZ.resx b/vsix/Resources/VSPackage.cs-CZ.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.cs-CZ.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.de-DE.resx b/vsix/Resources/VSPackage.de-DE.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.de-DE.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.en-US.resx b/vsix/Resources/VSPackage.en-US.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.en-US.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.es-ES.resx b/vsix/Resources/VSPackage.es-ES.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.es-ES.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.fr-FR.resx b/vsix/Resources/VSPackage.fr-FR.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.fr-FR.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.it-IT.resx b/vsix/Resources/VSPackage.it-IT.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.it-IT.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.ja-JP.resx b/vsix/Resources/VSPackage.ja-JP.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.ja-JP.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.ko-KR.resx b/vsix/Resources/VSPackage.ko-KR.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.ko-KR.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.pl-PL.resx b/vsix/Resources/VSPackage.pl-PL.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.pl-PL.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.pt-BR.resx b/vsix/Resources/VSPackage.pt-BR.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.pt-BR.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.resx b/vsix/Resources/VSPackage.resx new file mode 100644 index 000000000..731c40309 --- /dev/null +++ b/vsix/Resources/VSPackage.resx @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Windows Console Application (C++/WinRT) + + + A project for creating a C++/WinRT Windows console application. + + + Windows Desktop Application (C++/WinRT) + + + A project for creating a C++/WinRT Windows desktop application. + + + Blank App (C++/WinRT) + + + A project for a single page C++/WinRT Universal Windows Platform (UWP) app with no predefined layout. + + + Core App (C++/WinRT) + + + A project for a C++/WinRT Universal Windows Platform (UWP) app directly implementing CoreApplication. + + + Static Library (C++/WinRT) + + + A project for a C++/WinRT Static Library that can be used by a Universal Windows Platform app. + + + Windows Runtime Component (C++/WinRT) + + + A project for a C++/WinRT Windows Runtime component that can be used by a Universal Windows Platform app. + + + Blank Page (C++/WinRT) + + + A single page with no predefined layout, for a C++/WinRT Universal Windows Platform (UWP) app. + + + Blank User Control (C++/WinRT) + + + A blank user control with no predefined layout, for a C++/WinRT Universal Windows Platform (UWP) app. + + + View Model (C++/WinRT) + + + An empty interface definition suitable for XAML data binding, for a C++/WinRT Universal Windows Platform (UWP) app. + + diff --git a/vsix/Resources/VSPackage.ru-RU.resx b/vsix/Resources/VSPackage.ru-RU.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.ru-RU.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.tr-TR.resx b/vsix/Resources/VSPackage.tr-TR.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.tr-TR.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.zh-CN.resx b/vsix/Resources/VSPackage.zh-CN.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.zh-CN.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/Resources/VSPackage.zh-TW.resx b/vsix/Resources/VSPackage.zh-TW.resx new file mode 100644 index 000000000..c3d2f10dc --- /dev/null +++ b/vsix/Resources/VSPackage.zh-TW.resx @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/vsix/vsix.sln b/vsix/vsix.sln index 53a11fdc3..d10f26424 100644 --- a/vsix/vsix.sln +++ b/vsix/vsix.sln @@ -17,12 +17,12 @@ Global GlobalSection(ProjectConfigurationPlatforms) = postSolution {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Debug|x86.ActiveCfg = Debug|x86 - {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Debug|x86.Build.0 = Debug|x86 + {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Debug|x86.ActiveCfg = Debug|Any CPU + {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Debug|x86.Build.0 = Debug|Any CPU {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Release|Any CPU.Build.0 = Release|Any CPU - {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Release|x86.ActiveCfg = Release|x86 - {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Release|x86.Build.0 = Release|x86 + {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Release|x86.ActiveCfg = Release|Any CPU + {2F0C4AFA-FEFA-4D37-B824-0426CEB32DBA}.Release|x86.Build.0 = Release|Any CPU {3D56768C-78A5-4340-99AE-C728F3C75C1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3D56768C-78A5-4340-99AE-C728F3C75C1D}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D56768C-78A5-4340-99AE-C728F3C75C1D}.Debug|x86.ActiveCfg = Debug|Any CPU From 0be01db74002bcbb6c9bcc3fd6f0ef88961bf71b Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Wed, 8 Dec 2021 16:58:41 -0500 Subject: [PATCH 072/305] Fix compilation under Clang (#1073) --- cppwinrt/code_writers.h | 3 ++- cppwinrt/cppwinrt.vcxproj | 3 ++- cppwinrt/cppwinrt.vcxproj.filters | 3 +++ strings/base_stringable_format.h | 12 ++++-------- strings/base_stringable_format_1.h | 9 +++++++++ 5 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 strings/base_stringable_format_1.h diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index c369eb98c..9d4b98e23 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3259,6 +3259,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable w.write(strings::base_reference_produce); w.write(strings::base_deferral); w.write(strings::base_coroutine_foundation); + w.write(strings::base_stringable_format); } else if (namespace_name == "Windows.Foundation.Collections") { @@ -3295,7 +3296,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (namespace_name == "Windows.Foundation") { w.write(strings::base_reference_produce_1); - w.write(strings::base_stringable_format); + w.write(strings::base_stringable_format_1); } } } diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 71272d14f..258feafc6 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -79,9 +79,10 @@ + - + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index bfd56434a..dfe1488ee 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -169,6 +169,9 @@ strings + + strings + strings diff --git a/strings/base_stringable_format.h b/strings/base_stringable_format.h index 41a54dfd4..86c5acfc6 100644 --- a/strings/base_stringable_format.h +++ b/strings/base_stringable_format.h @@ -1,12 +1,8 @@ #ifdef __cpp_lib_format -template<> -struct std::formatter : std::formatter +template +auto std::formatter::format(winrt::Windows::Foundation::IStringable const& obj, FormatContext& fc) { - template - auto format(winrt::Windows::Foundation::IStringable const& obj, FormatContext& fc) - { - return std::formatter::format(obj.ToString(), fc); - } -}; + return std::formatter::format(obj.ToString(), fc); +} #endif diff --git a/strings/base_stringable_format_1.h b/strings/base_stringable_format_1.h new file mode 100644 index 000000000..6a7becdfc --- /dev/null +++ b/strings/base_stringable_format_1.h @@ -0,0 +1,9 @@ + +#ifdef __cpp_lib_format +template <> +struct std::formatter : std::formatter +{ + template + auto format(winrt::Windows::Foundation::IStringable const& obj, FormatContext& fc); +}; +#endif From a8dbc8842e148d9f067c7388b9f8c3d39b506e2f Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 13 Dec 2021 11:53:52 -0800 Subject: [PATCH 073/305] Onboard to localization build (#1075) * TDBuild - updating localized resource files. * Remove unused localizations * TDBuild - updating localized resource files. * Update TDBuild pipeline naming localized resx files correctly Co-authored-by: TDBuild --- vsix/Dev16/vsix.Dev16.csproj | 26 ++-- vsix/Dev17/vsix.Dev17.csproj | 26 ++-- vsix/Resources/VSPackage.en-US.resx | 131 ------------------ .../{ => cs-CZ}/VSPackage.cs-CZ.resx | 2 +- .../{ => de-DE}/VSPackage.de-DE.resx | 56 +++++++- .../{ => es-ES}/VSPackage.es-ES.resx | 2 +- .../{ => fr-FR}/VSPackage.fr-FR.resx | 2 +- .../{ => it-IT}/VSPackage.it-IT.resx | 2 +- .../{ => ja-JP}/VSPackage.ja-JP.resx | 56 +++++++- .../{ => ko-KR}/VSPackage.ko-KR.resx | 2 +- .../{ => pl-PL}/VSPackage.pl-PL.resx | 2 +- .../{ => pt-BR}/VSPackage.pt-BR.resx | 2 +- .../{ => ru-RU}/VSPackage.ru-RU.resx | 2 +- .../{ => tr-TR}/VSPackage.tr-TR.resx | 2 +- .../{ => zh-CN}/VSPackage.zh-CN.resx | 2 +- .../{ => zh-TW}/VSPackage.zh-TW.resx | 2 +- 16 files changed, 147 insertions(+), 170 deletions(-) delete mode 100644 vsix/Resources/VSPackage.en-US.resx rename vsix/Resources/{ => cs-CZ}/VSPackage.cs-CZ.resx (99%) rename vsix/Resources/{ => de-DE}/VSPackage.de-DE.resx (70%) rename vsix/Resources/{ => es-ES}/VSPackage.es-ES.resx (99%) rename vsix/Resources/{ => fr-FR}/VSPackage.fr-FR.resx (99%) rename vsix/Resources/{ => it-IT}/VSPackage.it-IT.resx (99%) rename vsix/Resources/{ => ja-JP}/VSPackage.ja-JP.resx (67%) rename vsix/Resources/{ => ko-KR}/VSPackage.ko-KR.resx (99%) rename vsix/Resources/{ => pl-PL}/VSPackage.pl-PL.resx (99%) rename vsix/Resources/{ => pt-BR}/VSPackage.pt-BR.resx (99%) rename vsix/Resources/{ => ru-RU}/VSPackage.ru-RU.resx (99%) rename vsix/Resources/{ => tr-TR}/VSPackage.tr-TR.resx (99%) rename vsix/Resources/{ => zh-CN}/VSPackage.zh-CN.resx (99%) rename vsix/Resources/{ => zh-TW}/VSPackage.zh-TW.resx (99%) diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index 6c1c2f1eb..4b7c01cd2 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -95,67 +95,67 @@ - + Resources\VSPackage.cs-CZ.resx - + Resources\VSPackage.de-DE.resx - + Resources\VSPackage.es-ES.resx - + Resources\VSPackage.fr-FR.resx - + Resources\VSPackage.it-IT.resx - + Resources\VSPackage.ja-JP.resx - + Resources\VSPackage.ko-KR.resx - + Resources\VSPackage.pl-PL.resx - + Resources\VSPackage.pt-BR.resx - + Resources\VSPackage.ru-RU.resx - + Resources\VSPackage.tr-TR.resx - + Resources\VSPackage.zh-CN.resx - + Resources\VSPackage.zh-TW.resx diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index 22c7fc2f2..6e6c35bbf 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -98,67 +98,67 @@ - + Resources\VSPackage.cs-CZ.resx - + Resources\VSPackage.de-DE.resx - + Resources\VSPackage.es-ES.resx - + Resources\VSPackage.fr-FR.resx - + Resources\VSPackage.it-IT.resx - + Resources\VSPackage.ja-JP.resx - + Resources\VSPackage.ko-KR.resx - + Resources\VSPackage.pl-PL.resx - + Resources\VSPackage.pt-BR.resx - + Resources\VSPackage.ru-RU.resx - + Resources\VSPackage.tr-TR.resx - + Resources\VSPackage.zh-CN.resx - + Resources\VSPackage.zh-TW.resx diff --git a/vsix/Resources/VSPackage.en-US.resx b/vsix/Resources/VSPackage.en-US.resx deleted file mode 100644 index c3d2f10dc..000000000 --- a/vsix/Resources/VSPackage.en-US.resx +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - diff --git a/vsix/Resources/VSPackage.cs-CZ.resx b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx similarity index 99% rename from vsix/Resources/VSPackage.cs-CZ.resx rename to vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.cs-CZ.resx +++ b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.de-DE.resx b/vsix/Resources/de-DE/VSPackage.de-DE.resx similarity index 70% rename from vsix/Resources/VSPackage.de-DE.resx rename to vsix/Resources/de-DE/VSPackage.de-DE.resx index c3d2f10dc..df574fe4d 100644 --- a/vsix/Resources/VSPackage.de-DE.resx +++ b/vsix/Resources/de-DE/VSPackage.de-DE.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + Windows-Konsolenanwendung (C++/WinRT) + + + Ein Projekt zum Erstellen einer C++-/WinRT-Windows-Konsolenanwendung. + + + Windows Desktop Application (C++/WinRT) + + + Ein Projekt zum Erstellen einer C++-/WinRT-Windows-Desktopanwendung. + + + Leere App (C++/WinRT) + + + Ein Projekt für eine C++/WinRT-Universelle Windows-Plattform-App (Single Page C++/WinRT Universelle Windows-Plattform) ohne vordefiniertes Layout. + + + Core App (C++/WinRT) + + + Ein Projekt für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP), die CoreApplication direkt implementiert. + + + Statische Bibliothek (C++/WinRT) + + + Ein Projekt für eine statische C++-/WinRT-Bibliothek, die von einer Universelle Windows-Plattform App verwendet werden kann. + + + Windows-Runtime Komponente (C++/WinRT) + + + Ein Projekt für eine C++-/WinRT-Windows-Runtime-Komponente, die von einer Universelle Windows-Plattform App verwendet werden kann. + + + Leere Seite (C++/WinRT) + + + Eine einzelne Seite ohne vordefiniertes Layout für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP). + + + Leeres Benutzersteuerelement (C++/WinRT) + + + Ein leeres Benutzersteuerelement ohne vordefiniertes Layout für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP). + + + Modell anzeigen (C++/WinRT) + + + Eine leere Schnittstellendefinition, die für XAML-Datenbindungen, für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP) geeignet ist. + + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.es-ES.resx b/vsix/Resources/es-ES/VSPackage.es-ES.resx similarity index 99% rename from vsix/Resources/VSPackage.es-ES.resx rename to vsix/Resources/es-ES/VSPackage.es-ES.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.es-ES.resx +++ b/vsix/Resources/es-ES/VSPackage.es-ES.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.fr-FR.resx b/vsix/Resources/fr-FR/VSPackage.fr-FR.resx similarity index 99% rename from vsix/Resources/VSPackage.fr-FR.resx rename to vsix/Resources/fr-FR/VSPackage.fr-FR.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.fr-FR.resx +++ b/vsix/Resources/fr-FR/VSPackage.fr-FR.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.it-IT.resx b/vsix/Resources/it-IT/VSPackage.it-IT.resx similarity index 99% rename from vsix/Resources/VSPackage.it-IT.resx rename to vsix/Resources/it-IT/VSPackage.it-IT.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.it-IT.resx +++ b/vsix/Resources/it-IT/VSPackage.it-IT.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.ja-JP.resx b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx similarity index 67% rename from vsix/Resources/VSPackage.ja-JP.resx rename to vsix/Resources/ja-JP/VSPackage.ja-JP.resx index c3d2f10dc..197469cd3 100644 --- a/vsix/Resources/VSPackage.ja-JP.resx +++ b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + Windows コンソール アプリケーション (C++/WinRT) + + + C++/WinRT Windows コンソール アプリケーションを作成するためのプロジェクトです。 + + + Windows デスクトップ アプリケーション (C++/WinRT) + + + C++/WinRT Windows デスクトップ アプリケーションを作成するためのプロジェクトです。 + + + 空のアプリ (C++/WinRT) + + + 定義済みのレイアウトのない単一ページの C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用のプロジェクトです。 + + + コア アプリ (C++/WinRT) + + + CoreApplication を直接実装する C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用のプロジェクトです。 + + + スタティック ライブラリ (C++/WinRT) + + + ユニバーサル Windows プラットフォーム アプリで使用できる C++/WinRT スタティック ライブラリ用のプロジェクトです。 + + + Windows ランタイム コンポーネント (C++/WinRT) + + + ユニバーサル Windows プラットフォーム アプリで使用できる C++/WinRT Windows ランタイム コンポーネント用のプロジェクトです。 + + + 空白のページ (C++/WinRT) + + + C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の定義済みレイアウトのない単一ページ。 + + + 空のユーザー コントロール (C++/WinRT) + + + C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の、定義済みのレイアウトのない空のユーザー コントロールです。 + + + モデルの表示 (C++/WinRT) + + + C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の XAML データ バインドに適した空のインターフェイス定義。 + + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.ko-KR.resx b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx similarity index 99% rename from vsix/Resources/VSPackage.ko-KR.resx rename to vsix/Resources/ko-KR/VSPackage.ko-KR.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.ko-KR.resx +++ b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.pl-PL.resx b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx similarity index 99% rename from vsix/Resources/VSPackage.pl-PL.resx rename to vsix/Resources/pl-PL/VSPackage.pl-PL.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.pl-PL.resx +++ b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.pt-BR.resx b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx similarity index 99% rename from vsix/Resources/VSPackage.pt-BR.resx rename to vsix/Resources/pt-BR/VSPackage.pt-BR.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.pt-BR.resx +++ b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.ru-RU.resx b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx similarity index 99% rename from vsix/Resources/VSPackage.ru-RU.resx rename to vsix/Resources/ru-RU/VSPackage.ru-RU.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.ru-RU.resx +++ b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.tr-TR.resx b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx similarity index 99% rename from vsix/Resources/VSPackage.tr-TR.resx rename to vsix/Resources/tr-TR/VSPackage.tr-TR.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.tr-TR.resx +++ b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.zh-CN.resx b/vsix/Resources/zh-CN/VSPackage.zh-CN.resx similarity index 99% rename from vsix/Resources/VSPackage.zh-CN.resx rename to vsix/Resources/zh-CN/VSPackage.zh-CN.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.zh-CN.resx +++ b/vsix/Resources/zh-CN/VSPackage.zh-CN.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file diff --git a/vsix/Resources/VSPackage.zh-TW.resx b/vsix/Resources/zh-TW/VSPackage.zh-TW.resx similarity index 99% rename from vsix/Resources/VSPackage.zh-TW.resx rename to vsix/Resources/zh-TW/VSPackage.zh-TW.resx index c3d2f10dc..edbbe5905 100644 --- a/vsix/Resources/VSPackage.zh-TW.resx +++ b/vsix/Resources/zh-TW/VSPackage.zh-TW.resx @@ -128,4 +128,4 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + \ No newline at end of file From 8be3a88896bb367f15950235755493dbf24d7b12 Mon Sep 17 00:00:00 2001 From: TDBuild Date: Wed, 15 Dec 2021 00:52:32 +0000 Subject: [PATCH 074/305] TDBuild - updating localized resource files. --- vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx | 54 +++++++++++++++++++++++ vsix/Resources/es-ES/VSPackage.es-ES.resx | 54 +++++++++++++++++++++++ vsix/Resources/fr-FR/VSPackage.fr-FR.resx | 54 +++++++++++++++++++++++ vsix/Resources/it-IT/VSPackage.it-IT.resx | 54 +++++++++++++++++++++++ vsix/Resources/ko-KR/VSPackage.ko-KR.resx | 54 +++++++++++++++++++++++ vsix/Resources/pl-PL/VSPackage.pl-PL.resx | 54 +++++++++++++++++++++++ vsix/Resources/pt-BR/VSPackage.pt-BR.resx | 54 +++++++++++++++++++++++ vsix/Resources/ru-RU/VSPackage.ru-RU.resx | 54 +++++++++++++++++++++++ vsix/Resources/tr-TR/VSPackage.tr-TR.resx | 54 +++++++++++++++++++++++ vsix/Resources/zh-CN/VSPackage.zh-CN.resx | 54 +++++++++++++++++++++++ vsix/Resources/zh-TW/VSPackage.zh-TW.resx | 54 +++++++++++++++++++++++ 11 files changed, 594 insertions(+) diff --git a/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx index edbbe5905..2459e857c 100644 --- a/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx +++ b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Konzolová aplikace systému Windows (C++/WinRT) + + + Projekt pro vytvoření konzolové aplikace C++/WinRT systému Windows + + + Desktopová aplikace pro Windows (C++/WinRT) + + + Projekt pro vytvoření desktopové aplikace C++/WinRT pro Windows + + + Prázdná aplikace (C++/WinRT) + + + Projekt pro jednostránkovou aplikaci C++/WinRT Univerzální platforma Windows (UPW) bez předdefinovaného rozložení + + + Základní aplikace (C++/WinRT) + + + Projekt pro aplikaci C++/WinRT Univerzální platforma Windows (UPW) přímo implementující CoreApplication + + + Statická knihovna (C++/WinRT) + + + Projekt pro statickou knihovnu C++/WinRT, kterou může používat aplikace Univerzální platforma Windows + + + prostředí Windows Runtime komponenta (C++/WinRT) + + + Projekt pro komponentu prostředí Windows Runtime C++/WinRT, kterou může používat aplikace Univerzální platforma Windows + + + Prázdná stránka (C++/WinRT) + + + Jedna stránka bez předdefinovaného rozložení pro aplikaci C++/WinRT Univerzální platforma Windows (UPW) + + + Prázdný uživatelský ovládací prvek (C++/WinRT) + + + Prázdný uživatelský ovládací prvek bez předdefinovaného rozložení pro aplikaci C++/WinRT Univerzální platforma Windows (UPW) + + + Zobrazit model (C++/WinRT) + + + Prázdná definice rozhraní vhodná pro datovou vazbu XAML pro aplikaci C++/WinRT Univerzální platforma Windows (UPW). + \ No newline at end of file diff --git a/vsix/Resources/es-ES/VSPackage.es-ES.resx b/vsix/Resources/es-ES/VSPackage.es-ES.resx index edbbe5905..5458c8743 100644 --- a/vsix/Resources/es-ES/VSPackage.es-ES.resx +++ b/vsix/Resources/es-ES/VSPackage.es-ES.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Aplicación de consola de Windows (C++/WinRT) + + + Proyecto para crear una aplicación de consola de Windows C++/WinRT. + + + Aplicación de escritorio de Windows (C++/WinRT) + + + Proyecto para crear una aplicación de escritorio de Windows C++/WinRT. + + + Aplicación en blanco (C++/WinRT) + + + Proyecto para una aplicación de Plataforma universal de Windows (UWP) de C++/WinRT de una sola página sin diseño predefinido. + + + Aplicación principal (C++/WinRT) + + + Proyecto para una aplicación de C++/WinRT Plataforma universal de Windows (UWP) que implementa CoreApplication directamente. + + + Biblioteca estática (C++/WinRT) + + + Proyecto para una biblioteca estática de C++/WinRT que puede usar una aplicación Plataforma universal de Windows. + + + componente Windows Runtime (C++/WinRT) + + + Proyecto para un componente de Windows Runtime de C++/WinRT que puede usar una aplicación Plataforma universal de Windows. + + + Página en blanco (C++/WinRT) + + + Una sola página sin diseño predefinido para una aplicación Plataforma universal de Windows Plataforma universal de Windows (UWP) de C++/WinRT. + + + Control de usuario en blanco (C++/WinRT) + + + Control de usuario en blanco sin diseño predefinido para una aplicación Plataforma universal de Windows Plataforma universal de Windows (UWP) de C++/WinRT. + + + Ver modelo (C++/WinRT) + + + Definición de interfaz vacía adecuada para el enlace de datos XAML para una aplicación Plataforma universal de Windows Plataforma universal de Windows (UWP) de C++/WinRT. + \ No newline at end of file diff --git a/vsix/Resources/fr-FR/VSPackage.fr-FR.resx b/vsix/Resources/fr-FR/VSPackage.fr-FR.resx index edbbe5905..25e96709a 100644 --- a/vsix/Resources/fr-FR/VSPackage.fr-FR.resx +++ b/vsix/Resources/fr-FR/VSPackage.fr-FR.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Application console Windows (C++/WinRT) + + + Projet de création d’une application console Windows C++/WinRT. + + + Application de bureau Windows (C++/WinRT) + + + Projet de création d’une application de bureau Windows C++/WinRT. + + + Application vide (C++/WinRT) + + + Projet pour une application de plateforme Windows universelle (UWP) C++/WinRT à page unique sans disposition prédéfinie. + + + Application principale (C++/WinRT) + + + Projet pour une application C++/WinRT plateforme Windows universelle (UWP) implémentant directement CoreApplication. + + + Bibliothèque statique (C++/WinRT) + + + Projet pour une bibliothèque statique C++/WinRT pouvant être utilisée par une application plateforme Windows universelle. + + + composant Windows Runtime (C++/WinRT) + + + Projet pour un composant Windows Runtime C++/WinRT qui peut être utilisé par une application plateforme Windows universelle. + + + Page vierge (C++/WinRT) + + + Page unique sans disposition prédéfinie pour une application de plateforme Windows universelle (UWP) C++/WinRT. + + + Contrôle utilisateur vide (C++/WinRT) + + + Contrôle utilisateur vide sans disposition prédéfinie pour une application de plateforme Windows universelle (UWP) C++/WinRT. + + + Afficher le modèle (C++/WinRT) + + + Définition d’interface vide adaptée à la liaison de données XAML pour une application UWP (C++/WinRT plateforme Windows universelle). + \ No newline at end of file diff --git a/vsix/Resources/it-IT/VSPackage.it-IT.resx b/vsix/Resources/it-IT/VSPackage.it-IT.resx index edbbe5905..3419eae6f 100644 --- a/vsix/Resources/it-IT/VSPackage.it-IT.resx +++ b/vsix/Resources/it-IT/VSPackage.it-IT.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Applicazione console Windows (C++/WinRT) + + + Progetto per la creazione di un'applicazione console windows C++/WinRT. + + + Applicazione desktop di Windows (C++/WinRT) + + + Progetto per la creazione di un'applicazione desktop windows C++/WinRT. + + + App vuota (C++/WinRT) + + + Progetto per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) a pagina singola senza layout predefinito. + + + App principale (C++/WinRT) + + + Progetto per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) (UWP) che implementa direttamente CoreApplication. + + + Libreria statica (C++/WinRT) + + + Progetto per una libreria statica C++/WinRT utilizzabile da un'app piattaforma UWP (Universal Windows Platform). + + + componente Windows Runtime (C++/WinRT) + + + Progetto per un componente di Windows Runtime C++/WinRT che può essere usato da un'app piattaforma UWP (Universal Windows Platform). + + + Pagina vuota (C++/WinRT) + + + Singola pagina senza layout predefinito per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) (UWP). + + + Controllo utente vuoto (C++/WinRT) + + + Controllo utente vuoto senza layout predefinito per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) (UWP). + + + Visualizza modello (C++/WinRT) + + + Definizione di interfaccia vuota adatta per data binding XAML per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) (UWP). + \ No newline at end of file diff --git a/vsix/Resources/ko-KR/VSPackage.ko-KR.resx b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx index edbbe5905..eb2ef40fb 100644 --- a/vsix/Resources/ko-KR/VSPackage.ko-KR.resx +++ b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Windows 콘솔 응용 프로그램(C++/WinRT) + + + C++/WinRT Windows 콘솔 응용 프로그램을 만드는 프로젝트입니다. + + + Windows 데스크톱 응용 프로그램(C++/WinRT) + + + C++/WinRT Windows 데스크톱 응용 프로그램을 만드는 프로젝트입니다. + + + 빈 앱(C++/WinRT) + + + 미리 정의된 레이아웃이 없는 단일 페이지 C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱용 프로젝트입니다. + + + 핵심 앱(C++/WinRT) + + + CoreApplication을 직접 구현하는 C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱용 프로젝트입니다. + + + 정적 라이브러리(C++/WinRT) + + + 유니버설 Windows 플랫폼 앱에서 사용할 수 있는 C++/WinRT 정적 라이브러리용 프로젝트입니다. + + + Windows 런타임 구성 요소(C++/WinRT) + + + 유니버설 Windows 플랫폼 앱에서 사용할 수 있는 C++/WinRT Windows 런타임 구성 요소에 대한 프로젝트입니다. + + + 빈 페이지(C++/WinRT) + + + C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 미리 정의된 레이아웃이 없는 단일 페이지입니다. + + + 빈 사용자 정의 컨트롤(C++/WinRT) + + + C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 미리 정의된 레이아웃이 없는 빈 사용자 정의 컨트롤입니다. + + + 모델 보기(C++/WinRT) + + + C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 적합한 XAML 데이터 바인딩에 적합한 빈 인터페이스 정의입니다. + \ No newline at end of file diff --git a/vsix/Resources/pl-PL/VSPackage.pl-PL.resx b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx index edbbe5905..c30ee809b 100644 --- a/vsix/Resources/pl-PL/VSPackage.pl-PL.resx +++ b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Aplikacja konsolowa systemu Windows (C++/WinRT) + + + Projekt służący do tworzenia aplikacji konsoli systemu Windows języka C++/WinRT. + + + Aplikacja klasyczna systemu Windows (C++/WinRT) + + + Projekt służący do tworzenia aplikacji klasycznej systemu Windows C++/WinRT. + + + Pusta aplikacja (C++/WinRT) + + + Projekt jednostronicowej aplikacji C++/WinRT platforma uniwersalna systemu Windows (UWP) bez wstępnie zdefiniowanego układu. + + + Podstawowa aplikacja (C++/WinRT) + + + Projekt aplikacji języka C++/WinRT platforma uniwersalna systemu Windows (UWP) bezpośrednio implementującej funkcję CoreApplication. + + + Biblioteka statyczna (C++/WinRT) + + + Projekt biblioteki statycznej C++/WinRT, który może być używany przez aplikację platforma uniwersalna systemu Windows. + + + Składnik środowisko wykonawcze systemu Windows (C++/WinRT) + + + Projekt składnika środowisko wykonawcze systemu Windows C++/WinRT, który może być używany przez aplikację platforma uniwersalna systemu Windows. + + + Pusta strona (C++/WinRT) + + + Pojedyncza strona bez wstępnie zdefiniowanego układu dla aplikacji platforma uniwersalna systemu Windows C++/WinRT (UWP). + + + Pusta kontrolka użytkownika (C++/WinRT) + + + Pusta kontrolka użytkownika bez wstępnie zdefiniowanego układu dla aplikacji platforma uniwersalna systemu Windows C++/WinRT (UWP). + + + Wyświetl model (C++/WinRT) + + + Pusta definicja interfejsu odpowiednia dla powiązania danych XAML dla aplikacji platforma uniwersalna systemu Windows C++/WinRT (UWP). + \ No newline at end of file diff --git a/vsix/Resources/pt-BR/VSPackage.pt-BR.resx b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx index edbbe5905..304b5f317 100644 --- a/vsix/Resources/pt-BR/VSPackage.pt-BR.resx +++ b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Aplicativo de Console do Windows (C++/WinRT) + + + Um projeto para criar um aplicativo de console do Windows C++/WinRT. + + + Aplicativo do Windows Desktop (C++/WinRT) + + + Um projeto para criar um aplicativo de área de trabalho do Windows C++/WinRT. + + + Aplicativo em Branco (C++/WinRT) + + + Um projeto para um aplicativo de página única C++/WinRT Plataforma Universal do Windows (UWP) sem layout predefinido. + + + Aplicativo Principal (C++/WinRT) + + + Um projeto para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP) implementando coreApplication diretamente. + + + Biblioteca Estática (C++/WinRT) + + + Um projeto para uma Biblioteca Estática C++/WinRT que pode ser usada por um Plataforma Universal do Windows aplicativo. + + + Windows Runtime Componente (C++/WinRT) + + + Um projeto para um componente de Windows Runtime C++/WinRT que pode ser usado por um Plataforma Universal do Windows aplicativo. + + + Página em Branco (C++/WinRT) + + + Uma única página sem layout predefinido para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP). + + + Controle de Usuário em Branco (C++/WinRT) + + + Um controle de usuário em branco sem layout predefinido para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP). + + + Exibir Modelo (C++/WinRT) + + + Uma definição de interface vazia adequada para associação de dados XAML, para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP). + \ No newline at end of file diff --git a/vsix/Resources/ru-RU/VSPackage.ru-RU.resx b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx index edbbe5905..d7df363df 100644 --- a/vsix/Resources/ru-RU/VSPackage.ru-RU.resx +++ b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Консольное приложение Windows (C++/WinRT) + + + Проект по созданию консольного приложения C++/WinRT для Windows. + + + Классические приложения Windows (C++/WinRT) + + + Проект по созданию настольного приложения Для Windows C++/WinRT. + + + Пустое приложение (C++/WinRT) + + + Проект для одной страницы приложения C++/WinRT универсальная платформа Windows (UWP) без предопределенного макета. + + + Основное приложение (C++/WinRT) + + + Проект для приложения C++/WinRT универсальная платформа Windows (UWP), напрямую реализующий CoreApplication. + + + Статическая библиотека (C++/WinRT) + + + Проект для статической библиотеки C++/WinRT, которую может использовать универсальная платформа Windows приложения. + + + среда выполнения Windows (C++/WinRT) + + + Проект для компонента C++/WinRT среда выполнения Windows, который может использоваться приложением универсальная платформа Windows. + + + Пустая страница (C++/WinRT) + + + Одна страница без предопределенного макета для приложения C++/WinRT универсальная платформа Windows (UWP). + + + Пустой пользовательский элемент управления (C++/WinRT) + + + Пустой пользовательский элемент управления без предопределенного макета для приложения C++/WinRT универсальная платформа Windows (UWP). + + + Просмотреть модель (C++/WinRT) + + + Пустое определение интерфейса, подходящее для привязки данных XAML для приложения C++/WinRT универсальная платформа Windows (UWP). + \ No newline at end of file diff --git a/vsix/Resources/tr-TR/VSPackage.tr-TR.resx b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx index edbbe5905..e25f0be57 100644 --- a/vsix/Resources/tr-TR/VSPackage.tr-TR.resx +++ b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Windows Konsol Uygulaması (C++/WinRT) + + + C++/WinRT Windows konsol uygulaması oluşturmaya yönelik bir proje. + + + Windows Masaüstü Uygulaması (C++/WinRT) + + + C++/WinRT Windows masaüstü uygulaması oluşturmaya yönelik bir proje. + + + Boş Uygulama (C++/WinRT) + + + Önceden tanımlanmış düzeni olmayan tek sayfalı C++/WinRT Evrensel Windows Platformu (UWP) uygulaması için bir proje. + + + Çekirdek Uygulama (C++/WinRT) + + + Doğrudan CoreApplication uygulayan bir C++/WinRT Evrensel Windows Platformu (UWP) uygulaması projesi. + + + Statik Kitaplık (C++/WinRT) + + + Bir C++/WinRT Statik Kitaplığı için, bir uygulama tarafından kullanılabilecek Evrensel Windows Platformu proje. + + + Windows Çalışma Zamanı Bileşeni (C++/WinRT) + + + Bir C++/WinRT Windows Çalışma Zamanı uygulama tarafından kullanılabilecek bir Evrensel Windows Platformu. + + + Boş Sayfa (C++/WinRT) + + + C++/WinRT (UWP) uygulaması için önceden tanımlanmış düzeni olmayan Evrensel Windows Platformu sayfa. + + + Boş Kullanıcı Denetimi (C++/WinRT) + + + C++/WinRT (UWP) uygulaması için önceden tanımlanmış düzeni olmayan Evrensel Windows Platformu kullanıcı denetimi. + + + Modeli Görüntüle (C++/WinRT) + + + Bir C++/WinRT (UWP) uygulaması için XAML veri bağlaması Evrensel Windows Platformu boş bir arabirim tanımı. + \ No newline at end of file diff --git a/vsix/Resources/zh-CN/VSPackage.zh-CN.resx b/vsix/Resources/zh-CN/VSPackage.zh-CN.resx index edbbe5905..de6b6c29d 100644 --- a/vsix/Resources/zh-CN/VSPackage.zh-CN.resx +++ b/vsix/Resources/zh-CN/VSPackage.zh-CN.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Windows 控制台应用程序(C++/WinRT) + + + 用于创建 C++/WinRT Windows 控制台应用程序的项目。 + + + Windows 桌面应用程序(C++/WinRT) + + + 用于创建 C++/WinRT Windows 桌面应用程序的项目。 + + + 空白应用(C++/WinRT) + + + 用于单页 C++/WinRT 通用 Windows 平台 (UWP)应用的项目,无预定义布局。 + + + 核心应用(C++/WinRT) + + + 直接实现 CoreApplication 的 C++/WinRT 通用 Windows 平台 (UWP)应用的项目。 + + + 静态库(C++/WinRT) + + + 可用于通用 Windows 平台应用的 C++/WinRT 静态库的项目。 + + + Windows 运行时组件(C++/WinRT) + + + 可用于通用 Windows 平台应用的 C++/WinRT Windows 运行时组件的项目。 + + + 空白页(C++/WinRT) + + + 对于 C++/WinRT 通用 Windows 平台 (UWP)应用,单个页面没有预定义的布局。 + + + 空白用户控件(C++/WinRT) + + + 对于 C++/WinRT 通用 Windows 平台 (UWP)应用,没有预定义布局的空白用户控件。 + + + 查看模型(C++/WinRT) + + + 一个空接口定义,适用于 XAML 数据绑定,适用于 C++/WinRT 通用 Windows 平台 (UWP)应用。 + \ No newline at end of file diff --git a/vsix/Resources/zh-TW/VSPackage.zh-TW.resx b/vsix/Resources/zh-TW/VSPackage.zh-TW.resx index edbbe5905..b63846afa 100644 --- a/vsix/Resources/zh-TW/VSPackage.zh-TW.resx +++ b/vsix/Resources/zh-TW/VSPackage.zh-TW.resx @@ -128,4 +128,58 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Windows 主控台應用程式(C++/WinRT) + + + 用於建立 C++/WinRT Windows 主控台應用程式的專案。 + + + Windows 桌面應用程式(C++/WinRT) + + + 用於建立 C++/WinRT Windows 傳統型應用程式的專案。 + + + 空白應用程式(C++/WinRT) + + + 單頁 C++/WinRT 通用 Windows 平臺 (UWP)應用程式的專案,沒有預先定義的版面配置。 + + + 核心應用程式(C++/WinRT) + + + C++/WinRT 通用 Windows 平臺 (UWP)應用程式的專案,會直接實作 CoreApplication。 + + + 靜態程式庫(C++/WinRT) + + + C++/WinRT 靜態程式庫的專案,可供通用 Windows 平臺應用程式使用。 + + + Windows 執行階段元件(C++/WinRT) + + + C++/WinRT Windows 執行階段元件的專案,可供通用 Windows 平臺應用程式使用。 + + + 空白頁(C++/WinRT) + + + C++/WinRT 通用 Windows 平臺 (UWP)應用程式的單一頁面,沒有預先定義的版面配置。 + + + 空白使用者控制項(C++/WinRT) + + + C++/WinRT 通用 Windows 平臺 (UWP)應用程式的空白使用者控制項,沒有預先定義的配置。 + + + 檢視模型 (C++/WinRT) + + + 適用于 C++/WinRT 通用 Windows 平臺 (UWP) 應用程式之 XAML 資料系結的空白介面定義。 + \ No newline at end of file From acf7188bed36ccadb4c7f353539381e07753fab9 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 15 Dec 2021 10:45:04 -0800 Subject: [PATCH 075/305] Minor updates to binaries to enable tooling scans (#1077) --- cppwinrt/cppwinrt.vcxproj | 4 ++++ natvis/cppwinrtvisualizer.vcxproj | 2 ++ 2 files changed, 6 insertions(+) diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 258feafc6..653480c81 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -288,6 +288,7 @@ Console true true + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) $(OutputPath)prebuild.exe ..\strings $(OutputPath) @@ -309,6 +310,7 @@ Console true true + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) $(OutputPath)prebuild.exe ..\strings $(OutputPath) @@ -330,6 +332,7 @@ Console true true + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) $(OutputPath)prebuild.exe ..\strings $(OutputPath) @@ -351,6 +354,7 @@ Console true true + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) $(OutputPath)prebuild.exe ..\strings $(OutputPath) diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index 9f058f036..240182574 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -173,6 +173,7 @@ advapi32.lib;shell32.lib;windowsapp.lib;$(VsDebugEng_Lib);%(AdditionalDependencies) .\cppwinrtvisualizer.def vsdebugeng.dll + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) @@ -202,6 +203,7 @@ advapi32.lib;shell32.lib;windowsapp.lib;$(VsDebugEng_Lib);%(AdditionalDependencies) .\cppwinrtvisualizer.def vsdebugeng.dll + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) From 74a401dd848552b66f978bb4646f5afae8d18146 Mon Sep 17 00:00:00 2001 From: TDBuild Date: Thu, 16 Dec 2021 06:01:47 +0000 Subject: [PATCH 076/305] TDBuild - updating localized resource files. --- vsix/Resources/de-DE/VSPackage.de-DE.resx | 14 +++++------ vsix/Resources/pl-PL/VSPackage.pl-PL.resx | 14 +++++------ vsix/Resources/zh-TW/VSPackage.zh-TW.resx | 30 +++++++++++------------ 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/vsix/Resources/de-DE/VSPackage.de-DE.resx b/vsix/Resources/de-DE/VSPackage.de-DE.resx index df574fe4d..ddb6dc1af 100644 --- a/vsix/Resources/de-DE/VSPackage.de-DE.resx +++ b/vsix/Resources/de-DE/VSPackage.de-DE.resx @@ -135,7 +135,7 @@ Ein Projekt zum Erstellen einer C++-/WinRT-Windows-Konsolenanwendung. - Windows Desktop Application (C++/WinRT) + Windows-Desktopanwendung (C++/WinRT) Ein Projekt zum Erstellen einer C++-/WinRT-Windows-Desktopanwendung. @@ -144,10 +144,10 @@ Leere App (C++/WinRT) - Ein Projekt für eine C++/WinRT-Universelle Windows-Plattform-App (Single Page C++/WinRT Universelle Windows-Plattform) ohne vordefiniertes Layout. + Ein Projekt für eine einseitige C++/WinRT-Universelle Windows-Plattform-App (UWP) ohne vordefiniertes Layout. - Core App (C++/WinRT) + Core-App (C++/WinRT) Ein Projekt für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP), die CoreApplication direkt implementiert. @@ -156,13 +156,13 @@ Statische Bibliothek (C++/WinRT) - Ein Projekt für eine statische C++-/WinRT-Bibliothek, die von einer Universelle Windows-Plattform App verwendet werden kann. + Ein Projekt für eine statische C++/WinRT-Bibliothek, die von einer Universellen Windows-Plattform-App verwendet werden kann. - Windows-Runtime Komponente (C++/WinRT) + Komponente für Windows-Runtime (C++/WinRT) - Ein Projekt für eine C++-/WinRT-Windows-Runtime-Komponente, die von einer Universelle Windows-Plattform App verwendet werden kann. + Ein Projekt für eine C++/WinRT-Komponente für Windows-Runtime, die von einer Universellen Windows-Plattform-App verwendet werden kann. Leere Seite (C++/WinRT) @@ -180,6 +180,6 @@ Modell anzeigen (C++/WinRT) - Eine leere Schnittstellendefinition, die für XAML-Datenbindungen, für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP) geeignet ist. + Eine leere Schnittstellendefinition, die für die XAML-Datenbindung für eine C++/WinRT-Universelle Windows-Plattform-App (UWP) geeignet ist. \ No newline at end of file diff --git a/vsix/Resources/pl-PL/VSPackage.pl-PL.resx b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx index c30ee809b..06cae62fe 100644 --- a/vsix/Resources/pl-PL/VSPackage.pl-PL.resx +++ b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx @@ -144,37 +144,37 @@ Pusta aplikacja (C++/WinRT) - Projekt jednostronicowej aplikacji C++/WinRT platforma uniwersalna systemu Windows (UWP) bez wstępnie zdefiniowanego układu. + Projekt jednostronicowej aplikacji platformy uniwersalnej systemu Windows (UWP) C++/WinRT bez wstępnie zdefiniowanego układu. Podstawowa aplikacja (C++/WinRT) - Projekt aplikacji języka C++/WinRT platforma uniwersalna systemu Windows (UWP) bezpośrednio implementującej funkcję CoreApplication. + Projekt aplikacji platformy uniwersalnej systemu Windows (UWP) C++/WinRT bezpośrednio implementującej funkcję CoreApplication. Biblioteka statyczna (C++/WinRT) - Projekt biblioteki statycznej C++/WinRT, który może być używany przez aplikację platforma uniwersalna systemu Windows. + Projekt biblioteki statycznej C++/WinRT, który może być używany przez aplikację platformy uniwersalnej systemu Windows. - Składnik środowisko wykonawcze systemu Windows (C++/WinRT) + Składnik środowiska wykonawczego systemu Windows (C++/WinRT) - Projekt składnika środowisko wykonawcze systemu Windows C++/WinRT, który może być używany przez aplikację platforma uniwersalna systemu Windows. + Projekt składnika środowiska wykonawczego systemu Windows C++/WinRT, który może być używany przez aplikację platformy uniwersalnej systemu Windows. Pusta strona (C++/WinRT) - Pojedyncza strona bez wstępnie zdefiniowanego układu dla aplikacji platforma uniwersalna systemu Windows C++/WinRT (UWP). + Pojedyncza strona bez wstępnie zdefiniowanego układu dla aplikacji platformy uniwersalnej systemu Windows (UWP) C++/WinRT. Pusta kontrolka użytkownika (C++/WinRT) - Pusta kontrolka użytkownika bez wstępnie zdefiniowanego układu dla aplikacji platforma uniwersalna systemu Windows C++/WinRT (UWP). + Pusta kontrolka użytkownika bez wstępnie zdefiniowanego układu dla aplikacji platformy uniwersalnej systemu Windows (UWP) C++/WinRT. Wyświetl model (C++/WinRT) diff --git a/vsix/Resources/zh-TW/VSPackage.zh-TW.resx b/vsix/Resources/zh-TW/VSPackage.zh-TW.resx index b63846afa..cd9797c51 100644 --- a/vsix/Resources/zh-TW/VSPackage.zh-TW.resx +++ b/vsix/Resources/zh-TW/VSPackage.zh-TW.resx @@ -129,57 +129,57 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Windows 主控台應用程式(C++/WinRT) + Windows 主控台應用程式 (C++/WinRT) 用於建立 C++/WinRT Windows 主控台應用程式的專案。 - Windows 桌面應用程式(C++/WinRT) + 傳統型 Windows 應用程式 (C++/WinRT) 用於建立 C++/WinRT Windows 傳統型應用程式的專案。 - 空白應用程式(C++/WinRT) + 空白應用程式 (C++/WinRT) - 單頁 C++/WinRT 通用 Windows 平臺 (UWP)應用程式的專案,沒有預先定義的版面配置。 + 沒有預先定義配置的單頁 C++/WinRT 通用 Windows 平台 (UWP)應用程式之專案。 - 核心應用程式(C++/WinRT) + 核心應用程式 (C++/WinRT) - C++/WinRT 通用 Windows 平臺 (UWP)應用程式的專案,會直接實作 CoreApplication。 + 直接實作 CoreApplication 的 C++/WinRT 通用 Windows 平台 (UWP) 應用程式之專案。 - 靜態程式庫(C++/WinRT) + 靜態程式庫 (C++/WinRT) - C++/WinRT 靜態程式庫的專案,可供通用 Windows 平臺應用程式使用。 + 可供通用 Windows 平台應用程式使用的 C++/WinRT 靜態程式庫之專案。 - Windows 執行階段元件(C++/WinRT) + Windows 執行階段元件 (C++/WinRT) - C++/WinRT Windows 執行階段元件的專案,可供通用 Windows 平臺應用程式使用。 + 可供通用 Windows 平台應用程式使用的 C++/WinRT Windows 執行階段元件之專案。 - 空白頁(C++/WinRT) + 空白頁 (C++/WinRT) - C++/WinRT 通用 Windows 平臺 (UWP)應用程式的單一頁面,沒有預先定義的版面配置。 + 沒有預先定義配置的 C++/WinRT 通用 Windows 平台 (UWP)應用程式之單一頁面。 - 空白使用者控制項(C++/WinRT) + 空白使用者控制項 (C++/WinRT) - C++/WinRT 通用 Windows 平臺 (UWP)應用程式的空白使用者控制項,沒有預先定義的配置。 + 沒有預先定義配置的 C++/WinRT 通用 Windows 平台 (UWP)應用程式之空白使用者控制項。 檢視模型 (C++/WinRT) - 適用于 C++/WinRT 通用 Windows 平臺 (UWP) 應用程式之 XAML 資料系結的空白介面定義。 + 適用於 C++/WinRT 通用 Windows 平台 (UWP) 應用程式之 XAML 資料繫結的空白介面定義。 \ No newline at end of file From b8dcbbfeb0f005fdb49ff7f72f1525c09a7a58f2 Mon Sep 17 00:00:00 2001 From: TDBuild Date: Fri, 17 Dec 2021 06:01:41 +0000 Subject: [PATCH 077/305] TDBuild - updating localized resource files. --- vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx | 22 +++++++++++----------- vsix/Resources/es-ES/VSPackage.es-ES.resx | 12 ++++++------ vsix/Resources/it-IT/VSPackage.it-IT.resx | 10 +++++----- vsix/Resources/ja-JP/VSPackage.ja-JP.resx | 18 +++++++++--------- vsix/Resources/ko-KR/VSPackage.ko-KR.resx | 14 +++++++------- vsix/Resources/pt-BR/VSPackage.pt-BR.resx | 6 +++--- vsix/Resources/ru-RU/VSPackage.ru-RU.resx | 18 +++++++++--------- vsix/Resources/tr-TR/VSPackage.tr-TR.resx | 2 +- vsix/Resources/zh-CN/VSPackage.zh-CN.resx | 10 +++++----- 9 files changed, 56 insertions(+), 56 deletions(-) diff --git a/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx index 2459e857c..1a2cb9671 100644 --- a/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx +++ b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx @@ -129,40 +129,40 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Konzolová aplikace systému Windows (C++/WinRT) + Konzolová aplikace pro Windows (C++/WinRT) - Projekt pro vytvoření konzolové aplikace C++/WinRT systému Windows + Projekt pro vytvoření konzolové aplikace pro Windows v C++/WinRT. Desktopová aplikace pro Windows (C++/WinRT) - Projekt pro vytvoření desktopové aplikace C++/WinRT pro Windows + Projekt pro vytvoření desktopové aplikace pro Windows v C++/WinRT. Prázdná aplikace (C++/WinRT) - Projekt pro jednostránkovou aplikaci C++/WinRT Univerzální platforma Windows (UPW) bez předdefinovaného rozložení + Projekt pro jednostránkovou aplikaci Univerzální platformy Windows (UPW) v C++/WinRT bez předdefinovaného rozložení. - Základní aplikace (C++/WinRT) + Aplikace Core (C++/WinRT) - Projekt pro aplikaci C++/WinRT Univerzální platforma Windows (UPW) přímo implementující CoreApplication + Projekt pro aplikaci Univerzální platformy Windows (UPW) C++/WinRT přímo implementuje CoreApplication. Statická knihovna (C++/WinRT) - Projekt pro statickou knihovnu C++/WinRT, kterou může používat aplikace Univerzální platforma Windows + Projekt pro statickou knihovnu C++/WinRT, který může používat aplikace Univerzální platformy Windows. - prostředí Windows Runtime komponenta (C++/WinRT) + Součást prostředí Windows Runtime (C++/WinRT) - Projekt pro komponentu prostředí Windows Runtime C++/WinRT, kterou může používat aplikace Univerzální platforma Windows + Projekt pro součást prostředí Windows Runtime C++/WinRT, kterou může používat aplikace Univerzální platformy Windows. Prázdná stránka (C++/WinRT) @@ -174,12 +174,12 @@ Prázdný uživatelský ovládací prvek (C++/WinRT) - Prázdný uživatelský ovládací prvek bez předdefinovaného rozložení pro aplikaci C++/WinRT Univerzální platforma Windows (UPW) + Prázdný uživatelský ovládací prvek bez předdefinovaného rozložení pro aplikaci Univerzální platformy Windows (UPW) v C++/WinRT. Zobrazit model (C++/WinRT) - Prázdná definice rozhraní vhodná pro datovou vazbu XAML pro aplikaci C++/WinRT Univerzální platforma Windows (UPW). + Prázdná definice rozhraní vhodná pro datovou vazbu XAML pro aplikaci Univerzální platformy Windows (UPW) C++/WinRT. \ No newline at end of file diff --git a/vsix/Resources/es-ES/VSPackage.es-ES.resx b/vsix/Resources/es-ES/VSPackage.es-ES.resx index 5458c8743..b4ef3890b 100644 --- a/vsix/Resources/es-ES/VSPackage.es-ES.resx +++ b/vsix/Resources/es-ES/VSPackage.es-ES.resx @@ -150,16 +150,16 @@ Aplicación principal (C++/WinRT) - Proyecto para una aplicación de C++/WinRT Plataforma universal de Windows (UWP) que implementa CoreApplication directamente. + Un proyecto para una aplicación C++/WinRT de la Plataforma universal de Windows (UWP) que implementa directamente CoreApplication. Biblioteca estática (C++/WinRT) - Proyecto para una biblioteca estática de C++/WinRT que puede usar una aplicación Plataforma universal de Windows. + Un proyecto para una biblioteca estática C++/WinRT que puede ser utilizada por una aplicación de la Plataforma universal de Windows. - componente Windows Runtime (C++/WinRT) + Componente de Windows Runtime (C++/WinRT) Proyecto para un componente de Windows Runtime de C++/WinRT que puede usar una aplicación Plataforma universal de Windows. @@ -168,18 +168,18 @@ Página en blanco (C++/WinRT) - Una sola página sin diseño predefinido para una aplicación Plataforma universal de Windows Plataforma universal de Windows (UWP) de C++/WinRT. + Una sola página sin un diseño predefinido para aplicaciones C++/WinRT de la Plataforma universal de Windows (UWP). Control de usuario en blanco (C++/WinRT) - Control de usuario en blanco sin diseño predefinido para una aplicación Plataforma universal de Windows Plataforma universal de Windows (UWP) de C++/WinRT. + Un control de usuario en blanco sin un diseño predefinido para aplicaciones C++/WinRT de la Plataforma universal de Windows (UWP). Ver modelo (C++/WinRT) - Definición de interfaz vacía adecuada para el enlace de datos XAML para una aplicación Plataforma universal de Windows Plataforma universal de Windows (UWP) de C++/WinRT. + Definición de interfaz vacía adecuada para el enlace de datos XAML, ara aplicaciones C++/WinRT de la Plataforma universal de Windows (UWP). \ No newline at end of file diff --git a/vsix/Resources/it-IT/VSPackage.it-IT.resx b/vsix/Resources/it-IT/VSPackage.it-IT.resx index 3419eae6f..ad6b26cd6 100644 --- a/vsix/Resources/it-IT/VSPackage.it-IT.resx +++ b/vsix/Resources/it-IT/VSPackage.it-IT.resx @@ -147,19 +147,19 @@ Progetto per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) a pagina singola senza layout predefinito. - App principale (C++/WinRT) + App core (C++/WinRT) - Progetto per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) (UWP) che implementa direttamente CoreApplication. + Progetto per un'app C++/WinRT della piattaforma UWP (Universal Windows Platform) (UWP) che implementa direttamente CoreApplication. Libreria statica (C++/WinRT) - Progetto per una libreria statica C++/WinRT utilizzabile da un'app piattaforma UWP (Universal Windows Platform). + Progetto per una libreria statica C++/WinRT utilizzabile da un'app della piattaforma UWP (Universal Windows Platform). - componente Windows Runtime (C++/WinRT) + Componente Windows Runtime (C++/WinRT) Progetto per un componente di Windows Runtime C++/WinRT che può essere usato da un'app piattaforma UWP (Universal Windows Platform). @@ -180,6 +180,6 @@ Visualizza modello (C++/WinRT) - Definizione di interfaccia vuota adatta per data binding XAML per un'app C++/WinRT piattaforma UWP (Universal Windows Platform) (UWP). + Definizione di interfaccia vuota adatta al data binding XAML, a un'app C++/WinRT della piattaforma UWP (Universal Windows Platform). \ No newline at end of file diff --git a/vsix/Resources/ja-JP/VSPackage.ja-JP.resx b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx index 197469cd3..6e694b9da 100644 --- a/vsix/Resources/ja-JP/VSPackage.ja-JP.resx +++ b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx @@ -132,52 +132,52 @@ Windows コンソール アプリケーション (C++/WinRT) - C++/WinRT Windows コンソール アプリケーションを作成するためのプロジェクトです。 + C++/WinRT Windows コンソール アプリケーションを作成するためのプロジェクト。 Windows デスクトップ アプリケーション (C++/WinRT) - C++/WinRT Windows デスクトップ アプリケーションを作成するためのプロジェクトです。 + C++/WinRT Windows デスクトップ アプリケーションを作成するためのプロジェクト。 空のアプリ (C++/WinRT) - 定義済みのレイアウトのない単一ページの C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用のプロジェクトです。 + 定義済みレイアウトのない単一ページの C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用のプロジェクト。 コア アプリ (C++/WinRT) - CoreApplication を直接実装する C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用のプロジェクトです。 + CoreApplication を直接実装する C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用のプロジェクト。 スタティック ライブラリ (C++/WinRT) - ユニバーサル Windows プラットフォーム アプリで使用できる C++/WinRT スタティック ライブラリ用のプロジェクトです。 + ユニバーサル Windows プラットフォーム アプリで使用できる C++/WinRT スタティック ライブラリのプロジェクト。 Windows ランタイム コンポーネント (C++/WinRT) - ユニバーサル Windows プラットフォーム アプリで使用できる C++/WinRT Windows ランタイム コンポーネント用のプロジェクトです。 + ユニバーサル Windows プラットフォーム アプリで使用できる C++/WinRT Windows ランタイム コンポーネントのプロジェクト。 空白のページ (C++/WinRT) - C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の定義済みレイアウトのない単一ページ。 + C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の、定義済みレイアウトのない単一のページ。 空のユーザー コントロール (C++/WinRT) - C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の、定義済みのレイアウトのない空のユーザー コントロールです。 + C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の、定義済みレイアウトのない空のユーザー コントロール。 - モデルの表示 (C++/WinRT) + ビュー モデル (C++/WinRT) C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の XAML データ バインドに適した空のインターフェイス定義。 diff --git a/vsix/Resources/ko-KR/VSPackage.ko-KR.resx b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx index eb2ef40fb..0b3fae132 100644 --- a/vsix/Resources/ko-KR/VSPackage.ko-KR.resx +++ b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx @@ -129,13 +129,13 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Windows 콘솔 응용 프로그램(C++/WinRT) + Windows 콘솔 애플리케이션(C++/WinRT) C++/WinRT Windows 콘솔 응용 프로그램을 만드는 프로젝트입니다. - Windows 데스크톱 응용 프로그램(C++/WinRT) + Windows 데스크톱 애플리케이션(C++/WinRT) C++/WinRT Windows 데스크톱 응용 프로그램을 만드는 프로젝트입니다. @@ -144,10 +144,10 @@ 빈 앱(C++/WinRT) - 미리 정의된 레이아웃이 없는 단일 페이지 C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱용 프로젝트입니다. + 미리 정의된 레이아웃이 없는 단일 페이지 C++/WinRT UWP(유니버설 Windows 플랫폼) 앱에 대한 프로젝트입니다. - 핵심 앱(C++/WinRT) + 코어 앱(C++/WinRT) CoreApplication을 직접 구현하는 C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱용 프로젝트입니다. @@ -156,7 +156,7 @@ 정적 라이브러리(C++/WinRT) - 유니버설 Windows 플랫폼 앱에서 사용할 수 있는 C++/WinRT 정적 라이브러리용 프로젝트입니다. + 유니버설 Windows 플랫폼 앱에서 사용할 수 있는 C++/WinRT 정적 라이브러리에 대한 프로젝트입니다. Windows 런타임 구성 요소(C++/WinRT) @@ -171,10 +171,10 @@ C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 미리 정의된 레이아웃이 없는 단일 페이지입니다. - 빈 사용자 정의 컨트롤(C++/WinRT) + 빈 사용자 컨트롤(C++/WinRT) - C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 미리 정의된 레이아웃이 없는 빈 사용자 정의 컨트롤입니다. + C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 미리 정의된 레이아웃이 없는 빈 사용자 컨트롤입니다. 모델 보기(C++/WinRT) diff --git a/vsix/Resources/pt-BR/VSPackage.pt-BR.resx b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx index 304b5f317..44133a9f1 100644 --- a/vsix/Resources/pt-BR/VSPackage.pt-BR.resx +++ b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx @@ -135,7 +135,7 @@ Um projeto para criar um aplicativo de console do Windows C++/WinRT. - Aplicativo do Windows Desktop (C++/WinRT) + Aplicativo da Área de Trabalho do Windows (C++/WinRT) Um projeto para criar um aplicativo de área de trabalho do Windows C++/WinRT. @@ -159,7 +159,7 @@ Um projeto para uma Biblioteca Estática C++/WinRT que pode ser usada por um Plataforma Universal do Windows aplicativo. - Windows Runtime Componente (C++/WinRT) + Componente do Windows Runtime (C++/WinRT) Um projeto para um componente de Windows Runtime C++/WinRT que pode ser usado por um Plataforma Universal do Windows aplicativo. @@ -177,7 +177,7 @@ Um controle de usuário em branco sem layout predefinido para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP). - Exibir Modelo (C++/WinRT) + Modelo de Exibição (C++/WinRT) Uma definição de interface vazia adequada para associação de dados XAML, para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP). diff --git a/vsix/Resources/ru-RU/VSPackage.ru-RU.resx b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx index d7df363df..f509b34de 100644 --- a/vsix/Resources/ru-RU/VSPackage.ru-RU.resx +++ b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx @@ -135,7 +135,7 @@ Проект по созданию консольного приложения C++/WinRT для Windows. - Классические приложения Windows (C++/WinRT) + Классическое приложение Windows (C++/WinRT) Проект по созданию настольного приложения Для Windows C++/WinRT. @@ -144,42 +144,42 @@ Пустое приложение (C++/WinRT) - Проект для одной страницы приложения C++/WinRT универсальная платформа Windows (UWP) без предопределенного макета. + Проект для одной страницы приложения универсальной платформы Windows C++/WinRT (UWP) без предопределенного макета. Основное приложение (C++/WinRT) - Проект для приложения C++/WinRT универсальная платформа Windows (UWP), напрямую реализующий CoreApplication. + Проект для приложения универсальной платформы Windows C++/WinRT (UWP), напрямую реализующий CoreApplication. Статическая библиотека (C++/WinRT) - Проект для статической библиотеки C++/WinRT, которую может использовать универсальная платформа Windows приложения. + Проект для статической библиотеки C++/WinRT, который может использоваться приложением универсальной платформы Windows. - среда выполнения Windows (C++/WinRT) + Компонент среды выполнения Windows (C++/WinRT) - Проект для компонента C++/WinRT среда выполнения Windows, который может использоваться приложением универсальная платформа Windows. + Проект для компонента среды выполнения Windows C++/WinRT, который может использоваться приложением универсальной платформы Windows. Пустая страница (C++/WinRT) - Одна страница без предопределенного макета для приложения C++/WinRT универсальная платформа Windows (UWP). + Одна страница без предопределенного макета для приложения универсальной платформы Windows C++/WinRT (UWP). Пустой пользовательский элемент управления (C++/WinRT) - Пустой пользовательский элемент управления без предопределенного макета для приложения C++/WinRT универсальная платформа Windows (UWP). + Пустой пользовательский элемент управления без предопределенного макета для приложения универсальной платформы Windows C++/WinRT (UWP). Просмотреть модель (C++/WinRT) - Пустое определение интерфейса, подходящее для привязки данных XAML для приложения C++/WinRT универсальная платформа Windows (UWP). + Пустое определение интерфейса, подходящее для привязки данных XAML, для приложения универсальной платформы Windows C++/WinRT (UWP). \ No newline at end of file diff --git a/vsix/Resources/tr-TR/VSPackage.tr-TR.resx b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx index e25f0be57..695905b60 100644 --- a/vsix/Resources/tr-TR/VSPackage.tr-TR.resx +++ b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx @@ -156,7 +156,7 @@ Statik Kitaplık (C++/WinRT) - Bir C++/WinRT Statik Kitaplığı için, bir uygulama tarafından kullanılabilecek Evrensel Windows Platformu proje. + Evrensel Windows Platformu uygulaması tarafından kullanılabilen bir C++/WinRT Statik Kitaplığı projesi. Windows Çalışma Zamanı Bileşeni (C++/WinRT) diff --git a/vsix/Resources/zh-CN/VSPackage.zh-CN.resx b/vsix/Resources/zh-CN/VSPackage.zh-CN.resx index de6b6c29d..97caef8be 100644 --- a/vsix/Resources/zh-CN/VSPackage.zh-CN.resx +++ b/vsix/Resources/zh-CN/VSPackage.zh-CN.resx @@ -144,19 +144,19 @@ 空白应用(C++/WinRT) - 用于单页 C++/WinRT 通用 Windows 平台 (UWP)应用的项目,无预定义布局。 + 用于没有预定义布局的单页面 C++/WinRT 通用 Windows 平台(UWP)应用的项目。 核心应用(C++/WinRT) - 直接实现 CoreApplication 的 C++/WinRT 通用 Windows 平台 (UWP)应用的项目。 + 用于直接实现 CoreApplication 的 C++/WinRT 通用 Windows 平台(UWP)应用的项目。 静态库(C++/WinRT) - 可用于通用 Windows 平台应用的 C++/WinRT 静态库的项目。 + 用于可由通用 Windows 平台应用使用的 C++/WinRT 静态库的项目。 Windows 运行时组件(C++/WinRT) @@ -165,7 +165,7 @@ 可用于通用 Windows 平台应用的 C++/WinRT Windows 运行时组件的项目。 - 空白页(C++/WinRT) + 空白页面(C++/WinRT) 对于 C++/WinRT 通用 Windows 平台 (UWP)应用,单个页面没有预定义的布局。 @@ -180,6 +180,6 @@ 查看模型(C++/WinRT) - 一个空接口定义,适用于 XAML 数据绑定,适用于 C++/WinRT 通用 Windows 平台 (UWP)应用。 + 适用于 C++/WinRT 通用 Windows 平台(UWP)应用的 XAML 数据绑定的空接口定义。 \ No newline at end of file From 51ec25ce5c657048fa552f3054d7427137c9d9ea Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Thu, 23 Dec 2021 17:33:32 -0500 Subject: [PATCH 078/305] Make winrt::event clearable (#1074) --- strings/base_events.h | 22 ++++++++++++++++++++-- test/test/event_clear.cpp | 35 +++++++++++++++++++++++++++++++++++ test/test/test.vcxproj | 1 + 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 test/test/event_clear.cpp diff --git a/strings/base_events.h b/strings/base_events.h index 8b4edb060..b5783555b 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -375,8 +375,8 @@ WINRT_EXPORT namespace winrt using delegate_type = Delegate; event() = default; - event(event const&) = delete; - event& operator =(event const&) = delete; + event(event const&) = delete; + event& operator =(event const&) = delete; explicit operator bool() const noexcept { @@ -466,6 +466,24 @@ WINRT_EXPORT namespace winrt } } + void clear() + { + // Extends life of old targets array to release delegates outside of lock. + delegate_array temp_targets; + + { + slim_lock_guard const change_guard(m_change); + + if (!m_targets) + { + return; + } + + slim_lock_guard const swap_guard(m_swap); + temp_targets = std::exchange(m_targets, nullptr); + } + } + template void operator()(Arg const&... args) { diff --git a/test/test/event_clear.cpp b/test/test/event_clear.cpp new file mode 100644 index 000000000..54db2cef7 --- /dev/null +++ b/test/test/event_clear.cpp @@ -0,0 +1,35 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; + +// +// Checks that clear removes all event handlers +// + +TEST_CASE("event_clear") +{ + event> event; + int counter{}; + + auto a = event.add([&](auto && ...) + { + counter += 1; + }); + + auto b = event.add([&](auto && ...) + { + counter += 10; + }); + + REQUIRE(counter == 0); + event(0, 0); + REQUIRE(counter == 11); + + // Clear event + event.clear(); + + counter = 0; + event(0, 0); + REQUIRE(counter == 0); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 00d8e4d1a..4c7c58517 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -336,6 +336,7 @@ + From 1ab11a3522fe3a6fcccc7e1f5b7187a9692c0033 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 10 Jan 2022 09:02:46 -0800 Subject: [PATCH 079/305] More reliable verbose path output (#1091) --- cppwinrt/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index eab187d6a..4ce543925 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -268,7 +268,9 @@ Where is one or more of: if (settings.verbose) { - w.write(" tool: %\n", canonical(path(argv[0]).replace_extension("exe")).string()); + char* path = nullptr; + _get_pgmptr(&path); + w.write(" tool: %\n", path); w.write(" ver: %\n", CPPWINRT_VERSION_STRING); for (auto&& file : settings.input) From 5792511e01615ad934cd1a2fcb7cd6e2ab15a83f Mon Sep 17 00:00:00 2001 From: David Matson Date: Wed, 12 Jan 2022 12:23:14 -0800 Subject: [PATCH 080/305] Document syntax to disable PCH (#1092) --- cppwinrt/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 4ce543925..6f10f8e79 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -25,7 +25,7 @@ namespace cppwinrt { "verbose", 0, 0, {}, "Show detailed progress information" }, { "overwrite", 0, 0, {}, "Overwrite generated component files" }, { "prefix", 0, 0, {}, "Use dotted namespace convention for component files (defaults to folders)" }, - { "pch", 0, 1, "", "Specify name of precompiled header file (defaults to pch.h)" }, + { "pch", 0, 1, "", "Specify name of precompiled header file (defaults to pch.h; use '.' to disable)" }, { "include", 0, option::no_max, "", "One or more prefixes to include in input" }, { "exclude", 0, option::no_max, "", "One or more prefixes to exclude from input" }, { "base", 0, 0, {}, "Generate base.h unconditionally" }, From 4b1e4deb4492f3a2e60ff5ad01b4f5db2762b7b6 Mon Sep 17 00:00:00 2001 From: David Matson Date: Wed, 12 Jan 2022 15:01:49 -0800 Subject: [PATCH 081/305] Set -pch correctly from targets when not using PCH (#1093) --- nuget/Microsoft.Windows.CppWinRT.targets | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index e0e2fe91a..7f27cd3c4 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -804,7 +804,8 @@ $(XamlMetaDataProviderPch) Text="Please retarget to 10.0.17709.0 or later, or rename your PCH to 'pch.h'."/> true - $(_PCH) + $(_PCH) + . -prefix From 880acd533a436780fb7adf141264c6ce73e0e89a Mon Sep 17 00:00:00 2001 From: TDBuild Date: Thu, 13 Jan 2022 06:01:54 +0000 Subject: [PATCH 082/305] TDBuild - updating localized resource files. --- vsix/Resources/de-DE/VSPackage.de-DE.resx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vsix/Resources/de-DE/VSPackage.de-DE.resx b/vsix/Resources/de-DE/VSPackage.de-DE.resx index ddb6dc1af..19453106c 100644 --- a/vsix/Resources/de-DE/VSPackage.de-DE.resx +++ b/vsix/Resources/de-DE/VSPackage.de-DE.resx @@ -144,42 +144,42 @@ Leere App (C++/WinRT) - Ein Projekt für eine einseitige C++/WinRT-Universelle Windows-Plattform-App (UWP) ohne vordefiniertes Layout. + Ein Projekt für eine einseitige C++/WinRT-UWP-App (Universelle Windows-Plattform) ohne vordefiniertes Layout. Core-App (C++/WinRT) - Ein Projekt für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP), die CoreApplication direkt implementiert. + Ein Projekt für eine C++-/WinRT-UWP-App (Universelle Windows-Plattform), die CoreApplication direkt implementiert. Statische Bibliothek (C++/WinRT) - Ein Projekt für eine statische C++/WinRT-Bibliothek, die von einer Universellen Windows-Plattform-App verwendet werden kann. + Ein Projekt für eine statische C++/WinRT-Bibliothek, die von einer UWP-App (Universelle Windows-Plattform) verwendet werden kann. Komponente für Windows-Runtime (C++/WinRT) - Ein Projekt für eine C++/WinRT-Komponente für Windows-Runtime, die von einer Universellen Windows-Plattform-App verwendet werden kann. + Ein Projekt für eine C++/WinRT-Komponente für Windows-Runtime, die von einer UWP-App (Universelle Windows-Plattform) verwendet werden kann. Leere Seite (C++/WinRT) - Eine einzelne Seite ohne vordefiniertes Layout für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP). + Eine einzelne Seite ohne vordefiniertes Layout für eine C++-/WinRT-UWP-App (Universelle Windows-Plattform). Leeres Benutzersteuerelement (C++/WinRT) - Ein leeres Benutzersteuerelement ohne vordefiniertes Layout für eine C++-/WinRT-Universelle Windows-Plattform-App (UWP). + Ein leeres Benutzersteuerelement ohne vordefiniertes Layout für eine C++-/WinRT-UWP-App (Universelle Windows-Plattform). Modell anzeigen (C++/WinRT) - Eine leere Schnittstellendefinition, die für die XAML-Datenbindung für eine C++/WinRT-Universelle Windows-Plattform-App (UWP) geeignet ist. + Eine leere Schnittstellendefinition, die für die XAML-Datenbindung für eine C++/WinRT-UWP-App (Universelle Windows-Plattform) geeignet ist. \ No newline at end of file From 66f6c6d296cfe37ace06b5efe2d18993b67ea785 Mon Sep 17 00:00:00 2001 From: TDBuild Date: Sat, 15 Jan 2022 06:03:16 +0000 Subject: [PATCH 083/305] TDBuild - updating localized resource files. --- vsix/Resources/it-IT/VSPackage.it-IT.resx | 4 ++-- vsix/Resources/ja-JP/VSPackage.ja-JP.resx | 2 +- vsix/Resources/ko-KR/VSPackage.ko-KR.resx | 8 ++++---- vsix/Resources/pl-PL/VSPackage.pl-PL.resx | 2 +- vsix/Resources/pt-BR/VSPackage.pt-BR.resx | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vsix/Resources/it-IT/VSPackage.it-IT.resx b/vsix/Resources/it-IT/VSPackage.it-IT.resx index ad6b26cd6..1bd57135f 100644 --- a/vsix/Resources/it-IT/VSPackage.it-IT.resx +++ b/vsix/Resources/it-IT/VSPackage.it-IT.resx @@ -132,13 +132,13 @@ Applicazione console Windows (C++/WinRT) - Progetto per la creazione di un'applicazione console windows C++/WinRT. + Progetto per la creazione di un'applicazione console Windows C++/WinRT. Applicazione desktop di Windows (C++/WinRT) - Progetto per la creazione di un'applicazione desktop windows C++/WinRT. + Progetto per la creazione di un'applicazione desktop Windows C++/WinRT. App vuota (C++/WinRT) diff --git a/vsix/Resources/ja-JP/VSPackage.ja-JP.resx b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx index 6e694b9da..5c380bfeb 100644 --- a/vsix/Resources/ja-JP/VSPackage.ja-JP.resx +++ b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx @@ -180,6 +180,6 @@ ビュー モデル (C++/WinRT) - C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の XAML データ バインドに適した空のインターフェイス定義。 + C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の XAML データ バインディングに適した空のインターフェイス定義。 \ No newline at end of file diff --git a/vsix/Resources/ko-KR/VSPackage.ko-KR.resx b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx index 0b3fae132..9fcbda4bb 100644 --- a/vsix/Resources/ko-KR/VSPackage.ko-KR.resx +++ b/vsix/Resources/ko-KR/VSPackage.ko-KR.resx @@ -129,13 +129,13 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Windows 콘솔 애플리케이션(C++/WinRT) + Windows 콘솔 응용 프로그램(C++/WinRT) C++/WinRT Windows 콘솔 응용 프로그램을 만드는 프로젝트입니다. - Windows 데스크톱 애플리케이션(C++/WinRT) + Windows 데스크톱 응용 프로그램(C++/WinRT) C++/WinRT Windows 데스크톱 응용 프로그램을 만드는 프로젝트입니다. @@ -171,7 +171,7 @@ C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 미리 정의된 레이아웃이 없는 단일 페이지입니다. - 빈 사용자 컨트롤(C++/WinRT) + 빈 사용자 정의 컨트롤(C++/WinRT) C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 미리 정의된 레이아웃이 없는 빈 사용자 컨트롤입니다. @@ -180,6 +180,6 @@ 모델 보기(C++/WinRT) - C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 적합한 XAML 데이터 바인딩에 적합한 빈 인터페이스 정의입니다. + C++/WinRT 유니버설 Windows 플랫폼(UWP) 앱에 대해 XAML 데이터 바인딩에 적합한 빈 인터페이스 정의입니다. \ No newline at end of file diff --git a/vsix/Resources/pl-PL/VSPackage.pl-PL.resx b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx index 06cae62fe..4bc31e919 100644 --- a/vsix/Resources/pl-PL/VSPackage.pl-PL.resx +++ b/vsix/Resources/pl-PL/VSPackage.pl-PL.resx @@ -180,6 +180,6 @@ Wyświetl model (C++/WinRT) - Pusta definicja interfejsu odpowiednia dla powiązania danych XAML dla aplikacji platforma uniwersalna systemu Windows C++/WinRT (UWP). + Pusta definicja interfejsu odpowiednia dla powiązania danych XAML dla aplikacji platformy uniwersalnej systemu Windows C++/WinRT (UWP). \ No newline at end of file diff --git a/vsix/Resources/pt-BR/VSPackage.pt-BR.resx b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx index 44133a9f1..c262e7265 100644 --- a/vsix/Resources/pt-BR/VSPackage.pt-BR.resx +++ b/vsix/Resources/pt-BR/VSPackage.pt-BR.resx @@ -180,6 +180,6 @@ Modelo de Exibição (C++/WinRT) - Uma definição de interface vazia adequada para associação de dados XAML, para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP). + Uma definição de interface vazia adequada para vinculação de dados XAML, para um aplicativo C++/WinRT Plataforma Universal do Windows (UWP). \ No newline at end of file From 310b8c7997f7dc0270a0b68e213f14b9fc59cb9e Mon Sep 17 00:00:00 2001 From: TDBuild Date: Sun, 16 Jan 2022 06:01:55 +0000 Subject: [PATCH 084/305] TDBuild - updating localized resource files. --- vsix/Resources/ja-JP/VSPackage.ja-JP.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsix/Resources/ja-JP/VSPackage.ja-JP.resx b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx index 5c380bfeb..6e694b9da 100644 --- a/vsix/Resources/ja-JP/VSPackage.ja-JP.resx +++ b/vsix/Resources/ja-JP/VSPackage.ja-JP.resx @@ -180,6 +180,6 @@ ビュー モデル (C++/WinRT) - C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の XAML データ バインディングに適した空のインターフェイス定義。 + C++/WinRT ユニバーサル Windows プラットフォーム (UWP) アプリ用の XAML データ バインドに適した空のインターフェイス定義。 \ No newline at end of file From d46a805fdea4039bd157be9868f37ac621013745 Mon Sep 17 00:00:00 2001 From: TDBuild Date: Mon, 17 Jan 2022 06:01:36 +0000 Subject: [PATCH 085/305] TDBuild - updating localized resource files. --- vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx index 1a2cb9671..68da51c3d 100644 --- a/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx +++ b/vsix/Resources/cs-CZ/VSPackage.cs-CZ.resx @@ -168,7 +168,7 @@ Prázdná stránka (C++/WinRT) - Jedna stránka bez předdefinovaného rozložení pro aplikaci C++/WinRT Univerzální platforma Windows (UPW) + Jedna stránka bez předdefinovaného rozložení pro aplikaci C++/WinRT Univerzální platforma Windows (UPW). Prázdný uživatelský ovládací prvek (C++/WinRT) From 3393e79d5c405ffee25d468f61f921c6216d21fe Mon Sep 17 00:00:00 2001 From: TDBuild Date: Tue, 18 Jan 2022 06:02:05 +0000 Subject: [PATCH 086/305] TDBuild - updating localized resource files. --- vsix/Resources/ru-RU/VSPackage.ru-RU.resx | 2 +- vsix/Resources/tr-TR/VSPackage.tr-TR.resx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/vsix/Resources/ru-RU/VSPackage.ru-RU.resx b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx index f509b34de..3688b6eff 100644 --- a/vsix/Resources/ru-RU/VSPackage.ru-RU.resx +++ b/vsix/Resources/ru-RU/VSPackage.ru-RU.resx @@ -138,7 +138,7 @@ Классическое приложение Windows (C++/WinRT) - Проект по созданию настольного приложения Для Windows C++/WinRT. + Проект по созданию настольного приложения для Windows C++/WinRT. Пустое приложение (C++/WinRT) diff --git a/vsix/Resources/tr-TR/VSPackage.tr-TR.resx b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx index 695905b60..69a5489ad 100644 --- a/vsix/Resources/tr-TR/VSPackage.tr-TR.resx +++ b/vsix/Resources/tr-TR/VSPackage.tr-TR.resx @@ -162,7 +162,7 @@ Windows Çalışma Zamanı Bileşeni (C++/WinRT) - Bir C++/WinRT Windows Çalışma Zamanı uygulama tarafından kullanılabilecek bir Evrensel Windows Platformu. + Bir Evrensel Windows Platformu uygulaması tarafından kullanılabilen bir C++/WinRT Windows Çalışma Zamanı bileşeni projesi. Boş Sayfa (C++/WinRT) @@ -171,10 +171,10 @@ C++/WinRT (UWP) uygulaması için önceden tanımlanmış düzeni olmayan Evrensel Windows Platformu sayfa. - Boş Kullanıcı Denetimi (C++/WinRT) + Boş Kullanıcı Kontrolü (C++/WinRT) - C++/WinRT (UWP) uygulaması için önceden tanımlanmış düzeni olmayan Evrensel Windows Platformu kullanıcı denetimi. + C++/WinRT (UWP) uygulaması için önceden tanımlanmış düzeni olmayan Evrensel Windows Platformu kullanıcı kontrolü. Modeli Görüntüle (C++/WinRT) From 1ccfe2ee565baebbc34d8934eb46edb1501eb9c7 Mon Sep 17 00:00:00 2001 From: John Tasler Date: Sat, 22 Jan 2022 12:17:09 -0800 Subject: [PATCH 087/305] Add visualizer for `Windows::UI::Color` (#1095) --- natvis/cppwinrt.natvis | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/natvis/cppwinrt.natvis b/natvis/cppwinrt.natvis index de9cff59c..168b5542e 100644 --- a/natvis/cppwinrt.natvis +++ b/natvis/cppwinrt.natvis @@ -20,12 +20,15 @@ null + + #{A,nvoXb}{R,nvoXb}{G,nvoXb}{B,nvoXb} + {{size = {m_size}, {m_data,[m_size]}}} - m_size - m_data + m_size + m_data From 24650deabbddf72f18c3f74b4884672c9ddecf60 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 31 Jan 2022 08:11:17 -0800 Subject: [PATCH 088/305] Fix weak references to coroutines (#1097) --- strings/base_implements.h | 21 ++++++--- test/old_tests/UnitTests/weak.cpp | 77 +++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index b2300edc5..df51f052f 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -831,7 +831,7 @@ namespace winrt::impl virtual ~root_implements() noexcept { // If a weak reference is created during destruction, this ensures that it is also destroyed. - subtract_reference(); + subtract_final_reference(); } int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept @@ -897,10 +897,6 @@ namespace winrt::impl if (target == 0) { - // If a weak reference was previously created, the m_references value will not be stable value (won't be zero). - // This ensures destruction has a stable value during destruction. - m_references = 1; - if constexpr (has_final_release::value) { D::final_release(std::unique_ptr(static_cast(this))); @@ -992,7 +988,7 @@ namespace winrt::impl } catch (...) { return to_hresult(); } - uint32_t subtract_reference() noexcept + uint32_t subtract_final_reference() noexcept { if constexpr (is_weak_ref_source::value) { @@ -1019,6 +1015,19 @@ namespace winrt::impl } } + uint32_t subtract_reference() noexcept + { + uint32_t result = subtract_final_reference(); + + if (result == 0) + { + // Ensure destruction happens with a stable reference count that isn't a weak reference. + m_references.store(1, std::memory_order_relaxed); + } + + return result; + } + template winrt::weak_ref get_weak() { diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index b253e6010..ba0fb5d86 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -68,6 +68,49 @@ namespace REQUIRE(weak_self.get() == nullptr); } }; + + struct WeakCreateWeakInDestructor : implements + { + winrt::weak_ref& weak_self; + + WeakCreateWeakInDestructor(winrt::weak_ref& magic) : weak_self(magic) {} + + ~WeakCreateWeakInDestructor() + { + // Creates a weak reference to itself in the destructor. + weak_self = get_weak(); + } + + hstring ToString() + { + return L"WeakCreateWeakInDestructor"; + } + }; + +#ifdef WINRT_IMPL_COROUTINES + // Returns an IAsyncAction that has already completed. + winrt::Windows::Foundation::IAsyncAction Action() + { + co_return; + } + + // Returns an IAsyncAction that has not completed. + // Call the resume() handle to complete it. + winrt::Windows::Foundation::IAsyncAction SuspendAction(impl::coroutine_handle<>& resume) + { + struct awaiter + { + impl::coroutine_handle<>& resume; + bool await_ready() { return false; } + void await_suspend(impl::coroutine_handle<> handle) { resume = handle; } + void await_resume() {} + }; + + co_await awaiter{ resume }; + co_return; + } + +#endif } TEST_CASE("weak,source") @@ -413,3 +456,37 @@ TEST_CASE("weak,self") a.ToString(); a = nullptr; } + +TEST_CASE("weak,create_weak_in_destructor") +{ + weak_ref magic; + IStringable a = make(magic); + a.ToString(); + a = nullptr; + REQUIRE(magic.get() == nullptr); +} + +#ifdef WINRT_IMPL_COROUTINES +TEST_CASE("weak,coroutine") +{ + // Run a coroutine to completion. Confirm that weak references fail to resolve. + auto weak = winrt::weak_ref(Action()); + REQUIRE(weak.get() == nullptr); + + // Start a coroutine but don't complete it yet. + // Confirm that weak references resolve. + impl::coroutine_handle<> resume; + weak = winrt::weak_ref(SuspendAction(resume)); + REQUIRE(weak.get() != nullptr); + // Now complete the coroutine. Confirm that weak references no longer resolve. + resume(); + REQUIRE(weak.get() == nullptr); + + // Verify that weak reference resolves as long as strong reference exists. + auto action = Action(); + weak = winrt::weak_ref(action); + REQUIRE(weak.get() == action); + action = nullptr; + REQUIRE(weak.get() == nullptr); +} +#endif From 59e04e5a9f153291c93c38004179dc2f47e84178 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 7 Feb 2022 11:17:34 -0800 Subject: [PATCH 089/305] yml --- .github/workflows/azure.yml | 554 ++++++++++++++++++++++++++++++++++++ 1 file changed, 554 insertions(+) create mode 100644 .github/workflows/azure.yml diff --git a/.github/workflows/azure.yml b/.github/workflows/azure.yml new file mode 100644 index 000000000..6e748c753 --- /dev/null +++ b/.github/workflows/azure.yml @@ -0,0 +1,554 @@ +# 'Allow scripts to access the OAuth token' was selected in pipeline. Add the following YAML to any steps requiring access: +# env: +# MY_ACCESS_TOKEN: $(System.AccessToken) +# Variable 'MajorVersion' was defined in the Variables tab +# Variable 'MinorVersion' was defined in the Variables tab +# Cron Schedules have been converted using UTC Time Zone and may need to be updated for your location +# Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration +# Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration +# Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration +trigger: + branches: + include: + - refs/heads/master + batch: True +schedules: +- cron: 0 2 * * * + branches: + include: + - refs/heads/master +name: $(MajorVersion).$(MinorVersion).$(date:yyMMdd)$(rev:.r) +resources: + repositories: + - repository: self + type: git + ref: master +jobs: +- job: Job_1 + displayName: Build Binaries + pool: + name: Hosted Windows 2019 with VS2019 + steps: + - checkout: self + clean: true + persistCredentials: True + - task: NuGetToolInstaller@1 + displayName: Use NuGet 5.3 + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + continueOnError: True + inputs: + versionSpec: 5.3 + - task: NuGetCommand@2 + displayName: NuGet restore + - task: CmdLine@2 + displayName: Build Tools + inputs: + script: >- + if "%VSCMD_VER%"=="" ( + pushd c: + call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" >nul 2>&1 + popd + ) + + + build_test_all.cmd $(BuildPlatform) $(BuildConfiguration) $(Build.BuildNumber) + failOnStderr: true + - task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + condition: eq(variables['BuildPlatform'], 'x64') + - task: PublishTestResults@2 + displayName: Publish Test Results + - task: CopyFiles@2 + displayName: Stage cppwinrt.* + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) + Contents: >- + cppwinrt.exe + + cppwinrt.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\cppwinrt + - task: CopyFiles@2 + displayName: Stage Component cppwinrtvisualizer.* + condition: and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64')), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: '$(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Component ' + Contents: > + cppwinrtvisualizer.dll + + cppwinrtvisualizer.pdb + + cppwinrtvisualizer.vsdconfig + TargetFolder: $(Build.ArtifactStagingDirectory)\Component + - task: CopyFiles@2 + displayName: Stage Standalone cppwinrtvisualizer.* + condition: and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64')), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Standalone + Contents: > + cppwinrtvisualizer.dll + + cppwinrtvisualizer.pdb + + cppwinrtvisualizer.vsdconfig + TargetFolder: $(Build.ArtifactStagingDirectory)\Standalone + - task: CopyFiles@2 + displayName: Stage cppwinrt_fast_forwarder.lib + condition: and(eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) + Contents: cppwinrt_fast_forwarder.lib + TargetFolder: $(Build.ArtifactStagingDirectory) + - task: PublishPipelineArtifact@0 + displayName: Publish Artifacts + condition: and(eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_$(BuildPlatform) + targetPath: $(Build.ArtifactStagingDirectory) + - task: PublishSymbols@2 + displayName: Publish symbols + condition: and(eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SymbolsFolder: $(Build.ArtifactStagingDirectory) + SearchPattern: '**/*.pdb' + IndexSources: false + SymbolServerType: TeamServices + SymbolsProduct: CppWinRT +- job: Job_2 + displayName: Build Internal Packages (VPacks) + dependsOn: Job_1 + pool: + vmImage: windows-2019 + steps: + - checkout: self + clean: true + persistCredentials: True + - task: PkgESSetupBuild@12 + displayName: Package ES - Setup Build + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + branchVersionExcludeBranch: master + disableWorkspace: true + disableMsbuildVersion: true + disableBuildTools: true + - task: DownloadPipelineArtifact@1 + displayName: Download x86 Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_x86 + downloadPath: $(Build.SourcesDirectory)\x86 + - task: DownloadPipelineArtifact@1 + displayName: Download x64 Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_x64 + downloadPath: $(Build.SourcesDirectory)\x64 + - task: DownloadPipelineArtifact@1 + displayName: Download arm Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_arm + downloadPath: $(Build.SourcesDirectory)\arm + - task: DownloadPipelineArtifact@1 + displayName: Download arm64 Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_arm64 + downloadPath: $(Build.SourcesDirectory)\arm64 + - task: CmdLine@2 + displayName: Parse PatchVersion + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: 'for /f "tokens=3,4 delims=." %%i in ("$(Build.BuildNumber)") do @echo ##vso[task.setvariable variable=PatchVersion;]%%i%%j ' + failOnStderr: true + - task: CmdLine@2 + displayName: Copy compiler contents for internal signing + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: > + md $(Build.SourcesDirectory)\x86\tempsign + + + echo Build Sources Directory: + + dir $(Build.SourcesDirectory) + + + echo x86 + + dir $(Build.SourcesDirectory)\x86 + + + echo cppwinrt + + dir $(Build.SourcesDirectory)\x86\cppwinrt + + + xcopy $(Build.SourcesDirectory)\x86\cppwinrt\*.* $(Build.SourcesDirectory)\x86\tempsign /icefzy + - task: EsrpCodeSigning@1 + displayName: Sign Compiler vPack for internal use + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + ConnectedServiceName: bf601a97-455d-4977-b248-07b90c96eed9 + FolderPath: $(Build.SourcesDirectory)\x86\tempsign + signConfigType: inlineSignParams + inlineOperation: >- + [ + { + "KeyCode" : "CP-458204", + "OperationCode" : "SigntoolSign", + "Parameters" : { + "OpusName" : "Windows Build Tools Internal", + "OpusInfo" : "http://www.microsoft.com", + "FileDigest" : "/fd \"SHA256\"", + "PageHash" : "/NPH", + "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-458204", + "OperationCode" : "SigntoolVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + - task: PkgESVPack@12 + displayName: 'Publish Compiler VPack ' + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + serviceType: drop + versionAs: parts + sourceDirectory: $(Build.SourcesDirectory)\x86\tempsign + description: C++/WinRT Compiler + pushPkgName: CppWinRT.Compiler + target: $(OSBuildToolsRoot)\cppwinrt + provData: false + majorVer: $(MajorVersion) + minorVer: $(MinorVersion) + patchVer: $(PatchVersion) + prereleaseVer: $(Build.SourceBranchName).$(BuildPlatform).$(BuildConfiguration).$(Build.BuildNumber).$(Build.SourceVersion) + symBaselineOutput: $(Build.SourcesDirectory)\x86\cppwinrt + symBaselineScanDir: $(Build.SourcesDirectory)\x86\cppwinrt + symBaselinePathNorm: osbuildtoolsroot\CppWinRT.Compiler + - task: CmdLine@2 + displayName: Delete internal compiler copy + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: >+ + rd $(Build.SourcesDirectory)\x86\tempsign /q /s + + - task: CopyFiles@2 + displayName: Stage CppWinRT.Compiler.man + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: $(XES_VPACKMANIFESTDIRECTORY) + Contents: $(XES_VPACKMANIFESTNAME) + TargetFolder: $(Build.ArtifactStagingDirectory) + - task: CmdLine@2 + displayName: Stage MSBuild vpack + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" + failOnStderr: true + - task: PkgESVPack@12 + displayName: Publish MSBuild VPack + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + serviceType: drop + versionAs: parts + sourceDirectory: $(Build.SourcesDirectory)\msbuild + description: C++/WinRT MSBuild + pushPkgName: CppWinRT.MSBuild + target: $(OSBuildToolsRoot)\cppwinrt + provData: false + majorVer: $(MajorVersion) + minorVer: $(MinorVersion) + patchVer: $(PatchVersion) + prereleaseVer: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) + - task: CopyFiles@2 + displayName: Stage CppWinRT.MSBuild.man + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: $(XES_VPACKMANIFESTDIRECTORY) + Contents: $(XES_VPACKMANIFESTNAME) + TargetFolder: $(Build.ArtifactStagingDirectory) + - task: CmdLine@2 + displayName: Stage OSBuildTools.Manifest Update + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + enabled: False + inputs: + script: >- + copy $(Build.SourcesDirectory)\src\package\cppwinrt\vpack\GitCheckin.json + + copy $(Build.SourcesDirectory)\vpack\*.man OSBuildTools.Manifest.Update + + type OSBuildTools.Manifest.Update + workingDirectory: $(Build.ArtifactStagingDirectory) + failOnStderr: true + - task: PublishPipelineArtifact@0 + displayName: Publish Update Manifests + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: VPack + targetPath: $(Build.ArtifactStagingDirectory) +- job: Phase_1 + displayName: Build External Packages (NuGet, VSIX) + cancelTimeoutInMinutes: 1 + dependsOn: Job_1 + pool: + vmImage: windows-2019 + steps: + - checkout: self + clean: true + persistCredentials: True + - task: NuGetToolInstaller@1 + displayName: Use NuGet 5.3 + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + continueOnError: True + inputs: + versionSpec: 5.3 + - task: NuGetCommand@2 + displayName: NuGet restore + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + - task: DownloadPipelineArtifact@1 + displayName: Download x86 Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_x86 + downloadPath: $(Build.SourcesDirectory)\x86 + - task: DownloadPipelineArtifact@1 + displayName: Download x64 Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_x64 + downloadPath: $(Build.SourcesDirectory)\x64 + - task: DownloadPipelineArtifact@1 + displayName: Download arm Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_arm + downloadPath: $(Build.SourcesDirectory)\arm + - task: DownloadPipelineArtifact@1 + displayName: Download arm64 Artifacts + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: $(BuildConfiguration)_arm64 + downloadPath: $(Build.SourcesDirectory)\arm64 + - task: EsrpCodeSigning@1 + displayName: ESRP CodeSigning NatVis + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.SourcesDirectory) + Pattern: >- + x86\cppwinrt\cppwinrt.exe + + x86\Component\cppwinrtvisualizer.dll + + x64\Component\cppwinrtvisualizer.dll + + x86\Standalone\cppwinrtvisualizer.dll + + x64\Standalone\cppwinrtvisualizer.dll + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: >- + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd sha256" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "signtool.exe", + "toolVersion": "6.2.9304.0" + } + ] + - task: CmdLine@2 + displayName: Stage Signed Binaries + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: >- + echo F|xcopy /S /Q /Y /F x86\cppwinrt\cppwinrt.exe $(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe + + echo F|xcopy /S /Q /Y /F x86\Component\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x86\Component\cppwinrtvisualizer.dll + + echo F|xcopy /S /Q /Y /F x64\Component\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x64\Component\cppwinrtvisualizer.dll + + echo F|xcopy /S /Q /Y /F x86\Standalone\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x86\Standalone\cppwinrtvisualizer.dll + + echo F|xcopy /S /Q /Y /F x64\Standalone\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x64\Standalone\cppwinrtvisualizer.dll + workingDirectory: $(Build.SourcesDirectory) + failOnStderr: true + - task: CmdLine@2 + displayName: Stage cppwinrtvisualizer.vsdconfig + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: >- + copy $(Build.SourcesDirectory)\x86\Component\cppwinrtvisualizer.vsdconfig x86\Component\cppwinrtvisualizer.vsdconfig + + copy $(Build.SourcesDirectory)\x86\Standalone\cppwinrtvisualizer.vsdconfig x86\Standalone\cppwinrtvisualizer.vsdconfig + workingDirectory: $(Build.ArtifactStagingDirectory) + failOnStderr: true + - task: NuGetCommand@2 + displayName: Build NuGet + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + command: pack + searchPatternPack: nuget/Microsoft.Windows.CppWinRT.nuspec + versioningScheme: byBuildNumber + buildProperties: 'cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' + - task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + - task: EsrpCodeSigning@1 + displayName: ESRP CodeSigning Nuget Package + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.ArtifactStagingDirectory) + Pattern: Microsoft.Windows.CppWinRT.*.nupkg + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: >- + [ + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetSign", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + - task: PkgESNuGetPublisher@0 + displayName: Publish NuGet Package + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + searchPattern: $(System.ArtifactsDirectory)\Microsoft.Windows.CppWinRT.$(Build.BuildNumber).nupkg + nuGetFeedType: internal + feedName: https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json + - task: VSBuild@1 + displayName: Build Component VSIX + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + solution: vsix/vsix.sln + msbuildArgs: /p:Deployment=Component,CppWinRTVersion=$(Build.BuildNumber),NatvisDirx86=$(Build.ArtifactStagingDirectory)\x86\Component\,NatvisDirx64=$(Build.ArtifactStagingDirectory)\x64\Component\,NupkgDir=$(Build.ArtifactStagingDirectory) /restore + platform: x86 + configuration: Release + - task: VSBuild@1 + displayName: Build Standalone VSIX + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + solution: vsix/vsix.sln + msbuildArgs: /p:Deployment=Standalone,CppWinRTVersion=$(Build.BuildNumber),NatvisDirx86=$(Build.ArtifactStagingDirectory)\x86\Standalone\,NatvisDirx64=$(Build.ArtifactStagingDirectory)\x64\Standalone\,NupkgDir=$(Build.ArtifactStagingDirectory) /restore + platform: x86 + configuration: Release + - task: EsrpCodeSigning@1 + displayName: ESRP CodeSigning VSIX + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.SourcesDirectory)\vsix\ + Pattern: >- + Dev16\bin\Release\Component\Microsoft.Windows.CppWinRT.vsix + + Dev16\bin\Release\Standalone\Microsoft.Windows.CppWinRT.vsix + + Dev17\bin\Release\Component\Microsoft.Windows.CppWinRT.Dev17.vsix + + Dev17\bin\Release\Standalone\Microsoft.Windows.CppWinRT.Dev17.vsix + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: > + [ + { + "KeyCode" : "CP-233016", + "OperationCode" : "OpcSign", + "Parameters" : { + "FileDigest" : "/fd SHA256" + }, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-233016", + "OperationCode" : "OpcVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + - task: CmdLine@2 + displayName: Stage Component VSIX + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: >- + echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.vsix $(Build.ArtifactStagingDirectory)\Component\Dev17\Microsoft.Windows.CppWinRT.Dev17.vsix + + echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.json $(Build.ArtifactStagingDirectory)\Component\Dev17\Microsoft.Windows.CppWinRT.Dev17.json + workingDirectory: $(Build.SourcesDirectory)\vsix\Dev17\bin\Release\Component + failOnStderr: true + - task: CopyFiles@2 + displayName: Stage Component VSIX Manifest + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\vsix + Contents: >- + extension.manifest.json + + overview.md + TargetFolder: $(Build.ArtifactStagingDirectory)\Component\Dev17 + OverWrite: true + - task: CmdLine@2 + displayName: Stage Standalone VSIX + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + script: echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.vsix $(Build.ArtifactStagingDirectory)\Standalone\Dev16\Microsoft.Windows.CppWinRT.vsix + workingDirectory: $(Build.SourcesDirectory)\vsix\Dev16\bin\$(BuildConfiguration)\Standalone + failOnStderr: true + - task: CopyFiles@2 + displayName: Stage Standalone VSIX Manifest + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\vsix + Contents: >- + extension.manifest.json + + overview.md + TargetFolder: $(Build.ArtifactStagingDirectory)\Standalone\Dev16 + OverWrite: true + - task: PublishPipelineArtifact@0 + displayName: Publish VSIX + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) + inputs: + artifactName: Publish + targetPath: $(Build.ArtifactStagingDirectory) +... From 7628e76748f7db6b4f14e1b47029e6c7330dc8fe Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 7 Feb 2022 11:24:01 -0800 Subject: [PATCH 090/305] yml --- .github/workflows/azure.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/azure.yml b/.github/workflows/azure.yml index 6e748c753..4b84dfef8 100644 --- a/.github/workflows/azure.yml +++ b/.github/workflows/azure.yml @@ -1,8 +1,6 @@ # 'Allow scripts to access the OAuth token' was selected in pipeline. Add the following YAML to any steps requiring access: # env: # MY_ACCESS_TOKEN: $(System.AccessToken) -# Variable 'MajorVersion' was defined in the Variables tab -# Variable 'MinorVersion' was defined in the Variables tab # Cron Schedules have been converted using UTC Time Zone and may need to be updated for your location # Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration # Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration @@ -17,7 +15,7 @@ schedules: branches: include: - refs/heads/master -name: $(MajorVersion).$(MinorVersion).$(date:yyMMdd)$(rev:.r) +name: 2.0.$(date:yyMMdd)$(rev:.r) resources: repositories: - repository: self @@ -226,8 +224,8 @@ jobs: pushPkgName: CppWinRT.Compiler target: $(OSBuildToolsRoot)\cppwinrt provData: false - majorVer: $(MajorVersion) - minorVer: $(MinorVersion) + majorVer: 2 + minorVer: 0 patchVer: $(PatchVersion) prereleaseVer: $(Build.SourceBranchName).$(BuildPlatform).$(BuildConfiguration).$(Build.BuildNumber).$(Build.SourceVersion) symBaselineOutput: $(Build.SourcesDirectory)\x86\cppwinrt @@ -264,8 +262,8 @@ jobs: pushPkgName: CppWinRT.MSBuild target: $(OSBuildToolsRoot)\cppwinrt provData: false - majorVer: $(MajorVersion) - minorVer: $(MinorVersion) + majorVer: 2 + minorVer: 0 patchVer: $(PatchVersion) prereleaseVer: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) - task: CopyFiles@2 From 0b2225d812e27581271a7907a01d1f29a8ef649a Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 8 Feb 2022 07:06:55 -0800 Subject: [PATCH 091/305] build --- .github/workflows/azure.yml | 552 ------------------------------------ 1 file changed, 552 deletions(-) delete mode 100644 .github/workflows/azure.yml diff --git a/.github/workflows/azure.yml b/.github/workflows/azure.yml deleted file mode 100644 index 4b84dfef8..000000000 --- a/.github/workflows/azure.yml +++ /dev/null @@ -1,552 +0,0 @@ -# 'Allow scripts to access the OAuth token' was selected in pipeline. Add the following YAML to any steps requiring access: -# env: -# MY_ACCESS_TOKEN: $(System.AccessToken) -# Cron Schedules have been converted using UTC Time Zone and may need to be updated for your location -# Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration -# Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration -# Multi-job configuration must be converted to matrix strategy: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml#multi-job-configuration -trigger: - branches: - include: - - refs/heads/master - batch: True -schedules: -- cron: 0 2 * * * - branches: - include: - - refs/heads/master -name: 2.0.$(date:yyMMdd)$(rev:.r) -resources: - repositories: - - repository: self - type: git - ref: master -jobs: -- job: Job_1 - displayName: Build Binaries - pool: - name: Hosted Windows 2019 with VS2019 - steps: - - checkout: self - clean: true - persistCredentials: True - - task: NuGetToolInstaller@1 - displayName: Use NuGet 5.3 - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - continueOnError: True - inputs: - versionSpec: 5.3 - - task: NuGetCommand@2 - displayName: NuGet restore - - task: CmdLine@2 - displayName: Build Tools - inputs: - script: >- - if "%VSCMD_VER%"=="" ( - pushd c: - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" >nul 2>&1 - popd - ) - - - build_test_all.cmd $(BuildPlatform) $(BuildConfiguration) $(Build.BuildNumber) - failOnStderr: true - - task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection - condition: eq(variables['BuildPlatform'], 'x64') - - task: PublishTestResults@2 - displayName: Publish Test Results - - task: CopyFiles@2 - displayName: Stage cppwinrt.* - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) - Contents: >- - cppwinrt.exe - - cppwinrt.pdb - TargetFolder: $(Build.ArtifactStagingDirectory)\cppwinrt - - task: CopyFiles@2 - displayName: Stage Component cppwinrtvisualizer.* - condition: and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64')), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: '$(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Component ' - Contents: > - cppwinrtvisualizer.dll - - cppwinrtvisualizer.pdb - - cppwinrtvisualizer.vsdconfig - TargetFolder: $(Build.ArtifactStagingDirectory)\Component - - task: CopyFiles@2 - displayName: Stage Standalone cppwinrtvisualizer.* - condition: and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64')), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Standalone - Contents: > - cppwinrtvisualizer.dll - - cppwinrtvisualizer.pdb - - cppwinrtvisualizer.vsdconfig - TargetFolder: $(Build.ArtifactStagingDirectory)\Standalone - - task: CopyFiles@2 - displayName: Stage cppwinrt_fast_forwarder.lib - condition: and(eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) - Contents: cppwinrt_fast_forwarder.lib - TargetFolder: $(Build.ArtifactStagingDirectory) - - task: PublishPipelineArtifact@0 - displayName: Publish Artifacts - condition: and(eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_$(BuildPlatform) - targetPath: $(Build.ArtifactStagingDirectory) - - task: PublishSymbols@2 - displayName: Publish symbols - condition: and(eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SymbolsFolder: $(Build.ArtifactStagingDirectory) - SearchPattern: '**/*.pdb' - IndexSources: false - SymbolServerType: TeamServices - SymbolsProduct: CppWinRT -- job: Job_2 - displayName: Build Internal Packages (VPacks) - dependsOn: Job_1 - pool: - vmImage: windows-2019 - steps: - - checkout: self - clean: true - persistCredentials: True - - task: PkgESSetupBuild@12 - displayName: Package ES - Setup Build - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - branchVersionExcludeBranch: master - disableWorkspace: true - disableMsbuildVersion: true - disableBuildTools: true - - task: DownloadPipelineArtifact@1 - displayName: Download x86 Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_x86 - downloadPath: $(Build.SourcesDirectory)\x86 - - task: DownloadPipelineArtifact@1 - displayName: Download x64 Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_x64 - downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 - displayName: Download arm64 Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_arm64 - downloadPath: $(Build.SourcesDirectory)\arm64 - - task: CmdLine@2 - displayName: Parse PatchVersion - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: 'for /f "tokens=3,4 delims=." %%i in ("$(Build.BuildNumber)") do @echo ##vso[task.setvariable variable=PatchVersion;]%%i%%j ' - failOnStderr: true - - task: CmdLine@2 - displayName: Copy compiler contents for internal signing - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: > - md $(Build.SourcesDirectory)\x86\tempsign - - - echo Build Sources Directory: - - dir $(Build.SourcesDirectory) - - - echo x86 - - dir $(Build.SourcesDirectory)\x86 - - - echo cppwinrt - - dir $(Build.SourcesDirectory)\x86\cppwinrt - - - xcopy $(Build.SourcesDirectory)\x86\cppwinrt\*.* $(Build.SourcesDirectory)\x86\tempsign /icefzy - - task: EsrpCodeSigning@1 - displayName: Sign Compiler vPack for internal use - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - ConnectedServiceName: bf601a97-455d-4977-b248-07b90c96eed9 - FolderPath: $(Build.SourcesDirectory)\x86\tempsign - signConfigType: inlineSignParams - inlineOperation: >- - [ - { - "KeyCode" : "CP-458204", - "OperationCode" : "SigntoolSign", - "Parameters" : { - "OpusName" : "Windows Build Tools Internal", - "OpusInfo" : "http://www.microsoft.com", - "FileDigest" : "/fd \"SHA256\"", - "PageHash" : "/NPH", - "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - }, - "ToolName" : "sign", - "ToolVersion" : "1.0" - }, - { - "KeyCode" : "CP-458204", - "OperationCode" : "SigntoolVerify", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - } - ] - - task: PkgESVPack@12 - displayName: 'Publish Compiler VPack ' - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - serviceType: drop - versionAs: parts - sourceDirectory: $(Build.SourcesDirectory)\x86\tempsign - description: C++/WinRT Compiler - pushPkgName: CppWinRT.Compiler - target: $(OSBuildToolsRoot)\cppwinrt - provData: false - majorVer: 2 - minorVer: 0 - patchVer: $(PatchVersion) - prereleaseVer: $(Build.SourceBranchName).$(BuildPlatform).$(BuildConfiguration).$(Build.BuildNumber).$(Build.SourceVersion) - symBaselineOutput: $(Build.SourcesDirectory)\x86\cppwinrt - symBaselineScanDir: $(Build.SourcesDirectory)\x86\cppwinrt - symBaselinePathNorm: osbuildtoolsroot\CppWinRT.Compiler - - task: CmdLine@2 - displayName: Delete internal compiler copy - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: >+ - rd $(Build.SourcesDirectory)\x86\tempsign /q /s - - - task: CopyFiles@2 - displayName: Stage CppWinRT.Compiler.man - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: $(XES_VPACKMANIFESTDIRECTORY) - Contents: $(XES_VPACKMANIFESTNAME) - TargetFolder: $(Build.ArtifactStagingDirectory) - - task: CmdLine@2 - displayName: Stage MSBuild vpack - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" - failOnStderr: true - - task: PkgESVPack@12 - displayName: Publish MSBuild VPack - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - serviceType: drop - versionAs: parts - sourceDirectory: $(Build.SourcesDirectory)\msbuild - description: C++/WinRT MSBuild - pushPkgName: CppWinRT.MSBuild - target: $(OSBuildToolsRoot)\cppwinrt - provData: false - majorVer: 2 - minorVer: 0 - patchVer: $(PatchVersion) - prereleaseVer: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) - - task: CopyFiles@2 - displayName: Stage CppWinRT.MSBuild.man - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: $(XES_VPACKMANIFESTDIRECTORY) - Contents: $(XES_VPACKMANIFESTNAME) - TargetFolder: $(Build.ArtifactStagingDirectory) - - task: CmdLine@2 - displayName: Stage OSBuildTools.Manifest Update - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - enabled: False - inputs: - script: >- - copy $(Build.SourcesDirectory)\src\package\cppwinrt\vpack\GitCheckin.json - - copy $(Build.SourcesDirectory)\vpack\*.man OSBuildTools.Manifest.Update - - type OSBuildTools.Manifest.Update - workingDirectory: $(Build.ArtifactStagingDirectory) - failOnStderr: true - - task: PublishPipelineArtifact@0 - displayName: Publish Update Manifests - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: VPack - targetPath: $(Build.ArtifactStagingDirectory) -- job: Phase_1 - displayName: Build External Packages (NuGet, VSIX) - cancelTimeoutInMinutes: 1 - dependsOn: Job_1 - pool: - vmImage: windows-2019 - steps: - - checkout: self - clean: true - persistCredentials: True - - task: NuGetToolInstaller@1 - displayName: Use NuGet 5.3 - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - continueOnError: True - inputs: - versionSpec: 5.3 - - task: NuGetCommand@2 - displayName: NuGet restore - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - - task: DownloadPipelineArtifact@1 - displayName: Download x86 Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_x86 - downloadPath: $(Build.SourcesDirectory)\x86 - - task: DownloadPipelineArtifact@1 - displayName: Download x64 Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_x64 - downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 - displayName: Download arm64 Artifacts - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: $(BuildConfiguration)_arm64 - downloadPath: $(Build.SourcesDirectory)\arm64 - - task: EsrpCodeSigning@1 - displayName: ESRP CodeSigning NatVis - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a - FolderPath: $(Build.SourcesDirectory) - Pattern: >- - x86\cppwinrt\cppwinrt.exe - - x86\Component\cppwinrtvisualizer.dll - - x64\Component\cppwinrtvisualizer.dll - - x86\Standalone\cppwinrtvisualizer.dll - - x64\Standalone\cppwinrtvisualizer.dll - UseMinimatch: true - signConfigType: inlineSignParams - inlineOperation: >- - [ - { - "keyCode": "CP-230012", - "operationSetCode": "SigntoolSign", - "parameters": [ - { - "parameterName": "OpusName", - "parameterValue": "Microsoft" - }, - { - "parameterName": "OpusInfo", - "parameterValue": "http://www.microsoft.com" - }, - { - "parameterName": "PageHash", - "parameterValue": "/NPH" - }, - { - "parameterName": "FileDigest", - "parameterValue": "/fd sha256" - }, - { - "parameterName": "TimeStamp", - "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - } - ], - "toolName": "signtool.exe", - "toolVersion": "6.2.9304.0" - } - ] - - task: CmdLine@2 - displayName: Stage Signed Binaries - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: >- - echo F|xcopy /S /Q /Y /F x86\cppwinrt\cppwinrt.exe $(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe - - echo F|xcopy /S /Q /Y /F x86\Component\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x86\Component\cppwinrtvisualizer.dll - - echo F|xcopy /S /Q /Y /F x64\Component\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x64\Component\cppwinrtvisualizer.dll - - echo F|xcopy /S /Q /Y /F x86\Standalone\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x86\Standalone\cppwinrtvisualizer.dll - - echo F|xcopy /S /Q /Y /F x64\Standalone\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x64\Standalone\cppwinrtvisualizer.dll - workingDirectory: $(Build.SourcesDirectory) - failOnStderr: true - - task: CmdLine@2 - displayName: Stage cppwinrtvisualizer.vsdconfig - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: >- - copy $(Build.SourcesDirectory)\x86\Component\cppwinrtvisualizer.vsdconfig x86\Component\cppwinrtvisualizer.vsdconfig - - copy $(Build.SourcesDirectory)\x86\Standalone\cppwinrtvisualizer.vsdconfig x86\Standalone\cppwinrtvisualizer.vsdconfig - workingDirectory: $(Build.ArtifactStagingDirectory) - failOnStderr: true - - task: NuGetCommand@2 - displayName: Build NuGet - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - command: pack - searchPatternPack: nuget/Microsoft.Windows.CppWinRT.nuspec - versioningScheme: byBuildNumber - buildProperties: 'cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' - - task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection - - task: EsrpCodeSigning@1 - displayName: ESRP CodeSigning Nuget Package - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a - FolderPath: $(Build.ArtifactStagingDirectory) - Pattern: Microsoft.Windows.CppWinRT.*.nupkg - UseMinimatch: true - signConfigType: inlineSignParams - inlineOperation: >- - [ - { - "KeyCode" : "CP-401405", - "OperationCode" : "NuGetSign", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - }, - { - "KeyCode" : "CP-401405", - "OperationCode" : "NuGetVerify", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - } - ] - - task: PkgESNuGetPublisher@0 - displayName: Publish NuGet Package - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - searchPattern: $(System.ArtifactsDirectory)\Microsoft.Windows.CppWinRT.$(Build.BuildNumber).nupkg - nuGetFeedType: internal - feedName: https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json - - task: VSBuild@1 - displayName: Build Component VSIX - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - solution: vsix/vsix.sln - msbuildArgs: /p:Deployment=Component,CppWinRTVersion=$(Build.BuildNumber),NatvisDirx86=$(Build.ArtifactStagingDirectory)\x86\Component\,NatvisDirx64=$(Build.ArtifactStagingDirectory)\x64\Component\,NupkgDir=$(Build.ArtifactStagingDirectory) /restore - platform: x86 - configuration: Release - - task: VSBuild@1 - displayName: Build Standalone VSIX - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - solution: vsix/vsix.sln - msbuildArgs: /p:Deployment=Standalone,CppWinRTVersion=$(Build.BuildNumber),NatvisDirx86=$(Build.ArtifactStagingDirectory)\x86\Standalone\,NatvisDirx64=$(Build.ArtifactStagingDirectory)\x64\Standalone\,NupkgDir=$(Build.ArtifactStagingDirectory) /restore - platform: x86 - configuration: Release - - task: EsrpCodeSigning@1 - displayName: ESRP CodeSigning VSIX - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a - FolderPath: $(Build.SourcesDirectory)\vsix\ - Pattern: >- - Dev16\bin\Release\Component\Microsoft.Windows.CppWinRT.vsix - - Dev16\bin\Release\Standalone\Microsoft.Windows.CppWinRT.vsix - - Dev17\bin\Release\Component\Microsoft.Windows.CppWinRT.Dev17.vsix - - Dev17\bin\Release\Standalone\Microsoft.Windows.CppWinRT.Dev17.vsix - UseMinimatch: true - signConfigType: inlineSignParams - inlineOperation: > - [ - { - "KeyCode" : "CP-233016", - "OperationCode" : "OpcSign", - "Parameters" : { - "FileDigest" : "/fd SHA256" - }, - "ToolName" : "sign", - "ToolVersion" : "1.0" - }, - { - "KeyCode" : "CP-233016", - "OperationCode" : "OpcVerify", - "Parameters" : {}, - "ToolName" : "sign", - "ToolVersion" : "1.0" - } - ] - - task: CmdLine@2 - displayName: Stage Component VSIX - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: >- - echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.vsix $(Build.ArtifactStagingDirectory)\Component\Dev17\Microsoft.Windows.CppWinRT.Dev17.vsix - - echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.json $(Build.ArtifactStagingDirectory)\Component\Dev17\Microsoft.Windows.CppWinRT.Dev17.json - workingDirectory: $(Build.SourcesDirectory)\vsix\Dev17\bin\Release\Component - failOnStderr: true - - task: CopyFiles@2 - displayName: Stage Component VSIX Manifest - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: $(Build.SourcesDirectory)\vsix - Contents: >- - extension.manifest.json - - overview.md - TargetFolder: $(Build.ArtifactStagingDirectory)\Component\Dev17 - OverWrite: true - - task: CmdLine@2 - displayName: Stage Standalone VSIX - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - script: echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.vsix $(Build.ArtifactStagingDirectory)\Standalone\Dev16\Microsoft.Windows.CppWinRT.vsix - workingDirectory: $(Build.SourcesDirectory)\vsix\Dev16\bin\$(BuildConfiguration)\Standalone - failOnStderr: true - - task: CopyFiles@2 - displayName: Stage Standalone VSIX Manifest - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - SourceFolder: $(Build.SourcesDirectory)\vsix - Contents: >- - extension.manifest.json - - overview.md - TargetFolder: $(Build.ArtifactStagingDirectory)\Standalone\Dev16 - OverWrite: true - - task: PublishPipelineArtifact@0 - displayName: Publish VSIX - condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual')) - inputs: - artifactName: Publish - targetPath: $(Build.ArtifactStagingDirectory) -... From 67cc9fa1e0974559f1cd73c6623ef514f90ff14d Mon Sep 17 00:00:00 2001 From: Jonathan Caves <45952631+JonCavesMSFT@users.noreply.github.com> Date: Tue, 8 Feb 2022 07:43:08 -0800 Subject: [PATCH 092/305] Add a missing 'typename' keyword (#1101) --- test/test/pch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test/pch.h b/test/test/pch.h index 916e8fe8f..65588aec3 100644 --- a/test/test/pch.h +++ b/test/test/pch.h @@ -45,4 +45,4 @@ using async_return_type = decltype(std::declval().GetResults()); template using async_progress_type = typename async_traits>::progress_type; template -inline constexpr bool has_async_progress = !std::is_same_v>::progress_type>; +inline constexpr bool has_async_progress = !std::is_same_v>::progress_type>; From 3b78eb21684902ee5b9af2961d0cfb763422b7ea Mon Sep 17 00:00:00 2001 From: QuellaZhang <36754348+QuellaZhang@users.noreply.github.com> Date: Tue, 15 Feb 2022 23:47:01 +0800 Subject: [PATCH 093/305] Add a missing 'typename' keyword (#1103) --- test/test_win7/pch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_win7/pch.h b/test/test_win7/pch.h index 84bb40137..1989286de 100644 --- a/test/test_win7/pch.h +++ b/test/test_win7/pch.h @@ -42,4 +42,4 @@ using async_return_type = decltype(std::declval().GetResults()); template using async_progress_type = typename async_traits>::progress_type; template -inline constexpr bool has_async_progress = !std::is_same_v>::progress_type>; +inline constexpr bool has_async_progress = !std::is_same_v>::progress_type>; From b4015649c5c658846bcd13d842a76e16135ea207 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 22 Feb 2022 12:58:33 -0800 Subject: [PATCH 094/305] Add type support for `Windows.Foundation.Numerics.Rational` (#1106) --- cppwinrt/type_writers.h | 24 +++++++++++++----------- test/test/rational.cpp | 18 ++++++++++++++++++ test/test/test.vcxproj | 1 + test/test_component/Simple.h | 10 ++++++++++ test/test_component/test_component.idl | 3 +++ 5 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 test/test/rational.cpp diff --git a/cppwinrt/type_writers.h b/cppwinrt/type_writers.h index a41b3086c..0fa3e5f8d 100644 --- a/cppwinrt/type_writers.h +++ b/cppwinrt/type_writers.h @@ -92,6 +92,18 @@ namespace cppwinrt return result; } + static bool transform_special_numeric_type(std::string_view& name) + { + if (name == "Matrix3x2") { name = "float3x2"; return true; } + else if (name == "Matrix4x4") { name = "float4x4"; return true; } + else if (name == "Plane") { name = "plane"; return true; } + else if (name == "Quaternion") { name = "quaternion"; return true; } + else if (name == "Vector2") { name = "float2"; return true; } + else if (name == "Vector3") { name = "float3"; return true; } + else if (name == "Vector4") { name = "float4"; return true; } + return false; + } + struct writer : writer_base { using writer_base::write; @@ -277,8 +289,6 @@ namespace cppwinrt return; } - // TODO: get rid of all these renames once parity with cppwinrt.exe has been reached... - if (name == "EventRegistrationToken" && ns == "Windows.Foundation") { write("winrt::event_token"); @@ -291,16 +301,8 @@ namespace cppwinrt { auto category = get_category(type); - if (ns == "Windows.Foundation.Numerics") + if (ns == "Windows.Foundation.Numerics" && transform_special_numeric_type(name)) { - if (name == "Matrix3x2") { name = "float3x2"; } - else if (name == "Matrix4x4") { name = "float4x4"; } - else if (name == "Plane") { name = "plane"; } - else if (name == "Quaternion") { name = "quaternion"; } - else if (name == "Vector2") { name = "float2"; } - else if (name == "Vector3") { name = "float3"; } - else if (name == "Vector4") { name = "float4"; } - write("winrt::@::%", ns, name); } else if (category == category::struct_type) diff --git a/test/test/rational.cpp b/test/test/rational.cpp new file mode 100644 index 000000000..c34dbce38 --- /dev/null +++ b/test/test/rational.cpp @@ -0,0 +1,18 @@ +#include "pch.h" +#include "winrt/test_component.h" +#include "winrt/Windows.Foundation.Numerics.h" + +using namespace winrt; +using namespace test_component; + +TEST_CASE("rational") +{ + Simple simple; + Windows::Foundation::Numerics::Rational rational = simple.ReturnRational(); + REQUIRE(rational.Numerator == 123); + REQUIRE(rational.Denominator == 456); + + Windows::Foundation::Numerics::float2 vector2 = simple.ReturnVector2(); + REQUIRE(vector2.x == 123.0); + REQUIRE(vector2.y == 456.0); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 4c7c58517..51dbfcb64 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -428,6 +428,7 @@ Create + diff --git a/test/test_component/Simple.h b/test/test_component/Simple.h index 0d97f5e1b..854c1235d 100644 --- a/test/test_component/Simple.h +++ b/test/test_component/Simple.h @@ -16,6 +16,16 @@ namespace winrt::test_component::implementation // All we care about static events (for now) is that they build. static event_token StaticEvent(Windows::Foundation::EventHandler const&) { return {}; } static void StaticEvent(event_token) { } + + Windows::Foundation::Numerics::float2 ReturnVector2() + { + return { 123.0, 456.0 }; + } + + Windows::Foundation::Numerics::Rational ReturnRational() + { + return { 123, 456 }; + } }; } namespace winrt::test_component::factory_implementation diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index 252e6d2f8..fb7444889 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -56,6 +56,9 @@ namespace test_component Windows.Foundation.IAsyncAction Action(Windows.Foundation.DateTime value); Object Object(Windows.Foundation.DateTime value); static event Windows.Foundation.EventHandler StaticEvent; + + Windows.Foundation.Numerics.Vector2 ReturnVector2(); + Windows.Foundation.Numerics.Rational ReturnRational(); } runtimeclass DeferrableEventArgs From 0c8f4e1e93dfcb9c07f3e5c58257d6000c164501 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Wed, 23 Feb 2022 18:02:57 -0800 Subject: [PATCH 095/305] Extend weak reference support to classic COM (#1104) --- strings/base_implements.h | 63 +++++++++++++++++-------------- test/old_tests/UnitTests/weak.cpp | 40 ++++++++++++++++++-- 2 files changed, 71 insertions(+), 32 deletions(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index df51f052f..e2c6f3a12 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1063,7 +1063,7 @@ namespace winrt::impl using is_agile = std::negation...>>; using is_inspectable = std::disjunction...>; - using is_weak_ref_source = std::conjunction...>>>; + using is_weak_ref_source = std::negation...>>; using use_module_lock = std::negation...>>; using weak_ref_t = impl::weak_ref; @@ -1125,57 +1125,64 @@ namespace winrt::impl impl::IWeakReferenceSource* make_weak_ref() noexcept { - static_assert(is_weak_ref_source::value, "This is only for weak ref support."); - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); - - if (is_weak_ref(count_or_pointer)) + if constexpr (is_weak_ref_source::value) { - return decode_weak_ref(count_or_pointer)->get_source(); - } - - com_ptr weak_ref; - *weak_ref.put() = new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)); + uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); - if (!weak_ref) - { - return nullptr; - } + if (is_weak_ref(count_or_pointer)) + { + return decode_weak_ref(count_or_pointer)->get_source(); + } - uintptr_t const encoding = encode_weak_ref(weak_ref.get()); + com_ptr weak_ref; + *weak_ref.put() = new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)); - for (;;) - { - if (m_references.compare_exchange_weak(count_or_pointer, encoding, std::memory_order_acq_rel, std::memory_order_relaxed)) + if (!weak_ref) { - impl::IWeakReferenceSource* result = weak_ref->get_source(); - detach_abi(weak_ref); - return result; + return nullptr; } - if (is_weak_ref(count_or_pointer)) + uintptr_t const encoding = encode_weak_ref(weak_ref.get()); + + for (;;) { - return decode_weak_ref(count_or_pointer)->get_source(); - } + if (m_references.compare_exchange_weak(count_or_pointer, encoding, std::memory_order_acq_rel, std::memory_order_relaxed)) + { + impl::IWeakReferenceSource* result = weak_ref->get_source(); + detach_abi(weak_ref); + return result; + } + + if (is_weak_ref(count_or_pointer)) + { + return decode_weak_ref(count_or_pointer)->get_source(); + } - weak_ref->set_strong(static_cast(count_or_pointer)); + weak_ref->set_strong(static_cast(count_or_pointer)); + } + } + else + { + static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); + return nullptr; } } static bool is_weak_ref(intptr_t const value) noexcept { - static_assert(is_weak_ref_source::value, "This is only for weak ref support."); + static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return value < 0; } static weak_ref_t* decode_weak_ref(uintptr_t const value) noexcept { - static_assert(is_weak_ref_source::value, "This is only for weak ref support."); + static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return reinterpret_cast(value << 1); } static uintptr_t encode_weak_ref(weak_ref_t* value) noexcept { - static_assert(is_weak_ref_source::value, "This is only for weak ref support."); + static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); constexpr uintptr_t pointer_flag = static_cast(1) << ((sizeof(uintptr_t) * 8) - 1); WINRT_ASSERT((reinterpret_cast(value) & 1) == 0); return (reinterpret_cast(value) >> 1) | pointer_flag; diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index ba0fb5d86..d93377df5 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -22,7 +22,7 @@ namespace } }; - struct NoWeak : implements + struct WeakClassicCom : implements { }; @@ -161,6 +161,26 @@ TEST_CASE("weak,source") REQUIRE(b.ToString() == L"Weak"); } + SECTION("classic-com") + { + com_ptr<::IUnknown> a = make(); + + weak_ref<::IUnknown> w = a; + com_ptr<::IUnknown> b = w.get(); + REQUIRE(b == a); + + // still one outstanding reference + b = nullptr; + b = w.get(); + REQUIRE(b != nullptr); + + // no outstanding references + a = nullptr; + b = nullptr; + b = w.get(); + REQUIRE(b == nullptr); + } + // Verify that deduction guides work. static_assert(std::is_same_v, decltype(weak_ref(IStringable()))>); static_assert(std::is_same_v, decltype(weak_ref(std::declval()))>); @@ -206,12 +226,24 @@ TEST_CASE("weak,QI") REQUIRE(ref.as<::IUnknown>() != object.as<::IUnknown>()); } - SECTION("no-weak") + SECTION("weak-classic-com") { - com_ptr<::IUnknown> object = make(); + com_ptr<::IUnknown> object = make(); REQUIRE(!object.try_as()); - REQUIRE(!object.try_as()); + REQUIRE(object.try_as()); REQUIRE(!object.try_as()); + + com_ptr source = object.as(); + REQUIRE(!source.try_as()); + REQUIRE(source.try_as()); + REQUIRE(object.as<::IUnknown>() == source.as<::IUnknown>()); + + com_ptr ref; + REQUIRE(S_OK == source->GetWeakReference(ref.put())); + REQUIRE(!ref.try_as()); + REQUIRE(!ref.try_as()); + REQUIRE(ref.as() == ref); + REQUIRE(ref.as<::IUnknown>() != object.as<::IUnknown>()); } SECTION("factory") From 0e33676e6d6c17d6a43e1ded9c94286305e77358 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Thu, 24 Feb 2022 09:38:15 -0800 Subject: [PATCH 096/305] Add guid brace parsing (#1109) --- strings/base_types.h | 9 ++++++++- test/test/guid.cpp | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/strings/base_types.h b/strings/base_types.h index afff3db35..84cf22f5d 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -85,8 +85,15 @@ WINRT_EXPORT namespace winrt private: template - static constexpr guid parse(TStringView const value) + static constexpr guid parse(TStringView value) { + // Handle {} and () + if (value.size() == 38 && ((value[0] == '{' && value[37] == '}') || (value[0] == '(' && value[37] == ')'))) + { + value.remove_prefix(1); + value.remove_suffix(1); + } + if (value.size() != 36 || value[8] != '-' || value[13] != '-' || value[18] != '-' || value[23] != '-') { throw std::invalid_argument("value is not a valid GUID string"); diff --git a/test/test/guid.cpp b/test/test/guid.cpp index 3dff63088..48d277e64 100644 --- a/test/test/guid.cpp +++ b/test/test/guid.cpp @@ -21,6 +21,8 @@ TEST_CASE("guid") REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff") == expected); REQUIRE(winrt::guid({ "{00112233-4455-6677-8899-aabbccddeeff}" + 1, 36 }) == expected); + REQUIRE(winrt::guid("{00112233-4455-6677-8899-aabbccddeeff}") == expected); + REQUIRE(winrt::guid("(00112233-4455-6677-8899-aabbccddeeff)") == expected); REQUIRE_THROWS_AS(winrt::guid(""), std::invalid_argument); REQUIRE_THROWS_AS(winrt::guid("not a guid"), std::invalid_argument); @@ -28,7 +30,6 @@ TEST_CASE("guid") REQUIRE_THROWS_AS(winrt::guid("too long string that's also not a guid"), std::invalid_argument); REQUIRE_THROWS_AS(winrt::guid("00112233-4455-6677-8899-aabbccddeeff with extra"), std::invalid_argument); REQUIRE_THROWS_AS(winrt::guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), std::invalid_argument); - REQUIRE_THROWS_AS(winrt::guid("{00112233-4455-6677-8899-aabbccddeeff}"), std::invalid_argument); // Verify that you can constexpr-construct a guid from a GUID. constexpr winrt::guid from_abi_guid = GUID{ 0x00112233, 0x4455, 0x6677, { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } }; From 8484e43b816d695a9b1e28582eda87696e6111d5 Mon Sep 17 00:00:00 2001 From: halflumi Date: Sat, 5 Mar 2022 01:39:25 +0800 Subject: [PATCH 097/305] Fix time_point compilation error with Clang (#1112) --- strings/base_chrono.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_chrono.h b/strings/base_chrono.h index 8af906176..e8e5a1ee4 100644 --- a/strings/base_chrono.h +++ b/strings/base_chrono.h @@ -42,7 +42,7 @@ WINRT_EXPORT namespace winrt static time_t to_time_t(time_point const& time) noexcept { - return static_cast(std::chrono::system_clock::to_time_t(to_sys(time))); + return static_cast(std::chrono::system_clock::to_time_t(to_sys(std::chrono::time_point_cast(time)))); } static time_point from_time_t(time_t time) noexcept From a7ee860e4933fdbc0345c537d5c5c1cbd4fb8be2 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 10 Mar 2022 14:43:27 -0800 Subject: [PATCH 098/305] Remove `WINRT_IMPL_AUTO` workaround (#1117) --- cppwinrt/code_writers.h | 16 ++++++---------- strings/base_macros.h | 6 ------ 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 9d4b98e23..1ab71f79f 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -992,9 +992,8 @@ namespace cppwinrt auto method_name = get_name(method); auto type = method.Parent(); - w.write(" %WINRT_IMPL_AUTO(%) %(%) const%;\n", + w.write(" %auto %(%) const%;\n", is_get_overload(method) ? "[[nodiscard]] " : "", - signature.return_signature(), method_name, bind(signature), is_noexcept(method) ? " noexcept" : ""); @@ -1133,7 +1132,7 @@ namespace cppwinrt if (is_remove_overload(method)) { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker - format = R"( template WINRT_IMPL_AUTO(%) consume_%::%(%) const noexcept + format = R"( template auto consume_%::%(%) const noexcept {% WINRT_IMPL_SHIM(%)->%(%);% } @@ -1141,7 +1140,7 @@ namespace cppwinrt } else { - format = R"( template WINRT_IMPL_AUTO(%) consume_%::%(%) const noexcept + format = R"( template auto consume_%::%(%) const noexcept {% WINRT_VERIFY_(0, WINRT_IMPL_SHIM(%)->%(%));% } @@ -1150,7 +1149,7 @@ namespace cppwinrt } else { - format = R"( template WINRT_IMPL_AUTO(%) consume_%::%(%) const + format = R"( template auto consume_%::%(%) const {% check_hresult(WINRT_IMPL_SHIM(%)->%(%));% } @@ -1159,7 +1158,6 @@ namespace cppwinrt w.write(format, bind(generics), - signature.return_signature(), type_impl_name, bind(generics), method_name, @@ -1207,14 +1205,13 @@ namespace cppwinrt // return static_cast<% const&>(*this).%(%); // - std::string_view format = R"( inline WINRT_IMPL_AUTO(%) %::%(%) const% + std::string_view format = R"( inline auto %::%(%) const% { return [&](% const& winrt_impl_base) { return winrt_impl_base.%(%); }(*this); } )"; w.write(format, - signature.return_signature(), class_type.TypeName(), method_name, bind(signature), @@ -1999,7 +1996,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable static void write_interface_override_method(writer& w, MethodDef const& method, std::string_view const& interface_name) { - auto format = R"( template WINRT_IMPL_AUTO(%) %T::%(%) const% + auto format = R"( template auto %T::%(%) const% { return shim().template try_as<%>().%(%); } @@ -2009,7 +2006,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable auto method_name = get_name(method); w.write(format, - signature.return_signature(), interface_name, method_name, bind(signature), diff --git a/strings/base_macros.h b/strings/base_macros.h index 1b96e240c..40473bb5d 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -15,12 +15,6 @@ #define WINRT_IMPL_SHIM(...) (*(abi_t<__VA_ARGS__>**)&static_cast<__VA_ARGS__ const&>(static_cast(*this))) -#ifdef __INTELLISENSE__ -#define WINRT_IMPL_AUTO(...) __VA_ARGS__ -#else -#define WINRT_IMPL_AUTO(...) auto -#endif - // Note: this is a workaround for a false-positive warning produced by the Visual C++ 15.9 compiler. #pragma warning(disable : 5046) From e0012b04cd3833c944984e681633df5fde6311ae Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 11 Mar 2022 11:26:43 -0800 Subject: [PATCH 099/305] Remove workaround for Visual C++ code gen bug (#1118) --- cppwinrt/code_writers.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 1ab71f79f..adf9a1392 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1197,17 +1197,9 @@ namespace cppwinrt method_signature signature{ method }; auto async_types_guard = w.push_async_types(signature.is_async()); - // - // Note: this use of a lambda is a workaround for a Visual C++ compiler bug: - // https://developercommunity.visualstudio.com/content/problem/554130/incorrect-code-gen-when-invoking-a-conversion-oper.html - // Once fixed, revert the function body back to this: - // - // return static_cast<% const&>(*this).%(%); - // - std::string_view format = R"( inline auto %::%(%) const% { - return [&](% const& winrt_impl_base) { return winrt_impl_base.%(%); }(*this); + return static_cast<% const&>(*this).%(%); } )"; From 768139a94370fccb38185f7dd83d4eac334e07f7 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 22 Mar 2022 15:14:59 -0700 Subject: [PATCH 100/305] Several nuget tests failing to build with VS2022. Standardize on directory.build.props to use PlatformToolset v143 (#1125) --- cppwinrt.props => Directory.Build.Props | 17 +++--------- cppwinrt/cppwinrt.vcxproj | 3 +-- fast_fwd/fast_fwd.vcxproj | 6 ++--- natvis/cppwinrtvisualizer.vcxproj | 8 ------ prebuild/prebuild.vcxproj | 3 +-- scratch/scratch.vcxproj | 3 +-- .../ConsoleApplication1.vcxproj | 5 ---- test/nuget/TestApp/TestApp.vcxproj | 5 ---- .../TestRuntimeComponent1.vcxproj | 5 ---- .../TestRuntimeComponent2.vcxproj | 5 ---- .../TestRuntimeComponent3.vcxproj | 5 ---- .../TestRuntimeComponentCX.vcxproj | 20 ++++++-------- ...entCXReferencingWinRTStaticLibrary.vcxproj | 26 ++++++------------- .../TestRuntimeComponentEmpty.vcxproj | 5 ---- ...untimeComponentNamespaceUnderscore.vcxproj | 5 ---- .../TestStaticLibrary1.vcxproj | 4 --- .../TestStaticLibrary2.vcxproj | 4 --- .../TestStaticLibrary3.vcxproj | 4 --- .../TestStaticLibrary4.vcxproj | 4 --- .../TestStaticLibrary5.vcxproj | 4 --- .../TestStaticLibrary6.vcxproj | 4 --- .../TestStaticLibrary7.vcxproj | 5 ---- test/old_tests/Component/Component.vcxproj | 3 +-- test/old_tests/Composable/Composable.vcxproj | 3 +-- test/old_tests/UnitTests/Tests.vcxproj | 3 +-- test/test/test.vcxproj | 3 +-- test/test_component/test_component.vcxproj | 3 +-- .../test_component_base.vcxproj | 3 +-- .../test_component_derived.vcxproj | 3 +-- .../test_component_fast.vcxproj | 3 +-- .../test_component_folders.vcxproj | 3 +-- .../test_component_no_pch.vcxproj | 3 +-- test/test_cpp20/test_cpp20.vcxproj | 3 +-- test/test_fast/test_fast.vcxproj | 3 +-- test/test_fast_fwd/test_fast_fwd.vcxproj | 3 +-- .../test_module_lock_custom.vcxproj | 3 +-- .../test_module_lock_none.vcxproj | 3 +-- test/test_slow/test_slow.vcxproj | 3 +-- test/test_win7/test_win7.vcxproj | 3 +-- 39 files changed, 42 insertions(+), 159 deletions(-) rename cppwinrt.props => Directory.Build.Props (84%) diff --git a/cppwinrt.props b/Directory.Build.Props similarity index 84% rename from cppwinrt.props rename to Directory.Build.Props index 943cbc823..1db701da1 100644 --- a/cppwinrt.props +++ b/Directory.Build.Props @@ -2,19 +2,12 @@ - - v141 - 10.0.17763.0 - - - - v142 - 10.0 - - - + v143 + v142 + v141 10.0 + 10.0.18362.0 - v143 - v142 - v141 + v141 + v142 + v143 10.0 10.0.18362.0 @@ -33,12 +33,11 @@ 2.3.4.5 - $(Platform) - x86 - $(SolutionDir)_build\$(CmakePlatform)\$(Configuration) - $(CmakeOutDir)\ + $(Platform) + x86 + $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ + $(OutDir) $(SolutionDir)_build\x86\$(Configuration)\ - $(CmakeOutDir)\ @@ -64,4 +63,10 @@ + + + + + diff --git a/Directory.Build.Targets b/Directory.Build.Targets new file mode 100644 index 000000000..98abcdd3f --- /dev/null +++ b/Directory.Build.Targets @@ -0,0 +1,7 @@ + + + + $(OutDir)temp\$(ProjectName)\ + + + diff --git a/build_test_all.cmd b/build_test_all.cmd index 13a68f6c9..e0325eb5d 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -3,6 +3,7 @@ set target_platform=%1 set target_configuration=%2 set target_version=%3 +set clean_intermediate_files=%4 if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Release diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 092591a8b..81b6703ef 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -190,20 +190,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - Disabled diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index e45c78a1e..397772285 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -67,25 +67,14 @@ - + true - x86\$(Configuration)\$(Deployment)\ - x86\$(Configuration)\$(Deployment)\ - - true - x64\$(Configuration)\$(Deployment)\ - x64\$(Configuration)\$(Deployment)\ - - + false - x86\$(Configuration)\$(Deployment)\ - x86\$(Configuration)\$(Deployment)\ - - false - x64\$(Configuration)\$(Deployment)\ - x64\$(Configuration)\$(Deployment)\ + + $(CppWinRTPlatform)\$(Configuration)\$(Deployment)\ diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index 01335f3b4..8308ae560 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -106,20 +106,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - Disabled diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 5f2adb1af..4a26617b4 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -107,20 +107,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed diff --git a/test/Directory.Build.Props b/test/Directory.Build.Props new file mode 100644 index 000000000..84e381220 --- /dev/null +++ b/test/Directory.Build.Props @@ -0,0 +1,10 @@ + + + + + v142 + + + + + diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index e0d413a85..2ce8c8005 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -121,7 +121,6 @@ false ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ false @@ -140,7 +139,6 @@ false ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ false @@ -159,14 +157,12 @@ false ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ false false ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index 71bf5eff4..b4b29d968 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -121,7 +121,6 @@ false ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ false @@ -140,7 +139,6 @@ false ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ false @@ -159,14 +157,12 @@ false ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ false false ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(OutDir)temp\$(ProjectName)\ diff --git a/test/old_tests/UnitTests/Tests.vcxproj b/test/old_tests/UnitTests/Tests.vcxproj index 3be42e48b..aedd02bfd 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj +++ b/test/old_tests/UnitTests/Tests.vcxproj @@ -214,33 +214,11 @@ - + true - $(OutDir)temp\$(ProjectName)\ - - true - - - true - - - true - $(OutDir)temp\$(ProjectName)\ - - - false - $(OutDir)temp\$(ProjectName)\ - - - false - - - false - - + false - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index f66d98dcc..dc6c96cea 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -107,20 +107,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 3a2eb1980..55096520a 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -118,7 +118,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -131,7 +130,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -144,12 +142,10 @@ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index 2a93b7452..8bf804684 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -118,7 +118,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -131,7 +130,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -144,12 +142,10 @@ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index 2dabc71ec..d444a2111 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -118,7 +118,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -131,7 +130,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -144,12 +142,10 @@ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index 50119cd07..9f42be8e3 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -119,7 +119,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -132,7 +131,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -145,12 +143,10 @@ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index d40e69d4e..b552d147f 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -118,7 +118,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -131,7 +130,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -144,12 +142,10 @@ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 787d9f4ac..b4ad8741f 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -118,7 +118,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -131,7 +130,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl @@ -144,12 +142,10 @@ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ Midl $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index a707c5166..79967de19 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -108,20 +108,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj index 3ce85f291..dbf3d9b8b 100644 --- a/test/test_fast/test_fast.vcxproj +++ b/test/test_fast/test_fast.vcxproj @@ -107,20 +107,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed diff --git a/test/test_fast_fwd/test_fast_fwd.vcxproj b/test/test_fast_fwd/test_fast_fwd.vcxproj index bae6f7925..c01406e38 100644 --- a/test/test_fast_fwd/test_fast_fwd.vcxproj +++ b/test/test_fast_fwd/test_fast_fwd.vcxproj @@ -59,7 +59,6 @@ Midl - $(OutDir)temp\$(ProjectName)\ diff --git a/test/test_module_lock_custom/test_module_lock_custom.vcxproj b/test/test_module_lock_custom/test_module_lock_custom.vcxproj index 330aafe1c..6bb40e761 100644 --- a/test/test_module_lock_custom/test_module_lock_custom.vcxproj +++ b/test/test_module_lock_custom/test_module_lock_custom.vcxproj @@ -107,20 +107,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed diff --git a/test/test_module_lock_none/test_module_lock_none.vcxproj b/test/test_module_lock_none/test_module_lock_none.vcxproj index a4c3d40cd..7f460c6b2 100644 --- a/test/test_module_lock_none/test_module_lock_none.vcxproj +++ b/test/test_module_lock_none/test_module_lock_none.vcxproj @@ -107,20 +107,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed diff --git a/test/test_slow/test_slow.vcxproj b/test/test_slow/test_slow.vcxproj index 6ee91fbbf..75891b64b 100644 --- a/test/test_slow/test_slow.vcxproj +++ b/test/test_slow/test_slow.vcxproj @@ -107,20 +107,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed diff --git a/test/test_win7/test_win7.vcxproj b/test/test_win7/test_win7.vcxproj index c1a06dce2..b85b6a448 100644 --- a/test/test_win7/test_win7.vcxproj +++ b/test/test_win7/test_win7.vcxproj @@ -107,20 +107,6 @@ - - $(OutDir)temp\$(ProjectName)\ - - - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - - - $(OutDir)temp\$(ProjectName)\ - MaxSpeed From 27adc6b382ea36a0ab3f6ecc97638f4ef149fdc5 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 24 Mar 2022 08:20:01 -0700 Subject: [PATCH 102/305] fix regression in nested visualizations with VS2019+ (#1126) * fix regression in nested visualizations with VS2019+ * bug in calculating child count --- natvis/object_visualizer.cpp | 46 +++++++++++++----------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 6bb6b6deb..4b1f7efd5 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -631,11 +631,10 @@ HRESULT object_visualizer::CreateEvaluationResult(_Deref_out_ DkmEvaluationResul } HRESULT object_visualizer::GetChildren( - _In_ UINT32 /*InitialRequestSize*/, + _In_ UINT32 InitialRequestSize, _In_ DkmInspectionContext* pInspectionContext, _Out_ DkmArray* pInitialChildren, - _Deref_out_ DkmEvaluationResultEnumContext** ppEnumContext -) + _Deref_out_ DkmEvaluationResultEnumContext** ppEnumContext) { // Ignore metadata errors to ensure that Raw Data is always available if (m_propertyData.empty()) @@ -667,32 +666,34 @@ HRESULT object_visualizer::GetChildren( this, pEnumContext.put())); - DkmAllocArray(0, pInitialChildren); + IF_FAIL_RET(GetItems(m_pVisualizedExpression.get(), pEnumContext.get(), 0, InitialRequestSize, pInitialChildren)); + *ppEnumContext = pEnumContext.detach(); return S_OK; } HRESULT object_visualizer::GetItems( - _In_ DkmVisualizedExpression* /*pVisualizedExpression*/, + _In_ DkmVisualizedExpression* pVisualizedExpression, _In_ DkmEvaluationResultEnumContext* /*pEnumContext*/, _In_ UINT32 StartIndex, _In_ UINT32 Count, - _Out_ DkmArray* pItems -) + _Out_ DkmArray* pItems) { - std::list> childItems; + CAutoDkmArray resultValues; + IF_FAIL_RET(DkmAllocArray(std::min(m_propertyData.size(), size_t(Count)), &resultValues)); - auto pParent = m_pVisualizedExpression.get(); - for( auto childIndex = StartIndex; childIndex < StartIndex + Count; ++childIndex) + auto pParent = pVisualizedExpression; + auto childCount = std::min(m_propertyData.size() - StartIndex, (size_t)Count); + for(auto i = 0; i < childCount; ++i) { - auto& prop = m_propertyData[childIndex]; + auto& prop = m_propertyData[i + (size_t)StartIndex]; com_ptr pPropertyVisualized; - if(FAILED(CreateChildVisualizedExpression(prop, pParent, m_isAbiObject, pPropertyVisualized.put()))) + if (FAILED(CreateChildVisualizedExpression(prop, pParent, m_isAbiObject, pPropertyVisualized.put()))) { com_ptr pErrorMessage; IF_FAIL_RET(DkmString::Create(L"", pErrorMessage.put())); - + com_ptr pDisplayName; IF_FAIL_RET(DkmString::Create(prop.displayName.c_str(), pDisplayName.put())); @@ -701,9 +702,9 @@ HRESULT object_visualizer::GetItems( pParent->InspectionContext(), pParent->StackFrame(), pDisplayName.get(), - nullptr, + nullptr, pErrorMessage.get(), - DkmEvaluationResultFlags::ExceptionThrown, + DkmEvaluationResultFlags::ExceptionThrown, DkmDataItem::Null(), pVisualizedResult.put() )); @@ -721,22 +722,9 @@ HRESULT object_visualizer::GetItems( pPropertyVisualized.put() )); } - childItems.push_back(pPropertyVisualized); - } - - CAutoDkmArray resultValues; - IF_FAIL_RET(DkmAllocArray(childItems.size(), &resultValues)); - - UINT32 j = 0; - auto pos = childItems.begin(); - while (pos != childItems.end()) - { - com_ptr pCurr = *pos; - resultValues.Members[j++] = pCurr.detach(); - pos++; + resultValues.Members[i] = pPropertyVisualized.detach(); } *pItems = resultValues.Detach(); - return S_OK; } From b69f40d6ecc7d852aebb0682e099322b60cc34e3 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 24 Mar 2022 10:06:41 -0700 Subject: [PATCH 103/305] per request, provide implementation-side visualizations. and always show raw data. (#1128) --- natvis/cppwinrt.natvis | 5 ++++ natvis/cppwinrt_visualizer.cpp | 15 ++++++---- natvis/object_visualizer.cpp | 54 +++++++++++++--------------------- natvis/object_visualizer.h | 14 ++++++--- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/natvis/cppwinrt.natvis b/natvis/cppwinrt.natvis index 168b5542e..7fad2e26c 100644 --- a/natvis/cppwinrt.natvis +++ b/natvis/cppwinrt.natvis @@ -14,6 +14,11 @@ null + + + + null + diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index 1e2539910..b44be1268 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -207,21 +207,26 @@ HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( IF_FAIL_RET(pTypeSymbol->get_name(&bstrTypeName)); // Visualize top-level C++/WinRT objects containing ABI pointers - bool isAbiObject; + ObjectType objectType; if (wcscmp(bstrTypeName, L"winrt::Windows::Foundation::IInspectable") == 0) { - isAbiObject = false; + objectType = ObjectType::Projection; } // Visualize nested object properties via raw ABI pointers else if ((wcscmp(bstrTypeName, L"winrt::impl::IInspectable") == 0) || (wcscmp(bstrTypeName, L"winrt::impl::inspectable_abi") == 0)) { - isAbiObject = true; + objectType = ObjectType::Abi; + } + // Visualize C++/WinRT object implementations + else if (wcsncmp(bstrTypeName, L"winrt::impl::producer<", wcslen(L"winrt::impl::producer<")) == 0) + { + objectType = ObjectType::Abi; } // Visualize all raw IInspectable pointers else if (wcscmp(bstrTypeName, L"IInspectable") == 0) { - isAbiObject = true; + objectType = ObjectType::Abi; } else { @@ -231,7 +236,7 @@ HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( return S_OK; } - IF_FAIL_RET(object_visualizer::CreateEvaluationResult(pVisualizedExpression, isAbiObject, ppResultObject)); + IF_FAIL_RET(object_visualizer::CreateEvaluationResult(pVisualizedExpression, objectType, ppResultObject)); return S_OK; } diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 4b1f7efd5..8bcb86877 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -99,14 +99,14 @@ static HRESULT EvaluatePropertyExpression( _In_ PropertyData const& prop, _In_ DkmVisualizedExpression* pExpression, _In_ DkmPointerValueHome* pObject, - bool isAbiObject, + ObjectType objectType, _Out_ com_ptr& pEvaluationResult ) { wchar_t abiAddress[40]; auto process = pExpression->RuntimeInstance()->Process(); bool is64Bit = ((process->SystemInformation()->Flags() & DefaultPort::DkmSystemInformationFlags::Is64Bit) != 0); - swprintf_s(abiAddress, is64Bit ? L"%s0x%I64x" : L"%s0x%08x", isAbiObject ? L"(::IUnknown*)" : L"*(::IUnknown**)", pObject->Address()); + swprintf_s(abiAddress, is64Bit ? L"%s0x%I64x" : L"%s0x%08x", objectType == ObjectType::Abi ? L"(::IUnknown*)" : L"*(::IUnknown**)", pObject->Address()); wchar_t wszEvalText[500]; std::wstring propCast; PCWSTR propField; @@ -174,12 +174,12 @@ static HRESULT EvaluatePropertyString( _In_ PropertyData const& prop, _In_ DkmVisualizedExpression* pExpression, _In_ DkmPointerValueHome* pObject, - bool isAbiObject, + ObjectType objectType, _Out_ com_ptr& pValue ) { com_ptr pEvaluationResult; - IF_FAIL_RET(EvaluatePropertyExpression(prop, pExpression, pObject, isAbiObject, pEvaluationResult)); + IF_FAIL_RET(EvaluatePropertyExpression(prop, pExpression, pObject, objectType, pEvaluationResult)); if (pEvaluationResult->TagValue() != DkmEvaluationResult::Tag::SuccessResult) { return E_FAIL; @@ -195,11 +195,11 @@ static HRESULT EvaluatePropertyString( static std::string GetRuntimeClass( _In_ DkmVisualizedExpression* pExpression, _In_ DkmPointerValueHome* pObject, - bool isAbiObject + ObjectType objectType ) { com_ptr pValue; - EvaluatePropertyString({ IID_IInspectable, -2, PropertyCategory::String }, pExpression, pObject, isAbiObject, pValue); + EvaluatePropertyString({ IID_IInspectable, -2, PropertyCategory::String }, pExpression, pObject, objectType, pValue); if (!pValue || pValue->Length() == 0) { return ""; @@ -210,16 +210,11 @@ static std::string GetRuntimeClass( static HRESULT ObjectToString( _In_ DkmVisualizedExpression* pExpression, _In_ DkmPointerValueHome* pObject, - bool isAbiObject, - _Out_ com_ptr& pValue, - bool* unavailable = nullptr + ObjectType objectType, + _Out_ com_ptr& pValue ) { - if (unavailable) - { - *unavailable = false; - } - if (SUCCEEDED(EvaluatePropertyString({ IID_IStringable, 0, PropertyCategory::String }, pExpression, pObject, isAbiObject, pValue))) + if (SUCCEEDED(EvaluatePropertyString({ IID_IStringable, 0, PropertyCategory::String }, pExpression, pObject, objectType, pValue))) { if (pValue && pValue->Length() > 0) { @@ -229,7 +224,7 @@ static HRESULT ObjectToString( // WINRT_abi_val returned 0, which may be success or failure (due to VirtualQuery validation) // Call back for the runtime class name to determine which it was - if (!GetRuntimeClass(pExpression, pObject, isAbiObject).empty()) + if (!GetRuntimeClass(pExpression, pObject, objectType).empty()) { return DkmString::Create(L"", pValue.put()); } @@ -237,17 +232,13 @@ static HRESULT ObjectToString( // VirtualQuery validation failed (as determined by no runtime class name) or an // exception escaped WINRT_abi_val (e.g, bad pointer, which we try to avoid via VirtualQuery) - if (unavailable) - { - *unavailable = true; - } return DkmString::Create(L"", pValue.put()); } static HRESULT CreateChildVisualizedExpression( _In_ PropertyData const& prop, _In_ DkmVisualizedExpression* pParent, - bool isAbiObject, + ObjectType objectType, _Deref_out_ DkmChildVisualizedExpression** ppResult ) { @@ -256,7 +247,7 @@ static HRESULT CreateChildVisualizedExpression( com_ptr pEvaluationResult; auto valueHome = make_com_ptr(pParent->ValueHome()); com_ptr pParentPointer = valueHome.as(); - IF_FAIL_RET(EvaluatePropertyExpression(prop, pParent, pParentPointer.get(), isAbiObject, pEvaluationResult)); + IF_FAIL_RET(EvaluatePropertyExpression(prop, pParent, pParentPointer.get(), objectType, pEvaluationResult)); if (pEvaluationResult->TagValue() != DkmEvaluationResult::Tag::SuccessResult) { return E_FAIL; @@ -273,7 +264,7 @@ static HRESULT CreateChildVisualizedExpression( { isNonNullObject = true; IF_FAIL_RET(DkmPointerValueHome::Create(childObjectAddress, pChildPointer.put())); - IF_FAIL_RET(ObjectToString(pParent, pChildPointer.get(), true, pValue)); + IF_FAIL_RET(ObjectToString(pParent, pChildPointer.get(), ObjectType::Abi, pValue)); } } if(!isNonNullObject) @@ -335,7 +326,7 @@ static HRESULT CreateChildVisualizedExpression( if (isNonNullObject) { - com_ptr pObjectVisualizer = make_self(pChildVisualizedExpression.get(), true); + com_ptr pObjectVisualizer = make_self(pChildVisualizedExpression.get(), ObjectType::Abi); IF_FAIL_RET(pChildVisualizedExpression->SetDataItem(DkmDataCreationDisposition::CreateNew, pObjectVisualizer.get())); } else @@ -492,7 +483,7 @@ void object_visualizer::GetPropertyData() { auto valueHome = make_com_ptr(m_pVisualizedExpression->ValueHome()); com_ptr pObject = valueHome.as(); - auto rc = GetRuntimeClass(m_pVisualizedExpression.get(), pObject.get(), m_isAbiObject); + auto rc = GetRuntimeClass(m_pVisualizedExpression.get(), pObject.get(), m_objectType); if (rc.empty()) { return; @@ -539,9 +530,9 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm } } -HRESULT object_visualizer::CreateEvaluationResult(_In_ DkmVisualizedExpression* pVisualizedExpression, _In_ bool isAbiObject, _Deref_out_ DkmEvaluationResult** ppResultObject) +HRESULT object_visualizer::CreateEvaluationResult(_In_ DkmVisualizedExpression* pVisualizedExpression, _In_ ObjectType objectType, _Deref_out_ DkmEvaluationResult** ppResultObject) { - com_ptr pObjectVisualizer = make_self(pVisualizedExpression, isAbiObject); + com_ptr pObjectVisualizer = make_self(pVisualizedExpression, objectType); IF_FAIL_RET(pVisualizedExpression->SetDataItem(DkmDataCreationDisposition::CreateNew, pObjectVisualizer.get())); @@ -582,7 +573,7 @@ HRESULT object_visualizer::CreateEvaluationResult(_Deref_out_ DkmEvaluationResul auto address = pPointerValueHome->Address(); com_ptr pValue; - DkmEvaluationResultFlags_t evalResultFlags = DkmEvaluationResultFlags::ReadOnly; + DkmEvaluationResultFlags_t evalResultFlags = DkmEvaluationResultFlags::ReadOnly | DkmEvaluationResultFlags::Expandable;; if (requires_refresh(address, m_pVisualizedExpression->InspectionContext()->EvaluationFlags())) { IF_FAIL_RET(DkmString::Create(L"", pValue.put())); @@ -591,12 +582,7 @@ HRESULT object_visualizer::CreateEvaluationResult(_Deref_out_ DkmEvaluationResul else { cache_refresh(address); - bool unavailable; - IF_FAIL_RET(ObjectToString(m_pVisualizedExpression.get(), pPointerValueHome.get(), m_isAbiObject, pValue, &unavailable)); - if (!unavailable) - { - evalResultFlags |= DkmEvaluationResultFlags::Expandable; - } + IF_FAIL_RET(ObjectToString(m_pVisualizedExpression.get(), pPointerValueHome.get(), m_objectType, pValue)); } com_ptr pAddress; @@ -689,7 +675,7 @@ HRESULT object_visualizer::GetItems( { auto& prop = m_propertyData[i + (size_t)StartIndex]; com_ptr pPropertyVisualized; - if (FAILED(CreateChildVisualizedExpression(prop, pParent, m_isAbiObject, pPropertyVisualized.put()))) + if(FAILED(CreateChildVisualizedExpression(prop, pParent, m_objectType, pPropertyVisualized.put()))) { com_ptr pErrorMessage; IF_FAIL_RET(DkmString::Create(L"", pErrorMessage.put())); diff --git a/natvis/object_visualizer.h b/natvis/object_visualizer.h index 2c84a4a94..08cc40f72 100644 --- a/natvis/object_visualizer.h +++ b/natvis/object_visualizer.h @@ -20,6 +20,12 @@ enum class PropertyCategory Class, }; +enum class ObjectType +{ + Abi, + Projection, +}; + // Metatdata for resolving a runtime class property value struct PropertyData { @@ -36,17 +42,17 @@ struct PropertyData struct __declspec(uuid("c7da92da-3bc9-4312-8a93-46f480663980")) object_visualizer : winrt::implements { - object_visualizer(Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, bool isAbiObject) + object_visualizer(Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, ObjectType objectType) { m_pVisualizedExpression = make_com_ptr(pVisualizedExpression); - m_isAbiObject = isAbiObject; + m_objectType = objectType; } ~object_visualizer() { } - static HRESULT CreateEvaluationResult(_In_ Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, _In_ bool isAbiObject, _Deref_out_ Microsoft::VisualStudio::Debugger::Evaluation::DkmEvaluationResult** ppResultObject); + static HRESULT CreateEvaluationResult(_In_ Microsoft::VisualStudio::Debugger::Evaluation::DkmVisualizedExpression* pVisualizedExpression, _In_ ObjectType objectType, _Deref_out_ Microsoft::VisualStudio::Debugger::Evaluation::DkmEvaluationResult** ppResultObject); HRESULT CreateEvaluationResult(_Deref_out_ Microsoft::VisualStudio::Debugger::Evaluation::DkmEvaluationResult** ppResultObject); @@ -69,7 +75,7 @@ object_visualizer : winrt::implements void GetPropertyData(); void GetTypeProperties(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& type_name); winrt::com_ptr m_pVisualizedExpression; - bool m_isAbiObject; + ObjectType m_objectType; std::vector m_propertyData; bool m_isStringable{ false }; }; From 04008670da93091c27530484d18e50a0ef08b691 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 31 Mar 2022 10:16:00 -0700 Subject: [PATCH 104/305] two-phase initialization support to prevent double-destruction on handing out this pointer in ctor (#1130) * two-phase initialization support to prevent double-destruction on handing out this pointer in ctor * PR feedback - primarily to hide/downplay the need to support Xaml with two-phase init * should Release on exception * remove unnecessary test case * PR feedback * use smart pointer instead of raw delete --- cppwinrt/component_writers.h | 2 + nuget/readme.md | 35 ++++++ strings/base_implements.h | 35 +++++- test/test/initialize.cpp | 119 ++++++++++++++++++ test/test/test.vcxproj | 1 + vsix/ItemTemplates/BlankPage/BlankPage.cpp | 5 - vsix/ItemTemplates/BlankPage/BlankPage.h | 6 +- .../BlankUserControl/BlankUserControl.cpp | 5 - .../BlankUserControl/BlankUserControl.h | 6 +- .../VC/Windows Universal/BlankApp/App.cpp | 3 +- .../VC/Windows Universal/BlankApp/App.h | 1 - .../Windows Universal/BlankApp/MainPage.cpp | 5 - .../VC/Windows Universal/BlankApp/MainPage.h | 6 +- 13 files changed, 202 insertions(+), 27 deletions(-) create mode 100644 test/test/initialize.cpp diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index f562dabef..fcb9f5ac7 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -860,7 +860,9 @@ catch (...) { return winrt::to_hresult(); } { auto format = R"( #if defined(WINRT_FORCE_INCLUDE_%_XAML_G_H) || __has_include("%.xaml.g.h") + #include "%.xaml.g.h" + #else namespace winrt::@::implementation diff --git a/nuget/readme.md b/nuget/readme.md index 566a4fd18..4d925d06d 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -77,6 +77,41 @@ To customize common C++/WinRT project properties: * expand the Common Properties item * select the C++/WinRT property page +## InitializeComponent + +In older versions of C++/WinRT, Xaml objects called InitializeComponent from constructors. This can lead to memory corruption if InitializeComponent throws an exception. + +```cpp +void MainPage::MainPage() +{ + // This pattern should no longer be used + InitializeComponent(); +} +``` + +C++/WinRT now calls InitializeComponent automatically and safely, after object construction. Explicit calls to InitializeComponent from constructors in existing code should now be removed. Multiple calls to InitializeComponent are idempotent. + +If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent: + +```cpp +void MainPage::InitializeComponent() +{ + // Call base InitializeComponent() to register with the Xaml runtime + MainPageT::InitializeComponent(); + // Can now access Xaml properties + MyButton().Content(box_value(L"Click")); +} +``` + +A non-Xaml object can also participate in two-phase construction by defining an InitializeComponent method. + +```cpp +void MyComponent::InitializeComponent() +{ + // Execute initialization logic that may throw +} +``` + ## Troubleshooting The msbuild verbosity level maps to msbuild message importance as follows: diff --git a/strings/base_implements.h b/strings/base_implements.h index e2c6f3a12..212f2ecf7 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1218,6 +1218,29 @@ namespace winrt::impl }; #endif + template + class has_initializer + { + template ().InitializeComponent())> static constexpr bool get_value(int) { return true; } + template static constexpr bool get_value(...) { return false; } + + public: + static constexpr bool value = get_value(0); + }; + + template + T* create_and_initialize(Args&&... args) + { + com_ptr instance{ new heap_implements(std::forward(args)...), take_ownership_from_abi }; + + if constexpr (has_initializer::value) + { + instance->InitializeComponent(); + } + + return instance.detach(); + } + inline com_ptr get_static_lifetime_map() { auto const lifetime_factory = get_activation_factory(L"Windows.ApplicationModel.Core.CoreApplication"); @@ -1233,7 +1256,7 @@ namespace winrt::impl if constexpr (!has_static_lifetime_v) { - return { to_abi(new heap_implements), take_ownership_from_abi }; + return { to_abi(create_and_initialize()), take_ownership_from_abi }; } else { @@ -1247,7 +1270,7 @@ namespace winrt::impl return { result, take_ownership_from_abi }; } - result_type object{ to_abi(new heap_implements), take_ownership_from_abi }; + result_type object{ to_abi(create_and_initialize()), take_ownership_from_abi }; static slim_mutex lock; slim_lock_guard const guard{ lock }; @@ -1293,17 +1316,17 @@ WINRT_EXPORT namespace winrt } else if constexpr (impl::has_composable::value) { - impl::com_ref result{ to_abi(new impl::heap_implements(std::forward(args)...)), take_ownership_from_abi }; + impl::com_ref result{ to_abi(impl::create_and_initialize(std::forward(args)...)), take_ownership_from_abi }; return result.template as(); } else if constexpr (impl::has_class_type::value) { static_assert(std::is_same_v>); - return typename D::class_type{ to_abi(new impl::heap_implements(std::forward(args)...)), take_ownership_from_abi }; + return typename D::class_type{ to_abi(impl::create_and_initialize(std::forward(args)...)), take_ownership_from_abi }; } else { - return impl::com_ref{ to_abi(new impl::heap_implements(std::forward(args)...)), take_ownership_from_abi }; + return impl::com_ref{ to_abi(impl::create_and_initialize(std::forward(args)...)), take_ownership_from_abi }; } } @@ -1325,7 +1348,7 @@ WINRT_EXPORT namespace winrt } else { - return { new impl::heap_implements(std::forward(args)...), take_ownership_from_abi }; + return { impl::create_and_initialize(std::forward(args)...), take_ownership_from_abi }; } } diff --git a/test/test/initialize.cpp b/test/test/initialize.cpp new file mode 100644 index 000000000..dbd95c3fe --- /dev/null +++ b/test/test/initialize.cpp @@ -0,0 +1,119 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; + +namespace +{ + class some_exception : public std::exception + { + public: + some_exception() noexcept + : exception("some_exception", 1) + { + } + }; + + template + struct InitializeT : implements + { + bool& m_initialize_called; + + InitializeT(bool& initialize_called) : m_initialize_called(initialize_called) + { + } + + ~InitializeT() + { + } + + void InitializeComponent() + { + m_initialize_called = true; + throw some_exception(); + } + + hstring ToString() + { + return {}; + } + }; + + struct Initialize : InitializeT + { + Initialize(bool& initialize_called) : InitializeT(initialize_called) + { + } + }; + + struct ThrowingDerived : InitializeT + { + ThrowingDerived(bool& initialize_called) : InitializeT(initialize_called) + { + throw some_exception(); + } + }; + + struct OverriddenInitialize : InitializeT + { + OverriddenInitialize(bool& initialize_called) : InitializeT(initialize_called) + { + } + + void InitializeComponent() + { + m_initialize_called = true; + } + }; +} + +TEST_CASE("initialize") +{ + // Ensure that failure to initialize is failure to instantiate, with no side effects + { + bool initialize_called{}; + bool exception_caught{}; + try + { + make(initialize_called); + } + catch (some_exception const&) + { + exception_caught = true; + } + REQUIRE(initialize_called); + REQUIRE(exception_caught); + } + + // Ensure that base is never initialized if exception thrown from derived/base constructor + { + bool initialize_called{}; + bool exception_caught{}; + try + { + make(initialize_called); + } + catch (some_exception const&) + { + exception_caught = true; + } + REQUIRE(!initialize_called); + REQUIRE(exception_caught); + } + + // Support for overriding initialization for post-processing (e.g., accessing Xaml properties) + { + bool initialize_called{}; + bool exception_caught{}; + try + { + make(initialize_called); + } + catch (some_exception const&) + { + exception_caught = true; + } + REQUIRE(initialize_called); + REQUIRE(!exception_caught); + } +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index dc6c96cea..8a570d258 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -369,6 +369,7 @@ + NotUsing NotUsing diff --git a/vsix/ItemTemplates/BlankPage/BlankPage.cpp b/vsix/ItemTemplates/BlankPage/BlankPage.cpp index 9af284cec..7410a619b 100644 --- a/vsix/ItemTemplates/BlankPage/BlankPage.cpp +++ b/vsix/ItemTemplates/BlankPage/BlankPage.cpp @@ -9,11 +9,6 @@ using namespace Windows::UI::Xaml; namespace winrt::$rootnamespace$::implementation { - $safeitemname$::$safeitemname$() - { - InitializeComponent(); - } - int32_t $safeitemname$::MyProperty() { throw hresult_not_implemented(); diff --git a/vsix/ItemTemplates/BlankPage/BlankPage.h b/vsix/ItemTemplates/BlankPage/BlankPage.h index f1dc903e8..58c0f3648 100644 --- a/vsix/ItemTemplates/BlankPage/BlankPage.h +++ b/vsix/ItemTemplates/BlankPage/BlankPage.h @@ -6,7 +6,11 @@ namespace winrt::$rootnamespace$::implementation { struct $safeitemname$ : $safeitemname$T<$safeitemname$> { - $safeitemname$(); + $safeitemname$() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); diff --git a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.cpp b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.cpp index 9af284cec..7410a619b 100644 --- a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.cpp +++ b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.cpp @@ -9,11 +9,6 @@ using namespace Windows::UI::Xaml; namespace winrt::$rootnamespace$::implementation { - $safeitemname$::$safeitemname$() - { - InitializeComponent(); - } - int32_t $safeitemname$::MyProperty() { throw hresult_not_implemented(); diff --git a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h index 7b994b1df..0ab08377a 100644 --- a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h +++ b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h @@ -10,7 +10,11 @@ namespace winrt::$rootnamespace$::implementation { struct $safeitemname$ : $safeitemname$T<$safeitemname$> { - $safeitemname$(); + $safeitemname$() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.cpp b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.cpp index 8806e25cb..2f3132d65 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.cpp +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.cpp @@ -14,12 +14,11 @@ using namespace $safeprojectname$; using namespace $safeprojectname$::implementation; /// -/// Initializes the singleton application object. This is the first line of authored code +/// Creates the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). /// App::App() { - InitializeComponent(); Suspending({ this, &App::OnSuspending }); #if defined _DEBUG && !defined DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.h b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.h index 8208308c8..b7fe65ef7 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.h +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/App.h @@ -6,7 +6,6 @@ namespace winrt::$safeprojectname$::implementation struct App : AppT { App(); - void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&); void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&); void OnNavigationFailed(IInspectable const&, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const&); diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.cpp b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.cpp index 5caaa46e6..af94324c3 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.cpp +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.cpp @@ -7,11 +7,6 @@ using namespace Windows::UI::Xaml; namespace winrt::$safeprojectname$::implementation { - MainPage::MainPage() - { - InitializeComponent(); - } - int32_t MainPage::MyProperty() { throw hresult_not_implemented(); diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h index 96c433917..92e0a689d 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h @@ -6,7 +6,11 @@ namespace winrt::$safeprojectname$::implementation { struct MainPage : MainPageT { - MainPage(); + MainPage() + { + // Xaml objects should not call InitializeComponent during construction. + // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent + } int32_t MyProperty(); void MyProperty(int32_t value); From c4a8e24472cd652a6f85a8f71180d5ccc2569de5 Mon Sep 17 00:00:00 2001 From: Duncan Horn <40036384+dunhor@users.noreply.github.com> Date: Sat, 9 Apr 2022 07:11:45 -0700 Subject: [PATCH 105/305] Update C++/WinRT to consider the full contract version history for fast ABI (#1132) --- cppwinrt/helpers.h | 274 ++++++++++++++++-- test/test_component_fast/Nomadic.cpp | 35 +++ test/test_component_fast/Nomadic.h | 24 ++ .../test_component_fast.idl | 74 +++++ .../test_component_fast.vcxproj | 2 + test/test_fast/Nomadic.cpp | 36 +++ test/test_fast/test_fast.vcxproj | 1 + 7 files changed, 427 insertions(+), 19 deletions(-) create mode 100644 test/test_component_fast/Nomadic.cpp create mode 100644 test/test_component_fast/Nomadic.h create mode 100644 test/test_fast/Nomadic.cpp diff --git a/cppwinrt/helpers.h b/cppwinrt/helpers.h index 22854c48e..b2d783d61 100644 --- a/cppwinrt/helpers.h +++ b/cppwinrt/helpers.h @@ -80,7 +80,7 @@ namespace cppwinrt // by the caller and callee. The exception to this rule is property setters where the callee may simply store a // reference to the collection. The collection thus becomes async in the sense that it is expected to remain // valid beyond the duration of the call. - + if (is_put_overload(m_method)) { return true; @@ -148,10 +148,54 @@ namespace cppwinrt return static_cast(get_attribute(row, type_namespace, type_name)); } + namespace impl + { + template + struct variant_index; + + template + struct variant_index + { + static constexpr bool found = std::is_same_v; + static constexpr std::size_t value = std::conditional_t, + variant_index>::value + (found ? 0 : 1); + }; + } + + template + struct variant_index; + + template + struct variant_index, T> : impl::variant_index + { + }; + + template + constexpr std::size_t variant_index_v = variant_index::value; + + template + auto get_integer_attribute(FixedArgSig const& signature) + { + auto variant = std::get(signature.value).value; + switch (variant.index()) + { + case variant_index_v>: return static_cast(std::get>(variant)); + case variant_index_v>: return static_cast(std::get>(variant)); + default: return std::get(variant); // Likely throws, but that's intentional + } + } + + template + auto get_attribute_value(FixedArgSig const& signature) + { + return std::get(std::get(signature.value).value); + } + template auto get_attribute_value(CustomAttribute const& attribute, uint32_t const arg) { - return std::get(std::get(attribute.Value().FixedArgs()[arg].value).value); + return get_attribute_value(attribute.Value().FixedArgs()[arg]); } static auto get_abi_name(MethodDef const& method) @@ -283,33 +327,200 @@ namespace cppwinrt return bases; } - static std::pair get_version(TypeDef const& type) + struct contract_version + { + std::string_view name; + uint32_t version; + }; + + struct previous_contract + { + std::string_view contract_from; + std::string_view contract_to; + uint32_t version_low; + uint32_t version_high; + }; + + struct contract_history + { + contract_version current_contract; + + // Sorted such that the first entry is the first contract the type was introduced in + std::vector previous_contracts; + }; + + static contract_version decode_contract_version_attribute(CustomAttribute const& attribute) + { + // ContractVersionAttribute has three constructors, but only two we care about here: + // .ctor(string contract, uint32 version) + // .ctor(System.Type contract, uint32 version) + auto signature = attribute.Value(); + auto& args = signature.FixedArgs(); + assert(args.size() == 2); + + contract_version result{}; + result.version = get_integer_attribute(args[1]); + call(std::get(args[0].value).value, + [&](ElemSig::SystemType t) + { + result.name = t.name; + }, + [&](std::string_view name) + { + result.name = name; + }, + [](auto&&) + { + assert(false); + }); + + return result; + } + + static previous_contract decode_previous_contract_attribute(CustomAttribute const& attribute) { - uint32_t version{}; + // PreviousContractVersionAttribute has two constructors: + // .ctor(string fromContract, uint32 versionLow, uint32 versionHigh) + // .ctor(string fromContract, uint32 versionLow, uint32 versionHigh, string contractTo) + auto signature = attribute.Value(); + auto& args = signature.FixedArgs(); + assert(args.size() >= 3); + + previous_contract result{}; + result.contract_from = get_attribute_value(args[0]); + result.version_low = get_integer_attribute(args[1]); + result.version_high = get_integer_attribute(args[2]); + if (args.size() == 4) + { + result.contract_to = get_attribute_value(args[3]); + } + + return result; + } + static contract_version get_initial_contract_version(TypeDef const& type) + { + // Most types don't have previous contracts, so optimize for that scenario to avoid unnecessary allocations + contract_version current_contract{}; + + // The initial contract, assuming the type has moved contracts, is the only contract name that doesn't appear as + // a "to contract" argument to a PreviousContractVersionAttribute. Note that this assumes that a type does not + // "return" to a prior contract, however this is a restriction enforced by midlrt + std::vector previous_contracts; + std::vector to_contracts; for (auto&& attribute : type.CustomAttribute()) { - auto name = attribute.TypeNamespaceAndName(); + auto [ns, name] = attribute.TypeNamespaceAndName(); + if (ns != "Windows.Foundation.Metadata") + { + continue; + } - if (name.first != "Windows.Foundation.Metadata") + if (name == "ContractVersionAttribute") + { + assert(current_contract.name.empty()); + current_contract = decode_contract_version_attribute(attribute); + } + else if (name == "PreviousContractVersionAttribute") + { + auto prev = decode_previous_contract_attribute(attribute); + + // If this contract was the target of an earlier contract change, we know this isn't the initial one + if (std::find(to_contracts.begin(), to_contracts.end(), prev.contract_from) == to_contracts.end()) + { + previous_contracts.push_back(contract_version{ prev.contract_from, prev.version_low }); + } + + if (!prev.contract_to.empty()) + { + auto itr = std::find_if(previous_contracts.begin(), previous_contracts.end(), [&](auto const& ver) + { + return ver.name == prev.contract_to; + }); + if (itr != previous_contracts.end()) + { + *itr = previous_contracts.back(); + previous_contracts.pop_back(); + } + + to_contracts.push_back(prev.contract_to); + } + } + else if (name == "VersionAttribute") + { + // Prefer contract versioning, if present. Otherwise, use an empty contract name to indicate that this + // is not a contract version + if (current_contract.name.empty()) + { + current_contract.version = get_attribute_value(attribute, 0); + } + } + } + + if (!previous_contracts.empty()) + { + assert(previous_contracts.size() == 1); + return previous_contracts[0]; + } + + return current_contract; + } + + static contract_history get_contract_history(TypeDef const& type) + { + contract_history result{}; + for (auto&& attribute : type.CustomAttribute()) + { + auto [ns, name] = attribute.TypeNamespaceAndName(); + if (ns != "Windows.Foundation.Metadata") { continue; } - if (name.second == "ContractVersionAttribute") + if (name == "ContractVersionAttribute") { - version = get_attribute_value(attribute, 1); - break; + assert(result.current_contract.name.empty()); + result.current_contract = decode_contract_version_attribute(attribute); } + else if (name == "PreviousContractVersionAttribute") + { + result.previous_contracts.push_back(decode_previous_contract_attribute(attribute)); + } + // We could report the version that the type was introduced if the type is not contract versioned, however + // that information is not useful to us anywhere, so just skip it + } + + if (result.previous_contracts.empty()) + { + return result; + } + assert(!result.current_contract.name.empty()); - if (name.second == "VersionAttribute") + // There's no guarantee that the contract history will be sorted in metadata (in fact it's unlikely to be) + for (auto& prev : result.previous_contracts) + { + if (prev.contract_to.empty() || (prev.contract_to == result.current_contract.name)) { - version = get_attribute_value(attribute, 0); + // No 'to' contract indicates that this was the last contract before the current one + prev.contract_to = result.current_contract.name; + std::swap(prev, result.previous_contracts.back()); break; } } + assert(result.previous_contracts.back().contract_to == result.current_contract.name); + + for (size_t size = result.previous_contracts.size() - 1; size; --size) + { + auto& last = result.previous_contracts[size]; + auto itr = std::find_if(result.previous_contracts.begin(), result.previous_contracts.begin() + size, [&](auto const& prev) + { + return prev.contract_to == last.contract_from; + }); + assert(itr != result.previous_contracts.end()); + std::swap(*itr, result.previous_contracts[size - 1]); + } - return { HIWORD(version), LOWORD(version) }; + return result; } struct interface_info @@ -321,7 +532,11 @@ namespace cppwinrt bool base{}; bool exclusive{}; bool fastabi{}; - std::pair version{}; + // A pair of (relativeContract, version) where 'relativeContract' is the contract the interface was introduced + // in relative to the contract history of the class. E.g. if a class goes from contract 'A' to 'B' to 'C', + // 'relativeContract' would be '0' for an interface introduced in contract 'A', '1' for an interface introduced + // in contract 'B', etc. This is only set/valid for 'fastabi' interfaces + std::pair relative_version{}; std::vector> generic_param_stack{}; }; @@ -421,7 +636,6 @@ namespace cppwinrt } info.exclusive = has_attribute(info.type, "Windows.Foundation.Metadata", "ExclusiveToAttribute"); - info.version = get_version(info.type); get_interfaces_impl(w, result, info.defaulted, info.overridable, base, info.generic_param_stack, info.type.InterfaceImpl()); insert_or_assign(result, name, std::move(info)); } @@ -443,10 +657,32 @@ namespace cppwinrt return result; } - auto count = std::count_if(result.begin(), result.end(), [](auto&& pair) + auto history = get_contract_history(type); + size_t count = 0; + for (auto& pair : result) { - return pair.second.exclusive && !pair.second.base && !pair.second.overridable; - }); + if (pair.second.exclusive && !pair.second.base && !pair.second.overridable) + { + ++count; + + auto introduced = get_initial_contract_version(pair.second.type); + pair.second.relative_version.second = introduced.version; + + auto itr = std::find_if(history.previous_contracts.begin(), history.previous_contracts.end(), [&](previous_contract const& prev) + { + return prev.contract_from == introduced.name; + }); + if (itr != history.previous_contracts.end()) + { + pair.second.relative_version.first = static_cast(itr - history.previous_contracts.begin()); + } + else + { + assert(history.current_contract.name == introduced.name); + pair.second.relative_version.first = static_cast(history.previous_contracts.size()); + } + } + } std::partial_sort(result.begin(), result.begin() + count, result.end(), [](auto&& left_pair, auto&& right_pair) { @@ -482,9 +718,9 @@ namespace cppwinrt return left_enabled; } - if (left.version != right.version) + if (left.relative_version != right.relative_version) { - return left.version < right.version; + return left.relative_version < right.relative_version; } return left_pair.first < right_pair.first; diff --git a/test/test_component_fast/Nomadic.cpp b/test/test_component_fast/Nomadic.cpp new file mode 100644 index 000000000..e2d5c8af5 --- /dev/null +++ b/test/test_component_fast/Nomadic.cpp @@ -0,0 +1,35 @@ +#include "pch.h" +#include "Nomadic.h" +#include "Nomadic.g.cpp" + +namespace winrt::test_component_fast::implementation +{ + hstring Nomadic::FirstMethod() + { + return L"FirstMethod"; + } + hstring Nomadic::SecondMethod() + { + return L"SecondMethod"; + } + hstring Nomadic::ThirdMethod() + { + return L"ThirdMethod"; + } + hstring Nomadic::FourthMethod() + { + return L"FourthMethod"; + } + hstring Nomadic::FifthMethod() + { + return L"FifthMethod"; + } + hstring Nomadic::SixthMethod() + { + return L"SixthMethod"; + } + hstring Nomadic::SeventhMethod() + { + return L"SeventhMethod"; + } +} diff --git a/test/test_component_fast/Nomadic.h b/test/test_component_fast/Nomadic.h new file mode 100644 index 000000000..65448b967 --- /dev/null +++ b/test/test_component_fast/Nomadic.h @@ -0,0 +1,24 @@ +#pragma once +#include "Nomadic.g.h" + +namespace winrt::test_component_fast::implementation +{ + struct Nomadic : NomadicT + { + Nomadic() = default; + + hstring FirstMethod(); + hstring SecondMethod(); + hstring ThirdMethod(); + hstring FourthMethod(); + hstring FifthMethod(); + hstring SixthMethod(); + hstring SeventhMethod(); + }; +} +namespace winrt::test_component_fast::factory_implementation +{ + struct Nomadic : NomadicT + { + }; +} diff --git a/test/test_component_fast/test_component_fast.idl b/test/test_component_fast/test_component_fast.idl index ad7f89ce4..915eec49d 100644 --- a/test/test_component_fast/test_component_fast.idl +++ b/test/test_component_fast/test_component_fast.idl @@ -42,6 +42,80 @@ namespace test_component_fast } } + [contractversion(10)] + apicontract FirstContract{}; + + [contractversion(10)] + apicontract SecondContract{}; + + [contractversion(10)] + apicontract ThirdContract{}; + + [contractversion(10)] + apicontract FourthContract{}; + + [fastabi2(ThirdContract, 3)] + [from_contract(FirstContract, range(1, 10), SecondContract)] + [from_contract(SecondContract, range(1, 10), ThirdContract)] + [from_contract(ThirdContract, range(1, 10))] + [contract(FourthContract, 1)] + runtimeclass Nomadic + { + Nomadic(); + + /* NOTE: There seems to be a bug in midlrt where 'INomadicSeventh' and 'INomadicEighth' are both versioned to + 1.0 (when the class was added to the contract) in metadata. The interface impl list has the correct + contract versions, however this trips us up since we only look at the version of the interface + [interface_name("INomadicEighth")] + [contract(FourthContract, 2.1)] + { + String EighthMethod(); + } + */ + + [interface_name("INomadicSeventh")] + [contract(FourthContract, 1.2)] + { + String SeventhMethod(); + } + + [interface_name("INomadicSixth")] + [contract(ThirdContract, 4.3)] + { + String SixthMethod(); + } + + [interface_name("INomadicFifth")] + [contract(ThirdContract, 3.4)] + { + String FifthMethod(); + } + + [interface_name("INomadicFourth")] + [contract(SecondContract, 6.5)] + { + String FourthMethod(); + } + + [interface_name("INomadicThird")] + [contract(SecondContract, 5.6)] + { + String ThirdMethod(); + } + + [interface_name("INomadicSecond")] + [contract(FirstContract, 8.7)] + { + String SecondMethod(); + } + + [interface_name("INomadicFirst")] + [contract(FirstContract, 7.8)] + { + String FirstMethod(); + } + } + namespace Composition { [contractversion(4)] diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index 9f42be8e3..8cc4739b1 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -617,6 +617,7 @@ + @@ -628,6 +629,7 @@ + diff --git a/test/test_fast/Nomadic.cpp b/test/test_fast/Nomadic.cpp new file mode 100644 index 000000000..98753c06d --- /dev/null +++ b/test/test_fast/Nomadic.cpp @@ -0,0 +1,36 @@ +#include "pch.h" +#include "winrt/test_component_fast.h" +#include + +using namespace winrt; +using namespace test_component_fast; + +hstring invoke_by_interface_vtable_offset(Nomadic const& nomadic, ptrdiff_t offset) +{ + // NOTE: Behavior guaranteed by Windows ABI; see the "C style interface" for WinRT/COM types for more info. Note + // that IInspectable has 6 functions in total (including those inherited from IUnknown) + auto insp = static_cast<::IInspectable*>(get_abi(nomadic)); + auto vtable = *reinterpret_cast(insp); + auto fn_ptr = static_cast(vtable[6 + offset]); + + HSTRING hstr; + check_hresult(fn_ptr(insp, &hstr)); + + hstring result; + attach_abi(result, hstr); + return result; +} + +TEST_CASE("Nomadic") +{ + impl::get_diagnostics_info().detach(); + + Nomadic n; + REQUIRE(invoke_by_interface_vtable_offset(n, 0) == L"FirstMethod"); + REQUIRE(invoke_by_interface_vtable_offset(n, 1) == L"SecondMethod"); + REQUIRE(invoke_by_interface_vtable_offset(n, 2) == L"ThirdMethod"); + REQUIRE(invoke_by_interface_vtable_offset(n, 3) == L"FourthMethod"); + REQUIRE(invoke_by_interface_vtable_offset(n, 4) == L"FifthMethod"); + REQUIRE(invoke_by_interface_vtable_offset(n, 5) == L"SixthMethod"); + REQUIRE(invoke_by_interface_vtable_offset(n, 6) == L"SeventhMethod"); +} diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj index dbf3d9b8b..c256cad6b 100644 --- a/test/test_fast/test_fast.vcxproj +++ b/test/test_fast/test_fast.vcxproj @@ -283,6 +283,7 @@ NotUsing + Create From 959ae02c71d65763f7ee13c182509fafd41f80b6 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Thu, 21 Apr 2022 07:13:45 -0700 Subject: [PATCH 106/305] Use `auto` trick to catch missing header files for `auto_revoke` (#1136) --- cppwinrt/code_writers.h | 23 ++++++++--------------- cppwinrt/component_writers.h | 8 ++++---- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index adf9a1392..7122e9541 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1001,7 +1001,7 @@ namespace cppwinrt if (is_add_overload(method)) { auto format = R"( using %_revoker = impl::event_revoker<%, &impl::abi_t<%>::remove_%>; - [[nodiscard]] %_revoker %(auto_revoke_t, %) const; + [[nodiscard]] auto %(auto_revoke_t, %) const; )"; w.write(format, @@ -1010,7 +1010,6 @@ namespace cppwinrt type, method_name, method_name, - method_name, bind(signature)); } } @@ -1170,7 +1169,7 @@ namespace cppwinrt if (is_add_overload(method)) { - format = R"( template typename consume_%::%_revoker consume_%::%(auto_revoke_t, %) const + format = R"( template auto consume_%::%(auto_revoke_t, %) const { return impl::make_event_revoker(this, %(%)); } @@ -1181,9 +1180,6 @@ namespace cppwinrt type_impl_name, bind(generics), method_name, - type_impl_name, - bind(generics), - method_name, bind(signature), method_name, method_name, @@ -1214,15 +1210,13 @@ namespace cppwinrt if (is_add_overload(method)) { - format = R"( inline %::%_revoker %::%(auto_revoke_t, %) const + format = R"( inline auto %::%(auto_revoke_t, %) const { return impl::make_event_revoker(this, %(%)); } )"; w.write(format, - class_type.TypeName(), - method_name, class_type.TypeName(), method_name, bind(signature), @@ -3017,7 +3011,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (is_add_overload(method)) { auto format = R"( using %_revoker = impl::factory_event_revoker<%, &impl::abi_t<%>::remove_%>; - [[nodiscard]] static %_revoker %(auto_revoke_t, %); + [[nodiscard]] static auto %(auto_revoke_t, %); )"; w.write(format, @@ -3026,7 +3020,6 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable factory.second.type, method_name, method_name, - method_name, bind(signature)); } } @@ -3056,21 +3049,21 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (is_add_overload(method)) { - auto format = R"( inline %::%_revoker %::%(auto_revoke_t, %) + auto format = R"( inline auto %::%(auto_revoke_t, %) { auto f = get_activation_factory<%, %>(); - return { f, f.%(%) }; + return %::%_revoker{ f, f.%(%) }; } )"; w.write(format, - type_name, - method_name, type_name, method_name, bind(signature), type_name, factory, + type_name, + method_name, method_name, bind(signature)); } diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index fcb9f5ac7..98bc75720 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -518,22 +518,22 @@ catch (...) { return winrt::to_hresult(); } if (is_add_overload(method)) { - auto format = R"( %::%_revoker %::%(auto_revoke_t, %) + auto format = R"( auto %::%(auto_revoke_t, %) { auto f = make().as<%>(); - return { f, f.%(%) }; + return %::%_revoker{ f, f.%(%) }; } )"; w.write(format, - type_name, - method_name, type_name, method_name, bind(signature), type_namespace, type_name, factory_name, + type_name, + method_name, method_name, bind(signature)); } From 0058881c879b5f7a56e5d3928d1e42faff72bc41 Mon Sep 17 00:00:00 2001 From: David Fields <18537467+dfields-msft@users.noreply.github.com> Date: Fri, 20 May 2022 08:08:40 -0700 Subject: [PATCH 107/305] Test whether SDKManifest.xml exists before attempting to read it (#1146) --- cppwinrt/cmd_reader.h | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cppwinrt/cmd_reader.h b/cppwinrt/cmd_reader.h index e50f66036..c86cfdcc6 100644 --- a/cppwinrt/cmd_reader.h +++ b/cppwinrt/cmd_reader.h @@ -71,17 +71,31 @@ namespace cppwinrt } } + enum class xml_requirement + { + required = 0, + optional + }; + inline void add_files_from_xml( std::set& files, std::string const& sdk_version, std::filesystem::path const& xml_path, - std::filesystem::path const& sdk_path) + std::filesystem::path const& sdk_path, + xml_requirement xml_path_requirement) { com_ptr stream; - check_xml(SHCreateStreamOnFileW( + auto streamResult = SHCreateStreamOnFileW( xml_path.c_str(), - STGM_READ, &stream.ptr)); + STGM_READ, &stream.ptr); + if (xml_path_requirement == xml_requirement::optional && + (streamResult == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || + streamResult == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND))) + { + return; + } + check_xml(streamResult); com_ptr reader; @@ -462,7 +476,7 @@ namespace cppwinrt xml_path /= sdk_version; xml_path /= L"Platform.xml"; - add_files_from_xml(files, sdk_version, xml_path, sdk_path); + add_files_from_xml(files, sdk_version, xml_path, sdk_path, xml_requirement::required); if (path.back() != '+') { @@ -474,7 +488,8 @@ namespace cppwinrt xml_path = item.path() / sdk_version; xml_path /= L"SDKManifest.xml"; - add_files_from_xml(files, sdk_version, xml_path, sdk_path); + // Not all Extension SDKs include an SDKManifest.xml file; ignore those which do not (e.g. WindowsIoT). + add_files_from_xml(files, sdk_version, xml_path, sdk_path, xml_requirement::optional); } continue; From dcea885fd470786cb1a4c75f1bd881d000d6b329 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 24 May 2022 14:58:47 -0700 Subject: [PATCH 108/305] Add support for composed implementations of IComponentConnector (#1149) * add support for composed implementations of IComponentConnector * document ComponentConnectorT helper * revert change for deriving without interfaces - creates other breaks and very atypical scenario * pr feedback * pr feedback * pr feedback * http://slashslash.info/petition/ compliance --- cppwinrt/code_writers.h | 8 ++ cppwinrt/component_writers.h | 1 + cppwinrt/cppwinrt.vcxproj | 3 +- cppwinrt/cppwinrt.vcxproj.filters | 15 ++-- nuget/readme.md | 8 ++ strings/base_implements.h | 98 +++++++++++++++++++------ strings/base_xaml_component_connector.h | 53 +++++++++++++ 7 files changed, 157 insertions(+), 29 deletions(-) create mode 100644 strings/base_xaml_component_connector.h diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 7122e9541..e6122a514 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3270,6 +3270,14 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable { w.write(strings::base_xaml_typename); } + else if (namespace_name == "Windows.UI.Xaml.Markup") + { + w.write(strings::base_xaml_component_connector, "Windows"); + } + else if (namespace_name == "Microsoft.UI.Xaml.Markup") + { + w.write(strings::base_xaml_component_connector, "Microsoft"); + } } static void write_namespace_special_1(writer& w, std::string_view const& namespace_name) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 98bc75720..8521a777e 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -797,6 +797,7 @@ catch (...) { return winrt::to_hresult(); } } else { + composable_base_name = w.write_temp("using composable_base = B;"); base_type_parameter = ", typename B"; base_type_argument = ", B"; no_module_lock = "no_module_lock, "; diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 81b6703ef..391fda68f 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -54,9 +54,9 @@ + - @@ -88,6 +88,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index dfe1488ee..9033a34a8 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -64,9 +64,6 @@ strings - - strings - strings @@ -163,9 +160,6 @@ strings - - strings - strings @@ -175,6 +169,15 @@ strings + + strings + + + strings + + + strings + diff --git a/nuget/readme.md b/nuget/readme.md index 4d925d06d..cc27391ec 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -112,6 +112,14 @@ void MyComponent::InitializeComponent() } ``` +***[Windows|Microsoft]::UI::Xaml::Markup::ComponentConnectorT*** + +A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implemenation for these interfaces: + +```cpp + struct DerivedPage : winrt::Windows::UI::Xaml::Markup::ComponentConnectorT> +``` + ## Troubleshooting The msbuild verbosity level maps to msbuild message importance as follows: diff --git a/strings/base_implements.h b/strings/base_implements.h index 212f2ecf7..53826d6b6 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -253,24 +253,24 @@ namespace winrt::impl template <> struct interface_list<> { - template - static constexpr void* find(const T*, const Predicate&) noexcept + template + static constexpr auto find(Traits const& traits) noexcept { - return nullptr; + return traits.not_found(); } }; template struct interface_list { - template - static constexpr void* find(const T* obj, const Predicate& pred) noexcept + template + static constexpr auto find(Traits const& traits) noexcept { - if (pred.template test()) + if (traits.template test()) { - return to_abi(obj); + return traits.template found(); } - return interface_list::find(obj, pred); + return interface_list::find(traits); } using first_interface = First; }; @@ -362,34 +362,88 @@ namespace winrt::impl using type = typename implements_default_interface::type; }; - struct iid_finder + template + struct find_iid_traits { - const guid& m_guid; + T const* m_object; + guid const& m_guid; template constexpr bool test() const noexcept { return is_guid_of::type>(m_guid); } + + template + constexpr void* found() const noexcept + { + return to_abi(m_object); + } + + static constexpr void* not_found() noexcept + { + return nullptr; + } }; template - auto find_iid(const T* obj, const guid& iid) noexcept + auto find_iid(T const* obj, guid const& iid) noexcept { - return static_cast(implemented_interfaces::find(obj, iid_finder{ iid })); + return static_cast(implemented_interfaces::find(find_iid_traits{ obj, iid })); } - struct inspectable_finder + template + struct has_interface_traits { + template + constexpr bool test() const noexcept + { + return std::is_same_v; + } + + template + static constexpr bool found() noexcept + { + return true; + } + + static constexpr bool not_found() noexcept + { + return false; + } + }; + + template + constexpr bool has_interface() noexcept + { + return impl::implemented_interfaces::find(has_interface_traits{}); + } + + template + struct find_inspectable_traits + { + T const* m_object; + template static constexpr bool test() noexcept { return std::is_base_of_v>; } + + template + constexpr void* found() const noexcept + { + return to_abi(m_object); + } + + static constexpr void* not_found() noexcept + { + return nullptr; + } }; template - inspectable_abi* find_inspectable(const T* obj) noexcept + inspectable_abi* find_inspectable(T const* obj) noexcept { using default_interface = typename implements_default_interface::type; @@ -399,7 +453,7 @@ namespace winrt::impl } else { - return static_cast(implemented_interfaces::find(obj, inspectable_finder{})); + return static_cast(implemented_interfaces::find(find_inspectable_traits{ obj })); } } @@ -502,7 +556,7 @@ namespace winrt::impl template struct produce : produce_base { - int32_t __stdcall QueryInterface(const guid& id, void** object) noexcept final + int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { return this->shim().NonDelegatingQueryInterface(id, object); } @@ -910,7 +964,7 @@ namespace winrt::impl return target; } - int32_t __stdcall NonDelegatingQueryInterface(const guid& id, void** object) noexcept + int32_t __stdcall NonDelegatingQueryInterface(guid const& id, void** object) noexcept { if (is_guid_of(id) || is_guid_of(id)) { @@ -932,13 +986,13 @@ namespace winrt::impl int32_t __stdcall NonDelegatingGetIids(uint32_t* count, guid** array) noexcept { - const auto& local_iids = static_cast(this)->get_local_iids(); - const uint32_t& local_count = local_iids.first; + auto const& local_iids = static_cast(this)->get_local_iids(); + uint32_t const& local_count = local_iids.first; if constexpr (root_implements_type::is_composing) { if (local_count > 0) { - const com_array& inner_iids = get_interfaces(root_implements_type::m_inner); + com_array const& inner_iids = get_interfaces(root_implements_type::m_inner); *count = local_count + inner_iids.size(); *array = static_cast(WINRT_IMPL_CoTaskMemAlloc(sizeof(guid)*(*count))); if (*array == nullptr) @@ -1189,7 +1243,7 @@ namespace winrt::impl } virtual unknown_abi* get_unknown() const noexcept = 0; - virtual std::pair get_local_iids() const noexcept = 0; + virtual std::pair get_local_iids() const noexcept = 0; virtual hstring GetRuntimeClassName() const = 0; virtual void* find_interface(guid const&) const noexcept = 0; virtual inspectable_abi* find_inspectable() const noexcept = 0; @@ -1450,7 +1504,7 @@ WINRT_EXPORT namespace winrt return impl::find_inspectable(static_cast(this)); } - std::pair get_local_iids() const noexcept override + std::pair get_local_iids() const noexcept override { using interfaces = impl::uncloaked_interfaces; using local_iids = impl::uncloaked_iids; diff --git a/strings/base_xaml_component_connector.h b/strings/base_xaml_component_connector.h new file mode 100644 index 000000000..ac2edf807 --- /dev/null +++ b/strings/base_xaml_component_connector.h @@ -0,0 +1,53 @@ + +WINRT_EXPORT namespace winrt::%::UI::Xaml::Markup +{ + template + struct ComponentConnectorT : D + { + using composable_base = typename D::composable_base; + + void InitializeComponent() + { + if constexpr (m_has_connectable_base) + { + m_dispatch_base = true; + composable_base::InitializeComponent(); + m_dispatch_base = false; + } + D::InitializeComponent(); + } + + void Connect(int32_t connectionId, Windows::Foundation::IInspectable const& target) + { + if constexpr (m_has_connectable_base) + { + if (m_dispatch_base) + { + composable_base::Connect(connectionId, target); + return; + } + } + D::Connect(connectionId, target); + } + + auto GetBindingConnector(int32_t connectionId, Windows::Foundation::IInspectable const& target) + { + if constexpr (m_has_connectable_base) + { + if (m_dispatch_base) + { + return composable_base::GetBindingConnector(connectionId, target); + } + } + return D::GetBindingConnector(connectionId, target); + } + + private: + static constexpr bool m_has_connectable_base{ + impl::has_initializer::value && + impl::has_interface() && + impl::has_interface() }; + + bool m_dispatch_base{}; + }; +} From a54d678bb4794b0727b23eb24846f99e56eaa77f Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 7 Jun 2022 15:06:03 -0700 Subject: [PATCH 109/305] IComponentConnector2 doesn't exist in WinUI (#1156) * IComponentConnector2 doesn't exist in WinUI * added new header --- cppwinrt/code_writers.h | 4 +- cppwinrt/cppwinrt.vcxproj | 1 + cppwinrt/cppwinrt.vcxproj.filters | 3 ++ strings/base_xaml_component_connector.h | 2 +- strings/base_xaml_component_connector_winui.h | 52 +++++++++++++++++++ 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 strings/base_xaml_component_connector_winui.h diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index e6122a514..1781ebe61 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3272,11 +3272,11 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable } else if (namespace_name == "Windows.UI.Xaml.Markup") { - w.write(strings::base_xaml_component_connector, "Windows"); + w.write(strings::base_xaml_component_connector); } else if (namespace_name == "Microsoft.UI.Xaml.Markup") { - w.write(strings::base_xaml_component_connector, "Microsoft"); + w.write(strings::base_xaml_component_connector_winui); } } diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 391fda68f..946152619 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -89,6 +89,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 9033a34a8..3176b206f 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -178,6 +178,9 @@ strings + + strings + diff --git a/strings/base_xaml_component_connector.h b/strings/base_xaml_component_connector.h index ac2edf807..16478f7a2 100644 --- a/strings/base_xaml_component_connector.h +++ b/strings/base_xaml_component_connector.h @@ -1,5 +1,5 @@ -WINRT_EXPORT namespace winrt::%::UI::Xaml::Markup +WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup { template struct ComponentConnectorT : D diff --git a/strings/base_xaml_component_connector_winui.h b/strings/base_xaml_component_connector_winui.h new file mode 100644 index 000000000..9a84cc11d --- /dev/null +++ b/strings/base_xaml_component_connector_winui.h @@ -0,0 +1,52 @@ + +WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup +{ + template + struct ComponentConnectorT : D + { + using composable_base = typename D::composable_base; + + void InitializeComponent() + { + if constexpr (m_has_connectable_base) + { + m_dispatch_base = true; + composable_base::InitializeComponent(); + m_dispatch_base = false; + } + D::InitializeComponent(); + } + + void Connect(int32_t connectionId, Windows::Foundation::IInspectable const& target) + { + if constexpr (m_has_connectable_base) + { + if (m_dispatch_base) + { + composable_base::Connect(connectionId, target); + return; + } + } + D::Connect(connectionId, target); + } + + auto GetBindingConnector(int32_t connectionId, Windows::Foundation::IInspectable const& target) + { + if constexpr (m_has_connectable_base) + { + if (m_dispatch_base) + { + return composable_base::GetBindingConnector(connectionId, target); + } + } + return D::GetBindingConnector(connectionId, target); + } + + private: + static constexpr bool m_has_connectable_base{ + impl::has_initializer::value && + impl::has_interface() }; + + bool m_dispatch_base{}; + }; +} From 4f0be70254efab15530feaf5fb4894ff56fe8617 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Wed, 8 Jun 2022 15:05:47 -0700 Subject: [PATCH 110/305] Static events should not use the auto trick (#1158) The same way we don't use the auto trick for static properties and static methods. --- cppwinrt/code_writers.h | 38 ++++++++++++++++++++++++++--------- cppwinrt/component_writers.h | 4 +++- test/test_component/Class.cpp | 7 +++++++ 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 1781ebe61..748996b1a 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2986,13 +2986,15 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable return; } + auto is_opt_type = settings.component_opt && settings.component_filter.includes(type); + for (auto&& method : factory.second.type.MethodList()) { method_signature signature{ method }; auto method_name = get_name(method); auto async_types_guard = w.push_async_types(signature.is_async()); - if (settings.component_opt && settings.component_filter.includes(type)) + if (is_opt_type) { w.write(" %static % %(%);\n", is_get_overload(method) ? "[[nodiscard]] " : "", @@ -3010,17 +3012,33 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (is_add_overload(method)) { - auto format = R"( using %_revoker = impl::factory_event_revoker<%, &impl::abi_t<%>::remove_%>; - [[nodiscard]] static auto %(auto_revoke_t, %); + { + auto format = R"( using %_revoker = impl::factory_event_revoker<%, &impl::abi_t<%>::remove_%>; )"; + w.write(format, + method_name, + factory.second.type, + factory.second.type, + method_name); + } - w.write(format, - method_name, - factory.second.type, - factory.second.type, - method_name, - method_name, - bind(signature)); + if (is_opt_type) + { + auto format = R"( [[nodiscard]] static %_revoker %(auto_revoke_t, %); +)"; + w.write(format, + method_name, + method_name, + bind(signature)); + } + else + { + auto format = R"( [[nodiscard]] static auto %(auto_revoke_t, %); +)"; + w.write(format, + method_name, + bind(signature)); + } } } } diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 8521a777e..acd2b871c 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -518,7 +518,7 @@ catch (...) { return winrt::to_hresult(); } if (is_add_overload(method)) { - auto format = R"( auto %::%(auto_revoke_t, %) + auto format = R"( %::%_revoker %::%(auto_revoke_t, %) { auto f = make().as<%>(); return %::%_revoker{ f, f.%(%) }; @@ -526,6 +526,8 @@ catch (...) { return winrt::to_hresult(); } )"; w.write(format, + type_name, + method_name, type_name, method_name, bind(signature), diff --git a/test/test_component/Class.cpp b/test/test_component/Class.cpp index f328a7ddf..4f36df5c1 100644 --- a/test/test_component/Class.cpp +++ b/test/test_component/Class.cpp @@ -515,4 +515,11 @@ namespace winrt::test_component::implementation } return pass; } +} + +namespace +{ + void ValidateStaticEventAutoRevoke() { + auto x = winrt::test_component::Simple::StaticEvent(winrt::auto_revoke, [](auto&&, auto&&) {}); + } } \ No newline at end of file From 53ee6de0645c00055700c190f6d4c08984ed834a Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Tue, 5 Jul 2022 11:23:01 -0400 Subject: [PATCH 111/305] Clarify usage of ComponentConnectorT::InitializeComponent (#1161) --- nuget/readme.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nuget/readme.md b/nuget/readme.md index cc27391ec..991fd2768 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -117,7 +117,19 @@ void MyComponent::InitializeComponent() A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implemenation for these interfaces: ```cpp - struct DerivedPage : winrt::Windows::UI::Xaml::Markup::ComponentConnectorT> +struct DerivedPage : winrt::Windows::UI::Xaml::Markup::ComponentConnectorT> +``` + +If overriding DerivedPage::InitializeComponent, ComponentConnectorT::InitializeComponent should be called instead of DerivedPageT::InitializeComponent: + +```cpp +void DerivedPage::InitializeComponent() +{ + // Call base InitializeComponent() to register with the Xaml runtime + ComponentConnectorT::InitializeComponent(); + // Can now access Xaml properties from base or derived class + MyBaseButton().Content(box_value(L"Click")); +} ``` ## Troubleshooting From f65801e69f1086951ca3a18d59e5156ea79a3291 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 6 Jul 2022 14:05:20 -0700 Subject: [PATCH 112/305] Zero-fill padding in detach_abi(com_array) (#1165) A code analysis warning recently fired for a customer on detach_abi(com_array). This function returns a std::pair, which will have, on 64-bit builds, 4 bytes of padding between the uint32 size and the pointer members. Currently, that padding is uninitialized. The idea behind the code analysis warning is that information may be leaked via those unitialized bytes. In practice, that's almost never going to be an issue for this function, because the std::pair is not an interesting object to pass around, and only exists as a convenience to return both the size and buffer of the com_array at the same time. However, the fix removes a pain point for a customer, is simple, risk-free, and actually gets optimized away in the 99% use case (return value stored in a local variable, access only the first/second members, not the padding bytes). Demo showing optimization: https://godbolt.org/z/T4vPhMKxn --- strings/base_array.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/strings/base_array.h b/strings/base_array.h index 5f0904efe..5d1bee3c5 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -420,7 +420,10 @@ WINRT_EXPORT namespace winrt template auto detach_abi(com_array& object) noexcept { - std::pair> result(object.size(), *reinterpret_cast*>(&object)); + std::pair> result; + memset(&result, 0, sizeof(result)); + result.first = object.size(); + result.second = *reinterpret_cast*>(&object); memset(&object, 0, sizeof(com_array)); return result; } From 36567e6e647c31caa3d3e5fe6a3219ceb6a78f3f Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Wed, 10 Aug 2022 05:41:44 -0700 Subject: [PATCH 113/305] Project contract names so they can be passed to IsApiContractPresent (#1172) --- cppwinrt/file_writers.h | 3 +++ test/test/names.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index 5168d8d7f..ed9386b4e 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -77,6 +77,7 @@ namespace cppwinrt w.write_each(members.classes); w.write_each(members.structs); w.write_each(members.delegates); + w.write_each(members.contracts); } { auto wrap_impl = wrap_impl_namespace(w); @@ -89,11 +90,13 @@ namespace cppwinrt // Class names are always required for activation. // Class, enum, and struct names are required for producing GUIDs for generic types. // Interface and delegates names are required for Xaml compatibility. + // Contract names are used by IsApiContractPresent. w.write_each(members.classes); w.write_each(members.enums); w.write_each(members.structs); w.write_each(members.interfaces); w.write_each(members.delegates); + w.write_each(members.contracts); w.write_each(members.interfaces); w.write_each(members.delegates); diff --git a/test/test/names.cpp b/test/test/names.cpp index 7730fe82e..5d978a825 100644 --- a/test/test/names.cpp +++ b/test/test/names.cpp @@ -16,4 +16,5 @@ TEST_CASE("names") check_terminated(name_of()); check_terminated(name_of>()); check_terminated(name_of>()); + check_terminated(name_of()); } From 9fc5cecf4ca2039777a3a7ab535d030915d56c18 Mon Sep 17 00:00:00 2001 From: David Matson Date: Mon, 22 Aug 2022 10:03:22 -0700 Subject: [PATCH 114/305] Do not delete (clean) a file not written by this target (fixes #1173). (#1174) Co-authored-by: Kenny Kerr --- nuget/Microsoft.Windows.CppWinRT.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 7f27cd3c4..84464b624 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -132,7 +132,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. <_FilesToDelete Include="$(GeneratedFilesDir)**"/> <_FilesToDelete Include="$(CppWinRTMergedDir)**"/> <_FilesToDelete Include="$(CppWinRTUnmergedDir)**"/> - <_FilesToDelete Include="$(CppWinRTProjectWinMD)"/> + <_FilesToDelete Include="$(CppWinRTProjectWinMD)" Condition="'$(CppWinRTGenerateWindowsMetadata)' == 'true'"/> From d029f0426e42db95148cbc0b22a2f0b567ff83d5 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Thu, 8 Sep 2022 06:51:49 -0700 Subject: [PATCH 115/305] Don't use `__uuidof` without `GUID` (#1180) --- strings/base_meta.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/base_meta.h b/strings/base_meta.h index f951c4db0..e80afb9bf 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -119,12 +119,12 @@ namespace winrt::impl template #if defined(__clang__) -#if __has_declspec_attribute(uuid) +#if __has_declspec_attribute(uuid) && defined(WINRT_IMPL_IUNKNOWN_DEFINED) inline const guid guid_v{ __uuidof(T) }; #else inline constexpr guid guid_v{}; #endif -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) && defined(WINRT_IMPL_IUNKNOWN_DEFINED) inline constexpr guid guid_v{ __uuidof(T) }; #else inline constexpr guid guid_v{}; From 380cb8f773e1b9da8d947f6567eeaac401e0c33c Mon Sep 17 00:00:00 2001 From: Tim Guenthner Date: Fri, 9 Sep 2022 13:05:31 -0700 Subject: [PATCH 116/305] Add explicit casts to atomic_ref_count (#1181) --- strings/base_string.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/strings/base_string.h b/strings/base_string.h index 244f81e99..c23e981c3 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -16,7 +16,7 @@ namespace winrt::impl uint32_t operator++() noexcept { - return m_count.fetch_add(1, std::memory_order_relaxed) + 1; + return static_cast(m_count.fetch_add(1, std::memory_order_relaxed) + 1); } uint32_t operator--() noexcept @@ -32,12 +32,12 @@ namespace winrt::impl abort(); } - return remaining; + return static_cast(remaining); } operator uint32_t() const noexcept { - return m_count; + return static_cast(m_count); } private: From 129fade35934b1f8477304894d3875ccb4d703ee Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 16 Sep 2022 12:49:11 -0500 Subject: [PATCH 117/305] Upgrade cppwinrt solution to Visual Studio 2022 (#1187) --- Directory.Build.Props | 6 +- test/Directory.Build.Props | 10 --- test/catch.hpp | 119 ++++++++++++++++------------- test/test_cpp20/test_cpp20.vcxproj | 2 +- 4 files changed, 68 insertions(+), 69 deletions(-) delete mode 100644 test/Directory.Build.Props diff --git a/Directory.Build.Props b/Directory.Build.Props index a15bd841c..858b09177 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -3,9 +3,7 @@ - v141 - v142 - v143 + v143 10.0 10.0.18362.0 @@ -46,7 +44,7 @@ true true stdcpp17 - stdcpplatest + stdcpp20 Use pch.h CPPWINRT_VERSION_STRING="$(CppWinRTBuildVersion)";%(PreprocessorDefinitions) diff --git a/test/Directory.Build.Props b/test/Directory.Build.Props deleted file mode 100644 index 84e381220..000000000 --- a/test/Directory.Build.Props +++ /dev/null @@ -1,10 +0,0 @@ - - - - - v142 - - - - - diff --git a/test/catch.hpp b/test/catch.hpp index 7e706f947..d2a12427b 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -1,9 +1,9 @@ /* - * Catch v2.13.7 - * Generated: 2021-07-28 20:29:27.753164 + * Catch v2.13.9 + * Generated: 2022-04-12 22:37:23.260201 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. + * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 7 +#define CATCH_VERSION_PATCH 9 #ifdef __clang__ # pragma clang system_header @@ -240,9 +240,6 @@ namespace Catch { // Visual C++ #if defined(_MSC_VER) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) - // Universal Windows platform does not support SEH // Or console colours (or console at all...) # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) @@ -251,13 +248,18 @@ namespace Catch { # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH # endif +# if !defined(__clang__) // Handle Clang masquerading for msvc + // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(__clang__) // Handle Clang masquerading for msvc # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR # endif // MSVC_TRADITIONAL + +// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) # endif // __clang__ #endif // _MSC_VER @@ -1010,34 +1012,34 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) #endif #endif @@ -1050,7 +1052,7 @@ struct AutoReg : NonCopyable { CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ @@ -1072,7 +1074,7 @@ struct AutoReg : NonCopyable { CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ @@ -1113,18 +1115,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \ @@ -1162,18 +1164,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T,__VA_ARGS__) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ @@ -1204,7 +1206,7 @@ struct AutoReg : NonCopyable { static void TestFunc() #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList ) + INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList ) #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ @@ -1237,18 +1239,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\ @@ -1289,18 +1291,18 @@ struct AutoReg : NonCopyable { #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) ) #endif #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ ) #else #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) #endif #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ @@ -1334,7 +1336,7 @@ struct AutoReg : NonCopyable { void TestName::test() #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList ) + INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList ) // end catch_test_registry.h // start catch_capture.hpp @@ -3091,7 +3093,7 @@ namespace Detail { Approx operator-() const; template ::value>::type> - Approx operator()( T const& value ) { + Approx operator()( T const& value ) const { Approx approx( static_cast(value) ); approx.m_epsilon = m_epsilon; approx.m_margin = m_margin; @@ -4163,7 +4165,7 @@ namespace Generators { if (!m_predicate(m_generator.get())) { // It might happen that there are no values that pass the // filter. In that case we throw an exception. - auto has_initial_value = next(); + auto has_initial_value = nextImpl(); if (!has_initial_value) { Catch::throw_exception(GeneratorException("No valid value found in filtered generator")); } @@ -4175,6 +4177,11 @@ namespace Generators { } bool next() override { + return nextImpl(); + } + + private: + bool nextImpl() { bool success = m_generator.next(); if (!success) { return false; @@ -13385,6 +13392,10 @@ namespace Catch { filename.erase(0, lastSlash); filename[0] = '#'; } + else + { + filename.insert(0, "#"); + } auto lastDot = filename.find_last_of('.'); if (lastDot != std::string::npos) { @@ -15380,7 +15391,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 13, 7, "", 0 ); + static Version version( 2, 13, 9, "", 0 ); return version; } @@ -17648,9 +17659,9 @@ int main (int argc, char * const argv[]) { #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #define CATCH_BENCHMARK(...) \ - INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) + INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) #define CATCH_BENCHMARK_ADVANCED(name) \ - INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) + INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) #endif // CATCH_CONFIG_ENABLE_BENCHMARKING // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required @@ -17752,9 +17763,9 @@ int main (int argc, char * const argv[]) { #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) #define BENCHMARK(...) \ - INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) + INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,)) #define BENCHMARK_ADVANCED(name) \ - INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name) + INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name) #endif // CATCH_CONFIG_ENABLE_BENCHMARKING using Catch::Detail::Approx; @@ -17801,8 +17812,8 @@ using Catch::Detail::Approx; #define CATCH_WARN( msg ) (void)(0) #define CATCH_CAPTURE( msg ) (void)(0) -#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) #define CATCH_SECTION( ... ) @@ -17811,7 +17822,7 @@ using Catch::Detail::Approx; #define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0) -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) @@ -17834,8 +17845,8 @@ using Catch::Detail::Approx; #endif // "BDD-style" convenience wrappers -#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className ) #define CATCH_GIVEN( desc ) #define CATCH_AND_GIVEN( desc ) #define CATCH_WHEN( desc ) @@ -17883,10 +17894,10 @@ using Catch::Detail::Approx; #define INFO( msg ) (void)(0) #define UNSCOPED_INFO( msg ) (void)(0) #define WARN( msg ) (void)(0) -#define CAPTURE( msg ) (void)(0) +#define CAPTURE( ... ) (void)(0) -#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) -#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #define METHOD_AS_TEST_CASE( method, ... ) #define REGISTER_TEST_CASE( Function, ... ) (void)(0) #define SECTION( ... ) @@ -17894,7 +17905,7 @@ using Catch::Detail::Approx; #define FAIL( ... ) (void)(0) #define FAIL_CHECK( ... ) (void)(0) #define SUCCEED( ... ) (void)(0) -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ )) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) @@ -17924,8 +17935,8 @@ using Catch::Detail::Approx; #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // "BDD-style" convenience wrappers -#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className ) #define GIVEN( desc ) #define AND_GIVEN( desc ) diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 79967de19..9fff3774a 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -39,7 +39,7 @@ {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} unittests test_cpp20 - latest + 20 From cea2e4121ea533653a9e99c50158e05b4d9af6b6 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 19 Sep 2022 10:25:53 -0700 Subject: [PATCH 118/305] Add `std::source_location` support when logging error information (#1185) --- strings/base_error.h | 166 ++++++++++++++++------------- strings/base_includes.h | 4 + strings/base_macros.h | 24 +++++ strings/base_meta.h | 2 +- test/test/custom_error.cpp | 6 +- test/test_cpp20/custom_error.cpp | 48 +++++++++ test/test_cpp20/pch.h | 2 + test/test_cpp20/test_cpp20.vcxproj | 1 + 8 files changed, 176 insertions(+), 77 deletions(-) create mode 100644 test/test_cpp20/custom_error.cpp diff --git a/strings/base_error.h b/strings/base_error.h index 45ed39cd3..44b955b95 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -207,17 +207,17 @@ WINRT_EXPORT namespace winrt return *this; } - explicit hresult_error(hresult const code) noexcept : m_code(verify_error(code)) + explicit hresult_error(hresult const code WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) { - originate(code, nullptr); + originate(code, nullptr WINRT_IMPL_SOURCE_LOCATION_FORWARD); } - hresult_error(hresult const code, param::hstring const& message) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) { - originate(code, get_abi(message)); + originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); } - hresult_error(hresult const code, take_ownership_from_abi_t) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) { com_ptr info; WINRT_IMPL_GetErrorInfo(0, info.put_void()); @@ -247,7 +247,7 @@ WINRT_EXPORT namespace winrt message = impl::trim_hresult_message(legacy.get(), WINRT_IMPL_SysStringLen(legacy.get())); } - originate(code, get_abi(message)); + originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); } } @@ -309,12 +309,24 @@ WINRT_EXPORT namespace winrt return 1; } - void originate(hresult const code, void* message) noexcept + void originate(hresult const code, void* message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept { static int32_t(__stdcall* handler)(int32_t error, void* message, void* exception) noexcept; impl::load_runtime_function(L"combase.dll", "RoOriginateLanguageException", handler, fallback_RoOriginateLanguageException); WINRT_VERIFY(handler(code, message, nullptr)); + // This is an extension point that can be filled in by other libraries (such as WIL) to get call outs when errors are + // originated. This is intended for logging purposes. When possible include the std::source_information so that accurate + // information is available on the caller who generated the error. + if (winrt_throw_hresult_handler) + { +#ifdef __cpp_lib_source_location + winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), code); +#else + winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), code); +#endif + } + com_ptr info; WINRT_VERIFY_(0, WINRT_IMPL_GetErrorInfo(0, info.put_void())); WINRT_VERIFY(info.try_as(m_info)); @@ -344,100 +356,104 @@ WINRT_EXPORT namespace winrt struct hresult_access_denied : hresult_error { - hresult_access_denied() noexcept : hresult_error(impl::error_access_denied) {} - hresult_access_denied(param::hstring const& message) noexcept : hresult_error(impl::error_access_denied, message) {} - hresult_access_denied(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi) {} + hresult_access_denied(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_access_denied WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_access_denied(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_access_denied(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_wrong_thread : hresult_error { - hresult_wrong_thread() noexcept : hresult_error(impl::error_wrong_thread) {} - hresult_wrong_thread(param::hstring const& message) noexcept : hresult_error(impl::error_wrong_thread, message) {} - hresult_wrong_thread(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi) {} + hresult_wrong_thread(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_wrong_thread WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_wrong_thread(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_wrong_thread(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_not_implemented : hresult_error { - hresult_not_implemented() noexcept : hresult_error(impl::error_not_implemented) {} - hresult_not_implemented(param::hstring const& message) noexcept : hresult_error(impl::error_not_implemented, message) {} - hresult_not_implemented(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi) {} + hresult_not_implemented(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_not_implemented WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_not_implemented(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_not_implemented(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_invalid_argument : hresult_error { - hresult_invalid_argument() noexcept : hresult_error(impl::error_invalid_argument) {} - hresult_invalid_argument(param::hstring const& message) noexcept : hresult_error(impl::error_invalid_argument, message) {} - hresult_invalid_argument(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi) {} + hresult_invalid_argument(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_invalid_argument WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_invalid_argument(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_invalid_argument(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_out_of_bounds : hresult_error { - hresult_out_of_bounds() noexcept : hresult_error(impl::error_out_of_bounds) {} - hresult_out_of_bounds(param::hstring const& message) noexcept : hresult_error(impl::error_out_of_bounds, message) {} - hresult_out_of_bounds(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi) {} + hresult_out_of_bounds(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_out_of_bounds WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_out_of_bounds(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_out_of_bounds(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_no_interface : hresult_error { - hresult_no_interface() noexcept : hresult_error(impl::error_no_interface) {} - hresult_no_interface(param::hstring const& message) noexcept : hresult_error(impl::error_no_interface, message) {} - hresult_no_interface(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi) {} + hresult_no_interface(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_no_interface WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_no_interface(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_no_interface(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_class_not_available : hresult_error { - hresult_class_not_available() noexcept : hresult_error(impl::error_class_not_available) {} - hresult_class_not_available(param::hstring const& message) noexcept : hresult_error(impl::error_class_not_available, message) {} - hresult_class_not_available(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi) {} + hresult_class_not_available(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_available WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_available(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_available(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_class_not_registered : hresult_error { - hresult_class_not_registered() noexcept : hresult_error(impl::error_class_not_registered) {} - hresult_class_not_registered(param::hstring const& message) noexcept : hresult_error(impl::error_class_not_registered, message) {} - hresult_class_not_registered(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi) {} + hresult_class_not_registered(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_registered WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_registered(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_registered(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_changed_state : hresult_error { - hresult_changed_state() noexcept : hresult_error(impl::error_changed_state) {} - hresult_changed_state(param::hstring const& message) noexcept : hresult_error(impl::error_changed_state, message) {} - hresult_changed_state(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi) {} + hresult_changed_state(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_changed_state WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_changed_state(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_changed_state(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_illegal_method_call : hresult_error { - hresult_illegal_method_call() noexcept : hresult_error(impl::error_illegal_method_call) {} - hresult_illegal_method_call(param::hstring const& message) noexcept : hresult_error(impl::error_illegal_method_call, message) {} - hresult_illegal_method_call(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi) {} + hresult_illegal_method_call(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_method_call WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_method_call(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_method_call(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_illegal_state_change : hresult_error { - hresult_illegal_state_change() noexcept : hresult_error(impl::error_illegal_state_change) {} - hresult_illegal_state_change(param::hstring const& message) noexcept : hresult_error(impl::error_illegal_state_change, message) {} - hresult_illegal_state_change(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi) {} + hresult_illegal_state_change(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_state_change WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_state_change(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_state_change(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_illegal_delegate_assignment : hresult_error { - hresult_illegal_delegate_assignment() noexcept : hresult_error(impl::error_illegal_delegate_assignment) {} - hresult_illegal_delegate_assignment(param::hstring const& message) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message) {} - hresult_illegal_delegate_assignment(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi) {} + hresult_illegal_delegate_assignment(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_delegate_assignment WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_delegate_assignment(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_delegate_assignment(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; struct hresult_canceled : hresult_error { - hresult_canceled() noexcept : hresult_error(impl::error_canceled) {} - hresult_canceled(param::hstring const& message) noexcept : hresult_error(impl::error_canceled, message) {} - hresult_canceled(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi) {} + hresult_canceled(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_canceled WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_canceled(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_canceled(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} }; - [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result) + [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) { if (winrt_throw_hresult_handler) { +#ifdef __cpp_lib_source_location + winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), result); +#else winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), result); +#endif } if (result == impl::error_bad_alloc) @@ -447,70 +463,70 @@ WINRT_EXPORT namespace winrt if (result == impl::error_access_denied) { - throw hresult_access_denied(take_ownership_from_abi); + throw hresult_access_denied(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_wrong_thread) { - throw hresult_wrong_thread(take_ownership_from_abi); + throw hresult_wrong_thread(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_not_implemented) { - throw hresult_not_implemented(take_ownership_from_abi); + throw hresult_not_implemented(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_invalid_argument) { - throw hresult_invalid_argument(take_ownership_from_abi); + throw hresult_invalid_argument(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_out_of_bounds) { - throw hresult_out_of_bounds(take_ownership_from_abi); + throw hresult_out_of_bounds(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_no_interface) { - throw hresult_no_interface(take_ownership_from_abi); + throw hresult_no_interface(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_class_not_available) { - throw hresult_class_not_available(take_ownership_from_abi); + throw hresult_class_not_available(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_class_not_registered) { - throw hresult_class_not_registered(take_ownership_from_abi); + throw hresult_class_not_registered(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_changed_state) { - throw hresult_changed_state(take_ownership_from_abi); + throw hresult_changed_state(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_illegal_method_call) { - throw hresult_illegal_method_call(take_ownership_from_abi); + throw hresult_illegal_method_call(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_illegal_state_change) { - throw hresult_illegal_state_change(take_ownership_from_abi); + throw hresult_illegal_state_change(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_illegal_delegate_assignment) { - throw hresult_illegal_delegate_assignment(take_ownership_from_abi); + throw hresult_illegal_delegate_assignment(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } if (result == impl::error_canceled) { - throw hresult_canceled(take_ownership_from_abi); + throw hresult_canceled(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } - throw hresult_error(result, take_ownership_from_abi); + throw hresult_error(result, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); } inline WINRT_IMPL_NOINLINE hresult to_hresult() noexcept @@ -571,53 +587,53 @@ WINRT_EXPORT namespace winrt } } - [[noreturn]] inline void throw_last_error() + [[noreturn]] inline void throw_last_error(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) { - throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError())); + throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError()) WINRT_IMPL_SOURCE_LOCATION_FORWARD); } - inline hresult check_hresult(hresult const result) + inline hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT) { if (result < 0) { - throw_hresult(result); + throw_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); } return result; } template - void check_nt(T result) + void check_nt(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) { if (result != 0) { - throw_hresult(impl::hresult_from_nt(result)); + throw_hresult(impl::hresult_from_nt(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); } } template - void check_win32(T result) + void check_win32(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) { if (result != 0) { - throw_hresult(impl::hresult_from_win32(result)); + throw_hresult(impl::hresult_from_win32(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); } } template - void check_bool(T result) + void check_bool(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) { if (!result) { - winrt::throw_last_error(); + winrt::throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); } } template - T* check_pointer(T* pointer) + T* check_pointer(T* pointer WINRT_IMPL_SOURCE_LOCATION_ARGS) { if (!pointer) { - throw_last_error(); + throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); } return pointer; @@ -634,11 +650,11 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { - inline hresult check_hresult_allow_bounds(hresult const result) + inline hresult check_hresult_allow_bounds(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) { if (result != impl::error_out_of_bounds && result != impl::error_fail && result != impl::error_file_not_found) { - check_hresult(result); + check_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); } return result; } diff --git a/strings/base_includes.h b/strings/base_includes.h index 14d992fc9..8fe598212 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -28,6 +28,10 @@ #include #endif +#ifdef __cpp_lib_source_location +#include +#endif + #ifdef __cpp_lib_coroutine #include diff --git a/strings/base_macros.h b/strings/base_macros.h index 40473bb5d..c1d0617c8 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -54,3 +54,27 @@ struct IUnknown; typedef struct _GUID GUID; #endif + +// std::source_location is a C++20 feature, which is above the C++17 feature floor for cppwinrt. The source location needs +// to be the calling code, not cppwinrt itself, so that it is useful to developers building on top of this library. As a +// result any public-facing method that can result in an error needs a default-constructed source_location argument. Because +// this type does not exist in C++17 we need to use a macro to optionally add parameters and forwarding wherever appropriate. +#ifdef __cpp_lib_source_location +#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , std::source_location const& sourceInformation +#define WINRT_IMPL_SOURCE_LOCATION_ARGS , std::source_location const& sourceInformation = std::source_location::current() +#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM std::source_location const& sourceInformation = std::source_location::current() + +#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation +#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation + +#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true") +#else +#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT +#define WINRT_IMPL_SOURCE_LOCATION_ARGS +#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM + +#define WINRT_IMPL_SOURCE_LOCATION_FORWARD +#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM + +#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false") +#endif diff --git a/strings/base_meta.h b/strings/base_meta.h index e80afb9bf..4bfa82d18 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -1,7 +1,7 @@ WINRT_EXPORT namespace winrt { - hresult check_hresult(hresult const result); + hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS); hresult to_hresult() noexcept; template diff --git a/test/test/custom_error.cpp b/test/test/custom_error.cpp index a39024c03..28a21aca3 100644 --- a/test/test/custom_error.cpp +++ b/test/test/custom_error.cpp @@ -59,7 +59,11 @@ namespace void __stdcall logger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept { - lineNumber; fileName; functionName; + // In C++17 these fields cannot be filled in so they are expected to be empty. + REQUIRE(lineNumber == 0); + REQUIRE(fileName == nullptr); + REQUIRE(functionName == nullptr); + REQUIRE(returnAddress); REQUIRE(result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) s_loggerCalled = true; diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp new file mode 100644 index 000000000..dc38bbdf9 --- /dev/null +++ b/test/test_cpp20/custom_error.cpp @@ -0,0 +1,48 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; + +namespace +{ + static bool s_loggerCalled = false; + + // Note that we are checking that the source line number matches expectations. If lines above this are changed + // then this value needs to change as well. + void FailOnLine15() + { + // Validate that handler translated exception + REQUIRE_THROWS_AS(check_hresult(0x80000018), hresult_illegal_delegate_assignment); + } + + void __stdcall logger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept + { + // In C++20 these fields should be filled in by std::source_location + REQUIRE(lineNumber == 15); + const auto fileNameSv = std::string_view(fileName); + REQUIRE(!fileNameSv.empty()); + REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); + const auto functionNameSv = std::string_view(functionName); + REQUIRE(!functionNameSv.empty()); + REQUIRE(functionNameSv == "FailOnLine15"); + + REQUIRE(returnAddress); + REQUIRE(result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + s_loggerCalled = true; + } +} + +TEST_CASE("custom_error_logger") +{ + // Set up global handler + REQUIRE(!s_loggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = logger; + + FailOnLine15(); + REQUIRE(s_loggerCalled); + + // Remove global handler + winrt_throw_hresult_handler = nullptr; + s_loggerCalled = false; +} diff --git a/test/test_cpp20/pch.h b/test/test_cpp20/pch.h index bd678407c..6565bea1b 100644 --- a/test/test_cpp20/pch.h +++ b/test/test_cpp20/pch.h @@ -11,4 +11,6 @@ #include #include "catch.hpp" +#include + using namespace std::literals; diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 9fff3774a..1717d6bf8 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -281,6 +281,7 @@ + From 64cdc7c6d806c94ae51417042c40f351b4c487b9 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 23 Sep 2022 11:52:00 -0700 Subject: [PATCH 119/305] Add arm64 debug visualizer and update VS SDK package for VSIX (#1190) * Build arm64 visualizer and include it in vsix * Add arm64 config to visualizer * Build arm64 visualizer in build_test_all * Update VS SDK package versions * Typo * Don't build cppwinrt.exe for arm64 (yet) --- build_test_all.cmd | 7 ++- build_vsix.cmd | 5 +- natvis/cppwinrtvisualizer.sln | 10 +++- natvis/cppwinrtvisualizer.vcxproj | 80 +++++++++++++++++++++++++++++++ vsix/Dev16/vsix.Dev16.csproj | 8 +++- vsix/Dev17/vsix.Dev17.csproj | 8 +++- 6 files changed, 108 insertions(+), 10 deletions(-) diff --git a/build_test_all.cmd b/build_test_all.cmd index e0325eb5d..29acdc77f 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -19,12 +19,15 @@ call .nuget\nuget.exe restore test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd if "%target_platform%"=="arm" goto :eof + +call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Component;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln +call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Standalone;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln + if "%target_platform%"=="arm64" goto :eof call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt _build\%target_platform%\%target_configuration%\cppwinrt.exe -in local -out _build\%target_platform%\%target_configuration% -verbose -call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Component;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln -call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Standalone;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln + call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test diff --git a/build_vsix.cmd b/build_vsix.cmd index ba2f75f31..111527a48 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -25,12 +25,13 @@ call msbuild /m /p:Configuration=%target_configuration%,Platform=arm64,CppWinRTB rem Build cppwinrt.exe for x86 only call msbuild /m /p:Configuration=%target_configuration%,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt -rem Build cppwinrt visualizer dll for x86 and x64 +rem Build cppwinrt visualizer dll for x86, x64, and arm64 call msbuild /p:Configuration=%target_configuration%,Platform=x64,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln call msbuild /p:Configuration=%target_configuration%,Platform=x86,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln +call msbuild /p:Configuration=%target_configuration%,Platform=arm64,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln rem Build nuget .nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%this_dir%_build\arm\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed rem Build vsix -call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln +call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln diff --git a/natvis/cppwinrtvisualizer.sln b/natvis/cppwinrtvisualizer.sln index d885e721a..2ed7efb70 100644 --- a/natvis/cppwinrtvisualizer.sln +++ b/natvis/cppwinrtvisualizer.sln @@ -1,22 +1,28 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32901.215 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppwinrtvisualizer", "cppwinrtvisualizer.vcxproj", "{3C692D34-10C1-4707-B469-5EDB0EEF8AFC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Debug|ARM64.Build.0 = Debug|ARM64 {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Debug|x64.ActiveCfg = Debug|x64 {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Debug|x64.Build.0 = Debug|x64 {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Debug|x86.ActiveCfg = Debug|Win32 {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Debug|x86.Build.0 = Debug|Win32 + {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Release|ARM64.ActiveCfg = Release|ARM64 + {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Release|ARM64.Build.0 = Release|ARM64 {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Release|x64.ActiveCfg = Release|x64 {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Release|x64.Build.0 = Release|x64 {3C692D34-10C1-4707-B469-5EDB0EEF8AFC}.Release|x86.ActiveCfg = Release|Win32 diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index 397772285..d7c3a4ae1 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -2,10 +2,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 @@ -41,11 +49,20 @@ DynamicLibrary true + + DynamicLibrary + true + DynamicLibrary false true + + DynamicLibrary + false + true + $(VSInstallDir)DIA SDK\include @@ -63,9 +80,15 @@ + + + + + + true @@ -127,6 +150,31 @@ vsdebugeng.dll + + + Use + Level4 + Disabled + false + _DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) + stdcpp17 + pch.h + /await + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + Windows + DebugFull + advapi32.lib;shell32.lib;windowsapp.lib;$(VsDebugEng_Lib);%(AdditionalDependencies) + .\cppwinrtvisualizer.def + vsdebugeng.dll + + Use @@ -187,6 +235,36 @@ /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + + + Use + Level4 + MaxSpeed + true + true + false + NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) + stdcpp17 + pch.h + /await + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + $(IntDir);%(AdditionalIncludeDirectories) + + + Windows + true + true + DebugFull + advapi32.lib;shell32.lib;windowsapp.lib;$(VsDebugEng_Lib);%(AdditionalDependencies) + .\cppwinrtvisualizer.def + vsdebugeng.dll + /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) + + %(AdditionalOptions) /DCOMPONENT_DEPLOYMENT @@ -208,8 +286,10 @@ Create Create + Create Create Create + Create diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index 4b7c01cd2..e9c5d140e 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -61,7 +61,11 @@ x64\%(Filename)%(Extension) true - + + arm64\%(Filename)%(Extension) + true + + Designer @@ -84,7 +88,7 @@ compile; build; native; contentfiles; analyzers; buildtransitive - 17.0.1619-preview1 + 17.3.2093 runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index 6e6c35bbf..3ef30ce63 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -64,6 +64,10 @@ x64\%(Filename)%(Extension) true + + arm64\%(Filename)%(Extension) + true + Designer @@ -83,10 +87,10 @@ - + compile; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive all From e7b690382e0e08af0ce5ddcfde37d8fdab0ddb24 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Thu, 29 Sep 2022 09:44:40 -0400 Subject: [PATCH 120/305] Make `guid` `constexpr` on Clang and improve error reporting (#1191) --- Directory.Build.Props | 9 ++++++--- natvis/cppwinrtvisualizer.vcxproj | 30 ++++++++++++------------------ strings/base_identity.h | 4 ---- strings/base_meta.h | 17 +++++++++++------ test/test/generic_types.cpp | 4 ---- test/test_win7/generic_types.cpp | 4 ---- 6 files changed, 29 insertions(+), 39 deletions(-) diff --git a/Directory.Build.Props b/Directory.Build.Props index 858b09177..abbedf15b 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -25,8 +25,11 @@ --> - clang-cl.exe - C:\Program Files\LLVM\bin + ClangCL + + 20 + + false @@ -51,7 +54,7 @@ true /bigobj /await %(AdditionalOptions) - -Wno-unused-command-line-argument -fno-delayed-template-parsing -Xclang -fcoroutines-ts -mcx16 + -Wno-unused-command-line-argument -fno-delayed-template-parsing -mcx16 onecore.lib diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index d7c3a4ae1..e504e197e 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -105,10 +105,9 @@ Level4 Disabled false - WIN32;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) - stdcpp17 - /await + stdcpp20 pch.h @@ -131,11 +130,10 @@ Level4 Disabled false - _DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) - stdcpp17 + stdcpp20 pch.h - /await _DEBUG;%(PreprocessorDefinitions) @@ -156,11 +154,10 @@ Level4 Disabled false - _DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) - stdcpp17 + stdcpp20 pch.h - /await _DEBUG;%(PreprocessorDefinitions) @@ -183,11 +180,10 @@ true true false - WIN32;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) - stdcpp17 + stdcpp20 pch.h - /await _DEBUG;%(PreprocessorDefinitions) @@ -213,11 +209,10 @@ true true false - NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) - stdcpp17 + stdcpp20 pch.h - /await _DEBUG;%(PreprocessorDefinitions) @@ -243,11 +238,10 @@ true true false - NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) - stdcpp17 + stdcpp20 pch.h - /await _DEBUG;%(PreprocessorDefinitions) diff --git a/strings/base_identity.h b/strings/base_identity.h index 5bf7bbaa8..52a77dfc4 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -458,12 +458,8 @@ namespace winrt::impl }; template -#ifdef __clang__ - inline static const auto name_v -#else #pragma warning(suppress: 4307) inline constexpr auto name_v -#endif { combine ( diff --git a/strings/base_meta.h b/strings/base_meta.h index 4bfa82d18..f19e0513a 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -117,17 +117,22 @@ namespace winrt::impl static constexpr auto data{ category_signature, T>::data }; }; - template #if defined(__clang__) + template + struct classic_com_guid + { #if __has_declspec_attribute(uuid) && defined(WINRT_IMPL_IUNKNOWN_DEFINED) - inline const guid guid_v{ __uuidof(T) }; + static constexpr guid value{ __uuidof(T) }; #else - inline constexpr guid guid_v{}; + static_assert(std::is_void_v /* dependent_false */, "To use classic COM interfaces, you must compile with -fms-extensions and include before including C++/WinRT headers."); #endif -#elif defined(_MSC_VER) && defined(WINRT_IMPL_IUNKNOWN_DEFINED) - inline constexpr guid guid_v{ __uuidof(T) }; + }; + + template + inline constexpr guid guid_v = classic_com_guid::value; #else - inline constexpr guid guid_v{}; + template + inline constexpr guid guid_v{ __uuidof(T) }; #endif template diff --git a/test/test/generic_types.cpp b/test/test/generic_types.cpp index 98ffd12eb..081155cd2 100644 --- a/test/test/generic_types.cpp +++ b/test/test/generic_types.cpp @@ -8,9 +8,5 @@ TEST_CASE("generic_types") REQUIRE_EQUAL_NAME(L"Windows.Foundation.Uri", Uri); REQUIRE_EQUAL_NAME(L"Windows.Foundation.PropertyType", PropertyType); REQUIRE_EQUAL_NAME(L"Windows.Foundation.Point", Point); - - // Clang 9 doesn't think this is a constant expression. -#ifndef __clang__ REQUIRE_EQUAL_NAME(L"Windows.Foundation.IStringable", IStringable); -#endif } diff --git a/test/test_win7/generic_types.cpp b/test/test_win7/generic_types.cpp index 98ffd12eb..081155cd2 100644 --- a/test/test_win7/generic_types.cpp +++ b/test/test_win7/generic_types.cpp @@ -8,9 +8,5 @@ TEST_CASE("generic_types") REQUIRE_EQUAL_NAME(L"Windows.Foundation.Uri", Uri); REQUIRE_EQUAL_NAME(L"Windows.Foundation.PropertyType", PropertyType); REQUIRE_EQUAL_NAME(L"Windows.Foundation.Point", Point); - - // Clang 9 doesn't think this is a constant expression. -#ifndef __clang__ REQUIRE_EQUAL_NAME(L"Windows.Foundation.IStringable", IStringable); -#endif } From 61b054a8c7fdd7b6f0d2d1f4dbfb8283bc9288c8 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Fri, 7 Oct 2022 00:33:52 -0400 Subject: [PATCH 121/305] Fix classic COM errors on non-supported compilers (#1194) --- strings/base_meta.h | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/strings/base_meta.h b/strings/base_meta.h index f19e0513a..0e800c49f 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -117,22 +117,33 @@ namespace winrt::impl static constexpr auto data{ category_signature, T>::data }; }; -#if defined(__clang__) template - struct classic_com_guid + struct classic_com_guid_error { -#if __has_declspec_attribute(uuid) && defined(WINRT_IMPL_IUNKNOWN_DEFINED) - static constexpr guid value{ __uuidof(T) }; -#else - static_assert(std::is_void_v /* dependent_false */, "To use classic COM interfaces, you must compile with -fms-extensions and include before including C++/WinRT headers."); +#ifdef __clang__ +#if !__has_declspec_attribute(uuid) + static_assert(std::is_void_v /* dependent_false */, "To use classic COM interfaces, you must compile with -fms-extensions."); +#endif + +#ifndef WINRT_IMPL_IUNKNOWN_DEFINED + static_assert(std::is_void_v /* dependent_false */, "To use classic COM interfaces, you must include before including C++/WinRT headers."); +#endif +#else // MSVC won't hit this struct, so we can safely assume everything that isn't Clang isn't supported + static_assert(std::is_void_v /* dependent_false */, "Classic COM interfaces are not supported with this compiler."); #endif }; template - inline constexpr guid guid_v = classic_com_guid::value; +#ifdef __clang__ +#if __has_declspec_attribute(uuid) && defined(WINRT_IMPL_IUNKNOWN_DEFINED) + inline constexpr guid guid_v{ __uuidof(T) }; #else - template + inline constexpr guid guid_v = classic_com_guid_error::value; +#endif +#elif defined(_MSC_VER) inline constexpr guid guid_v{ __uuidof(T) }; +#else + inline constexpr guid guid_v = classic_com_guid_error::value; #endif template From 631c8f7944dc5534ac2863b623a184164cccde67 Mon Sep 17 00:00:00 2001 From: Rose <83477269+AtariDreams@users.noreply.github.com> Date: Mon, 10 Oct 2022 11:10:21 -0400 Subject: [PATCH 122/305] Fix Clang 15 style warnings (#1196) --- cppwinrt/cmd_reader.h | 7 +++---- cppwinrt/code_writers.h | 15 ++++++--------- cppwinrt/component_writers.h | 10 +++++----- cppwinrt/helpers.h | 2 +- cppwinrt/text_writer.h | 4 ++-- natvis/cppwinrt_visualizer.cpp | 4 ++-- natvis/object_visualizer.cpp | 2 +- prebuild/main.cpp | 2 +- strings/base_collections_input_vector.h | 2 +- strings/base_coroutine_foundation.h | 2 +- strings/base_implements.h | 2 +- test/old_tests/UnitTests/handle.cpp | 2 +- 12 files changed, 25 insertions(+), 29 deletions(-) diff --git a/cppwinrt/cmd_reader.h b/cppwinrt/cmd_reader.h index c86cfdcc6..376180eb4 100644 --- a/cppwinrt/cmd_reader.h +++ b/cppwinrt/cmd_reader.h @@ -195,11 +195,10 @@ namespace cppwinrt inline std::string get_module_path() { std::string path(100, '?'); - DWORD actual_size{}; while (true) { - actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); + DWORD actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); if (actual_size < 1 + path.size()) { @@ -603,7 +602,7 @@ namespace cppwinrt first_arg = true; *argument_count = 0; - for (;;) + while (true) { if (*p) { @@ -621,7 +620,7 @@ namespace cppwinrt if (*p == '\0') break; - for (;;) + while (true) { copy_character = true; diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 748996b1a..c9f99c9ea 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -417,7 +417,7 @@ namespace cppwinrt static void write_generic_names(writer& w, std::pair const& params) { - bool first{ true }; + bool first = true; for (auto&& param : params) { @@ -2011,7 +2011,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable w.write_each(info.type.MethodList(), name); } - }; + } } static void write_class_override_implements(writer& w, get_interfaces_t const& interfaces) @@ -2035,21 +2035,18 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable static void write_class_override_requires(writer& w, get_interfaces_t const& interfaces) { - bool found{}; - for (auto&& [name, info] : interfaces) { if (!info.overridable) { w.write(", %", name); - found = true; } } } static void write_class_override_defaults(writer& w, get_interfaces_t const& interfaces) { - bool first{ true }; + bool first = true; for (auto&& [name, info] : interfaces) { @@ -2769,7 +2766,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable static void write_class_requires(writer& w, TypeDef const& type) { - bool first{ true }; + bool first = true; for (auto&& [interface_name, info] : get_interfaces(w, type)) { @@ -2793,7 +2790,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable static void write_fast_class_requires(writer& w, TypeDef const& type) { - bool first{ true }; + bool first = true; for (auto&& [interface_name, info] : get_interfaces(w, type)) { @@ -2817,7 +2814,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable static void write_class_base(writer& w, TypeDef const& type) { - bool first{ true }; + bool first = true; for (auto&& base : get_bases(type)) { diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index acd2b871c..fcfeddac0 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -27,7 +27,7 @@ namespace cppwinrt } } - bool first{ true }; + bool first = true; for (auto&& name : interfaces) { @@ -45,7 +45,7 @@ namespace cppwinrt static void write_component_class_base(writer& w, TypeDef const& type) { - bool first{ true }; + bool first = true; for (auto&& base : get_bases(type)) { @@ -289,7 +289,7 @@ catch (...) { return winrt::to_hresult(); } bind(signature)); } - void write_component_static_forwarder(writer& w, MethodDef const& method) + static void write_component_static_forwarder(writer& w, MethodDef const& method) { auto format = R"( auto %(%) { @@ -643,8 +643,8 @@ catch (...) { return winrt::to_hresult(); } { if (!info.base && info.is_default) { - auto methods = info.type.MethodList(); - offset += methods.second - methods.first; + auto [first, second] = info.type.MethodList(); + offset += second - first; break; } } diff --git a/cppwinrt/helpers.h b/cppwinrt/helpers.h index b2d783d61..a3b865b6e 100644 --- a/cppwinrt/helpers.h +++ b/cppwinrt/helpers.h @@ -127,7 +127,7 @@ namespace cppwinrt struct separator { writer& w; - bool first{ true }; + bool first = true; void operator()() { diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index bde87806e..50e6e6b15 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -461,7 +461,7 @@ namespace cppwinrt { return [&](auto& writer) { - bool first{ true }; + bool first = true; for (auto&& item : list) { @@ -484,7 +484,7 @@ namespace cppwinrt { return [&](auto& writer) { - bool first{ true }; + bool first = true; for (auto&& item : list) { diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index b44be1268..f6affd566 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -93,7 +93,7 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie { auto winmd_path = path{ processPath }; auto probe_file = std::string{ typeName }; - do + while (true) { winmd_path.replace_filename(probe_file + ".winmd"); MetadataDiagnostic(process, L"Looking for ", winmd_path); @@ -115,7 +115,7 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie break; } probe_file = probe_file.substr(0, pos); - } while (true); + } } TypeDef FindType(DkmProcess* process, std::string_view const& typeName) diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 8bcb86877..5308c33fc 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -573,7 +573,7 @@ HRESULT object_visualizer::CreateEvaluationResult(_Deref_out_ DkmEvaluationResul auto address = pPointerValueHome->Address(); com_ptr pValue; - DkmEvaluationResultFlags_t evalResultFlags = DkmEvaluationResultFlags::ReadOnly | DkmEvaluationResultFlags::Expandable;; + DkmEvaluationResultFlags_t evalResultFlags = DkmEvaluationResultFlags::ReadOnly | DkmEvaluationResultFlags::Expandable; if (requires_refresh(address, m_pVisualizedExpression->InspectionContext()->EvaluationFlags())) { IF_FAIL_RET(DkmString::Create(L"", pValue.put())); diff --git a/prebuild/main.cpp b/prebuild/main.cpp index d446c02d4..52a750776 100644 --- a/prebuild/main.cpp +++ b/prebuild/main.cpp @@ -49,7 +49,7 @@ namespace cppwinrt::strings { std::string_view remainder = view; - while (remainder.size()) + while (!remainder.empty()) { auto const size = std::min(size_t{ 16'000 }, remainder.size()); auto const chunk = remainder.substr(0, size); diff --git a/strings/base_collections_input_vector.h b/strings/base_collections_input_vector.h index 2482db968..b5b76de38 100644 --- a/strings/base_collections_input_vector.h +++ b/strings/base_collections_input_vector.h @@ -88,7 +88,7 @@ WINRT_EXPORT namespace winrt::param private: interface_type m_interface; - bool m_owned{ true }; + bool m_owned = true; }; template diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 3c309256c..71dbb0043 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -149,7 +149,7 @@ namespace winrt::impl Async const& async; Windows::Foundation::AsyncStatus status = Windows::Foundation::AsyncStatus::Started; int32_t failure = 0; - std::atomic suspending{ true }; + std::atomic suspending = true; void enable_cancellation(cancellable_promise* promise) { diff --git a/strings/base_implements.h b/strings/base_implements.h index 53826d6b6..8016bef28 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1198,7 +1198,7 @@ namespace winrt::impl uintptr_t const encoding = encode_weak_ref(weak_ref.get()); - for (;;) + while (true) { if (m_references.compare_exchange_weak(count_or_pointer, encoding, std::memory_order_acq_rel, std::memory_order_relaxed)) { diff --git a/test/old_tests/UnitTests/handle.cpp b/test/old_tests/UnitTests/handle.cpp index 1b06aac87..f2e69a54d 100644 --- a/test/old_tests/UnitTests/handle.cpp +++ b/test/old_tests/UnitTests/handle.cpp @@ -76,7 +76,7 @@ static void test_put(HANDLE * value) REQUIRE(value != nullptr); REQUIRE(*value == nullptr); - *value = CreateEvent(nullptr, true, true, nullptr);; + *value = CreateEvent(nullptr, true, true, nullptr); } TEST_CASE("handle, put") From 3d83c679eaa5a53bffd3c4de859fc456d5e38ac1 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Thu, 13 Oct 2022 22:40:49 +0800 Subject: [PATCH 123/305] Improve compatibility with mingw-w64 in generated headers (#1200) --- cppwinrt/code_writers.h | 18 +++++++++--------- cppwinrt/component_writers.h | 4 ++-- strings/base_abi.h | 36 ++++++++++++++++++------------------ strings/base_composable.h | 2 +- strings/base_delegate.h | 8 ++++---- strings/base_error.h | 1 - strings/base_extern.h | 8 ++++++++ strings/base_fast_forward.h | 9 ++++++++- strings/base_implements.h | 10 +++++----- strings/base_includes.h | 1 + strings/base_macros.h | 12 ++++++++++++ strings/base_meta.h | 4 ++-- 12 files changed, 70 insertions(+), 43 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index c9f99c9ea..24d45bdf3 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -348,7 +348,7 @@ namespace cppwinrt return; } - auto format = R"( template <%> struct __declspec(empty_bases) %; + auto format = R"( template <%> struct WINRT_IMPL_EMPTY_BASES %; )"; w.write(format, @@ -765,7 +765,7 @@ namespace cppwinrt { auto format = R"( template <> struct abi<%> { - struct __declspec(novtable) type : inspectable_abi + struct WINRT_IMPL_NOVTABLE type : inspectable_abi { )"; @@ -775,7 +775,7 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct __declspec(novtable) type : inspectable_abi + struct WINRT_IMPL_NOVTABLE type : inspectable_abi { )"; @@ -816,7 +816,7 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct __declspec(novtable) type : unknown_abi + struct WINRT_IMPL_NOVTABLE type : unknown_abi { virtual int32_t __stdcall Invoke(%) noexcept = 0; }; @@ -1962,7 +1962,7 @@ namespace cppwinrt static void write_dispatch_overridable(writer& w, TypeDef const& class_type) { auto format = R"(template -struct __declspec(empty_bases) produce_dispatch_to_overridable +struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable : produce_dispatch_to_overridable_base { %}; @@ -2378,7 +2378,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable if (empty(generics)) { - auto format = R"( struct __declspec(empty_bases) % : + auto format = R"( struct WINRT_IMPL_EMPTY_BASES % : winrt::Windows::Foundation::IInspectable, impl::consume_t<%>% { @@ -2401,7 +2401,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable type_name = remove_tick(type_name); auto format = R"( template <%> - struct __declspec(empty_bases) % : + struct WINRT_IMPL_EMPTY_BASES % : winrt::Windows::Foundation::IInspectable, impl::consume_t<%>% {% @@ -3147,7 +3147,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable auto type_name = type.TypeName(); auto factories = get_factories(w, type); - auto format = R"( struct __declspec(empty_bases) % : %%% + auto format = R"( struct WINRT_IMPL_EMPTY_BASES % : %%% { %(std::nullptr_t) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : %(ptr, take_ownership_from_abi) {} @@ -3172,7 +3172,7 @@ struct __declspec(empty_bases) produce_dispatch_to_overridable auto type_name = type.TypeName(); auto factories = get_factories(w, type); - auto format = R"( struct __declspec(empty_bases) % : %% + auto format = R"( struct WINRT_IMPL_EMPTY_BASES % : %% { %(std::nullptr_t) noexcept {} %(void* ptr, take_ownership_from_abi_t) noexcept : %(ptr, take_ownership_from_abi) {} diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index fcfeddac0..1f6a2dbf1 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -743,7 +743,7 @@ catch (...) { return winrt::to_hresult(); } auto format = R"(namespace winrt::@::implementation { template - struct __declspec(empty_bases) %_base : implements%%% + struct WINRT_IMPL_EMPTY_BASES %_base : implements%%% { using base_type = %_base; using class_type = @::%; @@ -836,7 +836,7 @@ catch (...) { return winrt::to_hresult(); } auto format = R"(namespace winrt::@::factory_implementation { template - struct __declspec(empty_bases) %T : implements + struct WINRT_IMPL_EMPTY_BASES %T : implements { using instance_type = @::%; diff --git a/strings/base_abi.h b/strings/base_abi.h index b14e8d85f..d1eab2950 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -3,7 +3,7 @@ namespace winrt::impl { template <> struct abi { - struct __declspec(novtable) type + struct WINRT_IMPL_NOVTABLE type { virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; virtual uint32_t __stdcall AddRef() noexcept = 0; @@ -15,7 +15,7 @@ namespace winrt::impl template <> struct abi { - struct __declspec(novtable) type : unknown_abi + struct WINRT_IMPL_NOVTABLE type : unknown_abi { virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; @@ -27,20 +27,20 @@ namespace winrt::impl template <> struct abi { - struct __declspec(novtable) type : inspectable_abi + struct WINRT_IMPL_NOVTABLE type : inspectable_abi { virtual int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; }; }; - struct __declspec(novtable) IAgileObject : unknown_abi {}; + struct WINRT_IMPL_NOVTABLE IAgileObject : unknown_abi {}; - struct __declspec(novtable) IAgileReference : unknown_abi + struct WINRT_IMPL_NOVTABLE IAgileReference : unknown_abi { virtual int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; }; - struct __declspec(novtable) IMarshal : unknown_abi + struct WINRT_IMPL_NOVTABLE IMarshal : unknown_abi { virtual int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept = 0; virtual int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept = 0; @@ -50,20 +50,20 @@ namespace winrt::impl virtual int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept = 0; }; - struct __declspec(novtable) IGlobalInterfaceTable : unknown_abi + struct WINRT_IMPL_NOVTABLE IGlobalInterfaceTable : unknown_abi { virtual int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, uint32_t* cookie) noexcept = 0; virtual int32_t __stdcall RevokeInterfaceFromGlobal(uint32_t cookie) noexcept = 0; virtual int32_t __stdcall GetInterfaceFromGlobal(uint32_t cookie, guid const& iid, void** object) noexcept = 0; }; - struct __declspec(novtable) IStaticLifetime : inspectable_abi + struct WINRT_IMPL_NOVTABLE IStaticLifetime : inspectable_abi { virtual int32_t __stdcall unused() noexcept = 0; virtual int32_t __stdcall GetCollection(void** value) noexcept = 0; }; - struct __declspec(novtable) IStaticLifetimeCollection : inspectable_abi + struct WINRT_IMPL_NOVTABLE IStaticLifetimeCollection : inspectable_abi { virtual int32_t __stdcall Lookup(void*, void**) noexcept = 0; virtual int32_t __stdcall unused() noexcept = 0; @@ -74,23 +74,23 @@ namespace winrt::impl virtual int32_t __stdcall unused4() noexcept = 0; }; - struct __declspec(novtable) IWeakReference : unknown_abi + struct WINRT_IMPL_NOVTABLE IWeakReference : unknown_abi { virtual int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; }; - struct __declspec(novtable) IWeakReferenceSource : unknown_abi + struct WINRT_IMPL_NOVTABLE IWeakReferenceSource : unknown_abi { virtual int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; }; - struct __declspec(novtable) IRestrictedErrorInfo : unknown_abi + struct WINRT_IMPL_NOVTABLE IRestrictedErrorInfo : unknown_abi { virtual int32_t __stdcall GetErrorDetails(bstr* description, int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; virtual int32_t __stdcall GetReference(bstr* reference) noexcept = 0; }; - struct __declspec(novtable) IErrorInfo : unknown_abi + struct WINRT_IMPL_NOVTABLE IErrorInfo : unknown_abi { virtual int32_t __stdcall GetGUID(guid* value) noexcept = 0; virtual int32_t __stdcall GetSource(bstr* value) noexcept = 0; @@ -99,7 +99,7 @@ namespace winrt::impl virtual int32_t __stdcall GetHelpContext(uint32_t* value) noexcept = 0; }; - struct __declspec(novtable) ILanguageExceptionErrorInfo2 : unknown_abi + struct WINRT_IMPL_NOVTABLE ILanguageExceptionErrorInfo2 : unknown_abi { virtual int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; virtual int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; @@ -109,12 +109,12 @@ namespace winrt::impl struct ICallbackWithNoReentrancyToApplicationSTA; - struct __declspec(novtable) IContextCallback : unknown_abi + struct WINRT_IMPL_NOVTABLE IContextCallback : unknown_abi { virtual int32_t __stdcall ContextCallback(int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; }; - struct __declspec(novtable) IServerSecurity : unknown_abi + struct WINRT_IMPL_NOVTABLE IServerSecurity : unknown_abi { virtual int32_t __stdcall QueryBlanket(uint32_t*, uint32_t*, wchar_t**, uint32_t*, uint32_t*, void**, uint32_t*) noexcept = 0; virtual int32_t __stdcall ImpersonateClient() noexcept = 0; @@ -122,12 +122,12 @@ namespace winrt::impl virtual int32_t __stdcall IsImpersonating() noexcept = 0; }; - struct __declspec(novtable) IBufferByteAccess : unknown_abi + struct WINRT_IMPL_NOVTABLE IBufferByteAccess : unknown_abi { virtual int32_t __stdcall Buffer(uint8_t** value) noexcept = 0; }; - struct __declspec(novtable) IMemoryBufferByteAccess : unknown_abi + struct WINRT_IMPL_NOVTABLE IMemoryBufferByteAccess : unknown_abi { virtual int32_t __stdcall GetBuffer(uint8_t** value, uint32_t* capacity) noexcept = 0; }; diff --git a/strings/base_composable.h b/strings/base_composable.h index efeb55877..7f675c970 100644 --- a/strings/base_composable.h +++ b/strings/base_composable.h @@ -27,7 +27,7 @@ namespace winrt::impl }; template - class __declspec(empty_bases) produce_dispatch_to_overridable_base + class WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable_base { protected: D& shim() noexcept diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 1ba8b4d69..e99fd4813 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -91,7 +91,7 @@ namespace winrt::impl } template - struct __declspec(novtable) variadic_delegate_abi : unknown_abi + struct WINRT_IMPL_NOVTABLE variadic_delegate_abi : unknown_abi { virtual R invoke(Args const& ...) = 0; }; @@ -151,7 +151,7 @@ namespace winrt::impl }; template - struct __declspec(empty_bases) delegate_base : Windows::Foundation::IUnknown + struct WINRT_IMPL_EMPTY_BASES delegate_base : Windows::Foundation::IUnknown { delegate_base(std::nullptr_t = nullptr) noexcept {} delegate_base(void* ptr, take_ownership_from_abi_t) noexcept : IUnknown(ptr, take_ownership_from_abi) {} @@ -201,13 +201,13 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { template - struct __declspec(empty_bases) delegate : impl::delegate_base + struct WINRT_IMPL_EMPTY_BASES delegate : impl::delegate_base { using impl::delegate_base::delegate_base; }; template - struct __declspec(empty_bases) delegate : impl::delegate_base + struct WINRT_IMPL_EMPTY_BASES delegate : impl::delegate_base { using impl::delegate_base::delegate_base; }; diff --git a/strings/base_error.h b/strings/base_error.h index 44b955b95..69e23adbd 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -1,6 +1,5 @@ #if defined(_MSC_VER) -#include #define WINRT_IMPL_RETURNADDRESS() _ReturnAddress() #elif defined(__GNUC__) #define WINRT_IMPL_RETURNADDRESS() __builtin_extract_return_addr(__builtin_return_address(0)) diff --git a/strings/base_extern.h b/strings/base_extern.h index 7782f3bcb..b4e3eeed0 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -83,6 +83,7 @@ extern "C" int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; } +#if defined(_MSC_VER) #ifdef _M_HYBRID #define WINRT_IMPL_LINK(function, count) __pragma(comment(linker, "/alternatename:#WINRT_IMPL_" #function "@" #count "=#" #function "@" #count)) #elif _M_ARM64EC @@ -92,6 +93,13 @@ extern "C" #else #define WINRT_IMPL_LINK(function, count) __pragma(comment(linker, "/alternatename:WINRT_IMPL_" #function "=" #function)) #endif +#elif defined(__GNUC__) +#if defined(__i386__) +#define WINRT_IMPL_LINK(function, count) __asm__(".weak _WINRT_IMPL_" #function "@" #count "\n.set _WINRT_IMPL_" #function "@" #count ", _" #function "@" #count); +#else +#define WINRT_IMPL_LINK(function, count) __asm__(".weak WINRT_IMPL_" #function "\n.set WINRT_IMPL_" #function ", " #function); +#endif +#endif WINRT_IMPL_LINK(LoadLibraryW, 4) WINRT_IMPL_LINK(FreeLibrary, 4) diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 298403197..88d99469a 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -4,6 +4,12 @@ #define WINRT_IMPL_STRING_1(expression) #expression #define WINRT_IMPL_STRING(expression) WINRT_IMPL_STRING_1(expression) +#if defined(_MSC_VER) +#define WINRT_IMPL_FF_NOVTABLE __declspec(novtable) +#else +#define WINRT_IMPL_FF_NOVTABLE +#endif + #if !defined(WINRT_FAST_ABI_SIZE) #define WINRT_FAST_ABI_SIZE % #endif @@ -30,7 +36,7 @@ namespace winrt::impl } }; - struct __declspec(novtable) inspectable + struct WINRT_IMPL_FF_NOVTABLE inspectable { virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; virtual uint32_t __stdcall AddRef() noexcept = 0; @@ -130,3 +136,4 @@ namespace winrt #undef WINRT_IMPL_STRING #undef WINRT_IMPL_STRING_1 +#undef WINRT_IMPL_FF_NOVTABLE diff --git a/strings/base_implements.h b/strings/base_implements.h index 8016bef28..a81df5f8e 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -749,7 +749,7 @@ namespace winrt::impl }; template - struct __declspec(empty_bases) root_implements_composing_outer + struct WINRT_IMPL_EMPTY_BASES root_implements_composing_outer { protected: static constexpr bool is_composing = false; @@ -757,7 +757,7 @@ namespace winrt::impl }; template <> - struct __declspec(empty_bases) root_implements_composing_outer + struct WINRT_IMPL_EMPTY_BASES root_implements_composing_outer { template auto try_as() const noexcept @@ -775,7 +775,7 @@ namespace winrt::impl }; template - struct __declspec(empty_bases) root_implements_composable_inner + struct WINRT_IMPL_EMPTY_BASES root_implements_composable_inner { protected: static constexpr inspectable_abi* outer() noexcept { return nullptr; } @@ -785,7 +785,7 @@ namespace winrt::impl }; template - struct __declspec(empty_bases) root_implements_composable_inner : producer + struct WINRT_IMPL_EMPTY_BASES root_implements_composable_inner : producer { protected: inspectable_abi* outer() noexcept { return m_outer; } @@ -800,7 +800,7 @@ namespace winrt::impl }; template - struct __declspec(novtable) root_implements + struct WINRT_IMPL_NOVTABLE root_implements : root_implements_composing_outer...>> , root_implements_composable_inner...>> , module_lock_updater...>> diff --git a/strings/base_includes.h b/strings/base_includes.h index 8fe598212..d514b415e 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -1,4 +1,5 @@ +#include #include #include #include diff --git a/strings/base_macros.h b/strings/base_macros.h index c1d0617c8..c4ec6645b 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -47,6 +47,18 @@ #define WINRT_IMPL_NOINLINE #endif +#if defined(_MSC_VER) +#define WINRT_IMPL_EMPTY_BASES __declspec(empty_bases) +#else +#define WINRT_IMPL_EMPTY_BASES +#endif + +#if defined(_MSC_VER) +#define WINRT_IMPL_NOVTABLE __declspec(novtable) +#else +#define WINRT_IMPL_NOVTABLE +#endif + #ifdef __IUnknown_INTERFACE_DEFINED__ #define WINRT_IMPL_IUNKNOWN_DEFINED #else diff --git a/strings/base_meta.h b/strings/base_meta.h index 0e800c49f..061a9f587 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -171,7 +171,7 @@ namespace winrt::impl }; template - struct __declspec(empty_bases) require : require_one... + struct WINRT_IMPL_EMPTY_BASES require : require_one... {}; template @@ -184,7 +184,7 @@ namespace winrt::impl }; template - struct __declspec(empty_bases) base : base_one... + struct WINRT_IMPL_EMPTY_BASES base : base_one... {}; template From 3ff66312a92d98655b14b3cab0a725d56901b2f6 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Sat, 15 Oct 2022 06:15:09 +0800 Subject: [PATCH 124/305] Add GitHub Action build and test workflow for MSVC (#1201) --- .github/workflows/msvc.yml | 70 ++++++++++++++++++++++++++++++++++++++ .gitignore | 3 +- run_tests.cmd | 8 ++++- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/msvc.yml diff --git a/.github/workflows/msvc.yml b/.github/workflows/msvc.yml new file mode 100644 index 000000000..31cc53512 --- /dev/null +++ b/.github/workflows/msvc.yml @@ -0,0 +1,70 @@ +name: MSVC Tests +on: + push: + pull_request: + branches: + - master + +jobs: + test-cppwinrt: + strategy: + matrix: + arch: [x86, x64, arm64] + config: [Debug, Release] + exclude: + - arch: arm64 + config: Debug + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Test all + run: | + $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat + if (!$VSDevCmd) { return 1 } + echo "Using VSDevCmd: ${VSDevCmd}" + cmd /c "${VSDevCmd}" "&" build_test_all.cmd ${{ matrix.arch }} ${{ matrix.config }} + + - name: Upload test log + if: matrix.arch != 'arm64' + uses: actions/upload-artifact@v3 + with: + name: test-output-${{ matrix.arch }}-${{ matrix.config }} + path: "*_results.txt" + + - name: Check test failure + if: matrix.arch != 'arm64' + run: | + if (Test-Path "test_failures.txt") { + Get-Content "test_failures.txt" | ForEach-Object { + Write-Error "error: Test '$_' failed!" + } + return 1 + } + if (!(Test-Path "*_results.txt")) { + Write-Error "error: No test output found!" + return 1 + } + + build-nuget: + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Package + run: | + $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat + if (!$VSDevCmd) { return 1 } + echo "Using VSDevCmd: ${VSDevCmd}" + cmd /c "${VSDevCmd}" "&" nuget.exe restore cppwinrt.sln + cmd /c "${VSDevCmd}" "&" build_nuget.cmd + if (!(Test-Path "*.nupkg")) { + Write-Error "error: Output nuget package not found!" + return 1 + } + + - name: Upload nuget package artifact + uses: actions/upload-artifact@v3 + with: + name: package + path: "*.nupkg" diff --git a/.gitignore b/.gitignore index 39ccd342c..9493fdad5 100644 --- a/.gitignore +++ b/.gitignore @@ -8,10 +8,11 @@ *.nupkg test*.xml test*_results.txt +test_failures.txt build packages Debug Release Generated Files obj -vsix/LICENSE \ No newline at end of file +vsix/LICENSE diff --git a/run_tests.cmd b/run_tests.cmd index 86ec520e1..cde12b1ec 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -21,5 +21,11 @@ goto :eof :run_test if not "%target_version%"=="" set args=-o %1-%target_version%.xml -r junit rem Buffer output and redirect to stdout/stderr depending whether the test executable exits successfully. Pipeline will fail if there's any output to stderr. -_build\%target_platform%\%target_configuration%\%1.exe %args% > %1_results.txt && type %1_results.txt || type %1_results.txt >&2 +_build\%target_platform%\%target_configuration%\%1.exe %args% > %1_results.txt +if %ERRORLEVEL% EQU 0 ( + type %1_results.txt +) else ( + type %1_results.txt >&2 + echo %1 >> test_failures.txt +) goto :eof From 956c8d29c5e370b0bb522f656f9d1784b716a56c Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Mon, 17 Oct 2022 22:25:56 +0800 Subject: [PATCH 125/305] Various fixes for tests/CI (#1206) --- .github/workflows/{msvc.yml => ci.yml} | 22 ++++++++++++---------- test/old_tests/UnitTests/Errors.cpp | 20 ++++++++++---------- test/old_tests/UnitTests/array.cpp | 6 +++--- test/old_tests/UnitTests/async.cpp | 14 ++++++++++---- test/old_tests/UnitTests/hresult_error.cpp | 18 +++++++++--------- test/test/async_auto_cancel.cpp | 16 +++++++++++----- test/test/async_cancel_callback.cpp | 14 ++++++++++---- test/test/async_check_cancel.cpp | 14 ++++++++++---- test/test/async_ref_result.cpp | 12 +++++++++--- test/test/error_info.cpp | 10 +++++----- test/test/hresult_class_not_registered.cpp | 4 ++-- test/test/multi_threaded_map.cpp | 4 ++-- test/test/notify_awaiter.cpp | 4 ++++ test/test/when.cpp | 8 +++++++- test/test_cpp20/main.cpp | 1 + test/test_fast/main.cpp | 1 + test/test_fast_fwd/main.cpp | 1 + test/test_module_lock_custom/main.cpp | 1 + test/test_module_lock_none/main.cpp | 1 + test/test_slow/main.cpp | 1 + test/test_win7/async_auto_cancel.cpp | 14 ++++++++++---- test/test_win7/async_cancel_callback.cpp | 14 ++++++++++---- test/test_win7/async_check_cancel.cpp | 14 ++++++++++---- 23 files changed, 140 insertions(+), 74 deletions(-) rename .github/workflows/{msvc.yml => ci.yml} (81%) diff --git a/.github/workflows/msvc.yml b/.github/workflows/ci.yml similarity index 81% rename from .github/workflows/msvc.yml rename to .github/workflows/ci.yml index 31cc53512..abcd8fd2e 100644 --- a/.github/workflows/msvc.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: MSVC Tests +name: CI Tests on: push: pull_request: @@ -6,7 +6,8 @@ on: - master jobs: - test-cppwinrt: + test-msvc-cppwinrt: + name: 'MSVC: Tests' strategy: matrix: arch: [x86, x64, arm64] @@ -21,7 +22,7 @@ jobs: - name: Test all run: | $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat - if (!$VSDevCmd) { return 1 } + if (!$VSDevCmd) { exit 1 } echo "Using VSDevCmd: ${VSDevCmd}" cmd /c "${VSDevCmd}" "&" build_test_all.cmd ${{ matrix.arch }} ${{ matrix.config }} @@ -37,16 +38,17 @@ jobs: run: | if (Test-Path "test_failures.txt") { Get-Content "test_failures.txt" | ForEach-Object { - Write-Error "error: Test '$_' failed!" + echo "::error::Test '$_' failed!" } - return 1 + exit 1 } if (!(Test-Path "*_results.txt")) { - Write-Error "error: No test output found!" - return 1 + echo "::error::No test output found!" + exit 1 } build-nuget: + name: Build nuget package with MSVC runs-on: windows-latest steps: - uses: actions/checkout@v3 @@ -54,13 +56,13 @@ jobs: - name: Package run: | $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat - if (!$VSDevCmd) { return 1 } + if (!$VSDevCmd) { exit 1 } echo "Using VSDevCmd: ${VSDevCmd}" cmd /c "${VSDevCmd}" "&" nuget.exe restore cppwinrt.sln cmd /c "${VSDevCmd}" "&" build_nuget.cmd if (!(Test-Path "*.nupkg")) { - Write-Error "error: Output nuget package not found!" - return 1 + echo "::error::Output nuget package not found!" + exit 1 } - name: Upload nuget package artifact diff --git a/test/old_tests/UnitTests/Errors.cpp b/test/old_tests/UnitTests/Errors.cpp index 85a2d2a60..000e93851 100644 --- a/test/old_tests/UnitTests/Errors.cpp +++ b/test/old_tests/UnitTests/Errors.cpp @@ -93,7 +93,7 @@ TEST_CASE("Errors") try { init_apartment(apartment_type::single_threaded); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const & e) { @@ -104,7 +104,7 @@ TEST_CASE("Errors") try { Uri uri(L"BAD"); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const & e) // catching specific exception type { @@ -115,7 +115,7 @@ TEST_CASE("Errors") try { Uri uri(L"BAD"); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const& e) { @@ -128,7 +128,7 @@ TEST_CASE("Errors") { Errors errors; errors.Propagate(); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const & e) // catching specific exception type { @@ -140,7 +140,7 @@ TEST_CASE("Errors") { Errors errors; errors.Fail(L"Failure message"); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_not_implemented const& e) { @@ -158,7 +158,7 @@ TEST_CASE("Errors") { Errors errors; errors.std_out_of_range(); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_out_of_bounds const& e) { @@ -169,7 +169,7 @@ TEST_CASE("Errors") { Errors errors; errors.std_invalid_argument(); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const& e) { @@ -180,7 +180,7 @@ TEST_CASE("Errors") { Errors errors; errors.std_exception(); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const& e) { @@ -207,7 +207,7 @@ TEST_CASE("Errors") try { check_win32(ERROR_NO_NETWORK); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const& e) { @@ -220,7 +220,7 @@ TEST_CASE("Errors") try { check_nt(STATUS_STACK_OVERFLOW); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const& e) { diff --git a/test/old_tests/UnitTests/array.cpp b/test/old_tests/UnitTests/array.cpp index bb3901564..3fc499bec 100644 --- a/test/old_tests/UnitTests/array.cpp +++ b/test/old_tests/UnitTests/array.cpp @@ -344,7 +344,7 @@ TEST_CASE("array,at,throw") try { a.at(3); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (std::out_of_range const & e) { @@ -357,7 +357,7 @@ TEST_CASE("array,at,throw") try { test_array_ref_at_throw({ 1, 2, 3 }); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (std::out_of_range const & e) { @@ -372,7 +372,7 @@ TEST_CASE("array,at,throw") try { a.at(5); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (std::out_of_range const & e) { diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 4452e6db4..817226c6d 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -14,6 +14,12 @@ using namespace std::chrono; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + IAsyncAction NoSuspend_IAsyncAction() { co_await 0s; @@ -1032,7 +1038,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await std::experimental::suspend_never{}; + co_await suspend_never{}; REQUIRE(false); } @@ -1040,7 +1046,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await std::experimental::suspend_never{}; + co_await suspend_never{}; REQUIRE(false); } @@ -1048,7 +1054,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await std::experimental::suspend_never{}; + co_await suspend_never{}; REQUIRE(false); co_return 0; } @@ -1057,7 +1063,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await std::experimental::suspend_never{}; + co_await suspend_never{}; REQUIRE(false); co_return 0; } diff --git a/test/old_tests/UnitTests/hresult_error.cpp b/test/old_tests/UnitTests/hresult_error.cpp index b9db219f4..1acac1565 100644 --- a/test/old_tests/UnitTests/hresult_error.cpp +++ b/test/old_tests/UnitTests/hresult_error.cpp @@ -23,7 +23,7 @@ TEST_CASE("hresult,S_FALSE") try { check_hresult(S_FALSE); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const & e) { @@ -40,7 +40,7 @@ TEST_CASE("hresult,init_apartment") try { init_apartment(apartment_type::single_threaded); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const & e) { @@ -55,7 +55,7 @@ TEST_CASE("hresult,restricted,consuming") try { Uri uri(L"BAD"); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const & e) // catching specific exception type { @@ -66,7 +66,7 @@ TEST_CASE("hresult,restricted,consuming") try { Uri uri(L"BAD"); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const & e) // catching generic exception type { @@ -501,7 +501,7 @@ TEST_CASE("hresult, std abi support") }; handler(nullptr, 0); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const& e) { @@ -517,7 +517,7 @@ TEST_CASE("hresult, std abi support") }; handler(nullptr, 0); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (std::bad_alloc const&) { @@ -531,7 +531,7 @@ TEST_CASE("hresult, std abi support") }; handler(nullptr, 0); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_out_of_bounds const& e) { @@ -547,7 +547,7 @@ TEST_CASE("hresult, std abi support") }; handler(nullptr, 0); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const& e) { @@ -575,4 +575,4 @@ TEST_CASE("hresult, to_message") { REQUIRE(to_message() == L"oh no, invalid handle"); } -} \ No newline at end of file +} diff --git a/test/test/async_auto_cancel.cpp b/test/test/async_auto_cancel.cpp index 2b1fdc728..bb49a9f5b 100644 --- a/test/test/async_auto_cancel.cpp +++ b/test/test/async_auto_cancel.cpp @@ -5,6 +5,12 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + // // Checks that the coroutine is automatically canceled when reaching a suspension point. // @@ -12,21 +18,21 @@ namespace IAsyncAction Action(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } IAsyncActionWithProgress ActionWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } IAsyncOperation Operation(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } @@ -34,7 +40,7 @@ namespace IAsyncOperationWithProgress OperationWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } @@ -48,7 +54,7 @@ namespace auto cancel = co_await get_cancellation_token(); cancel.callback(nullptr); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } diff --git a/test/test/async_cancel_callback.cpp b/test/test/async_cancel_callback.cpp index a69575a88..45699142b 100644 --- a/test/test/async_cancel_callback.cpp +++ b/test/test/async_cancel_callback.cpp @@ -5,6 +5,12 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + // // Checks that the cancellation callback is invoked. // @@ -23,7 +29,7 @@ namespace }(); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -38,7 +44,7 @@ namespace }); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -53,7 +59,7 @@ namespace }); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } @@ -69,7 +75,7 @@ namespace }); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index 38d21f48b..7ec697927 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -5,6 +5,12 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + // // Checks that manual cancellation checks work. // @@ -20,7 +26,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -35,7 +41,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -50,7 +56,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } @@ -66,7 +72,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test/async_ref_result.cpp b/test/test/async_ref_result.cpp index 015bb7b31..31cd1ce29 100644 --- a/test/test/async_ref_result.cpp +++ b/test/test/async_ref_result.cpp @@ -5,6 +5,12 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + // // Checks that references returned by awaitables // are not accidentally decayed. @@ -12,14 +18,14 @@ namespace // This test "runs" at compile time via static_assert. template - struct awaitable : std::experimental::suspend_never + struct awaitable : suspend_never { std::decay_t value; T await_resume() { return static_cast(value); } }; template - struct awaitable_member_awaiter : std::experimental::suspend_never + struct awaitable_member_awaiter : suspend_never { decltype(auto) get_awaiter() { return *this; } std::decay_t value; @@ -27,7 +33,7 @@ namespace }; template - struct awaitable_free_awaiter : std::experimental::suspend_never + struct awaitable_free_awaiter : suspend_never { std::decay_t value; T await_resume() { return static_cast(value); } diff --git a/test/test/error_info.cpp b/test/test/error_info.cpp index 5b312c451..96e2b2731 100644 --- a/test/test/error_info.cpp +++ b/test/test/error_info.cpp @@ -35,7 +35,7 @@ TEST_CASE("error_info") try { check_hresult(winrt_error_info()); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const& e) { @@ -45,7 +45,7 @@ TEST_CASE("error_info") try { check_hresult(com_error_info()); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const& e) { @@ -55,7 +55,7 @@ TEST_CASE("error_info") try { check_hresult(no_error_info()); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const& e) { @@ -66,7 +66,7 @@ TEST_CASE("error_info") { // This API reports using WinRT error info. Windows::Foundation::Uri(L"bad"); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_invalid_argument const& e) { @@ -78,7 +78,7 @@ TEST_CASE("error_info") // This API reports using COM error info. Windows::Data::Xml::Dom::XmlDocument doc; doc.LoadXml(L"bad"); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_error const& e) { diff --git a/test/test/hresult_class_not_registered.cpp b/test/test/hresult_class_not_registered.cpp index d1717569a..78223030a 100644 --- a/test/test/hresult_class_not_registered.cpp +++ b/test/test/hresult_class_not_registered.cpp @@ -20,11 +20,11 @@ TEST_CASE("hresult_class_not_registered") try { Async().get(); - FAIL(L"Previous line should throw"); + FAIL("Previous line should throw"); } catch (hresult_class_not_registered const& e) { REQUIRE(e.message() == L"test message"); REQUIRE(e.code() == REGDB_E_CLASSNOTREG); } -} \ No newline at end of file +} diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index 2f81d3789..b2b143f11 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -63,7 +63,7 @@ namespace } else { - return static_cast>(winrt::make>(std::move(values))); + return static_cast>(winrt::make>(std::move(values))); } } @@ -171,7 +171,7 @@ namespace auto hook = raw.hook; // Convert the raw_map into the desired Windows Runtime map interface. - auto m = make_threaded_map(std::move(raw)); + auto m = make_threaded_map(std::move(raw)); auto race = [&](collection_action action, auto&& background, auto&& foreground) { diff --git a/test/test/notify_awaiter.cpp b/test/test/notify_awaiter.cpp index dd936928a..de2c5f1ab 100644 --- a/test/test/notify_awaiter.cpp +++ b/test/test/notify_awaiter.cpp @@ -5,7 +5,11 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else using std::experimental::suspend_never; +#endif // Never suspends. // Allows copying, but asserts if you try. diff --git a/test/test/when.cpp b/test/test/when.cpp index 86edc6c77..35c9287a8 100644 --- a/test/test/when.cpp +++ b/test/test/when.cpp @@ -5,7 +5,13 @@ using namespace concurrency; using namespace winrt; using namespace Windows::Foundation; -struct CommaStruct : std::experimental::suspend_never +#ifdef __cpp_lib_coroutine +using std::suspend_never; +#else +using std::experimental::suspend_never; +#endif + +struct CommaStruct : suspend_never { // If the comma operator is invoked, we will get a build failure. CommaStruct operator,(CommaStruct) = delete; diff --git a/test/test_cpp20/main.cpp b/test/test_cpp20/main.cpp index 7873e4ee7..7c55cbbed 100644 --- a/test/test_cpp20/main.cpp +++ b/test/test_cpp20/main.cpp @@ -7,6 +7,7 @@ using namespace winrt; int main(int const argc, char** argv) { init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); return Catch::Session().run(argc, argv); } diff --git a/test/test_fast/main.cpp b/test/test_fast/main.cpp index 7873e4ee7..7c55cbbed 100644 --- a/test/test_fast/main.cpp +++ b/test/test_fast/main.cpp @@ -7,6 +7,7 @@ using namespace winrt; int main(int const argc, char** argv) { init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); return Catch::Session().run(argc, argv); } diff --git a/test/test_fast_fwd/main.cpp b/test/test_fast_fwd/main.cpp index f9b9c73d2..2ddbfe115 100644 --- a/test/test_fast_fwd/main.cpp +++ b/test/test_fast_fwd/main.cpp @@ -10,6 +10,7 @@ using namespace winrt; int main(int const argc, char** argv) { init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); return Catch::Session().run(argc, argv); } diff --git a/test/test_module_lock_custom/main.cpp b/test/test_module_lock_custom/main.cpp index 1372f2554..5f9a7913e 100644 --- a/test/test_module_lock_custom/main.cpp +++ b/test/test_module_lock_custom/main.cpp @@ -60,5 +60,6 @@ TEST_CASE("module_lock_custom") int main(int const argc, char** argv) { + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); return Catch::Session().run(argc, argv); } diff --git a/test/test_module_lock_none/main.cpp b/test/test_module_lock_none/main.cpp index 6fb4d379f..f34ece5ab 100644 --- a/test/test_module_lock_none/main.cpp +++ b/test/test_module_lock_none/main.cpp @@ -65,5 +65,6 @@ TEST_CASE("module_lock_none") int main(int const argc, char** argv) { + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); return Catch::Session().run(argc, argv); } diff --git a/test/test_slow/main.cpp b/test/test_slow/main.cpp index 7873e4ee7..7c55cbbed 100644 --- a/test/test_slow/main.cpp +++ b/test/test_slow/main.cpp @@ -7,6 +7,7 @@ using namespace winrt; int main(int const argc, char** argv) { init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); return Catch::Session().run(argc, argv); } diff --git a/test/test_win7/async_auto_cancel.cpp b/test/test_win7/async_auto_cancel.cpp index 45ff30fcf..e5e3dd776 100644 --- a/test/test_win7/async_auto_cancel.cpp +++ b/test/test_win7/async_auto_cancel.cpp @@ -5,6 +5,12 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + // // Checks that the coroutine is automatically canceled when reaching a suspension point. // @@ -12,21 +18,21 @@ namespace IAsyncAction Action(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } IAsyncActionWithProgress ActionWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } IAsyncOperation Operation(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } @@ -34,7 +40,7 @@ namespace IAsyncOperationWithProgress OperationWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test_win7/async_cancel_callback.cpp b/test/test_win7/async_cancel_callback.cpp index 0ab5b6bb1..8e20d01ec 100644 --- a/test/test_win7/async_cancel_callback.cpp +++ b/test/test_win7/async_cancel_callback.cpp @@ -5,6 +5,12 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + // // Checks that the cancellation callback is invoked. // @@ -20,7 +26,7 @@ namespace }); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -35,7 +41,7 @@ namespace }); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -50,7 +56,7 @@ namespace }); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } @@ -66,7 +72,7 @@ namespace }); co_await resume_on_signal(event); - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test_win7/async_check_cancel.cpp b/test/test_win7/async_check_cancel.cpp index 38d21f48b..7ec697927 100644 --- a/test/test_win7/async_check_cancel.cpp +++ b/test/test_win7/async_check_cancel.cpp @@ -5,6 +5,12 @@ using namespace Windows::Foundation; namespace { +#ifdef __cpp_lib_coroutine + using std::suspend_never; +#else + using std::experimental::suspend_never; +#endif + // // Checks that manual cancellation checks work. // @@ -20,7 +26,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -35,7 +41,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); } @@ -50,7 +56,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } @@ -66,7 +72,7 @@ namespace canceled = true; } - co_await std::experimental::suspend_never(); + co_await suspend_never(); REQUIRE(false); co_return 1; } From d3aa5db0990b08a7d2fdbeb5c69da45e6cdd6ee5 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 18 Oct 2022 21:28:35 +0800 Subject: [PATCH 126/305] Improve CI jobs split (#1210) --- .github/workflows/ci.yml | 234 ++++++++++++++++++++++++-- Directory.Build.Props | 1 + test/old_tests/UnitTests/Main.cpp | 5 + test/test/disconnected.cpp | 136 +++++++-------- test/test/main.cpp | 5 + test/test_cpp20/main.cpp | 5 + test/test_fast/main.cpp | 5 + test/test_fast_fwd/main.cpp | 5 + test/test_module_lock_custom/main.cpp | 5 + test/test_module_lock_none/main.cpp | 5 + test/test_slow/main.cpp | 5 + test/test_win7/disconnected.cpp | 136 +++++++-------- test/test_win7/main.cpp | 5 + 13 files changed, 403 insertions(+), 149 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index abcd8fd2e..315983297 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,8 +6,8 @@ on: - master jobs: - test-msvc-cppwinrt: - name: 'MSVC: Tests' + test-msvc-cppwinrt-build: + name: 'MSVC: Build' strategy: matrix: arch: [x86, x64, arm64] @@ -19,33 +19,237 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Test all + - name: Download nuget + run: | + mkdir ".\.nuget" + Invoke-WebRequest "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile ".\.nuget\nuget.exe" + + - name: Find VsDevCmd.bat run: | $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat if (!$VSDevCmd) { exit 1 } echo "Using VSDevCmd: ${VSDevCmd}" - cmd /c "${VSDevCmd}" "&" build_test_all.cmd ${{ matrix.arch }} ${{ matrix.config }} + Add-Content $env:GITHUB_ENV "VSDevCmd=$VSDevCmd" + + - name: Prepare build flags + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + $target_version = "1.2.3.4" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + + - name: Restore nuget packages + run: | + cmd /c "$env:VSDevCmd" "&" nuget restore cppwinrt.sln + + - name: Build fast_fwd + run: | + cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" cppwinrt.sln /t:fast_fwd + + - name: Build cppwinrt + if: matrix.arch != 'arm64' + run: | + cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - - name: Upload test log + - name: Upload built executables if: matrix.arch != 'arm64' uses: actions/upload-artifact@v3 with: - name: test-output-${{ matrix.arch }}-${{ matrix.config }} - path: "*_results.txt" + name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + path: | + _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe + _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll + _build/${{ matrix.arch }}/${{ matrix.config }}/*.winmd + _build/${{ matrix.arch }}/${{ matrix.config }}/*.lib + _build/${{ matrix.arch }}/${{ matrix.config }}/*.pdb - - name: Check test failure + - name: Run cppwinrt to build projection if: matrix.arch != 'arm64' run: | - if (Test-Path "test_failures.txt") { - Get-Content "test_failures.txt" | ForEach-Object { - echo "::error::Test '$_' failed!" - } - exit 1 + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose + + test-msvc-cppwinrt-test: + name: 'MSVC: Tests' + needs: test-msvc-cppwinrt-build + strategy: + fail-fast: false + matrix: + arch: [x86, x64] + config: [Debug, Release] + test_exe: [test, test_cpp20, test_win7, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Fetch cppwinrt executables + uses: actions/download-artifact@v3 + with: + name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + path: _build/${{ matrix.arch }}/${{ matrix.config }}/ + + - name: Download nuget + run: | + mkdir ".\.nuget" + Invoke-WebRequest "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile ".\.nuget\nuget.exe" + + - name: Find VsDevCmd.bat + run: | + $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat + if (!$VSDevCmd) { exit 1 } + echo "Using VSDevCmd: ${VSDevCmd}" + Add-Content $env:GITHUB_ENV "VSDevCmd=$VSDevCmd" + + - name: Prepare build flags + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + $target_version = "1.2.3.4" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + + - name: Restore nuget packages + run: | + cmd /c "$env:VSDevCmd" "&" nuget restore cppwinrt.sln + + - name: Remove cppwinrt dependency from all test projects + run: | + # HACK: We already have a built exe, so we want to avoid rebuilding cppwinrt + mv cppwinrt.sln cppwinrt.sln.orig + Get-Content cppwinrt.sln.orig | + Where-Object { -not $_.Contains("{D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}") } | + Set-Content cppwinrt.sln + + - name: Patch catch.hpp to make it build with ANSI colour + run: | + # HACK: Remove include and the isatty call in catch.hpp to make ANSI colour build work + mv test/catch.hpp test/catch.hpp.orig + Get-Content test/catch.hpp.orig | + Where-Object { -not $_.Contains("#include ") } | + ForEach-Object { + $_.Replace("isatty(STDOUT_FILENO)", "false") + } | + Set-Content test/catch.hpp + + - name: Run cppwinrt to build projection + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose + + - name: Build test '${{ matrix.test_exe }}' + run: | + $test_proj = "${{ matrix.test_exe }}" + if ($test_proj -eq "test_old") { + $test_proj = "old_tests\test_old" } - if (!(Test-Path "*_results.txt")) { - echo "::error::No test output found!" + + cmd /c "$env:VSDevCmd" "&" msbuild /m /p:TestsUseAnsiColor=1 "$env:msbuild_config_props" cppwinrt.sln /t:test\$test_proj + + - name: Run test '${{ matrix.test_exe }}' + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + $test_exe = "${{ matrix.test_exe }}" + $test_path = "_build\$target_platform\$target_configuration\$test_exe.exe" + if (!(Test-Path $test_path)) { + echo "::error::Test $test_exe is missing." exit 1 } + & $test_path --use-colour yes + + build-msvc-natvis: + name: 'Build natvis' + strategy: + matrix: + arch: [x86, x64, arm64] + config: [Release] + Deployment: [Component, Standalone] + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Download nuget + run: | + mkdir ".\.nuget" + Invoke-WebRequest "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile ".\.nuget\nuget.exe" + + - name: Find VsDevCmd.bat + run: | + $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat + if (!$VSDevCmd) { exit 1 } + echo "Using VSDevCmd: ${VSDevCmd}" + Add-Content $env:GITHUB_ENV "VSDevCmd=$VSDevCmd" + + - name: Prepare build flags + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + $target_version = "1.2.3.4" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + + - name: Restore nuget packages + run: | + cmd /c "$env:VSDevCmd" "&" nuget restore natvis\cppwinrtvisualizer.sln + + - name: Build natvis + run: | + cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln + + build-msvc-nuget-test: + name: 'Build nuget test' + needs: test-msvc-cppwinrt-build + strategy: + matrix: + arch: [x86, x64] + config: [Release] + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Fetch cppwinrt executables + uses: actions/download-artifact@v3 + with: + name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + path: _build/${{ matrix.arch }}/${{ matrix.config }}/ + + - name: Download nuget + run: | + mkdir ".\.nuget" + Invoke-WebRequest "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" -OutFile ".\.nuget\nuget.exe" + + - name: Find VsDevCmd.bat + run: | + $VSDevCmd = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere" -latest -find Common7\tools\VSDevCmd.bat + if (!$VSDevCmd) { exit 1 } + echo "Using VSDevCmd: ${VSDevCmd}" + Add-Content $env:GITHUB_ENV "VSDevCmd=$VSDevCmd" + + - name: Prepare build flags + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + $target_version = "1.2.3.4" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + + - name: Restore nuget packages + run: | + cmd /c "$env:VSDevCmd" "&" nuget restore test\nuget\NugetTest.sln + + - name: Run cppwinrt to build projection + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose + + - name: Run nuget test + run: | + cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" test\nuget\NugetTest.sln + if ($LastExitCode -ne 0) { + echo "::warning::nuget test failed" + } + # FIXME: This build was failing from the start + exit 0 build-nuget: name: Build nuget package with MSVC diff --git a/Directory.Build.Props b/Directory.Build.Props index abbedf15b..38ad08350 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -51,6 +51,7 @@ Use pch.h CPPWINRT_VERSION_STRING="$(CppWinRTBuildVersion)";%(PreprocessorDefinitions) + CATCH_CONFIG_COLOUR_ANSI;%(PreprocessorDefinitions) true /bigobj /await %(AdditionalOptions) diff --git a/test/old_tests/UnitTests/Main.cpp b/test/old_tests/UnitTests/Main.cpp index de63b39fc..da790c357 100644 --- a/test/old_tests/UnitTests/Main.cpp +++ b/test/old_tests/UnitTests/Main.cpp @@ -1,3 +1,4 @@ +#include #include "pch.h" #define CATCH_CONFIG_RUNNER @@ -9,6 +10,10 @@ int main(int argc, char * argv[]) init_apartment(); std::set_terminate([]{ reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); int const result = Catch::Session().run(argc, argv); // Completely unnecessary in an app, but useful for testing clear_factory_cache behavior. diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 41733e2f8..5a6b40e90 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -44,94 +44,96 @@ namespace } } -TEST_CASE("disconnected,handler") +TEST_CASE("disconnected,handler,1") { - { - event> source; + event> source; - source.add([](auto...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); + source.add([](auto...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); - auto token = source.add([](auto...) - { - throw hresult_error(E_INVALIDARG); - }); + auto token = source.add([](auto...) + { + throw hresult_error(E_INVALIDARG); + }); - // Should have two delegates - REQUIRE(source); + // Should have two delegates + REQUIRE(source); - // Should lose the disconnected delegate - source(nullptr, 123); - REQUIRE(source); + // Should lose the disconnected delegate + source(nullptr, 123); + REQUIRE(source); - // Fire the remaining delegate - source(nullptr, 123); - REQUIRE(source); + // Fire the remaining delegate + source(nullptr, 123); + REQUIRE(source); - // Remove the final delegate - source.remove(token); + // Remove the final delegate + source.remove(token); - // No more delegates - REQUIRE(!source); + // No more delegates + REQUIRE(!source); - source(nullptr, 123); - } + source(nullptr, 123); +} - { - auto async = Action(); +TEST_CASE("disconnected,handler,2") +{ + auto async = Action(); - async.Completed([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); - } + async.Completed([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); +} - { - auto async = ActionProgress(); - handle signal{ CreateEventW(nullptr, true, false, nullptr) }; +TEST_CASE("disconnected,handler,3") +{ + auto async = ActionProgress(); + handle signal{ CreateEventW(nullptr, true, false, nullptr) }; - async.Progress([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Progress([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); - async.Completed([&](auto&&...) - { - SetEvent(signal.get()); - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Completed([&](auto&&...) + { + SetEvent(signal.get()); + throw hresult_error(RPC_E_DISCONNECTED); + }); - WaitForSingleObject(signal.get(), INFINITE); - } + WaitForSingleObject(signal.get(), INFINITE); +} - { - auto async = Operation(); +TEST_CASE("disconnected,handler,4") +{ + auto async = Operation(); - async.Completed([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); - } + async.Completed([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); +} - { - auto async = OperationProgress(); - handle signal{ CreateEventW(nullptr, true, false, nullptr) }; +TEST_CASE("disconnected,handler,5") +{ + auto async = OperationProgress(); + handle signal{ CreateEventW(nullptr, true, false, nullptr) }; - async.Progress([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Progress([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); - async.Completed([&](auto&&...) - { - SetEvent(signal.get()); - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Completed([&](auto&&...) + { + SetEvent(signal.get()); + throw hresult_error(RPC_E_DISCONNECTED); + }); - WaitForSingleObject(signal.get(), INFINITE); - } + WaitForSingleObject(signal.get(), INFINITE); } // Custom action to simulate an out-of-process server that crashes before it can complete. diff --git a/test/test/main.cpp b/test/test/main.cpp index 7c55cbbed..cb2203171 100644 --- a/test/test/main.cpp +++ b/test/test/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" #include "winrt/base.h" @@ -8,6 +9,10 @@ int main(int const argc, char** argv) { init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_cpp20/main.cpp b/test/test_cpp20/main.cpp index 7c55cbbed..cb2203171 100644 --- a/test/test_cpp20/main.cpp +++ b/test/test_cpp20/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" #include "winrt/base.h" @@ -8,6 +9,10 @@ int main(int const argc, char** argv) { init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_fast/main.cpp b/test/test_fast/main.cpp index 7c55cbbed..cb2203171 100644 --- a/test/test_fast/main.cpp +++ b/test/test_fast/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" #include "winrt/base.h" @@ -8,6 +9,10 @@ int main(int const argc, char** argv) { init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_fast_fwd/main.cpp b/test/test_fast_fwd/main.cpp index 2ddbfe115..88d30fba3 100644 --- a/test/test_fast_fwd/main.cpp +++ b/test/test_fast_fwd/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" #include "winrt/base.h" @@ -11,6 +12,10 @@ int main(int const argc, char** argv) { init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_module_lock_custom/main.cpp b/test/test_module_lock_custom/main.cpp index 5f9a7913e..6680fdb51 100644 --- a/test/test_module_lock_custom/main.cpp +++ b/test/test_module_lock_custom/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" @@ -61,5 +62,9 @@ TEST_CASE("module_lock_custom") int main(int const argc, char** argv) { std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_module_lock_none/main.cpp b/test/test_module_lock_none/main.cpp index f34ece5ab..ad6d83ace 100644 --- a/test/test_module_lock_none/main.cpp +++ b/test/test_module_lock_none/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" #include @@ -66,5 +67,9 @@ TEST_CASE("module_lock_none") int main(int const argc, char** argv) { std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_slow/main.cpp b/test/test_slow/main.cpp index 7c55cbbed..cb2203171 100644 --- a/test/test_slow/main.cpp +++ b/test/test_slow/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" #include "winrt/base.h" @@ -8,6 +9,10 @@ int main(int const argc, char** argv) { init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_win7/disconnected.cpp b/test/test_win7/disconnected.cpp index 583b7df36..b893ff5d1 100644 --- a/test/test_win7/disconnected.cpp +++ b/test/test_win7/disconnected.cpp @@ -33,92 +33,94 @@ namespace } } -TEST_CASE("disconnected") +TEST_CASE("disconnected,1") { - { - event> source; + event> source; - source.add([](auto...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); + source.add([](auto...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); - auto token = source.add([](auto...) - { - throw hresult_error(E_INVALIDARG); - }); + auto token = source.add([](auto...) + { + throw hresult_error(E_INVALIDARG); + }); - // Should have two delegates - REQUIRE(source); + // Should have two delegates + REQUIRE(source); - // Should lose the disconnected delegate - source(nullptr, 123); - REQUIRE(source); + // Should lose the disconnected delegate + source(nullptr, 123); + REQUIRE(source); - // Fire the remaining delegate - source(nullptr, 123); - REQUIRE(source); + // Fire the remaining delegate + source(nullptr, 123); + REQUIRE(source); - // Remove the final delegate - source.remove(token); + // Remove the final delegate + source.remove(token); - // No more delegates - REQUIRE(!source); + // No more delegates + REQUIRE(!source); - source(nullptr, 123); - } + source(nullptr, 123); +} - { - auto async = Action(); +TEST_CASE("disconnected,2") +{ + auto async = Action(); - async.Completed([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); - } + async.Completed([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); +} - { - auto async = ActionProgress(); - handle signal{ CreateEventW(nullptr, true, false, nullptr) }; +TEST_CASE("disconnected,3") +{ + auto async = ActionProgress(); + handle signal{ CreateEventW(nullptr, true, false, nullptr) }; - async.Progress([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Progress([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); - async.Completed([&](auto&&...) - { - SetEvent(signal.get()); - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Completed([&](auto&&...) + { + SetEvent(signal.get()); + throw hresult_error(RPC_E_DISCONNECTED); + }); - WaitForSingleObject(signal.get(), INFINITE); - } + WaitForSingleObject(signal.get(), INFINITE); +} - { - auto async = Operation(); +TEST_CASE("disconnected,4") +{ + auto async = Operation(); - async.Completed([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); - } + async.Completed([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); +} - { - auto async = OperationProgress(); - handle signal{ CreateEventW(nullptr, true, false, nullptr) }; +TEST_CASE("disconnected,5") +{ + auto async = OperationProgress(); + handle signal{ CreateEventW(nullptr, true, false, nullptr) }; - async.Progress([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Progress([](auto&&...) + { + throw hresult_error(RPC_E_DISCONNECTED); + }); - async.Completed([&](auto&&...) - { - SetEvent(signal.get()); - throw hresult_error(RPC_E_DISCONNECTED); - }); + async.Completed([&](auto&&...) + { + SetEvent(signal.get()); + throw hresult_error(RPC_E_DISCONNECTED); + }); - WaitForSingleObject(signal.get(), INFINITE); - } + WaitForSingleObject(signal.get(), INFINITE); } diff --git a/test/test_win7/main.cpp b/test/test_win7/main.cpp index 7c55cbbed..cb2203171 100644 --- a/test/test_win7/main.cpp +++ b/test/test_win7/main.cpp @@ -1,3 +1,4 @@ +#include #define CATCH_CONFIG_RUNNER #include "catch.hpp" #include "winrt/base.h" @@ -8,6 +9,10 @@ int main(int const argc, char** argv) { init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } From 5390dc86d4fb59a98d5716b34b9e9e00d896e649 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Wed, 19 Oct 2022 02:58:43 +0800 Subject: [PATCH 127/305] Add CI test with LLVM 15 clang-cl (#1203) --- .github/workflows/ci.yml | 101 +++++++++++-- cppwinrt/cppwinrt.vcxproj | 3 - test/old_tests/UnitTests/agile_ref.cpp | 5 + .../old_tests/UnitTests/apartment_context.cpp | 5 + test/old_tests/UnitTests/async.cpp | 137 +++++++++++++++++- test/old_tests/UnitTests/async_cancel.cpp | 15 ++ test/old_tests/UnitTests/weak.cpp | 9 ++ test/test/GetMany.cpp | 4 + test/test/async_auto_cancel.cpp | 5 + test/test/async_cancel_callback.cpp | 5 + test/test/async_check_cancel.cpp | 5 + test/test/async_propagate_cancel.cpp | 5 + test/test/async_throw.cpp | 13 +- test/test/async_wait_for.cpp | 5 + test/test/await_adapter.cpp | 5 + test/test/coro_system.cpp | 3 + test/test/coro_ui_core.cpp | 5 +- test/test/custom_error.cpp | 29 +++- test/test/disconnected.cpp | 29 +++- test/test/multi_threaded_map.cpp | 4 + test/test/multi_threaded_vector.cpp | 4 + test/test_cpp20/custom_error.cpp | 44 ++++-- test/test_win7/GetMany.cpp | 4 + test/test_win7/async_auto_cancel.cpp | 5 + test/test_win7/async_cancel_callback.cpp | 5 + test/test_win7/async_check_cancel.cpp | 5 + test/test_win7/async_throw.cpp | 13 +- test/test_win7/async_wait_for.cpp | 5 + test/test_win7/disconnected.cpp | 24 ++- 29 files changed, 452 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 315983297..f09b518d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,18 +7,40 @@ on: jobs: test-msvc-cppwinrt-build: - name: 'MSVC: Build' + name: '${{ matrix.compiler }}: Build (${{ matrix.arch }}, ${{ matrix.config }})' strategy: matrix: + compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] exclude: - arch: arm64 config: Debug + - compiler: clang-cl + arch: arm64 + - compiler: clang-cl + config: Release runs-on: windows-latest steps: - uses: actions/checkout@v3 + - name: Install LLVM 15 + if: matrix.compiler == 'clang-cl' + run: | + Invoke-WebRequest "https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.2/LLVM-15.0.2-win64.exe" -OutFile LLVM-installer.exe + .\LLVM-installer.exe /S "/D=$pwd\LLVM" | Out-Null + rm LLVM-installer.exe + if (!(Test-Path "$pwd\LLVM\bin\clang-cl.exe")) { exit 1 } + Add-Content $env:GITHUB_PATH "$pwd\LLVM\bin" + + - name: Set up LLVM build tools for msbuild + if: matrix.compiler == 'clang-cl' + # Not using the LLVM tools that comes with MSVC. + run: | + Invoke-WebRequest "https://github.com/zufuliu/llvm-utils/releases/download/v22.09/LLVM_VS2017.zip" -OutFile LLVM_VS2017.zip + 7z x -y "LLVM_VS2017.zip" | Out-Null + cmd /c "LLVM_VS2017\install.bat" 1 + - name: Download nuget run: | mkdir ".\.nuget" @@ -36,7 +58,11 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" $target_version = "1.2.3.4" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + if ("${{ matrix.compiler }}" -eq "clang-cl") { + $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=$pwd\LLVM" + } + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" - name: Restore nuget packages run: | @@ -44,12 +70,12 @@ jobs: - name: Build fast_fwd run: | - cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" cppwinrt.sln /t:fast_fwd + cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:fast_fwd - name: Build cppwinrt if: matrix.arch != 'arm64' run: | - cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt + cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables if: matrix.arch != 'arm64' @@ -71,18 +97,39 @@ jobs: & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose test-msvc-cppwinrt-test: - name: 'MSVC: Tests' + name: '${{ matrix.compiler }}: Test [${{ matrix.test_exe }}] (${{ matrix.arch }}, ${{ matrix.config }})' needs: test-msvc-cppwinrt-build strategy: fail-fast: false matrix: + compiler: [MSVC, clang-cl] arch: [x86, x64] config: [Debug, Release] test_exe: [test, test_cpp20, test_win7, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + exclude: + - compiler: clang-cl + config: Release runs-on: windows-latest steps: - uses: actions/checkout@v3 + - name: Install LLVM 15 + if: matrix.compiler == 'clang-cl' + run: | + Invoke-WebRequest "https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.2/LLVM-15.0.2-win64.exe" -OutFile LLVM-installer.exe + .\LLVM-installer.exe /S "/D=$pwd\LLVM" | Out-Null + rm LLVM-installer.exe + if (!(Test-Path "$pwd\LLVM\bin\clang-cl.exe")) { exit 1 } + Add-Content $env:GITHUB_PATH "$pwd\LLVM\bin" + + - name: Set up LLVM build tools for msbuild + if: matrix.compiler == 'clang-cl' + run: | + # Not using the LLVM tools that comes with MSVC. + Invoke-WebRequest "https://github.com/zufuliu/llvm-utils/releases/download/v22.09/LLVM_VS2017.zip" -OutFile LLVM_VS2017.zip + 7z x -y "LLVM_VS2017.zip" | Out-Null + cmd /c "LLVM_VS2017\install.bat" 1 + - name: Fetch cppwinrt executables uses: actions/download-artifact@v3 with: @@ -106,7 +153,11 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" $target_version = "1.2.3.4" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + if ("${{ matrix.compiler }}" -eq "clang-cl") { + $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=$pwd\LLVM" + } + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" - name: Restore nuget packages run: | @@ -144,7 +195,39 @@ jobs: $test_proj = "old_tests\test_old" } - cmd /c "$env:VSDevCmd" "&" msbuild /m /p:TestsUseAnsiColor=1 "$env:msbuild_config_props" cppwinrt.sln /t:test\$test_proj + cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor /p:TestsUseAnsiColor=1 "$env:msbuild_config_props" cppwinrt.sln /t:test\$test_proj + + - name: Run tests in '${{ matrix.test_exe }}' one by one + if: matrix.compiler == 'clang-cl' + run: | + $target_configuration = "${{ matrix.config }}" + $target_platform = "${{ matrix.arch }}" + $test_exe = "${{ matrix.test_exe }}" + $test_path = "_build\$target_platform\$target_configuration\$test_exe.exe" + if (!(Test-Path $test_path)) { + echo "::error::Test $test_exe is missing." + exit 1 + } + $test_names = @( & $test_path --list-test-names-only ) + $failed_tests = 0 + foreach ($test_name in $test_names) { + echo "::group::Running test $test_name" + $escaped = $test_name.Replace("\", "\\").Replace(",", "\,").Replace("[", "\[") + & $test_path --use-colour yes --warn NoTests "$escaped" + echo "::endgroup::" + if ($LastExitCode -ne 0) { + $failed_tests += 1 + # Add a newline in case test exited abnormally without newline + echo "" + echo "::error::Test $test_exe/'$test_name' failed with exit code $LastExitCode!" + } + } + if ($failed_tests -eq 0) { + echo "All tests in $test_exe passed." + } else { + echo "$failed_tests failed in $test_exe." + exit 1 + } - name: Run test '${{ matrix.test_exe }}' run: | @@ -194,7 +277,7 @@ jobs: - name: Build natvis run: | - cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln + cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln build-msvc-nuget-test: name: 'Build nuget test' @@ -244,7 +327,7 @@ jobs: - name: Run nuget test run: | - cmd /c "$env:VSDevCmd" "&" msbuild /m "$env:msbuild_config_props" test\nuget\NugetTest.sln + cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" test\nuget\NugetTest.sln if ($LastExitCode -ne 0) { echo "::warning::nuget test failed" } diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 946152619..c107e2fbe 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -259,9 +259,6 @@ - - app.manifest;%(AdditionalManifestFiles) - diff --git a/test/old_tests/UnitTests/agile_ref.cpp b/test/old_tests/UnitTests/agile_ref.cpp index cfb97bb50..3d855f886 100644 --- a/test/old_tests/UnitTests/agile_ref.cpp +++ b/test/old_tests/UnitTests/agile_ref.cpp @@ -36,7 +36,12 @@ IAsyncAction test_agile_ref() }); } +#if defined(__clang__) && (defined(_M_IX86) || defined(__i386__)) +// FIXME: Test is known to crash with exit code 0x80000003 (breakpoint?) on x86 when built with Clang. +TEST_CASE("agile_ref", "[.clang-crash]") +#else TEST_CASE("agile_ref") +#endif { test_agile_ref().get(); } diff --git a/test/old_tests/UnitTests/apartment_context.cpp b/test/old_tests/UnitTests/apartment_context.cpp index e7c152fd2..f554afffc 100644 --- a/test/old_tests/UnitTests/apartment_context.cpp +++ b/test/old_tests/UnitTests/apartment_context.cpp @@ -255,7 +255,12 @@ TEST_CASE("apartment_context sta") TestStaToStaApartmentContext().get(); } +#if defined(__clang__) && (defined(_M_IX86) || defined(__i386__)) +// FIXME: Test is known to segfault on x86 when built with Clang. +TEST_CASE("apartment_context disconnected", "[.clang-crash]") +#else TEST_CASE("apartment_context disconnected") +#endif { TestDisconnectedApartmentContext().get(); } diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 817226c6d..08253a385 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -22,7 +22,7 @@ namespace IAsyncAction NoSuspend_IAsyncAction() { - co_await 0s; + co_await resume_after(0s); auto cancel = co_await get_cancellation_token(); @@ -34,7 +34,7 @@ namespace IAsyncActionWithProgress NoSuspend_IAsyncActionWithProgress() { - co_await 0s; + co_await resume_after(0s); auto cancel = co_await get_cancellation_token(); @@ -46,7 +46,7 @@ namespace IAsyncOperation NoSuspend_IAsyncOperation() { - co_await 0s; + co_await resume_after(0s); auto cancel = co_await get_cancellation_token(); @@ -60,7 +60,7 @@ namespace IAsyncOperationWithProgress NoSuspend_IAsyncOperationWithProgress() { - co_await 0s; + co_await resume_after(0s); auto cancel = co_await get_cancellation_token(); @@ -397,7 +397,12 @@ namespace #endif } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncAction", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncAction") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncAction async = Throw_IAsyncAction(event.get()); @@ -437,7 +442,12 @@ TEST_CASE("async, Throw_IAsyncAction") } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncAction, 2", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncAction, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncAction async = Throw_IAsyncAction(event.get()); @@ -478,7 +488,12 @@ TEST_CASE("async, Throw_IAsyncAction, 2") } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncActionWithProgress", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncActionWithProgress") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncActionWithProgress async = Throw_IAsyncActionWithProgress(event.get()); @@ -518,7 +533,12 @@ TEST_CASE("async, Throw_IAsyncActionWithProgress") } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncActionWithProgress, 2", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncActionWithProgress, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncActionWithProgress async = Throw_IAsyncActionWithProgress(event.get()); @@ -559,7 +579,12 @@ TEST_CASE("async, Throw_IAsyncActionWithProgress, 2") } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncOperation", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncOperation") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperation async = Throw_IAsyncOperation(event.get()); @@ -599,7 +624,12 @@ TEST_CASE("async, Throw_IAsyncOperation") } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncOperation, 2", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncOperation, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperation async = Throw_IAsyncOperation(event.get()); @@ -640,7 +670,12 @@ TEST_CASE("async, Throw_IAsyncOperation, 2") } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncOperationWithProgress", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncOperationWithProgress") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperationWithProgress async = Throw_IAsyncOperationWithProgress(event.get()); @@ -680,7 +715,12 @@ TEST_CASE("async, Throw_IAsyncOperationWithProgress") } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Throw_IAsyncOperationWithProgress, 2", "[.clang-crash]") +#else TEST_CASE("async, Throw_IAsyncOperationWithProgress, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperationWithProgress async = Throw_IAsyncOperationWithProgress(event.get()); @@ -773,7 +813,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncAction", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncAction") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncAction async = Cancel_IAsyncAction(event.get()); @@ -803,7 +848,12 @@ TEST_CASE("async, Cancel_IAsyncAction") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncAction, 2", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncAction, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncAction async = Cancel_IAsyncAction(event.get()); @@ -833,7 +883,12 @@ TEST_CASE("async, Cancel_IAsyncAction, 2") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncActionWithProgress", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncActionWithProgress") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncActionWithProgress async = Cancel_IAsyncActionWithProgress(event.get()); @@ -864,7 +919,12 @@ TEST_CASE("async, Cancel_IAsyncActionWithProgress") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncActionWithProgress, 2", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncActionWithProgress, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncActionWithProgress async = Cancel_IAsyncActionWithProgress(event.get()); @@ -895,7 +955,12 @@ TEST_CASE("async, Cancel_IAsyncActionWithProgress, 2") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncOperation", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncOperation") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperation async = Cancel_IAsyncOperation(event.get()); @@ -925,7 +990,12 @@ TEST_CASE("async, Cancel_IAsyncOperation") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncOperation, 2", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncOperation, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperation async = Cancel_IAsyncOperation(event.get()); @@ -955,7 +1025,12 @@ TEST_CASE("async, Cancel_IAsyncOperation, 2") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncOperationWithProgress", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncOperationWithProgress") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperationWithProgress async = Cancel_IAsyncOperationWithProgress(event.get()); @@ -986,7 +1061,12 @@ TEST_CASE("async, Cancel_IAsyncOperationWithProgress") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, Cancel_IAsyncOperationWithProgress, 2", "[.clang-crash]") +#else TEST_CASE("async, Cancel_IAsyncOperationWithProgress, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperationWithProgress async = Cancel_IAsyncOperationWithProgress(event.get()); @@ -1069,7 +1149,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, AutoCancel_IAsyncAction", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncAction") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncAction async = AutoCancel_IAsyncAction(event.get()); @@ -1097,7 +1182,12 @@ TEST_CASE("async, AutoCancel_IAsyncAction") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, AutoCancel_IAsyncAction, 2", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncAction, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncAction async = AutoCancel_IAsyncAction(event.get()); @@ -1125,7 +1215,12 @@ TEST_CASE("async, AutoCancel_IAsyncAction, 2") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncActionWithProgress") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncActionWithProgress async = AutoCancel_IAsyncActionWithProgress(event.get()); @@ -1153,7 +1248,12 @@ TEST_CASE("async, AutoCancel_IAsyncActionWithProgress") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, AutoCancel_IAsyncActionWithProgress, 2", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncActionWithProgress, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncActionWithProgress async = AutoCancel_IAsyncActionWithProgress(event.get()); @@ -1181,7 +1281,12 @@ TEST_CASE("async, AutoCancel_IAsyncActionWithProgress, 2") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, AutoCancel_IAsyncOperation", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncOperation") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperation async = AutoCancel_IAsyncOperation(event.get()); @@ -1209,7 +1314,12 @@ TEST_CASE("async, AutoCancel_IAsyncOperation") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, AutoCancel_IAsyncOperation, 2", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncOperation, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperation async = AutoCancel_IAsyncOperation(event.get()); @@ -1237,7 +1347,12 @@ TEST_CASE("async, AutoCancel_IAsyncOperation, 2") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperationWithProgress async = AutoCancel_IAsyncOperationWithProgress(event.get()); @@ -1265,7 +1380,12 @@ TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress") REQUIRE(statusMatches); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress, 2", "[.clang-crash]") +#else TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress, 2") +#endif { handle event { CreateEvent(nullptr, false, false, nullptr)}; IAsyncOperationWithProgress async = AutoCancel_IAsyncOperationWithProgress(event.get()); @@ -1323,7 +1443,12 @@ TEST_CASE("async, get, suspend with success") REQUIRE(456 == d.get()); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async, get, failure", "[.clang-crash]") +#else TEST_CASE("async, get, failure") +#endif { handle event{ CreateEvent(nullptr, true, false, nullptr) }; SetEvent(event.get()); @@ -1409,10 +1534,10 @@ namespace { IAsyncAction test_resume_after(uint32_t & before, uint32_t & after) { - co_await 0s; // should not suspend + co_await resume_after(0s); // should not suspend before = GetCurrentThreadId(); - co_await 1us; // should suspend and resume on background thread + co_await resume_after(1us); // should suspend and resume on background thread after = GetCurrentThreadId(); } } diff --git a/test/old_tests/UnitTests/async_cancel.cpp b/test/old_tests/UnitTests/async_cancel.cpp index 515b5fcff..9bf6a75bc 100644 --- a/test/old_tests/UnitTests/async_cancel.cpp +++ b/test/old_tests/UnitTests/async_cancel.cpp @@ -122,7 +122,12 @@ TEST_CASE("async_cancel_no_async") REQUIRE(a.Status() == AsyncStatus::Completed); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_cancel_before_callback", "[.clang-crash]") +#else TEST_CASE("async_cancel_before_callback") +#endif { handle begin{ CreateEvent(nullptr, true, false, nullptr) }; handle end{ CreateEvent(nullptr, true, false, nullptr) }; @@ -139,7 +144,12 @@ TEST_CASE("async_cancel_before_callback") REQUIRE(async.Status() == AsyncStatus::Canceled); } +#if defined(__clang__) +// FIXME: Test is known to randomly crash when built with Clang. +TEST_CASE("async_cancel_after_callback", "[.clang-crash]") +#else TEST_CASE("async_cancel_after_callback") +#endif { handle end{ CreateEvent(nullptr, true, false, nullptr) }; handle callback{ CreateEvent(nullptr, true, false, nullptr) }; @@ -154,7 +164,12 @@ TEST_CASE("async_cancel_after_callback") REQUIRE(async.Status() == AsyncStatus::Canceled); } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_cancel_use_status", "[.clang-crash]") +#else TEST_CASE("async_cancel_use_status") +#endif { // Validate that co_await preserves cancellation. handle complete{ CreateEvent(nullptr, true, false, nullptr) }; diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index d93377df5..6724b71ad 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -50,6 +50,8 @@ namespace } }; +// FIXME: Fail to compile with Clang due to incomplete type. +#if !defined(__clang__) struct WeakWithSelfReference : implements { winrt::weak_ref weak_self = get_weak(); @@ -68,6 +70,7 @@ namespace REQUIRE(weak_self.get() == nullptr); } }; +#endif struct WeakCreateWeakInDestructor : implements { @@ -444,10 +447,13 @@ TEST_CASE("weak,assignment") // Not constructible from L"" (because Uri constructor is explicit) static_assert(!std::is_constructible_v, const wchar_t*>); +// FIXME: WeakWithSelfReference fails to compile with Clang. +#if !defined(__clang__) // Constructible from com_ptr because com_ptr is // implicitly convertible to com_ptr. struct Derived : WeakWithSelfReference {}; weak_ref decay{ winrt::com_ptr{nullptr} }; +#endif } TEST_CASE("weak,module_lock") @@ -481,6 +487,8 @@ TEST_CASE("weak,no_module_lock") REQUIRE(get_module_lock() == object_count); } +// FIXME: WeakWithSelfReference fails to compile with Clang. +#if !defined(__clang__) TEST_CASE("weak,self") { // The REQUIRE statements are in the WeakWithSelfReference class itself. @@ -488,6 +496,7 @@ TEST_CASE("weak,self") a.ToString(); a = nullptr; } +#endif TEST_CASE("weak,create_weak_in_destructor") { diff --git a/test/test/GetMany.cpp b/test/test/GetMany.cpp index 23ea63e1e..292912046 100644 --- a/test/test/GetMany.cpp +++ b/test/test/GetMany.cpp @@ -255,6 +255,9 @@ TEST_CASE("GetMany") REQUIRE(buffer[3] == L""); } +// FIXME: Fail to compile with Clang due to recursive template instantiation using single_threaded_generator. +#if !defined(__clang__) + // Similar tests but with a list to ensure optimal code gen for containers that don't offer random access. // All @@ -358,6 +361,7 @@ TEST_CASE("GetMany") REQUIRE(buffer[2] == L"3"); REQUIRE(buffer[3] == L""); } +#endif // Pair { diff --git a/test/test/async_auto_cancel.cpp b/test/test/async_auto_cancel.cpp index bb49a9f5b..ef5ce2aa3 100644 --- a/test/test/async_auto_cancel.cpp +++ b/test/test/async_auto_cancel.cpp @@ -83,7 +83,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_auto_cancel", "[.clang-crash]") +#else TEST_CASE("async_auto_cancel") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test/async_cancel_callback.cpp b/test/test/async_cancel_callback.cpp index 45699142b..98a08ff99 100644 --- a/test/test/async_cancel_callback.cpp +++ b/test/test/async_cancel_callback.cpp @@ -93,7 +93,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_cancel_callback", "[.clang-crash]") +#else TEST_CASE("async_cancel_callback") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index 7ec697927..fb661d8c8 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -104,7 +104,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_check_cancel", "[.clang-crash]") +#else TEST_CASE("async_check_cancel") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test/async_propagate_cancel.cpp b/test/test/async_propagate_cancel.cpp index f735f1bf2..2739897ff 100644 --- a/test/test/async_propagate_cancel.cpp +++ b/test/test/async_propagate_cancel.cpp @@ -128,7 +128,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_propagate_cancel", "[.clang-crash]") +#else TEST_CASE("async_propagate_cancel") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test/async_throw.cpp b/test/test/async_throw.cpp index 2d50acfd9..bca1e9b26 100644 --- a/test/test/async_throw.cpp +++ b/test/test/async_throw.cpp @@ -12,26 +12,26 @@ namespace IAsyncAction Action() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); } IAsyncActionWithProgress ActionWithProgress() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); } IAsyncOperation Operation() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); co_return 1; } IAsyncOperationWithProgress OperationWithProgress() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); co_return 1; } @@ -77,7 +77,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_throw", "[.clang-crash]") +#else TEST_CASE("async_throw") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test/async_wait_for.cpp b/test/test/async_wait_for.cpp index 2173a5e86..d25664495 100644 --- a/test/test/async_wait_for.cpp +++ b/test/test/async_wait_for.cpp @@ -96,7 +96,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_wait_for", "[.clang-crash]") +#else TEST_CASE("async_wait_for") +#endif { check( Action(0s, AsyncStatus::Completed), diff --git a/test/test/await_adapter.cpp b/test/test/await_adapter.cpp index 16575699b..15a179e49 100644 --- a/test/test/await_adapter.cpp +++ b/test/test/await_adapter.cpp @@ -93,7 +93,12 @@ namespace } } +#if defined(__clang__) && (defined(_M_IX86) || defined(__i386__)) +// FIXME: Test is known to segfault on x86 when built with Clang. +TEST_CASE("await_adapter", "[.clang-crash]") +#else TEST_CASE("await_adapter") +#endif { auto controller = DispatcherQueueController::CreateOnDedicatedThread(); auto dispatcher = controller.DispatcherQueue(); diff --git a/test/test/coro_system.cpp b/test/test/coro_system.cpp index db6d5e4ac..21748a91c 100644 --- a/test/test/coro_system.cpp +++ b/test/test/coro_system.cpp @@ -13,7 +13,10 @@ namespace { co_await resume_foreground(queue); +// FIXME: Fail to compile with Clang due to co_await overload resolution +#if !defined(__clang__) co_await queue; +#endif } } diff --git a/test/test/coro_ui_core.cpp b/test/test/coro_ui_core.cpp index 70d7ef071..55df15b65 100644 --- a/test/test/coro_ui_core.cpp +++ b/test/test/coro_ui_core.cpp @@ -18,11 +18,14 @@ namespace co_await resume_foreground(queue); +// FIXME: Fail to compile with Clang due to co_await overload resolution +#if !defined(__clang__) co_await queue; +#endif } } TEST_CASE("coro_ui_core") { Async(nullptr, true); -} \ No newline at end of file +} diff --git a/test/test/custom_error.cpp b/test/test/custom_error.cpp index 28a21aca3..f186ee970 100644 --- a/test/test/custom_error.cpp +++ b/test/test/custom_error.cpp @@ -57,15 +57,23 @@ namespace static bool s_loggerCalled = false; + static struct { + uint32_t lineNumber; + char const* fileName; + char const* functionName; + void* returnAddress; + winrt::hresult result; + } s_loggerArgs{}; + void __stdcall logger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept { - // In C++17 these fields cannot be filled in so they are expected to be empty. - REQUIRE(lineNumber == 0); - REQUIRE(fileName == nullptr); - REQUIRE(functionName == nullptr); - - REQUIRE(returnAddress); - REQUIRE(result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + s_loggerArgs = { + /*.lineNumber =*/ lineNumber, + /*.fileName =*/ fileName, + /*.functionName =*/ functionName, + /*.returnAddress =*/ returnAddress, + /*.result =*/ result, + }; s_loggerCalled = true; } @@ -94,6 +102,13 @@ TEST_CASE("custom_error_logger") // Validate that handler translated exception REQUIRE_THROWS_AS(check_hresult(0x80000018), hresult_illegal_delegate_assignment); REQUIRE(s_loggerCalled); + // In C++17 these fields cannot be filled in so they are expected to be empty. + REQUIRE(s_loggerArgs.lineNumber == 0); + REQUIRE(s_loggerArgs.fileName == nullptr); + REQUIRE(s_loggerArgs.functionName == nullptr); + + REQUIRE(s_loggerArgs.returnAddress); + REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) // Remove global handler winrt_throw_hresult_handler = nullptr; diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 5a6b40e90..0def1ac69 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -16,7 +16,7 @@ namespace IAsyncActionWithProgress ActionProgress() { - co_await 500ms; + co_await resume_after(500ms); auto progress = co_await get_progress_token(); progress(123); co_return; @@ -29,7 +29,7 @@ namespace IAsyncOperationWithProgress OperationProgress() { - co_await 500ms; + co_await resume_after(500ms); auto progress = co_await get_progress_token(); progress(123); co_return 123; @@ -78,7 +78,12 @@ TEST_CASE("disconnected,handler,1") source(nullptr, 123); } +#if defined(__clang__) +// FIXME: Test is known to fail with unhandled exception when built with Clang. +TEST_CASE("disconnected,handler,2", "[!shouldfail]") +#else TEST_CASE("disconnected,handler,2") +#endif { auto async = Action(); @@ -88,7 +93,12 @@ TEST_CASE("disconnected,handler,2") }); } +#if defined(__clang__) +// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) +TEST_CASE("disconnected,handler,3", "[.clang-crash]") +#else TEST_CASE("disconnected,handler,3") +#endif { auto async = ActionProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; @@ -107,7 +117,12 @@ TEST_CASE("disconnected,handler,3") WaitForSingleObject(signal.get(), INFINITE); } +#if defined(__clang__) +// FIXME: Test is known to fail with unhandled exception when built with Clang. +TEST_CASE("disconnected,handler,4", "[!shouldfail]") +#else TEST_CASE("disconnected,handler,4") +#endif { auto async = Operation(); @@ -117,7 +132,12 @@ TEST_CASE("disconnected,handler,4") }); } +#if defined(__clang__) +// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) +TEST_CASE("disconnected,handler,5", "[.clang-crash]") +#else TEST_CASE("disconnected,handler,5") +#endif { auto async = OperationProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; @@ -230,7 +250,12 @@ TEST_CASE("disconnected,action") REQUIRE_THROWS_MATCHES(result.get(), hresult_error, holds_hresult(RPC_E_DISCONNECTED)); } +#if defined(__clang__) && (defined(_M_IX86) || defined(__i386__)) +// FIXME: Test is known to crash with exit code 0xc000070a on x86 when built with Clang. +TEST_CASE("disconnected,double", "[.clang-crash]") +#else TEST_CASE("disconnected,double") +#endif { // The double-disconnect case, where the IAsyncAction disconnects, // and tries to return to the original context, but it too has disconnected! diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index b2b143f11..f57cca23a 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -5,6 +5,9 @@ #include "multi_threaded_common.h" +// FIXME: Fail to compile with Clang due to "error : no type named 'type' in 'std::enable_if'" +#if !defined(__clang__) + using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; @@ -335,3 +338,4 @@ TEST_CASE("multi_threaded_observable_map") test_map_concurrency(); test_map_concurrency(); } +#endif diff --git a/test/test/multi_threaded_vector.cpp b/test/test/multi_threaded_vector.cpp index 24b27d0bc..55a206830 100644 --- a/test/test/multi_threaded_vector.cpp +++ b/test/test/multi_threaded_vector.cpp @@ -2,6 +2,9 @@ #include "multi_threaded_common.h" +// FIXME: Fail to compile with Clang due to "error : no type named 'type' in 'std::enable_if'" +#if !defined(__clang__) + using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; @@ -466,3 +469,4 @@ TEST_CASE("multi_threaded_observable_vector") test_vector_concurrency(); test_vector_concurrency(); } +#endif diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index dc38bbdf9..620ffc755 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -15,24 +15,35 @@ namespace REQUIRE_THROWS_AS(check_hresult(0x80000018), hresult_illegal_delegate_assignment); } + static struct { + uint32_t lineNumber; + char const* fileName; + char const* functionName; + void* returnAddress; + winrt::hresult result; + } s_loggerArgs{}; + void __stdcall logger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept { - // In C++20 these fields should be filled in by std::source_location - REQUIRE(lineNumber == 15); - const auto fileNameSv = std::string_view(fileName); - REQUIRE(!fileNameSv.empty()); - REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); - const auto functionNameSv = std::string_view(functionName); - REQUIRE(!functionNameSv.empty()); - REQUIRE(functionNameSv == "FailOnLine15"); - - REQUIRE(returnAddress); - REQUIRE(result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + s_loggerArgs = { + .lineNumber = lineNumber, + .fileName = fileName, + .functionName = functionName, + .returnAddress = returnAddress, + .result = result, + }; s_loggerCalled = true; } } +#if defined(__clang__) +// FIXME: Blocked on __cpp_consteval, see: +// * https://github.com/microsoft/cppwinrt/pull/1203#issuecomment-1279764927 +// * https://github.com/llvm/llvm-project/issues/57094 +TEST_CASE("custom_error_logger", "[!shouldfail]") +#else TEST_CASE("custom_error_logger") +#endif { // Set up global handler REQUIRE(!s_loggerCalled); @@ -41,6 +52,17 @@ TEST_CASE("custom_error_logger") FailOnLine15(); REQUIRE(s_loggerCalled); + // In C++20 these fields should be filled in by std::source_location + REQUIRE(s_loggerArgs.lineNumber == 15); + const auto fileNameSv = std::string_view(s_loggerArgs.fileName); + REQUIRE(!fileNameSv.empty()); + REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); + const auto functionNameSv = std::string_view(s_loggerArgs.functionName); + REQUIRE(!functionNameSv.empty()); + REQUIRE(functionNameSv == "FailOnLine15"); + + REQUIRE(s_loggerArgs.returnAddress); + REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) // Remove global handler winrt_throw_hresult_handler = nullptr; diff --git a/test/test_win7/GetMany.cpp b/test/test_win7/GetMany.cpp index 23ea63e1e..292912046 100644 --- a/test/test_win7/GetMany.cpp +++ b/test/test_win7/GetMany.cpp @@ -255,6 +255,9 @@ TEST_CASE("GetMany") REQUIRE(buffer[3] == L""); } +// FIXME: Fail to compile with Clang due to recursive template instantiation using single_threaded_generator. +#if !defined(__clang__) + // Similar tests but with a list to ensure optimal code gen for containers that don't offer random access. // All @@ -358,6 +361,7 @@ TEST_CASE("GetMany") REQUIRE(buffer[2] == L"3"); REQUIRE(buffer[3] == L""); } +#endif // Pair { diff --git a/test/test_win7/async_auto_cancel.cpp b/test/test_win7/async_auto_cancel.cpp index e5e3dd776..5272e7fad 100644 --- a/test/test_win7/async_auto_cancel.cpp +++ b/test/test_win7/async_auto_cancel.cpp @@ -70,7 +70,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_auto_cancel", "[.clang-crash]") +#else TEST_CASE("async_auto_cancel") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test_win7/async_cancel_callback.cpp b/test/test_win7/async_cancel_callback.cpp index 8e20d01ec..1f3a97e04 100644 --- a/test/test_win7/async_cancel_callback.cpp +++ b/test/test_win7/async_cancel_callback.cpp @@ -90,7 +90,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_cancel_callback", "[.clang-crash]") +#else TEST_CASE("async_cancel_callback") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test_win7/async_check_cancel.cpp b/test/test_win7/async_check_cancel.cpp index 7ec697927..fb661d8c8 100644 --- a/test/test_win7/async_check_cancel.cpp +++ b/test/test_win7/async_check_cancel.cpp @@ -104,7 +104,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_check_cancel", "[.clang-crash]") +#else TEST_CASE("async_check_cancel") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test_win7/async_throw.cpp b/test/test_win7/async_throw.cpp index 2d50acfd9..bca1e9b26 100644 --- a/test/test_win7/async_throw.cpp +++ b/test/test_win7/async_throw.cpp @@ -12,26 +12,26 @@ namespace IAsyncAction Action() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); } IAsyncActionWithProgress ActionWithProgress() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); } IAsyncOperation Operation() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); co_return 1; } IAsyncOperationWithProgress OperationWithProgress() { - co_await 10ms; + co_await resume_after(10ms); throw hresult_invalid_argument(L"Async"); co_return 1; } @@ -77,7 +77,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_throw", "[.clang-crash]") +#else TEST_CASE("async_throw") +#endif { Check(Action); Check(ActionWithProgress); diff --git a/test/test_win7/async_wait_for.cpp b/test/test_win7/async_wait_for.cpp index 2173a5e86..d25664495 100644 --- a/test/test_win7/async_wait_for.cpp +++ b/test/test_win7/async_wait_for.cpp @@ -96,7 +96,12 @@ namespace } } +#if defined(__clang__) +// FIXME: Test is known to segfault when built with Clang. +TEST_CASE("async_wait_for", "[.clang-crash]") +#else TEST_CASE("async_wait_for") +#endif { check( Action(0s, AsyncStatus::Completed), diff --git a/test/test_win7/disconnected.cpp b/test/test_win7/disconnected.cpp index b893ff5d1..a68639318 100644 --- a/test/test_win7/disconnected.cpp +++ b/test/test_win7/disconnected.cpp @@ -13,7 +13,7 @@ namespace IAsyncActionWithProgress ActionProgress() { - co_await 500ms; + co_await resume_after(500ms); auto progress = co_await get_progress_token(); progress(123); co_return; @@ -26,7 +26,7 @@ namespace IAsyncOperationWithProgress OperationProgress() { - co_await 500ms; + co_await resume_after(500ms); auto progress = co_await get_progress_token(); progress(123); co_return 123; @@ -67,7 +67,12 @@ TEST_CASE("disconnected,1") source(nullptr, 123); } +#if defined(__clang__) +// FIXME: Test is known to fail with unhandled exception when built with Clang. +TEST_CASE("disconnected,2", "[!shouldfail]") +#else TEST_CASE("disconnected,2") +#endif { auto async = Action(); @@ -77,7 +82,12 @@ TEST_CASE("disconnected,2") }); } +#if defined(__clang__) +// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) +TEST_CASE("disconnected,3", "[.clang-crash]") +#else TEST_CASE("disconnected,3") +#endif { auto async = ActionProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; @@ -96,7 +106,12 @@ TEST_CASE("disconnected,3") WaitForSingleObject(signal.get(), INFINITE); } +#if defined(__clang__) +// FIXME: Test is known to fail with unhandled exception when built with Clang. +TEST_CASE("disconnected,4", "[!shouldfail]") +#else TEST_CASE("disconnected,4") +#endif { auto async = Operation(); @@ -106,7 +121,12 @@ TEST_CASE("disconnected,4") }); } +#if defined(__clang__) +// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) +TEST_CASE("disconnected,5", "[.clang-crash]") +#else TEST_CASE("disconnected,5") +#endif { auto async = OperationProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; From bcfb8542cb01da0209fcd3607937474cf92adb80 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 19 Oct 2022 09:36:40 -0500 Subject: [PATCH 128/305] Create stale.yml --- .github/workflows/stale.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..17b7f4dbb --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,24 @@ +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '* * * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-stale: 14 + days-before-close: 5 + stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days' + stale-pr-message: 'This pull request is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' From fac0f88953c660c0d61dabed614f7a5f75da1f2d Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 19 Oct 2022 10:00:28 -0500 Subject: [PATCH 129/305] Update stale.yml --- .github/workflows/stale.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 17b7f4dbb..cc69c3e37 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,9 +16,9 @@ jobs: - uses: actions/stale@v5 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - days-before-stale: 14 + days-before-stale: 10 days-before-close: 5 - stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days' - stale-pr-message: 'This pull request is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days' + stale-issue-message: 'This issue is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' + stale-pr-message: 'This pull request is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' stale-issue-label: 'no-issue-activity' stale-pr-label: 'no-pr-activity' From 168f29e6f02b8c0152daecca191981d131f2eceb Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 19 Oct 2022 10:03:34 -0500 Subject: [PATCH 130/305] Update stale.yml --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index cc69c3e37..228876f0a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v6 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 10 From 95b9d9a608e3b413dd4711d1f481631fe6ba20de Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 19 Oct 2022 10:12:54 -0500 Subject: [PATCH 131/305] Update stale.yml --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 228876f0a..20bf8f2a4 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,7 +2,7 @@ name: Mark stale issues and pull requests on: schedule: - - cron: '* * * * *' + - cron: '0 0 * * *' jobs: stale: From 1b4e0099ccaa2e5b52eba23bc526fa81221abb8a Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Thu, 20 Oct 2022 23:42:42 +0800 Subject: [PATCH 132/305] CI: Build ARM64 cppwinrt and tests (not run) (#1211) --- .github/workflows/ci.yml | 40 +++++++++++++++++-- cppwinrt/cppwinrt.vcxproj | 4 +- test/old_tests/Component/Component.vcxproj | 8 ++-- test/old_tests/Composable/Composable.vcxproj | 6 +-- test/test/test.vcxproj | 16 ++++---- test/test_component/test_component.vcxproj | 4 +- .../test_component_base.vcxproj | 4 +- .../test_component_derived.vcxproj | 4 +- .../test_component_fast.vcxproj | 4 +- .../test_component_folders.vcxproj | 4 +- .../test_component_no_pch.vcxproj | 4 +- test/test_win7/test_win7.vcxproj | 16 ++++---- 12 files changed, 73 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f09b518d5..8336eee12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,13 +72,16 @@ jobs: run: | cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:fast_fwd + - name: Build x86 prebuild tool + if: matrix.arch == 'arm64' + run: | + cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" /p:Platform=x86 cppwinrt.sln /t:cppwinrt + - name: Build cppwinrt - if: matrix.arch != 'arm64' run: | cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - if: matrix.arch != 'arm64' uses: actions/upload-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin @@ -103,10 +106,14 @@ jobs: fail-fast: false matrix: compiler: [MSVC, clang-cl] - arch: [x86, x64] + arch: [x86, x64, arm64] config: [Debug, Release] test_exe: [test, test_cpp20, test_win7, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] exclude: + - arch: arm64 + config: Debug + - compiler: clang-cl + arch: arm64 - compiler: clang-cl config: Release runs-on: windows-latest @@ -131,11 +138,19 @@ jobs: cmd /c "LLVM_VS2017\install.bat" 1 - name: Fetch cppwinrt executables + if: matrix.arch != 'arm64' uses: actions/download-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ + - name: Fetch x86 cppwinrt executables (arm64 only) + if: matrix.arch == 'arm64' + uses: actions/download-artifact@v3 + with: + name: msvc-build-x86-Release-bin + path: _build/x86/Release/ + - name: Download nuget run: | mkdir ".\.nuget" @@ -186,7 +201,11 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose + $cppwinrt_path = "_build\$target_platform\$target_configuration\cppwinrt.exe" + if ($target_platform -eq "arm64") { + $cppwinrt_path = "_build\x86\Release\cppwinrt.exe" + } + & $cppwinrt_path -in local -out _build\$target_platform\$target_configuration -verbose - name: Build test '${{ matrix.test_exe }}' run: | @@ -230,6 +249,7 @@ jobs: } - name: Run test '${{ matrix.test_exe }}' + if: matrix.arch != 'arm64' run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" @@ -241,6 +261,18 @@ jobs: } & $test_path --use-colour yes + - name: Upload arm64 test executables + if: matrix.arch == 'arm64' + uses: actions/upload-artifact@v3 + with: + name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin + path: | + _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe + _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll + _build/${{ matrix.arch }}/${{ matrix.config }}/*.winmd + _build/${{ matrix.arch }}/${{ matrix.config }}/*.lib + _build/${{ matrix.arch }}/${{ matrix.config }}/*.pdb + build-msvc-natvis: name: 'Build natvis' strategy: diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index c107e2fbe..aa876effa 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -236,7 +236,7 @@ Console - $(OutputPath)prebuild.exe ..\strings $(OutputPath) + $(CppWinRTDir)prebuild.exe ..\strings $(OutputPath) @@ -319,7 +319,7 @@ /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) - $(OutputPath)prebuild.exe ..\strings $(OutputPath) + $(CppWinRTDir)prebuild.exe ..\strings $(OutputPath) diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index 2ce8c8005..9af296c51 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -1,4 +1,4 @@ - + @@ -131,7 +131,7 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -149,7 +149,7 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -166,7 +166,7 @@ - $(OutputPath)cppwinrt.exe -in $(OutputPath)Component.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk $(OutputPath)Composable.winmd -verbose + $(CppWinRTDir)cppwinrt.exe -in $(OutputPath)Component.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk $(OutputPath)Composable.winmd -verbose C++/WinRT compiler Generated Files\module.g.cpp $(OutputPath)Component.winmd diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index b4b29d968..d13d779b9 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -131,7 +131,7 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -149,7 +149,7 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -166,7 +166,7 @@ - $(OutDir)cppwinrt.exe -in $(OutDir)Composable.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -pch precomp.hpp -name Composable + $(CppWinRTDir)cppwinrt.exe -in $(OutDir)Composable.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -pch precomp.hpp -name Composable C++/WinRT compiler Generated Files\module.g.cpp $(OutDir)Composable.winmd diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 8a570d258..69c307ebf 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -122,7 +122,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -140,7 +140,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -158,7 +158,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -176,7 +176,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -194,7 +194,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -216,7 +216,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -238,7 +238,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -260,7 +260,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 55096520a..d1f668509 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -125,7 +125,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -137,7 +137,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index 8bf804684..d8768de47 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -125,7 +125,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -137,7 +137,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index d444a2111..e80ab4af1 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -125,7 +125,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -137,7 +137,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index 8cc4739b1..b9d54604b 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -126,7 +126,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -138,7 +138,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index b552d147f..0270ca257 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -125,7 +125,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -137,7 +137,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index b4ad8741f..594e85592 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -125,7 +125,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl @@ -137,7 +137,7 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); + $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl diff --git a/test/test_win7/test_win7.vcxproj b/test/test_win7/test_win7.vcxproj index b85b6a448..831c0c1d1 100644 --- a/test/test_win7/test_win7.vcxproj +++ b/test/test_win7/test_win7.vcxproj @@ -122,7 +122,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -140,7 +140,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -158,7 +158,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -176,7 +176,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -194,7 +194,7 @@ Console - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -216,7 +216,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -238,7 +238,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi @@ -260,7 +260,7 @@ true - $(OutputPath)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi + $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi From 6d3609a56f50d825c13a471049cad563d1cc1272 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Sat, 22 Oct 2022 01:10:16 +0800 Subject: [PATCH 133/305] Better support for mingw-w64 and GCC-compatible compilers (#1212) --- strings/base_activation.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index 8d8eb5e92..d77b8f5d8 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -128,7 +128,9 @@ WINRT_EXPORT namespace winrt #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#if defined _M_ARM +#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) +#define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER __asm__ __volatile__ ("dmb ish"); +#elif defined _M_ARM #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM_BARRIER_ISH)); #elif defined _M_ARM64 #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM64_BARRIER_ISH)); @@ -143,7 +145,11 @@ namespace winrt::impl _ReadWriteBarrier(); return result; #elif defined _M_ARM || defined _M_ARM64 +#if defined(__GNUC__) + int32_t const result = *target; +#else int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); +#endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; #else @@ -159,7 +165,11 @@ namespace winrt::impl _ReadWriteBarrier(); return result; #elif defined _M_ARM64 +#if defined(__GNUC__) + int64_t const result = *target; +#else int64_t const result = __iso_volatile_load64(target); +#endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; #else @@ -281,7 +291,12 @@ namespace winrt::impl object_and_count current_value{ pointer_value, 0 }; #if defined _WIN64 - if (1 == _InterlockedCompareExchange128((int64_t*)this, 0, 0, (int64_t*)¤t_value)) +#if defined(__GNUC__) + bool exchanged = __sync_bool_compare_and_swap((__int128*)this, *(__int128*)¤t_value, (__int128)0); +#else + bool exchanged = 1 == _InterlockedCompareExchange128((int64_t*)this, 0, 0, (int64_t*)¤t_value); +#endif + if (exchanged) { pointer_value->Release(); } From 3deb508335d545c8f0cafc5d6e0e3a6661045cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaigan=C3=A9sh=20Kumaran?= Date: Mon, 24 Oct 2022 22:18:43 +0530 Subject: [PATCH 134/305] `check_bool` now returns `T` (#1205) --- strings/base_error.h | 4 +++- test/old_tests/UnitTests/Errors.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/strings/base_error.h b/strings/base_error.h index 69e23adbd..b375d3913 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -619,12 +619,14 @@ WINRT_EXPORT namespace winrt } template - void check_bool(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + T check_bool(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) { if (!result) { winrt::throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); } + + return result; } template diff --git a/test/old_tests/UnitTests/Errors.cpp b/test/old_tests/UnitTests/Errors.cpp index 000e93851..33e9b422f 100644 --- a/test/old_tests/UnitTests/Errors.cpp +++ b/test/old_tests/UnitTests/Errors.cpp @@ -200,6 +200,8 @@ TEST_CASE("Errors") SetLastError(ERROR_CANCELLED); REQUIRE_THROWS_AS(check_bool(static_cast(false)), hresult_canceled); + REQUIRE(check_bool(true) == true); + // Support for Win32 errors. check_win32(ERROR_SUCCESS); REQUIRE_THROWS_AS(check_win32(ERROR_CANCELLED), hresult_canceled); From d6ef81196f145cfa58779fc41cdc0647fec4db9e Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 25 Oct 2022 00:49:07 +0800 Subject: [PATCH 135/305] Enable classic COM on mingw-w64 (#1215) --- strings/base_macros.h | 8 ++++++++ strings/base_meta.h | 16 +++------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/strings/base_macros.h b/strings/base_macros.h index c4ec6645b..a7d757fad 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -59,6 +59,14 @@ #define WINRT_IMPL_NOVTABLE #endif +#if defined(__clang__) +#define WINRT_IMPL_HAS_DECLSPEC_UUID __has_declspec_attribute(uuid) +#elif defined(_MSC_VER) +#define WINRT_IMPL_HAS_DECLSPEC_UUID 1 +#else +#define WINRT_IMPL_HAS_DECLSPEC_UUID 0 +#endif + #ifdef __IUnknown_INTERFACE_DEFINED__ #define WINRT_IMPL_IUNKNOWN_DEFINED #else diff --git a/strings/base_meta.h b/strings/base_meta.h index 061a9f587..54d41e61b 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -120,27 +120,17 @@ namespace winrt::impl template struct classic_com_guid_error { -#ifdef __clang__ -#if !__has_declspec_attribute(uuid) +#if !defined(__MINGW32__) && defined(__clang__) && !WINRT_IMPL_HAS_DECLSPEC_UUID static_assert(std::is_void_v /* dependent_false */, "To use classic COM interfaces, you must compile with -fms-extensions."); -#endif - -#ifndef WINRT_IMPL_IUNKNOWN_DEFINED +#elif !defined(WINRT_IMPL_IUNKNOWN_DEFINED) static_assert(std::is_void_v /* dependent_false */, "To use classic COM interfaces, you must include before including C++/WinRT headers."); -#endif #else // MSVC won't hit this struct, so we can safely assume everything that isn't Clang isn't supported static_assert(std::is_void_v /* dependent_false */, "Classic COM interfaces are not supported with this compiler."); #endif }; template -#ifdef __clang__ -#if __has_declspec_attribute(uuid) && defined(WINRT_IMPL_IUNKNOWN_DEFINED) - inline constexpr guid guid_v{ __uuidof(T) }; -#else - inline constexpr guid guid_v = classic_com_guid_error::value; -#endif -#elif defined(_MSC_VER) +#if (defined(_MSC_VER) && !defined(__clang__)) || ((WINRT_IMPL_HAS_DECLSPEC_UUID || defined(__MINGW32__)) && defined(WINRT_IMPL_IUNKNOWN_DEFINED)) inline constexpr guid guid_v{ __uuidof(T) }; #else inline constexpr guid guid_v = classic_com_guid_error::value; From 6ce4fa91bb98763c099e24a744b3234f6b23727c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaigan=C3=A9sh=20Kumaran?= Date: Tue, 1 Nov 2022 20:23:33 +0530 Subject: [PATCH 136/305] C++ Streams support for hstring and IStringable (#1221) --- cppwinrt/code_writers.h | 1 + cppwinrt/cppwinrt.vcxproj | 1 + cppwinrt/cppwinrt.vcxproj.filters | 3 ++ strings/base_includes.h | 4 +++ strings/base_string_operators.h | 8 +++++ strings/base_stringable_streams.h | 8 +++++ test/old_tests/UnitTests/Tests.vcxproj | 1 + .../old_tests/UnitTests/Tests.vcxproj.filters | 1 + test/old_tests/UnitTests/streams.cpp | 36 +++++++++++++++++++ 9 files changed, 63 insertions(+) create mode 100644 strings/base_stringable_streams.h create mode 100644 test/old_tests/UnitTests/streams.cpp diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 24d45bdf3..497af4c40 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3256,6 +3256,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable w.write(strings::base_deferral); w.write(strings::base_coroutine_foundation); w.write(strings::base_stringable_format); + w.write(strings::base_stringable_streams); } else if (namespace_name == "Windows.Foundation.Collections") { diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index aa876effa..75d8cee1e 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -80,6 +80,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 3176b206f..01aecb75e 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -168,6 +168,9 @@ strings + + + strings strings diff --git a/strings/base_includes.h b/strings/base_includes.h index d514b415e..ef2b9d8e2 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -25,6 +25,10 @@ #include #endif +#ifndef WINRT_LEAN_AND_MEAN +#include +#endif + #ifdef __cpp_lib_format #include #endif diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index 215186b04..f9701aa4b 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -160,4 +160,12 @@ WINRT_EXPORT namespace winrt { return impl::concat_hstring(left, right); } + +#ifndef WINRT_LEAN_AND_MEAN + inline std::wostream& operator<<(std::wostream& stream, hstring const& string) + { + stream << static_cast(string); + return stream; + } +#endif } diff --git a/strings/base_stringable_streams.h b/strings/base_stringable_streams.h new file mode 100644 index 000000000..52b481d6f --- /dev/null +++ b/strings/base_stringable_streams.h @@ -0,0 +1,8 @@ + +#ifndef WINRT_LEAN_AND_MEAN +inline std::wostream& operator<<(std::wostream& stream, winrt::Windows::Foundation::IStringable const& stringable) +{ + stream << stringable.ToString(); + return stream; +} +#endif diff --git a/test/old_tests/UnitTests/Tests.vcxproj b/test/old_tests/UnitTests/Tests.vcxproj index aedd02bfd..c0c178442 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj +++ b/test/old_tests/UnitTests/Tests.vcxproj @@ -118,6 +118,7 @@ + diff --git a/test/old_tests/UnitTests/Tests.vcxproj.filters b/test/old_tests/UnitTests/Tests.vcxproj.filters index 3e95c4a98..e1a6813a5 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj.filters +++ b/test/old_tests/UnitTests/Tests.vcxproj.filters @@ -88,6 +88,7 @@ + diff --git a/test/old_tests/UnitTests/streams.cpp b/test/old_tests/UnitTests/streams.cpp new file mode 100644 index 000000000..b6bc0f089 --- /dev/null +++ b/test/old_tests/UnitTests/streams.cpp @@ -0,0 +1,36 @@ + #include "pch.h" +#include "catch.hpp" +#include + +struct stringable : winrt::implements +{ + winrt::hstring ToString() + { + return L"a stringable object"; + } +}; + +TEST_CASE("streams") +{ + { + std::wstringstream ss; + winrt::hstring str = L"Hello World"; + ss << str; + REQUIRE(ss.str() == str); + } + + { + // Support embedded nulls. + std::wstringstream ss; + winrt::hstring str = L"Hello\0World"; + ss << str; + REQUIRE(ss.str() == str); + } + + { + std::wstringstream ss; + winrt::Windows::Foundation::IStringable obj = winrt::make(); + ss << obj; + REQUIRE(ss.str() == obj.ToString()); + } +} From 7b9d481c762b156c0bac162d0d5e782eddd14588 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Fri, 4 Nov 2022 10:02:01 -0700 Subject: [PATCH 137/305] Projects with a nested Windows namespace (e.g., Microsoft::Windows) fail to compile (#1223) --- strings/base_xaml_component_connector.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/base_xaml_component_connector.h b/strings/base_xaml_component_connector.h index 16478f7a2..366e18e22 100644 --- a/strings/base_xaml_component_connector.h +++ b/strings/base_xaml_component_connector.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, Windows::Foundation::IInspectable const& target) + void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { From 5db060eb2b897ec70d12e5912c38e1a6d50f33b4 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Fri, 4 Nov 2022 11:14:51 -0700 Subject: [PATCH 138/305] Include WinUI too (sigh) (#1224) --- strings/base_xaml_component_connector_winui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/base_xaml_component_connector_winui.h b/strings/base_xaml_component_connector_winui.h index 9a84cc11d..4a1f0326a 100644 --- a/strings/base_xaml_component_connector_winui.h +++ b/strings/base_xaml_component_connector_winui.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, Windows::Foundation::IInspectable const& target) + void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { From 526d72ad6f3a1800ff3d8472605dbbc9af07fff8 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Mon, 7 Nov 2022 21:55:46 +0800 Subject: [PATCH 139/305] Fix invoke call on Clang (possibly a compiler bug) (#1225) --- strings/base_coroutine_foundation.h | 4 ++-- test/test/disconnected.cpp | 20 -------------------- test/test_win7/disconnected.cpp | 20 -------------------- 3 files changed, 2 insertions(+), 42 deletions(-) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 71dbb0043..31ec1bcc4 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -414,7 +414,7 @@ namespace winrt::impl if (handler) { - invoke(handler, *this, status); + winrt::impl::invoke(handler, *this, status); } } @@ -539,7 +539,7 @@ namespace winrt::impl if (handler) { - invoke(handler, *this, status); + winrt::impl::invoke(handler, *this, status); } } diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 0def1ac69..816344c35 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -78,12 +78,7 @@ TEST_CASE("disconnected,handler,1") source(nullptr, 123); } -#if defined(__clang__) -// FIXME: Test is known to fail with unhandled exception when built with Clang. -TEST_CASE("disconnected,handler,2", "[!shouldfail]") -#else TEST_CASE("disconnected,handler,2") -#endif { auto async = Action(); @@ -93,12 +88,7 @@ TEST_CASE("disconnected,handler,2") }); } -#if defined(__clang__) -// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) -TEST_CASE("disconnected,handler,3", "[.clang-crash]") -#else TEST_CASE("disconnected,handler,3") -#endif { auto async = ActionProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; @@ -117,12 +107,7 @@ TEST_CASE("disconnected,handler,3") WaitForSingleObject(signal.get(), INFINITE); } -#if defined(__clang__) -// FIXME: Test is known to fail with unhandled exception when built with Clang. -TEST_CASE("disconnected,handler,4", "[!shouldfail]") -#else TEST_CASE("disconnected,handler,4") -#endif { auto async = Operation(); @@ -132,12 +117,7 @@ TEST_CASE("disconnected,handler,4") }); } -#if defined(__clang__) -// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) -TEST_CASE("disconnected,handler,5", "[.clang-crash]") -#else TEST_CASE("disconnected,handler,5") -#endif { auto async = OperationProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; diff --git a/test/test_win7/disconnected.cpp b/test/test_win7/disconnected.cpp index a68639318..17411e99e 100644 --- a/test/test_win7/disconnected.cpp +++ b/test/test_win7/disconnected.cpp @@ -67,12 +67,7 @@ TEST_CASE("disconnected,1") source(nullptr, 123); } -#if defined(__clang__) -// FIXME: Test is known to fail with unhandled exception when built with Clang. -TEST_CASE("disconnected,2", "[!shouldfail]") -#else TEST_CASE("disconnected,2") -#endif { auto async = Action(); @@ -82,12 +77,7 @@ TEST_CASE("disconnected,2") }); } -#if defined(__clang__) -// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) -TEST_CASE("disconnected,3", "[.clang-crash]") -#else TEST_CASE("disconnected,3") -#endif { auto async = ActionProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; @@ -106,12 +96,7 @@ TEST_CASE("disconnected,3") WaitForSingleObject(signal.get(), INFINITE); } -#if defined(__clang__) -// FIXME: Test is known to fail with unhandled exception when built with Clang. -TEST_CASE("disconnected,4", "[!shouldfail]") -#else TEST_CASE("disconnected,4") -#endif { auto async = Operation(); @@ -121,12 +106,7 @@ TEST_CASE("disconnected,4") }); } -#if defined(__clang__) -// FIXME: Test is known to abort when built with Clang. (Seems to be from unhandled exception thrown on a worker thread.) -TEST_CASE("disconnected,5", "[.clang-crash]") -#else TEST_CASE("disconnected,5") -#endif { auto async = OperationProgress(); handle signal{ CreateEventW(nullptr, true, false, nullptr) }; From b79565c8fc104301a344912499b5fc542bfdea5b Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Wed, 9 Nov 2022 01:04:20 +0800 Subject: [PATCH 140/305] Harden `disconnected.cpp` test (#1226) --- test/test/disconnected.cpp | 4 ++++ test/test_win7/disconnected.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 816344c35..ac97f8477 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -105,6 +105,8 @@ TEST_CASE("disconnected,handler,3") }); WaitForSingleObject(signal.get(), INFINITE); + // Give some time for to_hresult() to complete. + Sleep(500); } TEST_CASE("disconnected,handler,4") @@ -134,6 +136,8 @@ TEST_CASE("disconnected,handler,5") }); WaitForSingleObject(signal.get(), INFINITE); + // Give some time for to_hresult() to complete. + Sleep(500); } // Custom action to simulate an out-of-process server that crashes before it can complete. diff --git a/test/test_win7/disconnected.cpp b/test/test_win7/disconnected.cpp index 17411e99e..1757937d0 100644 --- a/test/test_win7/disconnected.cpp +++ b/test/test_win7/disconnected.cpp @@ -94,6 +94,8 @@ TEST_CASE("disconnected,3") }); WaitForSingleObject(signal.get(), INFINITE); + // Give some time for to_hresult() to complete. + Sleep(500); } TEST_CASE("disconnected,4") @@ -123,4 +125,6 @@ TEST_CASE("disconnected,5") }); WaitForSingleObject(signal.get(), INFINITE); + // Give some time for to_hresult() to complete. + Sleep(500); } From 5ca626adae21be363399b44d2b6a9ab316aab41f Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Thu, 10 Nov 2022 00:26:19 +0800 Subject: [PATCH 141/305] Add CMake build and a limited subset of tests for llvm-mingw (#1216) --- .github/workflows/ci.yml | 47 +++++++ CMakeLists.txt | 167 +++++++++++++++++++++++++ mingw-support/xmllite.def | 8 ++ mingw-support/xmllite_i386.def | 8 ++ test/CMakeLists.txt | 40 ++++++ test/mingw_com_support.h | 13 ++ test/test/CMakeLists.txt | 71 +++++++++++ test/test/async_auto_cancel.cpp | 2 +- test/test/async_cancel_callback.cpp | 2 +- test/test/async_check_cancel.cpp | 2 +- test/test/async_propagate_cancel.cpp | 2 +- test/test/async_throw.cpp | 2 +- test/test/async_wait_for.cpp | 2 +- test/test/await_adapter.cpp | 2 +- test/test/box_array.cpp | 8 +- test/test/capture.cpp | 6 +- test/test/disconnected.cpp | 7 ++ test/test/generic_type_names.cpp | 2 + test/test/generic_types.h | 4 + test/test/initialize.cpp | 4 +- test/test/inspectable_interop.cpp | 10 +- test/test/interop.cpp | 12 +- test/test/main.cpp | 4 + test/test/notify_awaiter.cpp | 12 +- test/test/numerics.cpp | 2 + test/test/pch.h | 2 + test/test/variadic_delegate.cpp | 2 +- test/test_win7/CMakeLists.txt | 58 +++++++++ test/test_win7/capture.cpp | 6 +- test/test_win7/generic_type_names.cpp | 2 + test/test_win7/generic_types.h | 4 + test/test_win7/inspectable_interop.cpp | 9 +- test/test_win7/interop.cpp | 12 +- test/test_win7/main.cpp | 4 + test/test_win7/numerics.cpp | 2 + test/test_win7/pch.h | 2 + 36 files changed, 516 insertions(+), 26 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 mingw-support/xmllite.def create mode 100644 mingw-support/xmllite_i386.def create mode 100644 test/CMakeLists.txt create mode 100644 test/mingw_com_support.h create mode 100644 test/test/CMakeLists.txt create mode 100644 test/test_win7/CMakeLists.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8336eee12..b75b06cfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -273,6 +273,53 @@ jobs: _build/${{ matrix.arch }}/${{ matrix.config }}/*.lib _build/${{ matrix.arch }}/${{ matrix.config }}/*.pdb + test-llvm-mingw-cppwinrt: + name: 'llvm-mingw: Build and test' + strategy: + matrix: + arch: [i686, x86_64] + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Install llvm-mingw toolchain + run: | + $llvm_mingw_version = "20220906" + Invoke-WebRequest "https://github.com/mstorsjo/llvm-mingw/releases/download/${llvm_mingw_version}/llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}.zip" -OutFile llvm-mingw.zip + 7z x llvm-mingw.zip + rm llvm-mingw.zip + if (!(Test-Path "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin\clang++.exe")) { return 1 } + Add-Content $env:GITHUB_PATH "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin" + + - name: Build cppwinrt + run: | + mkdir build + cd build + cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug + cmake --build . --target cppwinrt + + - name: Upload cppwinrt.exe + uses: actions/upload-artifact@v3 + with: + name: llvm-mingw-build-${{ matrix.arch }}-bin + path: build/cppwinrt.exe + + - name: Build tests + run: | + cd build + cmake --build . --target test-vanilla test_win7 + + - name: Upload test binaries + uses: actions/upload-artifact@v3 + with: + name: llvm-mingw-tests-${{ matrix.arch }}-bin + path: build/test/*.exe + + - name: Run tests + run: | + cd build + ctest --verbose + build-msvc-natvis: name: 'Build natvis' strategy: diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..0a60ba31e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,167 @@ +# This CMake build file is intended for use with the llvm-mingw toolchain: +# https://github.com/mstorsjo/llvm-mingw +# +# It most probably doesn't work with MSVC. + +cmake_minimum_required(VERSION 3.12) + +project(cppwinrt LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +set(CPPWINRT_BUILD_VERSION "2.3.4.5" CACHE STRING "The version string used for cppwinrt.") +add_compile_definitions(CPPWINRT_VERSION_STRING="${CPPWINRT_BUILD_VERSION}") + +# WinMD uses CreateFile2 which requires Windows 8. +add_compile_definitions(_WIN32_WINNT=0x0602) + + +# === prebuild: Generator tool for strings.cpp, strings.h, version.rc === + +set(PREBUILD_SRCS + prebuild/main.cpp + prebuild/pch.h +) +add_executable(prebuild ${PREBUILD_SRCS}) +target_include_directories(prebuild PRIVATE cppwinrt/) + + +# === Step to create autogenerated files === + +file(GLOB PREBUILD_STRINGS_FILES + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + strings/*.h +) +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/strings.cpp + ${PROJECT_BINARY_DIR}/version.rc + COMMAND "${PROJECT_BINARY_DIR}/prebuild.exe" ARGS "${PROJECT_SOURCE_DIR}/strings" "${PROJECT_BINARY_DIR}" + DEPENDS + prebuild + ${PREBUILD_STRINGS_FILES} + VERBATIM +) + + +# === cppwinrt === + +set(CPPWINRT_SRCS + cppwinrt/main.cpp + "${PROJECT_BINARY_DIR}/strings.cpp" +) + +set(CPPWINRT_HEADERS + cppwinrt/pch.h + cppwinrt/cmd_reader.h + cppwinrt/code_writers.h + cppwinrt/component_writers.h + cppwinrt/file_writers.h + cppwinrt/helpers.h + cppwinrt/pch.h + cppwinrt/settings.h + cppwinrt/task_group.h + cppwinrt/text_writer.h + cppwinrt/type_writers.h +) + +add_custom_command( + OUTPUT + "${PROJECT_BINARY_DIR}/app.manifest" + COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/cppwinrt/app.manifest" "${PROJECT_BINARY_DIR}/app.manifest" + DEPENDS "${PROJECT_SOURCE_DIR}/cppwinrt/app.manifest" + VERBATIM +) +# Do the configure_file dance so that app.manifest.rc don't get modified every +# single time the project is reconfigured and trigger a rebuild. +file(WRITE "${PROJECT_BINARY_DIR}/app.manifest.rc.in" "1 24 \"app.manifest\"\n") +configure_file( + "${PROJECT_BINARY_DIR}/app.manifest.rc.in" + "${PROJECT_BINARY_DIR}/app.manifest.rc" + COPYONLY +) + +set(CPPWINRT_RESOURCES + "${PROJECT_BINARY_DIR}/app.manifest" + "${PROJECT_BINARY_DIR}/app.manifest.rc" + "${PROJECT_BINARY_DIR}/version.rc" +) + +add_executable(cppwinrt ${CPPWINRT_SRCS} ${CPPWINRT_RESOURCES} ${CPPWINRT_HEADERS}) +target_include_directories(cppwinrt PRIVATE ${PROJECT_BINARY_DIR}) +target_link_libraries(cppwinrt shlwapi) + + +# HACK: Handle the xmllite import lib. +# mingw-w64 before commit 5ac1a2c is missing the import lib for xmllite. This +# checks whether the current build environment provides libxmllite.a, and +# generates the import lib if needed. + +set(XMLLITE_LIBRARY xmllite) +if(MINGW) + function(TestLinkXmlLite OUTPUT_VARNAME) + include(CheckCXXSourceCompiles) + set(CMAKE_REQUIRED_LIBRARIES xmllite) + check_cxx_source_compiles(" +#include +int main() { + CreateXmlReader(__uuidof(IXmlReader), nullptr, nullptr); +} + " ${OUTPUT_VARNAME}) + endfunction() + + function(TestIsI386 OUTPUT_VARNAME) + include(CheckCXXSourceCompiles) + check_cxx_source_compiles(" +#if !defined(__i386__) && !defined(_M_IX86) +# error Not i386 +#endif +int main() {} + " ${OUTPUT_VARNAME}) + endfunction() + + TestLinkXmlLite(HAS_LIBXMLLITE) + if(NOT HAS_LIBXMLLITE) + TestIsI386(TARGET_IS_I386) + if(TARGET_IS_I386) + set(XMLLITE_DEF_FILE xmllite_i386) + else() + set(XMLLITE_DEF_FILE xmllite) + endif() + add_custom_command( + OUTPUT + "${PROJECT_BINARY_DIR}/libxmllite.a" + COMMAND dlltool -k -d "${PROJECT_SOURCE_DIR}/mingw-support/${XMLLITE_DEF_FILE}.def" -l "${PROJECT_BINARY_DIR}/libxmllite.a" + DEPENDS "${PROJECT_SOURCE_DIR}/mingw-support/${XMLLITE_DEF_FILE}.def" + VERBATIM + ) + add_custom_target(gen-libxmllite + DEPENDS "${PROJECT_BINARY_DIR}/libxmllite.a" + ) + set(XMLLITE_LIBRARY "${PROJECT_BINARY_DIR}/libxmllite.a") + add_dependencies(cppwinrt gen-libxmllite) + endif() +endif() +target_link_libraries(cppwinrt "${XMLLITE_LIBRARY}") + + +# === winmd: External header-only library for reading winmd files === + +include(ExternalProject) +ExternalProject_Add(winmd + URL https://github.com/microsoft/winmd/releases/download/1.0.210629.2/Microsoft.Windows.WinMD.1.0.210629.2.nupkg + URL_HASH SHA256=4c5f29d948f5b3d724d229664c8f8e4823250d3c9f23ad8067b732fc7076d8c7 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" +) +add_dependencies(cppwinrt winmd) +ExternalProject_Get_Property(winmd SOURCE_DIR) +set(winmd_SOURCE_DIR "${SOURCE_DIR}") +target_include_directories(cppwinrt PRIVATE "${winmd_SOURCE_DIR}") + + +include(CTest) +add_subdirectory(test) diff --git a/mingw-support/xmllite.def b/mingw-support/xmllite.def new file mode 100644 index 000000000..c96291d16 --- /dev/null +++ b/mingw-support/xmllite.def @@ -0,0 +1,8 @@ +LIBRARY "XmlLite.dll" +EXPORTS +CreateXmlReader +CreateXmlReaderInputWithEncodingCodePage +CreateXmlReaderInputWithEncodingName +CreateXmlWriter +CreateXmlWriterOutputWithEncodingCodePage +CreateXmlWriterOutputWithEncodingName diff --git a/mingw-support/xmllite_i386.def b/mingw-support/xmllite_i386.def new file mode 100644 index 000000000..79921fce7 --- /dev/null +++ b/mingw-support/xmllite_i386.def @@ -0,0 +1,8 @@ +LIBRARY "XmlLite.dll" +EXPORTS +CreateXmlReader@12 +CreateXmlReaderInputWithEncodingCodePage@24 +CreateXmlReaderInputWithEncodingName@24 +CreateXmlWriter@12 +CreateXmlWriterOutputWithEncodingCodePage@16 +CreateXmlWriterOutputWithEncodingName@16 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..4cf322da9 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,40 @@ +# The tests use newer C++ features. +set(CMAKE_CXX_STANDARD 20) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}") +include_directories("${PROJECT_SOURCE_DIR}/cppwinrt") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/cppwinrt") + +function(TestIsX64 OUTPUT_VARNAME) + include(CheckCXXSourceCompiles) + check_cxx_source_compiles(" +#if !defined(__x86_64__) && !defined(_M_X64) +# error Not x86_64 +#endif +int main() {} + " ${OUTPUT_VARNAME}) +endfunction() +TestIsX64(TARGET_IS_X64) +if(TARGET_IS_X64) + add_compile_options(-mcx16) +endif() + + +add_custom_command( + OUTPUT + "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt/winrt/base.h" + COMMAND "${PROJECT_BINARY_DIR}/cppwinrt" -input local -output "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt" -verbose + DEPENDS + cppwinrt + VERBATIM +) +add_custom_target(build-cppwinrt-projection + DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt/winrt/base.h" +) + + +add_subdirectory(test) +add_subdirectory(test_win7) diff --git a/test/mingw_com_support.h b/test/mingw_com_support.h new file mode 100644 index 000000000..80e56455b --- /dev/null +++ b/test/mingw_com_support.h @@ -0,0 +1,13 @@ +#if defined(__clang__) +#define HAS_DECLSPEC_UUID __has_declspec_attribute(uuid) +#elif defined(_MSC_VER) +#define HAS_DECLSPEC_UUID 1 +#else +#define HAS_DECLSPEC_UUID 0 +#endif + +#if HAS_DECLSPEC_UUID +#define DECLSPEC_UUID(x) __declspec(uuid(x)) +#else +#define DECLSPEC_UUID(x) +#endif diff --git a/test/test/CMakeLists.txt b/test/test/CMakeLists.txt new file mode 100644 index 000000000..f5921a0bc --- /dev/null +++ b/test/test/CMakeLists.txt @@ -0,0 +1,71 @@ +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +# We can't build test_component[*] for mingw-w64 because it doesn't have an +# alternative to midl that can produce winmd files. Also, even if we do manage +# to reuse the MSVC-compiled binaries, mingw-w64 is still missing +# windowsnumerics.impl.h which is needed to provide the types +# winrt::Windows::Foundation::Numerics::float2 and friends that the components +# use. +list(APPEND BROKEN_TESTS + agility + delegates + enum + event_deferral + in_params + in_params_abi + no_make_detection + noexcept + optional + out_params + out_params_abi + parent_includes + rational + return_params + return_params_abi + struct_delegate + structs + uniform_in_params + velocity +) + +list(APPEND BROKEN_TESTS + # depends on pplawait.h + when +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test-vanilla main.cpp ${TEST_SRCS}) +set_target_properties(test-vanilla PROPERTIES OUTPUT_NAME "test") +target_link_libraries(test-vanilla runtimeobject) + +target_precompile_headers(test-vanilla PRIVATE pch.h) +set_source_files_properties( + main.cpp + coro_foundation.cpp + coro_system.cpp + coro_threadpool.cpp + coro_uicore.cpp + custom_activation.cpp + generic_type_names.cpp + guid_include.cpp + inspectable_interop.cpp + module_lock_dll.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test-vanilla build-cppwinrt-projection) + +add_test( + NAME test + COMMAND "$" +) diff --git a/test/test/async_auto_cancel.cpp b/test/test/async_auto_cancel.cpp index ef5ce2aa3..bffcb6e44 100644 --- a/test/test/async_auto_cancel.cpp +++ b/test/test/async_auto_cancel.cpp @@ -83,7 +83,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_auto_cancel", "[.clang-crash]") #else diff --git a/test/test/async_cancel_callback.cpp b/test/test/async_cancel_callback.cpp index 98a08ff99..c99e1dad4 100644 --- a/test/test/async_cancel_callback.cpp +++ b/test/test/async_cancel_callback.cpp @@ -93,7 +93,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_cancel_callback", "[.clang-crash]") #else diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index fb661d8c8..7547609f6 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -104,7 +104,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_check_cancel", "[.clang-crash]") #else diff --git a/test/test/async_propagate_cancel.cpp b/test/test/async_propagate_cancel.cpp index 2739897ff..a3e5af749 100644 --- a/test/test/async_propagate_cancel.cpp +++ b/test/test/async_propagate_cancel.cpp @@ -128,7 +128,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_propagate_cancel", "[.clang-crash]") #else diff --git a/test/test/async_throw.cpp b/test/test/async_throw.cpp index bca1e9b26..779351439 100644 --- a/test/test/async_throw.cpp +++ b/test/test/async_throw.cpp @@ -77,7 +77,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_throw", "[.clang-crash]") #else diff --git a/test/test/async_wait_for.cpp b/test/test/async_wait_for.cpp index d25664495..d7613083c 100644 --- a/test/test/async_wait_for.cpp +++ b/test/test/async_wait_for.cpp @@ -96,7 +96,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_wait_for", "[.clang-crash]") #else diff --git a/test/test/await_adapter.cpp b/test/test/await_adapter.cpp index 15a179e49..809567695 100644 --- a/test/test/await_adapter.cpp +++ b/test/test/await_adapter.cpp @@ -93,7 +93,7 @@ namespace } } -#if defined(__clang__) && (defined(_M_IX86) || defined(__i386__)) +#if defined(__clang__) && defined(_MSC_VER) && (defined(_M_IX86) || defined(__i386__)) // FIXME: Test is known to segfault on x86 when built with Clang. TEST_CASE("await_adapter", "[.clang-crash]") #else diff --git a/test/test/box_array.cpp b/test/test/box_array.cpp index 1c5b4a966..04377b334 100644 --- a/test/test/box_array.cpp +++ b/test/test/box_array.cpp @@ -8,17 +8,17 @@ namespace T defaultValue{}; winrt::com_array ary{ otherValue, defaultValue }; auto box = winrt::box_value(ary); - winrt::com_array unbox = box.try_as>().value(); + winrt::com_array unbox = box.template try_as>().value(); REQUIRE(unbox.size() == 2); REQUIRE(unbox.at(0) == otherValue); REQUIRE(unbox.at(1) == defaultValue); - unbox = box.as>(); + unbox = box.template as>(); REQUIRE(unbox.size() == 2); REQUIRE(unbox.at(0) == otherValue); REQUIRE(unbox.at(1) == defaultValue); if constexpr (!std::is_same_v) { - unbox = box.as>>().Value(); + unbox = box.template as>>().Value(); REQUIRE(unbox.size() == 2); REQUIRE(unbox.at(0) == otherValue); REQUIRE(unbox.at(1) == defaultValue); @@ -53,4 +53,4 @@ TEST_CASE("box_array") Verify({ 1,1 }); Verify({ 1,1 }); Verify({ 1,1,1,1 }); -} \ No newline at end of file +} diff --git a/test/test/capture.cpp b/test/test/capture.cpp index 8c75681b4..9019d1e34 100644 --- a/test/test/capture.cpp +++ b/test/test/capture.cpp @@ -3,12 +3,16 @@ using namespace winrt; using namespace Windows::Foundation; -struct __declspec(uuid("5fb96f8d-409c-42a9-99a7-8a95c1459dbd")) ICapture : ::IUnknown +struct DECLSPEC_UUID("5fb96f8d-409c-42a9-99a7-8a95c1459dbd") ICapture : ::IUnknown { virtual int32_t __stdcall GetValue() noexcept = 0; virtual int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept = 0; }; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ICapture, 0x5fb96f8d, 0x409c, 0x42a9, 0x99, 0xa7, 0x8a, 0x95, 0xc1, 0x45, 0x9d, 0xbd) +#endif + struct Capture : implements { int32_t const m_value{}; diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index ac97f8477..13fcad601 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -171,6 +171,12 @@ struct non_agile_abandoned_action : implements m_disconnect; }; +// Not yet buildable on mingw-w64. +// Missing CLSID_ContextSwitcher, IID_ICallbackWithNoReentrancyToApplicationSTA +// and __uuidof(IContextCallback). Also, the lambda needs to have __stdcall +// specified on it but there is a Clang crash bug blocking this: +// https://github.com/llvm/llvm-project/issues/58366 +#if !defined(__MINGW32__) namespace { template @@ -285,3 +291,4 @@ TEST_CASE("disconnected,double") test.get(); } +#endif diff --git a/test/test/generic_type_names.cpp b/test/test/generic_type_names.cpp index 580d69ac3..5a2d648a2 100644 --- a/test/test/generic_type_names.cpp +++ b/test/test/generic_type_names.cpp @@ -120,6 +120,7 @@ TEST_CASE("generic_type_names") IReference); REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", IReference); +#if __has_include() REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", IReference); REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", @@ -134,6 +135,7 @@ TEST_CASE("generic_type_names") IReference); REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", IReference); +#endif // Enums, structs, IInspectable, classes, and delegates diff --git a/test/test/generic_types.h b/test/test/generic_types.h index d96b3bbfe..5ddba76d9 100644 --- a/test/test/generic_types.h +++ b/test/test/generic_types.h @@ -3,7 +3,9 @@ using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; +#if __has_include() using namespace Windows::Foundation::Numerics; +#endif using namespace std::literals; #define REQUIRE_EQUAL_GUID(left, ...) STATIC_REQUIRE(equal(guid(left), guid_of<__VA_ARGS__>())); @@ -92,6 +94,7 @@ namespace REQUIRE_EQUAL_GUID("84F14C22-A00A-5272-8D3D-82112E66DF00", IReference); REQUIRE_EQUAL_GUID("80423F11-054F-5EAC-AFD3-63B6CE15E77B", IReference); REQUIRE_EQUAL_GUID("61723086-8e53-5276-9f36-2a4bb93e2b75", IReference); +#if __has_include() REQUIRE_EQUAL_GUID("48F6A69E-8465-57AE-9400-9764087F65AD", IReference); REQUIRE_EQUAL_GUID("1EE770FF-C954-59CA-A754-6199A9BE282C", IReference); REQUIRE_EQUAL_GUID("A5E843C9-ED20-5339-8F8D-9FE404CF3654", IReference); @@ -99,6 +102,7 @@ namespace REQUIRE_EQUAL_GUID("DACBFFDC-68EF-5FD0-B657-782D0AC9807E", IReference); REQUIRE_EQUAL_GUID("B27004BB-C014-5DCE-9A21-799C5A3C1461", IReference); REQUIRE_EQUAL_GUID("46D542A1-52F7-58E7-ACFC-9A6D364DA022", IReference); +#endif // Enums, structs, IInspectable, classes, and delegates diff --git a/test/test/initialize.cpp b/test/test/initialize.cpp index dbd95c3fe..e5532fe2d 100644 --- a/test/test/initialize.cpp +++ b/test/test/initialize.cpp @@ -5,11 +5,11 @@ using namespace Windows::Foundation; namespace { - class some_exception : public std::exception + class some_exception : public std::runtime_error { public: some_exception() noexcept - : exception("some_exception", 1) + : runtime_error("some_exception") { } }; diff --git a/test/test/inspectable_interop.cpp b/test/test/inspectable_interop.cpp index d693a6062..bfe46d041 100644 --- a/test/test/inspectable_interop.cpp +++ b/test/test/inspectable_interop.cpp @@ -1,3 +1,4 @@ +#include "mingw_com_support.h" #include #include "winrt/Windows.Foundation.h" #include "catch.hpp" @@ -6,11 +7,18 @@ using namespace winrt; namespace { - struct __declspec(uuid("ed0dd761-c31e-4803-8cf9-22a2cb20ec47")) IBadInterop : ::IInspectable + struct DECLSPEC_UUID("ed0dd761-c31e-4803-8cf9-22a2cb20ec47") IBadInterop : ::IInspectable { virtual int32_t __stdcall JustSayNo() noexcept = 0; }; +} + +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IBadInterop, 0xed0dd761, 0xc31e, 0x4803, 0x8c, 0xf9, 0x22, 0xa2, 0xcb, 0x20, 0xec, 0x47) +#endif +namespace +{ struct Sample : implements { Windows::Foundation::IInspectable ActivateInstance() diff --git a/test/test/interop.cpp b/test/test/interop.cpp index 9ca4c94ea..ec5476d15 100644 --- a/test/test/interop.cpp +++ b/test/test/interop.cpp @@ -1,18 +1,24 @@ #include "pch.h" #include -struct __declspec(uuid("5040a5f4-796a-42ff-9f06-be89137a518f")) IBase : IUnknown +struct DECLSPEC_UUID("5040a5f4-796a-42ff-9f06-be89137a518f") IBase : IUnknown { }; -struct __declspec(uuid("529fed32-514f-4150-b1ba-15b47df700b7")) IDerived : IBase +struct DECLSPEC_UUID("529fed32-514f-4150-b1ba-15b47df700b7") IDerived : IBase { }; -struct __declspec(uuid("b81fb2a2-eab4-488a-96a7-434873c2c20b")) IMoreDerived : IDerived +struct DECLSPEC_UUID("b81fb2a2-eab4-488a-96a7-434873c2c20b") IMoreDerived : IDerived { }; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IBase, 0x5040a5f4, 0x796a, 0x42ff, 0x9f, 0x06, 0xbe, 0x89, 0x13, 0x7a, 0x51, 0x8f) +__CRT_UUID_DECL(IDerived, 0x529fed32, 0x514f, 0x4150, 0xb1, 0xba, 0x15, 0xb4, 0x7d, 0xf7, 0x00, 0xb7) +__CRT_UUID_DECL(IMoreDerived, 0xb81fb2a2, 0xeab4, 0x488a, 0x96, 0xa7, 0x43, 0x48, 0x73, 0xc2, 0xc2, 0x0b) +#endif + namespace winrt { template<> bool is_guid_of(guid const& id) noexcept diff --git a/test/test/main.cpp b/test/test/main.cpp index cb2203171..10150c369 100644 --- a/test/test/main.cpp +++ b/test/test/main.cpp @@ -1,5 +1,9 @@ #include #define CATCH_CONFIG_RUNNER + +// Force reportFatal to be available on mingw-w64 +#define CATCH_CONFIG_WINDOWS_SEH + #include "catch.hpp" #include "winrt/base.h" diff --git a/test/test/notify_awaiter.cpp b/test/test/notify_awaiter.cpp index de2c5f1ab..0305e5a23 100644 --- a/test/test/notify_awaiter.cpp +++ b/test/test/notify_awaiter.cpp @@ -144,6 +144,14 @@ namespace } } +// GNUC does not support MSVC extension lambda call convention conversion +// https://devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623 +#if defined(__GNUC__) +#define LAMBDA_STDCALL __attribute__((stdcall)) +#else +#define LAMBDA_STDCALL +#endif + TEST_CASE("notify_awaiter") { // Everything works fine when nobody is watching. @@ -156,12 +164,12 @@ TEST_CASE("notify_awaiter") // Hook up some watchers. - winrt_suspend_handler = [](void const* token) noexcept + winrt_suspend_handler = [](void const* token) LAMBDA_STDCALL noexcept { watcher.push_back({ token, notification::suspend }); }; - winrt_resume_handler = [](void const* token) noexcept + winrt_resume_handler = [](void const* token) LAMBDA_STDCALL noexcept { auto last = watcher.back(); REQUIRE(last.first == token); diff --git a/test/test/numerics.cpp b/test/test/numerics.cpp index cfc73c0dd..23b2dfb34 100644 --- a/test/test/numerics.cpp +++ b/test/test/numerics.cpp @@ -5,9 +5,11 @@ using namespace Windows::Foundation::Numerics; TEST_CASE("numerics") { +#if __has_include() // Basic smoke test exercising SIMD intrinsics used by numerics. auto one = float4::one(); REQUIRE(one * one == one); +#endif } diff --git a/test/test/pch.h b/test/test/pch.h index 65588aec3..24d65c225 100644 --- a/test/test/pch.h +++ b/test/test/pch.h @@ -2,6 +2,8 @@ #pragma warning(4: 4458) // ensure we compile clean with this warning enabled +#include "mingw_com_support.h" + #define WINRT_LEAN_AND_MEAN #include #include "winrt/Windows.Foundation.Collections.h" diff --git a/test/test/variadic_delegate.cpp b/test/test/variadic_delegate.cpp index a4d0c4a80..6ffbe5ef4 100644 --- a/test/test/variadic_delegate.cpp +++ b/test/test/variadic_delegate.cpp @@ -150,7 +150,7 @@ TEST_CASE("variadic_delegate") // Exception { - delegate<> d = [] { throw std::exception("what"); }; + delegate<> d = [] { throw std::runtime_error("what"); }; REQUIRE_THROWS_AS(d(), std::exception); } diff --git a/test/test_win7/CMakeLists.txt b/test/test_win7/CMakeLists.txt new file mode 100644 index 000000000..7ada247c4 --- /dev/null +++ b/test/test_win7/CMakeLists.txt @@ -0,0 +1,58 @@ +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +# We can't build test_component[*] for mingw-w64 because it doesn't have an +# alternative to midl that can produce winmd files. Also, even if we do manage +# to reuse the MSVC-compiled binaries, mingw-w64 is still missing +# windowsnumerics.impl.h which is needed to provide the types +# winrt::Windows::Foundation::Numerics::float2 and friends that the components +# use. +list(APPEND BROKEN_TESTS + agility + delegates + enum + in_params + no_make_detection + noexcept + out_params + parent_includes + return_params + structs + uniform_in_params + velocity +) + +list(APPEND BROKEN_TESTS + # depends on pplawait.h + when +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_win7 main.cpp ${TEST_SRCS}) + +target_precompile_headers(test_win7 PRIVATE pch.h) +set_source_files_properties( + main.cpp + coro_foundation.cpp + coro_threadpool.cpp + generic_type_names.cpp + inspectable_interop.cpp + module_lock_dll.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_win7 build-cppwinrt-projection) + +add_test( + NAME test_win7 + COMMAND "$" +) diff --git a/test/test_win7/capture.cpp b/test/test_win7/capture.cpp index 8c75681b4..9019d1e34 100644 --- a/test/test_win7/capture.cpp +++ b/test/test_win7/capture.cpp @@ -3,12 +3,16 @@ using namespace winrt; using namespace Windows::Foundation; -struct __declspec(uuid("5fb96f8d-409c-42a9-99a7-8a95c1459dbd")) ICapture : ::IUnknown +struct DECLSPEC_UUID("5fb96f8d-409c-42a9-99a7-8a95c1459dbd") ICapture : ::IUnknown { virtual int32_t __stdcall GetValue() noexcept = 0; virtual int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept = 0; }; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ICapture, 0x5fb96f8d, 0x409c, 0x42a9, 0x99, 0xa7, 0x8a, 0x95, 0xc1, 0x45, 0x9d, 0xbd) +#endif + struct Capture : implements { int32_t const m_value{}; diff --git a/test/test_win7/generic_type_names.cpp b/test/test_win7/generic_type_names.cpp index 580d69ac3..a91266a83 100644 --- a/test/test_win7/generic_type_names.cpp +++ b/test/test_win7/generic_type_names.cpp @@ -114,6 +114,7 @@ TEST_CASE("generic_type_names") IReference); REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", IReference); +#if __has_include() REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", IReference); REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", @@ -134,6 +135,7 @@ TEST_CASE("generic_type_names") IReference); REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", IReference); +#endif // Enums, structs, IInspectable, classes, and delegates diff --git a/test/test_win7/generic_types.h b/test/test_win7/generic_types.h index d96b3bbfe..5ddba76d9 100644 --- a/test/test_win7/generic_types.h +++ b/test/test_win7/generic_types.h @@ -3,7 +3,9 @@ using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; +#if __has_include() using namespace Windows::Foundation::Numerics; +#endif using namespace std::literals; #define REQUIRE_EQUAL_GUID(left, ...) STATIC_REQUIRE(equal(guid(left), guid_of<__VA_ARGS__>())); @@ -92,6 +94,7 @@ namespace REQUIRE_EQUAL_GUID("84F14C22-A00A-5272-8D3D-82112E66DF00", IReference); REQUIRE_EQUAL_GUID("80423F11-054F-5EAC-AFD3-63B6CE15E77B", IReference); REQUIRE_EQUAL_GUID("61723086-8e53-5276-9f36-2a4bb93e2b75", IReference); +#if __has_include() REQUIRE_EQUAL_GUID("48F6A69E-8465-57AE-9400-9764087F65AD", IReference); REQUIRE_EQUAL_GUID("1EE770FF-C954-59CA-A754-6199A9BE282C", IReference); REQUIRE_EQUAL_GUID("A5E843C9-ED20-5339-8F8D-9FE404CF3654", IReference); @@ -99,6 +102,7 @@ namespace REQUIRE_EQUAL_GUID("DACBFFDC-68EF-5FD0-B657-782D0AC9807E", IReference); REQUIRE_EQUAL_GUID("B27004BB-C014-5DCE-9A21-799C5A3C1461", IReference); REQUIRE_EQUAL_GUID("46D542A1-52F7-58E7-ACFC-9A6D364DA022", IReference); +#endif // Enums, structs, IInspectable, classes, and delegates diff --git a/test/test_win7/inspectable_interop.cpp b/test/test_win7/inspectable_interop.cpp index d693a6062..95ee35522 100644 --- a/test/test_win7/inspectable_interop.cpp +++ b/test/test_win7/inspectable_interop.cpp @@ -6,11 +6,18 @@ using namespace winrt; namespace { - struct __declspec(uuid("ed0dd761-c31e-4803-8cf9-22a2cb20ec47")) IBadInterop : ::IInspectable + struct DECLSPEC_UUID("ed0dd761-c31e-4803-8cf9-22a2cb20ec47") IBadInterop : ::IInspectable { virtual int32_t __stdcall JustSayNo() noexcept = 0; }; +} + +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IBadInterop, 0xed0dd761, 0xc31e, 0x4803, 0x8c, 0xf9, 0x22, 0xa2, 0xcb, 0x20, 0xec, 0x47) +#endif +namespace +{ struct Sample : implements { Windows::Foundation::IInspectable ActivateInstance() diff --git a/test/test_win7/interop.cpp b/test/test_win7/interop.cpp index 9ca4c94ea..ec5476d15 100644 --- a/test/test_win7/interop.cpp +++ b/test/test_win7/interop.cpp @@ -1,18 +1,24 @@ #include "pch.h" #include -struct __declspec(uuid("5040a5f4-796a-42ff-9f06-be89137a518f")) IBase : IUnknown +struct DECLSPEC_UUID("5040a5f4-796a-42ff-9f06-be89137a518f") IBase : IUnknown { }; -struct __declspec(uuid("529fed32-514f-4150-b1ba-15b47df700b7")) IDerived : IBase +struct DECLSPEC_UUID("529fed32-514f-4150-b1ba-15b47df700b7") IDerived : IBase { }; -struct __declspec(uuid("b81fb2a2-eab4-488a-96a7-434873c2c20b")) IMoreDerived : IDerived +struct DECLSPEC_UUID("b81fb2a2-eab4-488a-96a7-434873c2c20b") IMoreDerived : IDerived { }; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IBase, 0x5040a5f4, 0x796a, 0x42ff, 0x9f, 0x06, 0xbe, 0x89, 0x13, 0x7a, 0x51, 0x8f) +__CRT_UUID_DECL(IDerived, 0x529fed32, 0x514f, 0x4150, 0xb1, 0xba, 0x15, 0xb4, 0x7d, 0xf7, 0x00, 0xb7) +__CRT_UUID_DECL(IMoreDerived, 0xb81fb2a2, 0xeab4, 0x488a, 0x96, 0xa7, 0x43, 0x48, 0x73, 0xc2, 0xc2, 0x0b) +#endif + namespace winrt { template<> bool is_guid_of(guid const& id) noexcept diff --git a/test/test_win7/main.cpp b/test/test_win7/main.cpp index cb2203171..10150c369 100644 --- a/test/test_win7/main.cpp +++ b/test/test_win7/main.cpp @@ -1,5 +1,9 @@ #include #define CATCH_CONFIG_RUNNER + +// Force reportFatal to be available on mingw-w64 +#define CATCH_CONFIG_WINDOWS_SEH + #include "catch.hpp" #include "winrt/base.h" diff --git a/test/test_win7/numerics.cpp b/test/test_win7/numerics.cpp index cfc73c0dd..23b2dfb34 100644 --- a/test/test_win7/numerics.cpp +++ b/test/test_win7/numerics.cpp @@ -5,9 +5,11 @@ using namespace Windows::Foundation::Numerics; TEST_CASE("numerics") { +#if __has_include() // Basic smoke test exercising SIMD intrinsics used by numerics. auto one = float4::one(); REQUIRE(one * one == one); +#endif } diff --git a/test/test_win7/pch.h b/test/test_win7/pch.h index 1989286de..92e8caa96 100644 --- a/test/test_win7/pch.h +++ b/test/test_win7/pch.h @@ -1,5 +1,7 @@ #pragma once +#include "mingw_com_support.h" + #define WINRT_LEAN_AND_MEAN #include #include "winrt/Windows.Foundation.Collections.h" From fb9ef7b9194a1f29578bf6b9329089e88c58c01c Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Fri, 11 Nov 2022 14:00:51 -0500 Subject: [PATCH 142/305] Remove low-level coroutine suspension notifications (#1228) --- strings/base_coroutine_foundation.h | 18 ++- strings/base_coroutine_threadpool.h | 101 -------------- strings/base_extern.h | 2 - test/old_tests/UnitTests/async.cpp | 8 +- test/test/async_ref_result.cpp | 71 ---------- test/test/async_throw.cpp | 8 +- test/test/disconnected.cpp | 4 +- test/test/notify_awaiter.cpp | 202 ---------------------------- test/test/test.vcxproj | 2 - test/test_win7/async_throw.cpp | 8 +- test/test_win7/disconnected.cpp | 4 +- 11 files changed, 27 insertions(+), 401 deletions(-) delete mode 100644 test/test/async_ref_result.cpp delete mode 100644 test/test/notify_awaiter.cpp diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 31ec1bcc4..22896f42b 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -577,11 +577,6 @@ namespace winrt::impl auto final_suspend() noexcept { - if (winrt_suspend_handler) - { - winrt_suspend_handler(this); - } - return final_suspend_awaiter{ this }; } @@ -606,14 +601,23 @@ namespace winrt::impl } template - auto await_transform(Expression&& expression) + Expression&& await_transform(Expression&& expression) { if (Status() == AsyncStatus::Canceled) { throw winrt::hresult_canceled(); } - return notify_awaiter{ static_cast(expression), m_propagate_cancellation ? &m_cancellable : nullptr }; + if constexpr (std::is_convertible_v&, enable_await_cancellation&>) + { + if (m_propagate_cancellation) + { + static_cast(expression).set_cancellable_promise(&m_cancellable); + expression.enable_cancellation(&m_cancellable); + } + } + + return std::forward(expression); } cancellation_token await_transform(get_cancellation_token_t) noexcept diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index ae77512d7..415857850 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -133,26 +133,6 @@ namespace winrt::impl resume_apartment_sync(context.m_context, handle, failure); } } - - template - class awaiter_finder - { - template static constexpr bool find_awaitable_member(...) { return false; } - template static constexpr bool find_co_await_member(...) { return false; } - template static constexpr bool find_co_await_free(...) { return false; } - -#ifdef WINRT_IMPL_COROUTINES - template ().await_ready())> static constexpr bool find_awaitable_member(int) { return true; } - template ().operator co_await())> static constexpr bool find_co_await_member(int) { return true; } - template ()))> static constexpr bool find_co_await_free(int) { return true; } -#endif - - public: - - static constexpr bool has_awaitable_member = find_awaitable_member(0); - static constexpr bool has_co_await_member = find_co_await_member(0); - static constexpr bool has_co_await_free = find_co_await_free(0); - }; } WINRT_EXPORT namespace winrt @@ -226,76 +206,6 @@ WINRT_EXPORT namespace winrt }; } -namespace winrt::impl -{ - template - decltype(auto) get_awaiter(T&& value) noexcept - { -#ifdef WINRT_IMPL_COROUTINES - if constexpr (awaiter_finder::has_co_await_member) - { - static_assert(!awaiter_finder::has_co_await_free, "Ambiguous operator co_await (as both member and free function)."); - return static_cast(value).operator co_await(); - } - else if constexpr (awaiter_finder::has_co_await_free) - { - return operator co_await(static_cast(value)); - } - else - { - static_assert(awaiter_finder::has_awaitable_member, "Not an awaitable type"); - return static_cast(value); - } -#else - return static_cast(value); -#endif - } - - template - struct notify_awaiter - { - decltype(get_awaiter(std::declval())) awaitable; - - notify_awaiter(T&& awaitable_arg, [[maybe_unused]] cancellable_promise* promise = nullptr) : awaitable(get_awaiter(static_cast(awaitable_arg))) - { - if constexpr (std::is_convertible_v&, enable_await_cancellation&>) - { - if (promise) - { - static_cast(awaitable).set_cancellable_promise(promise); - awaitable.enable_cancellation(promise); - } - } - } - - bool await_ready() - { - if (winrt_suspend_handler) - { - winrt_suspend_handler(this); - } - - return awaitable.await_ready(); - } - - template - auto await_suspend(coroutine_handle handle) - { - return awaitable.await_suspend(handle); - } - - decltype(auto) await_resume() - { - if (winrt_resume_handler) - { - winrt_resume_handler(this); - } - - return awaitable.await_resume(); - } - }; -} - WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_background() noexcept @@ -728,11 +638,6 @@ namespace std::experimental suspend_never final_suspend() const noexcept { - if (winrt_suspend_handler) - { - winrt_suspend_handler(this); - } - return{}; } @@ -740,12 +645,6 @@ namespace std::experimental { winrt::terminate(); } - - template - auto await_transform(Expression&& expression) - { - return winrt::impl::notify_awaiter{ static_cast(expression) }; - } }; }; } diff --git a/strings/base_extern.h b/strings/base_extern.h index b4e3eeed0..52b72bea5 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -2,8 +2,6 @@ __declspec(selectany) int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; __declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; __declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; -__declspec(selectany) void(__stdcall* winrt_suspend_handler)(void const* token) noexcept {}; -__declspec(selectany) void(__stdcall* winrt_resume_handler)(void const* token) noexcept {}; __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; extern "C" diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 08253a385..4544979d0 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -22,7 +22,7 @@ namespace IAsyncAction NoSuspend_IAsyncAction() { - co_await resume_after(0s); + co_await 0s; auto cancel = co_await get_cancellation_token(); @@ -34,7 +34,7 @@ namespace IAsyncActionWithProgress NoSuspend_IAsyncActionWithProgress() { - co_await resume_after(0s); + co_await 0s; auto cancel = co_await get_cancellation_token(); @@ -46,7 +46,7 @@ namespace IAsyncOperation NoSuspend_IAsyncOperation() { - co_await resume_after(0s); + co_await 0s; auto cancel = co_await get_cancellation_token(); @@ -60,7 +60,7 @@ namespace IAsyncOperationWithProgress NoSuspend_IAsyncOperationWithProgress() { - co_await resume_after(0s); + co_await 0s; auto cancel = co_await get_cancellation_token(); diff --git a/test/test/async_ref_result.cpp b/test/test/async_ref_result.cpp deleted file mode 100644 index 31cd1ce29..000000000 --- a/test/test/async_ref_result.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - - // - // Checks that references returned by awaitables - // are not accidentally decayed. - // - // This test "runs" at compile time via static_assert. - - template - struct awaitable : suspend_never - { - std::decay_t value; - T await_resume() { return static_cast(value); } - }; - - template - struct awaitable_member_awaiter : suspend_never - { - decltype(auto) get_awaiter() { return *this; } - std::decay_t value; - T await_resume() { return static_cast(value); } - }; - - template - struct awaitable_free_awaiter : suspend_never - { - std::decay_t value; - T await_resume() { return static_cast(value); } - }; - template - decltype(auto) get_awaiter(awaitable_free_awaiter&& value) { return std::move(value); } - - template typename A, typename T> - IAsyncAction Check() - { - decltype(auto) value = co_await A(); - static_assert(std::is_same_v); - } - - template typename A> - IAsyncAction Check() - { - co_await Check(); - co_await Check(); - co_await Check(); - co_await Check(); - } - - IAsyncAction Test() - { - co_await Check(); - co_await Check(); - co_await Check(); - } -} - -TEST_CASE("async_ref_result") -{ - Test().get(); -} diff --git a/test/test/async_throw.cpp b/test/test/async_throw.cpp index 779351439..88e38d323 100644 --- a/test/test/async_throw.cpp +++ b/test/test/async_throw.cpp @@ -12,26 +12,26 @@ namespace IAsyncAction Action() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); } IAsyncActionWithProgress ActionWithProgress() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); } IAsyncOperation Operation() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); co_return 1; } IAsyncOperationWithProgress OperationWithProgress() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); co_return 1; } diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 13fcad601..8c7e30e49 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -16,7 +16,7 @@ namespace IAsyncActionWithProgress ActionProgress() { - co_await resume_after(500ms); + co_await 500ms; auto progress = co_await get_progress_token(); progress(123); co_return; @@ -29,7 +29,7 @@ namespace IAsyncOperationWithProgress OperationProgress() { - co_await resume_after(500ms); + co_await 500ms; auto progress = co_await get_progress_token(); progress(123); co_return 123; diff --git a/test/test/notify_awaiter.cpp b/test/test/notify_awaiter.cpp deleted file mode 100644 index 0305e5a23..000000000 --- a/test/test/notify_awaiter.cpp +++ /dev/null @@ -1,202 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - - // Never suspends. - // Allows copying, but asserts if you try. - struct suspend_never_but_assert_if_copied : suspend_never - { - suspend_never_but_assert_if_copied() = default; - suspend_never_but_assert_if_copied(suspend_never_but_assert_if_copied const&) - { - REQUIRE(false); - } - }; - - // The bad_awaiter asserts if it ever gets used. - // Use it for ambiguous alternatives we don't want to pick. - struct bad_awaiter : suspend_never - { - void await_resume() const noexcept - { - REQUIRE(false); - } - }; - - // If the only awaitable is the member awaitable, then use it. - struct member_awaitable : suspend_never_but_assert_if_copied - { - }; - - // Should pick the free operator co_await over the member awaitable. - struct free_operator_awaitable : bad_awaiter - { - }; - auto operator co_await(free_operator_awaitable) - { - return suspend_never_but_assert_if_copied{}; - } - - // Should pick the member operator co_await over the member awaitable. - struct member_operator_awaitable : bad_awaiter - { - auto operator co_await() - { - return suspend_never_but_assert_if_copied{}; - } - }; - - // Verify that we can await non-copyable objects. - struct no_copy_awaitable : suspend_never - { - no_copy_awaitable() = default; - no_copy_awaitable(no_copy_awaitable const&) = delete; - }; - - // operator co_await takes precedence over member awaitable. - struct ambiguous_awaitable1 : bad_awaiter - { - auto operator co_await() - { - return suspend_never_but_assert_if_copied{}; - } - }; - - // This awaitable supports both member co_await - // and free co_await, and the free co_await is a - // better match if invoked on an lvalue. We don't try - // to support this case. We just declare it as ambiguous. - struct ambiguous_awaitable2 : bad_awaiter - { - auto operator co_await() const - { - return bad_awaiter{}; - } - }; - suspend_never_but_assert_if_copied operator co_await(ambiguous_awaitable2&) - { - return {}; - } - - // We invoke this on an lvalue, so the member co_await is unavailable. - // Verify that the unavailable co_await is ignored. - struct ambiguous_awaitable3 : suspend_never_but_assert_if_copied - { - auto operator co_await()&& - { - return bad_awaiter{}; - } - }; - - IAsyncAction AsyncAction() - { - co_return; - } - IAsyncActionWithProgress AsyncActionWithProgress() - { - co_return; - } - IAsyncOperation AsyncOperation() - { - co_return 0; - } - IAsyncOperationWithProgress AsyncOperationWithProgress() - { - co_return 0; - } - - enum class notification - { - suspend, - resume, - }; - - static std::vector> watcher; - static handle start_racing{ CreateEventW(nullptr, true, false, nullptr) }; - constexpr size_t test_suspension_points = 13; - - IAsyncAction Async() - { - co_await resume_on_signal(start_racing.get()); - co_await resume_background(); - co_await resume_background(); - co_await member_awaitable{}; - co_await free_operator_awaitable{}; - co_await member_operator_awaitable{}; - co_await no_copy_awaitable{}; - co_await ambiguous_awaitable1{}; - // co_await ambiguous_awaitable2{}; // does not compile - ambiguous_awaitable3 awaitable3; - co_await awaitable3; - co_await AsyncAction(); - co_await AsyncActionWithProgress(); - co_await AsyncOperation(); - co_await AsyncOperationWithProgress(); - } -} - -// GNUC does not support MSVC extension lambda call convention conversion -// https://devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623 -#if defined(__GNUC__) -#define LAMBDA_STDCALL __attribute__((stdcall)) -#else -#define LAMBDA_STDCALL -#endif - -TEST_CASE("notify_awaiter") -{ - // Everything works fine when nobody is watching. - - REQUIRE(!winrt_suspend_handler); - REQUIRE(!winrt_resume_handler); - SetEvent(start_racing.get()); - Async().get(); - ResetEvent(start_racing.get()); - - // Hook up some watchers. - - winrt_suspend_handler = [](void const* token) LAMBDA_STDCALL noexcept - { - watcher.push_back({ token, notification::suspend }); - }; - - winrt_resume_handler = [](void const* token) LAMBDA_STDCALL noexcept - { - auto last = watcher.back(); - REQUIRE(last.first == token); - REQUIRE(last.second == notification::suspend); - watcher.push_back({ token, notification::resume }); - }; - - // Prepare a coroutine. - REQUIRE(watcher.empty()); - auto async = Async(); - - // Give coroutine a moment to get to the starting line. - Sleep(1000); - - // Coroutine should have suspended once. - REQUIRE(watcher.size() == 1); - REQUIRE(watcher.back().second == notification::suspend); - - // And the race is on! - SetEvent(start_racing.get()); - async.get(); - - // Each suspension point should have been recorded plus one for each final_suspend. - REQUIRE(watcher.size() == 2 * test_suspension_points + 5); - - // Remove watchers. - - winrt_suspend_handler = nullptr; - winrt_resume_handler = nullptr; -} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 69c307ebf..bb33508a2 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -280,7 +280,6 @@ - @@ -402,7 +401,6 @@ - diff --git a/test/test_win7/async_throw.cpp b/test/test_win7/async_throw.cpp index bca1e9b26..1cdcf7ffc 100644 --- a/test/test_win7/async_throw.cpp +++ b/test/test_win7/async_throw.cpp @@ -12,26 +12,26 @@ namespace IAsyncAction Action() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); } IAsyncActionWithProgress ActionWithProgress() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); } IAsyncOperation Operation() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); co_return 1; } IAsyncOperationWithProgress OperationWithProgress() { - co_await resume_after(10ms); + co_await 10ms; throw hresult_invalid_argument(L"Async"); co_return 1; } diff --git a/test/test_win7/disconnected.cpp b/test/test_win7/disconnected.cpp index 1757937d0..a69a210d5 100644 --- a/test/test_win7/disconnected.cpp +++ b/test/test_win7/disconnected.cpp @@ -13,7 +13,7 @@ namespace IAsyncActionWithProgress ActionProgress() { - co_await resume_after(500ms); + co_await 500ms; auto progress = co_await get_progress_token(); progress(123); co_return; @@ -26,7 +26,7 @@ namespace IAsyncOperationWithProgress OperationProgress() { - co_await resume_after(500ms); + co_await 500ms; auto progress = co_await get_progress_token(); progress(123); co_return 123; From 8da046a1c3335eeda6df2da8a598ee7d43612f68 Mon Sep 17 00:00:00 2001 From: Raul Perez Date: Fri, 11 Nov 2022 18:18:34 -0800 Subject: [PATCH 143/305] Add fields to filter out templates appearing in the add new item dialog for non UAP projects (#1227) --- vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate | 6 +++++- .../BlankUserControl/cppwinrt_BlankUserControl.vstemplate | 6 +++++- vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate b/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate index 672d43b2f..bf6c43e9e 100644 --- a/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate +++ b/vsix/ItemTemplates/BlankPage/cppwinrt_BlankPage.vstemplate @@ -4,8 +4,12 @@ VC - 10 + 40 microsoft.Windows.CppWinRT.BlankPage + WinRT-Native-UAP + VisualC + WindowsXaml + 0 + false cppwinrt.ico cppwinrt.png diff --git a/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate b/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate index e872ae3e0..f457df025 100644 --- a/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate +++ b/vsix/ItemTemplates/BlankUserControl/cppwinrt_BlankUserControl.vstemplate @@ -4,8 +4,12 @@ VC - 10 + 41 microsoft.Windows.CppWinRT.BlankUserControl + WinRT-Native-UAP + VisualC + WindowsXaml + 0 + false cppwinrt.ico cppwinrt.png diff --git a/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate b/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate index 5e5a5dbdd..20d2bcd90 100644 --- a/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate +++ b/vsix/ItemTemplates/ViewModel/cppwinrt_ViewModel.vstemplate @@ -4,8 +4,12 @@ VC - 10 + 42 microsoft.Windows.CppWinRT.ViewModel + WinRT-Native-UAP + VisualC + WindowsXaml + 0 + false cppwinrt.ico cppwinrt.png From 104b0b9a2741d68b2112ecc6955e3cdf3fb85e4e Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Sat, 12 Nov 2022 10:32:51 -0500 Subject: [PATCH 144/305] Efficient way to format directly to hstring (#1207) --- strings/base_string.h | 28 ++++++++++++++++++++++++++++ test/test_cpp20/format.cpp | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/strings/base_string.h b/strings/base_string.h index c23e981c3..dbe022857 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -550,10 +550,38 @@ namespace winrt::impl auto end = std::copy(std::begin(temp), result.ptr, buffer); return hstring{ std::wstring_view{ buffer, static_cast(end - buffer)} }; } + +#if __cpp_lib_format >= 202207L + template + inline hstring base_format(Args&&... args) + { + auto const size = std::formatted_size(args...); + WINRT_ASSERT(size < UINT_MAX); + auto const size32 = static_cast(size); + + hstring_builder builder(size32); + WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); + return builder.to_hstring(); + } +#endif } WINRT_EXPORT namespace winrt { +#if __cpp_lib_format >= 202207L + template + inline hstring format(std::wformat_string const fmt, Args&&... args) + { + return impl::base_format(fmt, args...); + } + + template + inline hstring format(std::locale const& loc, std::wformat_string const fmt, Args&&... args) + { + return impl::base_format(loc, fmt, args...); + } +#endif + inline bool embedded_null(hstring const& value) noexcept { return std::any_of(value.begin(), value.end(), [](auto item) diff --git a/test/test_cpp20/format.cpp b/test/test_cpp20/format.cpp index b3119a77e..a77c2afbe 100644 --- a/test/test_cpp20/format.cpp +++ b/test/test_cpp20/format.cpp @@ -25,4 +25,11 @@ TEST_CASE("format") winrt::Windows::Data::Json::JsonArray jsonArray; REQUIRE(std::format(L"The contents of the array are: {}", jsonArray) == L"The contents of the array are: []"); } + +#if __cpp_lib_format >= 202207L + { + std::wstring str = L"World"; + REQUIRE(winrt::format(L"Hello {}", str) == L"Hello World"); + } +#endif } From 921f62f1faf4c4d36ae2c82b45aaac4334c69819 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Fri, 18 Nov 2022 23:32:09 +0800 Subject: [PATCH 145/305] Enable more tests on llvm-mingw and some fixes (#1229) --- .github/workflows/ci.yml | 6 +- cppwinrt/cmd_reader.h | 4 +- strings/base_includes.h | 2 +- strings/base_macros.h | 2 +- test/CMakeLists.txt | 34 +++++++++++ test/old_tests/CMakeLists.txt | 1 + test/old_tests/UnitTests/CMakeLists.txt | 61 +++++++++++++++++++ test/old_tests/UnitTests/Main.cpp | 5 ++ test/old_tests/UnitTests/VariadicDelegate.cpp | 4 +- test/old_tests/UnitTests/agile_ref.cpp | 4 +- .../old_tests/UnitTests/apartment_context.cpp | 21 ++++++- test/old_tests/UnitTests/array.cpp | 7 +++ test/old_tests/UnitTests/async.cpp | 50 +++++++-------- test/old_tests/UnitTests/async_cancel.cpp | 6 +- test/old_tests/UnitTests/capture.cpp | 6 +- test/old_tests/UnitTests/com_ref.cpp | 6 +- test/old_tests/UnitTests/hresult_error.cpp | 7 ++- test/old_tests/UnitTests/make_self.cpp | 12 +++- test/old_tests/UnitTests/param_iterable.cpp | 1 + test/old_tests/UnitTests/pch.h | 2 + test/test/coro_system.cpp | 3 - test/test/coro_ui_core.cpp | 3 - test/test/main.cpp | 1 + test/test_cpp20/CMakeLists.txt | 36 +++++++++++ test/test_cpp20/main.cpp | 4 ++ test/test_win7/async_auto_cancel.cpp | 2 +- test/test_win7/async_cancel_callback.cpp | 2 +- test/test_win7/async_check_cancel.cpp | 2 +- test/test_win7/async_throw.cpp | 2 +- test/test_win7/async_wait_for.cpp | 2 +- 30 files changed, 243 insertions(+), 55 deletions(-) create mode 100644 test/old_tests/CMakeLists.txt create mode 100644 test/old_tests/UnitTests/CMakeLists.txt create mode 100644 test/test_cpp20/CMakeLists.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b75b06cfd..310f7d1a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -295,8 +295,8 @@ jobs: run: | mkdir build cd build - cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug - cmake --build . --target cppwinrt + cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DDOWNLOAD_WINDOWSNUMERICS=TRUE + cmake --build . -j2 --target cppwinrt - name: Upload cppwinrt.exe uses: actions/upload-artifact@v3 @@ -307,7 +307,7 @@ jobs: - name: Build tests run: | cd build - cmake --build . --target test-vanilla test_win7 + cmake --build . -j2 --target test-vanilla test_cpp20 test_win7 test_old - name: Upload test binaries uses: actions/upload-artifact@v3 diff --git a/cppwinrt/cmd_reader.h b/cppwinrt/cmd_reader.h index 376180eb4..bb5454258 100644 --- a/cppwinrt/cmd_reader.h +++ b/cppwinrt/cmd_reader.h @@ -12,9 +12,9 @@ #include #include #include -#include +#include #include -#include +#include namespace cppwinrt { diff --git a/strings/base_includes.h b/strings/base_includes.h index ef2b9d8e2..10518a705 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -20,7 +20,7 @@ #include #include -#if __has_include() +#if __has_include() #define WINRT_IMPL_NUMERICS #include #endif diff --git a/strings/base_macros.h b/strings/base_macros.h index a7d757fad..d48db139d 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -33,7 +33,7 @@ #define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_END_NAMESPACE_ -#include +#include #undef _WINDOWS_NUMERICS_NAMESPACE_ #undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ #undef _WINDOWS_NUMERICS_END_NAMESPACE_ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4cf322da9..0c3c4de61 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,6 +22,35 @@ if(TARGET_IS_X64) endif() +# Some tests requires windowsnumerics.impl.h, but mingw-w64 didn't have this +# header until very recently. In case it is not present, download a copy if +# DOWNLOAD_WINDOWSNUMERICS is true, otherwise skip the tests which depend on +# this header. +function(TestHasWindowsnumerics OUTPUT_VARNAME) + include(CheckCXXSourceCompiles) + check_cxx_source_compiles(" +#define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_END_NAMESPACE_ +#include +int main() {} + " ${OUTPUT_VARNAME}) +endfunction() +TestHasWindowsnumerics(HAS_WINDOWSNUMERICS) +set(DOWNLOAD_WINDOWSNUMERICS FALSE CACHE BOOL "Whether to download a copy of mingw-w64's windowsnumerics.impl.h if not available.") +if(NOT HAS_WINDOWSNUMERICS AND DOWNLOAD_WINDOWSNUMERICS) + file( + DOWNLOAD https://github.com/mingw-w64/mingw-w64/raw/2b6272b31132e156dd1fc3722c1aa96b705a90dd/mingw-w64-headers/include/windowsnumerics.impl.h + "${CMAKE_CURRENT_BINARY_DIR}/windowsnumerics/windowsnumerics.impl.h" + EXPECTED_HASH SHA256=aff42491e57583c8ad8ca8e71d417a553bd1215ee9a71378679400ecded4b1ab + SHOW_PROGRESS + ) + include_directories("${CMAKE_CURRENT_BINARY_DIR}/windowsnumerics") + set(HAS_WINDOWSNUMERICS TRUE) + message(STATUS "Using windowsnumerics.impl.h downloaded from mingw-w64") +endif() + + add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt/winrt/base.h" @@ -37,4 +66,9 @@ add_custom_target(build-cppwinrt-projection add_subdirectory(test) +add_subdirectory(test_cpp20) add_subdirectory(test_win7) + +if(HAS_WINDOWSNUMERICS) + add_subdirectory(old_tests) +endif() diff --git a/test/old_tests/CMakeLists.txt b/test/old_tests/CMakeLists.txt new file mode 100644 index 000000000..e1af6d31c --- /dev/null +++ b/test/old_tests/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(UnitTests) diff --git a/test/old_tests/UnitTests/CMakeLists.txt b/test/old_tests/UnitTests/CMakeLists.txt new file mode 100644 index 000000000..7042aa63b --- /dev/null +++ b/test/old_tests/UnitTests/CMakeLists.txt @@ -0,0 +1,61 @@ +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(Main|pch)\\.cpp") + + +# We can't build custom Component for mingw-w64 because it doesn't have an +# alternative to midl that can produce winmd files. +list(APPEND BROKEN_TESTS + Boxing2 + Composable + Errors + Events + FastInput + Parameters + StructCodeGen + Structures + delegate_weak_strong + factory_cache + get_activation_factory + smart_pointers +) + +list(APPEND BROKEN_TESTS + # Missing `Windows.Applicationmodel.Activation.h` + constexpr + + # Missing `Windows.ApplicationModel.Appointments.h` + enum_flags + + # Missing component `Reflect`. + # Test is also not included in the VS project. + reflect + + # Segfault in winrt::impl::natvis::abi_val. + # Test is also not included in the VS project. + natvis +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_old Main.cpp ${TEST_SRCS}) +target_link_libraries(test_old runtimeobject synchronization) + +target_precompile_headers(test_old PRIVATE pch.h) +set_source_files_properties( + conditional_implements_pure.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_old build-cppwinrt-projection) + +add_test( + NAME test_old + COMMAND "$" +) diff --git a/test/old_tests/UnitTests/Main.cpp b/test/old_tests/UnitTests/Main.cpp index da790c357..3e5ecf03e 100644 --- a/test/old_tests/UnitTests/Main.cpp +++ b/test/old_tests/UnitTests/Main.cpp @@ -2,6 +2,10 @@ #include "pch.h" #define CATCH_CONFIG_RUNNER + +// Force reportFatal to be available on mingw-w64 +#define CATCH_CONFIG_WINDOWS_SEH + #include "catch.hpp" int main(int argc, char * argv[]) @@ -14,6 +18,7 @@ int main(int argc, char * argv[]) _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); int const result = Catch::Session().run(argc, argv); // Completely unnecessary in an app, but useful for testing clear_factory_cache behavior. diff --git a/test/old_tests/UnitTests/VariadicDelegate.cpp b/test/old_tests/UnitTests/VariadicDelegate.cpp index af5f86e2a..47c5da0fc 100644 --- a/test/old_tests/UnitTests/VariadicDelegate.cpp +++ b/test/old_tests/UnitTests/VariadicDelegate.cpp @@ -101,7 +101,7 @@ TEST_CASE("Variadic delegate - event") TEST_CASE("Variadic delegate - exception") { - delegate<> d = [] { throw std::exception("what"); }; + delegate<> d = [] { throw std::runtime_error("what"); }; REQUIRE_THROWS_AS(d(), std::exception); } @@ -120,4 +120,4 @@ TEST_CASE("Variadic delegate - object") REQUIRE(object.m_state == 0); d(123); REQUIRE(object.m_state == 123); -} \ No newline at end of file +} diff --git a/test/old_tests/UnitTests/agile_ref.cpp b/test/old_tests/UnitTests/agile_ref.cpp index 3d855f886..2bf6dd637 100644 --- a/test/old_tests/UnitTests/agile_ref.cpp +++ b/test/old_tests/UnitTests/agile_ref.cpp @@ -36,8 +36,8 @@ IAsyncAction test_agile_ref() }); } -#if defined(__clang__) && (defined(_M_IX86) || defined(__i386__)) -// FIXME: Test is known to crash with exit code 0x80000003 (breakpoint?) on x86 when built with Clang. +#if defined(__clang__) && defined(_MSC_VER) && (defined(_M_IX86) || defined(__i386__)) +// FIXME: Test is known to crash from calling invalid address on x86 when built with Clang. TEST_CASE("agile_ref", "[.clang-crash]") #else TEST_CASE("agile_ref") diff --git a/test/old_tests/UnitTests/apartment_context.cpp b/test/old_tests/UnitTests/apartment_context.cpp index f554afffc..8500a3100 100644 --- a/test/old_tests/UnitTests/apartment_context.cpp +++ b/test/old_tests/UnitTests/apartment_context.cpp @@ -46,6 +46,11 @@ namespace co_await context; } +// Not yet buildable on mingw-w64. The lambda needs to have __stdcall +// specified on it but there is a Clang crash bug blocking this: +// https://github.com/llvm/llvm-project/issues/58366 +#if !defined(__MINGW32__) + template void InvokeInContext(IContextCallback* context, TLambda&& lambda) { @@ -69,6 +74,8 @@ namespace return context; } +#endif + bool is_nta_on_mta() { APTTYPE type; @@ -90,6 +97,10 @@ namespace return (hr == RPC_E_SERVER_DIED_DNE) || (hr == RPC_E_DISCONNECTED); } +// Not yet buildable on mingw-w64. +// Missing __uuidof(IContextCallback). +#if !defined(__MINGW32__) + IAsyncAction TestNeutralApartmentContext() { auto controller = DispatcherQueueController::CreateOnDedicatedThread(); @@ -102,6 +113,8 @@ namespace REQUIRE(is_nta_on_mta()); } +#endif + IAsyncAction TestStaToStaApartmentContext() { bool pass = false; @@ -245,17 +258,23 @@ TEST_CASE("apartment_context coverage") Async().get(); } +// Not yet buildable on mingw-w64. +// Missing __uuidof(IContextCallback). +#if !defined(__MINGW32__) + TEST_CASE("apartment_context nta") { TestNeutralApartmentContext().get(); } +#endif + TEST_CASE("apartment_context sta") { TestStaToStaApartmentContext().get(); } -#if defined(__clang__) && (defined(_M_IX86) || defined(__i386__)) +#if defined(__clang__) && defined(_MSC_VER) && (defined(_M_IX86) || defined(__i386__)) // FIXME: Test is known to segfault on x86 when built with Clang. TEST_CASE("apartment_context disconnected", "[.clang-crash]") #else diff --git a/test/old_tests/UnitTests/array.cpp b/test/old_tests/UnitTests/array.cpp index 3fc499bec..f6a7654f3 100644 --- a/test/old_tests/UnitTests/array.cpp +++ b/test/old_tests/UnitTests/array.cpp @@ -941,13 +941,20 @@ TEST_CASE("array_view,cv array_view") array_view a2 = a; REQUIRE(a2.data() == a.data()); REQUIRE(a2.size() == 3); + // For libc++ as of LLVM 15, std::equal is unable to compare between + // volatile and non-volatile elements of ranges. + // https://github.com/llvm/llvm-project/issues/59021 +#if !defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 160000 REQUIRE(a2 == a); +#endif } { array_view a2 = a; REQUIRE(a2.data() == a.data()); REQUIRE(a2.size() == 3); +#if !defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 160000 REQUIRE(a2 == a); +#endif } } diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 4544979d0..e5c468144 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -397,7 +397,7 @@ namespace #endif } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncAction", "[.clang-crash]") #else @@ -442,7 +442,7 @@ TEST_CASE("async, Throw_IAsyncAction") } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncAction, 2", "[.clang-crash]") #else @@ -488,7 +488,7 @@ TEST_CASE("async, Throw_IAsyncAction, 2") } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncActionWithProgress", "[.clang-crash]") #else @@ -533,7 +533,7 @@ TEST_CASE("async, Throw_IAsyncActionWithProgress") } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncActionWithProgress, 2", "[.clang-crash]") #else @@ -579,7 +579,7 @@ TEST_CASE("async, Throw_IAsyncActionWithProgress, 2") } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncOperation", "[.clang-crash]") #else @@ -624,7 +624,7 @@ TEST_CASE("async, Throw_IAsyncOperation") } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncOperation, 2", "[.clang-crash]") #else @@ -670,7 +670,7 @@ TEST_CASE("async, Throw_IAsyncOperation, 2") } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncOperationWithProgress", "[.clang-crash]") #else @@ -715,7 +715,7 @@ TEST_CASE("async, Throw_IAsyncOperationWithProgress") } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Throw_IAsyncOperationWithProgress, 2", "[.clang-crash]") #else @@ -813,7 +813,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncAction", "[.clang-crash]") #else @@ -848,7 +848,7 @@ TEST_CASE("async, Cancel_IAsyncAction") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncAction, 2", "[.clang-crash]") #else @@ -883,7 +883,7 @@ TEST_CASE("async, Cancel_IAsyncAction, 2") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncActionWithProgress", "[.clang-crash]") #else @@ -919,7 +919,7 @@ TEST_CASE("async, Cancel_IAsyncActionWithProgress") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncActionWithProgress, 2", "[.clang-crash]") #else @@ -955,7 +955,7 @@ TEST_CASE("async, Cancel_IAsyncActionWithProgress, 2") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncOperation", "[.clang-crash]") #else @@ -990,7 +990,7 @@ TEST_CASE("async, Cancel_IAsyncOperation") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncOperation, 2", "[.clang-crash]") #else @@ -1025,7 +1025,7 @@ TEST_CASE("async, Cancel_IAsyncOperation, 2") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncOperationWithProgress", "[.clang-crash]") #else @@ -1061,7 +1061,7 @@ TEST_CASE("async, Cancel_IAsyncOperationWithProgress") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, Cancel_IAsyncOperationWithProgress, 2", "[.clang-crash]") #else @@ -1149,7 +1149,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, AutoCancel_IAsyncAction", "[.clang-crash]") #else @@ -1182,7 +1182,7 @@ TEST_CASE("async, AutoCancel_IAsyncAction") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, AutoCancel_IAsyncAction, 2", "[.clang-crash]") #else @@ -1215,7 +1215,7 @@ TEST_CASE("async, AutoCancel_IAsyncAction, 2") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("", "[.clang-crash]") #else @@ -1248,7 +1248,7 @@ TEST_CASE("async, AutoCancel_IAsyncActionWithProgress") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, AutoCancel_IAsyncActionWithProgress, 2", "[.clang-crash]") #else @@ -1281,7 +1281,7 @@ TEST_CASE("async, AutoCancel_IAsyncActionWithProgress, 2") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, AutoCancel_IAsyncOperation", "[.clang-crash]") #else @@ -1314,7 +1314,7 @@ TEST_CASE("async, AutoCancel_IAsyncOperation") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, AutoCancel_IAsyncOperation, 2", "[.clang-crash]") #else @@ -1347,7 +1347,7 @@ TEST_CASE("async, AutoCancel_IAsyncOperation, 2") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress", "[.clang-crash]") #else @@ -1380,7 +1380,7 @@ TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress") REQUIRE(statusMatches); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, AutoCancel_IAsyncOperationWithProgress, 2", "[.clang-crash]") #else @@ -1443,7 +1443,7 @@ TEST_CASE("async, get, suspend with success") REQUIRE(456 == d.get()); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async, get, failure", "[.clang-crash]") #else diff --git a/test/old_tests/UnitTests/async_cancel.cpp b/test/old_tests/UnitTests/async_cancel.cpp index 9bf6a75bc..1464b6c4e 100644 --- a/test/old_tests/UnitTests/async_cancel.cpp +++ b/test/old_tests/UnitTests/async_cancel.cpp @@ -122,7 +122,7 @@ TEST_CASE("async_cancel_no_async") REQUIRE(a.Status() == AsyncStatus::Completed); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_cancel_before_callback", "[.clang-crash]") #else @@ -144,7 +144,7 @@ TEST_CASE("async_cancel_before_callback") REQUIRE(async.Status() == AsyncStatus::Canceled); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to randomly crash when built with Clang. TEST_CASE("async_cancel_after_callback", "[.clang-crash]") #else @@ -164,7 +164,7 @@ TEST_CASE("async_cancel_after_callback") REQUIRE(async.Status() == AsyncStatus::Canceled); } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_cancel_use_status", "[.clang-crash]") #else diff --git a/test/old_tests/UnitTests/capture.cpp b/test/old_tests/UnitTests/capture.cpp index 936f5ed77..c72f1ecff 100644 --- a/test/old_tests/UnitTests/capture.cpp +++ b/test/old_tests/UnitTests/capture.cpp @@ -4,12 +4,16 @@ using namespace winrt; using namespace Windows::Foundation; -struct __declspec(uuid("5fb96f8d-409c-42a9-99a7-8a95c1459dbd")) ICapture : ::IUnknown +struct DECLSPEC_UUID("5fb96f8d-409c-42a9-99a7-8a95c1459dbd") ICapture : ::IUnknown { virtual int32_t __stdcall GetValue() noexcept = 0; virtual int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept = 0; }; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(ICapture, 0x5fb96f8d, 0x409c, 0x42a9, 0x99, 0xa7, 0x8a, 0x95, 0xc1, 0x45, 0x9d, 0xbd) +#endif + struct Capture : implements { int32_t const m_value{}; diff --git a/test/old_tests/UnitTests/com_ref.cpp b/test/old_tests/UnitTests/com_ref.cpp index 5457c493a..73c30e331 100644 --- a/test/old_tests/UnitTests/com_ref.cpp +++ b/test/old_tests/UnitTests/com_ref.cpp @@ -3,7 +3,7 @@ namespace { - struct __declspec(uuid("52bb7805-e46e-46f9-8508-86606d2f6bc1")) IClassic : ::IUnknown + struct DECLSPEC_UUID("52bb7805-e46e-46f9-8508-86606d2f6bc1") IClassic : ::IUnknown { }; @@ -12,6 +12,10 @@ namespace }; } +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IClassic, 0x52bb7805, 0xe46e, 0x46f9, 0x85, 0x08, 0x86, 0x60, 0x6d, 0x2f, 0x6b, 0xc1); +#endif + TEST_CASE("com_ref agile_ref") { { diff --git a/test/old_tests/UnitTests/hresult_error.cpp b/test/old_tests/UnitTests/hresult_error.cpp index 1acac1565..23ad209af 100644 --- a/test/old_tests/UnitTests/hresult_error.cpp +++ b/test/old_tests/UnitTests/hresult_error.cpp @@ -1,6 +1,11 @@ #include "pch.h" #include "catch.hpp" +// Missing in mingw-w64 +#ifndef E_BOUNDS +#define E_BOUNDS (0x8000000B) +#endif + extern "C" BOOL __stdcall RoOriginateLanguageException(HRESULT error, void* message, void* languageException); using namespace winrt; @@ -497,7 +502,7 @@ TEST_CASE("hresult, std abi support") { EventHandler handler = [](auto&& ...) { - throw std::exception("std__exception"); + throw std::runtime_error("std__exception"); }; handler(nullptr, 0); diff --git a/test/old_tests/UnitTests/make_self.cpp b/test/old_tests/UnitTests/make_self.cpp index 9924b4619..f7c0b1e3e 100644 --- a/test/old_tests/UnitTests/make_self.cpp +++ b/test/old_tests/UnitTests/make_self.cpp @@ -1,6 +1,12 @@ #include "pch.h" #include "catch.hpp" +#if defined(_MSC_VER) +#define WDECLSPECL_NOVTABLE __declspec(novtable) +#else +#define WDECLSPECL_NOVTABLE +#endif + // // These tests ensure that the make_self function works as expected to provide direct acccess // to an implementation. @@ -11,11 +17,15 @@ using namespace winrt; -struct __declspec(uuid("eebb3a22-13a6-43b9-9d53-b7deb5a20ae5")) __declspec(novtable) IMakeSelf : IUnknown +struct DECLSPEC_UUID("eebb3a22-13a6-43b9-9d53-b7deb5a20ae5") WDECLSPECL_NOVTABLE IMakeSelf : IUnknown { virtual HRESULT __stdcall Call() = 0; }; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IMakeSelf, 0xeebb3a22, 0x13a6, 0x43b9, 0x9d, 0x53, 0xb7, 0xde, 0xb5, 0xa2, 0x0a, 0xe5); +#endif + struct MakeSelfStringable : implements { hstring ToString() diff --git a/test/old_tests/UnitTests/param_iterable.cpp b/test/old_tests/UnitTests/param_iterable.cpp index 567e86859..758ff929d 100644 --- a/test/old_tests/UnitTests/param_iterable.cpp +++ b/test/old_tests/UnitTests/param_iterable.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "catch.hpp" +#include using namespace winrt; using namespace Windows::Foundation::Collections; diff --git a/test/old_tests/UnitTests/pch.h b/test/old_tests/UnitTests/pch.h index 51c6bc820..26990fd1c 100644 --- a/test/old_tests/UnitTests/pch.h +++ b/test/old_tests/UnitTests/pch.h @@ -4,6 +4,8 @@ #define WINRT_NATVIS #define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING +#include "mingw_com_support.h" + // Light up ::IUnknown interop by including this first #include #undef GetCurrentTime diff --git a/test/test/coro_system.cpp b/test/test/coro_system.cpp index 21748a91c..db6d5e4ac 100644 --- a/test/test/coro_system.cpp +++ b/test/test/coro_system.cpp @@ -13,10 +13,7 @@ namespace { co_await resume_foreground(queue); -// FIXME: Fail to compile with Clang due to co_await overload resolution -#if !defined(__clang__) co_await queue; -#endif } } diff --git a/test/test/coro_ui_core.cpp b/test/test/coro_ui_core.cpp index 55df15b65..90841cbc7 100644 --- a/test/test/coro_ui_core.cpp +++ b/test/test/coro_ui_core.cpp @@ -18,10 +18,7 @@ namespace co_await resume_foreground(queue); -// FIXME: Fail to compile with Clang due to co_await overload resolution -#if !defined(__clang__) co_await queue; -#endif } } diff --git a/test/test/main.cpp b/test/test/main.cpp index 10150c369..47d65e667 100644 --- a/test/test/main.cpp +++ b/test/test/main.cpp @@ -17,6 +17,7 @@ int main(int const argc, char** argv) _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); return Catch::Session().run(argc, argv); } diff --git a/test/test_cpp20/CMakeLists.txt b/test/test_cpp20/CMakeLists.txt new file mode 100644 index 000000000..66cfffcee --- /dev/null +++ b/test/test_cpp20/CMakeLists.txt @@ -0,0 +1,36 @@ +set(CMAKE_CXX_STANDARD 20) +# std::format, std::ranges::is_heap, std::views::reverse, std::ranges::max +# are experimental in libc++ as of Clang 15. +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") + +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +list(APPEND BROKEN_TESTS + # No broken tests. +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_cpp20 main.cpp ${TEST_SRCS}) + +target_precompile_headers(test_cpp20 PRIVATE pch.h) +set_source_files_properties( + main.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_cpp20 build-cppwinrt-projection) + +add_test( + NAME test_cpp20 + COMMAND "$" +) diff --git a/test/test_cpp20/main.cpp b/test/test_cpp20/main.cpp index cb2203171..10150c369 100644 --- a/test/test_cpp20/main.cpp +++ b/test/test_cpp20/main.cpp @@ -1,5 +1,9 @@ #include #define CATCH_CONFIG_RUNNER + +// Force reportFatal to be available on mingw-w64 +#define CATCH_CONFIG_WINDOWS_SEH + #include "catch.hpp" #include "winrt/base.h" diff --git a/test/test_win7/async_auto_cancel.cpp b/test/test_win7/async_auto_cancel.cpp index 5272e7fad..cceafa443 100644 --- a/test/test_win7/async_auto_cancel.cpp +++ b/test/test_win7/async_auto_cancel.cpp @@ -70,7 +70,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_auto_cancel", "[.clang-crash]") #else diff --git a/test/test_win7/async_cancel_callback.cpp b/test/test_win7/async_cancel_callback.cpp index 1f3a97e04..396636eba 100644 --- a/test/test_win7/async_cancel_callback.cpp +++ b/test/test_win7/async_cancel_callback.cpp @@ -90,7 +90,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_cancel_callback", "[.clang-crash]") #else diff --git a/test/test_win7/async_check_cancel.cpp b/test/test_win7/async_check_cancel.cpp index fb661d8c8..7547609f6 100644 --- a/test/test_win7/async_check_cancel.cpp +++ b/test/test_win7/async_check_cancel.cpp @@ -104,7 +104,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_check_cancel", "[.clang-crash]") #else diff --git a/test/test_win7/async_throw.cpp b/test/test_win7/async_throw.cpp index 1cdcf7ffc..88e38d323 100644 --- a/test/test_win7/async_throw.cpp +++ b/test/test_win7/async_throw.cpp @@ -77,7 +77,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_throw", "[.clang-crash]") #else diff --git a/test/test_win7/async_wait_for.cpp b/test/test_win7/async_wait_for.cpp index d25664495..d7613083c 100644 --- a/test/test_win7/async_wait_for.cpp +++ b/test/test_win7/async_wait_for.cpp @@ -96,7 +96,7 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_wait_for", "[.clang-crash]") #else From 96bfd1631e7b9dbf3c5e8aef0ae3a8f9e698f758 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 21 Nov 2022 11:26:06 -0500 Subject: [PATCH 146/305] Fix formatting base types such as integers (#1231) --- strings/base_string.h | 8 ++++---- test/test_cpp20/format.cpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/strings/base_string.h b/strings/base_string.h index dbe022857..13f3b9dce 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -555,12 +555,12 @@ namespace winrt::impl template inline hstring base_format(Args&&... args) { - auto const size = std::formatted_size(args...); + auto const size = std::formatted_size(std::forward(args)...); WINRT_ASSERT(size < UINT_MAX); auto const size32 = static_cast(size); hstring_builder builder(size32); - WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); + WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, std::forward(args)...).size); return builder.to_hstring(); } #endif @@ -572,13 +572,13 @@ WINRT_EXPORT namespace winrt template inline hstring format(std::wformat_string const fmt, Args&&... args) { - return impl::base_format(fmt, args...); + return impl::base_format(fmt, std::forward(args)...); } template inline hstring format(std::locale const& loc, std::wformat_string const fmt, Args&&... args) { - return impl::base_format(loc, fmt, args...); + return impl::base_format(loc, fmt, std::forward(args)...); } #endif diff --git a/test/test_cpp20/format.cpp b/test/test_cpp20/format.cpp index a77c2afbe..69da0d0c1 100644 --- a/test/test_cpp20/format.cpp +++ b/test/test_cpp20/format.cpp @@ -31,5 +31,9 @@ TEST_CASE("format") std::wstring str = L"World"; REQUIRE(winrt::format(L"Hello {}", str) == L"Hello World"); } + + { + REQUIRE(winrt::format(L"C++/WinRT #{:d}", 1) == L"C++/WinRT #1"); + } #endif } From e96613d88b16304d6035a090685dc168c2bf5e0a Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 22 Nov 2022 00:26:55 +0800 Subject: [PATCH 147/305] Fix multi_threaded_map/_vector tests on Clang (#1230) --- test/test/CMakeLists.txt | 2 +- test/test/multi_threaded_common.h | 1 - test/test/multi_threaded_map.cpp | 4 ---- test/test/multi_threaded_vector.cpp | 6 +----- 4 files changed, 2 insertions(+), 11 deletions(-) diff --git a/test/test/CMakeLists.txt b/test/test/CMakeLists.txt index f5921a0bc..c14fc7c00 100644 --- a/test/test/CMakeLists.txt +++ b/test/test/CMakeLists.txt @@ -46,7 +46,7 @@ endforeach() add_executable(test-vanilla main.cpp ${TEST_SRCS}) set_target_properties(test-vanilla PROPERTIES OUTPUT_NAME "test") -target_link_libraries(test-vanilla runtimeobject) +target_link_libraries(test-vanilla runtimeobject synchronization) target_precompile_headers(test-vanilla PRIVATE pch.h) set_source_files_properties( diff --git a/test/test/multi_threaded_common.h b/test/test/multi_threaded_common.h index 22a3e6577..971e56c6b 100644 --- a/test/test/multi_threaded_common.h +++ b/test/test/multi_threaded_common.h @@ -152,7 +152,6 @@ namespace concurrent_collections concurrency_checked_random_access_iterator(container const* c, iterator it) : owner(c), iterator(it) {} // Implicit conversion from non-const iterator to const iterator. - template>> concurrency_checked_random_access_iterator(concurrency_checked_random_access_iterator other) : owner(other.owner), iterator(other.inner()) { } concurrency_checked_random_access_iterator(concurrency_checked_random_access_iterator const&) = default; diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index f57cca23a..b2b143f11 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -5,9 +5,6 @@ #include "multi_threaded_common.h" -// FIXME: Fail to compile with Clang due to "error : no type named 'type' in 'std::enable_if'" -#if !defined(__clang__) - using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; @@ -338,4 +335,3 @@ TEST_CASE("multi_threaded_observable_map") test_map_concurrency(); test_map_concurrency(); } -#endif diff --git a/test/test/multi_threaded_vector.cpp b/test/test/multi_threaded_vector.cpp index 55a206830..3f7408510 100644 --- a/test/test/multi_threaded_vector.cpp +++ b/test/test/multi_threaded_vector.cpp @@ -2,9 +2,6 @@ #include "multi_threaded_common.h" -// FIXME: Fail to compile with Clang due to "error : no type named 'type' in 'std::enable_if'" -#if !defined(__clang__) - using namespace winrt; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; @@ -84,7 +81,7 @@ namespace } else { - return vector.as>(); + return vector.template as>(); } } } @@ -469,4 +466,3 @@ TEST_CASE("multi_threaded_observable_vector") test_vector_concurrency(); test_vector_concurrency(); } -#endif From d81ec9fde12adebfa21d90124d9ca5225e8d0131 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 22 Nov 2022 01:33:09 +0800 Subject: [PATCH 148/305] Minor changes to CMakeLists.txt (#1233) --- CMakeLists.txt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a60ba31e..bcc3ca583 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ # # It most probably doesn't work with MSVC. -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.16) project(cppwinrt LANGUAGES CXX) @@ -11,7 +11,10 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CPPWINRT_BUILD_VERSION "2.3.4.5" CACHE STRING "The version string used for cppwinrt.") -add_compile_definitions(CPPWINRT_VERSION_STRING="${CPPWINRT_BUILD_VERSION}") +if(CPPWINRT_BUILD_VERSION STREQUAL "2.3.4.5" OR CPPWINRT_BUILD_VERSION STREQUAL "0.0.0.0") + message(WARNING "CPPWINRT_BUILD_VERSION has been set to a dummy version string. Do not use in production!") +endif() +message(STATUS "Using version string: ${CPPWINRT_BUILD_VERSION}") # WinMD uses CreateFile2 which requires Windows 8. add_compile_definitions(_WIN32_WINNT=0x0602) @@ -24,6 +27,7 @@ set(PREBUILD_SRCS prebuild/pch.h ) add_executable(prebuild ${PREBUILD_SRCS}) +target_compile_definitions(prebuild PRIVATE CPPWINRT_VERSION_STRING="${CPPWINRT_BUILD_VERSION}") target_include_directories(prebuild PRIVATE cppwinrt/) @@ -90,9 +94,12 @@ set(CPPWINRT_RESOURCES ) add_executable(cppwinrt ${CPPWINRT_SRCS} ${CPPWINRT_RESOURCES} ${CPPWINRT_HEADERS}) +target_compile_definitions(cppwinrt PRIVATE CPPWINRT_VERSION_STRING="${CPPWINRT_BUILD_VERSION}") target_include_directories(cppwinrt PRIVATE ${PROJECT_BINARY_DIR}) target_link_libraries(cppwinrt shlwapi) +install(TARGETS cppwinrt) + # HACK: Handle the xmllite import lib. # mingw-w64 before commit 5ac1a2c is missing the import lib for xmllite. This @@ -164,4 +171,6 @@ target_include_directories(cppwinrt PRIVATE "${winmd_SOURCE_DIR}") include(CTest) -add_subdirectory(test) +if(BUILD_TESTING) + add_subdirectory(test) +endif() From 37bd17f2a8d004a94084ea47c70e2f9041672236 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 22 Nov 2022 01:57:55 +0800 Subject: [PATCH 149/305] Fix null pointer dereference in weak_ref::get() (#1232) --- .github/workflows/ci.yml | 13 ++++++++++++- strings/base_weak_ref.h | 7 +++++-- test/CMakeLists.txt | 7 +++++++ test/catch.hpp | 17 +++++++---------- test/test_cpp20/CMakeLists.txt | 7 +++++++ 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 310f7d1a9..6d82c6d1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -278,6 +278,7 @@ jobs: strategy: matrix: arch: [i686, x86_64] + config: [Debug, Release] runs-on: windows-latest steps: - uses: actions/checkout@v3 @@ -290,12 +291,21 @@ jobs: rm llvm-mingw.zip if (!(Test-Path "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin\clang++.exe")) { return 1 } Add-Content $env:GITHUB_PATH "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin" + # for the ASAN runtime DLL: + Add-Content $env:GITHUB_PATH "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\${{ matrix.arch }}-w64-mingw32\bin" - name: Build cppwinrt run: | mkdir build cd build - cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DDOWNLOAD_WINDOWSNUMERICS=TRUE + if ("${{ matrix.config }}" -eq "Debug") { + $sanitizers = "TRUE" + } else { + $sanitizers = "FALSE" + } + cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` + -DDOWNLOAD_WINDOWSNUMERICS=TRUE ` + -DENABLE_TEST_SANITIZERS=$sanitizers cmake --build . -j2 --target cppwinrt - name: Upload cppwinrt.exe @@ -318,6 +328,7 @@ jobs: - name: Run tests run: | cd build + $env:UBSAN_OPTIONS = "print_stacktrace=1" ctest --verbose build-msvc-natvis: diff --git a/strings/base_weak_ref.h b/strings/base_weak_ref.h index c98eb93a7..bc480ec2d 100644 --- a/strings/base_weak_ref.h +++ b/strings/base_weak_ref.h @@ -23,8 +23,11 @@ WINRT_EXPORT namespace winrt { impl::com_ref> temp; m_ref->Resolve(guid_of(), put_abi(temp)); - void* result = get_self(temp); - detach_abi(temp); + void* result = nullptr; + if (temp) { + result = get_self(temp); + detach_abi(temp); + } return impl::com_ref{ result, take_ownership_from_abi }; } else diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0c3c4de61..495b3b508 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -65,6 +65,13 @@ add_custom_target(build-cppwinrt-projection ) +set(ENABLE_TEST_SANITIZERS FALSE CACHE BOOL "Enable ASan and UBSan for the tests.") +if(ENABLE_TEST_SANITIZERS) + # Disable the 'vptr' check because it seems to produce false-positives when using COM classes. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,address -fno-sanitize=vptr") +endif() + + add_subdirectory(test) add_subdirectory(test_cpp20) add_subdirectory(test_win7) diff --git a/test/catch.hpp b/test/catch.hpp index d2a12427b..e949ee88c 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -10807,7 +10807,7 @@ namespace Catch { { static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, }; - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) { for (auto const& def : signalDefs) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { reportFatal(def.name); @@ -10821,7 +10821,7 @@ namespace Catch { // Since we do not support multiple instantiations, we put these // into global variables and rely on cleaning them up in outlined // constructors/destructors - static PVOID exceptionHandlerHandle = nullptr; + static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr; // For MSVC, we reserve part of the stack memory for handling // memory overflow structured exception. @@ -10841,18 +10841,15 @@ namespace Catch { FatalConditionHandler::~FatalConditionHandler() = default; void FatalConditionHandler::engage_platform() { - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - if (!exceptionHandlerHandle) { - CATCH_RUNTIME_ERROR("Could not register vectored exception handler"); - } + // Register as a the top level exception filter. + previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter); } void FatalConditionHandler::disengage_platform() { - if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) { - CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler"); + if (SetUnhandledExceptionFilter(reinterpret_cast(previousTopLevelExceptionFilter)) != topLevelExceptionFilter) { + CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter"); } - exceptionHandlerHandle = nullptr; + previousTopLevelExceptionFilter = nullptr; } } // end namespace Catch diff --git a/test/test_cpp20/CMakeLists.txt b/test/test_cpp20/CMakeLists.txt index 66cfffcee..8b787b696 100644 --- a/test/test_cpp20/CMakeLists.txt +++ b/test/test_cpp20/CMakeLists.txt @@ -3,6 +3,13 @@ set(CMAKE_CXX_STANDARD 20) # are experimental in libc++ as of Clang 15. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") +if(ENABLE_TEST_SANITIZERS) + # As of LLVM 15, custom_error.cpp doesn't build with ASAN due to: + # error: cannot make section .ASAN$GL associative with sectionless symbol _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4nposE + set_source_files_properties(custom_error.cpp PROPERTIES COMPILE_OPTIONS "-fno-sanitize=address") + set_source_files_properties(custom_error.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS true) +endif() + file(GLOB TEST_SRCS LIST_DIRECTORIES false CONFIGURE_DEPENDS From 530d383ddf3e5ce63665ff294b701850d6692569 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 22 Nov 2022 01:59:13 +0800 Subject: [PATCH 150/305] Partial GCC compatibility improvements (#1234) --- cppwinrt/pch.h | 1 + cppwinrt/text_writer.h | 1 + strings/base_chrono.h | 2 +- strings/base_includes.h | 9 ++++++++- strings/base_string_operators.h | 4 ++-- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cppwinrt/pch.h b/cppwinrt/pch.h index 335324767..e6a31443e 100644 --- a/cppwinrt/pch.h +++ b/cppwinrt/pch.h @@ -1,5 +1,6 @@ #pragma once +#include #include "cmd_reader.h" #include #include "task_group.h" diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index 50e6e6b15..3e210db83 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -6,6 +6,7 @@ #include #include #include +#include namespace cppwinrt { diff --git a/strings/base_chrono.h b/strings/base_chrono.h index e8e5a1ee4..151246d46 100644 --- a/strings/base_chrono.h +++ b/strings/base_chrono.h @@ -47,7 +47,7 @@ WINRT_EXPORT namespace winrt static time_point from_time_t(time_t time) noexcept { - return from_sys(std::chrono::system_clock::from_time_t(time)); + return std::chrono::time_point_cast(from_sys(std::chrono::system_clock::from_time_t(time))); } static file_time to_file_time(time_point const& time) noexcept diff --git a/strings/base_includes.h b/strings/base_includes.h index 10518a705..54edca841 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,10 @@ #include #include +#if __has_include() +#include +#endif + #if __has_include() #define WINRT_IMPL_NUMERICS #include @@ -50,7 +55,7 @@ namespace winrt::impl using suspend_never = std::suspend_never; } -#else +#elif __has_include() #include @@ -63,4 +68,6 @@ namespace winrt::impl using suspend_never = std::experimental::suspend_never; } +#else +#error C++/WinRT requires coroutine support, which is currently missing. Try enabling C++20 in your compiler. #endif diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index f9701aa4b..b00150f92 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -55,9 +55,9 @@ WINRT_EXPORT namespace winrt return left < std::wstring_view(right); } - bool operator<(hstring const& left, nullptr_t) = delete; + bool operator<(hstring const& left, std::nullptr_t) = delete; - bool operator<(nullptr_t, hstring const& right) = delete; + bool operator<(std::nullptr_t, hstring const& right) = delete; inline bool operator!=(hstring const& left, hstring const& right) noexcept { return !(left == right); } inline bool operator>(hstring const& left, hstring const& right) noexcept { return right < left; } inline bool operator<=(hstring const& left, hstring const& right) noexcept { return !(right < left); } From 80236cdf55a65cb67cecba4251e3c643ffb2f2b1 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Thu, 24 Nov 2022 10:10:21 +0800 Subject: [PATCH 151/305] Fix llvm-mingw tests with LLVM trunk (#1235) --- test/CMakeLists.txt | 2 +- test/test_cpp20/format.cpp | 3 +++ test/test_cpp20/ranges.cpp | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 495b3b508..19ce748a7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,7 +30,7 @@ function(TestHasWindowsnumerics OUTPUT_VARNAME) include(CheckCXXSourceCompiles) check_cxx_source_compiles(" #define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ namespace winrt::Windows::Foundation::Numerics #define _WINDOWS_NUMERICS_END_NAMESPACE_ #include int main() {} diff --git a/test/test_cpp20/format.cpp b/test/test_cpp20/format.cpp index 69da0d0c1..0c40a4113 100644 --- a/test/test_cpp20/format.cpp +++ b/test/test_cpp20/format.cpp @@ -1,4 +1,6 @@ #include "pch.h" + +#ifdef __cpp_lib_format #include struct stringable : winrt::implements @@ -37,3 +39,4 @@ TEST_CASE("format") } #endif } +#endif diff --git a/test/test_cpp20/ranges.cpp b/test/test_cpp20/ranges.cpp index 9bf88a579..9df542696 100644 --- a/test/test_cpp20/ranges.cpp +++ b/test/test_cpp20/ranges.cpp @@ -1,4 +1,6 @@ #include "pch.h" + +#ifdef __cpp_lib_ranges #include #include @@ -46,3 +48,4 @@ TEST_CASE("ranges") REQUIRE((result == std::vector{ 2, 4, 6 })); } } +#endif From da5579c352e60f25bd9259eec47d1dc1c04aecbb Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Mon, 28 Nov 2022 23:06:56 +0800 Subject: [PATCH 152/305] Support Linux cross-compilation with mingw-w64 (#1238) --- .github/workflows/ci.yml | 49 +++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 35 ++++++++++++++++---------- cppwinrt/main.cpp | 14 ++++++++--- cross-mingw-toolchain.cmake | 42 +++++++++++++++++++++++++++++++ prebuild/CMakeLists.txt | 23 +++++++++++++++++ 5 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 cross-mingw-toolchain.cmake create mode 100644 prebuild/CMakeLists.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d82c6d1f..70a05d307 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -331,6 +331,55 @@ jobs: $env:UBSAN_OPTIONS = "print_stacktrace=1" ctest --verbose + build-linux-cross-cppwinrt: + name: 'cross: Cross-build from Linux' + strategy: + matrix: + arch: [i686, x86_64] + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + + - name: Install cross compiler + run: | + arch=${{ matrix.arch }} + sudo apt-get install g++-mingw-w64-${arch/_/-} + sudo update-alternatives --set "${{ matrix.arch }}-w64-mingw32-gcc" "/usr/bin/${{ matrix.arch }}-w64-mingw32-gcc-posix" + sudo update-alternatives --set "${{ matrix.arch }}-w64-mingw32-g++" "/usr/bin/${{ matrix.arch }}-w64-mingw32-g++-posix" + + - name: Cross-build cppwinrt + run: | + cmake -S . -B build/cross_x64/ --toolchain cross-mingw-toolchain.cmake \ + -DCMAKE_SYSTEM_PROCESSOR=${{ matrix.arch }} \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_CXX_FLAGS="-static" \ + -DCMAKE_INSTALL_PREFIX=$PWD/install/ + cmake --build build/cross_x64/ --target install -j2 + + - name: Upload cppwinrt.exe + uses: actions/upload-artifact@v3 + with: + name: cross-build-${{ matrix.arch }}-bin + path: install/bin/cppwinrt.exe + + test-linux-cross-cppwinrt: + name: 'cross: Test run on Windows' + needs: build-linux-cross-cppwinrt + strategy: + matrix: + arch: [i686, x86_64] + runs-on: windows-latest + steps: + - name: Fetch cppwinrt executable + uses: actions/download-artifact@v3 + with: + name: cross-build-${{ matrix.arch }}-bin + path: ./ + + - name: Run cppwinrt to build projection + run: | + .\cppwinrt.exe -in local -out .\ -verbose + build-msvc-natvis: name: 'Build natvis' strategy: diff --git a/CMakeLists.txt b/CMakeLists.txt index bcc3ca583..b983c4587 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,13 +22,19 @@ add_compile_definitions(_WIN32_WINNT=0x0602) # === prebuild: Generator tool for strings.cpp, strings.h, version.rc === -set(PREBUILD_SRCS - prebuild/main.cpp - prebuild/pch.h -) -add_executable(prebuild ${PREBUILD_SRCS}) -target_compile_definitions(prebuild PRIVATE CPPWINRT_VERSION_STRING="${CPPWINRT_BUILD_VERSION}") -target_include_directories(prebuild PRIVATE cppwinrt/) +if(CMAKE_CROSSCOMPILING) + include(ExternalProject) + ExternalProject_Add(cppwinrt-prebuild + SOURCE_DIR "${PROJECT_SOURCE_DIR}/prebuild" + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX= "-DCPPWINRT_BUILD_VERSION=${CPPWINRT_BUILD_VERSION}" + ) + ExternalProject_Get_Property(cppwinrt-prebuild INSTALL_DIR) + set(PREBUILD_TOOL "${INSTALL_DIR}/bin/cppwinrt-prebuild") + unset(INSTALL_DIR) +else() + add_subdirectory(prebuild) + set(PREBUILD_TOOL cppwinrt-prebuild) +endif() # === Step to create autogenerated files === @@ -42,9 +48,9 @@ add_custom_command( OUTPUT ${PROJECT_BINARY_DIR}/strings.cpp ${PROJECT_BINARY_DIR}/version.rc - COMMAND "${PROJECT_BINARY_DIR}/prebuild.exe" ARGS "${PROJECT_SOURCE_DIR}/strings" "${PROJECT_BINARY_DIR}" + COMMAND "${PREBUILD_TOOL}" ARGS "${PROJECT_SOURCE_DIR}/strings" "${PROJECT_BINARY_DIR}" DEPENDS - prebuild + cppwinrt-prebuild ${PREBUILD_STRINGS_FILES} VERBATIM ) @@ -137,10 +143,11 @@ int main() {} else() set(XMLLITE_DEF_FILE xmllite) endif() + include(CMakeFindBinUtils) add_custom_command( OUTPUT "${PROJECT_BINARY_DIR}/libxmllite.a" - COMMAND dlltool -k -d "${PROJECT_SOURCE_DIR}/mingw-support/${XMLLITE_DEF_FILE}.def" -l "${PROJECT_BINARY_DIR}/libxmllite.a" + COMMAND "${CMAKE_DLLTOOL}" -k -d "${PROJECT_SOURCE_DIR}/mingw-support/${XMLLITE_DEF_FILE}.def" -l "${PROJECT_BINARY_DIR}/libxmllite.a" DEPENDS "${PROJECT_SOURCE_DIR}/mingw-support/${XMLLITE_DEF_FILE}.def" VERBATIM ) @@ -170,7 +177,9 @@ set(winmd_SOURCE_DIR "${SOURCE_DIR}") target_include_directories(cppwinrt PRIVATE "${winmd_SOURCE_DIR}") -include(CTest) -if(BUILD_TESTING) - add_subdirectory(test) +if(NOT CMAKE_CROSSCOMPILING) + include(CTest) + if(BUILD_TESTING) + add_subdirectory(test) + endif() endif() diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 6f10f8e79..5834d868f 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -268,9 +268,17 @@ Where is one or more of: if (settings.verbose) { - char* path = nullptr; - _get_pgmptr(&path); - w.write(" tool: %\n", path); + { + char* path = argv[0]; + char path_buf[32768]; + DWORD path_size = GetModuleFileNameA(nullptr, path_buf, sizeof(path_buf)); + if (path_size) + { + path_buf[sizeof(path_buf) - 1] = 0; + path = path_buf; + } + w.write(" tool: %\n", path); + } w.write(" ver: %\n", CPPWINRT_VERSION_STRING); for (auto&& file : settings.input) diff --git a/cross-mingw-toolchain.cmake b/cross-mingw-toolchain.cmake new file mode 100644 index 000000000..d58bb278d --- /dev/null +++ b/cross-mingw-toolchain.cmake @@ -0,0 +1,42 @@ +# This is a cmake-toolchain(5) file that can be used to cross-build +# cppwinrt.exe fron Linux or other operating systems using a mingw-w64 cross +# toolchain. This should work with both GCC-based and llvm-mingw toolchains. +# +# Example usage with external toolchain: +# +# $ cmake -S . -B build/cross_x64/ \ +# --toolchain cross-mingw-toolchain.cmake \ +# -DMINGW_BIN_PATH=/opt/llvm-mingw/bin \ +# -DCMAKE_BUILD_TYPE=RelWithDebInfo \ +# -DCMAKE_INSTALL_PREFIX=$PWD/install/ +# +# Example usage with toolchain installed system-wide: +# +# $ cmake -S . -B build/cross_i686/ \ +# --toolchain cross-mingw-toolchain.cmake \ +# -DCMAKE_SYSTEM_PROCESSOR=i686 \ +# -DCMAKE_BUILD_TYPE=RelWithDebInfo \ +# -DCMAKE_INSTALL_PREFIX=$PWD/install/ + + +set(CMAKE_SYSTEM_NAME Windows) +if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR) + set(CMAKE_SYSTEM_PROCESSOR x86_64) +endif() + +set(TOOLCHAIN_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32) + +if(DEFINED MINGW_BIN_PATH) + set(TOOLCHAIN_PREFIX "${MINGW_BIN_PATH}/${TOOLCHAIN_PREFIX}") +endif() + +set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}-gcc") +set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}-g++") +set(CMAKE_RC_COMPILER "${TOOLCHAIN_PREFIX}-windres") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +unset(TOOLCHAIN_PREFIX) diff --git a/prebuild/CMakeLists.txt b/prebuild/CMakeLists.txt new file mode 100644 index 000000000..da2162d44 --- /dev/null +++ b/prebuild/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.16) + +project(cppwinrt-prebuild LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +if(NOT DEFINED CPPWINRT_BUILD_VERSION) + message(FATAL_ERROR "CPPWINRT_BUILD_VERSION has not been defined. You should build the top-level project instead.") +endif() + + +set(PREBUILD_SRCS + main.cpp + pch.h +) +add_executable(cppwinrt-prebuild ${PREBUILD_SRCS}) +target_compile_definitions(cppwinrt-prebuild PRIVATE CPPWINRT_VERSION_STRING="${CPPWINRT_BUILD_VERSION}") +target_include_directories(cppwinrt-prebuild PRIVATE ../cppwinrt/) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + install(TARGETS cppwinrt-prebuild) +endif() From d86323ddadc8a72a8d5f61ce35ca7696b0d1a619 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Mon, 5 Dec 2022 22:28:56 +0800 Subject: [PATCH 153/305] CI: Refactor LLVM setup steps and use cache (#1242) --- .github/actions/setup-llvm-mingw/action.yml | 46 ++++++++++++++++++ .github/actions/setup-llvm-msvc/action.yml | 48 +++++++++++++++++++ .github/workflows/ci.yml | 53 +++++---------------- 3 files changed, 105 insertions(+), 42 deletions(-) create mode 100644 .github/actions/setup-llvm-mingw/action.yml create mode 100644 .github/actions/setup-llvm-msvc/action.yml diff --git a/.github/actions/setup-llvm-mingw/action.yml b/.github/actions/setup-llvm-mingw/action.yml new file mode 100644 index 000000000..04942cce4 --- /dev/null +++ b/.github/actions/setup-llvm-mingw/action.yml @@ -0,0 +1,46 @@ +name: 'Set up llvm-mingw toolchain' +description: 'Set up llvm-mingw toolchain' +inputs: + llvm-mingw-version: + description: 'llvm-mingw version' + required: true + default: '20220906' + host-arch: + description: 'llvm-mingw toolchain host architecture (e.g. i686, x86_64)' + required: true + default: 'x86_64' +outputs: + llvm-path: + description: "The path in which llvm-mingw is installed to" + value: ${{ steps.setup-llvm.outputs.llvm-path }} +runs: + using: "composite" + steps: + - name: Cache llvm-mingw + id: cache-llvm + uses: actions/cache@v3 + with: + path: .llvm-mingw + key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} + + - name: Install llvm-mingw ${{ inputs.llvm-mingw-version }} (${{ inputs.host-arch }}) + if: steps.cache-llvm.outputs.cache-hit != 'true' + shell: pwsh + run: | + $llvm_mingw_version = "${{ inputs.llvm-mingw-version }}" + $llvm_arch = "${{ inputs.host-arch }}" + Invoke-WebRequest "https://github.com/mstorsjo/llvm-mingw/releases/download/${llvm_mingw_version}/llvm-mingw-${llvm_mingw_version}-ucrt-${llvm_arch}.zip" -OutFile llvm-mingw.zip + 7z x llvm-mingw.zip -o"$pwd\.llvm-mingw" + rm llvm-mingw.zip + + - name: Set up llvm-mingw + id: setup-llvm + shell: pwsh + run: | + $llvm_mingw_version = "${{ inputs.llvm-mingw-version }}" + $llvm_arch = "${{ inputs.host-arch }}" + if (!(Test-Path "$pwd\.llvm-mingw\llvm-mingw-${llvm_mingw_version}-ucrt-${llvm_arch}\bin\clang++.exe")) { return 1 } + Add-Content $env:GITHUB_OUTPUT "llvm-path=$pwd\.llvm-mingw\llvm-mingw-${llvm_mingw_version}-ucrt-${llvm_arch}" + Add-Content $env:GITHUB_PATH "$pwd\.llvm-mingw\llvm-mingw-${llvm_mingw_version}-ucrt-${llvm_arch}\bin" + # for the ASAN runtime DLL: + Add-Content $env:GITHUB_PATH "$pwd\.llvm-mingw\llvm-mingw-${llvm_mingw_version}-ucrt-${llvm_arch}\${llvm_arch}-w64-mingw32\bin" diff --git a/.github/actions/setup-llvm-msvc/action.yml b/.github/actions/setup-llvm-msvc/action.yml new file mode 100644 index 000000000..5017f7dc9 --- /dev/null +++ b/.github/actions/setup-llvm-msvc/action.yml @@ -0,0 +1,48 @@ +name: 'Set up LLVM for MSVC' +description: 'Set up upstream LLVM for targeting MSVC ABI' +inputs: + llvm-version: + description: 'LLVM version' + required: true + default: '15.0.5' +outputs: + llvm-path: + description: "The path in which LLVM is installed to" + value: ${{ steps.setup-llvm.outputs.llvm-path }} +runs: + using: "composite" + steps: + - name: Cache LLVM and tools + id: cache-llvm + uses: actions/cache@v3 + with: + path: | + .LLVM + .llvm-utils + key: llvm-msvc-${{ runner.os }}-${{ inputs.llvm-version }} + + - name: Install LLVM ${{ inputs.llvm-version }} + if: steps.cache-llvm.outputs.cache-hit != 'true' + shell: pwsh + run: | + Invoke-WebRequest "https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ inputs.llvm-version }}/LLVM-${{ inputs.llvm-version }}-win64.exe" -OutFile LLVM-installer.exe + .\LLVM-installer.exe /S "/D=$pwd\.LLVM" | Out-Null + rm LLVM-installer.exe + + # Not using the LLVM tools that comes with MSVC. + - name: Download LLVM build tools for msbuild + if: steps.cache-llvm.outputs.cache-hit != 'true' + shell: pwsh + run: | + Invoke-WebRequest "https://github.com/zufuliu/llvm-utils/releases/download/v22.09/LLVM_VS2017.zip" -OutFile LLVM_VS2017.zip + 7z x -y "LLVM_VS2017.zip" -o"$pwd\.llvm-utils\" + rm LLVM_VS2017.zip + + - name: Set up LLVM build tools for msbuild + id: setup-llvm + shell: pwsh + run: | + if (!(Test-Path "$pwd\.LLVM\bin\clang-cl.exe")) { exit 1 } + Add-Content $env:GITHUB_PATH "$pwd\.LLVM\bin" + Add-Content $env:GITHUB_OUTPUT "llvm-path=$pwd\.LLVM" + cmd /c ".llvm-utils\LLVM_VS2017\install.bat" 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70a05d307..36de522bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,22 +24,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Install LLVM 15 + - id: setup-llvm + name: Set up LLVM (MSVC) + uses: ./.github/actions/setup-llvm-msvc if: matrix.compiler == 'clang-cl' - run: | - Invoke-WebRequest "https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.2/LLVM-15.0.2-win64.exe" -OutFile LLVM-installer.exe - .\LLVM-installer.exe /S "/D=$pwd\LLVM" | Out-Null - rm LLVM-installer.exe - if (!(Test-Path "$pwd\LLVM\bin\clang-cl.exe")) { exit 1 } - Add-Content $env:GITHUB_PATH "$pwd\LLVM\bin" - - - name: Set up LLVM build tools for msbuild - if: matrix.compiler == 'clang-cl' - # Not using the LLVM tools that comes with MSVC. - run: | - Invoke-WebRequest "https://github.com/zufuliu/llvm-utils/releases/download/v22.09/LLVM_VS2017.zip" -OutFile LLVM_VS2017.zip - 7z x -y "LLVM_VS2017.zip" | Out-Null - cmd /c "LLVM_VS2017\install.bat" 1 - name: Download nuget run: | @@ -60,7 +48,7 @@ jobs: $target_version = "1.2.3.4" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=$pwd\LLVM" + $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -120,22 +108,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Install LLVM 15 + - id: setup-llvm + name: Set up LLVM (MSVC) + uses: ./.github/actions/setup-llvm-msvc if: matrix.compiler == 'clang-cl' - run: | - Invoke-WebRequest "https://github.com/llvm/llvm-project/releases/download/llvmorg-15.0.2/LLVM-15.0.2-win64.exe" -OutFile LLVM-installer.exe - .\LLVM-installer.exe /S "/D=$pwd\LLVM" | Out-Null - rm LLVM-installer.exe - if (!(Test-Path "$pwd\LLVM\bin\clang-cl.exe")) { exit 1 } - Add-Content $env:GITHUB_PATH "$pwd\LLVM\bin" - - - name: Set up LLVM build tools for msbuild - if: matrix.compiler == 'clang-cl' - run: | - # Not using the LLVM tools that comes with MSVC. - Invoke-WebRequest "https://github.com/zufuliu/llvm-utils/releases/download/v22.09/LLVM_VS2017.zip" -OutFile LLVM_VS2017.zip - 7z x -y "LLVM_VS2017.zip" | Out-Null - cmd /c "LLVM_VS2017\install.bat" 1 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' @@ -170,7 +146,7 @@ jobs: $target_version = "1.2.3.4" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=$pwd\LLVM" + $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -283,16 +259,9 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Install llvm-mingw toolchain - run: | - $llvm_mingw_version = "20220906" - Invoke-WebRequest "https://github.com/mstorsjo/llvm-mingw/releases/download/${llvm_mingw_version}/llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}.zip" -OutFile llvm-mingw.zip - 7z x llvm-mingw.zip - rm llvm-mingw.zip - if (!(Test-Path "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin\clang++.exe")) { return 1 } - Add-Content $env:GITHUB_PATH "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin" - # for the ASAN runtime DLL: - Add-Content $env:GITHUB_PATH "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\${{ matrix.arch }}-w64-mingw32\bin" + - id: setup-llvm + name: Set up llvm-mingw + uses: ./.github/actions/setup-llvm-mingw - name: Build cppwinrt run: | From 4a5acf64457c82dbf1ce6f2e81bc0bdc1adbe51e Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Wed, 7 Dec 2022 01:13:30 +0800 Subject: [PATCH 154/305] Add Linux native build (#1239) --- .github/actions/setup-llvm-mingw/action.yml | 43 +++++++- .github/workflows/ci.yml | 105 +++++++++++++++++++- CMakeLists.txt | 68 +++++++------ cppwinrt/cmd_reader.h | 24 ++++- cppwinrt/main.cpp | 14 ++- cppwinrt/text_writer.h | 9 ++ prebuild/main.cpp | 5 +- test/CMakeLists.txt | 50 +++++++--- test/old_tests/UnitTests/Hash.cpp | 2 +- test/old_tests/UnitTests/pch.h | 52 +++++----- test/test/guid_include.cpp | 2 +- test/test_fast_fwd/FastForwarderTests.cpp | 6 +- 12 files changed, 294 insertions(+), 86 deletions(-) diff --git a/.github/actions/setup-llvm-mingw/action.yml b/.github/actions/setup-llvm-mingw/action.yml index 04942cce4..9926bbe93 100644 --- a/.github/actions/setup-llvm-mingw/action.yml +++ b/.github/actions/setup-llvm-mingw/action.yml @@ -12,19 +12,20 @@ inputs: outputs: llvm-path: description: "The path in which llvm-mingw is installed to" - value: ${{ steps.setup-llvm.outputs.llvm-path }} + value: ${{ ((runner.os == 'Windows') && steps.setup-llvm.outputs.llvm-path) || steps.setup-llvm-linux.outputs.llvm-path }} runs: using: "composite" steps: - - name: Cache llvm-mingw + - name: Cache llvm-mingw (Windows) id: cache-llvm + if: runner.os == 'Windows' uses: actions/cache@v3 with: path: .llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} - - name: Install llvm-mingw ${{ inputs.llvm-mingw-version }} (${{ inputs.host-arch }}) - if: steps.cache-llvm.outputs.cache-hit != 'true' + - name: Install llvm-mingw ${{ inputs.llvm-mingw-version }} (Windows ${{ inputs.host-arch }}) + if: runner.os == 'Windows' && steps.cache-llvm.outputs.cache-hit != 'true' shell: pwsh run: | $llvm_mingw_version = "${{ inputs.llvm-mingw-version }}" @@ -33,8 +34,9 @@ runs: 7z x llvm-mingw.zip -o"$pwd\.llvm-mingw" rm llvm-mingw.zip - - name: Set up llvm-mingw + - name: Set up llvm-mingw (Windows) id: setup-llvm + if: runner.os == 'Windows' shell: pwsh run: | $llvm_mingw_version = "${{ inputs.llvm-mingw-version }}" @@ -44,3 +46,34 @@ runs: Add-Content $env:GITHUB_PATH "$pwd\.llvm-mingw\llvm-mingw-${llvm_mingw_version}-ucrt-${llvm_arch}\bin" # for the ASAN runtime DLL: Add-Content $env:GITHUB_PATH "$pwd\.llvm-mingw\llvm-mingw-${llvm_mingw_version}-ucrt-${llvm_arch}\${llvm_arch}-w64-mingw32\bin" + + - name: Cache llvm-mingw (Linux) + id: cache-llvm-linux + if: runner.os == 'Linux' + uses: actions/cache@v3 + with: + path: /opt/llvm-mingw + key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} + + - name: Install llvm-mingw ${{ inputs.llvm-mingw-version }} (Linux ${{ inputs.host-arch }}) + if: runner.os == 'Linux' && steps.cache-llvm-linux.outputs.cache-hit != 'true' + shell: bash + run: | + llvm_mingw_version="${{ inputs.llvm-mingw-version }}" + llvm_arch="${{ inputs.host-arch }}" + mkdir -p /opt/llvm-mingw + cd /opt/llvm-mingw + curl -L https://github.com/mstorsjo/llvm-mingw/releases/download/20220906/llvm-mingw-${llvm_mingw_version}-ucrt-ubuntu-18.04-${llvm_arch}.tar.xz | tar xJ --strip-components=1 + + - name: Set up llvm-mingw (Linux) + id: setup-llvm-linux + if: runner.os == 'Linux' + shell: bash + run: | + cd /opt/llvm-mingw + if [ ! -x bin/clang++ ]; then + echo "$PWD/bin/clang++ not found or not executable!" + exit 1 + fi + echo "llvm-path=$PWD/llvm-mingw" >> $GITHUB_OUTPUT + echo "$PWD/bin" >> $GITHUB_PATH diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36de522bf..dca6c31bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,6 +252,7 @@ jobs: test-llvm-mingw-cppwinrt: name: 'llvm-mingw: Build and test' strategy: + fail-fast: false matrix: arch: [i686, x86_64] config: [Debug, Release] @@ -262,6 +263,8 @@ jobs: - id: setup-llvm name: Set up llvm-mingw uses: ./.github/actions/setup-llvm-mingw + with: + host-arch: ${{ matrix.arch }} - name: Build cppwinrt run: | @@ -335,19 +338,117 @@ jobs: name: 'cross: Test run on Windows' needs: build-linux-cross-cppwinrt strategy: + fail-fast: false matrix: arch: [i686, x86_64] runs-on: windows-latest steps: + - uses: actions/checkout@v3 + - name: Fetch cppwinrt executable uses: actions/download-artifact@v3 with: name: cross-build-${{ matrix.arch }}-bin - path: ./ + path: ./.test - name: Run cppwinrt to build projection run: | - .\cppwinrt.exe -in local -out .\ -verbose + .\.test\cppwinrt.exe -in local -out .\.test\out -verbose + + - id: setup-llvm + name: Set up llvm-mingw + uses: ./.github/actions/setup-llvm-mingw + with: + host-arch: ${{ matrix.arch }} + + - name: Build cppwinrt tests + run: | + mkdir build + cd build + cmake ../test -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug ` + -DCPPWINRT_PROJECTION_INCLUDE_DIR="../.test/out" ` + -DDOWNLOAD_WINDOWSNUMERICS=TRUE + cmake --build . -j2 + + - name: Run tests + run: | + cd build + ctest --verbose + + build-linux-native-cppwinrt: + name: 'linux: GCC native build + llvm-mingw cross-build tests' + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + + - name: Build cppwinrt + run: | + cmake -S . -B build/native/ \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_PREFIX=$PWD/install/ + cmake --build build/native/ --target install -j2 + + - name: Test run (cppwinrt -?) + run: | + install/bin/cppwinrt -? + + - name: Test run (build projection using Windows.winmd) + run: | + curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/metadata/default/Windows.winmd + install/bin/cppwinrt -in Windows.winmd -out /tmp/cppwinrt -verbose + + - id: setup-llvm + name: Set up llvm-mingw + uses: ./.github/actions/setup-llvm-mingw + + - name: Cross-build tests using projection + run: | + cmake -S test -B build/cross-tests --toolchain "$PWD/cross-mingw-toolchain.cmake" \ + -DCMAKE_SYSTEM_PROCESSOR=x86_64 \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_CXX_FLAGS="-static" \ + -DCPPWINRT_PROJECTION_INCLUDE_DIR=/tmp/cppwinrt \ + -DDOWNLOAD_WINDOWSNUMERICS=TRUE + cmake --build build/cross-tests -j2 + + - name: Upload built tests + uses: actions/upload-artifact@v3 + with: + name: linux-native-cppwinrt-cross-build-tests-x86_64-bin + path: build/cross-tests/*.exe + + test-linux-native-cppwinrt-cross-tests: + name: 'linux: Run llvm-mingw cross-build tests' + needs: build-linux-native-cppwinrt + strategy: + matrix: + arch: [x86_64] + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Fetch test executables + uses: actions/download-artifact@v3 + with: + name: linux-native-cppwinrt-cross-build-tests-${{ matrix.arch }}-bin + path: ./ + + - name: Run tests + run: | + $test_exes = ls *.exe -Name + $has_failed_tests = 0 + foreach ($test_exe in $test_exes) { + echo "::group::Run '$test_exe'" + & .\$test_exe + echo "::endgroup::" + if ($LastExitCode -ne 0) { + echo "::error::Test '$test_exe' failed!" + $has_failed_tests = 1 + } + } + if ($has_failed_tests -ne 0) { + exit 1 + } build-msvc-natvis: name: 'Build natvis' diff --git a/CMakeLists.txt b/CMakeLists.txt index b983c4587..e8ef5fa4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ # This CMake build file is intended for use with the llvm-mingw toolchain: # https://github.com/mstorsjo/llvm-mingw # +# It also works for building natively on Linux, or cross-building from Linux +# for running on Windows with a mingw-w64 toolchain. +# # It most probably doesn't work with MSVC. cmake_minimum_required(VERSION 3.16) @@ -16,8 +19,10 @@ if(CPPWINRT_BUILD_VERSION STREQUAL "2.3.4.5" OR CPPWINRT_BUILD_VERSION STREQUAL endif() message(STATUS "Using version string: ${CPPWINRT_BUILD_VERSION}") -# WinMD uses CreateFile2 which requires Windows 8. -add_compile_definitions(_WIN32_WINNT=0x0602) +if(WIN32) + # WinMD uses CreateFile2 which requires Windows 8. + add_compile_definitions(_WIN32_WINNT=0x0602) +endif() # === prebuild: Generator tool for strings.cpp, strings.h, version.rc === @@ -77,32 +82,37 @@ set(CPPWINRT_HEADERS cppwinrt/type_writers.h ) -add_custom_command( - OUTPUT - "${PROJECT_BINARY_DIR}/app.manifest" - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/cppwinrt/app.manifest" "${PROJECT_BINARY_DIR}/app.manifest" - DEPENDS "${PROJECT_SOURCE_DIR}/cppwinrt/app.manifest" - VERBATIM -) -# Do the configure_file dance so that app.manifest.rc don't get modified every -# single time the project is reconfigured and trigger a rebuild. -file(WRITE "${PROJECT_BINARY_DIR}/app.manifest.rc.in" "1 24 \"app.manifest\"\n") -configure_file( - "${PROJECT_BINARY_DIR}/app.manifest.rc.in" - "${PROJECT_BINARY_DIR}/app.manifest.rc" - COPYONLY -) +if(WIN32) + add_custom_command( + OUTPUT + "${PROJECT_BINARY_DIR}/app.manifest" + COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/cppwinrt/app.manifest" "${PROJECT_BINARY_DIR}/app.manifest" + DEPENDS "${PROJECT_SOURCE_DIR}/cppwinrt/app.manifest" + VERBATIM + ) + # Do the configure_file dance so that app.manifest.rc don't get modified every + # single time the project is reconfigured and trigger a rebuild. + file(WRITE "${PROJECT_BINARY_DIR}/app.manifest.rc.in" "1 24 \"app.manifest\"\n") + configure_file( + "${PROJECT_BINARY_DIR}/app.manifest.rc.in" + "${PROJECT_BINARY_DIR}/app.manifest.rc" + COPYONLY + ) -set(CPPWINRT_RESOURCES - "${PROJECT_BINARY_DIR}/app.manifest" - "${PROJECT_BINARY_DIR}/app.manifest.rc" - "${PROJECT_BINARY_DIR}/version.rc" -) + set(CPPWINRT_RESOURCES + "${PROJECT_BINARY_DIR}/app.manifest" + "${PROJECT_BINARY_DIR}/app.manifest.rc" + "${PROJECT_BINARY_DIR}/version.rc" + ) +endif() add_executable(cppwinrt ${CPPWINRT_SRCS} ${CPPWINRT_RESOURCES} ${CPPWINRT_HEADERS}) target_compile_definitions(cppwinrt PRIVATE CPPWINRT_VERSION_STRING="${CPPWINRT_BUILD_VERSION}") target_include_directories(cppwinrt PRIVATE ${PROJECT_BINARY_DIR}) -target_link_libraries(cppwinrt shlwapi) + +if(WIN32) + target_link_libraries(cppwinrt shlwapi) +endif() install(TARGETS cppwinrt) @@ -158,15 +168,17 @@ int main() {} add_dependencies(cppwinrt gen-libxmllite) endif() endif() -target_link_libraries(cppwinrt "${XMLLITE_LIBRARY}") +if(WIN32) + target_link_libraries(cppwinrt "${XMLLITE_LIBRARY}") +endif() # === winmd: External header-only library for reading winmd files === include(ExternalProject) ExternalProject_Add(winmd - URL https://github.com/microsoft/winmd/releases/download/1.0.210629.2/Microsoft.Windows.WinMD.1.0.210629.2.nupkg - URL_HASH SHA256=4c5f29d948f5b3d724d229664c8f8e4823250d3c9f23ad8067b732fc7076d8c7 + GIT_REPOSITORY https://github.com/microsoft/winmd.git + GIT_TAG 0f1eae3bfa63fa2ba3c2912cbfe72a01db94cc5a CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" @@ -174,10 +186,10 @@ ExternalProject_Add(winmd add_dependencies(cppwinrt winmd) ExternalProject_Get_Property(winmd SOURCE_DIR) set(winmd_SOURCE_DIR "${SOURCE_DIR}") -target_include_directories(cppwinrt PRIVATE "${winmd_SOURCE_DIR}") +target_include_directories(cppwinrt PRIVATE "${winmd_SOURCE_DIR}/src") -if(NOT CMAKE_CROSSCOMPILING) +if(WIN32 AND NOT CMAKE_CROSSCOMPILING) include(CTest) if(BUILD_TESTING) add_subdirectory(test) diff --git a/cppwinrt/cmd_reader.h b/cppwinrt/cmd_reader.h index bb5454258..7faf49e4f 100644 --- a/cppwinrt/cmd_reader.h +++ b/cppwinrt/cmd_reader.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -12,12 +13,16 @@ #include #include #include + +#if defined(_WIN32) || defined(_WIN64) #include #include #include +#endif namespace cppwinrt { +#if defined(_WIN32) || defined(_WIN64) struct registry_key { HKEY handle{}; @@ -291,6 +296,7 @@ namespace cppwinrt return result; } +#endif /* defined(_WIN32) || defined(_WIN64) */ [[noreturn]] inline void throw_invalid(std::string const& message) { @@ -440,6 +446,7 @@ namespace cppwinrt } if (path == "local") { +#if defined(_WIN32) || defined(_WIN64) std::array local{}; #ifdef _WIN64 ExpandEnvironmentStringsA("%windir%\\System32\\WinMetadata", local.data(), static_cast(local.size())); @@ -447,6 +454,9 @@ namespace cppwinrt ExpandEnvironmentStringsA("%windir%\\SysNative\\WinMetadata", local.data(), static_cast(local.size())); #endif add_directory(local.data()); +#else /* defined(_WIN32) || defined(_WIN64) */ + throw_invalid("Spec '", path, "' not supported outside of Windows"); +#endif /* defined(_WIN32) || defined(_WIN64) */ continue; } @@ -454,7 +464,11 @@ namespace cppwinrt if (path == "sdk" || path == "sdk+") { +#if defined(_WIN32) || defined(_WIN64) sdk_version = get_sdk_version(); +#else /* defined(_WIN32) || defined(_WIN64) */ + throw_invalid("Spec '", path, "' not supported outside of Windows"); +#endif /* defined(_WIN32) || defined(_WIN64) */ } else { @@ -469,6 +483,7 @@ namespace cppwinrt if (!sdk_version.empty()) { +#if defined(_WIN32) || defined(_WIN64) auto sdk_path = get_sdk_path(); auto xml_path = sdk_path; xml_path /= L"Platforms\\UAP"; @@ -490,6 +505,9 @@ namespace cppwinrt // Not all Extension SDKs include an SDKManifest.xml file; ignore those which do not (e.g. WindowsIoT). add_files_from_xml(files, sdk_version, xml_path, sdk_path, xml_requirement::optional); } +#else /* defined(_WIN32) || defined(_WIN64) */ + throw_invalid("Spec '", path, "' not supported outside of Windows"); +#endif /* defined(_WIN32) || defined(_WIN64) */ continue; } @@ -531,7 +549,11 @@ namespace cppwinrt template void extract_option(std::string_view arg, O const& options, L& last) { - if (arg[0] == '-' || arg[0] == '/') + if (arg[0] == '-' +#if defined(_WIN32) || defined(_WIN64) + || arg[0] == '/' +#endif + ) { arg.remove_prefix(1); last = find(options, arg); diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 5834d868f..16700a863 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -70,10 +70,14 @@ Copyright (c) Microsoft Corporation. All rights reserved. Where is one or more of: path Path to winmd file or recursively scanned folder - local Local ^%WinDir^%\System32\WinMetadata folder +)" +#if defined(_WIN32) || defined(_WIN64) +R"( local Local ^%WinDir^%\System32\WinMetadata folder sdk[+] Current version of Windows SDK [with extensions] 10.0.12345.0[+] Specific version of Windows SDK [with extensions] -)"; +)" +#endif + ; w.write(format, CPPWINRT_VERSION_STRING, bind_each(printOption, options)); } @@ -94,7 +98,7 @@ Where is one or more of: path output_folder = args.value("output", "."); create_directories(output_folder / "winrt/impl"); settings.output_folder = canonical(output_folder).string(); - settings.output_folder += '\\'; + settings.output_folder += std::filesystem::path::preferred_separator; for (auto && include : args.values("include")) { @@ -146,7 +150,7 @@ Where is one or more of: { create_directories(component); settings.component_folder = canonical(component).string(); - settings.component_folder += '\\'; + settings.component_folder += std::filesystem::path::preferred_separator; } } } @@ -270,6 +274,7 @@ Where is one or more of: { { char* path = argv[0]; +#if defined(_WIN32) || defined(_WIN64) char path_buf[32768]; DWORD path_size = GetModuleFileNameA(nullptr, path_buf, sizeof(path_buf)); if (path_size) @@ -277,6 +282,7 @@ Where is one or more of: path_buf[sizeof(path_buf) - 1] = 0; path = path_buf; } +#endif w.write(" tool: %\n", path); } w.write(" ver: %\n", CPPWINRT_VERSION_STRING); diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index 3e210db83..ee723c703 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -128,7 +128,16 @@ namespace cppwinrt void write_printf(char const* format, Args const&... args) { char buffer[128]; +#if defined(_WIN32) || defined(_WIN64) size_t const size = sprintf_s(buffer, format, args...); +#else + size_t size = snprintf(buffer, sizeof(buffer), format, args...); + if (size > sizeof(buffer) - 1) + { + fprintf(stderr, "\n*** WARNING: writer_base::write_printf -- buffer too small\n"); + size = sizeof(buffer) - 1; + } +#endif write(std::string_view{ buffer, size }); } diff --git a/prebuild/main.cpp b/prebuild/main.cpp index 52a750776..3e427d32b 100644 --- a/prebuild/main.cpp +++ b/prebuild/main.cpp @@ -19,9 +19,11 @@ int main(int const argc, char** argv) strings_h.write(R"( #pragma once namespace cppwinrt::strings { +extern "C++" { )"); strings_cpp.write(R"( +#include "strings.h" namespace cppwinrt::strings { )"); @@ -41,7 +43,7 @@ namespace cppwinrt::strings { strings_h.write(R"(extern char const %[%]; )", name.string(), - static_cast(view.size())); + static_cast(view.size() + 1)); strings_cpp.write(R"(extern char const %[] = R"xyz()xyz" )", @@ -66,6 +68,7 @@ namespace cppwinrt::strings { strings_h.write(R"( } +} )"); strings_cpp.write(R"( diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 19ce748a7..6cf1aa3ca 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,11 +1,23 @@ +cmake_minimum_required(VERSION 3.16) + +if(NOT DEFINED PROJECT_NAME) + project(cppwinrt-tests) + set(STANDALONE_TESTING 1) + include(CTest) + if(NOT BUILD_TESTING) + message(NOTICE "BUILD_TESTING is OFF, nothing to do.") + return() + endif() +endif() + # The tests use newer C++ features. set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}") -include_directories("${PROJECT_SOURCE_DIR}/cppwinrt") -include_directories("${CMAKE_CURRENT_BINARY_DIR}/cppwinrt") +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../cppwinrt") function(TestIsX64 OUTPUT_VARNAME) include(CheckCXXSourceCompiles) @@ -51,18 +63,28 @@ if(NOT HAS_WINDOWSNUMERICS AND DOWNLOAD_WINDOWSNUMERICS) endif() -add_custom_command( - OUTPUT - "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt/winrt/base.h" - COMMAND "${PROJECT_BINARY_DIR}/cppwinrt" -input local -output "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt" -verbose - DEPENDS - cppwinrt - VERBATIM -) -add_custom_target(build-cppwinrt-projection - DEPENDS - "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt/winrt/base.h" -) +if(STANDALONE_TESTING) + add_custom_target(build-cppwinrt-projection) + set(CPPWINRT_PROJECTION_INCLUDE_DIR "" CACHE PATH "Include path for the C++/WinRT projection headers") + if(NOT CPPWINRT_PROJECTION_INCLUDE_DIR) + message(FATAL_ERROR "CPPWINRT_PROJECTION_INCLUDE_DIR is not specified.") + endif() +else() + set(CPPWINRT_PROJECTION_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt") + add_custom_command( + OUTPUT + "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt/winrt/base.h" + COMMAND cppwinrt -input local -output "${CPPWINRT_PROJECTION_INCLUDE_DIR}" -verbose + DEPENDS + cppwinrt + VERBATIM + ) + add_custom_target(build-cppwinrt-projection + DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/cppwinrt/winrt/base.h" + ) +endif() +include_directories("${CPPWINRT_PROJECTION_INCLUDE_DIR}") set(ENABLE_TEST_SANITIZERS FALSE CACHE BOOL "Enable ASan and UBSan for the tests.") diff --git a/test/old_tests/UnitTests/Hash.cpp b/test/old_tests/UnitTests/Hash.cpp index 756beacab..7464da6ab 100644 --- a/test/old_tests/UnitTests/Hash.cpp +++ b/test/old_tests/UnitTests/Hash.cpp @@ -1,5 +1,5 @@ #include "pch.h" -#include "winrt\Windows.Foundation.h" +#include "winrt/Windows.Foundation.h" #include "catch.hpp" #include #include diff --git a/test/old_tests/UnitTests/pch.h b/test/old_tests/UnitTests/pch.h index 26990fd1c..4b940b552 100644 --- a/test/old_tests/UnitTests/pch.h +++ b/test/old_tests/UnitTests/pch.h @@ -10,29 +10,29 @@ #include #undef GetCurrentTime -#include "winrt\Windows.Foundation.Collections.h" -#include "winrt\Windows.Foundation.Diagnostics.h" -#include "winrt\Windows.ApplicationModel.Activation.h" -#include "winrt\Windows.ApplicationModel.Core.h" -#include "winrt\Windows.ApplicationModel.DataTransfer.h" -#include "winrt\Windows.ApplicationModel.Store.h" -#include "winrt\Windows.Data.Json.h" -#include "winrt\Windows.Devices.Perception.Provider.h" -#include "winrt\Windows.Devices.Sms.h" -#include "winrt\Windows.Graphics.Display.h" -#include "winrt\Windows.Graphics.Effects.h" -#include "winrt\Windows.Management.Deployment.h" -#include "winrt\Windows.Media.Audio.h" -#include "winrt\Windows.Media.Core.h" -#include "winrt\Windows.Media.Transcoding.h" -#include "winrt\Windows.Networking.Sockets.h" -#include "winrt\Windows.Security.Cryptography.Certificates.h" -#include "winrt\Windows.Storage.Streams.h" -#include "winrt\Windows.System.Threading.h" -#include "winrt\Windows.UI.Core.h" -#include "winrt\Windows.UI.Composition.h" -#include "winrt\Windows.UI.Xaml.Controls.h" -#include "winrt\Windows.UI.Xaml.Interop.h" -#include "winrt\Windows.Web.AtomPub.h" -#include "winrt\Windows.Web.Http.Headers.h" -#include "winrt\Windows.Web.Syndication.h" +#include "winrt/Windows.Foundation.Collections.h" +#include "winrt/Windows.Foundation.Diagnostics.h" +#include "winrt/Windows.ApplicationModel.Activation.h" +#include "winrt/Windows.ApplicationModel.Core.h" +#include "winrt/Windows.ApplicationModel.DataTransfer.h" +#include "winrt/Windows.ApplicationModel.Store.h" +#include "winrt/Windows.Data.Json.h" +#include "winrt/Windows.Devices.Perception.Provider.h" +#include "winrt/Windows.Devices.Sms.h" +#include "winrt/Windows.Graphics.Display.h" +#include "winrt/Windows.Graphics.Effects.h" +#include "winrt/Windows.Management.Deployment.h" +#include "winrt/Windows.Media.Audio.h" +#include "winrt/Windows.Media.Core.h" +#include "winrt/Windows.Media.Transcoding.h" +#include "winrt/Windows.Networking.Sockets.h" +#include "winrt/Windows.Security.Cryptography.Certificates.h" +#include "winrt/Windows.Storage.Streams.h" +#include "winrt/Windows.System.Threading.h" +#include "winrt/Windows.UI.Core.h" +#include "winrt/Windows.UI.Composition.h" +#include "winrt/Windows.UI.Xaml.Controls.h" +#include "winrt/Windows.UI.Xaml.Interop.h" +#include "winrt/Windows.Web.AtomPub.h" +#include "winrt/Windows.Web.Http.Headers.h" +#include "winrt/Windows.Web.Syndication.h" diff --git a/test/test/guid_include.cpp b/test/test/guid_include.cpp index 07a7d4988..212b6b0e5 100644 --- a/test/test/guid_include.cpp +++ b/test/test/guid_include.cpp @@ -1,3 +1,3 @@ #include "winrt/base.h" -#include +#include #include "winrt/Windows.Foundation.h" diff --git a/test/test_fast_fwd/FastForwarderTests.cpp b/test/test_fast_fwd/FastForwarderTests.cpp index 5a10216bf..8a80eaf1c 100644 --- a/test/test_fast_fwd/FastForwarderTests.cpp +++ b/test/test_fast_fwd/FastForwarderTests.cpp @@ -1,8 +1,8 @@ #include "pch.h" #include -#include "winrt\fast_forward.h" -#include "winrt\Windows.Foundation.h" -#include "winrt\FastForwarderTest.h" +#include "winrt/fast_forward.h" +#include "winrt/Windows.Foundation.h" +#include "winrt/FastForwarderTest.h" #include "Class.g.h" using namespace std::literals; From 3343c7cb787cdcb58eac1bff31ddbbf65dc8988b Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Wed, 14 Dec 2022 01:32:15 +0800 Subject: [PATCH 155/305] Make compatible with GCC (#1245) --- .github/workflows/ci.yml | 114 ++++++++++++++++++++++-- CMakeLists.txt | 1 + strings/base_chrono.h | 4 +- strings/base_coroutine_threadpool.h | 28 ++++++ strings/base_extern.h | 10 ++- strings/base_string.h | 12 +++ test/CMakeLists.txt | 10 +++ test/old_tests/UnitTests/CMakeLists.txt | 14 +-- test/old_tests/UnitTests/agile_ref.cpp | 3 + test/old_tests/UnitTests/async.cpp | 6 +- test/old_tests/UnitTests/hstring.cpp | 1 - test/old_tests/UnitTests/weak.cpp | 12 +-- test/test/CMakeLists.txt | 23 ++++- test/test/async_propagate_cancel.cpp | 3 +- test/test/custom_error.cpp | 6 ++ test/test_cpp20/CMakeLists.txt | 11 ++- test/test_cpp20/custom_error.cpp | 4 + test/test_win7/CMakeLists.txt | 12 ++- 18 files changed, 240 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dca6c31bc..1a3b121b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -257,6 +257,9 @@ jobs: arch: [i686, x86_64] config: [Debug, Release] runs-on: windows-latest + env: + CMAKE_COLOR_DIAGNOSTICS: 1 + CLICOLOR_FORCE: 1 steps: - uses: actions/checkout@v3 @@ -277,6 +280,8 @@ jobs: } cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` -DDOWNLOAD_WINDOWSNUMERICS=TRUE ` + -DUSE_ANSI_COLOR=TRUE ` + -DCMAKE_CXX_FLAGS="-fansi-escape-codes" ` -DENABLE_TEST_SANITIZERS=$sanitizers cmake --build . -j2 --target cppwinrt @@ -303,12 +308,69 @@ jobs: $env:UBSAN_OPTIONS = "print_stacktrace=1" ctest --verbose + test-msys2-gcc-cppwinrt: + name: 'gcc/msys2: Build and test (${{ matrix.sys }}, ${{ matrix.config }})' + strategy: + fail-fast: false + matrix: + include: + - { sys: mingw32, arch: i686, config: Release } + - { sys: mingw64, arch: x86_64, config: Debug } + - { sys: mingw64, arch: x86_64, config: Release } + - { sys: ucrt64, arch: x86_64, config: Release } + runs-on: windows-latest + env: + CMAKE_COLOR_DIAGNOSTICS: 1 + CLICOLOR_FORCE: 1 + defaults: + run: + shell: msys2 {0} + steps: + - uses: msys2/setup-msys2@v2 + with: + msystem: ${{matrix.sys}} + update: true + pacboy: >- + crt:p + gcc:p + binutils:p + cmake:p + ninja:p + + - uses: actions/checkout@v3 + + - name: Build cppwinrt + run: | + mkdir build + cd build + if [[ "${{ matrix.arch }}" = "i686" ]]; then + skip_large_pch_arg="-DSKIP_LARGE_PCH=TRUE" + fi + cmake ../ -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.config }} \ + -DDOWNLOAD_WINDOWSNUMERICS=TRUE \ + -DUSE_ANSI_COLOR=TRUE \ + $skip_large_pch_arg + cmake --build . --target cppwinrt + + - name: Build tests + run: | + cd build + cmake --build . -j2 --target test-vanilla test_cpp20 test_win7 test_old + + - name: Run tests + run: | + cd build + ctest --verbose + build-linux-cross-cppwinrt: name: 'cross: Cross-build from Linux' strategy: matrix: arch: [i686, x86_64] runs-on: ubuntu-22.04 + env: + CMAKE_COLOR_DIAGNOSTICS: 1 + CLICOLOR_FORCE: 1 steps: - uses: actions/checkout@v3 @@ -367,7 +429,8 @@ jobs: cd build cmake ../test -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug ` -DCPPWINRT_PROJECTION_INCLUDE_DIR="../.test/out" ` - -DDOWNLOAD_WINDOWSNUMERICS=TRUE + -DDOWNLOAD_WINDOWSNUMERICS=TRUE ` + -DUSE_ANSI_COLOR=TRUE cmake --build . -j2 - name: Run tests @@ -376,11 +439,35 @@ jobs: ctest --verbose build-linux-native-cppwinrt: - name: 'linux: GCC native build + llvm-mingw cross-build tests' + name: 'linux: GCC native build + mingw-w64 cross-build tests' + strategy: + fail-fast: false + matrix: + # TODO: Enable gcc build once Arch Linux gets more recent mingw-w64 headers (ver. 11 perhaps?) + # cross_toolchain: [gcc, llvm-mingw] + cross_toolchain: [llvm-mingw] + cross_arch: [i686, x86_64] + # include: + # - cross_toolchain: gcc + # container: + # image: archlinux:base-devel runs-on: ubuntu-22.04 + container: ${{ matrix.container }} + defaults: + run: + shell: bash + env: + CMAKE_COLOR_DIAGNOSTICS: 1 + CLICOLOR_FORCE: 1 steps: - uses: actions/checkout@v3 + - name: Install build tools + if: matrix.cross_toolchain == 'gcc' + run: | + pacman --noconfirm -Suuy + pacman --needed --noconfirm -S cmake ninja git + - name: Build cppwinrt run: | cmake -S . -B build/native/ \ @@ -399,30 +486,41 @@ jobs: - id: setup-llvm name: Set up llvm-mingw + if: matrix.cross_toolchain == 'llvm-mingw' uses: ./.github/actions/setup-llvm-mingw + - name: Install GCC cross compiler + if: matrix.cross_toolchain == 'gcc' + run: | + pacman --needed --noconfirm -S mingw-w64-gcc + - name: Cross-build tests using projection run: | cmake -S test -B build/cross-tests --toolchain "$PWD/cross-mingw-toolchain.cmake" \ - -DCMAKE_SYSTEM_PROCESSOR=x86_64 \ + -DCMAKE_SYSTEM_PROCESSOR=${{ matrix.cross_arch }} \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_CXX_FLAGS="-static" \ -DCPPWINRT_PROJECTION_INCLUDE_DIR=/tmp/cppwinrt \ - -DDOWNLOAD_WINDOWSNUMERICS=TRUE + -DDOWNLOAD_WINDOWSNUMERICS=TRUE \ + -DUSE_ANSI_COLOR=TRUE cmake --build build/cross-tests -j2 - name: Upload built tests uses: actions/upload-artifact@v3 with: - name: linux-native-cppwinrt-cross-build-tests-x86_64-bin + name: linux-native-cppwinrt-cross-build-tests-${{ matrix.cross_toolchain }}-${{ matrix.cross_arch }}-bin path: build/cross-tests/*.exe test-linux-native-cppwinrt-cross-tests: name: 'linux: Run llvm-mingw cross-build tests' needs: build-linux-native-cppwinrt strategy: + fail-fast: false matrix: - arch: [x86_64] + # TODO: Enable gcc build test when it is buildable + # cross_toolchain: [gcc, llvm-mingw] + cross_toolchain: [llvm-mingw] + cross_arch: [i686, x86_64] runs-on: windows-latest steps: - uses: actions/checkout@v3 @@ -430,7 +528,7 @@ jobs: - name: Fetch test executables uses: actions/download-artifact@v3 with: - name: linux-native-cppwinrt-cross-build-tests-${{ matrix.arch }}-bin + name: linux-native-cppwinrt-cross-build-tests-${{ matrix.cross_toolchain }}-${{ matrix.cross_arch }}-bin path: ./ - name: Run tests @@ -439,7 +537,7 @@ jobs: $has_failed_tests = 0 foreach ($test_exe in $test_exes) { echo "::group::Run '$test_exe'" - & .\$test_exe + & .\$test_exe --use-colour yes echo "::endgroup::" if ($LastExitCode -ne 0) { echo "::error::Test '$test_exe' failed!" diff --git a/CMakeLists.txt b/CMakeLists.txt index e8ef5fa4a..b5f547fd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,6 +182,7 @@ ExternalProject_Add(winmd CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" + UPDATE_COMMAND "" ) add_dependencies(cppwinrt winmd) ExternalProject_Get_Property(winmd SOURCE_DIR) diff --git a/strings/base_chrono.h b/strings/base_chrono.h index 151246d46..d48cd703b 100644 --- a/strings/base_chrono.h +++ b/strings/base_chrono.h @@ -42,12 +42,12 @@ WINRT_EXPORT namespace winrt static time_t to_time_t(time_point const& time) noexcept { - return static_cast(std::chrono::system_clock::to_time_t(to_sys(std::chrono::time_point_cast(time)))); + return static_cast(std::chrono::system_clock::to_time_t(std::chrono::time_point_cast(to_sys(time)))); } static time_point from_time_t(time_t time) noexcept { - return std::chrono::time_point_cast(from_sys(std::chrono::system_clock::from_time_t(time))); + return from_sys(std::chrono::time_point_cast(std::chrono::system_clock::from_time_t(time))); } static file_time to_file_time(time_point const& time) noexcept diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 415857850..9861b8294 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -328,6 +328,19 @@ WINRT_EXPORT namespace winrt { } +#if defined(__GNUC__) && !defined(__clang__) + // HACK: GCC seems to require a move when calling operator co_await + // on the return value of resume_after. + // This might be related to upstream bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99575 + awaitable(awaitable &&other) noexcept : + m_timer{std::move(other.m_timer)}, + m_duration{std::move(other.m_duration)}, + m_handle{std::move(other.m_handle)}, + m_state{other.m_state.load()} + {} +#endif + void enable_cancellation(cancellable_promise* promise) { promise->set_canceller([](void* context) @@ -434,6 +447,21 @@ WINRT_EXPORT namespace winrt m_handle(handle) {} +#if defined(__GNUC__) && !defined(__clang__) + // HACK: GCC seems to require a move when calling operator co_await + // on the return value of resume_on_signal. + // This might be related to upstream bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99575 + awaitable(awaitable &&other) noexcept : + m_wait{std::move(other.m_wait)}, + m_timeout{std::move(other.m_timeout)}, + m_handle{std::move(other.m_handle)}, + m_result{std::move(other.m_result)}, + m_resume{std::move(other.m_resume)}, + m_state{other.m_state.load()} + {} +#endif + void enable_cancellation(cancellable_promise* promise) { promise->set_canceller([](void* context) diff --git a/strings/base_extern.h b/strings/base_extern.h index 52b72bea5..e8a065710 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -93,9 +93,15 @@ extern "C" #endif #elif defined(__GNUC__) #if defined(__i386__) -#define WINRT_IMPL_LINK(function, count) __asm__(".weak _WINRT_IMPL_" #function "@" #count "\n.set _WINRT_IMPL_" #function "@" #count ", _" #function "@" #count); +#define WINRT_IMPL_LINK(function, count) __asm__( \ + ".globl _" #function "@" #count "\n\t" \ + ".weak _WINRT_IMPL_" #function "@" #count "\n\t" \ + ".set _WINRT_IMPL_" #function "@" #count ", _" #function "@" #count); #else -#define WINRT_IMPL_LINK(function, count) __asm__(".weak WINRT_IMPL_" #function "\n.set WINRT_IMPL_" #function ", " #function); +#define WINRT_IMPL_LINK(function, count) __asm__( \ + ".globl " #function "\n\t" \ + ".weak WINRT_IMPL_" #function "\n\t" \ + ".set WINRT_IMPL_" #function ", " #function); #endif #endif diff --git a/strings/base_string.h b/strings/base_string.h index 13f3b9dce..2a6023a26 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -488,11 +488,23 @@ namespace winrt::impl T const& object; +#if !defined(__GNUC__) || defined(__clang__) template operator R const& () const noexcept { return reinterpret_cast(object); } +#else + // HACK: GCC does not handle template deduction of const T& conversion + // function according to CWG issue 976. To make this compile on GCC, + // we have to intentionally drop the const qualifier. + // Ref: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61663 + template + operator R& () const noexcept + { + return const_cast(reinterpret_cast(object)); + } +#endif }; template diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6cf1aa3ca..d4bb3e125 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -94,6 +94,16 @@ if(ENABLE_TEST_SANITIZERS) endif() +set(USE_ANSI_COLOR FALSE CACHE BOOL "Enable ANSI colour output for Catch2 test runner.") +if(USE_ANSI_COLOR) + add_compile_definitions(CATCH_CONFIG_COLOUR_ANSI) + set(TEST_COLOR_ARG "--use-colour yes") +endif() + + +set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.") + + add_subdirectory(test) add_subdirectory(test_cpp20) add_subdirectory(test_win7) diff --git a/test/old_tests/UnitTests/CMakeLists.txt b/test/old_tests/UnitTests/CMakeLists.txt index 7042aa63b..908691653 100644 --- a/test/old_tests/UnitTests/CMakeLists.txt +++ b/test/old_tests/UnitTests/CMakeLists.txt @@ -47,15 +47,17 @@ endforeach() add_executable(test_old Main.cpp ${TEST_SRCS}) target_link_libraries(test_old runtimeobject synchronization) -target_precompile_headers(test_old PRIVATE pch.h) -set_source_files_properties( - conditional_implements_pure.cpp - PROPERTIES SKIP_PRECOMPILE_HEADERS true -) +if(NOT SKIP_LARGE_PCH) + target_precompile_headers(test_old PRIVATE pch.h) + set_source_files_properties( + conditional_implements_pure.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true + ) +endif() add_dependencies(test_old build-cppwinrt-projection) add_test( NAME test_old - COMMAND "$" + COMMAND "$" ${TEST_COLOR_ARG} ) diff --git a/test/old_tests/UnitTests/agile_ref.cpp b/test/old_tests/UnitTests/agile_ref.cpp index 2bf6dd637..13f76e17f 100644 --- a/test/old_tests/UnitTests/agile_ref.cpp +++ b/test/old_tests/UnitTests/agile_ref.cpp @@ -39,6 +39,9 @@ IAsyncAction test_agile_ref() #if defined(__clang__) && defined(_MSC_VER) && (defined(_M_IX86) || defined(__i386__)) // FIXME: Test is known to crash from calling invalid address on x86 when built with Clang. TEST_CASE("agile_ref", "[.clang-crash]") +#elif defined(__GNUC__) && !defined(__clang__) +// FIXME: Test is known to randomly crash or abort when built with GCC (segfaults under appverifier). +TEST_CASE("agile_ref", "[.gcc-crash]") #else TEST_CASE("agile_ref") #endif diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index e5c468144..979c2aac7 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -1566,10 +1566,12 @@ namespace co_await resume_on_signal(signal); // should not suspend because already signaled REQUIRE(caller == GetCurrentThreadId()); // still on calling thread - REQUIRE(false == co_await resume_on_signal(signal, 1us)); // should suspend but timeout + bool suspend_but_timeout_result = co_await resume_on_signal(signal, 1us); + REQUIRE(false == suspend_but_timeout_result); // should suspend but timeout REQUIRE(caller != GetCurrentThreadId()); // now on background thread - REQUIRE(true == co_await resume_on_signal(signal, 1s)); // should eventually succeed + bool suspend_and_succeed_result = co_await resume_on_signal(signal, 1s); + REQUIRE(true == suspend_and_succeed_result); // should eventually succeed } } diff --git a/test/old_tests/UnitTests/hstring.cpp b/test/old_tests/UnitTests/hstring.cpp index 1369fd229..2abd9769f 100644 --- a/test/old_tests/UnitTests/hstring.cpp +++ b/test/old_tests/UnitTests/hstring.cpp @@ -272,7 +272,6 @@ TEST_CASE("hstring,operator,std::wstring_view") REQUIRE(L"abc" == ws); hs.clear(); - REQUIRE(L"abc" == ws); ws = hs; REQUIRE(ws.empty()); } diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index 6724b71ad..55c40dbe6 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -50,8 +50,8 @@ namespace } }; -// FIXME: Fail to compile with Clang due to incomplete type. -#if !defined(__clang__) +// FIXME: Fail to compile with Clang and GCC due to incomplete type. +#if !defined(__clang__) && !defined(__GNUC__) struct WeakWithSelfReference : implements { winrt::weak_ref weak_self = get_weak(); @@ -447,8 +447,8 @@ TEST_CASE("weak,assignment") // Not constructible from L"" (because Uri constructor is explicit) static_assert(!std::is_constructible_v, const wchar_t*>); -// FIXME: WeakWithSelfReference fails to compile with Clang. -#if !defined(__clang__) +// FIXME: WeakWithSelfReference fails to compile with Clang and GCC. +#if !defined(__clang__) && !defined(__GNUC__) // Constructible from com_ptr because com_ptr is // implicitly convertible to com_ptr. struct Derived : WeakWithSelfReference {}; @@ -487,8 +487,8 @@ TEST_CASE("weak,no_module_lock") REQUIRE(get_module_lock() == object_count); } -// FIXME: WeakWithSelfReference fails to compile with Clang. -#if !defined(__clang__) +// FIXME: WeakWithSelfReference fails to compile with Clang and GCC. +#if !defined(__clang__) && !defined(__GNUC__) TEST_CASE("weak,self") { // The REQUIRE statements are in the WeakWithSelfReference class itself. diff --git a/test/test/CMakeLists.txt b/test/test/CMakeLists.txt index c14fc7c00..ba174d41b 100644 --- a/test/test/CMakeLists.txt +++ b/test/test/CMakeLists.txt @@ -39,6 +39,16 @@ list(APPEND BROKEN_TESTS when ) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # FIXME: GCC does not compile co_await on thread_pool because it wants + # a copy constructor. Disabling this test for now. + # This might be related to upstream bug: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103963 + list(APPEND BROKEN_TESTS + thread_pool + ) +endif() + # Exclude broken tests foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") @@ -63,9 +73,20 @@ set_source_files_properties( PROPERTIES SKIP_PRECOMPILE_HEADERS true ) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # GCC seems to miscompile out_params_bad.cpp if -fdevirtualize is enabled. + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108040 + set_source_files_properties(out_params_bad.cpp PROPERTIES COMPILE_OPTIONS "-fno-devirtualize") + + if(CMAKE_BUILD_TYPE STREQUAL "Release") + # GCC miscompiles multi_threaded_vector.cpp with -O3 + set_source_files_properties(multi_threaded_vector.cpp PROPERTIES COMPILE_OPTIONS "-O2") + endif() +endif() + add_dependencies(test-vanilla build-cppwinrt-projection) add_test( NAME test - COMMAND "$" + COMMAND "$" ${TEST_COLOR_ARG} ) diff --git a/test/test/async_propagate_cancel.cpp b/test/test/async_propagate_cancel.cpp index a3e5af749..b2e331929 100644 --- a/test/test/async_propagate_cancel.cpp +++ b/test/test/async_propagate_cancel.cpp @@ -132,7 +132,8 @@ namespace // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_propagate_cancel", "[.clang-crash]") #else -TEST_CASE("async_propagate_cancel") +// FIXME: mayfail because of https://github.com/microsoft/cppwinrt/issues/1243 +TEST_CASE("async_propagate_cancel", "[!mayfail]") #endif { Check(Action); diff --git a/test/test/custom_error.cpp b/test/test/custom_error.cpp index f186ee970..8e1855e31 100644 --- a/test/test/custom_error.cpp +++ b/test/test/custom_error.cpp @@ -102,10 +102,16 @@ TEST_CASE("custom_error_logger") // Validate that handler translated exception REQUIRE_THROWS_AS(check_hresult(0x80000018), hresult_illegal_delegate_assignment); REQUIRE(s_loggerCalled); +#ifndef __cpp_lib_source_location // In C++17 these fields cannot be filled in so they are expected to be empty. REQUIRE(s_loggerArgs.lineNumber == 0); REQUIRE(s_loggerArgs.fileName == nullptr); REQUIRE(s_loggerArgs.functionName == nullptr); +#else + // GCC/Clang can only compile these tests in C++20 mode. If source_location + // is available these fields will be filled in. Don't do any checks here + // because these are already tested in `test_cpp20/custom_error.cpp`. +#endif REQUIRE(s_loggerArgs.returnAddress); REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) diff --git a/test/test_cpp20/CMakeLists.txt b/test/test_cpp20/CMakeLists.txt index 8b787b696..cbf1b799d 100644 --- a/test/test_cpp20/CMakeLists.txt +++ b/test/test_cpp20/CMakeLists.txt @@ -1,7 +1,10 @@ set(CMAKE_CXX_STANDARD 20) -# std::format, std::ranges::is_heap, std::views::reverse, std::ranges::max -# are experimental in libc++ as of Clang 15. -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # std::format, std::ranges::is_heap, std::views::reverse, std::ranges::max + # are experimental in libc++ as of Clang 15. + # FIXME: Should probably use compile test instead? + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") +endif() if(ENABLE_TEST_SANITIZERS) # As of LLVM 15, custom_error.cpp doesn't build with ASAN due to: @@ -39,5 +42,5 @@ add_dependencies(test_cpp20 build-cppwinrt-projection) add_test( NAME test_cpp20 - COMMAND "$" + COMMAND "$" ${TEST_COLOR_ARG} ) diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index 620ffc755..707088cd9 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -59,7 +59,11 @@ TEST_CASE("custom_error_logger") REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); const auto functionNameSv = std::string_view(s_loggerArgs.functionName); REQUIRE(!functionNameSv.empty()); +#if defined(__GNUC__) && !defined(__clang__) + REQUIRE(functionNameSv == "void {anonymous}::FailOnLine15()"); +#else REQUIRE(functionNameSv == "FailOnLine15"); +#endif REQUIRE(s_loggerArgs.returnAddress); REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) diff --git a/test/test_win7/CMakeLists.txt b/test/test_win7/CMakeLists.txt index 7ada247c4..d1c4120ea 100644 --- a/test/test_win7/CMakeLists.txt +++ b/test/test_win7/CMakeLists.txt @@ -32,6 +32,16 @@ list(APPEND BROKEN_TESTS when ) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # FIXME: GCC does not compile co_await on thread_pool because it wants + # a copy constructor. Disabling this test for now. + # This might be related to upstream bug: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103963 + list(APPEND BROKEN_TESTS + thread_pool + ) +endif() + # Exclude broken tests foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") @@ -54,5 +64,5 @@ add_dependencies(test_win7 build-cppwinrt-projection) add_test( NAME test_win7 - COMMAND "$" + COMMAND "$" ${TEST_COLOR_ARG} ) From b482851c3721b4ef32eeb329a1064f162e877f7f Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Fri, 16 Dec 2022 00:07:35 +0800 Subject: [PATCH 156/305] FIx build on macOS and add CI build (#1247) --- .github/workflows/ci.yml | 28 ++++++++++++++++++++++++++++ cppwinrt/text_writer.h | 18 ++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a3b121b7..5124d0881 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -548,6 +548,34 @@ jobs: exit 1 } + build-macos-native-cppwinrt: + name: 'macOS: GCC native build' + runs-on: macos-latest + defaults: + run: + shell: bash + env: + CMAKE_COLOR_DIAGNOSTICS: 1 + CLICOLOR_FORCE: 1 + steps: + - uses: actions/checkout@v3 + + - name: Build cppwinrt + run: | + cmake -S . -B build/native/ \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_INSTALL_PREFIX=$PWD/install/ + cmake --build build/native/ --target install -j2 + + - name: Test run (cppwinrt -?) + run: | + install/bin/cppwinrt -? + + - name: Test run (build projection using Windows.winmd) + run: | + curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/metadata/default/Windows.winmd + install/bin/cppwinrt -in Windows.winmd -out build/out -verbose + build-msvc-natvis: name: 'Build natvis' strategy: diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index ee723c703..0b7c07a4e 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -104,22 +104,32 @@ namespace cppwinrt f(*static_cast(this)); } - void write(int32_t const value) + void write(int const value) { write(std::to_string(value)); } - void write(uint32_t const value) + void write(unsigned int const value) { write(std::to_string(value)); } - void write(int64_t const value) + void write(signed long const value) { write(std::to_string(value)); } - void write(uint64_t const value) + void write(unsigned long const value) + { + write(std::to_string(value)); + } + + void write(signed long long const value) + { + write(std::to_string(value)); + } + + void write(unsigned long long const value) { write(std::to_string(value)); } From 69f9d8ca189ee83b436c6544eeeb3a4dfd766da4 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 15 Dec 2022 19:31:38 -0600 Subject: [PATCH 157/305] Improve error reporting for clock test (#1248) --- test/old_tests/UnitTests/clock.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/old_tests/UnitTests/clock.cpp b/test/old_tests/UnitTests/clock.cpp index c18b5431a..9f82bd829 100644 --- a/test/old_tests/UnitTests/clock.cpp +++ b/test/old_tests/UnitTests/clock.cpp @@ -76,8 +76,8 @@ TEST_CASE("clock, time_t") REQUIRE(clock::to_time_t(clock::from_time_t(now_tt)) == now_tt); // Conversions are verified to be consistent. Now, verify that we're correctly converting epochs - const auto diff = abs(clock::now() - clock::from_time_t(time(nullptr))); - REQUIRE(diff < seconds{ 1 }); + const auto diff = duration_cast(abs(clock::now() - clock::from_time_t(time(nullptr)))).count(); + REQUIRE(diff < 1000); } TEST_CASE("clock, FILETIME") From 8ac2b798c70d4a0229b39b479a268d595ebd80e9 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 19 Dec 2022 09:45:09 -0500 Subject: [PATCH 158/305] Fix cancellation propagation by moving responsability to awaiter (#1246) --- strings/base_coroutine_foundation.h | 47 ++- strings/base_coroutine_threadpool.h | 422 +++++++++++++++------------ test/test/async_propagate_cancel.cpp | 18 +- test/test/await_completed.cpp | 9 +- 4 files changed, 272 insertions(+), 224 deletions(-) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 22896f42b..2f8297d0b 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -142,7 +142,7 @@ namespace winrt::impl #ifdef WINRT_IMPL_COROUTINES template - struct await_adapter : enable_await_cancellation + struct await_adapter : cancellable_awaiter> { await_adapter(Async const& async) : async(async) { } @@ -164,7 +164,22 @@ namespace winrt::impl return false; } - auto await_suspend(coroutine_handle<> handle) + template + auto await_suspend(coroutine_handle handle) + { + this->set_cancellable_promise_from_handle(handle); + return register_completed_callback(handle); + } + + auto await_resume() const + { + check_hresult(failure); + check_status_canceled(status); + return async.GetResults(); + } + + private: + auto register_completed_callback(coroutine_handle<> handle) { auto extend_lifetime = async; async.Completed(disconnect_aware_handler(this, handle)); @@ -178,14 +193,6 @@ namespace winrt::impl #endif } - auto await_resume() const - { - check_hresult(failure); - check_status_canceled(status); - return async.GetResults(); - } - - private: static fire_and_forget cancel_asynchronously(Async async) { co_await winrt::resume_background(); @@ -373,7 +380,7 @@ namespace winrt::impl }; template - struct promise_base : implements + struct promise_base : implements, cancellable_promise { using AsyncStatus = Windows::Foundation::AsyncStatus; @@ -471,7 +478,7 @@ namespace winrt::impl cancel(); } - m_cancellable.cancel(); + cancellable_promise::cancel(); } void Close() const noexcept @@ -608,15 +615,6 @@ namespace winrt::impl throw winrt::hresult_canceled(); } - if constexpr (std::is_convertible_v&, enable_await_cancellation&>) - { - if (m_propagate_cancellation) - { - static_cast(expression).set_cancellable_promise(&m_cancellable); - expression.enable_cancellation(&m_cancellable); - } - } - return std::forward(expression); } @@ -648,11 +646,6 @@ namespace winrt::impl } } - bool enable_cancellation_propagation(bool value) noexcept - { - return std::exchange(m_propagate_cancellation, value); - } - #if defined(_DEBUG) && !defined(WINRT_NO_MAKE_DETECTION) void use_make_function_to_create_this_object() final { @@ -673,10 +666,8 @@ namespace winrt::impl slim_mutex m_lock; async_completed_handler_t m_completed; winrt::delegate<> m_cancel; - cancellable_promise m_cancellable; std::atomic m_status; bool m_completed_assigned{ false }; - bool m_propagate_cancellation{ false }; }; } diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 9861b8294..fb23f24c9 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -173,19 +173,31 @@ WINRT_EXPORT namespace winrt } } + bool enable_cancellation_propagation(bool value) noexcept + { + return std::exchange(m_propagate_cancellation, value); + } + + bool cancellation_propagation_enabled() const noexcept + { + return m_propagate_cancellation; + } + private: static inline auto const cancelling_ptr = reinterpret_cast(1); std::atomic m_canceller{ nullptr }; void* m_context{ nullptr }; + bool m_propagate_cancellation{ false }; }; - struct enable_await_cancellation + template + struct cancellable_awaiter { - enable_await_cancellation() noexcept = default; - enable_await_cancellation(enable_await_cancellation const&) = default; + cancellable_awaiter() noexcept = default; + cancellable_awaiter(cancellable_awaiter const&) = default; - ~enable_await_cancellation() + ~cancellable_awaiter() { if (m_promise) { @@ -193,14 +205,27 @@ WINRT_EXPORT namespace winrt } } - void operator=(enable_await_cancellation const&) = delete; + void operator=(cancellable_awaiter const&) = delete; - void set_cancellable_promise(cancellable_promise* promise) noexcept + protected: + template + void set_cancellable_promise_from_handle(impl::coroutine_handle const& handle) { - m_promise = promise; + if constexpr (std::is_base_of_v) + { + set_cancellable_promise(&handle.promise()); + } } private: + void set_cancellable_promise(cancellable_promise* promise) + { + if (promise->cancellation_propagation_enabled()) + { + m_promise = promise; + static_cast(this)->enable_cancellation(m_promise); + } + } cancellable_promise* m_promise = nullptr; }; @@ -308,252 +333,267 @@ namespace winrt::impl impl::resume_apartment(context.context, handle, &failure); } }; -} - -WINRT_EXPORT namespace winrt -{ -#ifdef WINRT_IMPL_COROUTINES - inline impl::apartment_awaiter operator co_await(apartment_context const& context) - { - return{ context }; - } -#endif - [[nodiscard]] inline auto resume_after(Windows::Foundation::TimeSpan duration) noexcept + struct timespan_awaiter : cancellable_awaiter { - struct awaitable : enable_await_cancellation + explicit timespan_awaiter(Windows::Foundation::TimeSpan duration) noexcept : + m_duration(duration) { - explicit awaitable(Windows::Foundation::TimeSpan duration) noexcept : - m_duration(duration) - { - } + } #if defined(__GNUC__) && !defined(__clang__) - // HACK: GCC seems to require a move when calling operator co_await - // on the return value of resume_after. - // This might be related to upstream bug: - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99575 - awaitable(awaitable &&other) noexcept : - m_timer{std::move(other.m_timer)}, - m_duration{std::move(other.m_duration)}, - m_handle{std::move(other.m_handle)}, - m_state{other.m_state.load()} - {} + // HACK: GCC seems to require a move when calling operator co_await + // on the return value of resume_after. + // This might be related to upstream bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99575 + timespan_awaiter(timespan_awaiter &&other) noexcept : + m_timer{std::move(other.m_timer)}, + m_duration{std::move(other.m_duration)}, + m_handle{std::move(other.m_handle)}, + m_state{other.m_state.load()} + {} #endif - void enable_cancellation(cancellable_promise* promise) + void enable_cancellation(cancellable_promise* promise) + { + promise->set_canceller([](void* context) { - promise->set_canceller([](void* context) + auto that = static_cast(context); + if (that->m_state.exchange(state::canceled, std::memory_order_acquire) == state::pending) { - auto that = static_cast(context); - if (that->m_state.exchange(state::canceled, std::memory_order_acquire) == state::pending) - { - that->fire_immediately(); - } - }, this); - } + that->fire_immediately(); + } + }, this); + } - bool await_ready() const noexcept - { - return m_duration.count() <= 0; - } + bool await_ready() const noexcept + { + return m_duration.count() <= 0; + } - void await_suspend(impl::coroutine_handle<> handle) - { - m_handle = handle; - m_timer.attach(check_pointer(WINRT_IMPL_CreateThreadpoolTimer(callback, this, nullptr))); - int64_t relative_count = -m_duration.count(); - WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); + template + void await_suspend(impl::coroutine_handle handle) + { + set_cancellable_promise_from_handle(handle); - state expected = state::idle; - if (!m_state.compare_exchange_strong(expected, state::pending, std::memory_order_release)) - { - fire_immediately(); - } - } + m_handle = handle; + create_threadpool_timer(); + } - void await_resume() + void await_resume() + { + if (m_state.exchange(state::idle, std::memory_order_relaxed) == state::canceled) { - if (m_state.exchange(state::idle, std::memory_order_relaxed) == state::canceled) - { - throw hresult_canceled(); - } + throw hresult_canceled(); } + } - private: + private: + void create_threadpool_timer() + { + m_timer.attach(check_pointer(WINRT_IMPL_CreateThreadpoolTimer(callback, this, nullptr))); + int64_t relative_count = -m_duration.count(); + WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); - static int32_t __stdcall fallback_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept + state expected = state::idle; + if (!m_state.compare_exchange_strong(expected, state::pending, std::memory_order_release)) { - return 0; // pretend timer has already triggered and a callback is on its way + fire_immediately(); } + } - void fire_immediately() noexcept - { - static int32_t(__stdcall* handler)(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept; - impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolTimerEx", handler, fallback_SetThreadpoolTimerEx); + static int32_t __stdcall fallback_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept + { + return 0; // pretend timer has already triggered and a callback is on its way + } - if (handler(m_timer.get(), nullptr, 0, 0)) - { - int64_t now = 0; - WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); - } - } + void fire_immediately() noexcept + { + static int32_t(__stdcall * handler)(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept; + impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolTimerEx", handler, fallback_SetThreadpoolTimerEx); - static void __stdcall callback(void*, void* context, void*) noexcept + if (handler(m_timer.get(), nullptr, 0, 0)) { - auto that = reinterpret_cast(context); - that->m_handle(); + int64_t now = 0; + WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); } + } - struct timer_traits - { - using type = impl::ptp_timer; - - static void close(type value) noexcept - { - WINRT_IMPL_CloseThreadpoolTimer(value); - } + static void __stdcall callback(void*, void* context, void*) noexcept + { + auto that = reinterpret_cast(context); + that->m_handle(); + } - static constexpr type invalid() noexcept - { - return nullptr; - } - }; + struct timer_traits + { + using type = impl::ptp_timer; - enum class state { idle, pending, canceled }; + static void close(type value) noexcept + { + WINRT_IMPL_CloseThreadpoolTimer(value); + } - handle_type m_timer; - Windows::Foundation::TimeSpan m_duration; - impl::coroutine_handle<> m_handle; - std::atomic m_state{ state::idle }; + static constexpr type invalid() noexcept + { + return nullptr; + } }; - return awaitable{ duration }; - } + enum class state { idle, pending, canceled }; -#ifdef WINRT_IMPL_COROUTINES - inline auto operator co_await(Windows::Foundation::TimeSpan duration) - { - return resume_after(duration); - } -#endif + handle_type m_timer; + Windows::Foundation::TimeSpan m_duration; + impl::coroutine_handle<> m_handle; + std::atomic m_state{ state::idle }; + }; - [[nodiscard]] inline auto resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) noexcept + struct signal_awaiter : cancellable_awaiter { - struct awaitable : enable_await_cancellation - { - awaitable(void* handle, Windows::Foundation::TimeSpan timeout) noexcept : - m_timeout(timeout), - m_handle(handle) - {} + signal_awaiter(void* handle, Windows::Foundation::TimeSpan timeout) noexcept : + m_timeout(timeout), + m_handle(handle) + {} #if defined(__GNUC__) && !defined(__clang__) - // HACK: GCC seems to require a move when calling operator co_await - // on the return value of resume_on_signal. - // This might be related to upstream bug: - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99575 - awaitable(awaitable &&other) noexcept : - m_wait{std::move(other.m_wait)}, - m_timeout{std::move(other.m_timeout)}, - m_handle{std::move(other.m_handle)}, - m_result{std::move(other.m_result)}, - m_resume{std::move(other.m_resume)}, - m_state{other.m_state.load()} - {} + // HACK: GCC seems to require a move when calling operator co_await + // on the return value of resume_on_signal. + // This might be related to upstream bug: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99575 + signal_awaiter(signal_awaiter &&other) noexcept : + m_wait{std::move(other.m_wait)}, + m_timeout{std::move(other.m_timeout)}, + m_handle{std::move(other.m_handle)}, + m_result{std::move(other.m_result)}, + m_resume{std::move(other.m_resume)}, + m_state{other.m_state.load()} + {} #endif - void enable_cancellation(cancellable_promise* promise) + void enable_cancellation(cancellable_promise* promise) + { + promise->set_canceller([](void* context) { - promise->set_canceller([](void* context) + auto that = static_cast(context); + if (that->m_state.exchange(state::canceled, std::memory_order_acquire) == state::pending) { - auto that = static_cast(context); - if (that->m_state.exchange(state::canceled, std::memory_order_acquire) == state::pending) - { - that->fire_immediately(); - } - }, this); - } + that->fire_immediately(); + } + }, this); + } - bool await_ready() const noexcept + bool await_ready() const noexcept + { + return WINRT_IMPL_WaitForSingleObject(m_handle, 0) == 0; + } + + template + void await_suspend(impl::coroutine_handle resume) + { + set_cancellable_promise_from_handle(resume); + + m_resume = resume; + create_threadpool_wait(); + } + + bool await_resume() + { + if (m_state.exchange(state::idle, std::memory_order_relaxed) == state::canceled) { - return WINRT_IMPL_WaitForSingleObject(m_handle, 0) == 0; + throw hresult_canceled(); } + return m_result == 0; + } - void await_suspend(impl::coroutine_handle<> resume) - { - m_resume = resume; - m_wait.attach(check_pointer(WINRT_IMPL_CreateThreadpoolWait(callback, this, nullptr))); - int64_t relative_count = -m_timeout.count(); - int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; - WINRT_IMPL_SetThreadpoolWait(m_wait.get(), m_handle, file_time); + private: + static int32_t __stdcall fallback_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept + { + return 0; // pretend wait has already triggered and a callback is on its way + } - state expected = state::idle; - if (!m_state.compare_exchange_strong(expected, state::pending, std::memory_order_release)) - { - fire_immediately(); - } - } + void create_threadpool_wait() + { + m_wait.attach(check_pointer(WINRT_IMPL_CreateThreadpoolWait(callback, this, nullptr))); + int64_t relative_count = -m_timeout.count(); + int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; + WINRT_IMPL_SetThreadpoolWait(m_wait.get(), m_handle, file_time); - bool await_resume() + state expected = state::idle; + if (!m_state.compare_exchange_strong(expected, state::pending, std::memory_order_release)) { - if (m_state.exchange(state::idle, std::memory_order_relaxed) == state::canceled) - { - throw hresult_canceled(); - } - return m_result == 0; + fire_immediately(); } + } - private: - static int32_t __stdcall fallback_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept + void fire_immediately() noexcept + { + static int32_t(__stdcall * handler)(winrt::impl::ptp_wait, void*, void*, void*) noexcept; + impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolWaitEx", handler, fallback_SetThreadpoolWaitEx); + + if (handler(m_wait.get(), nullptr, nullptr, nullptr)) { - return 0; // pretend wait has already triggered and a callback is on its way + int64_t now = 0; + WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); } + } - void fire_immediately() noexcept - { - static int32_t(__stdcall* handler)(winrt::impl::ptp_wait, void*, void*, void*) noexcept; - impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolWaitEx", handler, fallback_SetThreadpoolWaitEx); + static void __stdcall callback(void*, void* context, void*, uint32_t result) noexcept + { + auto that = static_cast(context); + that->m_result = result; + that->m_resume(); + } - if (handler(m_wait.get(), nullptr, nullptr, nullptr)) - { - int64_t now = 0; - WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); - } - } + struct wait_traits + { + using type = impl::ptp_wait; - static void __stdcall callback(void*, void* context, void*, uint32_t result) noexcept + static void close(type value) noexcept { - auto that = static_cast(context); - that->m_result = result; - that->m_resume(); + WINRT_IMPL_CloseThreadpoolWait(value); } - struct wait_traits + static constexpr type invalid() noexcept { - using type = impl::ptp_wait; + return nullptr; + } + }; - static void close(type value) noexcept - { - WINRT_IMPL_CloseThreadpoolWait(value); - } + enum class state { idle, pending, canceled }; - static constexpr type invalid() noexcept - { - return nullptr; - } - }; + handle_type m_wait; + Windows::Foundation::TimeSpan m_timeout; + void* m_handle; + uint32_t m_result{}; + impl::coroutine_handle<> m_resume{ nullptr }; + std::atomic m_state{ state::idle }; + }; +} - enum class state { idle, pending, canceled }; +WINRT_EXPORT namespace winrt +{ +#ifdef WINRT_IMPL_COROUTINES + inline impl::apartment_awaiter operator co_await(apartment_context const& context) + { + return{ context }; + } +#endif - handle_type m_wait; - Windows::Foundation::TimeSpan m_timeout; - void* m_handle; - uint32_t m_result{}; - impl::coroutine_handle<> m_resume{ nullptr }; - std::atomic m_state{ state::idle }; - }; + [[nodiscard]] inline impl::timespan_awaiter resume_after(Windows::Foundation::TimeSpan duration) noexcept + { + return impl::timespan_awaiter{ duration }; + } - return awaitable{ handle, timeout }; +#ifdef WINRT_IMPL_COROUTINES + inline impl::timespan_awaiter operator co_await(Windows::Foundation::TimeSpan duration) + { + return resume_after(duration); + } +#endif + + [[nodiscard]] inline impl::signal_awaiter resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) noexcept + { + return impl::signal_awaiter{ handle, timeout }; } struct thread_pool diff --git a/test/test/async_propagate_cancel.cpp b/test/test/async_propagate_cancel.cpp index b2e331929..9e0ab8ee9 100644 --- a/test/test/async_propagate_cancel.cpp +++ b/test/test/async_propagate_cancel.cpp @@ -104,7 +104,7 @@ namespace } template - void Check(F make) + void CheckWithWait(F make, bool wait) { handle completed{ CreateEvent(nullptr, true, false, nullptr) }; auto async = make(); @@ -117,6 +117,12 @@ namespace SetEvent(completed.get()); }); + if (wait) + { + // ensure we hit the co_await that's cancellable before trying to cancel. + Sleep(1000); + } + async.Cancel(); // Wait indefinitely if a debugger is present, to make it easier to debug this test. @@ -126,14 +132,20 @@ namespace REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED)); REQUIRE_THROWS_AS(async.GetResults(), hresult_canceled); } + + template + void Check(F make) + { + CheckWithWait(make, false); + CheckWithWait(make, true); + } } #if defined(__clang__) && defined(_MSC_VER) // FIXME: Test is known to segfault when built with Clang. TEST_CASE("async_propagate_cancel", "[.clang-crash]") #else -// FIXME: mayfail because of https://github.com/microsoft/cppwinrt/issues/1243 -TEST_CASE("async_propagate_cancel", "[!mayfail]") +TEST_CASE("async_propagate_cancel") #endif { Check(Action); diff --git a/test/test/await_completed.cpp b/test/test/await_completed.cpp index fed776e90..8ee3a0cce 100644 --- a/test/test/await_completed.cpp +++ b/test/test/await_completed.cpp @@ -27,14 +27,19 @@ namespace } #endif - // Simple awaiter that (inefficiently) resumes from inside + // Simple awaiter that (inefficiently) resumes from inside a function nested in // await_suspend, for the purpose of measuring how much stack it consumes. // This is the best we can do with MSVC prerelease coroutines prior to 16.11. + // This simulates the behavior of await_adapter. struct resume_sync_from_await_suspend { bool await_ready() { return false; } - void await_suspend(winrt::impl::coroutine_handle<> h) { h(); } + template + void await_suspend(winrt::impl::coroutine_handle h) { resume_inner(h); } void await_resume() { } + + private: + void resume_inner(winrt::impl::coroutine_handle<> h) { h(); } }; IAsyncAction SyncCompletion() From 44572ed0f1f7777c33c6ca860e0195de7badcd7d Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 20 Dec 2022 09:59:35 +0800 Subject: [PATCH 159/305] Try to fix random failure of the clock test (#1251) --- test/old_tests/UnitTests/clock.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/old_tests/UnitTests/clock.cpp b/test/old_tests/UnitTests/clock.cpp index 9f82bd829..3940cb1c3 100644 --- a/test/old_tests/UnitTests/clock.cpp +++ b/test/old_tests/UnitTests/clock.cpp @@ -66,33 +66,34 @@ TEST_CASE("clock, units") TEST_CASE("clock, time_t") { + const DateTime now_dt = clock::now(); + const time_t now_tt = time(nullptr); + // Round trip from DateTime to time_t and back. // confirm that nothing happens other than truncating the fractional seconds - const DateTime now_dt = clock::now(); REQUIRE(clock::from_time_t(clock::to_time_t(now_dt)) == time_point_cast(now_dt)); // Same thing in reverse - const time_t now_tt = time(nullptr); REQUIRE(clock::to_time_t(clock::from_time_t(now_tt)) == now_tt); // Conversions are verified to be consistent. Now, verify that we're correctly converting epochs - const auto diff = duration_cast(abs(clock::now() - clock::from_time_t(time(nullptr)))).count(); + const auto diff = duration_cast(abs(now_dt - clock::from_time_t(now_tt))).count(); REQUIRE(diff < 1000); } TEST_CASE("clock, FILETIME") { - // Round trip conversions const DateTime now_dt = clock::now(); - REQUIRE(clock::from_file_time(clock::to_file_time(now_dt)) == now_dt); - FILETIME now_ft; ::GetSystemTimePreciseAsFileTime(&now_ft); + + // Round trip conversions + REQUIRE(clock::from_file_time(clock::to_file_time(now_dt)) == now_dt); + REQUIRE(clock::to_file_time(clock::from_file_time(now_ft)) == now_ft); // Verify epoch - ::GetSystemTimePreciseAsFileTime(&now_ft); - const auto diff = abs(clock::now() - clock::from_file_time(now_ft)); + const auto diff = abs(now_dt - clock::from_file_time(now_ft)); REQUIRE(diff < milliseconds{ 100 }); } From 31ad5bcd0108732cf1b6ba8a430869dc22c9d78b Mon Sep 17 00:00:00 2001 From: yuvaln-s1 Date: Tue, 20 Dec 2022 23:11:33 +0200 Subject: [PATCH 160/305] Fix object usage after move in make_delegate_with_shared_state (#1253) --- strings/base_coroutine_foundation.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 2f8297d0b..6afeff607 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -42,7 +42,8 @@ namespace winrt::impl std::pair make_delegate_with_shared_state(H&& handler) { auto d = make_delegate(std::forward(handler)); - return { std::move(d), reinterpret_cast*>(get_abi(d)) }; + auto abi = reinterpret_cast*>(get_abi(d)); + return { std::move(d), abi }; } template From 0a6cb062e2151cf6c8f357aa8ef735e359f8a98c Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Wed, 21 Dec 2022 08:13:41 +0800 Subject: [PATCH 161/305] mingw: Stop using .weak symbols aliases (#1250) --- strings/base_extern.h | 230 ++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 153 deletions(-) diff --git a/strings/base_extern.h b/strings/base_extern.h index e8a065710..266758aa0 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -4,83 +4,6 @@ __declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* __declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; -extern "C" -{ - void* __stdcall WINRT_IMPL_LoadLibraryW(wchar_t const* name) noexcept; - int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept; - void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept; - - int32_t __stdcall WINRT_IMPL_SetErrorInfo(uint32_t reserved, void* info) noexcept; - int32_t __stdcall WINRT_IMPL_GetErrorInfo(uint32_t reserved, void** info) noexcept; - int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, uint32_t type) noexcept; - void __stdcall WINRT_IMPL_CoUninitialize() noexcept; - - int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept; - int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, uint32_t context, winrt::guid const& iid, void** object) noexcept; - int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept; - int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept; - int32_t __stdcall WINRT_IMPL_CoGetApartmentType(int32_t* type, int32_t* qualifier) noexcept; - void* __stdcall WINRT_IMPL_CoTaskMemAlloc(std::size_t size) noexcept; - void __stdcall WINRT_IMPL_CoTaskMemFree(void* ptr) noexcept; - winrt::impl::bstr __stdcall WINRT_IMPL_SysAllocString(wchar_t const* value) noexcept; - void __stdcall WINRT_IMPL_SysFreeString(winrt::impl::bstr string) noexcept; - uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept; - int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept; - int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(uint32_t codepage, uint32_t flags, char const* in_string, int32_t in_size, wchar_t* out_string, int32_t out_size) noexcept; - int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(uint32_t codepage, uint32_t flags, wchar_t const* int_string, int32_t in_size, char* out_string, int32_t out_size, char const* default_char, int32_t* default_used) noexcept; - void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, uint32_t flags, size_t bytes) noexcept; - int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, uint32_t flags, void* value) noexcept; - void* __stdcall WINRT_IMPL_GetProcessHeap() noexcept; - uint32_t __stdcall WINRT_IMPL_FormatMessageW(uint32_t flags, void const* source, uint32_t code, uint32_t language, wchar_t* buffer, uint32_t size, va_list* arguments) noexcept; - uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept; - void __stdcall WINRT_IMPL_GetSystemTimePreciseAsFileTime(void* result) noexcept; - uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, uintptr_t length) noexcept; - void* __stdcall WINRT_IMPL_EncodePointer(void* ptr) noexcept; - - int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, uint32_t access, void** token) noexcept; - void* __stdcall WINRT_IMPL_GetCurrentProcess() noexcept; - int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, uint32_t level, void** duplicate) noexcept; - int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, uint32_t access, int32_t self, void** token) noexcept; - void* __stdcall WINRT_IMPL_GetCurrentThread() noexcept; - int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept; - - void __stdcall WINRT_IMPL_AcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept; - void __stdcall WINRT_IMPL_AcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept; - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept; - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept; - void __stdcall WINRT_IMPL_ReleaseSRWLockExclusive(winrt::impl::srwlock* lock) noexcept; - void __stdcall WINRT_IMPL_ReleaseSRWLockShared(winrt::impl::srwlock* lock) noexcept; - int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, uint32_t milliseconds, uint32_t flags) noexcept; - void __stdcall WINRT_IMPL_WakeConditionVariable(winrt::impl::condition_variable* cv) noexcept; - void __stdcall WINRT_IMPL_WakeAllConditionVariable(winrt::impl::condition_variable* cv) noexcept; - void* __stdcall WINRT_IMPL_InterlockedPushEntrySList(void* head, void* entry) noexcept; - void* __stdcall WINRT_IMPL_InterlockedFlushSList(void* head) noexcept; - - void* __stdcall WINRT_IMPL_CreateEventW(void*, int32_t, int32_t, void*) noexcept; - int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept; - int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept; - uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, uint32_t milliseconds) noexcept; - - int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept; - winrt::impl::ptp_timer __stdcall WINRT_IMPL_CreateThreadpoolTimer(void(__stdcall *callback)(void*, void* context, void*), void* context, void*) noexcept; - void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept; - void __stdcall WINRT_IMPL_CloseThreadpoolTimer(winrt::impl::ptp_timer timer) noexcept; - winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, uint32_t result), void* context, void*) noexcept; - void __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept; - void __stdcall WINRT_IMPL_CloseThreadpoolWait(winrt::impl::ptp_wait wait) noexcept; - winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept; - void __stdcall WINRT_IMPL_StartThreadpoolIo(winrt::impl::ptp_io io) noexcept; - void __stdcall WINRT_IMPL_CancelThreadpoolIo(winrt::impl::ptp_io io) noexcept; - void __stdcall WINRT_IMPL_CloseThreadpoolIo(winrt::impl::ptp_io io) noexcept; - winrt::impl::ptp_pool __stdcall WINRT_IMPL_CreateThreadpool(void* reserved) noexcept; - void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, uint32_t value) noexcept; - int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, uint32_t value) noexcept; - void __stdcall WINRT_IMPL_CloseThreadpool(winrt::impl::ptp_pool pool) noexcept; - - int32_t __stdcall WINRT_CanUnloadNow() noexcept; - int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; -} - #if defined(_MSC_VER) #ifdef _M_HYBRID #define WINRT_IMPL_LINK(function, count) __pragma(comment(linker, "/alternatename:#WINRT_IMPL_" #function "@" #count "=#" #function "@" #count)) @@ -93,86 +16,87 @@ extern "C" #endif #elif defined(__GNUC__) #if defined(__i386__) -#define WINRT_IMPL_LINK(function, count) __asm__( \ - ".globl _" #function "@" #count "\n\t" \ - ".weak _WINRT_IMPL_" #function "@" #count "\n\t" \ - ".set _WINRT_IMPL_" #function "@" #count ", _" #function "@" #count); +#define WINRT_IMPL_LINK(function, count) __asm__("_" #function "@" #count) #else -#define WINRT_IMPL_LINK(function, count) __asm__( \ - ".globl " #function "\n\t" \ - ".weak WINRT_IMPL_" #function "\n\t" \ - ".set WINRT_IMPL_" #function ", " #function); +#define WINRT_IMPL_LINK(function, count) __asm__(#function) #endif #endif -WINRT_IMPL_LINK(LoadLibraryW, 4) -WINRT_IMPL_LINK(FreeLibrary, 4) -WINRT_IMPL_LINK(GetProcAddress, 8) -WINRT_IMPL_LINK(SetErrorInfo, 8) -WINRT_IMPL_LINK(GetErrorInfo, 8) -WINRT_IMPL_LINK(CoInitializeEx, 8) -WINRT_IMPL_LINK(CoUninitialize, 0) - -WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8) -WINRT_IMPL_LINK(CoCreateInstance, 20) -WINRT_IMPL_LINK(CoGetCallContext, 8) -WINRT_IMPL_LINK(CoGetObjectContext, 8) -WINRT_IMPL_LINK(CoGetApartmentType, 8) -WINRT_IMPL_LINK(CoTaskMemAlloc, 4) -WINRT_IMPL_LINK(CoTaskMemFree, 4) -WINRT_IMPL_LINK(SysAllocString, 4) -WINRT_IMPL_LINK(SysFreeString, 4) -WINRT_IMPL_LINK(SysStringLen, 4) -WINRT_IMPL_LINK(IIDFromString, 8) -WINRT_IMPL_LINK(MultiByteToWideChar, 24) -WINRT_IMPL_LINK(WideCharToMultiByte, 32) -WINRT_IMPL_LINK(HeapAlloc, 12) -WINRT_IMPL_LINK(HeapFree, 12) -WINRT_IMPL_LINK(GetProcessHeap, 0) -WINRT_IMPL_LINK(FormatMessageW, 28) -WINRT_IMPL_LINK(GetLastError, 0) -WINRT_IMPL_LINK(GetSystemTimePreciseAsFileTime, 4) -WINRT_IMPL_LINK(VirtualQuery, 12) -WINRT_IMPL_LINK(EncodePointer, 4) - -WINRT_IMPL_LINK(OpenProcessToken, 12) -WINRT_IMPL_LINK(GetCurrentProcess, 0) -WINRT_IMPL_LINK(DuplicateToken, 12) -WINRT_IMPL_LINK(OpenThreadToken, 16) -WINRT_IMPL_LINK(GetCurrentThread, 0) -WINRT_IMPL_LINK(SetThreadToken, 8) - -WINRT_IMPL_LINK(AcquireSRWLockExclusive, 4) -WINRT_IMPL_LINK(AcquireSRWLockShared, 4) -WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4) -WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4) -WINRT_IMPL_LINK(ReleaseSRWLockExclusive, 4) -WINRT_IMPL_LINK(ReleaseSRWLockShared, 4) -WINRT_IMPL_LINK(SleepConditionVariableSRW, 16) -WINRT_IMPL_LINK(WakeConditionVariable, 4) -WINRT_IMPL_LINK(WakeAllConditionVariable, 4) -WINRT_IMPL_LINK(InterlockedPushEntrySList, 8) -WINRT_IMPL_LINK(InterlockedFlushSList, 4) - -WINRT_IMPL_LINK(CreateEventW, 16) -WINRT_IMPL_LINK(SetEvent, 4) -WINRT_IMPL_LINK(CloseHandle, 4) -WINRT_IMPL_LINK(WaitForSingleObject, 8) +extern "C" +{ + void* __stdcall WINRT_IMPL_LoadLibraryW(wchar_t const* name) noexcept WINRT_IMPL_LINK(LoadLibraryW, 4); + int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); + void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8); + + int32_t __stdcall WINRT_IMPL_SetErrorInfo(uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8); + int32_t __stdcall WINRT_IMPL_GetErrorInfo(uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); + int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); + void __stdcall WINRT_IMPL_CoUninitialize() noexcept WINRT_IMPL_LINK(CoUninitialize, 0); + + int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); + int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); + int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetCallContext, 8); + int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetObjectContext, 8); + int32_t __stdcall WINRT_IMPL_CoGetApartmentType(int32_t* type, int32_t* qualifier) noexcept WINRT_IMPL_LINK(CoGetApartmentType, 8); + void* __stdcall WINRT_IMPL_CoTaskMemAlloc(std::size_t size) noexcept WINRT_IMPL_LINK(CoTaskMemAlloc, 4); + void __stdcall WINRT_IMPL_CoTaskMemFree(void* ptr) noexcept WINRT_IMPL_LINK(CoTaskMemFree, 4); + winrt::impl::bstr __stdcall WINRT_IMPL_SysAllocString(wchar_t const* value) noexcept WINRT_IMPL_LINK(SysAllocString, 4); + void __stdcall WINRT_IMPL_SysFreeString(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysFreeString, 4); + uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysStringLen, 4); + int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept WINRT_IMPL_LINK(IIDFromString, 8); + int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(uint32_t codepage, uint32_t flags, char const* in_string, int32_t in_size, wchar_t* out_string, int32_t out_size) noexcept WINRT_IMPL_LINK(MultiByteToWideChar, 24); + int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(uint32_t codepage, uint32_t flags, wchar_t const* int_string, int32_t in_size, char* out_string, int32_t out_size, char const* default_char, int32_t* default_used) noexcept WINRT_IMPL_LINK(WideCharToMultiByte, 32); + void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, uint32_t flags, size_t bytes) noexcept WINRT_IMPL_LINK(HeapAlloc, 12); + int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, uint32_t flags, void* value) noexcept WINRT_IMPL_LINK(HeapFree, 12); + void* __stdcall WINRT_IMPL_GetProcessHeap() noexcept WINRT_IMPL_LINK(GetProcessHeap, 0); + uint32_t __stdcall WINRT_IMPL_FormatMessageW(uint32_t flags, void const* source, uint32_t code, uint32_t language, wchar_t* buffer, uint32_t size, va_list* arguments) noexcept WINRT_IMPL_LINK(FormatMessageW, 28); + uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept WINRT_IMPL_LINK(GetLastError, 0); + void __stdcall WINRT_IMPL_GetSystemTimePreciseAsFileTime(void* result) noexcept WINRT_IMPL_LINK(GetSystemTimePreciseAsFileTime, 4); + uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, uintptr_t length) noexcept WINRT_IMPL_LINK(VirtualQuery, 12); + void* __stdcall WINRT_IMPL_EncodePointer(void* ptr) noexcept WINRT_IMPL_LINK(EncodePointer, 4); + + int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, uint32_t access, void** token) noexcept WINRT_IMPL_LINK(OpenProcessToken, 12); + void* __stdcall WINRT_IMPL_GetCurrentProcess() noexcept WINRT_IMPL_LINK(GetCurrentProcess, 0); + int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, uint32_t level, void** duplicate) noexcept WINRT_IMPL_LINK(DuplicateToken, 12); + int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, uint32_t access, int32_t self, void** token) noexcept WINRT_IMPL_LINK(OpenThreadToken, 16); + void* __stdcall WINRT_IMPL_GetCurrentThread() noexcept WINRT_IMPL_LINK(GetCurrentThread, 0); + int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept WINRT_IMPL_LINK(SetThreadToken, 8); + + void __stdcall WINRT_IMPL_AcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockExclusive, 4); + void __stdcall WINRT_IMPL_AcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockShared, 4); + uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4); + uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4); + void __stdcall WINRT_IMPL_ReleaseSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockExclusive, 4); + void __stdcall WINRT_IMPL_ReleaseSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockShared, 4); + int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, uint32_t milliseconds, uint32_t flags) noexcept WINRT_IMPL_LINK(SleepConditionVariableSRW, 16); + void __stdcall WINRT_IMPL_WakeConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeConditionVariable, 4); + void __stdcall WINRT_IMPL_WakeAllConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeAllConditionVariable, 4); + void* __stdcall WINRT_IMPL_InterlockedPushEntrySList(void* head, void* entry) noexcept WINRT_IMPL_LINK(InterlockedPushEntrySList, 8); + void* __stdcall WINRT_IMPL_InterlockedFlushSList(void* head) noexcept WINRT_IMPL_LINK(InterlockedFlushSList, 4); + + void* __stdcall WINRT_IMPL_CreateEventW(void*, int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(CreateEventW, 16); + int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept WINRT_IMPL_LINK(SetEvent, 4); + int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept WINRT_IMPL_LINK(CloseHandle, 4); + uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, uint32_t milliseconds) noexcept WINRT_IMPL_LINK(WaitForSingleObject, 8); + + int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12); + winrt::impl::ptp_timer __stdcall WINRT_IMPL_CreateThreadpoolTimer(void(__stdcall *callback)(void*, void* context, void*), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolTimer, 12); + void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept WINRT_IMPL_LINK(SetThreadpoolTimer, 16); + void __stdcall WINRT_IMPL_CloseThreadpoolTimer(winrt::impl::ptp_timer timer) noexcept WINRT_IMPL_LINK(CloseThreadpoolTimer, 4); + winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, uint32_t result), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolWait, 12); + void __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept WINRT_IMPL_LINK(SetThreadpoolWait, 12); + void __stdcall WINRT_IMPL_CloseThreadpoolWait(winrt::impl::ptp_wait wait) noexcept WINRT_IMPL_LINK(CloseThreadpoolWait, 4); + winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolIo, 16); + void __stdcall WINRT_IMPL_StartThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(StartThreadpoolIo, 4); + void __stdcall WINRT_IMPL_CancelThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CancelThreadpoolIo, 4); + void __stdcall WINRT_IMPL_CloseThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CloseThreadpoolIo, 4); + winrt::impl::ptp_pool __stdcall WINRT_IMPL_CreateThreadpool(void* reserved) noexcept WINRT_IMPL_LINK(CreateThreadpool, 4); + void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8); + int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8); + void __stdcall WINRT_IMPL_CloseThreadpool(winrt::impl::ptp_pool pool) noexcept WINRT_IMPL_LINK(CloseThreadpool, 4); -WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12) -WINRT_IMPL_LINK(CreateThreadpoolTimer, 12) -WINRT_IMPL_LINK(SetThreadpoolTimer, 16) -WINRT_IMPL_LINK(CloseThreadpoolTimer, 4) -WINRT_IMPL_LINK(CreateThreadpoolWait, 12) -WINRT_IMPL_LINK(SetThreadpoolWait, 12) -WINRT_IMPL_LINK(CloseThreadpoolWait, 4) -WINRT_IMPL_LINK(CreateThreadpoolIo, 16) -WINRT_IMPL_LINK(StartThreadpoolIo, 4) -WINRT_IMPL_LINK(CancelThreadpoolIo, 4) -WINRT_IMPL_LINK(CloseThreadpoolIo, 4) -WINRT_IMPL_LINK(CreateThreadpool, 4) -WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8) -WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8) -WINRT_IMPL_LINK(CloseThreadpool, 4) + int32_t __stdcall WINRT_CanUnloadNow() noexcept; + int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; +} #undef WINRT_IMPL_LINK From 0214f2f7a2c8d19e78420cc445cf5ba490e4cc12 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Wed, 4 Jan 2023 01:33:25 +0800 Subject: [PATCH 162/305] cmake: Allow using external winmd headers to bypass download (#1256) --- CMakeLists.txt | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5f547fd5..139da8379 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,19 +175,29 @@ endif() # === winmd: External header-only library for reading winmd files === -include(ExternalProject) -ExternalProject_Add(winmd - GIT_REPOSITORY https://github.com/microsoft/winmd.git - GIT_TAG 0f1eae3bfa63fa2ba3c2912cbfe72a01db94cc5a - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - UPDATE_COMMAND "" -) -add_dependencies(cppwinrt winmd) -ExternalProject_Get_Property(winmd SOURCE_DIR) -set(winmd_SOURCE_DIR "${SOURCE_DIR}") -target_include_directories(cppwinrt PRIVATE "${winmd_SOURCE_DIR}/src") +set(EXTERNAL_WINMD_INCLUDE_DIR "" CACHE PATH "Path to the include dir of an\ + external copy of the winmd library headers. Leave empty (default) to have\ + it downloaded as ExternalProject during build.") + +if(EXTERNAL_WINMD_INCLUDE_DIR STREQUAL "") + message(STATUS "The winmd library will be downloaded using ExternalProject.") + include(ExternalProject) + ExternalProject_Add(winmd + GIT_REPOSITORY https://github.com/microsoft/winmd.git + GIT_TAG 0f1eae3bfa63fa2ba3c2912cbfe72a01db94cc5a + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + UPDATE_COMMAND "" + ) + add_dependencies(cppwinrt winmd) + ExternalProject_Get_Property(winmd SOURCE_DIR) + set(winmd_INCLUDE_DIR "${SOURCE_DIR}/src") +else() +message(STATUS "Using winmd library headers at ${EXTERNAL_WINMD_INCLUDE_DIR}") + set(winmd_INCLUDE_DIR "${EXTERNAL_WINMD_INCLUDE_DIR}") +endif() +target_include_directories(cppwinrt PRIVATE "${winmd_INCLUDE_DIR}") if(WIN32 AND NOT CMAKE_CROSSCOMPILING) From fe304096fa30583f3cc2ebfdbf564d2b4081e2ad Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Wed, 4 Jan 2023 01:33:53 +0800 Subject: [PATCH 163/305] Make headers partially usable with LLVM/libc++ 13 (#1257) --- strings/base_string.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/strings/base_string.h b/strings/base_string.h index 2a6023a26..2782968b8 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -642,6 +642,7 @@ WINRT_EXPORT namespace winrt return impl::hstring_convert(value); } +#if !defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 14000 inline hstring to_hstring(float value) { return impl::hstring_convert(value); @@ -651,6 +652,7 @@ WINRT_EXPORT namespace winrt { return impl::hstring_convert(value); } +#endif inline hstring to_hstring(char16_t value) { From 983f6598400bc2bdbd9025b5c1751e1b7d915670 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Mon, 9 Jan 2023 22:57:33 +0800 Subject: [PATCH 164/305] Cleaning up some warnings for Clang and GCC (#1255) --- strings/base_activation.h | 4 +++ strings/base_array.h | 29 ++++++++++++++----- strings/base_events.h | 2 ++ strings/base_identity.h | 4 +++ strings/base_implements.h | 9 ++++++ strings/base_macros.h | 6 ++++ strings/base_string_input.h | 4 +++ strings/base_version.h | 2 +- test/old_tests/Component/pch.h | 2 ++ test/old_tests/Composable/precomp.hpp | 2 ++ test/old_tests/UnitTests/Errors.cpp | 2 ++ test/old_tests/UnitTests/IReference.cpp | 4 ++- test/old_tests/UnitTests/Main.cpp | 4 +-- .../old_tests/UnitTests/apartment_context.cpp | 11 +++++++ test/old_tests/UnitTests/com_ref.cpp | 7 +++++ test/old_tests/UnitTests/constexpr.cpp | 2 ++ test/old_tests/UnitTests/enum_flags.cpp | 2 ++ test/old_tests/UnitTests/hresult_error.cpp | 4 ++- test/old_tests/UnitTests/meta.cpp | 2 ++ test/test/await_completed.cpp | 3 +- test/test/custom_error.cpp | 2 +- test/test/disconnected.cpp | 3 ++ test/test/event_clear.cpp | 2 ++ test/test/guid.cpp | 4 +-- test/test/inspectable_interop.cpp | 18 ++++++++++-- test/test/main.cpp | 4 +-- test/test/multi_threaded_common.h | 6 ++-- test/test/tearoff.cpp | 2 +- test/test_cpp20/custom_error.cpp | 2 +- test/test_cpp20/main.cpp | 4 +-- test/test_fast/main.cpp | 4 +-- test/test_fast_fwd/main.cpp | 4 +-- test/test_module_lock_custom/main.cpp | 4 +-- test/test_module_lock_none/main.cpp | 4 +-- test/test_slow/main.cpp | 4 +-- test/test_win7/inspectable_interop.cpp | 18 ++++++++++-- test/test_win7/main.cpp | 4 +-- 37 files changed, 153 insertions(+), 41 deletions(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index d77b8f5d8..5c6f938d9 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -196,8 +196,10 @@ namespace winrt::impl #ifdef _WIN64 inline constexpr uint32_t memory_allocation_alignment{ 16 }; +#ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4324) // structure was padded due to alignment specifier +#endif struct alignas(16) slist_entry { slist_entry* next; @@ -217,7 +219,9 @@ namespace winrt::impl uint64_t reserved4 : 60; } reserved2; }; +#ifdef _MSC_VER #pragma warning(pop) +#endif #else inline constexpr uint32_t memory_allocation_alignment{ 8 }; struct slist_entry diff --git a/strings/base_array.h b/strings/base_array.h index 5d1bee3c5..9f20cf34e 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -345,6 +345,26 @@ WINRT_EXPORT namespace winrt this->m_size = size; } } + + std::pair> detach_abi() noexcept + { +#ifdef _MSC_VER + // https://github.com/microsoft/cppwinrt/pull/1165 + std::pair> result; + memset(&result, 0, sizeof(result)); + result.first = this->size(); + result.second = *reinterpret_cast*>(this); + memset(this, 0, sizeof(com_array)); +#else + std::pair> result(this->size(), *reinterpret_cast*>(this)); + this->m_data = nullptr; + this->m_size = 0; +#endif + return result; + } + + template + friend std::pair> detach_abi(com_array& object) noexcept; }; template com_array(uint32_t, C const&) -> com_array>; @@ -418,14 +438,9 @@ WINRT_EXPORT namespace winrt } template - auto detach_abi(com_array& object) noexcept + std::pair> detach_abi(com_array& object) noexcept { - std::pair> result; - memset(&result, 0, sizeof(result)); - result.first = object.size(); - result.second = *reinterpret_cast*>(&object); - memset(&object, 0, sizeof(com_array)); - return result; + return object.detach_abi(); } template diff --git a/strings/base_events.h b/strings/base_events.h index b5783555b..131186864 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -331,7 +331,9 @@ namespace winrt::impl com_ptr> make_event_array(uint32_t const capacity) { void* raw = ::operator new(sizeof(event_array) + (sizeof(T)* capacity)); +#ifdef _MSC_VER #pragma warning(suppress: 6386) +#endif return { new(raw) event_array(capacity), take_ownership_from_abi }; } diff --git a/strings/base_identity.h b/strings/base_identity.h index 52a77dfc4..0f4a163b6 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -453,12 +453,16 @@ namespace winrt::impl template struct pinterface_guid { +#ifdef _MSC_VER #pragma warning(suppress: 4307) +#endif static constexpr guid value{ generate_guid(signature::data) }; }; template +#ifdef _MSC_VER #pragma warning(suppress: 4307) +#endif inline constexpr auto name_v { combine diff --git a/strings/base_implements.h b/strings/base_implements.h index a81df5f8e..80a69faa7 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -340,7 +340,9 @@ namespace winrt::impl template struct uncloaked_iids> { +#ifdef _MSC_VER #pragma warning(suppress: 4307) +#endif static constexpr std::array value{ winrt::guid_of() ... }; }; @@ -1462,6 +1464,10 @@ WINRT_EXPORT namespace winrt return result; } +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winconsistent-missing-override" +#endif impl::hresult_type __stdcall QueryInterface(impl::guid_type const& id, void** object) noexcept { return root_implements_type::QueryInterface(reinterpret_cast(id), object); @@ -1493,6 +1499,9 @@ WINRT_EXPORT namespace winrt { return root_implements_type::abi_GetTrustLevel(reinterpret_cast(value)); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif void* find_interface(guid const& id) const noexcept override { diff --git a/strings/base_macros.h b/strings/base_macros.h index d48db139d..1dd63c111 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -15,11 +15,13 @@ #define WINRT_IMPL_SHIM(...) (*(abi_t<__VA_ARGS__>**)&static_cast<__VA_ARGS__ const&>(static_cast(*this))) +#ifdef _MSC_VER // Note: this is a workaround for a false-positive warning produced by the Visual C++ 15.9 compiler. #pragma warning(disable : 5046) // Note: this is a workaround for a false-positive warning produced by the Visual C++ 16.3 compiler. #pragma warning(disable : 4268) +#endif #if defined(__cpp_lib_coroutine) || defined(__cpp_coroutines) || defined(_RESUMABLE_FUNCTIONS_SUPPORTED) #define WINRT_IMPL_COROUTINES @@ -87,7 +89,9 @@ typedef struct _GUID GUID; #define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation #define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation +#ifdef _MSC_VER #pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true") +#endif #else #define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT #define WINRT_IMPL_SOURCE_LOCATION_ARGS @@ -96,5 +100,7 @@ typedef struct _GUID GUID; #define WINRT_IMPL_SOURCE_LOCATION_FORWARD #define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM +#ifdef _MSC_VER #pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false") #endif +#endif diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 786b31519..8cfea212b 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -3,13 +3,17 @@ WINRT_EXPORT namespace winrt::param { struct hstring { +#ifdef _MSC_VER #pragma warning(suppress: 26495) +#endif hstring() noexcept : m_handle(nullptr) {} hstring(hstring const& values) = delete; hstring& operator=(hstring const& values) = delete; hstring(std::nullptr_t) = delete; +#ifdef _MSC_VER #pragma warning(suppress: 26495) +#endif hstring(winrt::hstring const& value) noexcept : m_handle(get_abi(value)) { } diff --git a/strings/base_version.h b/strings/base_version.h index 227f10402..adb3608da 100644 --- a/strings/base_version.h +++ b/strings/base_version.h @@ -4,13 +4,13 @@ extern "C" __declspec(selectany) char const * const WINRT_version = "C++/WinRT version:" CPPWINRT_VERSION; +#if defined(_MSC_VER) #ifdef _M_IX86 #pragma comment(linker, "/include:_WINRT_version") #else #pragma comment(linker, "/include:WINRT_version") #endif -#if defined(_MSC_VER) #pragma detect_mismatch("C++/WinRT version", CPPWINRT_VERSION) #endif diff --git a/test/old_tests/Component/pch.h b/test/old_tests/Component/pch.h index 7d1624884..5d84eecb6 100644 --- a/test/old_tests/Component/pch.h +++ b/test/old_tests/Component/pch.h @@ -1,6 +1,8 @@ #pragma once +#ifdef _MSC_VER #pragma warning(disable:4100) +#endif #include "winrt/Windows.Foundation.Collections.h" #include "winrt/Composable.h" diff --git a/test/old_tests/Composable/precomp.hpp b/test/old_tests/Composable/precomp.hpp index aa5d110c2..29f44db46 100644 --- a/test/old_tests/Composable/precomp.hpp +++ b/test/old_tests/Composable/precomp.hpp @@ -1,6 +1,8 @@ #pragma once +#ifdef _MSC_VER #pragma warning(disable:4100) +#endif #include "winrt/Windows.Foundation.h" #include "winrt/Composable.h" diff --git a/test/old_tests/UnitTests/Errors.cpp b/test/old_tests/UnitTests/Errors.cpp index 33e9b422f..472d633f1 100644 --- a/test/old_tests/UnitTests/Errors.cpp +++ b/test/old_tests/UnitTests/Errors.cpp @@ -66,7 +66,9 @@ void test_exception(HRESULT const code, std::wstring_view message) } } +#ifdef _MSC_VER #pragma warning(disable: 4702) // unreachable code +#endif TEST_CASE("Errors") { // These won't throw. diff --git a/test/old_tests/UnitTests/IReference.cpp b/test/old_tests/UnitTests/IReference.cpp index 50a349f89..cc03c5b9b 100644 --- a/test/old_tests/UnitTests/IReference.cpp +++ b/test/old_tests/UnitTests/IReference.cpp @@ -1,7 +1,9 @@ #include "pch.h" #include "catch.hpp" +#ifdef _MSC_VER #pragma warning(disable:4471) // a forward declaration of an unscoped enumeration must have an underlying type +#endif #include using namespace winrt; @@ -55,4 +57,4 @@ TEST_CASE("IReference, set WinRT runtime class property") { HttpContentDispositionHeaderValue value(L"inline"); value.Size(200); -} \ No newline at end of file +} diff --git a/test/old_tests/UnitTests/Main.cpp b/test/old_tests/UnitTests/Main.cpp index 3e5ecf03e..1f3818bda 100644 --- a/test/old_tests/UnitTests/Main.cpp +++ b/test/old_tests/UnitTests/Main.cpp @@ -15,9 +15,9 @@ int main(int argc, char * argv[]) init_apartment(); std::set_terminate([]{ reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); int const result = Catch::Session().run(argc, argv); diff --git a/test/old_tests/UnitTests/apartment_context.cpp b/test/old_tests/UnitTests/apartment_context.cpp index 8500a3100..1bdab7c8b 100644 --- a/test/old_tests/UnitTests/apartment_context.cpp +++ b/test/old_tests/UnitTests/apartment_context.cpp @@ -35,6 +35,11 @@ namespace context2 = nullptr; REQUIRE(!context2); +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wself-assign-overloaded" +#pragma clang diagnostic ignored "-Wself-move" +#endif // Self-copy-assignment context = context; REQUIRE(context); @@ -42,6 +47,9 @@ namespace // Self-move-assignment context = std::move(context); REQUIRE(context); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif co_await context; } @@ -76,6 +84,8 @@ namespace #endif +// Exclude on mingw-w64 to suppress `-Wunused-function` +#if !defined(__MINGW32__) bool is_nta_on_mta() { APTTYPE type; @@ -83,6 +93,7 @@ namespace check_hresult(CoGetApartmentType(&type, &qualifier)); return (type == APTTYPE_NA) && (qualifier == APTTYPEQUALIFIER_NA_ON_MTA || qualifier == APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA); } +#endif bool is_mta() { diff --git a/test/old_tests/UnitTests/com_ref.cpp b/test/old_tests/UnitTests/com_ref.cpp index 73c30e331..0d3e69120 100644 --- a/test/old_tests/UnitTests/com_ref.cpp +++ b/test/old_tests/UnitTests/com_ref.cpp @@ -13,7 +13,14 @@ namespace } #ifdef __CRT_UUID_DECL +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif __CRT_UUID_DECL(IClassic, 0x52bb7805, 0xe46e, 0x46f9, 0x85, 0x08, 0x86, 0x60, 0x6d, 0x2f, 0x6b, 0xc1); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif #endif TEST_CASE("com_ref agile_ref") diff --git a/test/old_tests/UnitTests/constexpr.cpp b/test/old_tests/UnitTests/constexpr.cpp index a881a2659..686d6ede9 100644 --- a/test/old_tests/UnitTests/constexpr.cpp +++ b/test/old_tests/UnitTests/constexpr.cpp @@ -2,7 +2,9 @@ #include "catch.hpp" #include "string_view_compare.h" +#ifdef _MSC_VER #pragma warning(disable:4471) // a forward declaration of an unscoped enumeration must have an underlying type +#endif #include using namespace std::string_view_literals; diff --git a/test/old_tests/UnitTests/enum_flags.cpp b/test/old_tests/UnitTests/enum_flags.cpp index 3b8274f7e..670199c88 100644 --- a/test/old_tests/UnitTests/enum_flags.cpp +++ b/test/old_tests/UnitTests/enum_flags.cpp @@ -1,7 +1,9 @@ #include "pch.h" #include "catch.hpp" +#ifdef _MSC_VER #pragma warning(disable:4471) // a forward declaration of an unscoped enumeration must have an underlying type +#endif #include #include "winrt/Windows.ApplicationModel.Appointments.h" diff --git a/test/old_tests/UnitTests/hresult_error.cpp b/test/old_tests/UnitTests/hresult_error.cpp index 23ad209af..fa15c2a1d 100644 --- a/test/old_tests/UnitTests/hresult_error.cpp +++ b/test/old_tests/UnitTests/hresult_error.cpp @@ -3,7 +3,7 @@ // Missing in mingw-w64 #ifndef E_BOUNDS -#define E_BOUNDS (0x8000000B) +#define E_BOUNDS ((HRESULT)0x8000000B) #endif extern "C" BOOL __stdcall RoOriginateLanguageException(HRESULT error, void* message, void* languageException); @@ -482,7 +482,9 @@ TEST_CASE("hresult, exception") } } +#ifdef _MSC_VER #pragma warning(disable: 4702) // unreachable code +#endif TEST_CASE("hresult, throw_last_error") { SetLastError(ERROR_CANCELLED); diff --git a/test/old_tests/UnitTests/meta.cpp b/test/old_tests/UnitTests/meta.cpp index e19a7202a..e8e61dda6 100644 --- a/test/old_tests/UnitTests/meta.cpp +++ b/test/old_tests/UnitTests/meta.cpp @@ -1,7 +1,9 @@ #include "pch.h" #include "catch.hpp" +#ifdef _MSC_VER #pragma warning(disable: 4505) +#endif using namespace winrt; using namespace Windows::Foundation; diff --git a/test/test/await_completed.cpp b/test/test/await_completed.cpp index 8ee3a0cce..be33e818f 100644 --- a/test/test/await_completed.cpp +++ b/test/test/await_completed.cpp @@ -62,6 +62,7 @@ namespace // is the ABI breaking change with MSVC standard-conforming coroutines.) REQUIRE(consumed <= sync_usage); #else + (void)sync_usage; // MSVC standard-conforming coroutines (as well as gcc and clang coroutines) // support "bool await_suspend" just fine. REQUIRE(consumed == 0); @@ -71,4 +72,4 @@ namespace TEST_CASE("await_completed_await") { SyncCompletion().get(); -} \ No newline at end of file +} diff --git a/test/test/custom_error.cpp b/test/test/custom_error.cpp index 8e1855e31..dbdf31ab9 100644 --- a/test/test/custom_error.cpp +++ b/test/test/custom_error.cpp @@ -114,7 +114,7 @@ TEST_CASE("custom_error_logger") #endif REQUIRE(s_loggerArgs.returnAddress); - REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + REQUIRE(s_loggerArgs.result == static_cast(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) // Remove global handler winrt_throw_hresult_handler = nullptr; diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 8c7e30e49..53dfbd142 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -35,6 +35,8 @@ namespace co_return 123; } +// Exclude on mingw-w64 to suppress `-Wunused-function` +#if !defined(__MINGW32__) bool is_mta() { APTTYPE type; @@ -42,6 +44,7 @@ namespace check_hresult(CoGetApartmentType(&type, &qualifier)); return type == APTTYPE_MTA; } +#endif } TEST_CASE("disconnected,handler,1") diff --git a/test/test/event_clear.cpp b/test/test/event_clear.cpp index 54db2cef7..54f3d62b7 100644 --- a/test/test/event_clear.cpp +++ b/test/test/event_clear.cpp @@ -16,11 +16,13 @@ TEST_CASE("event_clear") { counter += 1; }); + (void)a; auto b = event.add([&](auto && ...) { counter += 10; }); + (void)b; REQUIRE(counter == 0); event(0, 0); diff --git a/test/test/guid.cpp b/test/test/guid.cpp index 48d277e64..dc91c7d3c 100644 --- a/test/test/guid.cpp +++ b/test/test/guid.cpp @@ -20,7 +20,7 @@ TEST_CASE("guid") STATIC_REQUIRE_GUID_EQUAL(winrt::guid("00112233-4455-6677-8899-aabbccddeeff"), expected); REQUIRE(winrt::guid("00112233-4455-6677-8899-aabbccddeeff") == expected); - REQUIRE(winrt::guid({ "{00112233-4455-6677-8899-aabbccddeeff}" + 1, 36 }) == expected); + REQUIRE(winrt::guid({ &"{00112233-4455-6677-8899-aabbccddeeff}"[1], 36 }) == expected); REQUIRE(winrt::guid("{00112233-4455-6677-8899-aabbccddeeff}") == expected); REQUIRE(winrt::guid("(00112233-4455-6677-8899-aabbccddeeff)") == expected); @@ -34,4 +34,4 @@ TEST_CASE("guid") // Verify that you can constexpr-construct a guid from a GUID. constexpr winrt::guid from_abi_guid = GUID{ 0x00112233, 0x4455, 0x6677, { 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } }; STATIC_REQUIRE_GUID_EQUAL(from_abi_guid, expected); -} \ No newline at end of file +} diff --git a/test/test/inspectable_interop.cpp b/test/test/inspectable_interop.cpp index bfe46d041..e9094ca77 100644 --- a/test/test/inspectable_interop.cpp +++ b/test/test/inspectable_interop.cpp @@ -14,7 +14,14 @@ namespace } #ifdef __CRT_UUID_DECL +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif __CRT_UUID_DECL(IBadInterop, 0xed0dd761, 0xc31e, 0x4803, 0x8c, 0xf9, 0x22, 0xa2, 0xcb, 0x20, 0xec, 0x47) +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif #endif namespace @@ -26,15 +33,22 @@ namespace throw hresult_not_implemented(); } - hstring GetRuntimeClassName() + hstring GetRuntimeClassName() const { return L"Sample"; } - Windows::Foundation::TrustLevel GetTrustLevel() +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif + Windows::Foundation::TrustLevel GetTrustLevel() const noexcept { return Windows::Foundation::TrustLevel::PartialTrust; } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif int32_t __stdcall JustSayNo() noexcept final { diff --git a/test/test/main.cpp b/test/test/main.cpp index 47d65e667..1481be4dd 100644 --- a/test/test/main.cpp +++ b/test/test/main.cpp @@ -14,9 +14,9 @@ int main(int const argc, char** argv) init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); return Catch::Session().run(argc, argv); } diff --git a/test/test/multi_threaded_common.h b/test/test/multi_threaded_common.h index 971e56c6b..026cb3264 100644 --- a/test/test/multi_threaded_common.h +++ b/test/test/multi_threaded_common.h @@ -149,10 +149,10 @@ namespace concurrent_collections container const* owner; concurrency_checked_random_access_iterator() : owner(nullptr) {} - concurrency_checked_random_access_iterator(container const* c, iterator it) : owner(c), iterator(it) {} + concurrency_checked_random_access_iterator(container const* c, iterator it) : iterator(it), owner(c) {} // Implicit conversion from non-const iterator to const iterator. - concurrency_checked_random_access_iterator(concurrency_checked_random_access_iterator other) : owner(other.owner), iterator(other.inner()) { } + concurrency_checked_random_access_iterator(concurrency_checked_random_access_iterator other) : iterator(other.inner()), owner(other.owner) { } concurrency_checked_random_access_iterator(concurrency_checked_random_access_iterator const&) = default; concurrency_checked_random_access_iterator& operator=(concurrency_checked_random_access_iterator const&) = default; @@ -256,7 +256,7 @@ namespace concurrent_collections concurrency_guard() = default; concurrency_guard(concurrency_guard const& other) noexcept - : m_lock(0), hook(other.hook) + : hook(other.hook), m_lock(0) { auto guard = other.lock_nonconst(); } diff --git a/test/test/tearoff.cpp b/test/test/tearoff.cpp index 9ed622870..ac43140dd 100644 --- a/test/test/tearoff.cpp +++ b/test/test/tearoff.cpp @@ -181,7 +181,7 @@ namespace Closed = true; } - winrt::hstring GetRuntimeClassName() + winrt::hstring GetRuntimeClassName() const { return L"RuntimeClassName"; } diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index 707088cd9..e7e4b83aa 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -66,7 +66,7 @@ TEST_CASE("custom_error_logger") #endif REQUIRE(s_loggerArgs.returnAddress); - REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + REQUIRE(s_loggerArgs.result == static_cast(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) // Remove global handler winrt_throw_hresult_handler = nullptr; diff --git a/test/test_cpp20/main.cpp b/test/test_cpp20/main.cpp index 10150c369..30687e00c 100644 --- a/test/test_cpp20/main.cpp +++ b/test/test_cpp20/main.cpp @@ -14,9 +14,9 @@ int main(int const argc, char** argv) init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_fast/main.cpp b/test/test_fast/main.cpp index cb2203171..7590df7e1 100644 --- a/test/test_fast/main.cpp +++ b/test/test_fast/main.cpp @@ -10,9 +10,9 @@ int main(int const argc, char** argv) init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_fast_fwd/main.cpp b/test/test_fast_fwd/main.cpp index 88d30fba3..c5b6040f7 100644 --- a/test/test_fast_fwd/main.cpp +++ b/test/test_fast_fwd/main.cpp @@ -13,9 +13,9 @@ int main(int const argc, char** argv) init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_module_lock_custom/main.cpp b/test/test_module_lock_custom/main.cpp index 6680fdb51..862df57df 100644 --- a/test/test_module_lock_custom/main.cpp +++ b/test/test_module_lock_custom/main.cpp @@ -63,8 +63,8 @@ int main(int const argc, char** argv) { std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_module_lock_none/main.cpp b/test/test_module_lock_none/main.cpp index ad6d83ace..57e40a542 100644 --- a/test/test_module_lock_none/main.cpp +++ b/test/test_module_lock_none/main.cpp @@ -68,8 +68,8 @@ int main(int const argc, char** argv) { std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_slow/main.cpp b/test/test_slow/main.cpp index cb2203171..7590df7e1 100644 --- a/test/test_slow/main.cpp +++ b/test/test_slow/main.cpp @@ -10,9 +10,9 @@ int main(int const argc, char** argv) init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } diff --git a/test/test_win7/inspectable_interop.cpp b/test/test_win7/inspectable_interop.cpp index 95ee35522..0be7a9157 100644 --- a/test/test_win7/inspectable_interop.cpp +++ b/test/test_win7/inspectable_interop.cpp @@ -13,7 +13,14 @@ namespace } #ifdef __CRT_UUID_DECL +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif __CRT_UUID_DECL(IBadInterop, 0xed0dd761, 0xc31e, 0x4803, 0x8c, 0xf9, 0x22, 0xa2, 0xcb, 0x20, 0xec, 0x47) +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif #endif namespace @@ -25,15 +32,22 @@ namespace throw hresult_not_implemented(); } - hstring GetRuntimeClassName() + hstring GetRuntimeClassName() const { return L"Sample"; } - Windows::Foundation::TrustLevel GetTrustLevel() +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif + Windows::Foundation::TrustLevel GetTrustLevel() const noexcept { return Windows::Foundation::TrustLevel::PartialTrust; } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif int32_t __stdcall JustSayNo() noexcept final { diff --git a/test/test_win7/main.cpp b/test/test_win7/main.cpp index 10150c369..30687e00c 100644 --- a/test/test_win7/main.cpp +++ b/test/test_win7/main.cpp @@ -14,9 +14,9 @@ int main(int const argc, char** argv) init_apartment(); std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); return Catch::Session().run(argc, argv); } From a2131900b9dc9a317ea041abc2927656246089dd Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 10 Jan 2023 01:20:07 +0800 Subject: [PATCH 165/305] Add option for using custom license text (#1262) --- cppwinrt/code_writers.h | 6 ++---- cppwinrt/main.cpp | 36 +++++++++++++++++++++++++++++++++++- cppwinrt/settings.h | 1 + 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 497af4c40..c986c927f 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -24,10 +24,8 @@ namespace cppwinrt { w.write(R"(// C++/WinRT v% -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -)", CPPWINRT_VERSION_STRING); +% +)", CPPWINRT_VERSION_STRING, settings.license_template); } else { diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 16700a863..70a55b076 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -34,7 +34,7 @@ namespace cppwinrt { "?", 0, option::no_max, {}, {} }, { "library", 0, 1, "", "Specify library prefix (defaults to winrt)" }, { "filter" }, // One or more prefixes to include in input (same as -include) - { "license", 0, 0 }, // Generate license comment + { "license", 0, 1, "[]", "Generate license comment from template file" }, { "brackets", 0, 0 }, // Use angle brackets for #includes (defaults to quotes) { "fastabi", 0, 0 }, // Enable support for the Fast ABI { "ignore_velocity", 0, 0 }, // Ignore feature staging metadata and always include implementations @@ -115,6 +115,40 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder settings.exclude.insert(exclude); } + if (settings.license) + { + std::string license_arg = args.value("license"); + if (license_arg.empty()) + { + settings.license_template = R"(// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +)"; + } + else + { + std::filesystem::path template_path{ license_arg }; + std::ifstream template_file(absolute(template_path)); + if (template_file.fail()) + { + throw_invalid("Cannot read license template file '", absolute(template_path).string() + "'"); + } + std::string line_buf; + while (getline(template_file, line_buf)) + { + if (line_buf.empty()) + { + settings.license_template += "//\n"; + } + else + { + settings.license_template += "// "; + settings.license_template += line_buf; + settings.license_template += "\n"; + } + } + } + } + if (settings.component) { settings.component_overwrite = args.exists("overwrite"); diff --git a/cppwinrt/settings.h b/cppwinrt/settings.h index 7655f8cc2..e07df4ea2 100644 --- a/cppwinrt/settings.h +++ b/cppwinrt/settings.h @@ -10,6 +10,7 @@ namespace cppwinrt std::string output_folder; bool base{}; bool license{}; + std::string license_template; bool brackets{}; bool verbose{}; bool component{}; From 6ff78e4974b8ea42cbc97f6c41114f3dfb02b472 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:52:54 -0800 Subject: [PATCH 166/305] Add a mechanism to suppress `std::source_location` (#1260) --- .github/workflows/ci.yml | 6 +- build_test_all.cmd | 2 + cppwinrt.sln | 32 +- run_tests.cmd | 1 + strings/base_error.h | 4 +- strings/base_macros.h | 7 +- test/CMakeLists.txt | 1 + .../CMakeLists.txt | 48 +++ .../custom_error.cpp | 61 ++++ test/test_cpp20_no_sourcelocation/main.cpp | 26 ++ test/test_cpp20_no_sourcelocation/pch.cpp | 1 + test/test_cpp20_no_sourcelocation/pch.h | 16 + .../test_cpp20_no_sourcelocation.vcxproj | 300 ++++++++++++++++++ 13 files changed, 494 insertions(+), 11 deletions(-) create mode 100644 test/test_cpp20_no_sourcelocation/CMakeLists.txt create mode 100644 test/test_cpp20_no_sourcelocation/custom_error.cpp create mode 100644 test/test_cpp20_no_sourcelocation/main.cpp create mode 100644 test/test_cpp20_no_sourcelocation/pch.cpp create mode 100644 test/test_cpp20_no_sourcelocation/pch.h create mode 100644 test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5124d0881..cc7a854e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,7 +96,7 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_cpp20, test_win7, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_win7, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] exclude: - arch: arm64 config: Debug @@ -294,7 +294,7 @@ jobs: - name: Build tests run: | cd build - cmake --build . -j2 --target test-vanilla test_cpp20 test_win7 test_old + cmake --build . -j2 --target test-vanilla test_cpp20 test_cpp20_no_sourcelocation test_win7 test_old - name: Upload test binaries uses: actions/upload-artifact@v3 @@ -355,7 +355,7 @@ jobs: - name: Build tests run: | cd build - cmake --build . -j2 --target test-vanilla test_cpp20 test_win7 test_old + cmake --build . -j2 --target test-vanilla test_cpp20 test_cpp20_no_sourcelocation test_win7 test_old - name: Run tests run: | diff --git a/build_test_all.cmd b/build_test_all.cmd index 29acdc77f..6f7e24033 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -32,11 +32,13 @@ call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%, call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20_no_sourcelocation call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_win7 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_slow call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_module_lock_custom call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_module_lock_none +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_module_lock_none call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\old_tests\test_old call run_tests.cmd %target_platform% %target_configuration% diff --git a/cppwinrt.sln b/cppwinrt.sln index e3ce40f95..d56e050fb 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -34,9 +34,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component", "test\test EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test\test.vcxproj", "{D2961EA1-A8CA-4A62-B760-948403DC8494}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} {F1C915B3-2C64-4992-AFB7-7F035B1A7607} = {F1C915B3-2C64-4992-AFB7-7F035B1A7607} - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component_folders", "test\test_component_folders\test_component_folders.vcxproj", "{85695954-3800-4558-9857-966E69E9F9EC}" @@ -76,8 +76,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_slow", "test\test_slow EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_fast_fwd", "test\test_fast_fwd\test_fast_fwd.vcxproj", "{303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}" ProjectSection(ProjectDependencies) = postProject - {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} {0E0ACA62-A92F-44CF-BD41-AEB541946DF8} = {0E0ACA62-A92F-44CF-BD41-AEB541946DF8} + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fast_fwd", "fast_fwd\fast_fwd.vcxproj", "{A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}" @@ -86,9 +86,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scratch", "scratch\scratch. EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_none", "test\test_module_lock_none\test_module_lock_none.vcxproj", "{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}" ProjectSection(ProjectDependencies) = postProject - {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} - {13333A6F-6A4A-48CD-865C-0F65135EB018} = {13333A6F-6A4A-48CD-865C-0F65135EB018} {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E} = {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E} + {13333A6F-6A4A-48CD-865C-0F65135EB018} = {13333A6F-6A4A-48CD-865C-0F65135EB018} + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_custom", "test\test_module_lock_custom\test_module_lock_custom.vcxproj", "{08C40663-B6A3-481E-8755-AE32BAD99501}" @@ -100,9 +100,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3C7EA5F8-6 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7\test_win7.vcxproj", "{2EF696B9-7F4A-410F-AE5C-5301565C0F08}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} {F1C915B3-2C64-4992-AFB7-7F035B1A7607} = {F1C915B3-2C64-4992-AFB7-7F035B1A7607} - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp20\test_cpp20.vcxproj", "{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}" @@ -110,6 +110,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocation", "test\test_cpp20_no_sourcelocation\test_cpp20_no_sourcelocation.vcxproj", "{D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -458,6 +463,22 @@ Global {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.Build.0 = Release|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.ActiveCfg = Release|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.Build.0 = Release|Win32 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.ActiveCfg = Debug|ARM + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.Build.0 = Debug|ARM + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.Build.0 = Debug|ARM64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.ActiveCfg = Debug|x64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.Build.0 = Debug|x64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.ActiveCfg = Debug|Win32 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.Build.0 = Debug|Win32 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.ActiveCfg = Release|ARM + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.Build.0 = Release|ARM + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.ActiveCfg = Release|ARM64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.Build.0 = Release|ARM64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.ActiveCfg = Release|x64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.Build.0 = Release|x64 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.ActiveCfg = Release|Win32 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -481,6 +502,7 @@ Global {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {2EF696B9-7F4A-410F-AE5C-5301565C0F08} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/run_tests.cmd b/run_tests.cmd index cde12b1ec..71a9d1294 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -10,6 +10,7 @@ if "%target_configuration%"=="" set target_configuration=Debug call :run_test test call :run_test test_cpp20 +call :run_test test_cpp20_no_sourcelocation call :run_test test_win7 call :run_test test_fast call :run_test test_slow diff --git a/strings/base_error.h b/strings/base_error.h index b375d3913..98bb8e899 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -319,7 +319,7 @@ WINRT_EXPORT namespace winrt // information is available on the caller who generated the error. if (winrt_throw_hresult_handler) { -#ifdef __cpp_lib_source_location +#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), code); #else winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), code); @@ -448,7 +448,7 @@ WINRT_EXPORT namespace winrt { if (winrt_throw_hresult_handler) { -#ifdef __cpp_lib_source_location +#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), result); #else winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), result); diff --git a/strings/base_macros.h b/strings/base_macros.h index 1dd63c111..deea7e7c1 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -81,7 +81,10 @@ typedef struct _GUID GUID; // to be the calling code, not cppwinrt itself, so that it is useful to developers building on top of this library. As a // result any public-facing method that can result in an error needs a default-constructed source_location argument. Because // this type does not exist in C++17 we need to use a macro to optionally add parameters and forwarding wherever appropriate. -#ifdef __cpp_lib_source_location +// +// Some projects may decide to disable std::source_location support to prevent source code information from ending up in their +// release binaries, or to reduce binary size. Defining WINRT_NO_SOURCE_LOCATION will prevent this feature from activating. +#if defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) #define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , std::source_location const& sourceInformation #define WINRT_IMPL_SOURCE_LOCATION_ARGS , std::source_location const& sourceInformation = std::source_location::current() #define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM std::source_location const& sourceInformation = std::source_location::current() @@ -89,6 +92,8 @@ typedef struct _GUID GUID; #define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation #define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation +#define WINRT_SOURCE_LOCATION_ACTIVE + #ifdef _MSC_VER #pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true") #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d4bb3e125..d9c720a80 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -106,6 +106,7 @@ set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.") add_subdirectory(test) add_subdirectory(test_cpp20) +add_subdirectory(test_cpp20_no_sourcelocation) add_subdirectory(test_win7) if(HAS_WINDOWSNUMERICS) diff --git a/test/test_cpp20_no_sourcelocation/CMakeLists.txt b/test/test_cpp20_no_sourcelocation/CMakeLists.txt new file mode 100644 index 000000000..1944aece8 --- /dev/null +++ b/test/test_cpp20_no_sourcelocation/CMakeLists.txt @@ -0,0 +1,48 @@ +set(CMAKE_CXX_STANDARD 20) +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # std::format, std::ranges::is_heap, std::views::reverse, std::ranges::max + # are experimental in libc++ as of Clang 15. + # FIXME: Should probably use compile test instead? + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library") +endif() + +if(ENABLE_TEST_SANITIZERS) + # As of LLVM 15, custom_error.cpp doesn't build with ASAN due to: + # error: cannot make section .ASAN$GL associative with sectionless symbol _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4nposE + set_source_files_properties(custom_error.cpp PROPERTIES COMPILE_OPTIONS "-fno-sanitize=address") + set_source_files_properties(custom_error.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS true) +endif() + +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +list(APPEND BROKEN_TESTS + # No broken tests. +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_cpp20_no_sourcelocation main.cpp ${TEST_SRCS}) + +target_compile_definitions(test_cpp20_no_sourcelocation PRIVATE WINRT_NO_SOURCE_LOCATION) + +target_precompile_headers(test_cpp20_no_sourcelocation PRIVATE pch.h) +set_source_files_properties( + main.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_cpp20_no_sourcelocation build-cppwinrt-projection) + +add_test( + NAME test_cpp20_no_sourcelocation + COMMAND "$" ${TEST_COLOR_ARG} +) diff --git a/test/test_cpp20_no_sourcelocation/custom_error.cpp b/test/test_cpp20_no_sourcelocation/custom_error.cpp new file mode 100644 index 000000000..43e5f16d9 --- /dev/null +++ b/test/test_cpp20_no_sourcelocation/custom_error.cpp @@ -0,0 +1,61 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; + +namespace +{ + static bool s_loggerCalled = false; + + // Note that we are checking that the source line number matches expectations. If lines above this are changed + // then this value needs to change as well. + void FailOnLine15() + { + // Validate that handler translated exception + REQUIRE_THROWS_AS(check_hresult(0x80000018), hresult_illegal_delegate_assignment); + } + + static struct { + uint32_t lineNumber; + char const* fileName; + char const* functionName; + void* returnAddress; + winrt::hresult result; + } s_loggerArgs{}; + + void __stdcall logger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept + { + s_loggerArgs = { + .lineNumber = lineNumber, + .fileName = fileName, + .functionName = functionName, + .returnAddress = returnAddress, + .result = result, + }; + s_loggerCalled = true; + } +} + +TEST_CASE("custom_error_logger") +{ + // Set up global handler + REQUIRE(!s_loggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = logger; + + FailOnLine15(); + REQUIRE(s_loggerCalled); + // In C++20 these fields should be filled in by std::source_location. However, this binary has + // specified WINRT_NO_SOURCE_LOCATION so that support should be removed. As a result these should + // return the same (empty) values as C++17. + REQUIRE(s_loggerArgs.lineNumber == 0); + REQUIRE(s_loggerArgs.fileName == nullptr); + REQUIRE(s_loggerArgs.functionName == nullptr); + + REQUIRE(s_loggerArgs.returnAddress); + REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + + // Remove global handler + winrt_throw_hresult_handler = nullptr; + s_loggerCalled = false; +} diff --git a/test/test_cpp20_no_sourcelocation/main.cpp b/test/test_cpp20_no_sourcelocation/main.cpp new file mode 100644 index 000000000..10150c369 --- /dev/null +++ b/test/test_cpp20_no_sourcelocation/main.cpp @@ -0,0 +1,26 @@ +#include +#define CATCH_CONFIG_RUNNER + +// Force reportFatal to be available on mingw-w64 +#define CATCH_CONFIG_WINDOWS_SEH + +#include "catch.hpp" +#include "winrt/base.h" + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_cpp20_no_sourcelocation/pch.cpp b/test/test_cpp20_no_sourcelocation/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_cpp20_no_sourcelocation/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_cpp20_no_sourcelocation/pch.h b/test/test_cpp20_no_sourcelocation/pch.h new file mode 100644 index 000000000..6565bea1b --- /dev/null +++ b/test/test_cpp20_no_sourcelocation/pch.h @@ -0,0 +1,16 @@ +#pragma once + +#pragma warning(4: 4458) // ensure we compile clean with this warning enabled + +#define WINRT_LEAN_AND_MEAN +#include +#include "winrt/Windows.Data.Json.h" +#include "winrt/Windows.Foundation.h" +#include "winrt/Windows.Foundation.Collections.h" +#include "winrt/Windows.Foundation.Numerics.h" +#include +#include "catch.hpp" + +#include + +using namespace std::literals; diff --git a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj new file mode 100644 index 000000000..c71cfdc96 --- /dev/null +++ b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj @@ -0,0 +1,300 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} + unittests + test_cpp20_no_sourcelocation + 20 + + + + Application + true + + + Application + true + + + Application + true + + + Application + false + true + + + Application + false + true + + + Application + false + true + + + Application + true + + + Application + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + WINRT_NO_SOURCE_LOCATION;%(PreprocessorDefinitions) + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + + + Console + true + true + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + + + Console + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + + + Console + true + true + + + + + + + + + + + + + + + + + NotUsing + + + Create + + + + + + \ No newline at end of file From b5503ee594cbd01f911c222f9367d327cb885bf8 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 17 Jan 2023 13:03:24 -0600 Subject: [PATCH 167/305] issue template --- .github/ISSUE_TEMPLATE/bug_report.yml | 54 +++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 8 ++++ 2 files changed, 62 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..03cd0d44b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,54 @@ +name: Bug report +description: File a bug report about cppwinrt +title: "Bug:" +labels: [bug] +assignees: [] +body: + - type: markdown + attributes: + value: "Thank you for filing a bug report! 🐛" + - type: input + attributes: + label: Version + description: What is the version of cppwinrt you're using? + placeholder: You can find the exact version by running `cppwinrt.exe`. + - type: textarea + attributes: + label: Summary + description: > + Please provide a short summary of the bug, along with any information + you feel relevant to replicating the bug. + - type: textarea + attributes: + label: Reproducible example + description: > + Please provide all code needed to reproduce the issue. + placeholder: | + #include "winrt/Windows.Foundation.h" + + using namespace winrt; + using namespace Windows::Foundation; + + int main() + { + Uri uri(L"https://kennykerr.ca"); + printf("%ls\n", uri.ToString().c_str()); + } + render: rust + - type: textarea + attributes: + label: Expected behavior + description: "I expected to see this happen:" + - type: textarea + attributes: + label: Actual behavior + description: "Instead, this happened:" + - type: textarea + attributes: + label: Additional comments + description: Is there anything else you'd like to share? + validations: + required: false + - type: markdown + attributes: + value: "Thank you! ©️➕➕" diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..d32d2339d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Visual Studio or C++ question + url: https://developercommunity.visualstudio.com/cpp + about: Your open channel to Microsoft engineering teams + - name: Windows API question + url: https://docs.microsoft.com/en-us/answers/topics/windows-api.html + about: Please ask questions about the Windows API on Microsoft Q&A From e38b0801a8c12c0d07f16cb91581814425e8045f Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Mon, 30 Jan 2023 21:42:59 +0800 Subject: [PATCH 168/305] Enable cpp20/custom_error for incoming LLVM 16 (#1265) Tested with a recent llvm-mingw build very close to LLVM 16 rc1. --- test/test_cpp20/custom_error.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index e7e4b83aa..bdb88dcd3 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -36,11 +36,14 @@ namespace } } -#if defined(__clang__) +#if defined(__clang__) && defined(_MSC_VER) // FIXME: Blocked on __cpp_consteval, see: // * https://github.com/microsoft/cppwinrt/pull/1203#issuecomment-1279764927 // * https://github.com/llvm/llvm-project/issues/57094 TEST_CASE("custom_error_logger", "[!shouldfail]") +#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000 +// not available in libc++ before LLVM 16 +TEST_CASE("custom_error_logger", "[!shouldfail]") #else TEST_CASE("custom_error_logger") #endif @@ -61,6 +64,8 @@ TEST_CASE("custom_error_logger") REQUIRE(!functionNameSv.empty()); #if defined(__GNUC__) && !defined(__clang__) REQUIRE(functionNameSv == "void {anonymous}::FailOnLine15()"); +#elif defined(__GNUC__) && defined(__clang__) + REQUIRE(functionNameSv == "void (anonymous namespace)::FailOnLine15()"); #else REQUIRE(functionNameSv == "FailOnLine15"); #endif From d68a8c7bd998d4874445bdebe788d64627d623f0 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 31 Jan 2023 16:19:28 -0800 Subject: [PATCH 169/305] Move build pipeline into YAML (#1268) Among other things, this will allow the C++/WinRT build pipeline to stay synchronized with the product code. --- .pipelines/build.yml | 646 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 .pipelines/build.yml diff --git a/.pipelines/build.yml b/.pipelines/build.yml new file mode 100644 index 000000000..8cc369d6d --- /dev/null +++ b/.pipelines/build.yml @@ -0,0 +1,646 @@ +# 'Allow scripts to access the OAuth token' was selected in pipeline. Add the following YAML to any steps requiring access: +# env: +# MY_ACCESS_TOKEN: $(System.AccessToken) +# Variable 'MajorVersion' was defined in the Variables tab +# Variable 'MinorVersion' was defined in the Variables tab +trigger: + branches: + include: + - refs/heads/master + batch: True +schedules: +- cron: 0 18 * * * + branches: + include: + - refs/heads/master +name: $(MajorVersion).$(MinorVersion).$(date:yyMMdd)$(rev:.r) + +variables: + manualRelease: $[and(eq(variables['BuildConfiguration'], 'release'), in(variables['Build.Reason'], 'Manual'))] + +jobs: +- job: BuildBinaries + pool: + name: Azure Pipelines + vmImage: 'windows-2022' + demands: + - msbuild + strategy: + matrix: + x86: + buildPlatform: 'x86' + x64: + buildPlatform: 'x64' + arm: + buildPlatform: 'arm' + arm64: + buildPlatform: 'arm64' + + steps: + - checkout: self + clean: true + persistCredentials: True + + - task: NuGetToolInstaller@1 + displayName: Use NuGet 6.0.2 + continueOnError: True + inputs: + versionSpec: 6.0.2 + + - task: NuGetCommand@2 + displayName: NuGet restore + + - task: CmdLine@2 + displayName: Build Tools + inputs: + script: | + if "%VSCMD_VER%"=="" ( + pushd c: + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" >nul 2>&1 + popd + ) + + build_test_all.cmd $(BuildPlatform) $(BuildConfiguration) $(Build.BuildNumber) true + failOnStderr: true + + - task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + condition: eq(variables['BuildPlatform'], 'x64') + + - task: PublishTestResults@2 + displayName: Publish Test Results + enabled: False + + - task: CopyFiles@2 + displayName: Stage cppwinrt.* + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables.manualRelease, 'true')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) + Contents: | + cppwinrt.exe + cppwinrt.pdb + TargetFolder: $(Build.ArtifactStagingDirectory)\cppwinrt + + - task: CopyFiles@2 + displayName: Stage Component cppwinrtvisualizer.* + condition: $[and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')), eq(variables.manualRelease, 'true'))] + inputs: + SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Component + Contents: | + cppwinrtvisualizer.dll + cppwinrtvisualizer.pdb + cppwinrtvisualizer.vsdconfig + TargetFolder: $(Build.ArtifactStagingDirectory)\Component + + - task: CopyFiles@2 + displayName: Stage Standalone cppwinrtvisualizer.* + condition: $[and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')), eq(variables.manualRelease, 'true'))] + inputs: + SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Standalone + Contents: | + cppwinrtvisualizer.dll + cppwinrtvisualizer.pdb + cppwinrtvisualizer.vsdconfig + TargetFolder: $(Build.ArtifactStagingDirectory)\Standalone + + - task: CopyFiles@2 + displayName: Stage cppwinrt_fast_forwarder.lib + condition: eq(variables.manualRelease, 'true') + inputs: + SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) + Contents: cppwinrt_fast_forwarder.lib + TargetFolder: $(Build.ArtifactStagingDirectory) + + - task: ManifestGeneratorTask@0 + displayName: 'Manifest Generator ' + condition: and(eq(variables['BuildPlatform'], 'x86'), eq(variables.manualRelease, 'true')) + inputs: + BuildDropPath: $(Build.ArtifactStagingDirectory)\cppwinrt + + - task: PublishPipelineArtifact@0 + displayName: Publish Artifacts + condition: eq(variables.manualRelease, 'true') + inputs: + artifactName: $(BuildConfiguration)_$(BuildPlatform) + targetPath: $(Build.ArtifactStagingDirectory) + + - task: PublishSymbols@2 + displayName: Publish symbols + condition: eq(variables.manualRelease, 'true') + inputs: + SymbolsFolder: $(Build.ArtifactStagingDirectory) + SearchPattern: '**/*.pdb' + SymbolServerType: TeamServices + SymbolsProduct: CppWinRT + +- job: BuildInternal + displayName: Build Internal Packages (VPacks) + dependsOn: BuildBinaries + condition: and(succeeded(), ne(variables['SkipInternalPackages'], 'true'), eq(variables.manualRelease, 'true')) + pool: + name: Azure Pipelines + vmImage: 'windows-2022' + steps: + - checkout: self + clean: true + persistCredentials: True + + - task: PkgESSetupBuild@12 + displayName: Package ES - Setup Build + inputs: + branchVersionExcludeBranch: master + disableWorkspace: true + disableMsbuildVersion: true + disableBuildTools: true + + - task: DownloadPipelineArtifact@1 + displayName: Download x86 Artifacts + inputs: + artifactName: $(BuildConfiguration)_x86 + downloadPath: $(Build.SourcesDirectory)\x86 + + - task: DownloadPipelineArtifact@1 + displayName: Download x64 Artifacts + inputs: + artifactName: $(BuildConfiguration)_x64 + downloadPath: $(Build.SourcesDirectory)\x64 + + - task: DownloadPipelineArtifact@1 + displayName: Download arm Artifacts + inputs: + artifactName: $(BuildConfiguration)_arm + downloadPath: $(Build.SourcesDirectory)\arm + + - task: DownloadPipelineArtifact@1 + displayName: Download arm64 Artifacts + inputs: + artifactName: $(BuildConfiguration)_arm64 + downloadPath: $(Build.SourcesDirectory)\arm64 + + - task: CmdLine@2 + displayName: Parse PatchVersion + inputs: + script: 'for /f "tokens=3,4 delims=." %%i in ("$(Build.BuildNumber)") do @echo ##vso[task.setvariable variable=PatchVersion;]%%i%%j ' + failOnStderr: true + + - task: CmdLine@2 + displayName: Copy compiler contents for internal signing + inputs: + script: | + md $(Build.SourcesDirectory)\x86\tempsign + echo Build Sources Directory: + dir $(Build.SourcesDirectory) + echo x86 + dir $(Build.SourcesDirectory)\x86 + echo cppwinrt + dir $(Build.SourcesDirectory)\x86\cppwinrt + xcopy $(Build.SourcesDirectory)\x86\cppwinrt\*.* $(Build.SourcesDirectory)\x86\tempsign /icefzy + + - task: EsrpCodeSigning@2 + displayName: Sign Compiler vPack for internal use + inputs: + ConnectedServiceName: bf601a97-455d-4977-b248-07b90c96eed9 + FolderPath: $(Build.SourcesDirectory)\x86\tempsign + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-458204", + "OperationCode" : "SigntoolSign", + "Parameters" : { + "OpusName" : "Windows Build Tools Internal", + "OpusInfo" : "http://www.microsoft.com", + "FileDigest" : "/fd \"SHA256\"", + "PageHash" : "/NPH", + "TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + }, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-458204", + "OperationCode" : "SigntoolVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + + - task: PkgESVPack@12 + displayName: 'Publish Compiler VPack ' + inputs: + serviceType: drop + versionAs: parts + sourceDirectory: $(Build.SourcesDirectory)\x86\tempsign + description: C++/WinRT Compiler + pushPkgName: CppWinRT.Compiler + target: $(OSBuildToolsRoot)\cppwinrt + provData: false + majorVer: $(MajorVersion) + minorVer: $(MinorVersion) + patchVer: $(PatchVersion) + prereleaseVer: $(Build.SourceBranchName).x86.$(BuildConfiguration).$(Build.BuildNumber).$(Build.SourceVersion) + signSbom: false + + - task: CmdLine@2 + displayName: Delete internal compiler copy + inputs: + script: | + rd $(Build.SourcesDirectory)\x86\tempsign /q /s + + - task: CopyFiles@2 + displayName: Stage CppWinRT.Compiler.man + inputs: + SourceFolder: $(XES_VPACKMANIFESTDIRECTORY) + Contents: $(XES_VPACKMANIFESTNAME) + TargetFolder: $(Build.ArtifactStagingDirectory) + + - task: CmdLine@2 + displayName: Stage MSBuild vpack + inputs: + script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" + failOnStderr: true + + - task: PkgESVPack@12 + displayName: Publish MSBuild VPack + inputs: + serviceType: drop + versionAs: parts + sourceDirectory: $(Build.SourcesDirectory)\msbuild + description: C++/WinRT MSBuild + pushPkgName: CppWinRT.MSBuild + target: $(OSBuildToolsRoot)\cppwinrt + provData: false + majorVer: $(MajorVersion) + minorVer: $(MinorVersion) + patchVer: $(PatchVersion) + prereleaseVer: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) + signSbom: false + + - task: CopyFiles@2 + displayName: Stage CppWinRT.MSBuild.man + inputs: + SourceFolder: $(XES_VPACKMANIFESTDIRECTORY) + Contents: $(XES_VPACKMANIFESTNAME) + TargetFolder: $(Build.ArtifactStagingDirectory) + + - task: CmdLine@2 + displayName: Stage OSBuildTools.Manifest Update + enabled: False + inputs: + script: | + copy $(Build.SourcesDirectory)\src\package\cppwinrt\vpack\GitCheckin.json + copy $(Build.SourcesDirectory)\vpack\*.man OSBuildTools.Manifest.Update + type OSBuildTools.Manifest.Update + workingDirectory: $(Build.ArtifactStagingDirectory) + failOnStderr: true + + - task: PublishPipelineArtifact@0 + displayName: Publish Update Manifests + inputs: + artifactName: VPack + targetPath: $(Build.ArtifactStagingDirectory) + +- job: BuildExternal + displayName: Build External Packages (NuGet, VSIX) + cancelTimeoutInMinutes: 1 + dependsOn: BuildBinaries + condition: and(succeeded(), eq(variables.manualRelease, 'true')) + pool: + name: Azure Pipelines + vmImage: 'windows-2022' + steps: + - checkout: self + clean: true + persistCredentials: True + + - task: NuGetToolInstaller@1 + displayName: Use NuGet 6.0.2 + continueOnError: True + inputs: + versionSpec: 6.0.2 + + - task: NuGetCommand@2 + displayName: NuGet restore + + - task: DownloadPipelineArtifact@1 + displayName: Download x86 Artifacts + inputs: + artifactName: $(BuildConfiguration)_x86 + downloadPath: $(Build.SourcesDirectory)\x86 + + - task: DownloadPipelineArtifact@1 + displayName: Download x64 Artifacts + inputs: + artifactName: $(BuildConfiguration)_x64 + downloadPath: $(Build.SourcesDirectory)\x64 + + - task: DownloadPipelineArtifact@1 + displayName: Download arm Artifacts + inputs: + artifactName: $(BuildConfiguration)_arm + downloadPath: $(Build.SourcesDirectory)\arm + + - task: DownloadPipelineArtifact@1 + displayName: Download arm64 Artifacts + inputs: + artifactName: $(BuildConfiguration)_arm64 + downloadPath: $(Build.SourcesDirectory)\arm64 + + - task: EsrpCodeSigning@2 + displayName: ESRP CodeSigning NatVis + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.SourcesDirectory) + Pattern: | + x86\cppwinrt\cppwinrt.exe + x86\Component\cppwinrtvisualizer.dll + x64\Component\cppwinrtvisualizer.dll + arm64\Component\cppwinrtvisualizer.dll + x86\Standalone\cppwinrtvisualizer.dll + x64\Standalone\cppwinrtvisualizer.dll + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd sha256" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "signtool.exe", + "toolVersion": "6.2.9304.0" + } + ] + + - task: CmdLine@2 + displayName: Stage Signed Binaries + inputs: + script: | + echo F|xcopy /S /Q /Y /F x86\cppwinrt\cppwinrt.exe $(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe + echo F|xcopy /S /Q /Y /F x86\Component\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x86\Component\cppwinrtvisualizer.dll + echo F|xcopy /S /Q /Y /F x64\Component\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x64\Component\cppwinrtvisualizer.dll + echo F|xcopy /S /Q /Y /F arm64\Component\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\arm64\Component\cppwinrtvisualizer.dll + echo F|xcopy /S /Q /Y /F x86\Standalone\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x86\Standalone\cppwinrtvisualizer.dll + echo F|xcopy /S /Q /Y /F x64\Standalone\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\x64\Standalone\cppwinrtvisualizer.dll + echo F|xcopy /S /Q /Y /F arm64\Standalone\cppwinrtvisualizer.dll $(Build.ArtifactStagingDirectory)\arm64\Standalone\cppwinrtvisualizer.dll + workingDirectory: $(Build.SourcesDirectory) + failOnStderr: true + + - task: CmdLine@2 + displayName: Stage cppwinrtvisualizer.vsdconfig + inputs: + script: | + copy $(Build.SourcesDirectory)\x86\Component\cppwinrtvisualizer.vsdconfig x86\Component\cppwinrtvisualizer.vsdconfig + copy $(Build.SourcesDirectory)\x86\Standalone\cppwinrtvisualizer.vsdconfig x86\Standalone\cppwinrtvisualizer.vsdconfig + workingDirectory: $(Build.ArtifactStagingDirectory) + failOnStderr: true + + - task: NuGetCommand@2 + displayName: Build NuGet + inputs: + command: pack + searchPatternPack: nuget/Microsoft.Windows.CppWinRT.nuspec + versioningScheme: byBuildNumber + buildProperties: 'cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' + + - task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + + - task: EsrpCodeSigning@2 + displayName: ESRP CodeSigning Nuget Package + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.ArtifactStagingDirectory) + Pattern: Microsoft.Windows.CppWinRT.*.nupkg + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetSign", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-401405", + "OperationCode" : "NuGetVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + + - task: PkgESNuGetPublisher@0 + displayName: Publish NuGet Package + inputs: + searchPattern: $(System.ArtifactsDirectory)\Microsoft.Windows.CppWinRT.$(Build.BuildNumber).nupkg + nuGetFeedType: internal + feedName: https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json + + - task: VSBuild@1 + displayName: Build Component VSIXes + inputs: + solution: vsix/vsix.sln + msbuildArgs: /p:Deployment=Component,CppWinRTVersion=$(Build.BuildNumber),NatvisDirx86=$(Build.ArtifactStagingDirectory)\x86\Component\,NatvisDirx64=$(Build.ArtifactStagingDirectory)\x64\Component\,NatvisDirarm64=$(Build.ArtifactStagingDirectory)\arm64\Component\,NupkgDir=$(Build.ArtifactStagingDirectory) /restore + platform: Any CPU + configuration: Release + + - task: ExtractFiles@1 + displayName: Extract Component VSIX files for signing + inputs: + archiveFilePatterns: $(Build.SourcesDirectory)\vsix\Dev17\bin\Release\Component\Microsoft.Windows.CppWinRT.Dev17.vsix + destinationFolder: $(Agent.TempDirectory)\Microsoft.Windows.CppWinRT.Dev17.vsix + overwriteExistingFiles: true + + - task: EsrpCodeSigning@2 + displayName: ESRP CodeSign VSIX contents + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Agent.TempDirectory)\Microsoft.Windows.CppWinRT.Dev17.vsix + Pattern: '**/Microsoft.Windows.CppWinRT.*.dll' + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "keyCode": "CP-230012", + "operationSetCode": "SigntoolSign", + "parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd sha256" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "toolName": "signtool.exe", + "toolVersion": "6.2.9304.0" + } + ] + - task: ArchiveFiles@2 + displayName: Repack signed VSIX contents + inputs: + rootFolderOrFile: $(Agent.TempDirectory)\Microsoft.Windows.CppWinRT.Dev17.vsix + includeRootFolder: false + archiveFile: $(Build.SourcesDirectory)\vsix\Dev17\bin\Release\Component\Microsoft.Windows.CppWinRT.Dev17.vsix + + - task: VSBuild@1 + displayName: Build Standalone VSIXes + inputs: + solution: vsix/vsix.sln + msbuildArgs: /p:Deployment=Standalone,CppWinRTVersion=$(Build.BuildNumber),NatvisDirx86=$(Build.ArtifactStagingDirectory)\x86\Standalone\,NatvisDirx64=$(Build.ArtifactStagingDirectory)\x64\Standalone\,NatvisDirarm64=$(Build.ArtifactStagingDirectory)\arm64\Standalone\,NupkgDir=$(Build.ArtifactStagingDirectory) /restore + platform: x86 + configuration: Release + + - task: EsrpCodeSigning@2 + displayName: ESRP CodeSigning VSIX + inputs: + ConnectedServiceName: 81cc6790-027c-4ef3-928d-65e8b96a691a + FolderPath: $(Build.SourcesDirectory)\vsix\ + Pattern: | + Dev16\bin\Release\Component\Microsoft.Windows.CppWinRT.vsix + Dev16\bin\Release\Standalone\Microsoft.Windows.CppWinRT.vsix + Dev17\bin\Release\Component\Microsoft.Windows.CppWinRT.Dev17.vsix + Dev17\bin\Release\Standalone\Microsoft.Windows.CppWinRT.Dev17.vsix + UseMinimatch: true + signConfigType: inlineSignParams + inlineOperation: | + [ + { + "KeyCode" : "CP-233016", + "OperationCode" : "OpcSign", + "Parameters" : { + "FileDigest" : "/fd SHA256" + }, + "ToolName" : "sign", + "ToolVersion" : "1.0" + }, + { + "KeyCode" : "CP-233016", + "OperationCode" : "OpcVerify", + "Parameters" : {}, + "ToolName" : "sign", + "ToolVersion" : "1.0" + } + ] + + - task: CmdLine@2 + displayName: Stage Component VSIX (Dev17) + inputs: + script: | + echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.vsix $(Build.ArtifactStagingDirectory)\Component\Dev17\Microsoft.Windows.CppWinRT.Dev17.vsix + echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.json $(Build.ArtifactStagingDirectory)\Component\Dev17\Microsoft.Windows.CppWinRT.Dev17.json + echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.pdb $(Build.ArtifactStagingDirectory)\Component\Dev17\Microsoft.Windows.CppWinRT.Dev17.pdb + workingDirectory: $(Build.SourcesDirectory)\vsix\Dev17\bin\Release\Component + failOnStderr: true + + - task: CopyFiles@2 + displayName: Stage Component VSIX Manifest (Dev17) + inputs: + SourceFolder: $(Build.SourcesDirectory)\vsix + Contents: | + extension.manifest.json + overview.md + TargetFolder: $(Build.ArtifactStagingDirectory)\Component\Dev17 + OverWrite: true + + - task: CmdLine@2 + displayName: Stage Standalone VSIX (Dev16) + inputs: + script: echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.vsix $(Build.ArtifactStagingDirectory)\Standalone\Dev16\Microsoft.Windows.CppWinRT.vsix + workingDirectory: $(Build.SourcesDirectory)\vsix\Dev16\bin\$(BuildConfiguration)\Standalone + failOnStderr: true + + - task: CopyFiles@2 + displayName: Stage Standalone VSIX Manifest (Dev16) + inputs: + SourceFolder: $(Build.SourcesDirectory)\vsix + Contents: | + extension.manifest.json + overview.md + TargetFolder: $(Build.ArtifactStagingDirectory)\Standalone\Dev16 + OverWrite: true + + - task: CmdLine@2 + displayName: Stage Standalone VSIX (Dev17) + inputs: + script: echo F|xcopy /S /Q /Y /F Microsoft.Windows.CppWinRT.Dev17.vsix $(Build.ArtifactStagingDirectory)\Standalone\Dev17\Microsoft.Windows.CppWinRT.Dev17.vsix + workingDirectory: $(Build.SourcesDirectory)\vsix\Dev17\bin\$(BuildConfiguration)\Standalone + failOnStderr: true + + - task: CopyFiles@2 + displayName: Stage Standalone VSIX Manifest (Dev17) + inputs: + SourceFolder: $(Build.SourcesDirectory)\vsix + Contents: | + extension.manifest.json + overview.md + TargetFolder: $(Build.ArtifactStagingDirectory)\Standalone\Dev17 + OverWrite: true + + - task: ManifestGeneratorTask@0 + displayName: SBOM for Dev16 + inputs: + BuildDropPath: $(Build.ArtifactStagingDirectory)\Standalone\Dev16 + + - task: ManifestGeneratorTask@0 + displayName: SBOM for Dev17 Standalone + inputs: + BuildDropPath: $(Build.ArtifactStagingDirectory)\Standalone\Dev17 + + - task: ManifestGeneratorTask@0 + displayName: SBOM for Dev17 Component + inputs: + BuildDropPath: $(Build.ArtifactStagingDirectory)\Component\Dev17 + + - task: PublishPipelineArtifact@0 + displayName: Publish VSIX + inputs: + artifactName: Publish + targetPath: $(Build.ArtifactStagingDirectory) + + - task: PublishSymbols@2 + displayName: Publish Component VSIX symbols + inputs: + SymbolsFolder: $(Build.ArtifactStagingDirectory) + SearchPattern: '**/Microsoft.Windows.CppWinRT.Dev17.pdb' + SymbolServerType: TeamServices + SymbolsProduct: CppWinRT +... From ed69c4b4d62a40b11da09d5c6f3e7abdac8941e7 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 31 Jan 2023 23:26:03 -0800 Subject: [PATCH 170/305] Fix typo in build.yml --- .pipelines/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pipelines/build.yml b/.pipelines/build.yml index 8cc369d6d..817ab9fa3 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -83,7 +83,7 @@ jobs: - task: CopyFiles@2 displayName: Stage Component cppwinrtvisualizer.* - condition: $[and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')), eq(variables.manualRelease, 'true'))] + condition: and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')), eq(variables.manualRelease, 'true')) inputs: SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Component Contents: | @@ -94,7 +94,7 @@ jobs: - task: CopyFiles@2 displayName: Stage Standalone cppwinrtvisualizer.* - condition: $[and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')), eq(variables.manualRelease, 'true'))] + condition: and(or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')), eq(variables.manualRelease, 'true')) inputs: SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Standalone Contents: | From 047c179f15fefd227c142bd4ab98b51bebd0ffb2 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Sun, 5 Feb 2023 16:21:16 -0500 Subject: [PATCH 171/305] Make the formatter for IStringable const (#1270) --- strings/base_stringable_format.h | 2 +- strings/base_stringable_format_1.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/strings/base_stringable_format.h b/strings/base_stringable_format.h index 86c5acfc6..e8f51c3f2 100644 --- a/strings/base_stringable_format.h +++ b/strings/base_stringable_format.h @@ -1,7 +1,7 @@ #ifdef __cpp_lib_format template -auto std::formatter::format(winrt::Windows::Foundation::IStringable const& obj, FormatContext& fc) +auto std::formatter::format(winrt::Windows::Foundation::IStringable const& obj, FormatContext& fc) const { return std::formatter::format(obj.ToString(), fc); } diff --git a/strings/base_stringable_format_1.h b/strings/base_stringable_format_1.h index 6a7becdfc..82e6afa38 100644 --- a/strings/base_stringable_format_1.h +++ b/strings/base_stringable_format_1.h @@ -4,6 +4,6 @@ template <> struct std::formatter : std::formatter { template - auto format(winrt::Windows::Foundation::IStringable const& obj, FormatContext& fc); + auto format(winrt::Windows::Foundation::IStringable const& obj, FormatContext& fc) const; }; #endif From 3bbee2cf2c8da944a29f493c42f06ce57086f28f Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 6 Feb 2023 10:36:11 -0600 Subject: [PATCH 172/305] Workaround for false positive code analysis warning (#1269) --- strings/base_implements.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index 80a69faa7..e545b2a57 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1190,8 +1190,7 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->get_source(); } - com_ptr weak_ref; - *weak_ref.put() = new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)); + com_ptr weak_ref(new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)), take_ownership_from_abi); if (!weak_ref) { From 4363e5c37a4790c128eebb9261c71e672cec5dc6 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Wed, 8 Feb 2023 10:04:42 -0800 Subject: [PATCH 173/305] Stack usage reduction in apartment switching, and lifetime fixes (#1272) --- strings/base_coroutine_foundation.h | 8 ++++--- strings/base_coroutine_threadpool.h | 19 +++++++++++---- test/test/await_completed.cpp | 37 +++++++++++++++++++++++++++++ test/test_cpp20/await_completed.cpp | 14 +++++++++++ 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 6afeff607..1cfde4230 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -135,9 +135,12 @@ namespace winrt::impl } else { - resume_apartment(m_context, std::exchange(m_handle, {}), &m_awaiter->failure); + auto handle = std::exchange(m_handle, {}); + if (!resume_apartment(m_context, handle, &m_awaiter->failure)) + { + handle.resume(); + } } - } }; @@ -182,7 +185,6 @@ namespace winrt::impl private: auto register_completed_callback(coroutine_handle<> handle) { - auto extend_lifetime = async; async.Completed(disconnect_aware_handler(this, handle)); #ifdef _RESUMABLE_FUNCTIONS_SUPPORTED if (!suspending.exchange(false, std::memory_order_acquire)) diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index fb23f24c9..aa8a5b2b1 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -118,19 +118,22 @@ namespace winrt::impl WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) { - handle(); + return false; } else if (context.m_context_type == 1 /* APTTYPE_MTA */) { resume_background(handle); + return true; } else if (is_sta_thread()) { resume_apartment_on_threadpool(context.m_context, handle, failure); + return true; } else { resume_apartment_sync(context.m_context, handle, failure); + return true; } } } @@ -315,7 +318,7 @@ namespace winrt::impl { struct apartment_awaiter { - apartment_context context; // make a copy because resuming may destruct the original + apartment_context const& context; int32_t failure = 0; bool await_ready() const noexcept @@ -328,9 +331,17 @@ namespace winrt::impl check_hresult(failure); } - void await_suspend(impl::coroutine_handle<> handle) + auto await_suspend(impl::coroutine_handle<> handle) { - impl::resume_apartment(context.context, handle, &failure); + auto context_copy = context; +#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED + if (!impl::resume_apartment(context_copy.context, handle, &failure)) + { + handle.resume(); + } +#else + return impl::resume_apartment(context_copy.context, handle, &failure); +#endif } }; diff --git a/test/test/await_completed.cpp b/test/test/await_completed.cpp index be33e818f..6af8dfa21 100644 --- a/test/test/await_completed.cpp +++ b/test/test/await_completed.cpp @@ -66,6 +66,38 @@ namespace // MSVC standard-conforming coroutines (as well as gcc and clang coroutines) // support "bool await_suspend" just fine. REQUIRE(consumed == 0); +#endif + } + + // co_await the same apartment context and confirm that stack does not grow. + // This is in await_completed.cpp because it's basically the same thing as awaiting + // an already-completed coroutine, so the test uses the same infrastructure. + IAsyncAction TestApartmentContextNop() + { + winrt::apartment_context same_context; + + uintptr_t initial = approximate_stack_pointer(); + co_await resume_sync_from_await_suspend(); + uintptr_t sync_usage = initial - approximate_stack_pointer(); + + initial = approximate_stack_pointer(); + co_await same_context; + uintptr_t consumed = initial - approximate_stack_pointer(); + +#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED + // This branch is taken only for MSVC prerelease coroutines. + // + // MSVC prerelease coroutines prior to 16.11 do not implement "bool await_suspend" reliably, + // so we can't use it impl::apartment_awaiter. We must resume inline inside await_suspend, + // so there is a small amount of stack usage. (Pre-16.11 and post-16.11 prerelease coroutines + // are interoperable, so we cannot change behavior based on which compiler we are using, + // because that would introduce ODR violations. Our first opportunity to change behavior + // is the ABI breaking change with MSVC standard-conforming coroutines.) + REQUIRE(consumed <= sync_usage); +#else + // MSVC standard-conforming coroutines (as well as gcc and clang coroutines) + // support "bool await_suspend" just fine. + REQUIRE(consumed == 0); #endif } } @@ -73,3 +105,8 @@ TEST_CASE("await_completed_await") { SyncCompletion().get(); } + +TEST_CASE("apartment_context_nop") +{ + TestApartmentContextNop().get(); +} diff --git a/test/test_cpp20/await_completed.cpp b/test/test_cpp20/await_completed.cpp index 2448a3f88..3ae64e25e 100644 --- a/test/test_cpp20/await_completed.cpp +++ b/test/test_cpp20/await_completed.cpp @@ -38,8 +38,22 @@ namespace uintptr_t consumed = initial - approximate_stack_pointer(); REQUIRE(consumed == 0); } + + IAsyncAction TestApartmentContextNop() + { + // co_await the same apartment and confirm that stack does not grow. + winrt::apartment_context same_context; + uintptr_t initial = approximate_stack_pointer(); + co_await same_context; + uintptr_t consumed = initial - approximate_stack_pointer(); + REQUIRE(consumed == 0); + } } TEST_CASE("await_completed_await") { SyncCompletion().get(); +} +TEST_CASE("apartment_context_nop") +{ + TestApartmentContextNop().get(); } \ No newline at end of file From 419c33a90307ff47408cf2828692c62610308431 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Thu, 16 Feb 2023 10:53:02 -0800 Subject: [PATCH 174/305] Reduce stack consumption if unable to switch to `apartment_context` (#1276) --- strings/base_coroutine_foundation.h | 11 ++---- strings/base_coroutine_threadpool.h | 24 ++++++------- test/test/await_completed.cpp | 53 ----------------------------- 3 files changed, 12 insertions(+), 76 deletions(-) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 1cfde4230..4c467f921 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -169,7 +169,7 @@ namespace winrt::impl } template - auto await_suspend(coroutine_handle handle) + bool await_suspend(coroutine_handle handle) { this->set_cancellable_promise_from_handle(handle); return register_completed_callback(handle); @@ -183,17 +183,10 @@ namespace winrt::impl } private: - auto register_completed_callback(coroutine_handle<> handle) + bool register_completed_callback(coroutine_handle<> handle) { async.Completed(disconnect_aware_handler(this, handle)); -#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED - if (!suspending.exchange(false, std::memory_order_acquire)) - { - handle.resume(); - } -#else return suspending.exchange(false, std::memory_order_acquire); -#endif } static fire_and_forget cancel_asynchronously(Async async) diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index aa8a5b2b1..ba4d742b4 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -77,7 +77,7 @@ namespace winrt::impl return 0; }; - inline void resume_apartment_sync(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) { com_callback_args args{}; args.data = handle.address(); @@ -87,8 +87,9 @@ namespace winrt::impl { // Resume the coroutine on the wrong apartment, but tell it why. *failure = result; - handle(); + return false; } + return true; } struct threadpool_resume @@ -103,7 +104,10 @@ namespace winrt::impl inline void __stdcall fallback_submit_threadpool_callback(void*, void* p) noexcept { std::unique_ptr state{ static_cast(p) }; - resume_apartment_sync(state->m_context, state->m_handle, state->m_failure); + if (!resume_apartment_sync(state->m_context, state->m_handle, state->m_failure)) + { + state->m_handle.resume(); + } } inline void resume_apartment_on_threadpool(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) @@ -113,7 +117,7 @@ namespace winrt::impl state.release(); } - inline auto resume_apartment(resume_apartment_context const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, coroutine_handle<> handle, int32_t* failure) { WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) @@ -132,8 +136,7 @@ namespace winrt::impl } else { - resume_apartment_sync(context.m_context, handle, failure); - return true; + return resume_apartment_sync(context.m_context, handle, failure); } } } @@ -331,17 +334,10 @@ namespace winrt::impl check_hresult(failure); } - auto await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(impl::coroutine_handle<> handle) { auto context_copy = context; -#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED - if (!impl::resume_apartment(context_copy.context, handle, &failure)) - { - handle.resume(); - } -#else return impl::resume_apartment(context_copy.context, handle, &failure); -#endif } }; diff --git a/test/test/await_completed.cpp b/test/test/await_completed.cpp index 6af8dfa21..1d6143eb1 100644 --- a/test/test/await_completed.cpp +++ b/test/test/await_completed.cpp @@ -27,46 +27,12 @@ namespace } #endif - // Simple awaiter that (inefficiently) resumes from inside a function nested in - // await_suspend, for the purpose of measuring how much stack it consumes. - // This is the best we can do with MSVC prerelease coroutines prior to 16.11. - // This simulates the behavior of await_adapter. - struct resume_sync_from_await_suspend - { - bool await_ready() { return false; } - template - void await_suspend(winrt::impl::coroutine_handle h) { resume_inner(h); } - void await_resume() { } - - private: - void resume_inner(winrt::impl::coroutine_handle<> h) { h(); } - }; - IAsyncAction SyncCompletion() { uintptr_t initial = approximate_stack_pointer(); - co_await resume_sync_from_await_suspend(); - uintptr_t sync_usage = initial - approximate_stack_pointer(); - - initial = approximate_stack_pointer(); co_await AlreadyCompleted(); uintptr_t consumed = initial - approximate_stack_pointer(); -#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED - // This branch is taken only for MSVC prerelease coroutines. - // - // MSVC prerelease coroutines prior to 16.11 do not implement "bool await_suspend" reliably, - // so we can't use it impl::await_adapter. We must resume inline inside await_suspend, - // so there is a small amount of stack usage. (Pre-16.11 and post-16.11 prerelease coroutines - // are interoperable, so we cannot change behavior based on which compiler we are using, - // because that would introduce ODR violations. Our first opportunity to change behavior - // is the ABI breaking change with MSVC standard-conforming coroutines.) - REQUIRE(consumed <= sync_usage); -#else - (void)sync_usage; - // MSVC standard-conforming coroutines (as well as gcc and clang coroutines) - // support "bool await_suspend" just fine. REQUIRE(consumed == 0); -#endif } // co_await the same apartment context and confirm that stack does not grow. @@ -77,28 +43,9 @@ namespace winrt::apartment_context same_context; uintptr_t initial = approximate_stack_pointer(); - co_await resume_sync_from_await_suspend(); - uintptr_t sync_usage = initial - approximate_stack_pointer(); - - initial = approximate_stack_pointer(); co_await same_context; uintptr_t consumed = initial - approximate_stack_pointer(); - -#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED - // This branch is taken only for MSVC prerelease coroutines. - // - // MSVC prerelease coroutines prior to 16.11 do not implement "bool await_suspend" reliably, - // so we can't use it impl::apartment_awaiter. We must resume inline inside await_suspend, - // so there is a small amount of stack usage. (Pre-16.11 and post-16.11 prerelease coroutines - // are interoperable, so we cannot change behavior based on which compiler we are using, - // because that would introduce ODR violations. Our first opportunity to change behavior - // is the ABI breaking change with MSVC standard-conforming coroutines.) - REQUIRE(consumed <= sync_usage); -#else - // MSVC standard-conforming coroutines (as well as gcc and clang coroutines) - // support "bool await_suspend" just fine. REQUIRE(consumed == 0); -#endif } } TEST_CASE("await_completed_await") From 4e674c7ebf3c253b8b8d5d233c356295eb8187f6 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Fri, 17 Feb 2023 14:19:54 -0800 Subject: [PATCH 175/305] Fix unreliable clock epoch tests (#1277) --- test/old_tests/UnitTests/clock.cpp | 65 ++++++++++++++++++------------ 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/test/old_tests/UnitTests/clock.cpp b/test/old_tests/UnitTests/clock.cpp index 3940cb1c3..e9e7108f3 100644 --- a/test/old_tests/UnitTests/clock.cpp +++ b/test/old_tests/UnitTests/clock.cpp @@ -17,6 +17,18 @@ namespace winrt } } +// To confirm that two clocks have the same epoch, we +// capture one clock, then the other, then the first again, +// and verify that the three timestamps are ordered. This avoids +// spurious failures if a test machine is slow or experiences a +// clock tick at just the wrong time. +// +// We use a duration_cast to milliseconds so that the assertion +// failure message tells us how many milliseconds of error we encountered. +#define REQUIRE_ORDERED(a, b, c) \ + REQUIRE(duration_cast((b) - (a)).count() >= 0); \ + REQUIRE(duration_cast((c) - (b)).count() >= 0) + namespace Catch { template @@ -46,11 +58,13 @@ namespace Catch TEST_CASE("clock, now") { - Calendar calendar; - calendar.SetToNow(); + // Confirm that clock::now agrees with Calendar::SetToNow. + Calendar calendar1; + calendar1.SetToNow(); auto time = clock::now(); - auto diff = calendar.GetDateTime() - time; - REQUIRE(abs(diff) < milliseconds{ 100 }); + Calendar calendar2; + calendar2.SetToNow(); + REQUIRE_ORDERED(calendar1.GetDateTime(), time, calendar2.GetDateTime()); } TEST_CASE("clock, units") @@ -66,73 +80,72 @@ TEST_CASE("clock, units") TEST_CASE("clock, time_t") { - const DateTime now_dt = clock::now(); + const DateTime now1_dt = clock::now(); const time_t now_tt = time(nullptr); + const DateTime now2_dt = clock::now(); // Round trip from DateTime to time_t and back. // confirm that nothing happens other than truncating the fractional seconds - REQUIRE(clock::from_time_t(clock::to_time_t(now_dt)) == time_point_cast(now_dt)); + REQUIRE(clock::from_time_t(clock::to_time_t(now1_dt)) == time_point_cast(now1_dt)); // Same thing in reverse REQUIRE(clock::to_time_t(clock::from_time_t(now_tt)) == now_tt); // Conversions are verified to be consistent. Now, verify that we're correctly converting epochs - const auto diff = duration_cast(abs(now_dt - clock::from_time_t(now_tt))).count(); - REQUIRE(diff < 1000); + // Note that time_t has only 1s resolution, so we need to add 1 second of slop on either side. + REQUIRE_ORDERED(now1_dt - 1s, clock::from_time_t(now_tt), now2_dt + 1s); } TEST_CASE("clock, FILETIME") { - const DateTime now_dt = clock::now(); + const DateTime now1_dt = clock::now(); FILETIME now_ft; ::GetSystemTimePreciseAsFileTime(&now_ft); + const DateTime now2_dt = clock::now(); // Round trip conversions - REQUIRE(clock::from_file_time(clock::to_file_time(now_dt)) == now_dt); + REQUIRE(clock::from_file_time(clock::to_file_time(now1_dt)) == now1_dt); REQUIRE(clock::to_file_time(clock::from_file_time(now_ft)) == now_ft); // Verify epoch - const auto diff = abs(now_dt - clock::from_file_time(now_ft)); - REQUIRE(diff < milliseconds{ 100 }); + REQUIRE_ORDERED(now1_dt, clock::from_file_time(now_ft), now2_dt); } TEST_CASE("clock, system_clock") { - DateTime const now_dt = clock::now(); - auto const now_sys = system_clock::now(); + DateTime const now1_dt = clock::now(); + auto const now1_sys = system_clock::now(); + DateTime const now2_dt = clock::now(); + auto const now2_sys = system_clock::now(); // Round trip DateTime to std::chrono::system_clock::time_point and back - REQUIRE(clock::from_sys(clock::to_sys(now_dt)) == now_dt); + REQUIRE(clock::from_sys(clock::to_sys(now1_dt)) == now1_dt); // Round trip other direction - REQUIRE(clock::to_sys(clock::from_sys(now_sys)) == now_sys); + REQUIRE(clock::to_sys(clock::from_sys(now1_sys)) == now1_sys); // Round trip with custom resolution { - auto const now_dt_sec = time_point_cast(now_dt); + auto const now_dt_sec = time_point_cast(now1_dt); REQUIRE(clock::from_sys(clock::to_sys(now_dt_sec)) == now_dt_sec); } { - auto const now_dt_mins = time_point_cast(now_dt); + auto const now_dt_mins = time_point_cast(now1_dt); REQUIRE(clock::from_sys(clock::to_sys(now_dt_mins)) == now_dt_mins); } { - auto const now_sys_sec = time_point_cast(now_sys); + auto const now_sys_sec = time_point_cast(now1_sys); REQUIRE(clock::to_sys(clock::from_sys(now_sys_sec)) == now_sys_sec); } { - auto const now_sys_mins = time_point_cast(now_sys); + auto const now_sys_mins = time_point_cast(now1_sys); REQUIRE(clock::to_sys(clock::from_sys(now_sys_mins)) == now_sys_mins); } // Verify that the epoch calculations are correct. { - auto const diff = now_dt - clock::from_sys(now_sys); - REQUIRE(abs(diff) < milliseconds{ 100 }); - } - { - auto const diff = now_sys - clock::to_sys(now_dt); - REQUIRE(abs(diff) < milliseconds{ 100 }); + REQUIRE_ORDERED(now1_dt, clock::from_sys(now1_sys), now2_dt); + REQUIRE_ORDERED(clock::from_sys(now1_sys), now2_dt, clock::from_sys(now2_sys)); } } From abcdc75e008aa87dc733f29a9ec75e6508923ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaigan=C3=A9sh=20Kumaran?= Date: Mon, 20 Feb 2023 21:08:23 +0530 Subject: [PATCH 176/305] Add `to_hstring` overload for `IStringable` (#1271) --- cppwinrt/code_writers.h | 1 + cppwinrt/cppwinrt.vcxproj | 1 + cppwinrt/cppwinrt.vcxproj.filters | 5 ++++- strings/base_stringable_to_hstring.h | 8 ++++++++ test/old_tests/UnitTests/to_hstring.cpp | 12 ++++++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 strings/base_stringable_to_hstring.h diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index c986c927f..e0162fe45 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3253,6 +3253,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable w.write(strings::base_reference_produce); w.write(strings::base_deferral); w.write(strings::base_coroutine_foundation); + w.write(strings::base_stringable_to_hstring); w.write(strings::base_stringable_format); w.write(strings::base_stringable_streams); } diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 75d8cee1e..f0d1e5706 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -81,6 +81,7 @@ + diff --git a/cppwinrt/cppwinrt.vcxproj.filters b/cppwinrt/cppwinrt.vcxproj.filters index 01aecb75e..96129ab20 100644 --- a/cppwinrt/cppwinrt.vcxproj.filters +++ b/cppwinrt/cppwinrt.vcxproj.filters @@ -169,7 +169,7 @@ strings - + strings @@ -184,6 +184,9 @@ strings + + strings + diff --git a/strings/base_stringable_to_hstring.h b/strings/base_stringable_to_hstring.h new file mode 100644 index 000000000..f92da965b --- /dev/null +++ b/strings/base_stringable_to_hstring.h @@ -0,0 +1,8 @@ + +WINRT_EXPORT namespace winrt +{ + inline hstring to_hstring(Windows::Foundation::IStringable const& stringable) + { + return stringable.ToString(); + } +} diff --git a/test/old_tests/UnitTests/to_hstring.cpp b/test/old_tests/UnitTests/to_hstring.cpp index 9f3463a56..1d287c09b 100644 --- a/test/old_tests/UnitTests/to_hstring.cpp +++ b/test/old_tests/UnitTests/to_hstring.cpp @@ -4,6 +4,14 @@ using namespace winrt; +struct stringable : winrt::implements +{ + winrt::hstring ToString() + { + return L"a stringable object"; + } +}; + namespace { void test_cases() @@ -82,6 +90,10 @@ namespace hstring const c = to_hstring(b); REQUIRE(a == c); } + { + auto const obj = make(); + REQUIRE(to_hstring(obj) == obj.ToString()); + } } } From 72b30cc0f14096d8d578e201188dc442725f2880 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Thu, 23 Feb 2023 15:38:07 -0600 Subject: [PATCH 177/305] Add a clang-specific impl->projection conversion operator (#1274) --- strings/base_implements.h | 15 +++++++++++++++ test/old_tests/UnitTests/as_implements.cpp | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/strings/base_implements.h b/strings/base_implements.h index e545b2a57..ca69bc38b 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -110,10 +110,25 @@ namespace winrt::impl template struct producer_convert : producer::type> { +#ifdef __clang__ + // This is sub-optimal in that it requires an AddRef and Release of the + // implementation type for every conversion, but it works around an + // issue where Clang ignores the conversion of producer_ref const + // to I&& (an rvalue ref that cannot bind a const rvalue). + // See CWG rev. 110 active issue 2077, "Overload resolution and invalid + // rvalue-reference initialization" + operator I() const noexcept + { + I result{ nullptr }; + copy_from_abi(result, (produce::type>*)this); + return result; + } +#else operator producer_ref const() const noexcept { return { (produce::type>*)this }; } +#endif operator producer_vtable const() const noexcept { diff --git a/test/old_tests/UnitTests/as_implements.cpp b/test/old_tests/UnitTests/as_implements.cpp index 4c99631fb..60b27342f 100644 --- a/test/old_tests/UnitTests/as_implements.cpp +++ b/test/old_tests/UnitTests/as_implements.cpp @@ -138,3 +138,13 @@ TEST_CASE("as_implements_inheritance") REQUIRE(bar.get() == foo2.get()); } } + +TEST_CASE("convert_to_implements_via_uniform_initialization") +{ + // uniform initialization relies on IStringable(IStringable&&), + // which requires non-const rvalue semantics. + com_ptr foo = make_self(); + IStringable stringable{ *foo }; + com_ptr foo2 = stringable.as(); + REQUIRE(foo.get() == foo2.get()); +} From 629f9e7659a7dae408606456cf8a9f05ff2f4511 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 3 Mar 2023 10:48:16 -0600 Subject: [PATCH 178/305] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 51044dead..57ee9502f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[![Build status](https://dev.azure.com/microsoft/Dart/_apis/build/status/cppwinrt%20internal%20build)](https://dev.azure.com/microsoft/Dart/_build/latest?definitionId=31784) - # The C++/WinRT language projection C++/WinRT is an entirely standard C++ language projection for Windows Runtime (WinRT) APIs, implemented as a header-file-based library, and designed to provide you with first-class access to the modern Windows API. With C++/WinRT, you can author and consume Windows Runtime APIs using any standards-compliant C++17 compiler. From 9e89b5c9fe3bb14ec4842ff54ea444a26c4495b0 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 13 Mar 2023 12:26:53 -0700 Subject: [PATCH 179/305] Create pipeline to sync mirror repo (#1286) --- .pipelines/sync-mirror.yml | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .pipelines/sync-mirror.yml diff --git a/.pipelines/sync-mirror.yml b/.pipelines/sync-mirror.yml new file mode 100644 index 000000000..add70e3ba --- /dev/null +++ b/.pipelines/sync-mirror.yml @@ -0,0 +1,54 @@ +# Sync branches in a mirror repository to a base repo by running this pipeline +# from the mirror repo, and supplying the base repo as a parameter +name: $(BuildDefinitionName)_$(date:yyMMdd)$(rev:.r) + +parameters: + - name: "SourceToTargetBranches" + type: object + default: + master: master + - name: "SourceRepository" + type: string + default: "https://github.com/microsoft/cppwinrt.git" + +jobs: + - job: SyncMirror + strategy: + matrix: + ${{ each branches in parameters.SourceToTargetBranches }}: + ${{ branches.key }}: + SourceBranch: ${{ branches.key }} + TargetBranch: ${{ branches.value }} + dependsOn: [] + pool: + name: Azure Pipelines + vmImage: 'windows-2022' + steps: + - checkout: self + persistCredentials: true + + - task: PowerShell@2 + inputs: + targetType: 'inline' + script: | + Write-Host "SourceBranch " + "$(SourceBranch)" + Write-Host "TargetBranch " + "$(TargetBranch)" + + $repo = "${{ parameters.SourceRepository }}" + git remote add sourcerepo $repo + git remote + + $target = "$(TargetBranch)" + git fetch origin $target + git checkout $target + git pull origin $target + + $source = "$(SourceBranch)" + git fetch sourcerepo $source + git pull sourcerepo $source + + - task: CmdLine@2 + inputs: + script: | + git push + From f3c730994ea129fc5ac26ce59e7c05f8d5ee83e8 Mon Sep 17 00:00:00 2001 From: Johan Laanstra Date: Fri, 24 Mar 2023 11:32:14 -0700 Subject: [PATCH 180/305] Expose configuring /nomidl. (#1290) * Expose configuring /nomidl. * Add test project and fix comments. --- nuget/Microsoft.Windows.CppWinRT.props | 1 + nuget/Microsoft.Windows.CppWinRT.targets | 6 +- test/nuget/NuGetTest.sln | 22 ++- test/nuget/TestApp/TestApp.vcxproj | 3 + test/nuget/TestProxyStub/IAsyncContract.idl | 11 ++ .../TestProxyStub/IAsyncContractParameter.idl | 11 ++ test/nuget/TestProxyStub/TestProxyStub.def | 3 + .../nuget/TestProxyStub/TestProxyStub.vcxproj | 127 ++++++++++++++++++ test/nuget/TestProxyStub/pch.cpp | 1 + test/nuget/TestProxyStub/pch.h | 8 ++ 10 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 test/nuget/TestProxyStub/IAsyncContract.idl create mode 100644 test/nuget/TestProxyStub/IAsyncContractParameter.idl create mode 100644 test/nuget/TestProxyStub/TestProxyStub.def create mode 100644 test/nuget/TestProxyStub/TestProxyStub.vcxproj create mode 100644 test/nuget/TestProxyStub/pch.cpp create mode 100644 test/nuget/TestProxyStub/pch.h diff --git a/nuget/Microsoft.Windows.CppWinRT.props b/nuget/Microsoft.Windows.CppWinRT.props index d7e2c652c..e1d9b4716 100644 --- a/nuget/Microsoft.Windows.CppWinRT.props +++ b/nuget/Microsoft.Windows.CppWinRT.props @@ -43,6 +43,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. nul nul + true + false + false + + + + DynamicLibrary + v143 + Unicode + + + + + + + + + WIN32;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + Use + pch.h + %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + + + Windows + onecore.lib;onecoreuap.lib;%(AdditionalDependencies) + TestProxyStub.def + + + Stub + Stub + true + $(IntDir)dlldata.c + $(IntDir)%(FileName).h + $(IntDir)%(FileName)_i.c + $(IntDir)%(FileName)_p.c + $(WindowsSDK_UnionMetadataPath) + true + false + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + + + + + + + + NotUsing + + + NotUsing + + + NotUsing + + + NotUsing + + + NotUsing + + + Create + + + + + + + + false + + + false + + + + + \ No newline at end of file diff --git a/test/nuget/TestProxyStub/pch.cpp b/test/nuget/TestProxyStub/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestProxyStub/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestProxyStub/pch.h b/test/nuget/TestProxyStub/pch.h new file mode 100644 index 000000000..3186dac74 --- /dev/null +++ b/test/nuget/TestProxyStub/pch.h @@ -0,0 +1,8 @@ +// +// pch.h +// Header for platform projection include files +// + +#pragma once + +#include From 737adea24aaa7b4ed639b689ee94d9d3e00f1a00 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 27 Mar 2023 18:34:35 -0700 Subject: [PATCH 181/305] Compliance and test cleanup (#1291) * Compliance and test cleanup * Leave CFG off for debug builds --- cppwinrt/cppwinrt.vcxproj | 4 ++++ natvis/cppwinrtvisualizer.vcxproj | 3 +++ .../ConsoleApplication1_TemporaryKey.pfx | Bin 2520 -> 0 bytes ...ComponentNamespaceUnderscore_TemporaryKey.pfx | Bin 2512 -> 0 bytes test/old_tests/UnitTests/Main.cpp | 5 +++++ test/test_module_lock_none/main.cpp | 5 +++++ 6 files changed, 17 insertions(+) delete mode 100644 test/nuget/ConsoleApplication1/ConsoleApplication1_TemporaryKey.pfx delete mode 100644 test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore_TemporaryKey.pfx diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index f0d1e5706..46b5836e7 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -269,6 +269,7 @@ true ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded + Guard Console @@ -291,6 +292,7 @@ true ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded + Guard Console @@ -313,6 +315,7 @@ true ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded + Guard Console @@ -335,6 +338,7 @@ true ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded + Guard Console diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index e504e197e..3cf92f1cd 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -184,6 +184,7 @@ $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 pch.h + Guard _DEBUG;%(PreprocessorDefinitions) @@ -213,6 +214,7 @@ $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 pch.h + Guard _DEBUG;%(PreprocessorDefinitions) @@ -242,6 +244,7 @@ $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 pch.h + Guard _DEBUG;%(PreprocessorDefinitions) diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1_TemporaryKey.pfx b/test/nuget/ConsoleApplication1/ConsoleApplication1_TemporaryKey.pfx deleted file mode 100644 index b1f67069d42d1e64062ed5913a05bcad7d1339f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2520 zcmZWq2{_bi7yr)~gOa5PV{fu#q7h@VBqB7nv1BZ{WGTcD264rVONdCxGA8@hT zr;=cn@a+hM2U0-cBf}_s(I9*qP2t}8pAh#SFbelO5N3h81V8-mEdE0fXaNPbkEXzO z&{FV2|AE2c0x;fM&tC)DIySqmT%3N|KoZ7vT;j<$JJJnjo$b}L*bTNt^N#!u zA1i^M#u83h#VOsm^Zq8zS7;|He>LY*uYJBzp2h}!JLFMIL&4)?rTX+RdV6lZ=?usC ztJA;$QUK{SybHbDMzTqi;FveTmm02qdAL=ZoWPehI~ZILYv3==r0=i8{UzDw!rB~W zFvH`{s^!L#&Lw-P(cg^srbTaBPi=}HgUOwXtzC1O7x^?8(`q!1>hm+!G(_EIKhDf> zP`%|(5OR4X*&-=5&Niz27{GfWNxHpZuR2RP$W{AE?u@`FoS!3`(y}gTAHk!C94~Xa zqvPq);b&UrvIqHClXs=?MFzC(=sok)z71~Tfzd0kN}o3<1!Q;+6Ibu5dR)lGe0bn> z%F#NBNTUwA39PMB{L?++NmO>e=&MR$c}TL$``61qg{m``^I$f1rctm&-Z4kJIY)B_ z-CHoujn11Rqhu_WQkL3E%RVoKvyA>7QM1Zowkx+5HmX`Ry-hRN?5Y!#a=*ln*&XCL zb}G2P_A2{V{332uSxG+DZJNHBU@5&98$vqO!ySxA70T;ZK4M31>O`PJ0P#&IO8>Ng z3ZqH1yMITE=Qf$*YPIi!UyJP>9AR7twIH`j#J{usc7H%1In;<866NXVFDN!mRzH-& z@BjHLZTbF7s99ZyeETnGlnwfhpreqXYG<{bfBOUzv7IldyZ4=t`!+sqXu`Jr(}T(H zk=)C*qle^T&urxx%p$YzF%~{z7!7L^NF(0y*`B539%An7t_Z!fY}lui)zzzcf~9pOWd)P}tEFbhWZ3)v1(pCAY1A z8sp)39lP>W2PO2;Kqkve%6dx7=ghMrm3h{4ZOr^k&k;3`z4vJK9tQqf+mE~7kCGc` zg>KWom-o3iaSQ$FH2D5yV-)Mz2kx6W?z*nNW5Q5`4SMYRZVG2Q9weHz}`nNpuQzzetz3I@;w z&Vh0bPz5|e%nS5YK~)F5!I&!G0miVv*}tu8AVULWV8OT+XnBBHXtXPw4+V$7AQY@H zL>(_<1y};UATbyS1VTW)4uk@7fE~F0g%E)opl1Zyw}BuK3k3aOuuKr(^LLgUfd88p z26|p#3&Cg#SNK1j^S}!zTs|P=1%&|M1|I#-m+}82pGc)yHEH$8{x$MrDO~6P#3EFT zpm&IHpH+MRjJIXZwU~w!2HekL1N%>6zx^?po*a_3KT!rNoX*a3aHD(X$KEH|mLv zNZqr_b6c;?8^1G4Q0Y~SW}A_W<*gvI3AXUYV@Hii_h_?R5v%&b%qHiut}bKyDE-ie z>|yb}GRRPlv2SdVRQZ9*X@akP1=rb67Km#^;SQlaoI$qcSU%l5w1oD{b>qnzCpn$z zw6)teIpp)r_rns|HSt7bsa;S+V5Z}^0lBKBs@QQ6dq6crl<;`joW`iiHIZH>k1~^t z{X5^h8j9pEUn&$#w3Rr(pQ0;vE~i{LoVhZ&9f4<2DQ7gUoKNzviqG#ZJqTK}oX*Ip zu;&!L7h~qMEM3TIk^U+apwC>JO131J*)-3MDB21i|Mm`xN7Qtl89hOL2bXVEX^=+U z-g+8Yyi5`uS znSLpxTJnVpY6mVZ>%AJS(BvsidWIKlI+%&MlpobP%vz6^gW@WGdnLfzq0qhGa1=T} zc>dM0M|xgObo~QZb*RY?Er()qd-OueFZ){9DaKN8rvfu$-n`NDphYFeL}~V-sdgDT zD84a)chXNq&?NA{p^Y;@oKvIhNDUL`nL>s(8i z3YA*h-i24tpx%1csyPumXoD9GpB1KrXA~oLqy6uQ5JDC^EiY$f``IAs(iWs+$pl(r zP~b6-HzXMYKJ|OR`LTdrTJl?GYf553jIhkb3bZa-7R>|aMhS315ipU}#%>X-zQ}TX pykR#q>dV3N2K_#m$ZS|qciYO{<#Z8jP{rH(lG#Q+`+q&Se*yFOh5-No diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore_TemporaryKey.pfx b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore_TemporaryKey.pfx deleted file mode 100644 index dac97059a8cb20c1fc0771a2086483fbbedd1071..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2512 zcmZXUc{J2tAIHD5mwh;m~}V; zdZb}ay4vc}Bn%9O_d+SqAt{85jhIp9i_&6~+D0SLyk}COZdHy)t{rD9Qn3rc{5TE1dGAQF(cIV2UPOhA`{-elxhZExSu3rRt2m;n{M?NK&4YQi*K3Vzv*~GK& zNLrKi0&np$OyRq)UyH7$m>TVruKak*%czf6Fua|=P=}v0HOWV75eCM}b#wk`b5W5y z+mK7OIRXh6U2s1YecW5gn%<804O!o4lUm>7k^ESf(8x1b0Y?qB4?Y;&Y`&Vpq^>z9 z>*vc2J6?MJ}Bj(a)sFok zE?0_!&9pqKnPO)plGEXbcjOyOe0}RvvwfQ+E9VLHratj+Cv>n=E5k(Dd6DD+Hui&X z#)TIVx)o9y7&Drcb#jQ8;xz9IjkZAHpN0@u+*p=c;8E_xMZGi2_H)ggnT~`%7Xq66 z?|(d+K?51=Z@q&VKgI{3Fz?oyPNWf6Cq{^LjDyOXip#upT5iko_ncHaVW{XA@0C;N zC1c{`8$>v!@=4}-goWRU`?}e0ate5DGZ4{TZo%h`=K_9LuV8J+ z&eh>@-*wXCDAPFl?aLDyml5i6ft%9dAT=(;aejK-+M0wr4^T6RJx%Eoq5r!|HO$1JU zm5n6TrB!i#ZQIYl1ZonashYxfUopVObL4=i7VT0JWxf?R9def(hcF}sd-Z$ujz4ss zJB1WH7e46_O|4XbUpAgX-}J-_31#n?b;(&2@8hl2={9xeIk=tlHgL1#P)c&g@Xa1t zA@^UnppwO-8<(%kF_=tJ%S(n6MW~@NP649r1m(8!NnC$Q+P9LuR*hKk+!HU9k&v*h z?TRH8o-FMNKVa7>40({7DqCeDo|Mw|;dFkd^L4=yWZs8+-^Ajx`SA~%D#SyIqfwgi zTEho4JK}-6&aztk`v>E8n!>#a&k$#vmy$jR#}rxa-Kf`0`%Wv<=}|_jK(~Qu($X1I?P=oD zvJUBDneKbn@N;9-F?+c*J@ucY-7z#uX#kgQCjb2w>PAsQApi5^fcJ!n(Q7UHuA8HU zxtT-##X)qHxS0=arBgrr&fQqxuSGK$H+telP6gU_o{j3(^wGb05Z1Tuqs$@H)0{6b z`YglF7mYD?*XK*v$p6vPDQ!}Aeq($e875vtxd-+nSIo_q5~=5@fKyL3jC z2aTaSDOX;Hi|WSm{XH((1#mDZ6a)YO*8U&Jk26D>0E&PLa2@aflmR8+EX$wy9SOfP zWk8kHQDw2KfI5H$)L5B1fMZ1^)=~wou@t{F1V9z*0%Jc713^I))ngzW9%%(w0^Tff z06+w8v+Oz$2%rFKmj6Zk0Z&$?&&orAn=D3T)d7GzEBE@XLIL>S`+`^%fptv)mI5LE z{c<=ghXQe9q03+pzzVkibU^<<@>kZV1J7qmU4D)HyA+751T9y!?G=FC-Hamgxbrd} zIkSB;4QkJ|BZPT!nJO@oqb?yq}G zM9Dp!krP)_mC-d0^3fL_Z7*4lX@J!h?~*RbRuR?QqQ}G@e=YeWLMXp;Ps#P?qnwlb zj%}FRYDl%t7Lf~?w1mxP3;vEsqMjw>Gek|IZ0wpuW@-xc;#0_Q(!UUmV8S_IOVe3l zP&dd{c;vCT&0+9-I>Ew}%b4k$LYSGzGfWz&eOBerVRVK-z9JG;Pc=x@6iS1%9~;TL zAGuY76iJeNuasLc((hM?;pu*-oyFX>R4P@4E=&(8iBYy>G&32#z#d6dTDyGO;3VQy z*R6-l0lM&P7i8GZccjUe^#`-(%6^hvP@QHa@g7M#FXHIHgu=QAv)6hiQ4X8_W0x6!obDt zac1c>GTn$@(FdDOg_~-ZUXXo+e?Do^e5~V$WPdh_m)14;AtCkYj&^%ikh?d#S5t() z4G`tQ>)uwwSDG&b*(Nph?y7P0tAyfXxW`m%H|-hoeHTW-I7hNpFmfB#QTY*s`c91m zE#cOzoDB}8yF5g$+!EUUgz3m@W1rX!5+L`#oeZlNDp%*03M83&mf?F8DlFgD1xN_? zy}NgmUY@XC;4G%Uxbqcb_`*xq57YG6{es%StH!uUuKJ7luISp48PK-_1V*nWxqHCE z2Bt9@UGS6^comd>FClbW(%9`)_IwjDp|S@2(J~*+d{XNxGyoBtd5yd^5qr0)E+aVK zO@|x1dtCFQLHUqX7bdsWp51qWyPuL6+0fMVwIIBTK#}Yz6DoV;*lss1<1ZP>kPqzs zQ&!KR)?}PUudDnVn-TIyuYjtebNa@upcDnw%lj1wkD^n(b>-&e<}#7fiO>}^YTBor zAvcDP&bqt97)FP`r5@@+hpEDLu78-9 zx~TV&Ui576D-c!_D~^T3*iIuLU=b*P*f=5P-b~1LR^FQy6KFv~7^W%_%0IGM-g&)2 VhbF|dx6 Date: Thu, 30 Mar 2023 06:48:23 -0700 Subject: [PATCH 182/305] Use safe DLL loading (avoid current directory) (#1293) --- strings/base_activation.h | 4 ++-- strings/base_agile_ref.h | 7 ++++++- strings/base_extern.h | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/strings/base_activation.h b/strings/base_activation.h index 5c6f938d9..b27cefb70 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -39,7 +39,7 @@ namespace winrt::impl if (hr == impl::error_not_initialized) { - auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(WINRT_IMPL_LoadLibraryW(L"combase.dll"), "CoIncrementMTAUsage")); + auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); if (!usage) { @@ -66,7 +66,7 @@ namespace winrt::impl { path.resize(count); path += L".dll"; - library_handle library(WINRT_IMPL_LoadLibraryW(path.c_str())); + library_handle library(load_library(path.c_str())); path.resize(path.size() - 4); if (!library) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index eb5bfe245..b2ff542d9 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -126,6 +126,11 @@ namespace winrt::impl atomic_ref_count m_references{ 1 }; }; + inline void* load_library(wchar_t const* library) noexcept + { + return WINRT_IMPL_LoadLibraryExW(library, nullptr, 0x00001000 /* LOAD_LIBRARY_SEARCH_DEFAULT_DIRS */); + } + template void load_runtime_function(wchar_t const* library, char const* name, F& result, L fallback) noexcept { @@ -134,7 +139,7 @@ namespace winrt::impl return; } - result = reinterpret_cast(WINRT_IMPL_GetProcAddress(WINRT_IMPL_LoadLibraryW(library), name)); + result = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(library), name)); if (result) { diff --git a/strings/base_extern.h b/strings/base_extern.h index 266758aa0..c0fb15acf 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -24,7 +24,7 @@ __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId extern "C" { - void* __stdcall WINRT_IMPL_LoadLibraryW(wchar_t const* name) noexcept WINRT_IMPL_LINK(LoadLibraryW, 4); + void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8); From 6162c9d05d42281114e0891b7b71f57ea2b6ab5f Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Fri, 31 Mar 2023 20:17:20 -0700 Subject: [PATCH 183/305] Fix flakey clock and line-number tests (#1294) --- test/old_tests/UnitTests/clock.cpp | 5 +++-- test/test_cpp20/custom_error.cpp | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/old_tests/UnitTests/clock.cpp b/test/old_tests/UnitTests/clock.cpp index e9e7108f3..2898d34af 100644 --- a/test/old_tests/UnitTests/clock.cpp +++ b/test/old_tests/UnitTests/clock.cpp @@ -92,8 +92,9 @@ TEST_CASE("clock, time_t") REQUIRE(clock::to_time_t(clock::from_time_t(now_tt)) == now_tt); // Conversions are verified to be consistent. Now, verify that we're correctly converting epochs - // Note that time_t has only 1s resolution, so we need to add 1 second of slop on either side. - REQUIRE_ORDERED(now1_dt - 1s, clock::from_time_t(now_tt), now2_dt + 1s); + // Note that time_t has only 1s resolution, so we need to add 2 seconds of slop on either side. + // (One second for measurement error, and another second for rounding error.) + REQUIRE_ORDERED(now1_dt - 2s, clock::from_time_t(now_tt), now2_dt + 2s); } TEST_CASE("clock, FILETIME") diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index bdb88dcd3..2714fa837 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -7,11 +7,10 @@ namespace { static bool s_loggerCalled = false; - // Note that we are checking that the source line number matches expectations. If lines above this are changed - // then this value needs to change as well. void FailOnLine15() { // Validate that handler translated exception +#line 15 // Force next line to be reported as line number 15 REQUIRE_THROWS_AS(check_hresult(0x80000018), hresult_illegal_delegate_assignment); } From c3b7fcfc9910e8eb87b02ba0e4356f123a327c44 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 3 Apr 2023 10:52:40 -0700 Subject: [PATCH 184/305] Move official build pipelines to OneBranch (#1295) * Add OneBranch pipelines --- .pipelines/OneBranch.Official.yml | 193 ++++++++++++++++++++ .pipelines/OneBranch.PullRequest.yml | 70 +++++++ .pipelines/jobs/OneBranchBuild.yml | 141 ++++++++++++++ .pipelines/jobs/OneBranchNuGet.yml | 76 ++++++++ .pipelines/jobs/OneBranchTest.yml | 114 ++++++++++++ .pipelines/jobs/OneBranchVsix.yml | 147 +++++++++++++++ .pipelines/variables/OneBranchVariables.yml | 16 ++ .pipelines/variables/version.yml | 7 + 8 files changed, 764 insertions(+) create mode 100644 .pipelines/OneBranch.Official.yml create mode 100644 .pipelines/OneBranch.PullRequest.yml create mode 100644 .pipelines/jobs/OneBranchBuild.yml create mode 100644 .pipelines/jobs/OneBranchNuGet.yml create mode 100644 .pipelines/jobs/OneBranchTest.yml create mode 100644 .pipelines/jobs/OneBranchVsix.yml create mode 100644 .pipelines/variables/OneBranchVariables.yml create mode 100644 .pipelines/variables/version.yml diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml new file mode 100644 index 000000000..def1114a8 --- /dev/null +++ b/.pipelines/OneBranch.Official.yml @@ -0,0 +1,193 @@ +parameters: # parameters are shown up in ADO UI in a build queue time +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: false + +variables: +- template: variables/version.yml +- template: variables/OneBranchVariables.yml + parameters: + debug: ${{ parameters.debug }} + +name: 2.0.$(date:yyMMdd)$(rev:.r) + +trigger: none + +resources: + repositories: + - repository: templates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main + +extends: + template: v2/Microsoft.Official.yml@templates + parameters: + platform: + name: 'windows_undocked' + product: 'build_tools' + + cloudvault: + enabled: false + + globalSdl: + tsa: + enabled: false + + nugetPublishing: + feeds: + name: CppWinRT + + stages: + - stage: build + pool: + type: windows + + jobs: + - template: .pipelines/jobs/OneBranchBuild.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) + OfficialBuild: true + + - stage: vpack + dependsOn: build + jobs: + - job: Compiler_vpack + pool: + type: windows + variables: + ob_outputDirectory: '$(Build.SourcesDirectory)\out' + + ob_createvpack_enabled: true + ob_createvpack_packagename: CppWinRT.Compiler + ob_createvpack_owneralias: cpp4uwpt + ob_createvpack_description: C++/WinRT Compiler + ob_createvpack_provData: true + ob_createvpack_versionAs: parts + ob_createvpack_majorVer: $(MajorVersion) + ob_createvpack_minorVer: $(MinorVersion) + ob_createvpack_patchVer: $(PatchVersion) + ob_createvpack_metadata: $(Build.SourceBranchName).x86.$(Build.BuildNumber).$(Build.SourceVersion) + ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt + + steps: + - task: UseDotNet@2 + continueOnError: true + inputs: + packageType: 'runtime' + version: '6.x' + performMultiLevelLookup: true + + - task: DownloadPipelineArtifact@2 + displayName: 'Download x86 artifacts' + inputs: + artifactName: 'drop_build_x86' + targetPath: '$(Build.SourcesDirectory)/x86' + + - task: CopyFiles@2 + displayName: 'Stage compiler vpack contents' + inputs: + SourceFolder: $(Build.SourcesDirectory)/x86 + Contents: | + cppwinrt/cppwinrt.exe + cppwinrt/cppwinrt.pdb + TargetFolder: $(ob_outputDirectory) + + - job: MSBuild_vpack + pool: + type: windows + variables: + ob_outputDirectory: '$(Build.SourcesDirectory)\out' + + ob_createvpack_enabled: true + ob_createvpack_packagename: CppWinRT.MSBuild + ob_createvpack_owneralias: cpp4uwpt + ob_createvpack_description: C++/WinRT MSBuild + ob_createvpack_provData: true + ob_createvpack_versionAs: parts + ob_createvpack_majorVer: $(MajorVersion) + ob_createvpack_minorVer: $(MinorVersion) + ob_createvpack_patchVer: $(PatchVersion) + ob_createvpack_metadata: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) + ob_createvpack_verbose: true + ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt + + steps: + - task: UseDotNet@2 + continueOnError: true + inputs: + packageType: 'runtime' + version: '6.x' + performMultiLevelLookup: true + + - task: DownloadPipelineArtifact@2 + displayName: 'Download x86 artifacts' + inputs: + artifactName: 'drop_build_x86' + targetPath: '$(Build.SourcesDirectory)/x86' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download x64 artifacts' + inputs: + artifactName: 'drop_build_x64' + targetPath: '$(Build.SourcesDirectory)/x64' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download arm artifacts' + inputs: + artifactName: 'drop_build_arm' + targetPath: '$(Build.SourcesDirectory)/arm' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download arm64 artifacts' + inputs: + artifactName: 'drop_build_arm64' + targetPath: '$(Build.SourcesDirectory)/arm64' + + - task: CmdLine@2 + displayName: 'Stage MSBuild vpack contents' + inputs: + script: | + set TargetDir=$(ob_outputDirectory) + rd /s /q %TargetDir% >nul 2>&1 + md %TargetDir% + cd %TargetDir% + + copy $(Build.SourcesDirectory)\vsix\Microsoft.Cpp.CppWinRT.props + copy $(Build.SourcesDirectory)\nuget\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props + copy $(Build.SourcesDirectory)\nuget\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets + copy $(Build.SourcesDirectory)\nuget\CppWinrtRules.Project.xml CppWinrtRules.Project.xml + echo d | xcopy $(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib build\native\lib\i386 + echo d | xcopy $(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib build\native\lib\Win32 + echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\amd64 + echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\x64 + echo d | xcopy $(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib build\native\lib\arm + echo d | xcopy $(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib build\native\lib\arm64 + + - stage: NuGet + dependsOn: build + jobs: + - template: .pipelines/jobs/OneBranchNuGet.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) + OfficialBuild: true + + - stage: Test + dependsOn: build + jobs: + - template: .pipelines/jobs/OneBranchTest.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) + + - stage: Vsix + dependsOn: NuGet + jobs: + - template: .pipelines/jobs/OneBranchVsix.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) + OfficialBuild: true diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml new file mode 100644 index 000000000..2ee26d1ad --- /dev/null +++ b/.pipelines/OneBranch.PullRequest.yml @@ -0,0 +1,70 @@ +parameters: +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: false + +variables: +- template: variables/version.yml +- template: variables/OneBranchVariables.yml + parameters: + debug: ${{ parameters.debug }} + +name: PullRequest_2.0.$(date:yyMMdd)$(rev:.r) + +trigger: none + +pool: + type: windows + +resources: + repositories: + - repository: templates + type: git + name: OneBranch.Pipelines/GovernedTemplates + ref: refs/heads/main + +extends: + template: v2/Microsoft.NonOfficial.yml@templates + parameters: + platform: + name: 'windows_undocked' + product: 'build_tools' + + globalSdl: + tsa: + enabled: false + sbom: + enabled: true + + stages: + - stage: build + jobs: + - template: .pipelines/jobs/OneBranchBuild.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) + + - stage: NuGet + dependsOn: build + jobs: + - template: .pipelines/jobs/OneBranchNuGet.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) + + - stage: Test + dependsOn: build + jobs: + - template: .pipelines/jobs/OneBranchTest.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) + + - stage: Vsix + dependsOn: NuGet + jobs: + - template: .pipelines/jobs/OneBranchVsix.yml@self + parameters: + BuildConfiguration: $(BuildConfiguration) + BuildVersion: $(BuildVersion) diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml new file mode 100644 index 000000000..984530eba --- /dev/null +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -0,0 +1,141 @@ +parameters: + - name: BuildConfiguration + type: string + - name: BuildVersion + type: string + - name: OutputDirectory + type: string + default: '$(Build.SourcesDirectory)\out' + - name: OfficialBuild + type: boolean + default: false + +jobs: +- job: + pool: + type: windows + strategy: + matrix: + x86: + BuildPlatform: 'x86' + x64: + BuildPlatform: 'x64' + arm: + BuildPlatform: 'arm' + arm64: + BuildPlatform: 'arm64' + + variables: + ob_outputDirectory: ${{ parameters.OutputDirectory }} + ob_artifactSuffix: $(BuildPlatform) + StagingFolder: $(ob_outputDirectory) + + ${{ if eq(parameters.OfficialBuild, 'false') }}: + ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + + ob_symbolsPublishing_enabled: ${{ parameters.OfficialBuild }} + ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' + ob_symbolsPublishing_searchPattern: '**\*.pdb' + ob_symbolsPublishing_indexSources: true + + steps: + - task: UseDotNet@2 + continueOnError: true + inputs: + packageType: 'runtime' + version: '6.x' + performMultiLevelLookup: true + + - task: NuGetCommand@2 + displayName: NuGet restore cppwinrt.sln + inputs: + command: 'restore' + restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + + - task: VSBuild@1 + displayName: Build fast_fwd + inputs: + solution: $(Build.SourcesDirectory)\cppwinrt.sln + msbuildArgs: /t:fast_fwd /m /p:CppWinRTBuildVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true + platform: $(BuildPlatform) + configuration: ${{ parameters.BuildConfiguration }} + + - task: CopyFiles@2 + displayName: Stage cppwinrt_fast_forwarder.lib + inputs: + SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) + Contents: cppwinrt_fast_forwarder.lib + TargetFolder: $(StagingFolder) + + - task: NuGetCommand@2 + displayName: NuGet restore cppwinrtvisualizer.sln + inputs: + command: 'restore' + restoreSolution: '$(Build.SourcesDirectory)\natvis\cppwinrtvisualizer.sln' + + - task: VSBuild@1 + displayName: Build Component visualizer + condition: or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')) + inputs: + solution: $(Build.SourcesDirectory)\natvis\cppwinrtvisualizer.sln + msbuildArgs: /m /p:Deployment=Component,CppWinRTBuildVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true + platform: $(BuildPlatform) + configuration: ${{ parameters.BuildConfiguration }} + + - task: VSBuild@1 + displayName: Build Standalone visualizer + condition: or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')) + inputs: + solution: $(Build.SourcesDirectory)\natvis\cppwinrtvisualizer.sln + msbuildArgs: /m /p:Deployment=Standalone,CppWinRTBuildVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true + platform: $(BuildPlatform) + configuration: ${{ parameters.BuildConfiguration }} + + - task: CopyFiles@2 + displayName: Stage Component cppwinrtvisualizer.* + condition: or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Component + Contents: | + cppwinrtvisualizer.dll + cppwinrtvisualizer.pdb + cppwinrtvisualizer.vsdconfig + TargetFolder: $(StagingFolder)\Component + + - task: CopyFiles@2 + displayName: Stage Standalone cppwinrtvisualizer.* + condition: or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'arm64')) + inputs: + SourceFolder: $(Build.SourcesDirectory)\natvis\$(BuildPlatform)\$(BuildConfiguration)\Standalone + Contents: | + cppwinrtvisualizer.dll + cppwinrtvisualizer.pdb + cppwinrtvisualizer.vsdconfig + TargetFolder: $(StagingFolder)\Standalone + + - task: VSBuild@1 + displayName: Build cppwinrt + condition: or(eq(variables['BuildPlatform'], 'x86'), eq(variables['BuildPlatform'], 'x64')) + inputs: + solution: $(Build.SourcesDirectory)\cppwinrt.sln + msbuildArgs: /t:cppwinrt /m /p:CppWinRTBuildVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true + platform: $(BuildPlatform) + configuration: ${{ parameters.BuildConfiguration }} + + - task: CopyFiles@2 + displayName: Stage cppwinrt.* + inputs: + SourceFolder: $(Build.SourcesDirectory)\_build\$(BuildPlatform)\$(BuildConfiguration) + Contents: | + cppwinrt.exe + cppwinrt.pdb + TargetFolder: $(StagingFolder)\cppwinrt + + - task: onebranch.pipeline.signing@1 + displayName: '🔒 Onebranch Signing for cppwinrt binaries' + condition: eq(${{ parameters.OfficialBuild }}, 'true') + inputs: + command: sign + signing_profile: external_distribution + files_to_sign: '**/*.dll;**/*.exe' + search_root: $(StagingFolder) diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml new file mode 100644 index 000000000..803e6f9f7 --- /dev/null +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -0,0 +1,76 @@ +# Build the NuGet package +parameters: + - name: BuildConfiguration + type: string + - name: BuildVersion + type: string + - name: OfficialBuild + type: boolean + default: false + +jobs: + - job: + pool: + type: windows + + variables: + ob_outputDirectory: '$(Build.SourcesDirectory)\out' + ob_nugetPublishing_enabled: ${{ parameters.OfficialBuild }} + PackageVersion: ${{ parameters.BuildVersion }} + + steps: + - task: UseDotNet@2 + continueOnError: true + inputs: + packageType: 'runtime' + version: '6.x' + performMultiLevelLookup: true + + - task: NuGetToolInstaller@1 + displayName: Use NuGet 6.0.2 + continueOnError: True + inputs: + versionSpec: 6.0.2 + + - task: DownloadPipelineArtifact@1 + displayName: 'Download x86 artifacts' + inputs: + artifactName: 'drop_build_x86' + targetPath: '$(Build.SourcesDirectory)/x86' + + - task: DownloadPipelineArtifact@1 + displayName: 'Download x64 artifacts' + inputs: + artifactName: 'drop_build_x64' + targetPath: '$(Build.SourcesDirectory)/x64' + + - task: DownloadPipelineArtifact@1 + displayName: 'Download arm artifacts' + inputs: + artifactName: 'drop_build_arm' + targetPath: '$(Build.SourcesDirectory)/arm' + + - task: DownloadPipelineArtifact@1 + displayName: 'Download arm64 artifacts' + inputs: + artifactName: 'drop_build_arm64' + targetPath: '$(Build.SourcesDirectory)/arm64' + + - task: NuGetCommand@2 + displayName: 'Build NuGet package' + inputs: + command: 'pack' + packagesToPack: 'nuget/Microsoft.Windows.CppWinRT.nuspec' + versioningScheme: byEnvVar + versionEnvVar: 'PackageVersion' + buildProperties: 'cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib' + packDestination: $(ob_outputDirectory)\packages + + - task: onebranch.pipeline.signing@1 + displayName: '🔒 Onebranch Signing for NuGet package' + condition: eq(${{ parameters.OfficialBuild }}, 'true') + inputs: + command: sign + signing_profile: external_distribution + files_to_sign: 'Microsoft.Windows.CppWinRT.*.nupkg' + search_root: $(ob_outputDirectory)\packages diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml new file mode 100644 index 000000000..3acaccf7d --- /dev/null +++ b/.pipelines/jobs/OneBranchTest.yml @@ -0,0 +1,114 @@ +parameters: + - name: BuildConfiguration + type: string + - name: BuildVersion + type: string + +jobs: +- job: + pool: + type: windows + strategy: + matrix: + test.x86: + TestExe: 'test' + TestProject: 'test' + BuildPlatform: 'x86' + test_cpp20.x86: + TestExe: 'test_cpp20' + TestProject: 'test_cpp20' + BuildPlatform: 'x86' + test_cpp20_no_sourcelocation.x86: + TestExe: 'test_cpp20_no_sourcelocation' + TestProject: 'test_cpp20_no_sourcelocation' + BuildPlatform: 'x86' + test_win7.x86: + TestExe: 'test_win7' + TestProject: 'test_win7' + BuildPlatform: 'x86' + test_fast.x86: + TestExe: 'test_fast' + TestProject: 'test_fast' + BuildPlatform: 'x86' + test_slow.x86: + TestExe: 'test_slow' + TestProject: 'test_slow' + BuildPlatform: 'x86' + test_old.x86: + TestExe: 'test_old' + TestProject: 'old_tests\test_old' + BuildPlatform: 'x86' + test_module_lock_custom.x86: + TestExe: 'test_module_lock_custom' + TestProject: 'test_module_lock_custom' + BuildPlatform: 'x86' + test_module_lock_none.x86: + TestExe: 'test_module_lock_none' + TestProject: 'test_module_lock_none' + BuildPlatform: 'x86' + + variables: + ob_outputDirectory: $(Build.SourcesDirectory)\out + ob_artifactSuffix: $(TestExe).$(BuildPlatform) + ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + + BuildPath: '$(Build.SourcesDirectory)/_build/$(BuildPlatform)/${{ parameters.BuildConfiguration }}' + + steps: + - task: UseDotNet@2 + continueOnError: true + inputs: + packageType: 'runtime' + version: '6.x' + performMultiLevelLookup: true + + - task: DownloadPipelineArtifact@2 + displayName: 'Download cppwinrt executable' + inputs: + artifactName: 'drop_build_$(BuildPlatform)' + targetPath: '$(Pipeline.Workspace)' + + - task: CopyFiles@2 + displayName: 'Patch cppwinrt executable into build directory' + inputs: + sourceFolder: '$(Pipeline.Workspace)' + Contents: '**\cppwinrt.exe' + TargetFolder: $(BuildPath) + flattenFolders: true + + - task: NuGetCommand@2 + displayName: NuGet restore cppwinrt.sln + inputs: + command: 'restore' + restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + + - task: PowerShell@2 + displayName: Remove cppwinrt dependency from test projects + inputs: + targetType: inline + script: | + # Hack-ish: We already have a built exe, so we want to avoid rebuilding cppwinrt + mv cppwinrt.sln cppwinrt.sln.orig + Get-Content cppwinrt.sln.orig | + Where-Object { -not $_.Contains("{D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}") } | + Set-Content cppwinrt.sln + "Modified contents" + Get-Content cppwinrt.sln + + - task: CmdLine@2 + displayName: Run cppwinrt to build projection + inputs: + script: $(BuildPath)\cppwinrt.exe -in local -out $(BuildPath) -verbose + + - task: VSBuild@1 + displayName: Build test + inputs: + solution: $(Build.SourcesDirectory)\cppwinrt.sln + msbuildArgs: /t:test\$(TestProject) /m /p:CppWinRTBuildVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true /bl:$(ob_outputDirectory)\output.binlog + platform: $(BuildPlatform) + configuration: ${{ parameters.BuildConfiguration }} + + - task: CmdLine@2 + displayName: Run test + inputs: + script: $(BuildPath)\$(TestExe).exe diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml new file mode 100644 index 000000000..2efa5b29c --- /dev/null +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -0,0 +1,147 @@ +parameters: + - name: BuildConfiguration + type: string + - name: BuildVersion + type: string + - name: OfficialBuild + type: boolean + default: false + +jobs: +- job: + pool: + type: windows + strategy: + matrix: + Standalone: + Deployment: 'Standalone' + VsVersion: 'Dev17' + VsixFilename: Microsoft.Windows.CppWinRT.$(VsVersion) + Component: + Deployment: 'Component' + VsVersion: 'Dev17' + VsixFilename: Microsoft.Windows.CppWinRT.$(VsVersion) + Dev16: + Deployment: 'Standalone' + VsVersion: 'Dev16' + VsixFilename: Microsoft.Windows.CppWinRT + + variables: + ob_outputDirectory: $(Build.SourcesDirectory)\out + ob_artifactSuffix: $(VsVersion)_$(Deployment) + + BuildFolder: $(Build.SourcesDirectory)\vsix\$(VsVersion)\bin\${{ parameters.BuildConfiguration }}\$(Deployment) + + ob_symbolsPublishing_enabled: true + ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' + ob_symbolsPublishing_searchPattern: '**\*.pdb' + ob_symbolsPublishing_indexSources: true + + steps: + - task: UseDotNet@2 + continueOnError: true + inputs: + packageType: 'sdk' + version: '6.x' + performMultiLevelLookup: true + + - task: NuGetToolInstaller@1 + displayName: Use NuGet 6.0.2 + continueOnError: True + inputs: + versionSpec: 6.0.2 + + - task: NuGetCommand@2 + displayName: NuGet restore + inputs: + command: 'restore' + restoreSolution: '$(Build.SourcesDirectory)\vsix\vsix.sln' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download x86 binaries' + inputs: + artifactName: 'drop_build_x86' + targetPath: '$(Build.SourcesDirectory)\x86' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download x64 binaries' + inputs: + artifactName: 'drop_build_x64' + targetPath: '$(Build.SourcesDirectory)\x64' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download arm binaries' + inputs: + artifactName: 'drop_build_arm' + targetPath: '$(Build.SourcesDirectory)\arm' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download arm64 binaries' + inputs: + artifactName: 'drop_build_arm64' + targetPath: '$(Build.SourcesDirectory)\arm64' + + - task: DownloadPipelineArtifact@2 + displayName: 'Download NuGet' + inputs: + artifactName: 'drop_NuGet_' + targetPath: '$(Pipeline.Workspace)\nuget' + + - task: VSBuild@1 + displayName: Build VSIX + inputs: + solution: $(Build.SourcesDirectory)\vsix\vsix.sln + msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog + platform: 'Any CPU' + configuration: ${{ parameters.BuildConfiguration }} + + - task: ExtractFiles@1 + displayName: Extract VSIX contents for signing + inputs: + archiveFilePatterns: '$(BuildFolder)\$(VsixFilename).vsix' + destinationFolder: '$(Agent.TempDirectory)\$(VsixFilename)' + overwriteExistingFiles: true + + - task: onebranch.pipeline.signing@1 + displayName: '🔒 Onebranch Signing for VSIX contents' + condition: eq(${{ parameters.OfficialBuild }}, 'true') + inputs: + command: sign + signing_profile: external_distribution + files_to_sign: '**/Microsoft.Windows.CppWinRT.*.dll' + search_root: '$(Agent.TempDirectory)\$(VsixFilename)' + + - task: ArchiveFiles@2 + displayName: 'Repack signed VSIX contents' + inputs: + rootFolderOrFile: '$(Agent.TempDirectory)\$(VsixFilename)' + includeRootFolder: false + archiveFile: '$(ob_outputDirectory)\$(VsixFilename).vsix' + + - task: onebranch.pipeline.signing@1 + displayName: '🔒 Onebranch Signing for VSIX' + condition: eq(${{ parameters.OfficialBuild }}, 'true') + inputs: + command: sign + signing_profile: external_distribution + files_to_sign: '$(VsixFilename).vsix' + search_root: '$(ob_outputDirectory)' + + - task: CopyFiles@2 + displayName: Stage VSIX Manifest + inputs: + SourceFolder: '$(Build.SourcesDirectory)\vsix' + Contents: | + extension.manifest.json + overview.md + TargetFolder: '$(ob_outputDirectory)' + + - task: CopyFiles@2 + displayName: Stage VSIX json and symbols + inputs: + SourceFolder: $(Buildfolder) + Contents: | + $(VsixFilename).pdb + $(VsixFilename).json + TargetFolder: '$(ob_outputDirectory)' + diff --git a/.pipelines/variables/OneBranchVariables.yml b/.pipelines/variables/OneBranchVariables.yml new file mode 100644 index 000000000..42f17e75c --- /dev/null +++ b/.pipelines/variables/OneBranchVariables.yml @@ -0,0 +1,16 @@ +parameters: +- name: 'debug' + displayName: 'Enable debug output' + type: boolean + default: false + +variables: + system.debug: ${{ parameters.debug }} + ENABLE_PRS_DELAYSIGN: 1 + NUGET_XMLDOC_MODE: none + + # Docker image which is used to build the project https://aka.ms/obpipelines/containers + WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022@sha256:57a4885980ad4deec119d0e3c84abeebc57573c03b3da0ea63971fc9c0eadf45' + + Codeql.Enabled: true # CodeQL once every 3 days on the default branch for all languages its applicable to in that pipeline. + GDN_USE_DOTNET: true \ No newline at end of file diff --git a/.pipelines/variables/version.yml b/.pipelines/variables/version.yml new file mode 100644 index 000000000..576d896eb --- /dev/null +++ b/.pipelines/variables/version.yml @@ -0,0 +1,7 @@ +variables: + MajorVersion: "2" + MinorVersion: "0" + VersionDate: $[format('{0:yyMMdd}', pipeline.startTime)] + VersionCounter: $[counter(variables['VersionDate'], 1)] + BuildVersion: $(MajorVersion).$(MinorVersion).$(VersionDate).$(VersionCounter) + PatchVersion: $(VersionDate)$(VersionCounter) \ No newline at end of file From 65581a379f1be3ec74af510acb702c8da804597d Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Sat, 29 Apr 2023 14:53:13 -0500 Subject: [PATCH 185/305] Add `capture` support for unconventional result types (#1301) --- strings/base_com_ptr.h | 17 +++++++++--- test/old_tests/UnitTests/capture.cpp | 39 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 66dd2c9e7..14a9a0851 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -7,16 +7,27 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { + struct capture_decay + { + void** result; + + template + operator T** () + { + return reinterpret_cast(result); + } + }; + template int32_t capture_to(void**result, F function, Args&& ...args) { - return function(args..., guid_of(), result); + return function(args..., guid_of(), capture_decay{ result }); } template || std::is_union_v, int> = 0> int32_t capture_to(void** result, O* object, M method, Args&& ...args) { - return (object->*method)(args..., guid_of(), result); + return (object->*method)(args..., guid_of(), capture_decay{ result }); } template @@ -343,7 +354,7 @@ namespace winrt::impl template int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) { - return (object.get()->*(method))(args..., guid_of(), result); + return (object.get()->*(method))(args..., guid_of(), capture_decay{ result }); } } diff --git a/test/old_tests/UnitTests/capture.cpp b/test/old_tests/UnitTests/capture.cpp index c72f1ecff..3cfa2a684 100644 --- a/test/old_tests/UnitTests/capture.cpp +++ b/test/old_tests/UnitTests/capture.cpp @@ -8,6 +8,7 @@ struct DECLSPEC_UUID("5fb96f8d-409c-42a9-99a7-8a95c1459dbd") ICapture : ::IUnkno { virtual int32_t __stdcall GetValue() noexcept = 0; virtual int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept = 0; + virtual int32_t __stdcall CreateMemberCapture2(int32_t value, GUID const& iid, ::IUnknown** object) noexcept = 0; }; #ifdef __CRT_UUID_DECL @@ -33,6 +34,12 @@ struct Capture : implements auto capture = make(value); return capture->QueryInterface(iid, object); } + + int32_t __stdcall CreateMemberCapture2(int32_t value, GUID const& iid, ::IUnknown** object) noexcept override + { + auto capture = make(value); + return capture->QueryInterface(iid, reinterpret_cast(object)); + } }; HRESULT __stdcall CreateCapture(int value, GUID const& iid, void** object) noexcept @@ -41,6 +48,12 @@ HRESULT __stdcall CreateCapture(int value, GUID const& iid, void** object) noexc return capture->QueryInterface(iid, object); } +HRESULT __stdcall CreateCapture2(int value, GUID const& iid, ::IInspectable** object) noexcept +{ + auto capture = make(value); + return capture->QueryInterface(iid, reinterpret_cast(object)); +} + TEST_CASE("capture") { // Capture from global function. @@ -67,6 +80,19 @@ TEST_CASE("capture") com_ptr d; + // Capture with an unconventional result type. + auto e = capture(a, &ICapture::CreateMemberCapture2, 30); + REQUIRE(e->GetValue() == 30); + e = nullptr; + e.capture(a, &ICapture::CreateMemberCapture2, 40); + REQUIRE(e->GetValue() == 40); + + com_ptr f = capture(CreateCapture2, 10); + REQUIRE(f->GetValue() == 10); + f = nullptr; + f.capture(CreateCapture2, 20); + REQUIRE(a->GetValue() == 20); + REQUIRE_THROWS_AS(capture(CreateCapture, 0), hresult_no_interface); REQUIRE_THROWS_AS(d.capture(CreateCapture, 0), hresult_no_interface); REQUIRE_THROWS_AS(capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface); @@ -104,6 +130,19 @@ TEST_CASE("try_capture") com_ptr d; + // Capture with an unconventional result type. + auto e = try_capture(a, &ICapture::CreateMemberCapture2, 30); + REQUIRE(e->GetValue() == 30); + e = nullptr; + REQUIRE(e.try_capture(a, &ICapture::CreateMemberCapture2, 40)); + REQUIRE(e->GetValue() == 40); + + com_ptr f = try_capture(CreateCapture2, 10); + REQUIRE(f->GetValue() == 10); + f = nullptr; + REQUIRE(f.try_capture(CreateCapture2, 20)); + REQUIRE(f->GetValue() == 20); + REQUIRE(!try_capture(CreateCapture, 0)); REQUIRE(!d.try_capture(CreateCapture, 0)); REQUIRE(!try_capture(a, &ICapture::CreateMemberCapture, 0)); From 49b2cab4ce04cb62b59a947dd6d6add2b4be509b Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 11 May 2023 03:55:38 -0700 Subject: [PATCH 186/305] Remove ARM OneBranch build workaround (#1303) --- .pipelines/variables/OneBranchVariables.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pipelines/variables/OneBranchVariables.yml b/.pipelines/variables/OneBranchVariables.yml index 42f17e75c..8e6ad8af0 100644 --- a/.pipelines/variables/OneBranchVariables.yml +++ b/.pipelines/variables/OneBranchVariables.yml @@ -10,7 +10,7 @@ variables: NUGET_XMLDOC_MODE: none # Docker image which is used to build the project https://aka.ms/obpipelines/containers - WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022@sha256:57a4885980ad4deec119d0e3c84abeebc57573c03b3da0ea63971fc9c0eadf45' + WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' Codeql.Enabled: true # CodeQL once every 3 days on the default branch for all languages its applicable to in that pipeline. GDN_USE_DOTNET: true \ No newline at end of file From 45872647571996c6bb8dad944994456d3383e255 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 15 May 2023 11:19:04 -0700 Subject: [PATCH 187/305] Remove explicitly setting PreferredToolArchitecture, since VS 2022 handles this more comprehensively (#1304) --- nuget/Microsoft.Windows.CppWinRT.props | 1 - 1 file changed, 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.props b/nuget/Microsoft.Windows.CppWinRT.props index e1d9b4716..60736e177 100644 --- a/nuget/Microsoft.Windows.CppWinRT.props +++ b/nuget/Microsoft.Windows.CppWinRT.props @@ -13,7 +13,6 @@ Copyright (C) Microsoft Corporation. All rights reserved. - x64 true true false From 858d50369ab845db3b0c178b6632bb8e13f4d142 Mon Sep 17 00:00:00 2001 From: alvinhochun Date: Tue, 16 May 2023 21:23:36 +0800 Subject: [PATCH 188/305] Disable MSYS2 mingw32 CI due to running out of memory (#1305) --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc7a854e0..503c3d4b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -314,7 +314,8 @@ jobs: fail-fast: false matrix: include: - - { sys: mingw32, arch: i686, config: Release } + # 32-bit builds are running out of memory + # - { sys: mingw32, arch: i686, config: Release } - { sys: mingw64, arch: x86_64, config: Debug } - { sys: mingw64, arch: x86_64, config: Release } - { sys: ucrt64, arch: x86_64, config: Release } From 780e09599b33e7268913f0f2d10545ba7d277adf Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 17 May 2023 12:26:26 -0500 Subject: [PATCH 189/305] Add UTF-8 path support (#1307) --- cppwinrt/app.manifest | 1 + 1 file changed, 1 insertion(+) diff --git a/cppwinrt/app.manifest b/cppwinrt/app.manifest index 16b477c20..69b366b27 100644 --- a/cppwinrt/app.manifest +++ b/cppwinrt/app.manifest @@ -3,6 +3,7 @@ true + UTF-8 \ No newline at end of file From 0e740b1bae4578ce0c5b2ff9b7778fee167160e7 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Wed, 24 May 2023 09:16:44 -0400 Subject: [PATCH 190/305] Update issue template to use `cpp` instead of `rust` (#1313) --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 03cd0d44b..748763028 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -34,7 +34,7 @@ body: Uri uri(L"https://kennykerr.ca"); printf("%ls\n", uri.ToString().c_str()); } - render: rust + render: cpp - type: textarea attributes: label: Expected behavior From e2dc21469b91006fa25ef5081e2f953dee77c881 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Sat, 27 May 2023 14:38:18 -0500 Subject: [PATCH 191/305] Update readme --- README.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/README.md b/README.md index 57ee9502f..91e20bb19 100644 --- a/README.md +++ b/README.md @@ -18,17 +18,3 @@ If you really want to build it yourself, the simplest way to do so is to run the * Build the x64 Release configuration of the `prebuild` and `cppwinrt` projects only. Do not attempt to build anything else just yet. * Run `build_projection.cmd` in the dev command prompt. * Switch to the x64 Debug configuration in Visual Studio and build all projects as needed. - -# Contributing - -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. - -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. From ed6a1e37a2db50176b1a5ad9cf22c501a242ba20 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 30 May 2023 08:42:50 -0500 Subject: [PATCH 192/305] Update open source docs (#1315) --- CODE_OF_CONDUCT.md => docs/code_of_conduct.md | 2 +- docs/contributing.md | 13 +++++++++++++ SECURITY.md => docs/security.md | 18 +++++++++--------- 3 files changed, 23 insertions(+), 10 deletions(-) rename CODE_OF_CONDUCT.md => docs/code_of_conduct.md (93%) create mode 100644 docs/contributing.md rename SECURITY.md => docs/security.md (72%) diff --git a/CODE_OF_CONDUCT.md b/docs/code_of_conduct.md similarity index 93% rename from CODE_OF_CONDUCT.md rename to docs/code_of_conduct.md index f9ba8cf65..6257f2e76 100644 --- a/CODE_OF_CONDUCT.md +++ b/docs/code_of_conduct.md @@ -6,4 +6,4 @@ Resources: - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) -- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns +- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 000000000..0c5c1ee9c --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,13 @@ +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/SECURITY.md b/docs/security.md similarity index 72% rename from SECURITY.md rename to docs/security.md index e0dfff56a..b8a28b1c5 100644 --- a/SECURITY.md +++ b/docs/security.md @@ -1,20 +1,20 @@ - + ## Security -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below. +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. ## Reporting Security Issues **Please do not report security vulnerabilities through public GitHub issues.** -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: @@ -28,7 +28,7 @@ Please include the requested information listed below (as much as you can provid This information will help us triage your report more quickly. -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. ## Preferred Languages @@ -36,6 +36,6 @@ We prefer all communications to be in English. ## Policy -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). - + \ No newline at end of file From c24bc391ed1a9976ededf46d1111cd609ae5d02c Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 8 Jun 2023 12:18:38 -0500 Subject: [PATCH 193/305] Fix workflow trigger (#1321) --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 503c3d4b0..f96dfad43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,8 @@ name: CI Tests + on: - push: pull_request: + push: branches: - master From ec54c402156f263f8447ab78d7af31290dfd2538 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Wed, 21 Jun 2023 15:16:35 -0500 Subject: [PATCH 194/305] Clarify contributing guide (#1324) --- .github/pull_request_template.md | 3 +++ docs/contributing.md | 19 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..88999e247 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,3 @@ +What's this all about? + +Fixes: #0000 ⬅️ Be sure to refer to an existing issue here! diff --git a/docs/contributing.md b/docs/contributing.md index 0c5c1ee9c..9671ac0f7 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,8 +1,21 @@ ## Contributing -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. +Thanks for your interest in C++/WinRT! You are welcome to contribute by filing issues for problems you encounter. +Project maintainers will consider changes that improve compatibility or fix bugs. + +The following process is required in order to have a pull request considered: + +* File an issue for any change you would like to propose. This can start a discussion so we can agree on an approach +before you invest a large amount of time. Due to the large number of dependent projects, contributions that include +compatibility risk or added complexity will generally be rejected. + +* Contributors will need the help of a project maintainer to verify the change with the Windows operating system +build system. If a project maintainer is available to provide guidance and mentorship for the change, a pull request +may be opened to begin the formal review process. + +Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that +you have the right to, and actually do, grant us the rights to use your contribution. For details, +visit https://cla.opensource.microsoft.com. When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions From d3bb275464b03855c3e566af633cc90f3bf94f27 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Thu, 22 Jun 2023 10:39:33 -0700 Subject: [PATCH 195/305] Fix source location test failure resulting from newer compiler (#1326) --- test/test_cpp20/custom_error.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index 2714fa837..34a0ea38f 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -61,13 +61,10 @@ TEST_CASE("custom_error_logger") REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); const auto functionNameSv = std::string_view(s_loggerArgs.functionName); REQUIRE(!functionNameSv.empty()); -#if defined(__GNUC__) && !defined(__clang__) - REQUIRE(functionNameSv == "void {anonymous}::FailOnLine15()"); -#elif defined(__GNUC__) && defined(__clang__) - REQUIRE(functionNameSv == "void (anonymous namespace)::FailOnLine15()"); -#else - REQUIRE(functionNameSv == "FailOnLine15"); -#endif + // Every compiler has a slightly different naming approach for this function, and even the same + // compiler can change its mind over time. Instead of matching the entire function name just + // match against the part we care about. + REQUIRE((functionNameSv.find("FailOnLine15") != std::string_view::npos)); REQUIRE(s_loggerArgs.returnAddress); REQUIRE(s_loggerArgs.result == static_cast(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) From 297454ee285476f16bf11425bd60daf4593b66ee Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Tue, 27 Jun 2023 12:40:35 -0400 Subject: [PATCH 196/305] Allow classic COM interfaces with get_self (#1314) * Allow classic COM interfaces with get_self Fixes #1312 * Fix mingw builds --------- Co-authored-by: Kenny Kerr --- strings/base_implements.h | 6 ++++ strings/base_meta.h | 3 ++ test/old_tests/UnitTests/interop.cpp | 49 ++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/strings/base_implements.h b/strings/base_implements.h index ca69bc38b..0c0ff0684 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -242,6 +242,12 @@ WINRT_EXPORT namespace winrt return &static_cast>*>(get_abi(from))->shim(); } + template + D* get_self(com_ptr const& from) noexcept + { + return static_cast(static_cast*>(from.get())); + } + template [[deprecated]] D* from_abi(I const& from) noexcept { diff --git a/strings/base_meta.h b/strings/base_meta.h index 54d41e61b..f474fced4 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -13,6 +13,9 @@ WINRT_EXPORT namespace winrt template struct com_ptr; + template + D* get_self(com_ptr const& from) noexcept; + namespace param { template diff --git a/test/old_tests/UnitTests/interop.cpp b/test/old_tests/UnitTests/interop.cpp index 1f3ae56fd..357904a19 100644 --- a/test/old_tests/UnitTests/interop.cpp +++ b/test/old_tests/UnitTests/interop.cpp @@ -7,6 +7,10 @@ using namespace Windows::Foundation; namespace { + struct IClassicComInterface : ::IUnknown {}; + + struct ClassicCom : implements {}; + struct Stringable : implements { Stringable(std::wstring_view const& value = L"Stringable") : m_value(value) @@ -30,8 +34,16 @@ namespace object->AddRef(); return object->Release(); } + + template + uint32_t get_ref_count(com_ptr const& object) + { + return get_ref_count(object.get()); + } } +template <> inline constexpr winrt::guid winrt::impl::guid_v{ 0xc136bb75, 0xbc03, 0x41a6, { 0xa5, 0xdc, 0x5e, 0xfa, 0x67, 0x92, 0x4e, 0xbf } }; + TEST_CASE("interop") { uint32_t const before = get_module_lock(); @@ -108,6 +120,43 @@ TEST_CASE("self") REQUIRE(get_ref_count(object) == 1); object = nullptr; + strong = weak.get(); + REQUIRE(!strong); +} + +TEST_CASE("self_classic_com") +{ + com_ptr strong = make_self(); + + REQUIRE(get_ref_count(strong.get()) == 1); + + com_ptr object = strong.as(); + + REQUIRE(get_ref_count(strong.get()) == 2); + + ClassicCom* ptr = get_self(object); + REQUIRE(ptr == strong.get()); + + REQUIRE(get_ref_count(strong.get()) == 2); + strong = nullptr; + REQUIRE(get_ref_count(object) == 1); + + strong = get_self(object)->get_strong(); + REQUIRE(get_ref_count(object) == 2); + strong = nullptr; + REQUIRE(get_ref_count(object) == 1); + + weak_ref weak = get_self(object)->get_weak(); + REQUIRE(get_ref_count(object) == 1); // <-- still just one! + + strong = weak.get(); + REQUIRE(strong); + REQUIRE(get_ref_count(object) == 2); + + strong = nullptr; + REQUIRE(get_ref_count(object) == 1); + object = nullptr; + strong = weak.get(); REQUIRE(!strong); } \ No newline at end of file From 953d65cc85d5fb75986c4bcdb024f4906a367ee0 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 10 Jul 2023 18:16:10 -0400 Subject: [PATCH 197/305] Register event handlers with `shared_ptr` and `weak_ptr` (#1330) --- cppwinrt/code_writers.h | 36 ++++++++ strings/base_delegate.h | 10 +++ .../UnitTests/delegate_weak_strong.cpp | 85 ++++++++++++++++++- test/test/variadic_delegate.cpp | 52 ++++++++++++ 4 files changed, 180 insertions(+), 3 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index e0162fe45..df5dd0c35 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2446,6 +2446,8 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable template %(O* object, M method); template %(com_ptr&& object, M method); template %(weak_ref&& object, M method); + template %(std::shared_ptr&& object, M method); + template %(std::weak_ptr&& object, M method); auto operator()(%) const; }; )"; @@ -2462,6 +2464,8 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable type_name, type_name, type_name, + type_name, + type_name, bind(signature)); } @@ -2523,6 +2527,14 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable %([o = std::move(object), method](auto&&... args) { if (auto s = o.get()) { ((*s).*(method))(args...); } }) { } + template <%> template %<%>::%(std::shared_ptr&& object, M method) : + %([o = std::move(object), method](auto&&... args) { return ((*o).*(method))(args...); }) + { + } + template <%> template %<%>::%(std::weak_ptr&& object, M method) : + %([o = std::move(object), method](auto&&... args) { if (auto s = o.lock()) { ((*s).*(method))(args...); } }) + { + } template <%> auto %<%>::operator()(%) const {% check_hresult((*(impl::abi_t<%<%>>**)this)->Invoke(%));% @@ -2562,6 +2574,16 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable bind(generics), type_name, bind_list(", ", generics), + type_name, + type_name, + bind(generics), + type_name, + bind_list(", ", generics), + type_name, + type_name, + bind(generics), + type_name, + bind_list(", ", generics), bind(signature), bind(signature, true), type_name, @@ -2591,6 +2613,14 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable %([o = std::move(object), method](auto&&... args) { if (auto s = o.get()) { ((*s).*(method))(args...); } }) { } + template %::%(std::shared_ptr&& object, M method) : + %([o = std::move(object), method](auto&&... args) { return ((*o).*(method))(args...); }) + { + } + template %::%(std::weak_ptr&& object, M method) : + %([o = std::move(object), method](auto&&... args) { if (auto s = o.lock()) { ((*s).*(method))(args...); } }) + { + } inline auto %::operator()(%) const {% check_hresult((*(impl::abi_t<%>**)this)->Invoke(%));% @@ -2615,6 +2645,12 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable type_name, type_name, type_name, + type_name, + type_name, + type_name, + type_name, + type_name, + type_name, bind(signature), bind(signature, true), type_name, diff --git a/strings/base_delegate.h b/strings/base_delegate.h index e99fd4813..59c4bfdbe 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -179,6 +179,16 @@ namespace winrt::impl { } + template delegate_base(std::shared_ptr&& object, M method) : + delegate_base([o = std::move(object), method](auto&& ... args) { return ((*o).*(method))(args...); }) + { + } + + template delegate_base(std::weak_ptr&& object, M method) : + delegate_base([o = std::move(object), method](auto&& ... args) { if (auto s = o.lock()) { ((*s).*(method))(args...); } }) + { + } + auto operator()(Args const& ... args) const { return (*(variadic_delegate_abi * *)this)->invoke(args...); diff --git a/test/old_tests/UnitTests/delegate_weak_strong.cpp b/test/old_tests/UnitTests/delegate_weak_strong.cpp index b042d6da0..30b02672a 100644 --- a/test/old_tests/UnitTests/delegate_weak_strong.cpp +++ b/test/old_tests/UnitTests/delegate_weak_strong.cpp @@ -31,6 +31,25 @@ namespace } }; + template + struct ObjectStd : std::enable_shared_from_this> + { + ~ObjectStd() + { + destroyed = true; + } + + void StrongHandler(Sender const&, Args const&) + { + ++strong_count; + } + + void WeakHandler(Sender const&, Args const&) + { + ++weak_count; + } + }; + struct ReturnObject : implements { ~ReturnObject() @@ -44,8 +63,21 @@ namespace } }; + struct ReturnObjectStd : std::enable_shared_from_this + { + ~ReturnObjectStd() + { + destroyed = true; + } + + int Handler(int a, int b) + { + return a + b; + } + }; + template - void test_delegate() + void test_delegate_winrt() { auto object = make_self>(); @@ -81,6 +113,51 @@ namespace weak({}, {}); REQUIRE(weak_count == 2); } + + template + void test_delegate_std() + { + auto object = std::make_shared>(); + + Delegate strong{ object->shared_from_this(), &ObjectStd::StrongHandler }; + Delegate weak{ object->weak_from_this(), &ObjectStd::WeakHandler }; + + destroyed = false; + strong_count = 0; + weak_count = 0; + + // Both weak and strong handlers + strong({}, {}); + weak({}, {}); + REQUIRE(strong_count == 1); + REQUIRE(weak_count == 1); + + // Local 'object' strong reference is released + object = nullptr; + + // Still both since strong handler keeps object alive + strong({}, {}); + weak({}, {}); + REQUIRE(strong_count == 2); + REQUIRE(weak_count == 2); + + // ~Object is called since the strong delegate is destroyed + REQUIRE(!destroyed); + strong = nullptr; + REQUIRE(destroyed); + + // Weak delegate remains but no longer fires + REQUIRE(weak_count == 2); + weak({}, {}); + REQUIRE(weak_count == 2); + } + + template + void test_delegate() + { + test_delegate_winrt(); + test_delegate_std(); + } } TEST_CASE("delegate_weak_strong") @@ -111,8 +188,10 @@ TEST_CASE("delegate_weak_strong") // scenarios such as callbacks so weak support isn't interesting anyway, but it does work with get_strong. auto object = make_self(); - Component::TwoArgDelegateReturn strong{ object->get_strong(), &ReturnObject::Handler }; - REQUIRE(5 == strong(2, 3)); + + auto objectStd = std::make_shared(); + Component::TwoArgDelegateReturn strongStd{ objectStd->shared_from_this(), &ReturnObjectStd::Handler }; + REQUIRE(5 == strongStd(2, 3)); } diff --git a/test/test/variadic_delegate.cpp b/test/test/variadic_delegate.cpp index 6ffbe5ef4..7291ddbeb 100644 --- a/test/test/variadic_delegate.cpp +++ b/test/test/variadic_delegate.cpp @@ -40,6 +40,20 @@ namespace return L"Object"; } }; + + struct ObjectStd : std::enable_shared_from_this + { + int& m_count; + + ObjectStd(int& count) : m_count(count) + { + } + + void Callback() + { + ++m_count; + } + }; } TEST_CASE("variadic_delegate") @@ -100,6 +114,44 @@ TEST_CASE("variadic_delegate") REQUIRE(count == 2); // Unchanged } + // shared_from_this + { + int count{}; + auto object = std::make_shared(count); + + delegate<> up{ object->shared_from_this(), &ObjectStd::Callback }; + + REQUIRE(count == 0); + up(); + REQUIRE(count == 1); + up(); + REQUIRE(count == 2); + + object = nullptr; + + up(); + REQUIRE(count == 3); + } + + // weak_from_this + { + int count{}; + auto object = std::make_shared(count); + + delegate<> up{ object->weak_from_this(), &ObjectStd::Callback }; + + REQUIRE(count == 0); + up(); + REQUIRE(count == 1); + up(); + REQUIRE(count == 2); + + object = nullptr; + + up(); + REQUIRE(count == 2); // Unchanged + } + // Mixed arguments { int count{}; From 0958cf3a4d572b54d14a06e9d506a1ddd09fae2e Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Tue, 11 Jul 2023 22:38:42 -0400 Subject: [PATCH 198/305] Hide protected and overridable members from public projections (#1319) --- README.md | 12 +++- build_prior_projection.cmd | 50 ++++++++++++++ build_projection.cmd | 9 ++- build_test_all.cmd | 2 +- cppwinrt/code_writers.h | 67 +++++++++++++++---- cppwinrt/component_writers.h | 41 ++++++++++-- cppwinrt/helpers.h | 2 + prepare_versionless_diffs.cmd | 41 ++++++++++++ test/old_tests/Composable/Base.cpp | 5 ++ test/old_tests/Composable/Base.h | 1 + test/old_tests/Composable/Composable.idl | 8 +++ test/old_tests/Composable/Derived.cpp | 5 ++ test/old_tests/Composable/Derived.h | 1 + test/old_tests/UnitTests/Composable.cpp | 30 ++++++++- test/test_component_base/HierarchyA.cpp | 10 +++ test/test_component_base/HierarchyA.h | 2 + test/test_component_base/HierarchyB.cpp | 8 +++ test/test_component_base/HierarchyB.h | 2 + .../test_component_base.idl | 4 ++ .../Nested.HierarchyC.cpp | 5 +- .../Nested.HierarchyD.cpp | 3 + 21 files changed, 286 insertions(+), 22 deletions(-) create mode 100644 build_prior_projection.cmd create mode 100644 prepare_versionless_diffs.cmd diff --git a/README.md b/README.md index 91e20bb19..2dcfdd69c 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,16 @@ If you really want to build it yourself, the simplest way to do so is to run the * Open a dev command prompt pointing at the root of the repo. * Open the `cppwinrt.sln` solution. -* Build the x64 Release configuration of the `prebuild` and `cppwinrt` projects only. Do not attempt to build anything else just yet. +* Build the x64 Release configuration of the `cppwinrt` project only. Do not attempt to build anything else just yet. * Run `build_projection.cmd` in the dev command prompt. * Switch to the x64 Debug configuration in Visual Studio and build all projects as needed. + +## Comparing Outputs + +Comparing the output of the prior release and your current changes will help show the impact of any updates. Starting from +a dev command prompt at the root of the repo _after_ following the above build instructions: + +* Run `build_projection.cmd` in the dev command prompt +* Run `build_prior_projection.cmd` in the dev command prompt as well +* Run `prepare_versionless_diffs.cmd` which removes version stamps on both current and prior projection +* Use a directory-level differencing tool to compare `_build\$(arch)\$(flavor)\winrt` and `_reference\$(arch)\$(flavor)\winrt` diff --git a/build_prior_projection.cmd b/build_prior_projection.cmd new file mode 100644 index 000000000..c7bdf2f64 --- /dev/null +++ b/build_prior_projection.cmd @@ -0,0 +1,50 @@ +@echo off + +setlocal ENABLEDELAYEDEXPANSION + +set target_platform=%1 +set target_configuration=%2 +if "%target_platform%"=="" set target_platform=x64 + +if /I "%target_platform%" equ "all" ( + if "%target_configuration%"=="" ( + set target_configuration=all + ) + call %0 x86 !target_configuration! + call %0 x64 !target_configuration! + call %0 arm !target_configuration! + call %0 arm64 !target_configuration! + goto :eof +) + +if /I "%target_configuration%" equ "all" ( + call %0 %target_platform% Debug + call %0 %target_platform% Release + goto :eof +) + +if "%target_configuration%"=="" ( + set target_configuration=Debug +) + +set reference_output=%~p0\_reference\%target_platform%\%target_configuration% +if exist "%reference_output%" ( + echo Removing existing reference projections + rmdir /s /q "%reference_output%" +) + +if not exist ".\.nuget" mkdir ".\.nuget" +if not exist ".\.nuget\nuget.exe" powershell -Command "$ProgressPreference = 'SilentlyContinue' ; Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\.nuget\nuget.exe" + +mkdir %reference_output%\package +.\.nuget\nuget.exe install Microsoft.Windows.CppWinRT -o %reference_output%\package +set reference_cppwinrt= +for /F "delims=" %%a in ('dir /s /b %reference_output%\package\cppwinrt.exe') DO set reference_cppwinrt=%%a +if "%reference_cppwinrt%"=="" ( + echo Could not find the reference cppwinrt.exe under %reference_output%\package + goto :EOF +) + +echo Generating reference projection from %reference_cppwinrt% to %reference_output%\cppwinrt +%reference_cppwinrt% -in local -out %reference_output% -verbose +echo. diff --git a/build_projection.cmd b/build_projection.cmd index 9480b5ec0..778fa7aca 100644 --- a/build_projection.cmd +++ b/build_projection.cmd @@ -27,6 +27,13 @@ if "%target_configuration%"=="" ( set target_configuration=Debug ) +set cppwinrt_exe=%~p0\_build\x64\Release\cppwinrt.exe + +if not exist "%cppwinrt_exe%" ( + echo Remember to build the "prebuild" and then "cppwinrt" projects for Release x64 first + goto :eof +) + echo Building projection into %target_platform% %target_configuration% -%~p0\_build\x64\Release\cppwinrt.exe -in local -out %~p0\_build\%target_platform%\%target_configuration% -verbose +%cppwinrt_exe% -in local -out %~p0\_build\%target_platform%\%target_configuration% -verbose echo. diff --git a/build_test_all.cmd b/build_test_all.cmd index 6f7e24033..681f8c682 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -10,7 +10,7 @@ if "%target_configuration%"=="" set target_configuration=Release if "%target_version%"=="" set target_version=1.2.3.4 if not exist ".\.nuget" mkdir ".\.nuget" -if not exist ".\.nuget\nuget.exe" powershell -Command "Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\.nuget\nuget.exe" +if not exist ".\.nuget\nuget.exe" powershell -Command "$ProgressPreference = 'SilentlyContinue' ; Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\.nuget\nuget.exe" call .nuget\nuget.exe restore cppwinrt.sln" call .nuget\nuget.exe restore natvis\cppwinrtvisualizer.sln diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index df5dd0c35..a5c306fa5 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2035,13 +2035,39 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { for (auto&& [name, info] : interfaces) { - if (!info.overridable) + if (!info.overridable && !info.is_protected) { w.write(", %", name); } } } + static void write_class_override_protected_requires(writer& w, get_interfaces_t const& interfaces) + { + bool first = true; + + for (auto&& [name, info] : interfaces) + { + if (info.is_protected) + { + if (first) + { + first = false; + w.write(",\n protected impl::require'); + } + } + static void write_class_override_defaults(writer& w, get_interfaces_t const& interfaces) { bool first = true; @@ -2073,6 +2099,18 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable } } + static void write_class_override_friends(writer& w, get_interfaces_t const& interfaces) + { + for (auto&& [name, info] : interfaces) + { + if (info.is_protected) + { + w.write("\n friend impl::consume_t;", name); + w.write("\n friend impl::require_one;", name); + } + } + } + static void write_call_factory(writer& w, TypeDef const& type, TypeDef const& factory) { std::string factory_name; @@ -2243,10 +2281,10 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable auto format = R"( template struct %T : implements, - impl::require, + impl::require%, impl::base% { - using composable = %; + using composable = %;% protected: %% }; )"; @@ -2258,10 +2296,12 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable type_name, bind(interfaces), bind(interfaces), + bind(interfaces), type_name, bind(type), bind(interfaces), type_name, + bind(interfaces), bind(type, factories), bind(interfaces)); } @@ -2326,18 +2366,21 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable for (auto&& [interface_name, info] : get_interfaces(w, type)) { - if (info.defaulted && !info.base) + if (!info.is_protected && !info.overridable) { - for (auto&& method : info.type.MethodList()) + if (info.defaulted && !info.base) { - method_usage[get_name(method)].insert(default_interface_name); + for (auto&& method : info.type.MethodList()) + { + method_usage[get_name(method)].insert(default_interface_name); + } } - } - else - { - for (auto&& method : info.type.MethodList()) + else { - method_usage[get_name(method)].insert(interface_name); + for (auto&& method : info.type.MethodList()) + { + method_usage[get_name(method)].insert(interface_name); + } } } } @@ -2804,7 +2847,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable for (auto&& [interface_name, info] : get_interfaces(w, type)) { - if (!info.defaulted || info.base) + if ((!info.defaulted || info.base) && (!info.is_protected && !info.overridable)) { if (first) { diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 1f6a2dbf1..4a2cce556 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -743,13 +743,13 @@ catch (...) { return winrt::to_hresult(); } auto format = R"(namespace winrt::@::implementation { template - struct WINRT_IMPL_EMPTY_BASES %_base : implements%%% + struct WINRT_IMPL_EMPTY_BASES %_base : implements%%%% { using base_type = %_base; using class_type = @::%; using implements_type = typename %_base::implements_type; using implements_type::implements_type; - % + %% hstring GetRuntimeClassName() const { return L"%.%"; @@ -764,6 +764,8 @@ catch (...) { return winrt::to_hresult(); } std::string base_type_argument; std::string no_module_lock; std::string external_requires; + std::string external_protected_requires; + std::string friends; if (base_type) { @@ -774,7 +776,9 @@ catch (...) { return winrt::to_hresult(); } composable_base_name = w.write_temp("using composable_base = %;", base_type); auto base_interfaces = get_interfaces(w, base_type); uint32_t base_interfaces_count{}; + uint32_t protected_base_interfaces_count{}; external_requires = ",\n impl::require(type), bind(type), type_name, @@ -823,6 +853,7 @@ catch (...) { return winrt::to_hresult(); } type_name, type_name, composable_base_name, + friends, type_namespace, type_name, bind(type), diff --git a/cppwinrt/helpers.h b/cppwinrt/helpers.h index a3b865b6e..522d0bcd1 100644 --- a/cppwinrt/helpers.h +++ b/cppwinrt/helpers.h @@ -527,6 +527,7 @@ namespace cppwinrt { TypeDef type; bool is_default{}; + bool is_protected{}; bool defaulted{}; bool overridable{}; bool base{}; @@ -577,6 +578,7 @@ namespace cppwinrt auto type = impl.Interface(); auto name = w.write_temp("%", type); info.is_default = has_attribute(impl, "Windows.Foundation.Metadata", "DefaultAttribute"); + info.is_protected = has_attribute(impl, "Windows.Foundation.Metadata", "ProtectedAttribute"); info.defaulted = !base && (defaulted || info.is_default); { diff --git a/prepare_versionless_diffs.cmd b/prepare_versionless_diffs.cmd new file mode 100644 index 000000000..468645657 --- /dev/null +++ b/prepare_versionless_diffs.cmd @@ -0,0 +1,41 @@ +@echo off + +setlocal ENABLEDELAYEDEXPANSION + +set target_platform=%1 +set target_configuration=%2 +if "%target_platform%"=="" set target_platform=x64 + +if /I "%target_platform%" equ "all" ( + if "%target_configuration%"=="" ( + set target_configuration=all + ) + call %0 x86 !target_configuration! + call %0 x64 !target_configuration! + call %0 arm !target_configuration! + call %0 arm64 !target_configuration! + goto :eof +) + +if /I "%target_configuration%" equ "all" ( + call %0 %target_platform% Debug + call %0 %target_platform% Release + goto :eof +) + +if "%target_configuration%"=="" ( + set target_configuration=Debug +) + +set reference_output=%~p0\_reference\%target_platform%\%target_configuration% +set build_output=%~p0\_build\%target_platform%\%target_configuration% + +echo Removing version stamps from %reference_output%\winrt +pushd %reference_output%\winrt +powershell -Command "gci -r -include *.h,*.ixx | %%{ (get-content $_) -replace 'was generated by.*|CPPWINRT_VERSION.*','' | set-content $_ }" +popd + +echo Removing version stamps from %build_output%\winrt +pushd %build_output%\winrt +powershell -Command "gci -r -include *.h,*.ixx | %%{ (get-content $_) -replace 'was generated by.*|CPPWINRT_VERSION.*','' | set-content $_ }" +popd diff --git a/test/old_tests/Composable/Base.cpp b/test/old_tests/Composable/Base.cpp index 77ded2403..a1a1678ff 100644 --- a/test/old_tests/Composable/Base.cpp +++ b/test/old_tests/Composable/Base.cpp @@ -41,6 +41,11 @@ namespace winrt::Composable::implementation return 42; } + int32_t Base::ProtectedMethod() + { + return 0xDEADBEEF; + } + hstring Base::Name() const { return m_name; diff --git a/test/old_tests/Composable/Base.h b/test/old_tests/Composable/Base.h index bbc05d820..4b23c6c88 100644 --- a/test/old_tests/Composable/Base.h +++ b/test/old_tests/Composable/Base.h @@ -18,6 +18,7 @@ namespace winrt::Composable::implementation hstring OverridableMethod() ; virtual hstring OverridableVirtualMethod(); int32_t OverridableNoexceptMethod() noexcept; + int32_t ProtectedMethod(); hstring Name() const; diff --git a/test/old_tests/Composable/Composable.idl b/test/old_tests/Composable/Composable.idl index 83e0c5868..7f298e195 100644 --- a/test/old_tests/Composable/Composable.idl +++ b/test/old_tests/Composable/Composable.idl @@ -39,10 +39,17 @@ namespace Composable HRESULT OverridableVirtualMethod([out, retval] HSTRING* value); [noexcept2] HRESULT OverridableNoexceptMethod([out, retval] int* value); }; + + [version(1.0), uuid(6EA77EAE-56BC-419D-AE70-211C1A631496), exclusiveto(Base)] + interface IBaseProtected : IInspectable + { + HRESULT ProtectedMethod([out, retval] int* value); + }; [version(1.0), uuid(5f3996e1-3cf7-4716-9a3d-11eb5d32caff), exclusiveto(Derived)] interface IDerived : IInspectable { + HRESULT CallProtectedMethod([out, retval] int* value); }; [version(1.0), uuid(56dc2c28-edd1-4fa3-91e5-f63c3db47070), exclusiveto(Derived)] @@ -60,6 +67,7 @@ namespace Composable { [default] interface IBase; [overridable] interface Composable.IBaseOverrides; + [protected] interface Composable.IBaseProtected; }; [composable(Composable.IDerivedFactory, public, 1.0)] diff --git a/test/old_tests/Composable/Derived.cpp b/test/old_tests/Composable/Derived.cpp index b4c74e433..19fdbcc77 100644 --- a/test/old_tests/Composable/Derived.cpp +++ b/test/old_tests/Composable/Derived.cpp @@ -12,4 +12,9 @@ namespace winrt::Composable::implementation { return L"Derived::OverridableVirtualMethod"; } + + int32_t Derived::CallProtectedMethod() + { + return ProtectedMethod(); + } } diff --git a/test/old_tests/Composable/Derived.h b/test/old_tests/Composable/Derived.h index ff6d7778f..7d2463c81 100644 --- a/test/old_tests/Composable/Derived.h +++ b/test/old_tests/Composable/Derived.h @@ -14,6 +14,7 @@ namespace winrt::Composable::implementation hstring VirtualMethod() override; hstring OverridableVirtualMethod() override; + int32_t CallProtectedMethod(); }; } diff --git a/test/old_tests/UnitTests/Composable.cpp b/test/old_tests/UnitTests/Composable.cpp index 56fc97e1c..3cbc283d6 100644 --- a/test/old_tests/UnitTests/Composable.cpp +++ b/test/old_tests/UnitTests/Composable.cpp @@ -14,6 +14,7 @@ namespace constexpr auto Base_OverridableMethod{ L"Base::OverridableMethod"sv }; constexpr auto Base_OverridableVirtualMethod{ L"Base::OverridableVirtualMethod"sv }; constexpr auto Base_OverridableNoexceptMethod{ 42 }; + constexpr auto Base_ProtectedMethod{ 0xDEADBEEF }; constexpr auto Derived_VirtualMethod{ L"Derived::VirtualMethod"sv }; constexpr auto Derived_OverridableVirtualMethod{ L"Derived::OverridableVirtualMethod"sv }; @@ -61,12 +62,20 @@ TEST_CASE("Composable.OverriddenBase") { return OverriddenBase_OverridableNoexceptMethod; } + + int32_t CallProtectedMethod() + { + return ProtectedMethod(); + } }; - auto object = make(); + + auto object_self = make_self(); + auto object = object_self.as(); REQUIRE(object.VirtualMethod() == Base_VirtualMethod); REQUIRE(object.CallOverridableMethod() == OverriddenBase_OverridableMethod); REQUIRE(object.CallOverridableVirtualMethod() == OverriddenBase_OverridableVirtualMethod); REQUIRE(object.CallOverridableNoexceptMethod() == OverriddenBase_OverridableNoexceptMethod); + REQUIRE(object_self->CallProtectedMethod() == Base_ProtectedMethod); } { const std::wstring OverridableMethodResult = std::wstring(OverriddenBase_OverridableMethod) + L"=>" + Base_OverridableMethod.data(); @@ -106,6 +115,7 @@ TEST_CASE("Composable.Derived") REQUIRE(obj.CallOverridableMethod() == Base_OverridableMethod); REQUIRE(obj.CallOverridableVirtualMethod() == Derived_OverridableVirtualMethod); REQUIRE(obj.CallOverridableNoexceptMethod() == Base_OverridableNoexceptMethod); + REQUIRE(obj.CallProtectedMethod() == Base_ProtectedMethod); } namespace @@ -133,6 +143,24 @@ namespace CallIDerived(obj); CallDerived(obj); } + + template + struct has_ProtectedMember : std::false_type { }; + + template + struct has_ProtectedMember>> : std::true_type { }; + + // make sure we can't access protected members directly + static_assert(!has_ProtectedMember::value); + static_assert(!has_ProtectedMember::value); + static_assert(!has_ProtectedMember::value); + static_assert(!has_ProtectedMember::value); + + // make sure we can't implicitly convert to IBaseProtected + static_assert(!std::is_convertible_v); + static_assert(!std::is_convertible_v); + static_assert(!std::is_convertible_v); + static_assert(!std::is_convertible_v); } TEST_CASE("Composable conversions") diff --git a/test/test_component_base/HierarchyA.cpp b/test/test_component_base/HierarchyA.cpp index ab5ff5ea9..887b31bc9 100644 --- a/test/test_component_base/HierarchyA.cpp +++ b/test/test_component_base/HierarchyA.cpp @@ -7,6 +7,10 @@ namespace winrt::test_component_base::implementation { throw hresult_not_implemented(); } + HierarchyA::HierarchyA(int32_t dummy, hstring const& name) + { + throw hresult_not_implemented(); + } void HierarchyA::HierarchyA_Method() { //test_component_base::HierarchyA a = *this; @@ -15,4 +19,10 @@ namespace winrt::test_component_base::implementation //test_component_base::IHierarchyA ia = *this; //assert(a); } + int HierarchyA::HierarchyA_Protected() + { + return 42; + } + + static_assert(!std::is_constructible_v); } diff --git a/test/test_component_base/HierarchyA.h b/test/test_component_base/HierarchyA.h index bc574e3cc..ebca21e3a 100644 --- a/test/test_component_base/HierarchyA.h +++ b/test/test_component_base/HierarchyA.h @@ -8,7 +8,9 @@ namespace winrt::test_component_base::implementation HierarchyA() = default; HierarchyA(hstring const& name); + HierarchyA(int32_t dummy, hstring const& name); void HierarchyA_Method(); + int HierarchyA_Protected(); }; } namespace winrt::test_component_base::factory_implementation diff --git a/test/test_component_base/HierarchyB.cpp b/test/test_component_base/HierarchyB.cpp index 062015a5a..34c73104f 100644 --- a/test/test_component_base/HierarchyB.cpp +++ b/test/test_component_base/HierarchyB.cpp @@ -7,8 +7,16 @@ namespace winrt::test_component_base::implementation { throw hresult_not_implemented(); } + HierarchyB::HierarchyB(int32_t dummy, hstring const& name) : HierarchyB_base(dummy, name) + { + throw hresult_not_implemented(); + } void HierarchyB::HierarchyB_Method() { throw hresult_not_implemented(); } + void HierarchyB::HierarchyB_TestInnerProtected() + { + assert(HierarchyA_Protected() == 42); + } } diff --git a/test/test_component_base/HierarchyB.h b/test/test_component_base/HierarchyB.h index 3cce7c2ea..cff644ef8 100644 --- a/test/test_component_base/HierarchyB.h +++ b/test/test_component_base/HierarchyB.h @@ -9,7 +9,9 @@ namespace winrt::test_component_base::implementation HierarchyB() = default; HierarchyB(hstring const& name); + HierarchyB(int32_t dummy, hstring const& name); void HierarchyB_Method(); + void HierarchyB_TestInnerProtected(); }; } namespace winrt::test_component_base::factory_implementation diff --git a/test/test_component_base/test_component_base.idl b/test/test_component_base/test_component_base.idl index 5caff8906..9169b28b7 100644 --- a/test/test_component_base/test_component_base.idl +++ b/test/test_component_base/test_component_base.idl @@ -6,15 +6,19 @@ namespace test_component_base { HierarchyA(); HierarchyA(String name); + protected HierarchyA(Int32 dummy, String name); void HierarchyA_Method(); + protected Int32 HierarchyA_Protected(); } unsealed runtimeclass HierarchyB : HierarchyA { HierarchyB(); HierarchyB(String name); + protected HierarchyB(Int32 dummy, String name); void HierarchyB_Method(); + void HierarchyB_TestInnerProtected(); } } diff --git a/test/test_component_derived/Nested.HierarchyC.cpp b/test/test_component_derived/Nested.HierarchyC.cpp index a9c4fa2e2..f711adbd4 100644 --- a/test/test_component_derived/Nested.HierarchyC.cpp +++ b/test/test_component_derived/Nested.HierarchyC.cpp @@ -3,7 +3,7 @@ namespace winrt::test_component_derived::Nested::implementation { - HierarchyC::HierarchyC(hstring const& name) + HierarchyC::HierarchyC(hstring const& name) : HierarchyC_base(10, name) { throw hresult_not_implemented(); } @@ -11,4 +11,7 @@ namespace winrt::test_component_derived::Nested::implementation { throw hresult_not_implemented(); } + + static_assert(!std::is_convertible_v); + static_assert(!std::is_constructible_v); } diff --git a/test/test_component_derived/Nested.HierarchyD.cpp b/test/test_component_derived/Nested.HierarchyD.cpp index 286af6bbf..bad2cf1ce 100644 --- a/test/test_component_derived/Nested.HierarchyD.cpp +++ b/test/test_component_derived/Nested.HierarchyD.cpp @@ -32,5 +32,8 @@ namespace winrt::test_component_derived::Nested::implementation test_component_base::IHierarchyA ia = *this; assert(ia); + + assert(HierarchyA_Protected() == 42); + HierarchyB_TestInnerProtected(); } } From 4196e08bd2907707def400f8f83f176359d4adea Mon Sep 17 00:00:00 2001 From: Jon Wiswall Date: Wed, 9 Aug 2023 23:40:40 -0700 Subject: [PATCH 199/305] Increase foldability of various templates (#1338) * Add SDKReference-sourced WinMDs when building * Add solution items so they're more easily edited * Update development guidance slightly * First attempt at template folding * Make packages easier to build, remove warning about unreferenced static * Lift delegate creation out for better folding * More folding of events * Another delegate folded * PR feedback * Speculative improvement for QueryInterface * PR feedback --------- Co-authored-by: Jon Wiswall Co-authored-by: Kenny Kerr Co-authored-by: Jon Wiswall --- README.md | 4 +- build_nuget.cmd | 4 +- cppwinrt.sln | 13 ++++ nuget/Microsoft.Windows.CppWinRT.nuspec | 2 +- strings/base_delegate.h | 72 ++++++++++++---------- strings/base_events.h | 80 ++++++++++++++----------- strings/base_implements.h | 43 +++++++------ 7 files changed, 128 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index 2dcfdd69c..7e69fd979 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,13 @@ C++/WinRT is an entirely standard C++ language projection for Windows Runtime (W Don't build C++/WinRT yourself - just download the latest version here: https://aka.ms/cppwinrt/nuget +## Working on the compiler + If you really want to build it yourself, the simplest way to do so is to run the `build_test_all.cmd` script in the root directory. Developers needing to work on the C++/WinRT compiler itself should go through the following steps to arrive at an efficient inner loop: * Open a dev command prompt pointing at the root of the repo. * Open the `cppwinrt.sln` solution. -* Build the x64 Release configuration of the `cppwinrt` project only. Do not attempt to build anything else just yet. +* Rebuild the x64 Release configuration of the `cppwinrt` project only. Do not attempt to build anything else just yet. * Run `build_projection.cmd` in the dev command prompt. * Switch to the x64 Debug configuration in Visual Studio and build all projects as needed. diff --git a/build_nuget.cmd b/build_nuget.cmd index 068e1dfd0..cb950a625 100644 --- a/build_nuget.cmd +++ b/build_nuget.cmd @@ -1,7 +1,7 @@ rem @echo off set target_version=%1 -if "%target_version%"=="" set target_version=1.2.3.4 +if "%target_version%"=="" set target_version=3.0.0.0 call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd @@ -10,4 +10,4 @@ call msbuild /m /p:Configuration=Release,Platform=arm64,CppWinRTBuildVersion=%ta call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt -nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%cd%\_build\arm\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib +nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%cd%\_build\arm\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib diff --git a/cppwinrt.sln b/cppwinrt.sln index d56e050fb..8b162344f 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -115,6 +115,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocatio {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}" + ProjectSection(SolutionItems) = preProject + build_nuget.cmd = build_nuget.cmd + build_prior_projection.cmd = build_prior_projection.cmd + build_projection.cmd = build_projection.cmd + build_test_all.cmd = build_test_all.cmd + build_vsix.cmd = build_vsix.cmd + compile_tests.cmd = compile_tests.cmd + prepare_versionless_diffs.cmd = prepare_versionless_diffs.cmd + README.md = README.md + run_tests.cmd = run_tests.cmd + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM diff --git a/nuget/Microsoft.Windows.CppWinRT.nuspec b/nuget/Microsoft.Windows.CppWinRT.nuspec index a49f1eb8f..882931734 100644 --- a/nuget/Microsoft.Windows.CppWinRT.nuspec +++ b/nuget/Microsoft.Windows.CppWinRT.nuspec @@ -2,7 +2,7 @@ Microsoft.Windows.CppWinRT - 1.0.0.0 + $target_version$ C++/WinRT Build Support Microsoft Microsoft diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 59c4bfdbe..05742b610 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -6,39 +6,60 @@ namespace winrt::impl #pragma warning(disable:4458) // declaration hides class member (okay because we do not use named members of base class) #endif - template - struct implements_delegate : abi_t, H, update_module_lock + struct implements_delegate_base { - implements_delegate(H&& handler) : H(std::forward(handler)) + WINRT_IMPL_NOINLINE uint32_t increment_reference() noexcept { + return ++m_references; } - int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + WINRT_IMPL_NOINLINE uint32_t decrement_reference() noexcept + { + return --m_references; + } + + WINRT_IMPL_NOINLINE uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept { - if (is_guid_of(id) || is_guid_of(id) || is_guid_of(id)) + if (id == derivedId || is_guid_of(id) || is_guid_of(id)) { - *result = static_cast*>(this); - AddRef(); + *result = derivedAbiPtr; + increment_reference(); return 0; } if (is_guid_of(id)) { - return make_marshaler(this, result); + return make_marshaler(derivedAbiPtr, result); } *result = nullptr; return error_no_interface; } + private: + atomic_ref_count m_references{ 1 }; + }; + + template + struct implements_delegate : abi_t, implements_delegate_base, H, update_module_lock + { + implements_delegate(H&& handler) : H(std::forward(handler)) + { + } + + int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + { + return query_interface(id, result, static_cast*>(this), guid_of()); + } + uint32_t __stdcall AddRef() noexcept final { - return ++m_references; + return increment_reference(); } uint32_t __stdcall Release() noexcept final { - auto const remaining = --m_references; + auto const remaining = decrement_reference(); if (remaining == 0) { @@ -47,10 +68,6 @@ namespace winrt::impl return remaining; } - - private: - - atomic_ref_count m_references{ 1 }; }; template @@ -73,15 +90,16 @@ namespace winrt::impl return delegate; } + const auto id = guid_of(); com_ptr ref; - get_agile_reference(guid_of(), get_abi(delegate), ref.put_void()); + get_agile_reference(id, get_abi(delegate), ref.put_void()); if (ref) { - return [ref = std::move(ref)](auto&& ... args) + return [ref = std::move(ref), id](auto&& ... args) { T delegate; - ref->Resolve(guid_of(), put_abi(delegate)); + ref->Resolve(id, put_abi(delegate)); return delegate(args...); }; } @@ -97,7 +115,7 @@ namespace winrt::impl }; template - struct variadic_delegate final : variadic_delegate_abi, H, update_module_lock + struct variadic_delegate final : variadic_delegate_abi, implements_delegate_base, H, update_module_lock { variadic_delegate(H&& handler) : H(std::forward(handler)) { @@ -117,25 +135,17 @@ namespace winrt::impl int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final { - if (is_guid_of(id) || is_guid_of(id)) - { - *result = static_cast(this); - AddRef(); - return 0; - } - - *result = nullptr; - return error_no_interface; + return query_interface(id, result, static_cast(this), guid_of()); } uint32_t __stdcall AddRef() noexcept final { - return ++m_references; + return increment_reference(); } uint32_t __stdcall Release() noexcept final { - auto const remaining = --m_references; + auto const remaining = decrement_reference(); if (remaining == 0) { @@ -144,10 +154,6 @@ namespace winrt::impl return remaining; } - - private: - - atomic_ref_count m_references{ 1 }; }; template diff --git a/strings/base_events.h b/strings/base_events.h index 131186864..139746fd0 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -342,6 +342,24 @@ namespace winrt::impl return 1; } + WINRT_IMPL_NOINLINE inline bool report_failed_invoke() + { + int32_t const code = to_hresult(); + + static int32_t(__stdcall * handler)(int32_t, int32_t, void*) noexcept; + impl::load_runtime_function(L"combase.dll", "RoTransformError", handler, fallback_RoTransformError); + handler(code, 0, nullptr); + + if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED + code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) + code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE + { + return false; + } + + return true; + } + template bool invoke(Delegate const& delegate, Arg const&... args) noexcept { @@ -351,18 +369,7 @@ namespace winrt::impl } catch (...) { - int32_t const code = to_hresult(); - - static int32_t(__stdcall * handler)(int32_t, int32_t, void*) noexcept; - impl::load_runtime_function(L"combase.dll", "RoTransformError", handler, fallback_RoTransformError); - handler(code, 0, nullptr); - - if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED - code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) - code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE - { - return false; - } + return report_failed_invoke(); } return true; @@ -387,28 +394,7 @@ WINRT_EXPORT namespace winrt event_token add(delegate_type const& delegate) { - event_token token{}; - - // Extends life of old targets array to release delegates outside of lock. - delegate_array temp_targets; - - { - slim_lock_guard const change_guard(m_change); - delegate_array new_targets = impl::make_event_array((!m_targets) ? 1 : m_targets->size() + 1); - - if (m_targets) - { - std::copy_n(m_targets->begin(), m_targets->size(), new_targets->begin()); - } - - new_targets->back() = impl::make_agile_delegate(delegate); - token = get_token(new_targets->back()); - - slim_lock_guard const swap_guard(m_swap); - temp_targets = std::exchange(m_targets, std::move(new_targets)); - } - - return token; + return add_agile(impl::make_agile_delegate(delegate)); } void remove(event_token const token) @@ -510,6 +496,32 @@ WINRT_EXPORT namespace winrt private: + WINRT_IMPL_NOINLINE event_token add_agile(delegate_type delegate) + { + event_token token{}; + + // Extends life of old targets array to release delegates outside of lock. + delegate_array temp_targets; + + { + slim_lock_guard const change_guard(m_change); + delegate_array new_targets = impl::make_event_array((!m_targets) ? 1 : m_targets->size() + 1); + + if (m_targets) + { + std::copy_n(m_targets->begin(), m_targets->size(), new_targets->begin()); + } + + new_targets->back() = std::move(delegate); + token = get_token(new_targets->back()); + + slim_lock_guard const swap_guard(m_swap); + temp_targets = std::exchange(m_targets, std::move(new_targets)); + } + + return token; + } + event_token get_token(delegate_type const& delegate) const noexcept { return event_token{ reinterpret_cast(WINRT_IMPL_EncodePointer(get_abi(delegate))) }; diff --git a/strings/base_implements.h b/strings/base_implements.h index 0c0ff0684..5e8e6a29d 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1156,19 +1156,16 @@ namespace winrt::impl return 0; } - if constexpr (is_agile::value) - { - if (is_guid_of(id)) - { - *object = get_unknown(); - AddRef(); - return 0; - } + return query_interface_common(id, object); + } - if (is_guid_of(id)) - { - return make_marshaler(get_unknown(), object); - } + WINRT_IMPL_NOINLINE int32_t query_interface_common(guid const& id, void** object) noexcept + { + if (is_guid_of(id)) + { + *object = get_unknown(); + AddRef(); + return 0; } if constexpr (is_inspectable::value) @@ -1181,13 +1178,6 @@ namespace winrt::impl } } - if (is_guid_of(id)) - { - *object = get_unknown(); - AddRef(); - return 0; - } - if constexpr (is_weak_ref_source::value) { if (is_guid_of(id)) @@ -1196,6 +1186,21 @@ namespace winrt::impl return *object ? error_ok : error_bad_alloc; } } + + if constexpr (is_agile::value) + { + if (is_guid_of(id)) + { + *object = get_unknown(); + AddRef(); + return 0; + } + + if (is_guid_of(id)) + { + return make_marshaler(get_unknown(), object); + } + } return query_interface_tearoff(id, object); } From 9b453cfc518bdaa7e2ff590526c4883457fd6065 Mon Sep 17 00:00:00 2001 From: Jon Wiswall Date: Thu, 17 Aug 2023 15:51:08 -0700 Subject: [PATCH 200/305] Enable faster dev cycle in Visual Studio (#1340) * Enable faster dev cycle in Visual Studio * Oops, remove one more run * Fix linux build temporarily - see also #1341 --------- Co-authored-by: Jon Wiswall --- .github/workflows/ci.yml | 4 +- README.md | 10 +- build_test_all.cmd | 1 - cppwinrt.sln | 12 ++- test/test_component/test_component.vcxproj | 109 ++------------------- 5 files changed, 29 insertions(+), 107 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f96dfad43..aa568e507 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -483,7 +483,7 @@ jobs: - name: Test run (build projection using Windows.winmd) run: | - curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/metadata/default/Windows.winmd + curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/bindgen/default/Windows.winmd install/bin/cppwinrt -in Windows.winmd -out /tmp/cppwinrt -verbose - id: setup-llvm @@ -575,7 +575,7 @@ jobs: - name: Test run (build projection using Windows.winmd) run: | - curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/metadata/default/Windows.winmd + curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/bindgen/default/Windows.winmd install/bin/cppwinrt -in Windows.winmd -out build/out -verbose build-msvc-natvis: diff --git a/README.md b/README.md index 7e69fd979..691809d31 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,13 @@ If you really want to build it yourself, the simplest way to do so is to run the * Open a dev command prompt pointing at the root of the repo. * Open the `cppwinrt.sln` solution. -* Rebuild the x64 Release configuration of the `cppwinrt` project only. Do not attempt to build anything else just yet. -* Run `build_projection.cmd` in the dev command prompt. -* Switch to the x64 Debug configuration in Visual Studio and build all projects as needed. +* Choose a configuration (x64, x86, Release, Debug) and build projects as needed. + +If you are working on an ARM64 or ARM specific issue from an x64 or x86 host, you will need to instead: + +* Open the `cppwinrt.sln` solution +* Build the x86 version of the "cppwinrt" project first +* Switch to your preferred configuration and build the test binaries and run them in your test environment ## Comparing Outputs diff --git a/build_test_all.cmd b/build_test_all.cmd index 681f8c682..18585bab8 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -26,7 +26,6 @@ call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%, if "%target_platform%"=="arm64" goto :eof call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt -_build\%target_platform%\%target_configuration%\cppwinrt.exe -in local -out _build\%target_platform%\%target_configuration% -verbose call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln diff --git a/cppwinrt.sln b/cppwinrt.sln index 8b162344f..e08c2d1cf 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28606.126 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppwinrt", "cppwinrt\cppwinrt.vcxproj", "{D613FB39-5035-4043-91E2-BAB323908AF4}" ProjectSection(ProjectDependencies) = postProject @@ -24,6 +24,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Component", "test\old_tests EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Composable", "test\old_tests\Composable\Composable.vcxproj", "{152E4C6E-9A9D-4D5A-B38D-4905D173649A}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject @@ -41,16 +42,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test\test.vcxp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component_folders", "test\test_component_folders\test_component_folders.vcxproj", "{85695954-3800-4558-9857-966E69E9F9EC}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component_no_pch", "test\test_component_no_pch\test_component_no_pch.vcxproj", "{F1C915B3-2C64-4992-AFB7-7F035B1A7607}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component_base", "test\test_component_base\test_component_base.vcxproj", "{13333A6F-6A4A-48CD-865C-0F65135EB018}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject @@ -61,6 +65,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component_derived", "t EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_component_fast", "test\test_component_fast\test_component_fast.vcxproj", "{0E0ACA62-A92F-44CF-BD41-AEB541946DF8}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject @@ -93,6 +98,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_none", "te EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_custom", "test\test_module_lock_custom\test_module_lock_custom.vcxproj", "{08C40663-B6A3-481E-8755-AE32BAD99501}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject @@ -107,11 +113,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp20\test_cpp20.vcxproj", "{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocation", "test\test_cpp20_no_sourcelocation\test_cpp20_no_sourcelocation.vcxproj", "{D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}" ProjectSection(ProjectDependencies) = postProject + {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index d1f668509..15aa24447 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -182,18 +182,6 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd - @@ -243,19 +231,6 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd - @@ -305,19 +280,6 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd - @@ -354,18 +316,6 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd - @@ -406,18 +356,6 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd - @@ -471,19 +409,6 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd - @@ -537,19 +462,6 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd - @@ -590,17 +502,16 @@ C:\Windows\System32\WinMetadata true - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component.winmd + + + + + $(CppWinRTDir)cppwinrt -in local -out $(OutputPath) -verbose + $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component.winmd -comp "$(ProjectDir)Generated Files" -out "$(ProjectDir)Generated Files" -include test_component -ref sdk -verbose -prefix -opt -lib test -fastabi -overwrite -name test_component + + Projecting Windows and component metadata into $(OutputPath) + $(OutputPath)\winrt\base.h;Generated Files\module.g.cpp + $(CppWinRTDir)cppwinrt.exe;$(OutputPath)test_component.winmd From de6ca88bd6a36cb6d6fc936a649a49b816b12d60 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Mon, 28 Aug 2023 08:35:09 -0500 Subject: [PATCH 201/305] Remove old Windows 7 support code (#1348) --- .github/workflows/ci.yml | 296 +----------------- .pipelines/jobs/OneBranchTest.yml | 4 - build_test_all.cmd | 1 - cppwinrt.sln | 24 -- run_tests.cmd | 1 - strings/base_activation.h | 13 +- strings/base_agile_ref.h | 47 +-- strings/base_coroutine_threadpool.h | 19 +- strings/base_error.h | 20 +- strings/base_events.h | 10 +- strings/base_extern.h | 8 + test/CMakeLists.txt | 1 - test/test_win7/CMakeLists.txt | 68 ---- test/test_win7/GetMany.cpp | 382 ----------------------- test/test_win7/abi_guard.cpp | 293 ----------------- test/test_win7/agile_ref.cpp | 54 ---- test/test_win7/agility.cpp | 140 --------- test/test_win7/async_auto_cancel.cpp | 84 ----- test/test_win7/async_cancel_callback.cpp | 104 ------ test/test_win7/async_check_cancel.cpp | 118 ------- test/test_win7/async_local.cpp | 74 ----- test/test_win7/async_no_suspend.cpp | 85 ----- test/test_win7/async_progress.cpp | 82 ----- test/test_win7/async_result.cpp | 86 ----- test/test_win7/async_return.cpp | 52 --- test/test_win7/async_suspend.cpp | 98 ------ test/test_win7/async_throw.cpp | 91 ------ test/test_win7/async_wait_for.cpp | 141 --------- test/test_win7/capture.cpp | 75 ----- test/test_win7/cmd_reader.cpp | 154 --------- test/test_win7/coro_foundation.cpp | 21 -- test/test_win7/coro_threadpool.cpp | 20 -- test/test_win7/custom_error.cpp | 52 --- test/test_win7/delegate.cpp | 72 ----- test/test_win7/delegates.cpp | 98 ------ test/test_win7/disconnected.cpp | 130 -------- test/test_win7/enum.cpp | 24 -- test/test_win7/fast_iterator.cpp | 23 -- test/test_win7/final_release.cpp | 66 ---- test/test_win7/generic_type_names.cpp | 152 --------- test/test_win7/generic_types.cpp | 12 - test/test_win7/generic_types.h | 115 ------- test/test_win7/guid_key.cpp | 22 -- test/test_win7/iid_ppv_args.cpp | 39 --- test/test_win7/in_params.cpp | 61 ---- test/test_win7/inspectable_interop.cpp | 85 ----- test/test_win7/interop.cpp | 86 ----- test/test_win7/invalid_events.cpp | 63 ---- test/test_win7/main.cpp | 26 -- test/test_win7/module_lock_dll.cpp | 50 --- test/test_win7/names.cpp | 19 -- test/test_win7/no_make_detection.cpp | 10 - test/test_win7/noexcept.cpp | 17 - test/test_win7/numerics.cpp | 15 - test/test_win7/out_params.cpp | 278 ----------------- test/test_win7/parent_includes.cpp | 17 - test/test_win7/pch.cpp | 1 - test/test_win7/pch.h | 47 --- test/test_win7/return_params.cpp | 80 ----- test/test_win7/structs.cpp | 18 -- test/test_win7/test_win7.vcxproj | 363 --------------------- test/test_win7/thread_pool.cpp | 61 ---- test/test_win7/uniform_in_params.cpp | 29 -- test/test_win7/velocity.cpp | 44 --- test/test_win7/when.cpp | 74 ----- 65 files changed, 17 insertions(+), 4898 deletions(-) delete mode 100644 test/test_win7/CMakeLists.txt delete mode 100644 test/test_win7/GetMany.cpp delete mode 100644 test/test_win7/abi_guard.cpp delete mode 100644 test/test_win7/agile_ref.cpp delete mode 100644 test/test_win7/agility.cpp delete mode 100644 test/test_win7/async_auto_cancel.cpp delete mode 100644 test/test_win7/async_cancel_callback.cpp delete mode 100644 test/test_win7/async_check_cancel.cpp delete mode 100644 test/test_win7/async_local.cpp delete mode 100644 test/test_win7/async_no_suspend.cpp delete mode 100644 test/test_win7/async_progress.cpp delete mode 100644 test/test_win7/async_result.cpp delete mode 100644 test/test_win7/async_return.cpp delete mode 100644 test/test_win7/async_suspend.cpp delete mode 100644 test/test_win7/async_throw.cpp delete mode 100644 test/test_win7/async_wait_for.cpp delete mode 100644 test/test_win7/capture.cpp delete mode 100644 test/test_win7/cmd_reader.cpp delete mode 100644 test/test_win7/coro_foundation.cpp delete mode 100644 test/test_win7/coro_threadpool.cpp delete mode 100644 test/test_win7/custom_error.cpp delete mode 100644 test/test_win7/delegate.cpp delete mode 100644 test/test_win7/delegates.cpp delete mode 100644 test/test_win7/disconnected.cpp delete mode 100644 test/test_win7/enum.cpp delete mode 100644 test/test_win7/fast_iterator.cpp delete mode 100644 test/test_win7/final_release.cpp delete mode 100644 test/test_win7/generic_type_names.cpp delete mode 100644 test/test_win7/generic_types.cpp delete mode 100644 test/test_win7/generic_types.h delete mode 100644 test/test_win7/guid_key.cpp delete mode 100644 test/test_win7/iid_ppv_args.cpp delete mode 100644 test/test_win7/in_params.cpp delete mode 100644 test/test_win7/inspectable_interop.cpp delete mode 100644 test/test_win7/interop.cpp delete mode 100644 test/test_win7/invalid_events.cpp delete mode 100644 test/test_win7/main.cpp delete mode 100644 test/test_win7/module_lock_dll.cpp delete mode 100644 test/test_win7/names.cpp delete mode 100644 test/test_win7/no_make_detection.cpp delete mode 100644 test/test_win7/noexcept.cpp delete mode 100644 test/test_win7/numerics.cpp delete mode 100644 test/test_win7/out_params.cpp delete mode 100644 test/test_win7/parent_includes.cpp delete mode 100644 test/test_win7/pch.cpp delete mode 100644 test/test_win7/pch.h delete mode 100644 test/test_win7/return_params.cpp delete mode 100644 test/test_win7/structs.cpp delete mode 100644 test/test_win7/test_win7.vcxproj delete mode 100644 test/test_win7/thread_pool.cpp delete mode 100644 test/test_win7/uniform_in_params.cpp delete mode 100644 test/test_win7/velocity.cpp delete mode 100644 test/test_win7/when.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa568e507..2d37aa360 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,7 +97,7 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_win7, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] exclude: - arch: arm64 config: Debug @@ -250,120 +250,6 @@ jobs: _build/${{ matrix.arch }}/${{ matrix.config }}/*.lib _build/${{ matrix.arch }}/${{ matrix.config }}/*.pdb - test-llvm-mingw-cppwinrt: - name: 'llvm-mingw: Build and test' - strategy: - fail-fast: false - matrix: - arch: [i686, x86_64] - config: [Debug, Release] - runs-on: windows-latest - env: - CMAKE_COLOR_DIAGNOSTICS: 1 - CLICOLOR_FORCE: 1 - steps: - - uses: actions/checkout@v3 - - - id: setup-llvm - name: Set up llvm-mingw - uses: ./.github/actions/setup-llvm-mingw - with: - host-arch: ${{ matrix.arch }} - - - name: Build cppwinrt - run: | - mkdir build - cd build - if ("${{ matrix.config }}" -eq "Debug") { - $sanitizers = "TRUE" - } else { - $sanitizers = "FALSE" - } - cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.config }} ` - -DDOWNLOAD_WINDOWSNUMERICS=TRUE ` - -DUSE_ANSI_COLOR=TRUE ` - -DCMAKE_CXX_FLAGS="-fansi-escape-codes" ` - -DENABLE_TEST_SANITIZERS=$sanitizers - cmake --build . -j2 --target cppwinrt - - - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v3 - with: - name: llvm-mingw-build-${{ matrix.arch }}-bin - path: build/cppwinrt.exe - - - name: Build tests - run: | - cd build - cmake --build . -j2 --target test-vanilla test_cpp20 test_cpp20_no_sourcelocation test_win7 test_old - - - name: Upload test binaries - uses: actions/upload-artifact@v3 - with: - name: llvm-mingw-tests-${{ matrix.arch }}-bin - path: build/test/*.exe - - - name: Run tests - run: | - cd build - $env:UBSAN_OPTIONS = "print_stacktrace=1" - ctest --verbose - - test-msys2-gcc-cppwinrt: - name: 'gcc/msys2: Build and test (${{ matrix.sys }}, ${{ matrix.config }})' - strategy: - fail-fast: false - matrix: - include: - # 32-bit builds are running out of memory - # - { sys: mingw32, arch: i686, config: Release } - - { sys: mingw64, arch: x86_64, config: Debug } - - { sys: mingw64, arch: x86_64, config: Release } - - { sys: ucrt64, arch: x86_64, config: Release } - runs-on: windows-latest - env: - CMAKE_COLOR_DIAGNOSTICS: 1 - CLICOLOR_FORCE: 1 - defaults: - run: - shell: msys2 {0} - steps: - - uses: msys2/setup-msys2@v2 - with: - msystem: ${{matrix.sys}} - update: true - pacboy: >- - crt:p - gcc:p - binutils:p - cmake:p - ninja:p - - - uses: actions/checkout@v3 - - - name: Build cppwinrt - run: | - mkdir build - cd build - if [[ "${{ matrix.arch }}" = "i686" ]]; then - skip_large_pch_arg="-DSKIP_LARGE_PCH=TRUE" - fi - cmake ../ -GNinja -DCMAKE_BUILD_TYPE=${{ matrix.config }} \ - -DDOWNLOAD_WINDOWSNUMERICS=TRUE \ - -DUSE_ANSI_COLOR=TRUE \ - $skip_large_pch_arg - cmake --build . --target cppwinrt - - - name: Build tests - run: | - cd build - cmake --build . -j2 --target test-vanilla test_cpp20 test_cpp20_no_sourcelocation test_win7 test_old - - - name: Run tests - run: | - cd build - ctest --verbose - build-linux-cross-cppwinrt: name: 'cross: Cross-build from Linux' strategy: @@ -398,186 +284,6 @@ jobs: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe - test-linux-cross-cppwinrt: - name: 'cross: Test run on Windows' - needs: build-linux-cross-cppwinrt - strategy: - fail-fast: false - matrix: - arch: [i686, x86_64] - runs-on: windows-latest - steps: - - uses: actions/checkout@v3 - - - name: Fetch cppwinrt executable - uses: actions/download-artifact@v3 - with: - name: cross-build-${{ matrix.arch }}-bin - path: ./.test - - - name: Run cppwinrt to build projection - run: | - .\.test\cppwinrt.exe -in local -out .\.test\out -verbose - - - id: setup-llvm - name: Set up llvm-mingw - uses: ./.github/actions/setup-llvm-mingw - with: - host-arch: ${{ matrix.arch }} - - - name: Build cppwinrt tests - run: | - mkdir build - cd build - cmake ../test -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug ` - -DCPPWINRT_PROJECTION_INCLUDE_DIR="../.test/out" ` - -DDOWNLOAD_WINDOWSNUMERICS=TRUE ` - -DUSE_ANSI_COLOR=TRUE - cmake --build . -j2 - - - name: Run tests - run: | - cd build - ctest --verbose - - build-linux-native-cppwinrt: - name: 'linux: GCC native build + mingw-w64 cross-build tests' - strategy: - fail-fast: false - matrix: - # TODO: Enable gcc build once Arch Linux gets more recent mingw-w64 headers (ver. 11 perhaps?) - # cross_toolchain: [gcc, llvm-mingw] - cross_toolchain: [llvm-mingw] - cross_arch: [i686, x86_64] - # include: - # - cross_toolchain: gcc - # container: - # image: archlinux:base-devel - runs-on: ubuntu-22.04 - container: ${{ matrix.container }} - defaults: - run: - shell: bash - env: - CMAKE_COLOR_DIAGNOSTICS: 1 - CLICOLOR_FORCE: 1 - steps: - - uses: actions/checkout@v3 - - - name: Install build tools - if: matrix.cross_toolchain == 'gcc' - run: | - pacman --noconfirm -Suuy - pacman --needed --noconfirm -S cmake ninja git - - - name: Build cppwinrt - run: | - cmake -S . -B build/native/ \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DCMAKE_INSTALL_PREFIX=$PWD/install/ - cmake --build build/native/ --target install -j2 - - - name: Test run (cppwinrt -?) - run: | - install/bin/cppwinrt -? - - - name: Test run (build projection using Windows.winmd) - run: | - curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/bindgen/default/Windows.winmd - install/bin/cppwinrt -in Windows.winmd -out /tmp/cppwinrt -verbose - - - id: setup-llvm - name: Set up llvm-mingw - if: matrix.cross_toolchain == 'llvm-mingw' - uses: ./.github/actions/setup-llvm-mingw - - - name: Install GCC cross compiler - if: matrix.cross_toolchain == 'gcc' - run: | - pacman --needed --noconfirm -S mingw-w64-gcc - - - name: Cross-build tests using projection - run: | - cmake -S test -B build/cross-tests --toolchain "$PWD/cross-mingw-toolchain.cmake" \ - -DCMAKE_SYSTEM_PROCESSOR=${{ matrix.cross_arch }} \ - -DCMAKE_BUILD_TYPE=Debug \ - -DCMAKE_CXX_FLAGS="-static" \ - -DCPPWINRT_PROJECTION_INCLUDE_DIR=/tmp/cppwinrt \ - -DDOWNLOAD_WINDOWSNUMERICS=TRUE \ - -DUSE_ANSI_COLOR=TRUE - cmake --build build/cross-tests -j2 - - - name: Upload built tests - uses: actions/upload-artifact@v3 - with: - name: linux-native-cppwinrt-cross-build-tests-${{ matrix.cross_toolchain }}-${{ matrix.cross_arch }}-bin - path: build/cross-tests/*.exe - - test-linux-native-cppwinrt-cross-tests: - name: 'linux: Run llvm-mingw cross-build tests' - needs: build-linux-native-cppwinrt - strategy: - fail-fast: false - matrix: - # TODO: Enable gcc build test when it is buildable - # cross_toolchain: [gcc, llvm-mingw] - cross_toolchain: [llvm-mingw] - cross_arch: [i686, x86_64] - runs-on: windows-latest - steps: - - uses: actions/checkout@v3 - - - name: Fetch test executables - uses: actions/download-artifact@v3 - with: - name: linux-native-cppwinrt-cross-build-tests-${{ matrix.cross_toolchain }}-${{ matrix.cross_arch }}-bin - path: ./ - - - name: Run tests - run: | - $test_exes = ls *.exe -Name - $has_failed_tests = 0 - foreach ($test_exe in $test_exes) { - echo "::group::Run '$test_exe'" - & .\$test_exe --use-colour yes - echo "::endgroup::" - if ($LastExitCode -ne 0) { - echo "::error::Test '$test_exe' failed!" - $has_failed_tests = 1 - } - } - if ($has_failed_tests -ne 0) { - exit 1 - } - - build-macos-native-cppwinrt: - name: 'macOS: GCC native build' - runs-on: macos-latest - defaults: - run: - shell: bash - env: - CMAKE_COLOR_DIAGNOSTICS: 1 - CLICOLOR_FORCE: 1 - steps: - - uses: actions/checkout@v3 - - - name: Build cppwinrt - run: | - cmake -S . -B build/native/ \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DCMAKE_INSTALL_PREFIX=$PWD/install/ - cmake --build build/native/ --target install -j2 - - - name: Test run (cppwinrt -?) - run: | - install/bin/cppwinrt -? - - - name: Test run (build projection using Windows.winmd) - run: | - curl -o Windows.winmd -L https://github.com/microsoft/windows-rs/raw/master/crates/libs/bindgen/default/Windows.winmd - install/bin/cppwinrt -in Windows.winmd -out build/out -verbose - build-msvc-natvis: name: 'Build natvis' strategy: diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index 3acaccf7d..d9634ff1e 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -22,10 +22,6 @@ jobs: TestExe: 'test_cpp20_no_sourcelocation' TestProject: 'test_cpp20_no_sourcelocation' BuildPlatform: 'x86' - test_win7.x86: - TestExe: 'test_win7' - TestProject: 'test_win7' - BuildPlatform: 'x86' test_fast.x86: TestExe: 'test_fast' TestProject: 'test_fast' diff --git a/build_test_all.cmd b/build_test_all.cmd index 18585bab8..89967a04b 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -32,7 +32,6 @@ call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%, call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20_no_sourcelocation -call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_win7 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_slow call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_module_lock_custom diff --git a/cppwinrt.sln b/cppwinrt.sln index e08c2d1cf..43e96ffab 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -104,13 +104,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_custom", " EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3C7EA5F8-6E8C-4376-B499-2CAF596384B0}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win7", "test\test_win7\test_win7.vcxproj", "{2EF696B9-7F4A-410F-AE5C-5301565C0F08}" - ProjectSection(ProjectDependencies) = postProject - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} - {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} - {F1C915B3-2C64-4992-AFB7-7F035B1A7607} = {F1C915B3-2C64-4992-AFB7-7F035B1A7607} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20", "test\test_cpp20\test_cpp20.vcxproj", "{5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}" ProjectSection(ProjectDependencies) = postProject {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} = {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270} @@ -452,22 +445,6 @@ Global {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.Build.0 = Release|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.ActiveCfg = Release|Win32 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.Build.0 = Release|Win32 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM.ActiveCfg = Debug|ARM - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM.Build.0 = Debug|ARM - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|ARM64.Build.0 = Debug|ARM64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x64.ActiveCfg = Debug|x64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x64.Build.0 = Debug|x64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x86.ActiveCfg = Debug|Win32 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Debug|x86.Build.0 = Debug|Win32 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM.ActiveCfg = Release|ARM - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM.Build.0 = Release|ARM - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM64.ActiveCfg = Release|ARM64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|ARM64.Build.0 = Release|ARM64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.ActiveCfg = Release|x64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x64.Build.0 = Release|x64 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.ActiveCfg = Release|Win32 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08}.Release|x86.Build.0 = Release|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -521,7 +498,6 @@ Global {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} - {2EF696B9-7F4A-410F-AE5C-5301565C0F08} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection diff --git a/run_tests.cmd b/run_tests.cmd index 71a9d1294..77d883642 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -11,7 +11,6 @@ if "%target_configuration%"=="" set target_configuration=Debug call :run_test test call :run_test test_cpp20 call :run_test test_cpp20_no_sourcelocation -call :run_test test_win7 call :run_test test_fast call :run_test test_slow call :run_test test_old diff --git a/strings/base_activation.h b/strings/base_activation.h index b27cefb70..bb6be5ca1 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -18,13 +18,6 @@ namespace winrt::impl using library_handle = handle_type; - inline int32_t __stdcall fallback_RoGetActivationFactory(void*, guid const&, void** factory) noexcept - { - *factory = nullptr; - return error_class_not_available; - } - - template WINRT_IMPL_NOINLINE hresult get_runtime_activation_factory_impl(param::hstring const& name, winrt::guid const& guid, void** result) noexcept { @@ -33,9 +26,7 @@ namespace winrt::impl return winrt_activation_handler(*(void**)(&name), guid, result); } - static int32_t(__stdcall * handler)(void* classId, winrt::guid const& iid, void** factory) noexcept; - impl::load_runtime_function(L"combase.dll", "RoGetActivationFactory", handler, fallback_RoGetActivationFactory); - hresult hr = handler(*(void**)(&name), guid, result); + hresult hr = WINRT_IMPL_RoGetActivationFactory(*(void**)(&name), guid, result); if (hr == impl::error_not_initialized) { @@ -48,7 +39,7 @@ namespace winrt::impl void* cookie; usage(&cookie); - hr = handler(*(void**)(&name), guid, result); + hr = WINRT_IMPL_RoGetActivationFactory(*(void**)(&name), guid, result); } if (hr == 0) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index b2ff542d9..8993d846b 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -131,54 +131,9 @@ namespace winrt::impl return WINRT_IMPL_LoadLibraryExW(library, nullptr, 0x00001000 /* LOAD_LIBRARY_SEARCH_DEFAULT_DIRS */); } - template - void load_runtime_function(wchar_t const* library, char const* name, F& result, L fallback) noexcept - { - if (result) - { - return; - } - - result = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(library), name)); - - if (result) - { - return; - } - - result = fallback; - } - - inline int32_t __stdcall fallback_RoGetAgileReference(uint32_t, winrt::guid const& iid, void* object, void** reference) noexcept - { - *reference = nullptr; - static constexpr guid git_clsid{ 0x00000323, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } }; - - com_ptr git; - hresult hr = WINRT_IMPL_CoCreateInstance(git_clsid, nullptr, 1 /*CLSCTX_INPROC_SERVER*/, guid_of(), git.put_void()); - - if (hr < 0) - { - return hr; - } - - uint32_t cookie{}; - hr = git->RegisterInterfaceInGlobal(object, iid, &cookie); - - if (hr < 0) - { - return hr; - } - - *reference = new agile_ref_fallback(std::move(git), cookie); - return 0; - } - inline hresult get_agile_reference(winrt::guid const& iid, void* object, void** reference) noexcept { - static int32_t(__stdcall * handler)(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept; - load_runtime_function(L"combase.dll", "RoGetAgileReference", handler, fallback_RoGetAgileReference); - return handler(0, iid, object, reference); + return WINRT_IMPL_RoGetAgileReference(0, iid, object, reference); } } diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index ba4d742b4..e3a283e33 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -409,17 +409,9 @@ namespace winrt::impl } } - static int32_t __stdcall fallback_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept - { - return 0; // pretend timer has already triggered and a callback is on its way - } - void fire_immediately() noexcept { - static int32_t(__stdcall * handler)(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept; - impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolTimerEx", handler, fallback_SetThreadpoolTimerEx); - - if (handler(m_timer.get(), nullptr, 0, 0)) + if (WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), nullptr, 0, 0)) { int64_t now = 0; WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); @@ -513,10 +505,6 @@ namespace winrt::impl } private: - static int32_t __stdcall fallback_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept - { - return 0; // pretend wait has already triggered and a callback is on its way - } void create_threadpool_wait() { @@ -534,10 +522,7 @@ namespace winrt::impl void fire_immediately() noexcept { - static int32_t(__stdcall * handler)(winrt::impl::ptp_wait, void*, void*, void*) noexcept; - impl::load_runtime_function(L"kernel32.dll", "SetThreadpoolWaitEx", handler, fallback_SetThreadpoolWaitEx); - - if (handler(m_wait.get(), nullptr, nullptr, nullptr)) + if (WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), nullptr, nullptr, nullptr)) { int64_t now = 0; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); diff --git a/strings/base_error.h b/strings/base_error.h index 98bb8e899..2a6eea281 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -175,11 +175,6 @@ namespace winrt::impl hstring const m_message; atomic_ref_count m_references{ 1 }; }; - - [[noreturn]] inline void __stdcall fallback_RoFailFastWithErrorContext(int32_t) noexcept - { - abort(); - } } WINRT_EXPORT namespace winrt @@ -301,18 +296,9 @@ WINRT_EXPORT namespace winrt private: - static int32_t __stdcall fallback_RoOriginateLanguageException(int32_t error, void* message, void*) noexcept - { - com_ptr info(new (std::nothrow) impl::error_info_fallback(error, message), take_ownership_from_abi); - WINRT_VERIFY_(0, WINRT_IMPL_SetErrorInfo(0, info.get())); - return 1; - } - void originate(hresult const code, void* message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept { - static int32_t(__stdcall* handler)(int32_t error, void* message, void* exception) noexcept; - impl::load_runtime_function(L"combase.dll", "RoOriginateLanguageException", handler, fallback_RoOriginateLanguageException); - WINRT_VERIFY(handler(code, message, nullptr)); + WINRT_VERIFY(WINRT_IMPL_RoOriginateLanguageException(code, message, nullptr)); // This is an extension point that can be filled in by other libraries (such as WIL) to get call outs when errors are // originated. This is intended for logging purposes. When possible include the std::source_information so that accurate @@ -642,9 +628,7 @@ WINRT_EXPORT namespace winrt [[noreturn]] inline void terminate() noexcept { - static void(__stdcall * handler)(int32_t) noexcept; - impl::load_runtime_function(L"combase.dll", "RoFailFastWithErrorContext", handler, impl::fallback_RoFailFastWithErrorContext); - handler(to_hresult()); + WINRT_IMPL_RoFailFastWithErrorContext(to_hresult()); abort(); } } diff --git a/strings/base_events.h b/strings/base_events.h index 139746fd0..77952474e 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -337,18 +337,10 @@ namespace winrt::impl return { new(raw) event_array(capacity), take_ownership_from_abi }; } - inline int32_t __stdcall fallback_RoTransformError(int32_t, int32_t, void*) noexcept - { - return 1; - } - WINRT_IMPL_NOINLINE inline bool report_failed_invoke() { int32_t const code = to_hresult(); - - static int32_t(__stdcall * handler)(int32_t, int32_t, void*) noexcept; - impl::load_runtime_function(L"combase.dll", "RoTransformError", handler, fallback_RoTransformError); - handler(code, 0, nullptr); + WINRT_IMPL_RoTransformError(code, 0, nullptr); if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) diff --git a/strings/base_extern.h b/strings/base_extern.h index c0fb15acf..92872d416 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -24,6 +24,14 @@ __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId extern "C" { + int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12); + int32_t __stdcall WINRT_IMPL_RoGetAgileReference(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16); + int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); + int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); + int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); + void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); + int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); + void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d9c720a80..ed1515526 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -107,7 +107,6 @@ set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.") add_subdirectory(test) add_subdirectory(test_cpp20) add_subdirectory(test_cpp20_no_sourcelocation) -add_subdirectory(test_win7) if(HAS_WINDOWSNUMERICS) add_subdirectory(old_tests) diff --git a/test/test_win7/CMakeLists.txt b/test/test_win7/CMakeLists.txt deleted file mode 100644 index d1c4120ea..000000000 --- a/test/test_win7/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -file(GLOB TEST_SRCS - LIST_DIRECTORIES false - CONFIGURE_DEPENDS - *.cpp -) -list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") - - -# We can't build test_component[*] for mingw-w64 because it doesn't have an -# alternative to midl that can produce winmd files. Also, even if we do manage -# to reuse the MSVC-compiled binaries, mingw-w64 is still missing -# windowsnumerics.impl.h which is needed to provide the types -# winrt::Windows::Foundation::Numerics::float2 and friends that the components -# use. -list(APPEND BROKEN_TESTS - agility - delegates - enum - in_params - no_make_detection - noexcept - out_params - parent_includes - return_params - structs - uniform_in_params - velocity -) - -list(APPEND BROKEN_TESTS - # depends on pplawait.h - when -) - -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # FIXME: GCC does not compile co_await on thread_pool because it wants - # a copy constructor. Disabling this test for now. - # This might be related to upstream bug: - # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103963 - list(APPEND BROKEN_TESTS - thread_pool - ) -endif() - -# Exclude broken tests -foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) - list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") -endforeach() - -add_executable(test_win7 main.cpp ${TEST_SRCS}) - -target_precompile_headers(test_win7 PRIVATE pch.h) -set_source_files_properties( - main.cpp - coro_foundation.cpp - coro_threadpool.cpp - generic_type_names.cpp - inspectable_interop.cpp - module_lock_dll.cpp - PROPERTIES SKIP_PRECOMPILE_HEADERS true -) - -add_dependencies(test_win7 build-cppwinrt-projection) - -add_test( - NAME test_win7 - COMMAND "$" ${TEST_COLOR_ARG} -) diff --git a/test/test_win7/GetMany.cpp b/test/test_win7/GetMany.cpp deleted file mode 100644 index 292912046..000000000 --- a/test/test_win7/GetMany.cpp +++ /dev/null @@ -1,382 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation::Collections; - -// -// Now that all of the generics are generated (rather than hand-written), it's far less likely -// that something like GetMany is incorrect. And the "FillArray" pattern used by GetMany is -// tested elsewhere in the out_params and return_params tests. However since C++/WinRT provides -// an implementation of GetMany over and above the projection, these tests validate the this -// implementation is correct. Other tests exist for collections under 'old_tests' but new -// optimizations are coming for GetMany and I want to make sure that GetMany is completely -// covered. -// - -namespace -{ - template - IIterator single_threaded_generator(std::vector&& values = {}) - { - // This iterator may only be advanced once, ensuring the GetMany complexity optimization - // is actually enforced with this test. - - struct generator_container - { - explicit generator_container(IIterator const& first) : m_current(first) - { - if (!m_current.HasCurrent()) - { - m_current = nullptr; - } - } - - IIterator begin() const { return m_current; } - IIterator end() const { return nullptr; } - - private: - IIterator m_current; - }; - - struct generator : implements>, iterable_base - { - explicit generator(IIterator const& first) : m_container(first) - { - } - - auto& get_container() noexcept - { - return m_container; - } - - auto& get_container() const noexcept - { - return m_container; - } - - private: - generator_container m_container; - }; - - auto v = single_threaded_vector(std::move(values)); - return make(v.First()).First(); - } -} - -TEST_CASE("GetMany") -{ - // All - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == v.GetMany(0, buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - } - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == v.First().GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - } - - // None - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC }; - REQUIRE(0 == v.GetMany(3, buffer)); - REQUIRE(buffer[0] == 0xCC); - REQUIRE(buffer[1] == 0xCC); - REQUIRE(buffer[2] == 0xCC); - } - { - auto v = single_threaded_vector({ 1,2,3,4 }); - auto pos = v.First(); - std::array buffer{ 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == pos.GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - buffer = { 0xCC, 0xCC, 0xCC }; - REQUIRE(1 == pos.GetMany(buffer)); - REQUIRE(buffer[0] == 4); - REQUIRE(buffer[1] == 0xCC); - REQUIRE(buffer[2] == 0xCC); - buffer = { 0xCC, 0xCC, 0xCC }; - REQUIRE(0 == pos.GetMany(buffer)); - REQUIRE(buffer[0] == 0xCC); - REQUIRE(buffer[1] == 0xCC); - REQUIRE(buffer[2] == 0xCC); - } - - // Less - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC }; - REQUIRE(2 == v.GetMany(0, buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - } - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC }; - REQUIRE(2 == v.First().GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - } - - // More - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == v.GetMany(0, buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - REQUIRE(buffer[3] == 0xCC); - } - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == v.First().GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - REQUIRE(buffer[3] == 0xCC); - } - - // Offset - { - auto v = single_threaded_vector({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC }; - REQUIRE(2 == v.GetMany(1, buffer)); - REQUIRE(buffer[0] == 2); - REQUIRE(buffer[1] == 3); - REQUIRE(buffer[2] == 0xCC); - REQUIRE(buffer[3] == 0xCC); - } - - // The same tests but with a non-trivially destructible type... - - // All - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old" }; - REQUIRE(3 == v.GetMany(0, buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - } - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old" }; - REQUIRE(3 == v.First().GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - } - - // None - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old" }; - REQUIRE(0 == v.GetMany(3, buffer)); - REQUIRE(buffer[0] == L""); - REQUIRE(buffer[1] == L""); - REQUIRE(buffer[2] == L""); - } - { - auto v = single_threaded_vector({ L"1",L"2",L"3",L"4" }); - auto pos = v.First(); - std::array buffer{ L"old", L"old", L"old" }; - REQUIRE(3 == pos.GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - buffer = { L"old", L"old", L"old" }; - REQUIRE(1 == pos.GetMany(buffer)); - REQUIRE(buffer[0] == L"4"); - REQUIRE(buffer[1] == L""); - REQUIRE(buffer[2] == L""); - buffer = { L"old", L"old", L"old" }; - REQUIRE(0 == pos.GetMany(buffer)); - REQUIRE(buffer[0] == L""); - REQUIRE(buffer[1] == L""); - REQUIRE(buffer[2] == L""); - } - - // Less - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old" }; - REQUIRE(2 == v.GetMany(0, buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - } - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old" }; - REQUIRE(2 == v.First().GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - } - - // More - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old", L"old" }; - REQUIRE(3 == v.GetMany(0, buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - REQUIRE(buffer[3] == L""); - } - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old", L"old" }; - REQUIRE(3 == v.First().GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - REQUIRE(buffer[3] == L""); - } - - // Offset - { - auto v = single_threaded_vector({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old", L"old" }; - REQUIRE(2 == v.GetMany(1, buffer)); - REQUIRE(buffer[0] == L"2"); - REQUIRE(buffer[1] == L"3"); - REQUIRE(buffer[2] == L""); - REQUIRE(buffer[3] == L""); - } - -// FIXME: Fail to compile with Clang due to recursive template instantiation using single_threaded_generator. -#if !defined(__clang__) - - // Similar tests but with a list to ensure optimal code gen for containers that don't offer random access. - - // All - { - IIterator v = single_threaded_generator({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == v.GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - } - - // None - { - IIterator v = single_threaded_generator({ 1,2,3,4,5 }); - std::array buffer{ 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == v.GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - buffer = { 0xCC, 0xCC, 0xCC }; - REQUIRE(2 == v.GetMany(buffer)); - REQUIRE(buffer[0] == 4); - REQUIRE(buffer[1] == 5); - REQUIRE(buffer[2] == 0xCC); - buffer = { 0xCC, 0xCC, 0xCC }; - REQUIRE(0 == v.GetMany(buffer)); - REQUIRE(buffer[0] == 0xCC); - REQUIRE(buffer[1] == 0xCC); - REQUIRE(buffer[2] == 0xCC); - } - - // Less - { - IIterator v = single_threaded_generator({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC }; - REQUIRE(2 == v.GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - } - - // More - { - IIterator v = single_threaded_generator({ 1,2,3 }); - std::array buffer{ 0xCC, 0xCC, 0xCC, 0xCC }; - REQUIRE(3 == v.GetMany(buffer)); - REQUIRE(buffer[0] == 1); - REQUIRE(buffer[1] == 2); - REQUIRE(buffer[2] == 3); - REQUIRE(buffer[3] == 0xCC); - } - - // The same tests but with a non-trivially destructible type... - - // All - { - IIterator v = single_threaded_generator({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old" }; - REQUIRE(3 == v.GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - } - - // None - { - IIterator v = single_threaded_generator({ L"1",L"2",L"3",L"4" }); - std::array buffer{ L"old", L"old", L"old" }; - REQUIRE(3 == v.GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - buffer = { L"old", L"old", L"old" }; - REQUIRE(1 == v.GetMany(buffer)); - REQUIRE(buffer[0] == L"4"); - REQUIRE(buffer[1] == L""); - REQUIRE(buffer[2] == L""); - buffer = { L"old", L"old", L"old" }; - REQUIRE(0 == v.GetMany(buffer)); - REQUIRE(buffer[0] == L""); - REQUIRE(buffer[1] == L""); - REQUIRE(buffer[2] == L""); - } - - // Less - { - IIterator v = single_threaded_generator({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old" }; - REQUIRE(2 == v.GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - } - - // More - { - IIterator v = single_threaded_generator({ L"1",L"2",L"3" }); - std::array buffer{ L"old", L"old", L"old", L"old" }; - REQUIRE(3 == v.GetMany(buffer)); - REQUIRE(buffer[0] == L"1"); - REQUIRE(buffer[1] == L"2"); - REQUIRE(buffer[2] == L"3"); - REQUIRE(buffer[3] == L""); - } -#endif - - // Pair - { - auto m = single_threaded_map(); - m.Insert(1, L"1"); - m.Insert(2, L"2"); - m.Insert(3, L"3"); - m.Insert(4, L"4"); - std::array, 3> buffer; - REQUIRE(3 == m.First().GetMany(buffer)); - REQUIRE(buffer[0].Key() == 1); - REQUIRE(buffer[1].Key() == 2); - REQUIRE(buffer[2].Key() == 3); - REQUIRE(buffer[0].Value() == L"1"); - REQUIRE(buffer[1].Value() == L"2"); - REQUIRE(buffer[2].Value() == L"3"); - } -} diff --git a/test/test_win7/abi_guard.cpp b/test/test_win7/abi_guard.cpp deleted file mode 100644 index c0244a475..000000000 --- a/test/test_win7/abi_guard.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // - // This implemenetation uses the simplest abi_enter and abi_exit methods - // - struct Simple : implements - { - void Close() - { - } - - hstring ToString() - { - return L""; - } - - void abi_enter() - { - ++m_enter; - } - - void abi_exit() - { - ++m_exit; - } - - int m_enter{}; - int m_exit{}; - }; - - // - // This implemenetation uses the abi_enter but omits the abi_exit method - // - struct OnlyEnter : implements - { - void Close() - { - } - - hstring ToString() - { - return L""; - } - - void abi_enter() - { - ++m_enter; - } - - int m_enter{}; - }; - - // - // This implemenetation throws from the abi_enter method - // - struct Throwing : implements - { - void Close() - { - } - - hstring ToString() - { - return L""; - } - - void abi_enter() - { - throw hresult_wrong_thread(); - } - - void abi_exit() - { - ++m_exit; - } - - int m_exit{}; - }; - - // - // This implemenetation provides a nested abi_guard - // - struct NestedGuard : implements - { - void Close() - { - } - - hstring ToString() - { - return L""; - } - - int m_enter{}; - int m_exit{}; - - struct abi_guard - { - abi_guard(NestedGuard& that) : - m_that(that) - { - ++m_that.m_enter; - } - - ~abi_guard() - { - ++m_that.m_exit; - } - - private: - - NestedGuard& m_that; - }; - }; - - template - struct CountGuard - { - CountGuard(T& that) : - m_that(that) - { - ++m_that.m_enter; - } - - ~CountGuard() - { - ++m_that.m_exit; - } - - private: - - T& m_that; - }; - - // - // This implemenetation use an abi_guard type alias - // - struct GuardAlias : implements - { - void Close() - { - } - - hstring ToString() - { - return L""; - } - - int m_enter{}; - int m_exit{}; - - using abi_guard = CountGuard; - }; - - template - struct ThrowGuard - { - ThrowGuard(T&) - { - throw hresult_wrong_thread(); - } - }; - - // - // This implemenetation use an abi_guard type alias that thows - // - struct ThrowAlias : implements - { - void Close() - { - } - - hstring ToString() - { - return L""; - } - - using abi_guard = ThrowGuard; - }; -} - -TEST_CASE("abi_guard") -{ - { - com_ptr impl = make_self(); - - impl->Close(); - impl->ToString(); - REQUIRE(impl->m_enter == 0); - REQUIRE(impl->m_exit == 0); - - IClosable closable = impl.as(); - closable.Close(); - REQUIRE(impl->m_enter == 1); - REQUIRE(impl->m_exit == 1); - - IStringable stringable = impl.as(); - stringable.ToString(); - REQUIRE(impl->m_enter == 2); - REQUIRE(impl->m_exit == 2); - } - { - com_ptr impl = make_self(); - - impl->Close(); - impl->ToString(); - - REQUIRE(impl->m_enter == 0); - - IClosable closable = impl.as(); - closable.Close(); - - REQUIRE(impl->m_enter == 1); - - IStringable stringable = impl.as(); - stringable.ToString(); - - REQUIRE(impl->m_enter == 2); - } - { - com_ptr impl = make_self(); - - impl->Close(); - impl->ToString(); - - IClosable closable = impl.as(); - REQUIRE_THROWS_AS(closable.Close(), hresult_wrong_thread); - - IStringable stringable = impl.as(); - REQUIRE_THROWS_AS(stringable.ToString(), hresult_wrong_thread); - - REQUIRE(impl->m_exit == 0); - } - { - com_ptr impl = make_self(); - - impl->Close(); - impl->ToString(); - - REQUIRE(impl->m_enter == 0); - REQUIRE(impl->m_exit == 0); - - IClosable closable = impl.as(); - closable.Close(); - - REQUIRE(impl->m_enter == 1); - REQUIRE(impl->m_exit == 1); - - IStringable stringable = impl.as(); - stringable.ToString(); - - REQUIRE(impl->m_enter == 2); - REQUIRE(impl->m_exit == 2); - } - { - com_ptr impl = make_self(); - - impl->Close(); - impl->ToString(); - - REQUIRE(impl->m_enter == 0); - REQUIRE(impl->m_exit == 0); - - IClosable closable = impl.as(); - closable.Close(); - - REQUIRE(impl->m_enter == 1); - REQUIRE(impl->m_exit == 1); - - IStringable stringable = impl.as(); - stringable.ToString(); - - REQUIRE(impl->m_enter == 2); - REQUIRE(impl->m_exit == 2); - } - { - com_ptr impl = make_self(); - - impl->Close(); - impl->ToString(); - - IClosable closable = impl.as(); - REQUIRE_THROWS_AS(closable.Close(), hresult_wrong_thread); - - IStringable stringable = impl.as(); - REQUIRE_THROWS_AS(stringable.ToString(), hresult_wrong_thread); - } -} diff --git a/test/test_win7/agile_ref.cpp b/test/test_win7/agile_ref.cpp deleted file mode 100644 index e0ab43a34..000000000 --- a/test/test_win7/agile_ref.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - struct Object : implements - { - hstring ToString() - { - return L"Object"; - } - }; -} - -TEST_CASE("agile_ref") -{ - agile_ref ref = make(); - - // - // Here we're creating an agile_ref explicitly and using a traditional lambda variable capture - // to pass it to the delegate. - // - - delegate<> a = [ref] - { - IStringable object = ref.get(); - REQUIRE(object.ToString() == L"Object"); - }; - - a(); - - // - // Here's we're using the make_agile helper with generalized lambda capture to produce a - // variable local to the lambda. - // - - delegate<> b = [ref = make_agile(make())] - { - IStringable object = ref.get(); - REQUIRE(object.ToString() == L"Object"); - }; - - b(); - - // - // And it's ok to resolve a nullptr agile_ref. - // - - agile_ref empty; - IStringable object = empty.get(); - REQUIRE(object == nullptr); -} diff --git a/test/test_win7/agility.cpp b/test/test_win7/agility.cpp deleted file mode 100644 index 78fed2fda..000000000 --- a/test/test_win7/agility.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.Delegates.h" - -// -// These tests confirm the COM identity and other behaviours for agile implementations. -// - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - struct TestAgile : implements - { - bool& m_destroyed; - TestAgile(bool& destroyed) : m_destroyed(destroyed) { m_destroyed = false; } - ~TestAgile() { m_destroyed = true; } - - void Close() {} - }; - - struct TestNonAgile : implements - { - void Close() {} - }; -} - -TEST_CASE("agility") -{ - using Windows::Foundation::IUnknown; - using Windows::Foundation::IInspectable; - - // Test agility - { - bool destroyed = false; - - { - IInspectable object = make(destroyed); - - // Confirm agility - object.as(); - - // Confirm legacy agility - com_ptr marshal = object.as(); - - // Confirm tear-off identity - IUnknown object_identity = object.as(); - IUnknown marshal_identity = marshal.as(); - - REQUIRE(object_identity == marshal_identity); - REQUIRE(!destroyed); - } - - // Confirm tear-off does not leak reference - REQUIRE(destroyed); - } - - // Test non-agility - { - IInspectable object = make(); - - // Does not implement IAgileObject - REQUIRE_THROWS_AS(object.as(), hresult_no_interface); - - // Does not implement IMarshal - REQUIRE_THROWS_AS(object.as(), hresult_no_interface); - } - - // Test IMarshal tearoff lifetime - { - bool destroyed = false; - - IInspectable object = make(destroyed); - com_ptr marshal = object.as(); - object = nullptr; - REQUIRE(!destroyed); - - // Confirm agility (back to object) - marshal.as(); - - // QI on tearoff itself - com_ptr marshal2 = marshal.as(); - REQUIRE(marshal == marshal2); - marshal2 = nullptr; - - // Confirm tear-off does not leak reference - REQUIRE(!destroyed); - marshal = nullptr; - REQUIRE(destroyed); - } - - // Test agile delegate - { - IUnknown object = test_component::Delegates::AgileDelegate([] {}); - com_ptr marshal = object.as(); - object = nullptr; - - // Confirm agility (back to object) - marshal.as(); - - // QI on tearoff itself - com_ptr marshal2 = marshal.as(); - REQUIRE(marshal == marshal2); - } - - // Test agile weak reference - { - bool destroyed = false; - IClosable object = make(destroyed); - com_ptr source = object.as(); - - // Clear object but source keeps object alive - object = nullptr; - source.as(); - - com_ptr ref; - check_hresult(source->GetWeakReference(ref.put())); - - // Drop the source object - REQUIRE(S_OK == ref->Resolve(guid_of(), put_abi(object))); - REQUIRE(object != nullptr); - source = nullptr; - REQUIRE(!destroyed); - object = nullptr; - REQUIRE(destroyed); - REQUIRE(S_OK == ref->Resolve(guid_of(), put_abi(object))); - REQUIRE(object == nullptr); - - // Marshaling support on weak ref - com_ptr marshal = ref.as(); - ref = nullptr; - - // Confirm agility (back to object): - marshal.as(); - - // QI on tearoff itself - com_ptr marshal2 = marshal.as(); - REQUIRE(marshal == marshal2); - } -} diff --git a/test/test_win7/async_auto_cancel.cpp b/test/test_win7/async_auto_cancel.cpp deleted file mode 100644 index cceafa443..000000000 --- a/test/test_win7/async_auto_cancel.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - - // - // Checks that the coroutine is automatically canceled when reaching a suspension point. - // - - IAsyncAction Action(HANDLE event) - { - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - } - - IAsyncActionWithProgress ActionWithProgress(HANDLE event) - { - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - } - - IAsyncOperation Operation(HANDLE event) - { - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress(HANDLE event) - { - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - co_return 1; - } - - template - void Check(F make) - { - handle start{ CreateEvent(nullptr, true, false, nullptr) }; - handle completed{ CreateEvent(nullptr, true, false, nullptr) }; - auto async = make(start.get()); - REQUIRE(async.Status() == AsyncStatus::Started); - - async.Completed([&](auto&& sender, AsyncStatus status) - { - REQUIRE(async == sender); - REQUIRE(status == AsyncStatus::Canceled); - SetEvent(completed.get()); - }); - - async.Cancel(); - SetEvent(start.get()); - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); - - REQUIRE(async.Status() == AsyncStatus::Canceled); - REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED)); - REQUIRE_THROWS_AS(async.GetResults(), hresult_canceled); - } -} - -#if defined(__clang__) && defined(_MSC_VER) -// FIXME: Test is known to segfault when built with Clang. -TEST_CASE("async_auto_cancel", "[.clang-crash]") -#else -TEST_CASE("async_auto_cancel") -#endif -{ - Check(Action); - Check(ActionWithProgress); - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_cancel_callback.cpp b/test/test_win7/async_cancel_callback.cpp deleted file mode 100644 index 396636eba..000000000 --- a/test/test_win7/async_cancel_callback.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - - // - // Checks that the cancellation callback is invoked. - // - - IAsyncAction Action(HANDLE event, bool& canceled) - { - auto cancel = co_await get_cancellation_token(); - - cancel.callback([&] - { - REQUIRE(!canceled); - canceled = true; - }); - - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - } - - IAsyncActionWithProgress ActionWithProgress(HANDLE event, bool& canceled) - { - auto cancel = co_await get_cancellation_token(); - - cancel.callback([&] - { - REQUIRE(!canceled); - canceled = true; - }); - - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - } - - IAsyncOperation Operation(HANDLE event, bool& canceled) - { - auto cancel = co_await get_cancellation_token(); - - cancel.callback([&] - { - REQUIRE(!canceled); - canceled = true; - }); - - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress(HANDLE event, bool& canceled) - { - auto cancel = co_await get_cancellation_token(); - - cancel.callback([&] - { - REQUIRE(!canceled); - canceled = true; - }); - - co_await resume_on_signal(event); - co_await suspend_never(); - REQUIRE(false); - co_return 1; - } - - template - void Check(F make) - { - handle event{ CreateEvent(nullptr, true, false, nullptr) }; - bool canceled = false; - auto async = make(event.get(), canceled); - async.Cancel(); - REQUIRE(canceled); - SetEvent(event.get()); - REQUIRE_THROWS_AS(async.GetResults(), hresult_canceled); - } -} - -#if defined(__clang__) && defined(_MSC_VER) -// FIXME: Test is known to segfault when built with Clang. -TEST_CASE("async_cancel_callback", "[.clang-crash]") -#else -TEST_CASE("async_cancel_callback") -#endif -{ - Check(Action); - Check(ActionWithProgress); - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_check_cancel.cpp b/test/test_win7/async_check_cancel.cpp deleted file mode 100644 index 7547609f6..000000000 --- a/test/test_win7/async_check_cancel.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - - // - // Checks that manual cancellation checks work. - // - - IAsyncAction Action(HANDLE event, bool& canceled) - { - co_await resume_on_signal(event); - auto cancel = co_await get_cancellation_token(); - - if (cancel()) - { - REQUIRE(!canceled); - canceled = true; - } - - co_await suspend_never(); - REQUIRE(false); - } - - IAsyncActionWithProgress ActionWithProgress(HANDLE event, bool& canceled) - { - co_await resume_on_signal(event); - auto cancel = co_await get_cancellation_token(); - - if (cancel()) - { - REQUIRE(!canceled); - canceled = true; - } - - co_await suspend_never(); - REQUIRE(false); - } - - IAsyncOperation Operation(HANDLE event, bool& canceled) - { - co_await resume_on_signal(event); - auto cancel = co_await get_cancellation_token(); - - if (cancel()) - { - REQUIRE(!canceled); - canceled = true; - } - - co_await suspend_never(); - REQUIRE(false); - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress(HANDLE event, bool& canceled) - { - co_await resume_on_signal(event); - auto cancel = co_await get_cancellation_token(); - - if (cancel()) - { - REQUIRE(!canceled); - canceled = true; - } - - co_await suspend_never(); - REQUIRE(false); - co_return 1; - } - - template - void Check(F make) - { - handle start{ CreateEvent(nullptr, true, false, nullptr) }; - handle completed{ CreateEvent(nullptr, true, false, nullptr) }; - bool canceled = false; - auto async = make(start.get(), canceled); - REQUIRE(async.Status() == AsyncStatus::Started); - - async.Completed([&](auto&& sender, AsyncStatus status) - { - REQUIRE(async == sender); - REQUIRE(status == AsyncStatus::Canceled); - REQUIRE(canceled); - SetEvent(completed.get()); - }); - - async.Cancel(); - SetEvent(start.get()); - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); - - REQUIRE(async.Status() == AsyncStatus::Canceled); - REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED)); - REQUIRE_THROWS_AS(async.GetResults(), hresult_canceled); - } -} - -#if defined(__clang__) && defined(_MSC_VER) -// FIXME: Test is known to segfault when built with Clang. -TEST_CASE("async_check_cancel", "[.clang-crash]") -#else -TEST_CASE("async_check_cancel") -#endif -{ - Check(Action); - Check(ActionWithProgress); - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_local.cpp b/test/test_win7/async_local.cpp deleted file mode 100644 index fa96dabb5..000000000 --- a/test/test_win7/async_local.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // - // Checks that coroutine locals are destroyed prior to notifying waiters. - // - - struct Local - { - bool& destroyed; - - ~Local() - { - REQUIRE(!destroyed); - destroyed = true; - } - }; - - IAsyncAction Action(HANDLE event, bool& destroyed) - { - co_await resume_on_signal(event); - Local local{ destroyed }; - } - - IAsyncActionWithProgress ActionWithProgress(HANDLE event, bool& destroyed) - { - co_await resume_on_signal(event); - Local local{ destroyed }; - } - - IAsyncOperation Operation(HANDLE event, bool& destroyed) - { - co_await resume_on_signal(event); - Local local{ destroyed }; - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress(HANDLE event, bool& destroyed) - { - co_await resume_on_signal(event); - Local local{ destroyed }; - co_return 1; - } - - template - void Check(F make) - { - handle start{ CreateEvent(nullptr, true, false, nullptr) }; - handle completed{ CreateEvent(nullptr, true, false, nullptr) }; - bool destroyed = false; - auto async = make(start.get(), destroyed); - - async.Completed([&](auto&&...) - { - REQUIRE(destroyed); - SetEvent(completed.get()); - }); - - SetEvent(start.get()); - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); - } -} - -TEST_CASE("async_local") -{ - Check(Action); - Check(ActionWithProgress); - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_no_suspend.cpp b/test/test_win7/async_no_suspend.cpp deleted file mode 100644 index 6888d0b98..000000000 --- a/test/test_win7/async_no_suspend.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // - // Checks that coroutines lacking suspension points work. - // - - IAsyncAction Action() - { - co_return; - } - - IAsyncActionWithProgress ActionWithProgress() - { - co_return; - } - - IAsyncOperation Operation() - { - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress() - { - co_return 1; - } - - IAsyncAction Await() - { - co_await Action(); - co_await ActionWithProgress(); - co_await Operation(); - co_await OperationWithProgress(); - } - - template - void Check(T const& async) - { - REQUIRE(async.Status() == AsyncStatus::Completed); - REQUIRE(async.ErrorCode() == 0); - REQUIRE(async.Id() == 1); - - // Should not throw in the Completed state. - async.GetResults(); - - bool completed = false; - - async.Completed([&](auto&& sender, AsyncStatus status) - { - completed = true; - REQUIRE(async == sender); - REQUIRE(status == AsyncStatus::Completed); - }); - - REQUIRE(completed); - - // May only assign Completed handler once. - REQUIRE_THROWS_AS(async.Completed([&](auto && ...) {}), hresult_illegal_delegate_assignment); - - // Close does nothing. - async.Close(); - - // Harmless but too late to cancel. - async.Cancel(); - REQUIRE(async.Status() == AsyncStatus::Completed); - } -} - -TEST_CASE("async_no_suspend") -{ - Action().get(); - ActionWithProgress().get(); - Operation().get(); - OperationWithProgress().get(); - Await().get(); - - Check(Action()); - Check(ActionWithProgress()); - Check(Operation()); - Check(OperationWithProgress()); -} diff --git a/test/test_win7/async_progress.cpp b/test/test_win7/async_progress.cpp deleted file mode 100644 index 0a2790f50..000000000 --- a/test/test_win7/async_progress.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // - // Checks that progress reporting works. - // - - IAsyncActionWithProgress Action(HANDLE event) - { - co_await resume_on_signal(event); - auto progress = co_await get_progress_token(); - progress(123); - } - - IAsyncOperationWithProgress Operation(HANDLE event) - { - co_await resume_on_signal(event); - auto progress = co_await get_progress_token(); - progress(123); - co_return 1; - } - - template - IAsyncAction Check(F make) - { - // Event not set to allow Progress handler to be wired up. - handle start{ CreateEvent(nullptr, true, false, nullptr) }; - - auto async = make(start.get()); - bool progress = false; - - async.Progress([&](auto&& sender, int value) - { - progress = true; - REQUIRE(async == sender); - REQUIRE(value == 123); - }); - - SetEvent(start.get()); - co_await async; - - REQUIRE(progress); - REQUIRE(async.Status() == AsyncStatus::Completed); - REQUIRE(async.ErrorCode() == S_OK); - } - - template - IAsyncAction TooLate(F make) - { - // Event initially set so that coroutine does not suspend. - handle start{ CreateEvent(nullptr, true, true, nullptr) }; - - auto async = make(start.get()); - REQUIRE(async.Status() == AsyncStatus::Completed); - - bool progress = false; - - async.Progress([&](auto&&...) - { - REQUIRE(false); - }); - - co_await async; - - REQUIRE(!progress); - REQUIRE(async.Status() == AsyncStatus::Completed); - REQUIRE(async.ErrorCode() == S_OK); - } -} - -TEST_CASE("async_progress") -{ - Check(Action); - Check(Operation); - - TooLate(Action); - TooLate(Operation); -} diff --git a/test/test_win7/async_result.cpp b/test/test_win7/async_result.cpp deleted file mode 100644 index 9c1accccb..000000000 --- a/test/test_win7/async_result.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // - // Checks that result values are propagated properly. - // - - IAsyncOperation Operation(HANDLE event) - { - co_await resume_on_signal(event); - co_return 123; - } - - IAsyncOperationWithProgress OperationWithProgress(HANDLE event) - { - co_await resume_on_signal(event); - co_return 123; - } - - IAsyncAction Await() - { - // Manual reset so that all waiters will resume and initially set so they won't block. - handle event{ CreateEvent(nullptr, true, true, nullptr) }; - - int a = co_await Operation(event.get()); - int b = co_await OperationWithProgress(event.get()); - - REQUIRE(a == 123); - REQUIRE(b == 123); - } - - template - void Check(F make) - { - handle start{ CreateEvent(nullptr, true, false, nullptr) }; - handle completed{ CreateEvent(nullptr, true, false, nullptr) }; - auto async = make(start.get()); - REQUIRE(async.Status() == AsyncStatus::Started); - if constexpr (has_async_progress) - { - // You're allowed to peek at partial results of IAsyncXxxWithProgress. - REQUIRE_NOTHROW(async.GetResults()); - } - else - { - REQUIRE_THROWS_AS(async.GetResults(), hresult_illegal_method_call); - } - - async.Completed([&](auto&& sender, AsyncStatus status) - { - REQUIRE(async == sender); - REQUIRE(status == AsyncStatus::Completed); - SetEvent(completed.get()); - }); - - // Still in Started state waiting for signal. - Sleep(100); - REQUIRE(WaitForSingleObject(completed.get(), 0) == WAIT_TIMEOUT); - REQUIRE(async.Status() == AsyncStatus::Started); - - // Signal async to run. - SetEvent(start.get()); - - // Wait for async to complete. - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); - - REQUIRE(async.Status() == AsyncStatus::Completed); - REQUIRE(async.ErrorCode() == S_OK); - REQUIRE(async.GetResults() == 123); - } -} - -TEST_CASE("async_result") -{ - handle start{ CreateEvent(nullptr, true, true, nullptr) }; - REQUIRE(123 == Operation(start.get()).get()); - REQUIRE(123 == OperationWithProgress(start.get()).get()); - Await().get(); - - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_return.cpp b/test/test_win7/async_return.cpp deleted file mode 100644 index 23b1c1eec..000000000 --- a/test/test_win7/async_return.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // - // Checks that return values support both rvalue and lvalue. - // - - IAsyncOperation Operation(bool rvalue) - { - if (rvalue) - { - hstring value = L"rvalue"; - co_return std::move(value); - } - else - { - hstring value = L"lvalue"; - co_return value; - } - } - - IAsyncOperationWithProgress OperationWithProgress(bool rvalue) - { - if (rvalue) - { - hstring value = L"rvalue"; - co_return std::move(value); - } - else - { - hstring value = L"lvalue"; - co_return value; - } - } - - template - void Check(F make) - { - REQUIRE(make(true).get() == L"rvalue"); - REQUIRE(make(false).get() == L"lvalue"); - } -} - -TEST_CASE("async_return") -{ - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_suspend.cpp b/test/test_win7/async_suspend.cpp deleted file mode 100644 index f7beee21d..000000000 --- a/test/test_win7/async_suspend.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // - // Checks basic suspension behavior. - // - - IAsyncAction Action(HANDLE event) - { - co_await resume_on_signal(event); - } - - IAsyncActionWithProgress ActionWithProgress(HANDLE event) - { - co_await resume_on_signal(event); - } - - IAsyncOperation Operation(HANDLE event) - { - co_await resume_on_signal(event); - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress(HANDLE event) - { - co_await resume_on_signal(event); - co_return 1; - } - - IAsyncAction Await() - { - // Manual reset so that all waiters will resume and initially set so they won't block. - handle event{ CreateEvent(nullptr, true, true, nullptr) }; - - co_await Action(event.get()); - co_await ActionWithProgress(event.get()); - co_await Operation(event.get()); - co_await OperationWithProgress(event.get()); - } - - template - void Check(F make) - { - handle start{ CreateEvent(nullptr, true, false, nullptr) }; - handle completed{ CreateEvent(nullptr, true, false, nullptr) }; - auto async = make(start.get()); - REQUIRE(async.Status() == AsyncStatus::Started); - if constexpr (has_async_progress) - { - // You're allowed to peek at partial results of IAsyncXxxWithProgress. - REQUIRE_NOTHROW(async.GetResults()); - } - else - { - REQUIRE_THROWS_AS(async.GetResults(), hresult_illegal_method_call); - } - - async.Completed([&](auto&& sender, AsyncStatus status) - { - REQUIRE(async == sender); - REQUIRE(status == AsyncStatus::Completed); - SetEvent(completed.get()); - }); - - // Still in Started state waiting for signal. - Sleep(100); - REQUIRE(WaitForSingleObject(completed.get(), 0) == WAIT_TIMEOUT); - REQUIRE(async.Status() == AsyncStatus::Started); - - // Signal async to run. - SetEvent(start.get()); - - // Wait for async to complete. - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); - - REQUIRE(async.Status() == AsyncStatus::Completed); - REQUIRE(async.ErrorCode() == S_OK); - } -} - -TEST_CASE("async_suspend") -{ - handle start{ CreateEvent(nullptr, true, true, nullptr) }; - Action(start.get()).get(); - ActionWithProgress(start.get()).get(); - Operation(start.get()).get(); - OperationWithProgress(start.get()).get(); - Await().get(); - - Check(Action); - Check(ActionWithProgress); - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_throw.cpp b/test/test_win7/async_throw.cpp deleted file mode 100644 index 88e38d323..000000000 --- a/test/test_win7/async_throw.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; -using namespace std::chrono_literals; - -namespace -{ - // - // Checks that exceptions are correctly captured and propagated. - // - - IAsyncAction Action() - { - co_await 10ms; - throw hresult_invalid_argument(L"Async"); - } - - IAsyncActionWithProgress ActionWithProgress() - { - co_await 10ms; - throw hresult_invalid_argument(L"Async"); - } - - IAsyncOperation Operation() - { - co_await 10ms; - throw hresult_invalid_argument(L"Async"); - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress() - { - co_await 10ms; - throw hresult_invalid_argument(L"Async"); - co_return 1; - } - - template - void Check(F make) - { - try - { - make().get(); - REQUIRE(false); - } - catch (hresult_invalid_argument const& e) - { - REQUIRE(e.message() == L"Async"); - } - - handle completed{ CreateEvent(nullptr, true, false, nullptr) }; - auto async = make(); - - async.Completed([&](auto&& sender, AsyncStatus status) - { - REQUIRE(async == sender); - REQUIRE(status == AsyncStatus::Error); - SetEvent(completed.get()); - }); - - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); - REQUIRE(async.Status() == AsyncStatus::Error); - - hresult_error e(async.ErrorCode(), take_ownership_from_abi); - REQUIRE(e.message() == L"Async"); - - try - { - async.GetResults(); - REQUIRE(false); - } - catch (hresult_invalid_argument const& e) - { - REQUIRE(e.message() == L"Async"); - } - } -} - -#if defined(__clang__) && defined(_MSC_VER) -// FIXME: Test is known to segfault when built with Clang. -TEST_CASE("async_throw", "[.clang-crash]") -#else -TEST_CASE("async_throw") -#endif -{ - Check(Action); - Check(ActionWithProgress); - Check(Operation); - Check(OperationWithProgress); -} diff --git a/test/test_win7/async_wait_for.cpp b/test/test_win7/async_wait_for.cpp deleted file mode 100644 index d7613083c..000000000 --- a/test/test_win7/async_wait_for.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include "pch.h" - -using namespace std::literals; -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - IAsyncAction Action(TimeSpan delay, AsyncStatus result) - { - co_await resume_after(delay); - - if (result == AsyncStatus::Error) - { - throw hresult_invalid_argument(); - } - - if (result == AsyncStatus::Canceled) - { - throw hresult_canceled(); - } - } - - IAsyncActionWithProgress ActionWithProgress(TimeSpan delay, AsyncStatus result) - { - co_await resume_after(delay); - - if (result == AsyncStatus::Error) - { - throw hresult_invalid_argument(); - } - - if (result == AsyncStatus::Canceled) - { - throw hresult_canceled(); - } - } - - IAsyncOperation Operation(TimeSpan delay, AsyncStatus result) - { - co_await resume_after(delay); - - if (result == AsyncStatus::Error) - { - throw hresult_invalid_argument(); - } - - if (result == AsyncStatus::Canceled) - { - throw hresult_canceled(); - } - - co_return 1; - } - - IAsyncOperationWithProgress OperationWithProgress(TimeSpan delay, AsyncStatus result) - { - co_await resume_after(delay); - - if (result == AsyncStatus::Error) - { - throw hresult_invalid_argument(); - } - - if (result == AsyncStatus::Canceled) - { - throw hresult_canceled(); - } - - co_return 1; - } - - template - void check(T const& no_suspend_ok, T const& no_suspend_fail, T const& delay_ok, T const& delay_fail, T const& no_suspend_cancel, T const& delay_cancel, T const& long_delay) - { - REQUIRE(no_suspend_ok.wait_for(0s) == AsyncStatus::Completed); - no_suspend_ok.get(); - REQUIRE_THROWS_AS(no_suspend_ok.wait_for(0s), hresult_illegal_delegate_assignment); - - REQUIRE(no_suspend_fail.wait_for(0s) == AsyncStatus::Error); - REQUIRE_THROWS_AS(no_suspend_fail.get(), hresult_invalid_argument); - - REQUIRE(delay_ok.wait_for(1s) == AsyncStatus::Completed); - delay_ok.get(); - - REQUIRE(delay_fail.wait_for(1s) == AsyncStatus::Error); - REQUIRE_THROWS_AS(delay_fail.get(), hresult_invalid_argument); - - REQUIRE(no_suspend_cancel.wait_for(0s) == AsyncStatus::Canceled); - REQUIRE_THROWS_AS(no_suspend_cancel.get(), hresult_canceled); - - REQUIRE(delay_cancel.wait_for(1s) == AsyncStatus::Canceled); - REQUIRE_THROWS_AS(delay_cancel.get(), hresult_canceled); - - REQUIRE(long_delay.wait_for(100ms) == AsyncStatus::Started); - } -} - -#if defined(__clang__) && defined(_MSC_VER) -// FIXME: Test is known to segfault when built with Clang. -TEST_CASE("async_wait_for", "[.clang-crash]") -#else -TEST_CASE("async_wait_for") -#endif -{ - check( - Action(0s, AsyncStatus::Completed), - Action(0s, AsyncStatus::Error), - Action(100ms, AsyncStatus::Completed), - Action(100ms, AsyncStatus::Error), - Action(0s, AsyncStatus::Canceled), - Action(100ms, AsyncStatus::Canceled), - Action(1h, AsyncStatus::Completed)); - - check( - ActionWithProgress(0s, AsyncStatus::Completed), - ActionWithProgress(0s, AsyncStatus::Error), - ActionWithProgress(100ms, AsyncStatus::Completed), - ActionWithProgress(100ms, AsyncStatus::Error), - ActionWithProgress(0s, AsyncStatus::Canceled), - ActionWithProgress(100ms, AsyncStatus::Canceled), - ActionWithProgress(1h, AsyncStatus::Completed)); - - check( - Operation(0s, AsyncStatus::Completed), - Operation(0s, AsyncStatus::Error), - Operation(100ms, AsyncStatus::Completed), - Operation(100ms, AsyncStatus::Error), - Operation(0s, AsyncStatus::Canceled), - Operation(100ms, AsyncStatus::Canceled), - Operation(1h, AsyncStatus::Completed)); - - check( - OperationWithProgress(0s, AsyncStatus::Completed), - OperationWithProgress(0s, AsyncStatus::Error), - OperationWithProgress(100ms, AsyncStatus::Completed), - OperationWithProgress(100ms, AsyncStatus::Error), - OperationWithProgress(0s, AsyncStatus::Canceled), - OperationWithProgress(100ms, AsyncStatus::Canceled), - OperationWithProgress(1h, AsyncStatus::Completed)); -} diff --git a/test/test_win7/capture.cpp b/test/test_win7/capture.cpp deleted file mode 100644 index 9019d1e34..000000000 --- a/test/test_win7/capture.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -struct DECLSPEC_UUID("5fb96f8d-409c-42a9-99a7-8a95c1459dbd") ICapture : ::IUnknown -{ - virtual int32_t __stdcall GetValue() noexcept = 0; - virtual int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept = 0; -}; - -#ifdef __CRT_UUID_DECL -__CRT_UUID_DECL(ICapture, 0x5fb96f8d, 0x409c, 0x42a9, 0x99, 0xa7, 0x8a, 0x95, 0xc1, 0x45, 0x9d, 0xbd) -#endif - -struct Capture : implements -{ - int32_t const m_value{}; - - Capture(int32_t value) : - m_value{ value } - { - } - - hstring ToString() - { - return hstring{ std::to_wstring(m_value) }; - } - - int32_t __stdcall GetValue() noexcept override - { - return m_value; - } - - int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept override - { - auto capture = make(value); - return capture->QueryInterface(iid, object); - } -}; - -HRESULT __stdcall CreateNonMemberCapture(int value, GUID const& iid, void** object) noexcept -{ - auto capture = make(value); - return capture->QueryInterface(iid, object); -} - -TEST_CASE("capture") -{ - com_ptr a = capture(CreateNonMemberCapture, 10); - REQUIRE(a->GetValue() == 10); - a = nullptr; - a.capture(CreateNonMemberCapture, 20); - REQUIRE(a->GetValue() == 20); - - com_ptr b = capture(a, &ICapture::CreateMemberCapture, 30); - REQUIRE(b->GetValue() == 30); - b = nullptr; - b.capture(a, &ICapture::CreateMemberCapture, 40); - REQUIRE(b->GetValue() == 40); - - IStringable c = capture(CreateNonMemberCapture, 50); - REQUIRE(c.ToString() == L"50"); - c = capture(a, &ICapture::CreateMemberCapture, 60); - REQUIRE(c.ToString() == L"60"); - - com_ptr d; - - REQUIRE_THROWS_AS(capture(CreateNonMemberCapture, 0), hresult_no_interface); - REQUIRE_THROWS_AS(capture(CreateNonMemberCapture, 0), hresult_no_interface); - REQUIRE_THROWS_AS(d.capture(CreateNonMemberCapture, 0), hresult_no_interface); - REQUIRE_THROWS_AS(capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface); - REQUIRE_THROWS_AS(capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface); - REQUIRE_THROWS_AS(d.capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface); -} diff --git a/test/test_win7/cmd_reader.cpp b/test/test_win7/cmd_reader.cpp deleted file mode 100644 index 731922fd8..000000000 --- a/test/test_win7/cmd_reader.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "pch.h" -#include "cmd_reader.h" -#include - -using namespace cppwinrt; - -class response_file -{ - const char* resp_file_name = "respfile.txt"; - void write_response_file(const char* input) - { - std::ofstream resp_file(resp_file_name); - if (!resp_file.is_open()) - FAIL("Response file could not be created"); - resp_file << input; - resp_file.close(); - } - - void remove_response_file() - { - std::remove(resp_file_name); - } - -public: - response_file(const char* input) - { - write_response_file(input); - } - - template - reader create_reader(size_t const argc, const char* argv[], const option(&options)[numOptions]) - { - return reader{ argc, argv, options }; - } - - ~response_file() - { - remove_response_file(); - } -}; - -TEST_CASE("cmd_reader") -{ - static constexpr option options[] - { - { "input", 1 }, - { "reference", 0 }, - { "output", 0, 1 }, - { "component", 0, 1 }, - { "filter", 0 }, - { "name", 0, 1 }, - { "verbose", 0, 0 }, - }; - - // input and output - { - const char* argv[] = { "progname", "-in", "example_file.in", "-out", "example_file.out" }; - const size_t argc = 5; - reader args{ argc, argv, options }; - - REQUIRE(args.exists("input")); - REQUIRE(args.value("input") == "example_file.in"); - REQUIRE_FALSE(args.exists("reference")); - REQUIRE(args.exists("output")); - REQUIRE(args.value("output") == "example_file.out"); - REQUIRE_FALSE(args.exists("filter")); - REQUIRE_FALSE(args.exists("name")); - REQUIRE_FALSE(args.exists("verbose")); - } - - // response file #1: filename no quotes - { - const char* argv[] = { "progname", "@respfile.txt" }; - const size_t argc = _countof(argv); - - response_file rf{ R"(-in example_file.in -out example_file.out)" }; - reader args = rf.create_reader(argc, argv, options); - - REQUIRE(args.exists("input")); - REQUIRE(args.value("input") == "example_file.in"); - REQUIRE_FALSE(args.exists("reference")); - REQUIRE(args.exists("output")); - REQUIRE(args.value("output") == "example_file.out"); - REQUIRE_FALSE(args.exists("filter")); - REQUIRE_FALSE(args.exists("name")); - REQUIRE_FALSE(args.exists("verbose")); - } - - // response file #2: filename with quotes - { - const char* argv[] = { "progname", "@respfile.txt" }; - const size_t argc = _countof(argv); - - response_file rf{ R"(-in "example file.in" -out "example file.out")" }; - reader args = rf.create_reader(argc, argv, options); - - REQUIRE(args.exists("input")); - REQUIRE(args.value("input") == "example file.in"); - REQUIRE_FALSE(args.exists("reference")); - REQUIRE(args.exists("output")); - REQUIRE(args.value("output") == "example file.out"); - REQUIRE_FALSE(args.exists("filter")); - REQUIRE_FALSE(args.exists("name")); - REQUIRE_FALSE(args.exists("verbose")); - } - - // response file #3: filename with quote within name - { - const char* argv[] = { "progname", "@respfile.txt" }; - const size_t argc = _countof(argv); - - response_file rf{ R"(-in example\"file.in -out example\"file.out)" }; - reader args = rf.create_reader(argc, argv, options); - - REQUIRE(args.exists("input")); - REQUIRE(args.value("input") == R"(example"file.in)"); - REQUIRE_FALSE(args.exists("reference")); - REQUIRE(args.exists("output")); - REQUIRE(args.value("output") == R"(example"file.out)"); - REQUIRE_FALSE(args.exists("filter")); - REQUIRE_FALSE(args.exists("name")); - REQUIRE_FALSE(args.exists("verbose")); - } - - // response file #4: really really long path - { - const char* argv[] = { "progname", "@respfile.txt" }; - const size_t argc = _countof(argv); - std::string file_name_in(R"(C:\)"); - std::string file_name_out(R"(C:\)"); - std::string input_str("-in "); - - for (int i = 0; i < 500; i++) { - file_name_in.append(R"(dirname\)"); - file_name_out.append(R"(dirname\)"); - } - - file_name_in.append("example_file.in"); - file_name_out.append("example_file.out"); - input_str.append(file_name_in).append(" -out ").append(file_name_out); - - response_file rf{ input_str.data() }; - reader args = rf.create_reader(argc, argv, options); - - REQUIRE(args.exists("input")); - REQUIRE(args.value("input") == file_name_in); - REQUIRE_FALSE(args.exists("reference")); - REQUIRE(args.exists("output")); - REQUIRE(args.value("output") == file_name_out); - REQUIRE_FALSE(args.exists("filter")); - REQUIRE_FALSE(args.exists("name")); - REQUIRE_FALSE(args.exists("verbose")); - } -} diff --git a/test/test_win7/coro_foundation.cpp b/test/test_win7/coro_foundation.cpp deleted file mode 100644 index c2705982a..000000000 --- a/test/test_win7/coro_foundation.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Intentionally not using pch... -#include "catch.hpp" - -// Only need winrt/Windows.Foundation.h for IAsyncXxx coroutine support -#include "winrt/Windows.Foundation.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - IAsyncOperation Async() - { - co_return L"hello"; - } -} - -TEST_CASE("coro_foundation") -{ - REQUIRE(Async().get() == L"hello"); -} diff --git a/test/test_win7/coro_threadpool.cpp b/test/test_win7/coro_threadpool.cpp deleted file mode 100644 index 4c31f8a03..000000000 --- a/test/test_win7/coro_threadpool.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Intentionally not using pch... -#include "catch.hpp" - -// Only need winrt/base.h for coroutine thread pool support. -#include "winrt/base.h" - -using namespace winrt; - -namespace -{ - fire_and_forget Async() - { - co_await resume_background(); - } -} - -TEST_CASE("coro_base") -{ - Async(); -} diff --git a/test/test_win7/custom_error.cpp b/test/test_win7/custom_error.cpp deleted file mode 100644 index b9850845a..000000000 --- a/test/test_win7/custom_error.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - // Some custom exception type unknown to C++/WinRT - struct CustomError - { - }; - - struct Sample : implements - { - hstring ToString() - { - // Throw custom exception inside C++/WinRT projection - throw CustomError(); - } - }; - - // Global handler to translate custom exception - int32_t __stdcall handler(void* address) noexcept - { - REQUIRE(address); - - try - { - throw; - } - catch (CustomError) - { - return 0x80000018; // E_ILLEGAL_DELEGATE_ASSIGNMENT - } - - REQUIRE(false); - return 0; - } -} - -TEST_CASE("custom_error") -{ - // Set up global handler - REQUIRE(!winrt_to_hresult_handler); - winrt_to_hresult_handler = handler; - - // Validate that handler translated exception - REQUIRE_THROWS_AS(make().ToString(), hresult_illegal_delegate_assignment); - - // Remove global handler - winrt_to_hresult_handler = nullptr; -} diff --git a/test/test_win7/delegate.cpp b/test/test_win7/delegate.cpp deleted file mode 100644 index bade55060..000000000 --- a/test/test_win7/delegate.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "pch.h" - -using namespace winrt; - -TEST_CASE("delegate") -{ - // <> - { - bool invoked = false; - delegate<> d = [&] {invoked = true; }; - d(); - REQUIRE(invoked); - } - - // - { - int result = 0; - delegate d = [&](int a) {result = a; }; - d(123); - REQUIRE(result == 123); - } - - // - { - int result = 0; - delegate d = [&](int a, int b) {result = a + b; }; - d(4,5); - REQUIRE(result == 9); - } - - // void() - { - bool invoked = false; - delegate d = [&] {invoked = true; }; - d(); - REQUIRE(invoked); - } - - // void(int) - { - int result = 0; - delegate d = [&](int a) {result = a; }; - d(123); - REQUIRE(result == 123); - } - - // void(int,int) - { - int result = 0; - delegate d = [&](int a, int b) {result = a + b; }; - d(4, 5); - REQUIRE(result == 9); - } - - // int() - { - delegate d = [] { return 123; }; - REQUIRE(d() == 123); - } - - // int(int) - { - delegate d = [](int a) {return a; }; - REQUIRE(d(123) == 123); - } - - // int(int,int) - { - delegate d = [](int a, int b) {return a + b; }; - REQUIRE(d(4, 5) == 9); - } -} diff --git a/test/test_win7/delegates.cpp b/test/test_win7/delegates.cpp deleted file mode 100644 index af2eb6daf..000000000 --- a/test/test_win7/delegates.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.Delegates.h" - -using namespace winrt; -using namespace test_component::Delegates; - -TEST_CASE("delegates") -{ - { - bool run{}; - AgileDelegate d = [&] {run = true; }; - REQUIRE(!run); - d(); - REQUIRE(run); - } - { - hstring value; - InDelegate d = [&](hstring const& in) - { - value = in; - }; - REQUIRE(value.empty()); - d(L"Test"); - REQUIRE(value == L"Test"); - } - { - ReturnStringDelegate d = [] {return L"Test"; }; - REQUIRE(d() == L"Test"); - } - { - ReturnInt32Delegate d = [] {return 123; }; - REQUIRE(d() == 123); - } - { - OutStringDelegate d = [](hstring& value) - { - value = L"Test"; - }; - hstring value; - d(value); - REQUIRE(value == L"Test"); - } - { - OutStringDelegate d = [](hstring&) - { - }; - hstring value = L"old"; - d(value); - REQUIRE(value == L""); - } - { - OutInt32Delegate d = [](int32_t & value) - { - value = 123; - }; - int32_t value{ 0xCC }; - d(value); - REQUIRE(value == 123); - } - { - OutInt32Delegate d = [](int32_t&) - { - }; - int32_t value{ 123 }; - d(value); - REQUIRE(value == 123); - } - { - ReturnStringArrayDelegate d = [] { return com_array{ L"One", L"Two", L"Three" }; }; - com_array value = d(); - REQUIRE(value.size() == 3); - REQUIRE(value[0] == L"One"); - REQUIRE(value[1] == L"Two"); - REQUIRE(value[2] == L"Three"); - } - { - OutStringArrayDelegate d = [](com_array& value) { value = { L"One", L"Two", L"Three" }; }; - - com_array value; - d(value); - - REQUIRE(value.size() == 3); - REQUIRE(value[0] == L"One"); - REQUIRE(value[1] == L"Two"); - REQUIRE(value[2] == L"Three"); - } - { - RefStringArrayDelegate d = [](array_view value) { value[0] = L"One"; value[1] = L"Two"; value[2] = L"Three"; }; - - std::array value{ L"r1", L"r2", L"r3", L"r4" }; - d(value); - - REQUIRE(value[0] == L"One"); - REQUIRE(value[1] == L"Two"); - REQUIRE(value[2] == L"Three"); - REQUIRE(value[3] == L""); - } -} diff --git a/test/test_win7/disconnected.cpp b/test/test_win7/disconnected.cpp deleted file mode 100644 index a69a210d5..000000000 --- a/test/test_win7/disconnected.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "pch.h" - -using namespace std::literals; -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - IAsyncAction Action() - { - co_return; - } - - IAsyncActionWithProgress ActionProgress() - { - co_await 500ms; - auto progress = co_await get_progress_token(); - progress(123); - co_return; - } - - IAsyncOperation Operation() - { - co_return 123; - } - - IAsyncOperationWithProgress OperationProgress() - { - co_await 500ms; - auto progress = co_await get_progress_token(); - progress(123); - co_return 123; - } -} - -TEST_CASE("disconnected,1") -{ - event> source; - - source.add([](auto...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); - - auto token = source.add([](auto...) - { - throw hresult_error(E_INVALIDARG); - }); - - // Should have two delegates - REQUIRE(source); - - // Should lose the disconnected delegate - source(nullptr, 123); - REQUIRE(source); - - // Fire the remaining delegate - source(nullptr, 123); - REQUIRE(source); - - // Remove the final delegate - source.remove(token); - - // No more delegates - REQUIRE(!source); - - source(nullptr, 123); -} - -TEST_CASE("disconnected,2") -{ - auto async = Action(); - - async.Completed([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); -} - -TEST_CASE("disconnected,3") -{ - auto async = ActionProgress(); - handle signal{ CreateEventW(nullptr, true, false, nullptr) }; - - async.Progress([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); - - async.Completed([&](auto&&...) - { - SetEvent(signal.get()); - throw hresult_error(RPC_E_DISCONNECTED); - }); - - WaitForSingleObject(signal.get(), INFINITE); - // Give some time for to_hresult() to complete. - Sleep(500); -} - -TEST_CASE("disconnected,4") -{ - auto async = Operation(); - - async.Completed([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); -} - -TEST_CASE("disconnected,5") -{ - auto async = OperationProgress(); - handle signal{ CreateEventW(nullptr, true, false, nullptr) }; - - async.Progress([](auto&&...) - { - throw hresult_error(RPC_E_DISCONNECTED); - }); - - async.Completed([&](auto&&...) - { - SetEvent(signal.get()); - throw hresult_error(RPC_E_DISCONNECTED); - }); - - WaitForSingleObject(signal.get(), INFINITE); - // Give some time for to_hresult() to complete. - Sleep(500); -} diff --git a/test/test_win7/enum.cpp b/test/test_win7/enum.cpp deleted file mode 100644 index 48f356a75..000000000 --- a/test/test_win7/enum.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.h" - -using namespace winrt; -using namespace test_component; - -TEST_CASE("enum") -{ - STATIC_REQUIRE(std::is_same_v, int32_t>); - STATIC_REQUIRE(std::is_same_v, uint32_t>); - - STATIC_REQUIRE(name_of() == L"test_component.Signed"sv); - STATIC_REQUIRE(name_of() == L"test_component.Unsigned"sv); - - REQUIRE(((Unsigned::First | Unsigned::Second | Unsigned::Third) & Unsigned::Second) == Unsigned::Second); - - REQUIRE(static_cast(Signed::First) == -1); - REQUIRE(static_cast(Signed::Second) == 0); - REQUIRE(static_cast(Signed::Third) == 1); - - REQUIRE(static_cast(Unsigned::First) == 0); - REQUIRE(static_cast(Unsigned::Second) == 1); - REQUIRE(static_cast(Unsigned::Third) == 2); -} diff --git a/test/test_win7/fast_iterator.cpp b/test/test_win7/fast_iterator.cpp deleted file mode 100644 index 5be28fb3d..000000000 --- a/test/test_win7/fast_iterator.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "pch.h" - -TEST_CASE("fast_iterator") -{ - { - auto v = winrt::single_threaded_vector({ 1, 2, 3 }); - - std::vector result; - - std::copy(begin(v), end(v), std::back_inserter(result)); - - REQUIRE((result == std::vector{ 1, 2, 3 })); - } - { - auto v = winrt::single_threaded_vector({ 1, 2, 3 }); - - std::vector result; - - std::copy(rbegin(v), rend(v), std::back_inserter(result)); - - REQUIRE((result == std::vector{ 3, 2, 1 })); - } -} diff --git a/test/test_win7/final_release.cpp b/test/test_win7/final_release.cpp deleted file mode 100644 index c615499cb..000000000 --- a/test/test_win7/final_release.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - struct Sample : implements - { - hstring ToString() - { - return L"Sample"; - } - - ~Sample() - { - // It's safe to QI/AddRef/Release inside destructor. - IStringable s; - check_hresult(QueryInterface(guid_of(), put_abi(s))); - REQUIRE(s.ToString() == L"Sample"); - - // Weak references are also supported during destruction. - REQUIRE(weak_ref{ s }.get()); - - REQUIRE(released); - REQUIRE(!destroyed); - destroyed = true; - } - - static void final_release(std::unique_ptr ptr) noexcept - { - // It's safe to QI/AddRef/Release inside final_release. - IStringable s; - check_hresult(ptr->QueryInterface(guid_of(), put_abi(s))); - REQUIRE(s.ToString() == L"Sample"); - - // References must be released prior to destroying the unique_ptr. - s = nullptr; - - REQUIRE(!released); - REQUIRE(!destroyed); - released = true; - ptr = nullptr; - REQUIRE(destroyed); - } - - static inline bool released; - static inline bool destroyed; - }; -} - -TEST_CASE("final_release") -{ - { - auto s = make(); - - // Weak references are supported prior to destruction. - REQUIRE(weak_ref{ s }.get()); - - REQUIRE(!Sample::released); - REQUIRE(!Sample::destroyed); - s = nullptr; - REQUIRE(Sample::released); - REQUIRE(Sample::destroyed); - } -} diff --git a/test/test_win7/generic_type_names.cpp b/test/test_win7/generic_type_names.cpp deleted file mode 100644 index a91266a83..000000000 --- a/test/test_win7/generic_type_names.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// Windows.Foundation is intentionally *not* included here to ensure that stable names/guids -// are generated with only the xxx.0.h header. This ensures that indirect declarations produce -// stable identity values. -#define WINRT_LEAN_AND_MEAN -#include "winrt/Windows.Storage.h" - -#include "catch.hpp" -#include "generic_types.h" - -TEST_CASE("generic_type_names") -{ - using A = IIterable; - using B = IKeyValuePair>; - - test_guids(); - - // - // Generated Windows.Foundation names - // - - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IStringable", - IStringable); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IAsyncActionWithProgress`1>", - IAsyncActionWithProgress); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IAsyncOperationWithProgress`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - IAsyncOperationWithProgress); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IAsyncOperation`1>", - IAsyncOperation); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReferenceArray`1>", - IReferenceArray); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1>", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncActionProgressHandler`1>", - AsyncActionProgressHandler); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncActionWithProgressCompletedHandler`1>", - AsyncActionWithProgressCompletedHandler); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncOperationCompletedHandler`1>", - AsyncOperationCompletedHandler); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncOperationProgressHandler`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - AsyncOperationProgressHandler); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.AsyncOperationWithProgressCompletedHandler`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - AsyncOperationWithProgressCompletedHandler); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.EventHandler`1>", - EventHandler); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.TypedEventHandler`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - TypedEventHandler); - - // - // Generated Windows.Foundation.Collections names - // - - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IIterable`1>", - IIterable); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IIterator`1>", - IIterator); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IKeyValuePair`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - IKeyValuePair); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IMapChangedEventArgs`1>", - IMapChangedEventArgs); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IMapView`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - IMapView); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IMap`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - IMap); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IObservableMap`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - IObservableMap); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IObservableVector`1>", - IObservableVector); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVectorView`1>", - IVectorView); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1>", - IVector); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.MapChangedEventHandler`2, Windows.Foundation.Collections.IKeyValuePair`2, Single>>>", - MapChangedEventHandler); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.VectorChangedEventHandler`1>", - VectorChangedEventHandler); - - // - // Generated primitive names - // - - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); -#if __has_include() - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); -#endif - - // Enums, structs, IInspectable, classes, and delegates - - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IReference`1", - IReference); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1", - IVector); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1", - IVector); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Collections.IVector`1", - IVector); -} diff --git a/test/test_win7/generic_types.cpp b/test/test_win7/generic_types.cpp deleted file mode 100644 index 081155cd2..000000000 --- a/test/test_win7/generic_types.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "pch.h" -#include "generic_types.h" - -TEST_CASE("generic_types") -{ - test_guids(); - - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Uri", Uri); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.PropertyType", PropertyType); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.Point", Point); - REQUIRE_EQUAL_NAME(L"Windows.Foundation.IStringable", IStringable); -} diff --git a/test/test_win7/generic_types.h b/test/test_win7/generic_types.h deleted file mode 100644 index 5ddba76d9..000000000 --- a/test/test_win7/generic_types.h +++ /dev/null @@ -1,115 +0,0 @@ -#pragma once - -using namespace winrt; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -#if __has_include() -using namespace Windows::Foundation::Numerics; -#endif -using namespace std::literals; - -#define REQUIRE_EQUAL_GUID(left, ...) STATIC_REQUIRE(equal(guid(left), guid_of<__VA_ARGS__>())); -#define REQUIRE_EQUAL_NAME(left, ...) STATIC_REQUIRE(left == name_of<__VA_ARGS__>()); - -namespace -{ - constexpr bool equal(guid const& left, guid const& right) noexcept - { - return left.Data1 == right.Data1 && - left.Data2 == right.Data2 && - left.Data3 == right.Data3 && - left.Data4[0] == right.Data4[0] && - left.Data4[1] == right.Data4[1] && - left.Data4[2] == right.Data4[2] && - left.Data4[3] == right.Data4[3] && - left.Data4[4] == right.Data4[4] && - left.Data4[5] == right.Data4[5] && - left.Data4[6] == right.Data4[6] && - left.Data4[7] == right.Data4[7]; - } - - void test_guids() - { - using A = IIterable; - using B = IKeyValuePair>; - - REQUIRE_EQUAL_GUID("96369F54-8EB6-48F0-ABCE-C1B211E627C3"sv, IStringable); - - // - // Generated Windows.Foundation GUIDs - // - - REQUIRE_EQUAL_GUID("DD725452-2DA3-5103-9C7D-22EE9BB14AD3", IAsyncActionWithProgress); - REQUIRE_EQUAL_GUID("94645425-B9E5-5B91-B509-8DA4DF6A8916", IAsyncOperationWithProgress); - REQUIRE_EQUAL_GUID("2BD35EE6-72D9-5C5D-9827-05EBB81487AB", IAsyncOperation); - REQUIRE_EQUAL_GUID("4A33FE03-E8B9-5346-A124-5449913ECA57", IReferenceArray); - REQUIRE_EQUAL_GUID("F9E4006C-6E8C-56DF-811C-61F9990EBFB0", IReference); - REQUIRE_EQUAL_GUID("C261D8D0-71BA-5F38-A239-872342253A18", AsyncActionProgressHandler); - REQUIRE_EQUAL_GUID("9A0D211C-0374-5D23-9E15-EAA3570FAE63", AsyncActionWithProgressCompletedHandler); - REQUIRE_EQUAL_GUID("9D534225-231F-55E7-A6D0-6C938E2D9160", AsyncOperationCompletedHandler); - REQUIRE_EQUAL_GUID("264F1E0C-ABE4-590B-9D37-E1CC118ECC75", AsyncOperationProgressHandler); - REQUIRE_EQUAL_GUID("C2D078D8-AC47-55AB-83E8-123B2BE5BC5A", AsyncOperationWithProgressCompletedHandler); - REQUIRE_EQUAL_GUID("FA0B7D80-7EFA-52DF-9B69-0574CE57ADA4", EventHandler); - REQUIRE_EQUAL_GUID("EDB31843-B4CF-56EB-925A-D4D0CE97A08D", TypedEventHandler); - - // - // Generated Windows.Foundation.Collections GUIDs - // - - REQUIRE_EQUAL_GUID("96565EB9-A692-59C8-BCB5-647CDE4E6C4D", IIterable); - REQUIRE_EQUAL_GUID("3C9B1E27-8357-590B-8828-6E917F172390", IIterator); - REQUIRE_EQUAL_GUID("89336CD9-8B66-50A7-9759-EB88CCB2E1FE", IKeyValuePair); - REQUIRE_EQUAL_GUID("E1AA5138-12BD-51A1-8558-698DFD070ABE", IMapChangedEventArgs); - REQUIRE_EQUAL_GUID("B78F0653-FA89-59CF-BA95-726938AAE666", IMapView); - REQUIRE_EQUAL_GUID("9962CD50-09D5-5C46-B1E1-3C679C1C8FAE", IMap); - REQUIRE_EQUAL_GUID("75F99E2A-137E-537E-A5B1-0B5A6245FC02", IObservableMap); - REQUIRE_EQUAL_GUID("D24C289F-2341-5128-AAA1-292DD0DC1950", IObservableVector); - REQUIRE_EQUAL_GUID("5F07498B-8E14-556E-9D2E-2E98D5615DA9", IVectorView); - REQUIRE_EQUAL_GUID("0E3F106F-A266-50A1-8043-C90FCF3844F6", IVector); - REQUIRE_EQUAL_GUID("19046F0B-CF81-5DEC-BBB2-7CC250DA8B8B", MapChangedEventHandler); - REQUIRE_EQUAL_GUID("A1E9ACD7-E4DF-5A79-AEFA-DE07934AB0FB", VectorChangedEventHandler); - - // - // Generated primitive GUIDs - // - - REQUIRE_EQUAL_GUID("3C00FD60-2950-5939-A21A-2D12C5A01B8A", IReference); - REQUIRE_EQUAL_GUID("95500129-FBF6-5AFC-89DF-70642D741990", IReference); - REQUIRE_EQUAL_GUID("6EC9E41B-6709-5647-9918-A1270110FC4E", IReference); - REQUIRE_EQUAL_GUID("548CEFBD-BC8A-5FA0-8DF2-957440FC8BF4", IReference); - REQUIRE_EQUAL_GUID("4DDA9E24-E69F-5C6A-A0A6-93427365AF2A", IReference); - REQUIRE_EQUAL_GUID("e5198cc8-2873-55f5-b0a1-84ff9e4aad62", IReference); - REQUIRE_EQUAL_GUID("5AB7D2C3-6B62-5E71-A4B6-2D49C4F238FD", IReference); - REQUIRE_EQUAL_GUID("513ef3af-e784-5325-a91e-97c2b8111cf3", IReference); - REQUIRE_EQUAL_GUID("6755e376-53bb-568b-a11d-17239868309e", IReference); - REQUIRE_EQUAL_GUID("719CC2BA-3E76-5DEF-9F1A-38D85A145EA8", IReference); - REQUIRE_EQUAL_GUID("2F2D6C29-5473-5F3E-92E7-96572BB990E2", IReference); - REQUIRE_EQUAL_GUID("FB393EF3-BBAC-5BD5-9144-84F23576F415", IReference); - REQUIRE_EQUAL_GUID("7D50F649-632C-51F9-849A-EE49428933EA", IReference); - REQUIRE_EQUAL_GUID("6FF27A1E-4B6A-59B7-B2C3-D1F2EE474593", IReference); - REQUIRE_EQUAL_GUID("FD416DFB-2A07-52EB-AAE3-DFCE14116C05", IReference); - REQUIRE_EQUAL_GUID("A9B18291-CE2A-5DAE-8A23-B7F7388416DB", IReference); - REQUIRE_EQUAL_GUID("604D0C4C-91DE-5C2A-935F-362F13EAF800", IReference); - REQUIRE_EQUAL_GUID("5541D8A7-497C-5AA4-86FC-7713ADBF2A2C", IReference); - REQUIRE_EQUAL_GUID("84F14C22-A00A-5272-8D3D-82112E66DF00", IReference); - REQUIRE_EQUAL_GUID("80423F11-054F-5EAC-AFD3-63B6CE15E77B", IReference); - REQUIRE_EQUAL_GUID("61723086-8e53-5276-9f36-2a4bb93e2b75", IReference); -#if __has_include() - REQUIRE_EQUAL_GUID("48F6A69E-8465-57AE-9400-9764087F65AD", IReference); - REQUIRE_EQUAL_GUID("1EE770FF-C954-59CA-A754-6199A9BE282C", IReference); - REQUIRE_EQUAL_GUID("A5E843C9-ED20-5339-8F8D-9FE404CF3654", IReference); - REQUIRE_EQUAL_GUID("76358CFD-2CBD-525B-A49E-90EE18247B71", IReference); - REQUIRE_EQUAL_GUID("DACBFFDC-68EF-5FD0-B657-782D0AC9807E", IReference); - REQUIRE_EQUAL_GUID("B27004BB-C014-5DCE-9A21-799C5A3C1461", IReference); - REQUIRE_EQUAL_GUID("46D542A1-52F7-58E7-ACFC-9A6D364DA022", IReference); -#endif - - // Enums, structs, IInspectable, classes, and delegates - - REQUIRE_EQUAL_GUID("ECEBDE54-FAC0-5AEB-9BA9-9E1FE17E31D5", IReference); - REQUIRE_EQUAL_GUID("84F14C22-A00A-5272-8D3D-82112E66DF00", IReference); - REQUIRE_EQUAL_GUID("B32BDCA4-5E52-5B27-BC5D-D66A1A268C2A", IVector); - REQUIRE_EQUAL_GUID("0D82BD8D-FE62-5D67-A7B9-7886DD75BC4E", IVector); - REQUIRE_EQUAL_GUID("5DAFE591-86DC-59AA-BFDA-07F5D59FC708", IVector); - } -} diff --git a/test/test_win7/guid_key.cpp b/test/test_win7/guid_key.cpp deleted file mode 100644 index aaf560e15..000000000 --- a/test/test_win7/guid_key.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -TEST_CASE("guid_key") -{ - auto uri = guid_of(); - auto deferral = guid_of(); - - std::map ordered; - ordered[uri] = "Uri"; - ordered[deferral] = "Deferral"; - REQUIRE(ordered[uri] == "Uri"); - REQUIRE(ordered[deferral] == "Deferral"); - - std::unordered_map unordered; - unordered[uri] = "Uri"; - unordered[deferral] = "Deferral"; - REQUIRE(unordered[uri] == "Uri"); - REQUIRE(unordered[deferral] == "Deferral"); -} diff --git a/test/test_win7/iid_ppv_args.cpp b/test/test_win7/iid_ppv_args.cpp deleted file mode 100644 index 012e1856d..000000000 --- a/test/test_win7/iid_ppv_args.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "pch.h" -#include - -namespace -{ - struct Stringable : winrt::implements - { - winrt::hstring ToString() - { - return L"hello"; - } - }; - - HRESULT GetStringable(GUID const& id, void** object) noexcept - { - *object = nullptr; - - if (id != __uuidof(ABI::Windows::Foundation::IStringable)) - { - return E_NOINTERFACE; - } - - *object = winrt::detach_abi(winrt::make()); - return S_OK; - } -} - -TEST_CASE("iid_ppv_args") -{ - { - winrt::com_ptr ptr; - REQUIRE(S_OK == GetStringable(IID_PPV_ARGS(&ptr))); - REQUIRE(ptr.as().ToString() == L"hello"); - } - { - winrt::com_ptr ptr; - REQUIRE(E_NOINTERFACE == GetStringable(IID_PPV_ARGS(&ptr))); - } -} diff --git a/test/test_win7/in_params.cpp b/test/test_win7/in_params.cpp deleted file mode 100644 index dec896930..000000000 --- a/test/test_win7/in_params.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.h" - -using namespace winrt; -using namespace Windows::Foundation; -using namespace test_component; - -namespace -{ - struct Value : implements - { - Value(int32_t value) : - m_value(value) - { - } - - hstring ToString() - { - return hstring{ std::to_wstring(m_value) }; - } - - private: - - int32_t m_value{}; - }; -} - -TEST_CASE("in_params") -{ - Class object; - - REQUIRE(object.InInt32(123) == L"123"); - REQUIRE(object.InString(L"123") == L"123"); - REQUIRE(object.InObject(make(123)) == L"123"); - REQUIRE(object.InStringable(make(123)) == L"123"); - REQUIRE(object.InStruct({ L"1", L"2" }) == L"12"); - REQUIRE(object.InStructRef({ L"1", L"2" }) == L"12ref"); - REQUIRE(object.InEnum(Signed::First) == L"First"); - - REQUIRE(object.InInt32Array({ 1,2 }) == L"12"); - REQUIRE(object.InStringArray({ L"1", L"2" }) == L"12"); - REQUIRE(object.InObjectArray({ make(1), make(2) }) == L"12"); - REQUIRE(object.InStringableArray({ make(1), make(2) }) == L"12"); - REQUIRE(object.InStructArray({ {L"1",L"2"}, {L"3",L"4"} }) == L"1234"); - REQUIRE(object.InEnumArray({ Signed::First, Signed::Second }) == L"FirstSecond"); - - // Ensure 0-length arrays are passed as non-null pointers to the ABI, - // in order to keep RPC happy. - REQUIRE(object.InInt32Array({ }) == L""); - REQUIRE(object.InStringArray({ }) == L""); - REQUIRE(object.InObjectArray({ }) == L""); - REQUIRE(object.InStringableArray({ }) == L""); - REQUIRE(object.InStructArray({ }) == L""); - REQUIRE(object.InEnumArray({ }) == L""); - - // params::hstring optimizations - REQUIRE(object.InString(L"") == L""); - REQUIRE(object.InString({}) == L""); - wchar_t non_const_string[1] = { L'\0' }; - REQUIRE(object.InString(non_const_string) == L""); -} diff --git a/test/test_win7/inspectable_interop.cpp b/test/test_win7/inspectable_interop.cpp deleted file mode 100644 index 0be7a9157..000000000 --- a/test/test_win7/inspectable_interop.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include "winrt/Windows.Foundation.h" -#include "catch.hpp" - -using namespace winrt; - -namespace -{ - struct DECLSPEC_UUID("ed0dd761-c31e-4803-8cf9-22a2cb20ec47") IBadInterop : ::IInspectable - { - virtual int32_t __stdcall JustSayNo() noexcept = 0; - }; -} - -#ifdef __CRT_UUID_DECL -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -__CRT_UUID_DECL(IBadInterop, 0xed0dd761, 0xc31e, 0x4803, 0x8c, 0xf9, 0x22, 0xa2, 0xcb, 0x20, 0xec, 0x47) -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#endif - -namespace -{ - struct Sample : implements - { - Windows::Foundation::IInspectable ActivateInstance() - { - throw hresult_not_implemented(); - } - - hstring GetRuntimeClassName() const - { - return L"Sample"; - } - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverloaded-virtual" -#endif - Windows::Foundation::TrustLevel GetTrustLevel() const noexcept - { - return Windows::Foundation::TrustLevel::PartialTrust; - } -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - - int32_t __stdcall JustSayNo() noexcept final - { - return 123; - } - }; -} - -TEST_CASE("inspectable_interop") -{ - Windows::Foundation::IActivationFactory a = make(); - REQUIRE(a != nullptr); - - Windows::Foundation::IActivationFactory b = a.as(); - REQUIRE(b != nullptr); - - com_ptr c = a.as(); - REQUIRE(c != nullptr); - REQUIRE(c->JustSayNo() == 123); - - Windows::Foundation::IActivationFactory d = c.as(); - REQUIRE(a == d); - - Windows::Foundation::IInspectable f = c.as(); - REQUIRE(f != nullptr); - - Windows::Foundation::IInspectable e(c.detach(), take_ownership_from_abi); - - REQUIRE(winrt::get_class_name(e) == L"Sample"); - REQUIRE(winrt::get_trust_level(e) == Windows::Foundation::TrustLevel::PartialTrust); - - auto interfaces = winrt::get_interfaces(e); - REQUIRE(interfaces.size() == 1); - REQUIRE(interfaces[0] == guid_of()); -} diff --git a/test/test_win7/interop.cpp b/test/test_win7/interop.cpp deleted file mode 100644 index ec5476d15..000000000 --- a/test/test_win7/interop.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "pch.h" -#include - -struct DECLSPEC_UUID("5040a5f4-796a-42ff-9f06-be89137a518f") IBase : IUnknown -{ -}; - -struct DECLSPEC_UUID("529fed32-514f-4150-b1ba-15b47df700b7") IDerived : IBase -{ -}; - -struct DECLSPEC_UUID("b81fb2a2-eab4-488a-96a7-434873c2c20b") IMoreDerived : IDerived -{ -}; - -#ifdef __CRT_UUID_DECL -__CRT_UUID_DECL(IBase, 0x5040a5f4, 0x796a, 0x42ff, 0x9f, 0x06, 0xbe, 0x89, 0x13, 0x7a, 0x51, 0x8f) -__CRT_UUID_DECL(IDerived, 0x529fed32, 0x514f, 0x4150, 0xb1, 0xba, 0x15, 0xb4, 0x7d, 0xf7, 0x00, 0xb7) -__CRT_UUID_DECL(IMoreDerived, 0xb81fb2a2, 0xeab4, 0x488a, 0x96, 0xa7, 0x43, 0x48, 0x73, 0xc2, 0xc2, 0x0b) -#endif - -namespace winrt -{ - template<> bool is_guid_of(guid const& id) noexcept - { - return is_guid_of(id); - } - - template<> bool is_guid_of(guid const& id) noexcept - { - return is_guid_of(id); - } -} - -using namespace winrt; - -struct MyBase : implements -{ -}; - -struct MyDerived : implements -{ -}; - -struct MyMoreDerived : implements -{ -}; - -Windows::Foundation::IAsyncAction Async() -{ - co_return; -} - -TEST_CASE("interop") -{ - { - Windows::Foundation::IAsyncAction a = Async(); - com_ptr<::IInspectable> b = a.as<::IInspectable>(); - Windows::Foundation::IAsyncAction c = b.as(); - REQUIRE(a == c); - } - { - com_ptr a = make(); - REQUIRE(a); - REQUIRE(a.try_as() != nullptr); - REQUIRE(a.try_as() == nullptr); - REQUIRE(a.try_as() == nullptr); - REQUIRE(a.try_as<::IInspectable>() == nullptr); - } - { - com_ptr a = make(); - REQUIRE(a); - REQUIRE(a.try_as() != nullptr); - REQUIRE(a.try_as() != nullptr); - REQUIRE(a.try_as() == nullptr); - REQUIRE(a.try_as<::IInspectable>() == nullptr); - } - { - com_ptr a = make(); - REQUIRE(a); - REQUIRE(a.try_as() != nullptr); - REQUIRE(a.try_as() != nullptr); - REQUIRE(a.try_as() != nullptr); - REQUIRE(a.try_as<::IInspectable>() != nullptr); - } -} diff --git a/test/test_win7/invalid_events.cpp b/test/test_win7/invalid_events.cpp deleted file mode 100644 index a8f6a69bd..000000000 --- a/test/test_win7/invalid_events.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -// -// Checks that invalid tokens may be removed harmlessly. -// - -TEST_CASE("invalid_events") -{ - event> event; - int counter{}; - - auto a = event.add([&](auto && ...) - { - counter += 1; - }); - - auto b = event.add([&](auto && ...) - { - counter += 10; - }); - - REQUIRE(counter == 0); - event(0, 0); - REQUIRE(counter == 11); - - // Remove invalid token (with two valids) - event.remove(event_token {1}); - - counter = 0; - event(0, 0); - REQUIRE(counter == 11); - - // Remove valid token - event.remove(b); - - counter = 0; - event(0, 0); - REQUIRE(counter == 1); - - // Remove invalid token (with one valid) - event.remove(event_token {1}); - - counter = 0; - event(0, 0); - REQUIRE(counter == 1); - - // Remove remaining valid token - event.remove(a); - - counter = 0; - event(0, 0); - REQUIRE(counter == 0); - - // Remove invalid token (with no valids) - event.remove(event_token {1}); - - counter = 0; - event(0, 0); - REQUIRE(counter == 0); -} diff --git a/test/test_win7/main.cpp b/test/test_win7/main.cpp deleted file mode 100644 index 30687e00c..000000000 --- a/test/test_win7/main.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -#define CATCH_CONFIG_RUNNER - -// Force reportFatal to be available on mingw-w64 -#define CATCH_CONFIG_WINDOWS_SEH - -#include "catch.hpp" -#include "winrt/base.h" - -using namespace winrt; - -int main(int const argc, char** argv) -{ - init_apartment(); - std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); - return Catch::Session().run(argc, argv); -} - -CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) -{ - return to_string(e.message()); -} diff --git a/test/test_win7/module_lock_dll.cpp b/test/test_win7/module_lock_dll.cpp deleted file mode 100644 index 605142126..000000000 --- a/test/test_win7/module_lock_dll.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "catch.hpp" - -// The default behavior (no macro) provides the static winrt::get_module_lock implementation for components/DLLs. - -#include "winrt/Windows.Foundation.h" - -namespace -{ - struct Stringable : winrt::implements - { - winrt::hstring ToString() - { - return L"Stringable"; - } - }; -} - -TEST_CASE("module_lock_dll") -{ - uint32_t const count = winrt::get_module_lock(); - - ++winrt::get_module_lock(); - - REQUIRE(winrt::get_module_lock() == count + 1); - - --winrt::get_module_lock(); - - REQUIRE(winrt::get_module_lock() == count); - - { - auto stringable = winrt::make(); - REQUIRE(winrt::get_module_lock() == count + 1); - } - - REQUIRE(winrt::get_module_lock() == count); - - { - winrt::Windows::Foundation::EventHandler delegate = [](auto&&...) {}; - REQUIRE(winrt::get_module_lock() == count + 1); - } - - REQUIRE(winrt::get_module_lock() == count); - - { - winrt::delegate delegate = [] {}; - REQUIRE(winrt::get_module_lock() == count + 1); - } - - REQUIRE(winrt::get_module_lock() == count); -} diff --git a/test/test_win7/names.cpp b/test/test_win7/names.cpp deleted file mode 100644 index 7730fe82e..000000000 --- a/test/test_win7/names.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -void check_terminated(winrt::param::hstring const&) -{ -} - -TEST_CASE("names") -{ - REQUIRE(name_of() == L"{00000000-0000-0000-c000-000000000046}"sv); - STATIC_REQUIRE(name_of() == L"Object"sv); - - check_terminated(name_of()); - check_terminated(name_of()); - check_terminated(name_of>()); - check_terminated(name_of>()); -} diff --git a/test/test_win7/no_make_detection.cpp b/test/test_win7/no_make_detection.cpp deleted file mode 100644 index f098f3228..000000000 --- a/test/test_win7/no_make_detection.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.h" - -using namespace winrt; -using namespace test_component; - -TEST_CASE("no_make_detection") -{ - REQUIRE(test_component::Class::TestNoMakeDetection()); -} diff --git a/test/test_win7/noexcept.cpp b/test/test_win7/noexcept.cpp deleted file mode 100644 index 1df30689f..000000000 --- a/test/test_win7/noexcept.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.h" - -using namespace winrt; -using namespace test_component; - -TEST_CASE("noexcept") -{ - Class c; - - c.NoexceptVoid(); - int32_t a = c.NoexceptInt32(); - hstring b = c.NoexceptString(); - - REQUIRE(a == 123); - REQUIRE(b == L"123"); -} diff --git a/test/test_win7/numerics.cpp b/test/test_win7/numerics.cpp deleted file mode 100644 index 23b2dfb34..000000000 --- a/test/test_win7/numerics.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation::Numerics; - -TEST_CASE("numerics") -{ -#if __has_include() - // Basic smoke test exercising SIMD intrinsics used by numerics. - - auto one = float4::one(); - - REQUIRE(one * one == one); -#endif -} diff --git a/test/test_win7/out_params.cpp b/test/test_win7/out_params.cpp deleted file mode 100644 index 7aafb63ae..000000000 --- a/test/test_win7/out_params.cpp +++ /dev/null @@ -1,278 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.h" - -using namespace winrt; -using namespace Windows::Foundation; -using namespace test_component; - -namespace -{ - struct Stringable : implements - { - hstring ToString() - { - return L"Stringable"; - } - }; -} - -TEST_CASE("out_params") -{ - Class object; - - { - int value; - object.OutInt32(value); - REQUIRE(value == 123); - } - { - hstring value = L"replace"; - object.OutString(value); - REQUIRE(value == L"123"); - } - { - IInspectable value = make(); - object.OutObject(value); - REQUIRE(value.as().ToString() == L"123"); - } - { - IStringable value = make(); - object.OutStringable(value); - REQUIRE(value.ToString() == L"123"); - } - { - Struct value{ L"First", L"Second" }; - object.OutStruct(value); - REQUIRE(value.First == L"1"); - REQUIRE(value.Second == L"2"); - } - { - Signed value; - object.OutEnum(value); - REQUIRE(value == Signed::First); - } - - { - com_array value(10); - object.OutInt32Array(value); - REQUIRE(value.size() == 3); - REQUIRE(value[0] == 1); - REQUIRE(value[1] == 2); - REQUIRE(value[2] == 3); - } - { - com_array value(10); - object.OutStringArray(value); - REQUIRE(value.size() == 3); - REQUIRE(value[0] == L"1"); - REQUIRE(value[1] == L"2"); - REQUIRE(value[2] == L"3"); - } - { - com_array value(10); - object.OutObjectArray(value); - REQUIRE(value.size() == 3); - REQUIRE(value[0].as().ToString() == L"1"); - REQUIRE(value[1].as().ToString() == L"2"); - REQUIRE(value[2].as().ToString() == L"3"); - } - { - com_array value(10); - object.OutStringableArray(value); - REQUIRE(value.size() == 3); - REQUIRE(value[0].ToString() == L"1"); - REQUIRE(value[1].ToString() == L"2"); - REQUIRE(value[2].ToString() == L"3"); - } - { - com_array value(10); - object.OutStructArray(value); - REQUIRE(value.size() == 2); - REQUIRE(value[0].First == L"1"); - REQUIRE(value[0].Second == L"2"); - REQUIRE(value[1].First == L"10"); - REQUIRE(value[1].Second == L"20"); - } - { - com_array value(10); - object.OutEnumArray(value); - REQUIRE(value.size() == 2); - REQUIRE(value[0] == Signed::First); - REQUIRE(value[1] == Signed::Second); - } - - { - std::array value{ 0xCC, 0xCC, 0xCC, 0xCC }; - object.RefInt32Array(value); - REQUIRE(value[0] == 1); - REQUIRE(value[1] == 2); - REQUIRE(value[2] == 3); - REQUIRE(value[3] == 0xCC); - } - { - std::array value{ L"r1", L"r2", L"r3", L"r4" }; - object.RefStringArray(value); - REQUIRE(value[0] == L"1"); - REQUIRE(value[1] == L"2"); - REQUIRE(value[2] == L"3"); - REQUIRE(value[3] == L""); - } - { - std::array value{ make(), make(), make(), make() }; - object.RefObjectArray(value); - REQUIRE(value[0].as().ToString() == L"1"); - REQUIRE(value[1].as().ToString() == L"2"); - REQUIRE(value[2].as().ToString() == L"3"); - REQUIRE(value[3] == nullptr); - } - { - std::array value{ make(), make(), make(), make() }; - object.RefStringableArray(value); - REQUIRE(value[0].ToString() == L"1"); - REQUIRE(value[1].ToString() == L"2"); - REQUIRE(value[2].ToString() == L"3"); - REQUIRE(value[3] == nullptr); - } - { - std::array value{ {L"First", L"Second"} }; - object.RefStructArray(value); - REQUIRE(value[0].First == L"1"); - REQUIRE(value[0].Second == L"2"); - REQUIRE(value[1].First == L"3"); - REQUIRE(value[1].Second == L"4"); - REQUIRE(value[2].First == L""); - REQUIRE(value[2].Second == L""); - } - { - std::array value{}; - object.RefEnumArray(value); - REQUIRE(value.size() == 3); - REQUIRE(value[0] == Signed::First); - REQUIRE(value[1] == Signed::Second); - REQUIRE(value[2] == static_cast(0)); - } - // Ensure 0-length arrays are passed as non-null pointers to the ABI, - // in order to keep RPC happy. - { - REQUIRE_NOTHROW(object.RefInt32Array({})); - REQUIRE_NOTHROW(object.RefStringArray({})); - REQUIRE_NOTHROW(object.RefObjectArray({})); - REQUIRE_NOTHROW(object.RefStringableArray({})); - REQUIRE_NOTHROW(object.RefStructArray({})); - REQUIRE_NOTHROW(object.RefEnumArray({})); - } - - object.Fail(true); - - { - int value = 0xCC; - REQUIRE_THROWS_AS(object.OutInt32(value), hresult_invalid_argument); - REQUIRE(value == 0xCC); - } - { - hstring value = L"replace"; - REQUIRE_THROWS_AS(object.OutString(value), hresult_invalid_argument); - REQUIRE(value == L""); - } - { - IInspectable value = make(); - REQUIRE_THROWS_AS(object.OutObject(value), hresult_invalid_argument); - REQUIRE(value == nullptr); - } - { - IStringable value = make(); - REQUIRE_THROWS_AS(object.OutStringable(value), hresult_invalid_argument); - REQUIRE(value == nullptr); - } - { - Struct value{ L"First", L"Second" }; - REQUIRE_THROWS_AS(object.OutStruct(value), hresult_invalid_argument); - REQUIRE(value.First == L""); - REQUIRE(value.Second == L""); - } - { - Signed value = static_cast(0xCC); - REQUIRE_THROWS_AS(object.OutEnum(value), hresult_invalid_argument); - REQUIRE(static_cast(value) == 0xCC); - } - - { - com_array value(10); - REQUIRE_THROWS_AS(object.OutInt32Array(value), hresult_invalid_argument); - REQUIRE(value.size() == 0); - } - { - com_array value(10); - REQUIRE_THROWS_AS(object.OutStringArray(value), hresult_invalid_argument); - REQUIRE(value.size() == 0); - } - { - com_array value(10); - REQUIRE_THROWS_AS(object.OutObjectArray(value), hresult_invalid_argument); - REQUIRE(value.size() == 0); - } - { - com_array value(10); - REQUIRE_THROWS_AS(object.OutStringableArray(value), hresult_invalid_argument); - REQUIRE(value.size() == 0); - } - { - com_array value(10); - REQUIRE_THROWS_AS(object.OutStructArray(value), hresult_invalid_argument); - REQUIRE(value.size() == 0); - } - { - com_array value(10); - REQUIRE_THROWS_AS(object.OutEnumArray(value), hresult_invalid_argument); - REQUIRE(value.size() == 0); - } - - { - std::array value{ 0xCC, 0xCC, 0xCC, 0xCC }; - REQUIRE_THROWS_AS(object.RefInt32Array(value), hresult_invalid_argument); - REQUIRE(value[0] == 0xCC); - REQUIRE(value[1] == 0xCC); - REQUIRE(value[2] == 0xCC); - REQUIRE(value[3] == 0xCC); - } - { - std::array value{ L"r1", L"r2", L"r3", L"r4" }; - REQUIRE_THROWS_AS(object.RefStringArray(value), hresult_invalid_argument); - REQUIRE(value[0] == L""); - REQUIRE(value[1] == L""); - REQUIRE(value[2] == L""); - REQUIRE(value[3] == L""); - } - { - std::array value{ make(), make(), make(), make() }; - REQUIRE_THROWS_AS(object.RefObjectArray(value), hresult_invalid_argument); - REQUIRE(value[0] == nullptr); - REQUIRE(value[1] == nullptr); - REQUIRE(value[2] == nullptr); - REQUIRE(value[3] == nullptr); - } - { - std::array value{ make(), make(), make(), make() }; - REQUIRE_THROWS_AS(object.RefStringableArray(value), hresult_invalid_argument); - REQUIRE(value[0] == nullptr); - REQUIRE(value[1] == nullptr); - REQUIRE(value[2] == nullptr); - REQUIRE(value[3] == nullptr); - } - { - std::array value{ {L"First", L"Second"} }; - REQUIRE_THROWS_AS(object.RefStructArray(value), hresult_invalid_argument); - REQUIRE(value[0].First == L""); - REQUIRE(value[0].Second == L""); - REQUIRE(value[1].First == L""); - REQUIRE(value[1].Second == L""); - REQUIRE(value[2].First == L""); - REQUIRE(value[2].Second == L""); - } - { - std::array value{ static_cast(0xCC), static_cast(0xCC) }; - REQUIRE_THROWS_AS(object.RefEnumArray(value), hresult_invalid_argument); - REQUIRE(value[0] == static_cast(0xCC)); - REQUIRE(value[1] == static_cast(0xCC)); - } -} diff --git a/test/test_win7/parent_includes.cpp b/test/test_win7/parent_includes.cpp deleted file mode 100644 index f7dc0d0c8..000000000 --- a/test/test_win7/parent_includes.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.Parent.One.Two.Three.h" - -using namespace winrt::test_component; - -TEST_CASE("parent_includes") -{ - // Including "...Three.h" should include all (available) ancestors, skipping - // any that are empty. In this case, "Three" and "Parent" are not empty while - // the intermediate namespaces are empty. - - Parent::One::Two::Three::ThreeStruct three; - three.Value = 0; - - Parent::ParentStruct parent; - parent.Value = 0; -} diff --git a/test/test_win7/pch.cpp b/test/test_win7/pch.cpp deleted file mode 100644 index 1d9f38c57..000000000 --- a/test/test_win7/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.h" diff --git a/test/test_win7/pch.h b/test/test_win7/pch.h deleted file mode 100644 index 92e8caa96..000000000 --- a/test/test_win7/pch.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include "mingw_com_support.h" - -#define WINRT_LEAN_AND_MEAN -#include -#include "winrt/Windows.Foundation.Collections.h" -#include "winrt/Windows.Foundation.Numerics.h" -#include "catch.hpp" - -using namespace std::literals; - -// Extracts return and progress types from IAsyncXxx. - -template -struct async_traits; - -template<> -struct async_traits -{ - using progress_type = void; -}; - -template -struct async_traits> -{ - using progress_type = P; -}; - -template -struct async_traits> -{ - using progress_type = void; -}; - -template -struct async_traits> -{ - using progress_type = P; -}; - -template -using async_return_type = decltype(std::declval().GetResults()); -template -using async_progress_type = typename async_traits>::progress_type; -template -inline constexpr bool has_async_progress = !std::is_same_v>::progress_type>; diff --git a/test/test_win7/return_params.cpp b/test/test_win7/return_params.cpp deleted file mode 100644 index 3ff5026d1..000000000 --- a/test/test_win7/return_params.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.h" - -using namespace winrt; -using namespace Windows::Foundation; -using namespace test_component; - -namespace -{ - struct Stringable : implements - { - hstring ToString() - { - return L"Stringable"; - } - }; -} - -TEST_CASE("return_params") -{ - Class object; - - { - int value = object.ReturnInt32(); - REQUIRE(value == 123); - } - { - hstring value = object.ReturnString(); - REQUIRE(value == L"123"); - } - { - IInspectable value = object.ReturnObject(); - REQUIRE(value.as().ToString() == L"123"); - } - { - IStringable value = object.ReturnStringable(); - REQUIRE(value.ToString() == L"123"); - } - { - Struct value = object.ReturnStruct(); - REQUIRE(value.First == L"1"); - REQUIRE(value.Second == L"2"); - } - { - com_array value = object.ReturnInt32Array(); - REQUIRE(value.size() == 3); - REQUIRE(value[0] == 1); - REQUIRE(value[1] == 2); - REQUIRE(value[2] == 3); - } - { - com_array value = object.ReturnStringArray(); - REQUIRE(value.size() == 3); - REQUIRE(value[0] == L"1"); - REQUIRE(value[1] == L"2"); - REQUIRE(value[2] == L"3"); - } - { - com_array value = object.ReturnObjectArray(); - REQUIRE(value.size() == 3); - REQUIRE(value[0].as().ToString() == L"1"); - REQUIRE(value[1].as().ToString() == L"2"); - REQUIRE(value[2].as().ToString() == L"3"); - } - { - com_array value = object.ReturnStringableArray(); - REQUIRE(value.size() == 3); - REQUIRE(value[0].ToString() == L"1"); - REQUIRE(value[1].ToString() == L"2"); - REQUIRE(value[2].ToString() == L"3"); - } - { - com_array value = object.ReturnStructArray(); - REQUIRE(value.size() == 2); - REQUIRE(value[0].First == L"1"); - REQUIRE(value[0].Second == L"2"); - REQUIRE(value[1].First == L"10"); - REQUIRE(value[1].Second == L"20"); - } -} diff --git a/test/test_win7/structs.cpp b/test/test_win7/structs.cpp deleted file mode 100644 index 3926c06ed..000000000 --- a/test/test_win7/structs.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.Structs.Nested.h" -#include "winrt/test_component_no_pch.Peer2.h" - -using namespace winrt; - -TEST_CASE("structs") -{ - test_component::Structs::Nested::Outer outer{}; - outer.Depends.InnerValue = 1; - outer.OuterValue = 2; - - test_component_no_pch::Peer2::B depends{}; - depends.First.Value = 1; - - test_component::Structs::All all{}; - all.H = {}; -} diff --git a/test/test_win7/test_win7.vcxproj b/test/test_win7/test_win7.vcxproj deleted file mode 100644 index 831c0c1d1..000000000 --- a/test/test_win7/test_win7.vcxproj +++ /dev/null @@ -1,363 +0,0 @@ - - - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - {2EF696B9-7F4A-410F-AE5C-5301565C0F08} - unittests - test_win7 - - - - Application - true - - - Application - true - - - Application - true - - - Application - false - true - - - Application - false - true - - - Application - false - true - - - Application - true - - - Application - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - Disabled - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - Disabled - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - Disabled - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - Disabled - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..;..\..\cppwinrt - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NotUsing - - - NotUsing - - - - - - - - - - - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - NotUsing - - - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - Create - - - - - - - - - - - - \ No newline at end of file diff --git a/test/test_win7/thread_pool.cpp b/test/test_win7/thread_pool.cpp deleted file mode 100644 index ac75dac18..000000000 --- a/test/test_win7/thread_pool.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "pch.h" - -using namespace winrt; -using namespace Windows::Foundation; - -namespace -{ - struct AsyncQueue - { - thread_pool m_pool; - - AsyncQueue(uint32_t const high, uint32_t const low) - { - m_pool.thread_limits(high, low); - } - - IAsyncAction Async(delegate<> callback) - { - co_await m_pool; - callback(); - } - }; - - uint32_t test(uint32_t const iterations, uint32_t const high, uint32_t const low) - { - AsyncQueue queue(high, low); - std::vector results; - uint32_t counter{}; - - for (uint32_t i = 0; i < iterations; ++i) - { - results.push_back(queue.Async([&] - { - auto value = counter + 1; - Sleep(10); // Induce thread pool to use more threads if available, also force race condition - counter = value; - })); - } - - for (auto&& async : results) - { - async.get(); - } - - return counter; - } -} - -TEST_CASE("thread_pool") -{ - uint32_t const test_iterations = 100; - - uint32_t const stable_counter = test(test_iterations, 1, 1); - uint32_t const unstable_counter = test(test_iterations, 10, 10); - - // This is determinstic since the queue is single-threaded. - REQUIRE(stable_counter == test_iterations); - - // This is unlikely to fail since the pool is multi-threaded. - REQUIRE(unstable_counter < test_iterations); -} diff --git a/test/test_win7/uniform_in_params.cpp b/test/test_win7/uniform_in_params.cpp deleted file mode 100644 index 50eb3fde3..000000000 --- a/test/test_win7/uniform_in_params.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.h" - -using namespace winrt; -using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; -using namespace test_component; - -TEST_CASE("uniform_in_params") -{ - Class{ single_threaded_vector({ L"test" }).as>(), 0 }; - Class{ single_threaded_map(std::map{ {L"test", L"test" } }).as>>(), 0, 0 }; - Class{ single_threaded_map(std::map{ {L"test", L"test" } }), 0, 0, 0 }; - Class{ single_threaded_map(std::map{ {L"test", L"test" } }).GetView(), 0, 0, 0, 0 }; - Class{ single_threaded_vector({ L"test" }), 0, 0, 0, 0, 0 }; - Class{ single_threaded_vector({ L"test" }).GetView(), 0, 0, 0, 0, 0, 0 }; - - Class c; - REQUIRE(L"test" == c.InIterable({L"test"})); - REQUIRE(L"test" == c.InIterablePair(single_threaded_map(std::map{ {L"test", L"test" } }))); - REQUIRE(L"test" == c.InAsyncIterable({ L"test" }).get()); - REQUIRE(L"test" == c.InAsyncIterablePair(single_threaded_map(std::map{ {L"test", L"test" } })).get()); - REQUIRE(L"test" == c.InMap(single_threaded_map(std::map{ {L"test", L"test" } }))); - REQUIRE(L"test" == c.InMapView(single_threaded_map(std::map{ {L"test", L"test" } }).GetView())); - REQUIRE(L"test" == c.InAsyncMapView(single_threaded_map(std::map{ {L"test", L"test" } }).GetView()).get()); - REQUIRE(L"test" == c.InVector({ L"test" })); - REQUIRE(L"test" == c.InVectorView({ L"test" })); - REQUIRE(L"test" == c.InAsyncVectorView({ L"test" }).get()); -} diff --git a/test/test_win7/velocity.cpp b/test/test_win7/velocity.cpp deleted file mode 100644 index 11b11c1d7..000000000 --- a/test/test_win7/velocity.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "pch.h" -#include "winrt/test_component.Velocity.h" - -using namespace winrt; -using namespace test_component::Velocity; - -TEST_CASE("velocity") -{ - // This interface is always disabled but shows up in the type system - // if it is present in the winmd. - IInterface1 a; - REQUIRE(a == nullptr); - - // This interface is always enabled and is naturally available in - // the projection. - IInterface2 b; - REQUIRE(b == nullptr); - - // Class1 is always disabled and thus will not activate. - REQUIRE_THROWS_AS(Class1(), hresult_class_not_registered); - - // Class2 is always enabled so should activate just fine. - Class2 c; - c.Class2_Method(); - - // Class3 is always disabled and thus will not activate. - REQUIRE_THROWS_AS(Class3(), hresult_class_not_registered); - - // Class4 is not feature-controlled but uses feature interfaces. - Class4 d; - d.Class4_Method(); - - // The single argument constructor is always disabled. - REQUIRE_THROWS_AS(Class4(1), hresult_class_not_registered); - - // The Class4_Static1 static is always disabled. - REQUIRE_THROWS_AS(Class4::Class4_Static1(), hresult_class_not_registered); - - // The two argument constructor is always enabled. - Class4 e(1, 2); - - // The Class4_Static2 static is always enabled. - Class4::Class4_Static2(); -} diff --git a/test/test_win7/when.cpp b/test/test_win7/when.cpp deleted file mode 100644 index a3b284169..000000000 --- a/test/test_win7/when.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "pch.h" -#include - -using namespace concurrency; -using namespace winrt; -using namespace Windows::Foundation; - -task ppl(bool& done) -{ - co_await resume_background(); - done = true; -} - -IAsyncAction async(bool& done) -{ - co_await resume_background(); - done = true; -} - -IAsyncOperation when_signaled(int value, handle const& event) -{ - co_await resume_on_signal(event.get()); - co_return value; -} - -IAsyncAction done() -{ - co_return; -} - -TEST_CASE("when") -{ - { - bool ppl_done = false; - bool async_done = false; - - // Ensures that different async types can be aggregated. - when_all(ppl(ppl_done), async(async_done)).get(); - - REQUIRE(ppl_done); - REQUIRE(async_done); - } - { - // Works with IAsyncAction (with no return value). - IAsyncAction result = when_any(done(), done()); - result.get(); - } - { - handle first_event{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; - handle second_event{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; - - IAsyncOperation first = when_signaled(1, first_event); - IAsyncOperation second = when_signaled(2, second_event); - - IAsyncOperation result = when_any(first, second); - - // Make sure we're still waiting. - Sleep(100); - REQUIRE(result.Status() == AsyncStatus::Started); - REQUIRE(first.Status() == AsyncStatus::Started); - REQUIRE(second.Status() == AsyncStatus::Started); - - // Allow only one of the async objects to complete. - SetEvent(second_event.get()); - - // This should now complete. - REQUIRE(2 == result.get()); - - REQUIRE(first.Status() == AsyncStatus::Started); - REQUIRE(second.Status() == AsyncStatus::Completed); - - SetEvent(first_event.get()); - } -} From 691f6f8c9d6cbdde5ba99363a26f0f8a8486dd13 Mon Sep 17 00:00:00 2001 From: Jon Wiswall Date: Mon, 28 Aug 2023 10:24:04 -0700 Subject: [PATCH 202/305] Support for std::span for winrt::array_view and winrt::com_array (#1343) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Implicit conversion between std::span and winrt::array_view * Add testing and additional ctad for spans * PR FB - yes, yes it does! * PR FB --------- Co-authored-by: Jaiganésh Kumaran Co-authored-by: Jon Wiswall Co-authored-by: Kenny Kerr --- strings/base_array.h | 33 +++++ strings/base_includes.h | 4 + test/test_cpp20/array_span.cpp | 189 +++++++++++++++++++++++++++++ test/test_cpp20/pch.h | 1 + test/test_cpp20/test_cpp20.vcxproj | 1 + 5 files changed, 228 insertions(+) create mode 100644 test/test_cpp20/array_span.cpp diff --git a/strings/base_array.h b/strings/base_array.h index 9f20cf34e..a4f570614 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -31,6 +31,20 @@ WINRT_EXPORT namespace winrt array_view(value.begin(), static_cast(value.size())) {} +#ifdef __cpp_lib_span + template + array_view(std::span span) noexcept : + array_view(span.data(), static_cast(span.size())) + { + WINRT_ASSERT(span.size() <= UINT_MAX); + } + + operator std::span() const noexcept + { + return { m_data, m_size }; + } +#endif + template array_view(C(&value)[N]) noexcept : array_view(value, N) @@ -223,6 +237,11 @@ WINRT_EXPORT namespace winrt template array_view(std::array& value) -> array_view; template array_view(std::array const& value) -> array_view; +#ifdef __cpp_lib_span + template array_view(std::span& value) -> array_view; + template array_view(std::span const& value) -> array_view; +#endif + template struct com_array : array_view { @@ -274,6 +293,15 @@ WINRT_EXPORT namespace winrt com_array(value.begin(), value.end()) {} +#ifdef __cpp_lib_span + template + explicit com_array(std::span span) noexcept : + com_array(span.data(), span.data() + span.size()) + { + WINRT_ASSERT(span.size() <= UINT_MAX); + } +#endif + template explicit com_array(U const(&value)[N]) : com_array(value, value + N) @@ -375,6 +403,11 @@ WINRT_EXPORT namespace winrt template com_array(C const(&)[N]) -> com_array>; template com_array(std::initializer_list) -> com_array>; +#ifdef __cpp_lib_span + template com_array(std::span const& value) -> com_array>; +#endif + + namespace impl { template diff --git a/strings/base_includes.h b/strings/base_includes.h index 54edca841..ee22bc0aa 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -34,6 +34,10 @@ #include #endif +#ifdef __cpp_lib_span +#include +#endif + #ifdef __cpp_lib_format #include #endif diff --git a/test/test_cpp20/array_span.cpp b/test/test_cpp20/array_span.cpp new file mode 100644 index 000000000..dff5a2ec5 --- /dev/null +++ b/test/test_cpp20/array_span.cpp @@ -0,0 +1,189 @@ +#include "pch.h" +#include "catch.hpp" +#include + +using namespace winrt; +using namespace Windows::Foundation; +using namespace Windows::Storage::Streams; +using namespace Windows::Data::Json; + +// +// This is a helper to create a data reader for use in testing arrays. +// +static IAsyncOperation CreateDataReader(std::initializer_list values) +{ + InMemoryRandomAccessStream stream; + DataWriter writer(stream); + writer.WriteByte(1); + writer.WriteByte(2); + writer.WriteByte(3); + co_await writer.StoreAsync(); + + stream.Seek(0); + DataReader reader(stream); + co_await reader.LoadAsync(3); + co_return reader; +} + +// +// This test illustrates an array_view (non-const) bound to a std::span on a std::array +// +TEST_CASE("array,DataReader,std::span") +{ + auto reader = CreateDataReader({ 1, 2, 3 }).get(); + + std::array a{}; + std::span sp(a); + reader.ReadBytes(sp); // FillArray pattern + + REQUIRE(a.size() == 3); + REQUIRE(a[0] == 1); + REQUIRE(a[1] == 2); + REQUIRE(a[2] == 3); +} + +// +// This test illustrates passing a std::array to a method that takes array_view +// +TEST_CASE("array,DataReader,std::span,direct") +{ + auto reader = CreateDataReader({ 1, 2, 3 }).get(); + + std::array a{}; + reader.ReadBytes(a); // FillArray pattern + + REQUIRE(a.size() == 3); + REQUIRE(a[0] == 1); + REQUIRE(a[1] == 2); + REQUIRE(a[2] == 3); +} + + +TEST_CASE("array_view,span") +{ + { + int v[] = { 1, 2, 3 }; + std::span s(v); + array_view a = s; + REQUIRE(a.data() == v); + REQUIRE(a.size() == 3); + } + + { + int v[] = { 1, 2, 3 }; + std::span s(v); + array_view a = s; + REQUIRE(a.data() == v); + REQUIRE(a.size() == 3); + } + + { + int const v[] = { 1, 2, 3 }; + std::span s(v); + array_view a = s; + REQUIRE(a.data() == v); + REQUIRE(a.size() == 3); + } +} + +// +// Tests com_array support for span construction. +// +TEST_CASE("com_array,span") +{ + { + int v[] = { 1, 2, 3 }; + std::span s(v); + com_array a(s); + REQUIRE(a.size() == 3); + REQUIRE(a[0] == 1); + REQUIRE(a[1] == 2); + REQUIRE(a[2] == 3); + } +} + +// +// Tests array_view support for conversion to span +// +TEST_CASE("array_view,span,as") +{ + { + int v[] = { 1, 2, 3 }; + array_view a = v; + std::span s(a); + REQUIRE(s.data() == v); + REQUIRE(s.size() == 3); + } + + { + int v[] = { 1, 2, 3 }; + array_view a = v; + std::span s(a); + REQUIRE(s.data() == v); + REQUIRE(s.size() == 3); + } + + { + int const v[] = { 1, 2, 3 }; + array_view a = v; + std::span s(a); + REQUIRE(s.data() == v); + REQUIRE(s.size() == 3); + } +} + +// +// Tests com_array support for conversion to span +// +TEST_CASE("com_array,span,as") +{ + { + int v[] = { 1, 2, 3 }; + com_array a(v); + std::span s(a); + REQUIRE(s.size() == 3); + REQUIRE(s[0] == 1); + REQUIRE(s[1] == 2); + REQUIRE(s[2] == 3); + } +} + +// Verify that class template argument deduction works for array_view. +TEST_CASE("array_view,span,ctad") +{ +#define REQUIRE_DEDUCED_AS(T, ...) \ + static_assert(std::is_same_v, decltype(array_view(__VA_ARGS__))>) + + uint8_t a[] = {1, 2, 3}; + std::span sp{ a }; + + REQUIRE_DEDUCED_AS(uint8_t, sp); + + std::span csp{ a }; + REQUIRE_DEDUCED_AS(uint8_t const, csp); + + std::span const cs{ a }; + REQUIRE_DEDUCED_AS(uint8_t const, cs); + +#undef REQUIRE_DEDUCED_AS +} + +// Verify that class template argument deduction works for com_array. +TEST_CASE("com_array,span,ctad") +{ +#define REQUIRE_DEDUCED_AS(T, ...) \ + static_assert(std::is_same_v, decltype(com_array(__VA_ARGS__))>) + + uint8_t a[] = { 1, 2, 3 }; + + std::span sp{ a }; + REQUIRE_DEDUCED_AS(uint8_t, sp); + + std::span csp{ a }; + REQUIRE_DEDUCED_AS(uint8_t, csp); + + std::span const cs{ a }; + REQUIRE_DEDUCED_AS(uint8_t, cs); + +#undef REQUIRE_DEDUCED_AS +} diff --git a/test/test_cpp20/pch.h b/test/test_cpp20/pch.h index 6565bea1b..c1a8f5ff3 100644 --- a/test/test_cpp20/pch.h +++ b/test/test_cpp20/pch.h @@ -8,6 +8,7 @@ #include "winrt/Windows.Foundation.h" #include "winrt/Windows.Foundation.Collections.h" #include "winrt/Windows.Foundation.Numerics.h" +#include "winrt/Windows.Storage.Streams.h" #include #include "catch.hpp" diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 1717d6bf8..72d203a37 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -280,6 +280,7 @@ + From 23c4ced66ac1672a2326eec3e6b1c24f42353c3c Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 2 Sep 2023 12:14:52 -0500 Subject: [PATCH 203/305] Improve GCC compatibility (#1352) --- strings/base_implements.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index 5e8e6a29d..d0bb09012 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -801,7 +801,7 @@ namespace winrt::impl struct WINRT_IMPL_EMPTY_BASES root_implements_composable_inner { protected: - static constexpr inspectable_abi* outer() noexcept { return nullptr; } + static inspectable_abi* outer() noexcept { return nullptr; } template friend class produce_dispatch_to_overridable_base; From fac72c82b09ea1501a2c2eb6c00fd8cd89363392 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Tue, 12 Sep 2023 11:25:16 -0700 Subject: [PATCH 204/305] Add `resume_agile` to allow coroutine to resume in any apartment (#1356) --- strings/base_coroutine_foundation.h | 48 ++++++++++------ strings/base_coroutine_threadpool.h | 17 ++---- strings/base_meta.h | 19 +++++++ test/test/await_adapter.cpp | 85 ++++++++++++++++++++--------- 4 files changed, 112 insertions(+), 57 deletions(-) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 4c467f921..ba61cd49a 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -99,44 +99,49 @@ namespace winrt::impl return async.GetResults(); } - template - struct disconnect_aware_handler + struct ignore_apartment_context {}; + + template + struct disconnect_aware_handler : private std::conditional_t { disconnect_aware_handler(Awaiter* awaiter, coroutine_handle<> handle) noexcept : m_awaiter(awaiter), m_handle(handle) { } - disconnect_aware_handler(disconnect_aware_handler&& other) noexcept - : m_context(std::move(other.m_context)) - , m_awaiter(std::exchange(other.m_awaiter, {})) - , m_handle(std::exchange(other.m_handle, {})) { } + disconnect_aware_handler(disconnect_aware_handler&& other) = default; ~disconnect_aware_handler() { - if (m_handle) Complete(); + if (m_handle.value) Complete(); } template void operator()(Async&&, Windows::Foundation::AsyncStatus status) { - m_awaiter->status = status; + m_awaiter.value->status = status; Complete(); } private: - resume_apartment_context m_context; - Awaiter* m_awaiter; - coroutine_handle<> m_handle; + movable_primitive m_awaiter; + movable_primitive, nullptr> m_handle; void Complete() { - if (m_awaiter->suspending.exchange(false, std::memory_order_release)) + if (m_awaiter.value->suspending.exchange(false, std::memory_order_release)) { - m_handle = nullptr; // resumption deferred to await_suspend + m_handle.value = nullptr; // resumption deferred to await_suspend } else { - auto handle = std::exchange(m_handle, {}); - if (!resume_apartment(m_context, handle, &m_awaiter->failure)) + auto handle = m_handle.detach(); + if constexpr (preserve_context) + { + if (!resume_apartment(*this, handle, &m_awaiter.value->failure)) + { + handle.resume(); + } + } + else { handle.resume(); } @@ -145,7 +150,7 @@ namespace winrt::impl }; #ifdef WINRT_IMPL_COROUTINES - template + template struct await_adapter : cancellable_awaiter> { await_adapter(Async const& async) : async(async) { } @@ -185,7 +190,7 @@ namespace winrt::impl private: bool register_completed_callback(coroutine_handle<> handle) { - async.Completed(disconnect_aware_handler(this, handle)); + async.Completed(disconnect_aware_handler(this, handle)); return suspending.exchange(false, std::memory_order_acquire); } @@ -249,6 +254,15 @@ namespace winrt::impl } #ifdef WINRT_IMPL_COROUTINES +WINRT_EXPORT namespace winrt +{ + template>> + inline impl::await_adapter resume_agile(Async const& async) + { + return { async }; + }; +} + WINRT_EXPORT namespace winrt::Windows::Foundation { inline impl::await_adapter operator co_await(IAsyncAction const& async) diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index e3a283e33..0faaa1acd 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -52,23 +52,14 @@ namespace winrt::impl { resume_apartment_context() = default; resume_apartment_context(std::nullptr_t) : m_context(nullptr), m_context_type(-1) {} - resume_apartment_context(resume_apartment_context const&) = default; - resume_apartment_context(resume_apartment_context&& other) noexcept : - m_context(std::move(other.m_context)), m_context_type(std::exchange(other.m_context_type, -1)) {} - resume_apartment_context& operator=(resume_apartment_context const&) = default; - resume_apartment_context& operator=(resume_apartment_context&& other) noexcept - { - m_context = std::move(other.m_context); - m_context_type = std::exchange(other.m_context_type, -1); - return *this; - } + bool valid() const noexcept { - return m_context_type >= 0; + return m_context_type.value >= 0; } com_ptr m_context = try_capture(WINRT_IMPL_CoGetObjectContext); - int32_t m_context_type = get_apartment_type().first; + movable_primitive m_context_type = get_apartment_type().first; }; inline int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept @@ -124,7 +115,7 @@ namespace winrt::impl { return false; } - else if (context.m_context_type == 1 /* APTTYPE_MTA */) + else if (context.m_context_type.value == 1 /* APTTYPE_MTA */) { resume_background(handle); return true; diff --git a/strings/base_meta.h b/strings/base_meta.h index f474fced4..2c1796e9c 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -193,6 +193,25 @@ namespace winrt::impl } } + template + struct movable_primitive + { + T value = empty_value; + movable_primitive() = default; + movable_primitive(T const& init) : value(init) {} + movable_primitive(movable_primitive const&) = default; + movable_primitive(movable_primitive&& other) : + value(other.detach()) {} + movable_primitive& operator=(movable_primitive const&) = default; + movable_primitive& operator=(movable_primitive&& other) + { + value = other.detach(); + return *this; + } + + T detach() { return std::exchange(value, empty_value); } + }; + template struct arg { diff --git a/test/test/await_adapter.cpp b/test/test/await_adapter.cpp index 809567695..701bc6b15 100644 --- a/test/test/await_adapter.cpp +++ b/test/test/await_adapter.cpp @@ -18,13 +18,9 @@ namespace static handle signal{ CreateEventW(nullptr, false, false, nullptr) }; - IAsyncAction OtherForegroundAsync() + IAsyncAction OtherForegroundAsync(DispatcherQueue dispatcher) { - // Simple coroutine that completes on a unique STA thread. - - auto controller = DispatcherQueueController::CreateOnDedicatedThread(); - auto dispatcher = controller.DispatcherQueue(); - + // Simple coroutine that completes on the specified STA thread. co_await resume_foreground(dispatcher); } @@ -35,37 +31,37 @@ namespace co_await resume_background(); } - IAsyncAction ForegroundAsync(DispatcherQueue dispatcher) + // Coroutine that completes on dispatcher1, while potentially blocking dispatcher2. + IAsyncAction ForegroundAsync(DispatcherQueue dispatcher1, DispatcherQueue dispatcher2) { REQUIRE(!is_sta()); - co_await resume_foreground(dispatcher); + co_await resume_foreground(dispatcher1); REQUIRE(is_sta()); // This exercises one STA thread waiting on another thus one context callback // completing on another. uint32_t id = GetCurrentThreadId(); - co_await OtherForegroundAsync(); + co_await OtherForegroundAsync(dispatcher2); REQUIRE(id == GetCurrentThreadId()); - // This just avoids the ForegroundAsync coroutine completing before - // BackgroundAsync waits on the result, forcing the Completed handler - // to be called on the foreground thread. This just makes the test - // success/failure more predictable. + // This Sleep() makes it more likely that the caller will actually suspend in await_suspend, + // so that the Completed handler triggers a resumption from the dispatcher1 thread. Sleep(100); } - fire_and_forget SignalFromForeground(DispatcherQueue dispatcher) + fire_and_forget SignalFromForeground(DispatcherQueue dispatcher1) { REQUIRE(!is_sta()); - co_await resume_foreground(dispatcher); + co_await resume_foreground(dispatcher1); REQUIRE(is_sta()); - // Previously, this signal was never raised because the foreground thread - // was always blocked waiting for ContextCallback to return. + // Previously, we never got here because of a deadlock: + // The dispatcher1 thread was blocked waiting for ContextCallback to return, + // but the ContextCallback is waiting for this event to get signaled. REQUIRE(SetEvent(signal.get())); } - IAsyncAction BackgroundAsync(DispatcherQueue dispatcher) + IAsyncAction BackgroundAsync(DispatcherQueue dispatcher1, DispatcherQueue dispatcher2) { // Switch to a background (MTA) thread. co_await resume_background(); @@ -76,19 +72,19 @@ namespace co_await OtherBackgroundAsync(); REQUIRE(!is_sta()); - // Wait for a coroutine that completes on a foreground (STA) thread. - co_await ForegroundAsync(dispatcher); + // Wait for a coroutine that completes on a the dispatcher1 thread (STA). + co_await ForegroundAsync(dispatcher1, dispatcher2); // Resumption should automatically switch to a background (MTA) thread - // without blocking the Completed handler (which would in turn block the foreground thread). + // without blocking the Completed handler (which would in turn block the dispatcher1 thread). REQUIRE(!is_sta()); - // Attempt to signal from the foreground thread under the assumption - // that the foreground thread is not blocked. - SignalFromForeground(dispatcher); + // Attempt to signal from the dispatcher1 thread under the assumption + // that the dispatcher1 thread is not blocked. + SignalFromForeground(dispatcher1); - // Block the background (MTA) thread indefinitely until the signal is raied. - // Previously this would deadlock. + // Block the background (MTA) thread indefinitely until the signal is raised. + // Previously this would hang because the signal never got raised. REQUIRE(WAIT_OBJECT_0 == WaitForSingleObject(signal.get(), INFINITE)); } } @@ -99,9 +95,44 @@ TEST_CASE("await_adapter", "[.clang-crash]") #else TEST_CASE("await_adapter") #endif +{ + auto controller1 = DispatcherQueueController::CreateOnDedicatedThread(); + auto controller2 = DispatcherQueueController::CreateOnDedicatedThread(); + + BackgroundAsync(controller1.DispatcherQueue(), controller2.DispatcherQueue()).get(); + controller1.ShutdownQueueAsync().get(); + controller2.ShutdownQueueAsync().get(); +} + +namespace +{ + IAsyncAction OtherBackgroundDelayAsync() + { + // Simple coroutine that completes on some MTA thread after a brief delay + // to ensure that the caller has suspended. + + co_await resume_after(100ms); + } + + IAsyncAction AgileAsync(DispatcherQueue dispatcher) + { + // Switch to the STA. + co_await resume_foreground(dispatcher); + REQUIRE(is_sta()); + + // Ask for agile resumption of a coroutine that finishes on a background thread. + // Add a 100ms delay to ensure we suspend. + co_await resume_agile(OtherBackgroundDelayAsync()); + // We should be on the background thread now. + REQUIRE(!is_sta()); + } +} + +TEST_CASE("await_adapter_agile") { auto controller = DispatcherQueueController::CreateOnDedicatedThread(); auto dispatcher = controller.DispatcherQueue(); - BackgroundAsync(dispatcher).get(); + AgileAsync(dispatcher).get(); + controller.ShutdownQueueAsync().get(); } From bf4459b25aeeb7093e8262fb3b29ca70b0ab2e60 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Thu, 14 Sep 2023 16:19:23 -0700 Subject: [PATCH 205/305] Allow resume_agile to be stored in a variable (#1358) `resume_agile` exposes the ability to save the `await_adapter` in a variable. This was not possible without `resume_agile` because the `await_adapter` had previously been available only via `operator co_await`, which means that it is created only in response to an immediate attempt to `co_await` it, so we knew that it would be consumed before its argument (possibly a temporary) was destructed. `resume_agile` returns the `await_adapter`, and we expect people to await it immediately, but it's possible that they decide to save it in a variable and await it later. In that case, we have to record the `Async` as a value instead of a reference. We forward the `resume_agile` argument into the `Async` so that it moves if given an rvalue reference, or copies if given an lvalue reference. This ensure that the common case where somebody does `co_await resume_agile(DoSomething())`, we do not incur any additional AddRefs or Releases. Now that it's possible to `co_await` the `await_adapter` twice, we have to worry about `await_suspend` being called twice. It had previously assumed that `suspending` was true (since that's how it was constructed), but that is no longer valid in the `resume_agile` case if somebody tries to await the `resume_agile` twice. So we have to force it to `true`. (Now, the second await will fail with "illegal delegate assignment", but our failure to set `suspending` to `true` led to double-resumption, which is super-bad.) --- strings/base_coroutine_foundation.h | 16 +++++++++----- test/test/await_adapter.cpp | 33 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index ba61cd49a..670a65403 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -151,11 +151,12 @@ namespace winrt::impl #ifdef WINRT_IMPL_COROUTINES template - struct await_adapter : cancellable_awaiter> + struct await_adapter : cancellable_awaiter> { - await_adapter(Async const& async) : async(async) { } + template + await_adapter(T&& async) : async(std::forward(async)) { } - Async const& async; + std::conditional_t async; Windows::Foundation::AsyncStatus status = Windows::Foundation::AsyncStatus::Started; int32_t failure = 0; std::atomic suspending = true; @@ -190,6 +191,11 @@ namespace winrt::impl private: bool register_completed_callback(coroutine_handle<> handle) { + if constexpr (!preserve_context) + { + // Ensure that the illegal delegate assignment propagates properly. + suspending.store(true, std::memory_order_relaxed); + } async.Completed(disconnect_aware_handler(this, handle)); return suspending.exchange(false, std::memory_order_acquire); } @@ -257,9 +263,9 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { template>> - inline impl::await_adapter resume_agile(Async const& async) + inline impl::await_adapter, false> resume_agile(Async&& async) { - return { async }; + return { std::forward(async) }; }; } diff --git a/test/test/await_adapter.cpp b/test/test/await_adapter.cpp index 701bc6b15..dccb9ce3d 100644 --- a/test/test/await_adapter.cpp +++ b/test/test/await_adapter.cpp @@ -136,3 +136,36 @@ TEST_CASE("await_adapter_agile") AgileAsync(dispatcher).get(); controller.ShutdownQueueAsync().get(); } + +namespace +{ + IAsyncAction AgileAsyncVariable(DispatcherQueue dispatcher) + { + // Switch to the STA. + co_await resume_foreground(dispatcher); + REQUIRE(is_sta()); + + // Ask for agile resumption of a coroutine that finishes on a background thread. + // Add a 100ms delay to ensure we suspend. Store the resume_agile in a variable + // and await the variable. + auto op = resume_agile(OtherBackgroundDelayAsync()); + co_await op; + // We should be on the background thread now. + REQUIRE(!is_sta()); + + // Second attempt to await the op should fail cleanly. + REQUIRE_THROWS_AS(co_await op, hresult_illegal_delegate_assignment); + // We should still be on the background thread. + REQUIRE(!is_sta()); + } +} + + +TEST_CASE("await_adapter_agile_variable") +{ + auto controller = DispatcherQueueController::CreateOnDedicatedThread(); + auto dispatcher = controller.DispatcherQueue(); + + AgileAsyncVariable(dispatcher).get(); + controller.ShutdownQueueAsync().get(); +} From 912aa47ff43e0379e89d10dcb0d470bd360d17e3 Mon Sep 17 00:00:00 2001 From: Jon Wiswall Date: Sat, 25 Nov 2023 21:48:38 -0800 Subject: [PATCH 206/305] Update GitHub action LLVM version to 17.0.5 (#1373) * Maybe update tools version * LLVM & Clang v17.0.5 now support source_location properly --- .github/actions/setup-llvm-msvc/action.yml | 2 +- Directory.Build.Props | 4 ++++ test/test_cpp20/custom_error.cpp | 7 +------ 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/actions/setup-llvm-msvc/action.yml b/.github/actions/setup-llvm-msvc/action.yml index 5017f7dc9..d6a2a5faa 100644 --- a/.github/actions/setup-llvm-msvc/action.yml +++ b/.github/actions/setup-llvm-msvc/action.yml @@ -4,7 +4,7 @@ inputs: llvm-version: description: 'LLVM version' required: true - default: '15.0.5' + default: '17.0.5' outputs: llvm-path: description: "The path in which LLVM is installed to" diff --git a/Directory.Build.Props b/Directory.Build.Props index 38ad08350..95286d288 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -22,6 +22,10 @@ Optionally add /t: to only build a given a solution project: msbuild /m /p:Configuration=Debug,Platform=x64,Clang=1 cppwinrt.sln /t:cppwinrt + + If you have deployed the LLVM toolset elsewhere, add its path to the configuration: + + msbuild /m /p:Configuration=Debug,Platform=x64,Clang=1,LLVMToolsVersion=17.0.5,LLVMInstallDir=C:\llvm cppwinrt.sln --> diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index 34a0ea38f..97bfd8dc9 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -35,12 +35,7 @@ namespace } } -#if defined(__clang__) && defined(_MSC_VER) -// FIXME: Blocked on __cpp_consteval, see: -// * https://github.com/microsoft/cppwinrt/pull/1203#issuecomment-1279764927 -// * https://github.com/llvm/llvm-project/issues/57094 -TEST_CASE("custom_error_logger", "[!shouldfail]") -#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000 +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000 // not available in libc++ before LLVM 16 TEST_CASE("custom_error_logger", "[!shouldfail]") #else From fc587f31f94481b7e71306d84354d545d4dd8642 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Sat, 25 Nov 2023 23:18:59 -0800 Subject: [PATCH 207/305] Allow delegates to be created with weak reference + lambda (#1372) We have found that a very common pattern for event handlers is to capture a weak reference into a lambda, and in the event handler, try to upgrade the weak reference to a strong one, and if so, do some work: ```cpp widget.Closed([weak = get_weak(), data](auto&& sender, auto&& args) { if (auto strongThis = weak.get()) { strongThis->do_all_the_things(data); } }); ``` This commit extends the existing delegate constructors to permit a `winrt::weak_ref` + lambda (or `std::weak_ptr` + lambda), which simplifies the above to ```cpp widget.Closed({ get_weak(), [this, data](auto&& sender, auto&& args) { do_all_the_things(data); } }); ``` ## Implementation notes A lambda and pointer to member function are hard to distinguish in a template parameter list. In theory, we could use SFINAE or partial specialization, but a simpler solution is to distinguish the two inside the body of the constructor, via `std::is_member_function_pointer_v`. The `com_ptr` and `shared_ptr` variants of the test were unified, since I found myself editing two nearly identical tests. Fixes #1371 Co-authored-by: Jon Wiswall --- cppwinrt/code_writers.h | 32 ++-- strings/base_delegate.h | 14 +- .../UnitTests/delegate_weak_strong.cpp | 146 +++++++++--------- 3 files changed, 106 insertions(+), 86 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index a5c306fa5..3c77269cd 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2488,9 +2488,9 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable template %(F* function); template %(O* object, M method); template %(com_ptr&& object, M method); - template %(weak_ref&& object, M method); + template %(weak_ref&& object, LM&& lambda_or_method); template %(std::shared_ptr&& object, M method); - template %(std::weak_ptr&& object, M method); + template %(std::weak_ptr&& object, LM&& lambda_or_method); auto operator()(%) const; }; )"; @@ -2566,16 +2566,22 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable %([o = std::move(object), method](auto&&... args) { return ((*o).*(method))(args...); }) { } - template <%> template %<%>::%(weak_ref&& object, M method) : - %([o = std::move(object), method](auto&&... args) { if (auto s = o.get()) { ((*s).*(method))(args...); } }) + template <%> template %<%>::%(weak_ref&& object, LM&& lambda_or_method) : + %([o = std::move(object), lm = std::forward(lambda_or_method)](auto&&... args) { if (auto s = o.get()) { + if constexpr (std::is_member_function_pointer_v) ((*s).*(lm))(args...); + else lm(args...); + } }) { } template <%> template %<%>::%(std::shared_ptr&& object, M method) : %([o = std::move(object), method](auto&&... args) { return ((*o).*(method))(args...); }) { } - template <%> template %<%>::%(std::weak_ptr&& object, M method) : - %([o = std::move(object), method](auto&&... args) { if (auto s = o.lock()) { ((*s).*(method))(args...); } }) + template <%> template %<%>::%(std::weak_ptr&& object, LM&& lambda_or_method) : + %([o = std::move(object), lm = std::forward(lambda_or_method)](auto&&... args) { if (auto s = o.lock()) { + if constexpr (std::is_member_function_pointer_v) ((*s).*(lm))(args...); + else lm(args...); + } }) { } template <%> auto %<%>::operator()(%) const @@ -2652,16 +2658,22 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable %([o = std::move(object), method](auto&&... args) { return ((*o).*(method))(args...); }) { } - template %::%(weak_ref&& object, M method) : - %([o = std::move(object), method](auto&&... args) { if (auto s = o.get()) { ((*s).*(method))(args...); } }) + template %::%(weak_ref&& object, LM&& lambda_or_method) : + %([o = std::move(object), lm = std::forward(lambda_or_method)](auto&&... args) { if (auto s = o.get()) { + if constexpr (std::is_member_function_pointer_v) ((*s).*(lm))(args...); + else lm(args...); + } }) { } template %::%(std::shared_ptr&& object, M method) : %([o = std::move(object), method](auto&&... args) { return ((*o).*(method))(args...); }) { } - template %::%(std::weak_ptr&& object, M method) : - %([o = std::move(object), method](auto&&... args) { if (auto s = o.lock()) { ((*s).*(method))(args...); } }) + template %::%(std::weak_ptr&& object, LM&& lambda_or_method) : + %([o = std::move(object), lm = std::forward(lambda_or_method)](auto&&... args) { if (auto s = o.lock()) { + if constexpr (std::is_member_function_pointer_v) ((*s).*(lm))(args...); + else lm(args...); + } }) { } inline auto %::operator()(%) const diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 05742b610..8902b3cc6 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -180,8 +180,11 @@ namespace winrt::impl { } - template delegate_base(winrt::weak_ref&& object, M method) : - delegate_base([o = std::move(object), method](auto&& ... args) { if (auto s = o.get()) { ((*s).*(method))(args...); } }) + template delegate_base(winrt::weak_ref&& object, LM&& lambda_or_method) : + delegate_base([o = std::move(object), lm = std::forward(lambda_or_method)](auto&&... args) { if (auto s = o.get()) { + if constexpr (std::is_member_function_pointer_v) ((*s).*(lm))(args...); + else lm(args...); + }}) { } @@ -190,8 +193,11 @@ namespace winrt::impl { } - template delegate_base(std::weak_ptr&& object, M method) : - delegate_base([o = std::move(object), method](auto&& ... args) { if (auto s = o.lock()) { ((*s).*(method))(args...); } }) + template delegate_base(std::weak_ptr&& object, LM&& lambda_or_method) : + delegate_base([o = std::move(object), lm = std::forward(lambda_or_method)](auto&&... args) { if (auto s = o.lock()) { + if constexpr (std::is_member_function_pointer_v) ((*s).*(lm))(args...); + else lm(args...); + }}) { } diff --git a/test/old_tests/UnitTests/delegate_weak_strong.cpp b/test/old_tests/UnitTests/delegate_weak_strong.cpp index 30b02672a..84990c750 100644 --- a/test/old_tests/UnitTests/delegate_weak_strong.cpp +++ b/test/old_tests/UnitTests/delegate_weak_strong.cpp @@ -8,55 +8,85 @@ using namespace Windows::Foundation::Collections; namespace { - bool destroyed{}; - int strong_count{}; - int weak_count{}; + struct Counters + { + bool destroyed{}; + int strong_count{}; + int weak_count{}; + int weak_lambda_count{}; + + bool is_count(int value) + { + return strong_count == value && weak_count == value && weak_lambda_count == value; + } + }; template struct Object : implements, IInspectable> { + std::shared_ptr m_counters; + + Object(std::shared_ptr const& counters) : m_counters(counters) {} + + static auto make(std::shared_ptr const& counters) + { + return make_self(counters); + } + + auto strong() { return this->get_strong(); } + auto weak() { return this->get_weak(); } + ~Object() { - destroyed = true; + m_counters->destroyed = true; } void StrongHandler(Sender const&, Args const&) { - ++strong_count; + REQUIRE(!m_counters->destroyed); + ++m_counters->strong_count; } void WeakHandler(Sender const&, Args const&) { - ++weak_count; + REQUIRE(!m_counters->destroyed); + ++m_counters->weak_count; } }; template struct ObjectStd : std::enable_shared_from_this> { + std::shared_ptr m_counters; + + ObjectStd(std::shared_ptr const& counters) : m_counters(counters) {} + + static auto make(std::shared_ptr const& counters) + { + return std::make_shared(counters); + } + + auto strong() { return this->shared_from_this(); } + auto weak() { return this->weak_from_this(); } + ~ObjectStd() { - destroyed = true; + m_counters->destroyed = true; } void StrongHandler(Sender const&, Args const&) { - ++strong_count; + ++m_counters->strong_count; } void WeakHandler(Sender const&, Args const&) { - ++weak_count; + ++m_counters->weak_count; } }; struct ReturnObject : implements { - ~ReturnObject() - { - destroyed = true; - } - int Handler(int a, int b) { return a + b; @@ -65,91 +95,63 @@ namespace struct ReturnObjectStd : std::enable_shared_from_this { - ~ReturnObjectStd() - { - destroyed = true; - } - int Handler(int a, int b) { return a + b; } }; - template - void test_delegate_winrt() + template + void test_delegate_pattern() { - auto object = make_self>(); - - Delegate strong{ object->get_strong(), &Object::StrongHandler }; - Delegate weak{ object->get_weak(), &Object::WeakHandler }; + auto counters = std::make_shared(); + auto object = Recipient::make(counters); - destroyed = false; - strong_count = 0; - weak_count = 0; + Delegate strong{ object->strong(), &Recipient::StrongHandler}; + Delegate weak{ object->weak(), &Recipient::WeakHandler }; + Delegate weak_lambda{ object->weak(),[counters](auto&&, auto&&) { + REQUIRE(!counters->destroyed); + ++counters->weak_lambda_count; + } }; - // Both weak and strong handlers + // All handlers are active at this point strong({}, {}); weak({}, {}); - REQUIRE(strong_count == 1); - REQUIRE(weak_count == 1); + weak_lambda({}, {}); + REQUIRE(counters->is_count(1)); // Local 'object' strong reference is released object = nullptr; - // Still both since strong handler keeps object alive + // Still invoked since strong handler keeps object alive strong({}, {}); weak({}, {}); - REQUIRE(strong_count == 2); - REQUIRE(weak_count == 2); + weak_lambda({}, {}); + REQUIRE(counters->is_count(2)); - // ~Object is called since the strong delegate is destroyed - REQUIRE(!destroyed); + // ~Recipient is called since the strong delegate is destroyed + REQUIRE(!counters->destroyed); strong = nullptr; - REQUIRE(destroyed); + REQUIRE(counters->destroyed); // Weak delegate remains but no longer fires - REQUIRE(weak_count == 2); + // Strong delegate shouldn't fire either + REQUIRE(counters->is_count(2)); weak({}, {}); - REQUIRE(weak_count == 2); + weak_lambda({}, {}); + REQUIRE(counters->is_count(2)); } template - void test_delegate_std() + void test_delegate_winrt() { - auto object = std::make_shared>(); - - Delegate strong{ object->shared_from_this(), &ObjectStd::StrongHandler }; - Delegate weak{ object->weak_from_this(), &ObjectStd::WeakHandler }; - - destroyed = false; - strong_count = 0; - weak_count = 0; - - // Both weak and strong handlers - strong({}, {}); - weak({}, {}); - REQUIRE(strong_count == 1); - REQUIRE(weak_count == 1); - - // Local 'object' strong reference is released - object = nullptr; - - // Still both since strong handler keeps object alive - strong({}, {}); - weak({}, {}); - REQUIRE(strong_count == 2); - REQUIRE(weak_count == 2); - - // ~Object is called since the strong delegate is destroyed - REQUIRE(!destroyed); - strong = nullptr; - REQUIRE(destroyed); + test_delegate_pattern, Delegate>(); + } - // Weak delegate remains but no longer fires - REQUIRE(weak_count == 2); - weak({}, {}); - REQUIRE(weak_count == 2); + template + void test_delegate_std() + { + test_delegate_pattern, Delegate>(); } template From 2511bf7fcb54a64c1e596a950788e2ee30cd1e4c Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 6 Dec 2023 15:33:21 -0800 Subject: [PATCH 208/305] Update pool (#1374) --- .pipelines/sync-mirror.yml | 83 ++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/.pipelines/sync-mirror.yml b/.pipelines/sync-mirror.yml index add70e3ba..f7be6296d 100644 --- a/.pipelines/sync-mirror.yml +++ b/.pipelines/sync-mirror.yml @@ -11,44 +11,57 @@ parameters: type: string default: "https://github.com/microsoft/cppwinrt.git" -jobs: - - job: SyncMirror - strategy: - matrix: - ${{ each branches in parameters.SourceToTargetBranches }}: - ${{ branches.key }}: - SourceBranch: ${{ branches.key }} - TargetBranch: ${{ branches.value }} - dependsOn: [] +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: pool: - name: Azure Pipelines - vmImage: 'windows-2022' - steps: - - checkout: self - persistCredentials: true + name: Azure-Pipelines-1ESPT-ExDShared + image: windows-2022 + os: windows + customBuildTags: + - ES365AIMigrationTooling + stages: + - stage: stage + jobs: + - job: SyncMirror + strategy: + matrix: + ${{ each branches in parameters.SourceToTargetBranches }}: + ${{ branches.key }}: + SourceBranch: ${{ branches.key }} + TargetBranch: ${{ branches.value }} + dependsOn: [] + steps: + - checkout: self + persistCredentials: true - - task: PowerShell@2 - inputs: - targetType: 'inline' - script: | - Write-Host "SourceBranch " + "$(SourceBranch)" - Write-Host "TargetBranch " + "$(TargetBranch)" + - task: PowerShell@2 + inputs: + targetType: 'inline' + script: | + Write-Host "SourceBranch " + "$(SourceBranch)" + Write-Host "TargetBranch " + "$(TargetBranch)" - $repo = "${{ parameters.SourceRepository }}" - git remote add sourcerepo $repo - git remote + $repo = "${{ parameters.SourceRepository }}" + git remote add sourcerepo $repo + git remote - $target = "$(TargetBranch)" - git fetch origin $target - git checkout $target - git pull origin $target + $target = "$(TargetBranch)" + git fetch origin $target + git checkout $target + git pull origin $target - $source = "$(SourceBranch)" - git fetch sourcerepo $source - git pull sourcerepo $source - - - task: CmdLine@2 - inputs: - script: | - git push + $source = "$(SourceBranch)" + git fetch sourcerepo $source + git pull sourcerepo $source + - task: CmdLine@2 + inputs: + script: | + git push From 5ef408f8b068f6311b86f0f7a52842fb94485810 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Fri, 22 Dec 2023 11:47:37 -0800 Subject: [PATCH 209/305] User/dmachaj/slim source location (#1379) * First draft of slim_source_location * Fix build breaks from first impl * Fix failing test case --- strings/base_macros.h | 75 ++++++++++++++++++++++++++++++-- test/test_cpp20/custom_error.cpp | 4 ++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/strings/base_macros.h b/strings/base_macros.h index deea7e7c1..e0167d152 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -85,6 +85,58 @@ typedef struct _GUID GUID; // Some projects may decide to disable std::source_location support to prevent source code information from ending up in their // release binaries, or to reduce binary size. Defining WINRT_NO_SOURCE_LOCATION will prevent this feature from activating. #if defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) + +namespace winrt::impl +{ + // This struct is intended to be highly similar to std::source_location. The key difference is + // that function_name is NOT included. Function names do not fold to identical strings and can + // have heavy binary size overhead when templates cause many permutations to exist. + struct slim_source_location + { + [[nodiscard]] static consteval slim_source_location current( + const std::uint_least32_t line = __builtin_LINE(), + const char* const file = __builtin_FILE()) noexcept + { + return slim_source_location{ line, file }; + } + + [[nodiscard]] constexpr slim_source_location() noexcept = default; + + [[nodiscard]] constexpr slim_source_location(const std::uint_least32_t line, + const char* const file) noexcept : + m_line(line), + m_file(file) + {} + + [[nodiscard]] constexpr std::uint_least32_t line() const noexcept + { + return m_line; + } + + [[nodiscard]] constexpr const char* file_name() const noexcept + { + return m_file; + } + + constexpr const char* function_name() const noexcept + { + // This is intentionally not included. See comment above. + return nullptr; + } + + private: + const std::uint_least32_t m_line{}; + const char* const m_file{}; + }; +} + +// std::source_location includes function_name which can be helpful but creates a lot of binary size impact. Many consumers +// have defined WINRT_NO_SOURCE_LOCATION to prevent this impact, losing the value of source_location. We have defined a +// slim_source_location struct that is equivalent but excludes function_name. This should have the vast majority of the +// usefulness of source_location while having a much smaller binary impact. +// +// When building _DEBUG binary size is not usually much of a concern, so we can use the full source_location type. +#ifdef _DEBUG #define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , std::source_location const& sourceInformation #define WINRT_IMPL_SOURCE_LOCATION_ARGS , std::source_location const& sourceInformation = std::source_location::current() #define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM std::source_location const& sourceInformation = std::source_location::current() @@ -96,7 +148,24 @@ typedef struct _GUID GUID; #ifdef _MSC_VER #pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true") -#endif +#endif // _MSC_VER + +#else // !_DEBUG +#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , winrt::impl::slim_source_location const& sourceInformation +#define WINRT_IMPL_SOURCE_LOCATION_ARGS , winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() +#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() + +#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation +#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation + +#define WINRT_SOURCE_LOCATION_ACTIVE + +#ifdef _MSC_VER +#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") +#endif // _MSC_VER + +#endif // _DEBUG + #else #define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT #define WINRT_IMPL_SOURCE_LOCATION_ARGS @@ -107,5 +176,5 @@ typedef struct _GUID GUID; #ifdef _MSC_VER #pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false") -#endif -#endif +#endif // _MSC_VER +#endif // defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index 97bfd8dc9..d7b055e47 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -54,12 +54,16 @@ TEST_CASE("custom_error_logger") const auto fileNameSv = std::string_view(s_loggerArgs.fileName); REQUIRE(!fileNameSv.empty()); REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); +#ifdef _DEBUG const auto functionNameSv = std::string_view(s_loggerArgs.functionName); REQUIRE(!functionNameSv.empty()); // Every compiler has a slightly different naming approach for this function, and even the same // compiler can change its mind over time. Instead of matching the entire function name just // match against the part we care about. REQUIRE((functionNameSv.find("FailOnLine15") != std::string_view::npos)); +#else + REQUIRE(s_loggerArgs.functionName == nullptr); +#endif // _DEBUG REQUIRE(s_loggerArgs.returnAddress); REQUIRE(s_loggerArgs.result == static_cast(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) From cb674723b42b830215156ccb032533c0e3092c28 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 28 Dec 2023 10:59:33 -0800 Subject: [PATCH 210/305] CppWinRTAddXamlReferences to not use outputs as inputs (#1381) Incremental builds fail when a referenced project's winmd has been updated. This is because the CppWinRT reference projection is properly using project's referenced winmds as inputs. But the MarkupCompilePass2 target is using XamlReferencesToCompile, which has been set here to use previously copied output files. --- nuget/Microsoft.Windows.CppWinRT.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 3b8b21972..f5606caec 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -859,9 +859,9 @@ $(XamlMetaDataProviderPch) + DependsOnTargets="$(CppWinRTAddXamlReferencesDependsOn);CppWinRTGetResolvedWinMD;GetCppWinRTProjectWinMDReferences"> - + From 25a14f89655ffdbaa85fa9e0e797de7ddc340dac Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 11 Jan 2024 20:12:06 -0800 Subject: [PATCH 211/305] Update build.yml for Azure Pipelines (#1384) #1338 changed the NuGet version to a property, but didn't update the build.yml to do the same thing --- .pipelines/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pipelines/build.yml b/.pipelines/build.yml index 817ab9fa3..8a7ee5568 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -422,7 +422,7 @@ jobs: command: pack searchPatternPack: nuget/Microsoft.Windows.CppWinRT.nuspec versioningScheme: byBuildNumber - buildProperties: 'cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' + buildProperties: 'target_version=$(Build.BuildNumber);cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' - task: ComponentGovernanceComponentDetection@0 displayName: Component Detection From 2bfcd7524af95087dcb60ce550dbc046f9ccec27 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 16 Jan 2024 13:00:38 -0600 Subject: [PATCH 212/305] Fail gracefully when error reporting is suppressed (#1386) --- strings/base_error.h | 4 ++-- test/test/suppress_error_info.cpp | 17 +++++++++++++++++ test/test/test.vcxproj | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 test/test/suppress_error_info.cpp diff --git a/strings/base_error.h b/strings/base_error.h index 2a6eea281..07d688472 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -313,8 +313,8 @@ WINRT_EXPORT namespace winrt } com_ptr info; - WINRT_VERIFY_(0, WINRT_IMPL_GetErrorInfo(0, info.put_void())); - WINRT_VERIFY(info.try_as(m_info)); + WINRT_IMPL_GetErrorInfo(0, info.put_void()); + info.try_as(m_info); } static hresult verify_error(hresult const code) noexcept diff --git a/test/test/suppress_error_info.cpp b/test/test/suppress_error_info.cpp new file mode 100644 index 000000000..f2d25cac1 --- /dev/null +++ b/test/test/suppress_error_info.cpp @@ -0,0 +1,17 @@ +#include "pch.h" +#include + +TEST_CASE("suppress_error_info") +{ + winrt::check_hresult(RoSetErrorReportingFlags(RO_ERROR_REPORTING_SUPPRESSSETERRORINFO)); + + // Since the error information is suppressed, the best we can hope for is that C++/WinRT + // will provide a generic message for the HRESULT. + REQUIRE(winrt::hresult_error(E_FAIL, L"message").message() == L"Unspecified error"); + + winrt::check_hresult(RoSetErrorReportingFlags(RO_ERROR_REPORTING_USESETERRORINFO)); + + // The default behavior has been restored, so C++/WinRT can faithfully provide error + // information as usual. + REQUIRE(winrt::hresult_error(E_FAIL, L"message").message() == L"message"); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index bb33508a2..b75f2e219 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -418,6 +418,7 @@ + From 91f485fbf2291da083f4360a098dfc2e57475026 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 22 Jan 2024 14:47:43 -0500 Subject: [PATCH 213/305] Remove double forward (#1387) * Remove double forward * Fix compilation issues --- strings/base_string.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/strings/base_string.h b/strings/base_string.h index 2782968b8..e70eed925 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -567,12 +567,18 @@ namespace winrt::impl template inline hstring base_format(Args&&... args) { - auto const size = std::formatted_size(std::forward(args)...); + // don't forward because an object could be moved-from, causing issues + // for the second format call. + // not forwarding lets us take both rvalues and lvalues but pass them + // further down as an lvalue ref. some types can only be formatted + // when non-const (e.g. ranges::filter_view) so taking a const reference + // as parameter wouldn't work for all scenarios. + auto const size = std::formatted_size(args...); WINRT_ASSERT(size < UINT_MAX); auto const size32 = static_cast(size); hstring_builder builder(size32); - WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, std::forward(args)...).size); + WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); return builder.to_hstring(); } #endif @@ -582,15 +588,15 @@ WINRT_EXPORT namespace winrt { #if __cpp_lib_format >= 202207L template - inline hstring format(std::wformat_string const fmt, Args&&... args) + inline hstring format(std::wformat_string const fmt, Args&&... args) { - return impl::base_format(fmt, std::forward(args)...); + return impl::base_format(fmt, args...); } template - inline hstring format(std::locale const& loc, std::wformat_string const fmt, Args&&... args) + inline hstring format(std::locale const& loc, std::wformat_string const fmt, Args&&... args) { - return impl::base_format(loc, fmt, std::forward(args)...); + return impl::base_format(loc, fmt, args...); } #endif From e69ff22721f9fb968a18d8da6ef67d062a9e5db1 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Thu, 8 Feb 2024 12:46:38 -0600 Subject: [PATCH 214/305] Remove dead code related to Windows 7 support (#1390) --- strings/base_agile_ref.h | 55 ----------------------- strings/base_error.h | 97 ---------------------------------------- 2 files changed, 152 deletions(-) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index 8993d846b..b85cb7e61 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -71,61 +71,6 @@ namespace winrt::impl using update_module_lock = module_lock_updater; - struct agile_ref_fallback final : IAgileReference, update_module_lock - { - agile_ref_fallback(com_ptr&& git, uint32_t cookie) noexcept : - m_git(std::move(git)), - m_cookie(cookie) - { - } - - ~agile_ref_fallback() noexcept - { - m_git->RevokeInterfaceFromGlobal(m_cookie); - } - - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final - { - if (is_guid_of(id) || is_guid_of(id) || is_guid_of(id)) - { - *object = static_cast(this); - AddRef(); - return 0; - } - - *object = nullptr; - return error_no_interface; - } - - uint32_t __stdcall AddRef() noexcept final - { - return ++m_references; - } - - uint32_t __stdcall Release() noexcept final - { - auto const remaining = --m_references; - - if (remaining == 0) - { - delete this; - } - - return remaining; - } - - int32_t __stdcall Resolve(guid const& id, void** object) noexcept final - { - return m_git->GetInterfaceFromGlobal(m_cookie, id, object); - } - - private: - - com_ptr m_git; - uint32_t m_cookie{}; - atomic_ref_count m_references{ 1 }; - }; - inline void* load_library(wchar_t const* library) noexcept { return WINRT_IMPL_LoadLibraryExW(library, nullptr, 0x00001000 /* LOAD_LIBRARY_SEARCH_DEFAULT_DIRS */); diff --git a/strings/base_error.h b/strings/base_error.h index 07d688472..6e0aa103a 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -78,103 +78,6 @@ namespace winrt::impl { return ((int32_t)((x) | 0x10000000)); } - - struct error_info_fallback final : IErrorInfo, IRestrictedErrorInfo, update_module_lock - { - error_info_fallback(int32_t code, void* message) noexcept : - m_code(code), - m_message(message ? *reinterpret_cast(&message) : message_from_hresult(code)) - { - } - - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final - { - if (is_guid_of(id) || is_guid_of(id) || is_guid_of(id)) - { - *object = static_cast(this); - AddRef(); - return 0; - } - - if (is_guid_of(id)) - { - *object = static_cast(this); - AddRef(); - return 0; - } - - *object = nullptr; - return error_no_interface; - } - - uint32_t __stdcall AddRef() noexcept final - { - return ++m_references; - } - - uint32_t __stdcall Release() noexcept final - { - auto const remaining = --m_references; - - if (remaining == 0) - { - delete this; - } - - return remaining; - } - - int32_t __stdcall GetGUID(guid* value) noexcept final - { - *value = {}; - return 0; - } - - int32_t __stdcall GetSource(bstr* value) noexcept final - { - *value = nullptr; - return 0; - } - - int32_t __stdcall GetDescription(bstr* value) noexcept final - { - *value = WINRT_IMPL_SysAllocString(m_message.c_str()); - return *value ? error_ok : error_bad_alloc; - } - - int32_t __stdcall GetHelpFile(bstr* value) noexcept final - { - *value = nullptr; - return 0; - } - - int32_t __stdcall GetHelpContext(uint32_t* value) noexcept final - { - *value = 0; - return 0; - } - - int32_t __stdcall GetErrorDetails(bstr* fallback, int32_t* error, bstr* message, bstr* capability) noexcept final - { - *fallback = nullptr; - *error = m_code; - *capability = nullptr; - *message = WINRT_IMPL_SysAllocString(m_message.c_str()); - return *message ? error_ok : error_bad_alloc; - } - - int32_t __stdcall GetReference(bstr* value) noexcept final - { - *value = nullptr; - return 0; - } - - private: - - hresult const m_code; - hstring const m_message; - atomic_ref_count m_references{ 1 }; - }; } WINRT_EXPORT namespace winrt From 6dccf9ef884a6b1613f14682d8ae181563a00559 Mon Sep 17 00:00:00 2001 From: Dan Legg Date: Thu, 28 Mar 2024 18:06:25 -0700 Subject: [PATCH 215/305] Pipeline changes to build, publish, and test (#1400) Co-authored-by: Dan Legg --- .pipelines/OneBranch.Official.yml | 4 ---- .pipelines/jobs/OneBranchNuGet.yml | 15 ++++++++------- .pipelines/jobs/OneBranchTest.yml | 3 +++ .pipelines/jobs/OneBranchVsix.yml | 4 ++-- test/test_cpp20/format.cpp | 9 +++++++++ 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index def1114a8..3c2ffdfcd 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -34,10 +34,6 @@ extends: globalSdl: tsa: enabled: false - - nugetPublishing: - feeds: - name: CppWinRT stages: - stage: build diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 803e6f9f7..e2a871114 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -15,7 +15,6 @@ jobs: variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ob_nugetPublishing_enabled: ${{ parameters.OfficialBuild }} PackageVersion: ${{ parameters.BuildVersion }} steps: @@ -59,12 +58,8 @@ jobs: - task: NuGetCommand@2 displayName: 'Build NuGet package' inputs: - command: 'pack' - packagesToPack: 'nuget/Microsoft.Windows.CppWinRT.nuspec' - versioningScheme: byEnvVar - versionEnvVar: 'PackageVersion' - buildProperties: 'cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib' - packDestination: $(ob_outputDirectory)\packages + command: 'custom' + arguments: 'pack nuget/Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory $(ob_outputDirectory)\packages -Properties Configuration=release;cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib;target_version=$(PackageVersion) -Version $(PackageVersion) -Verbosity Detailed' - task: onebranch.pipeline.signing@1 displayName: '🔒 Onebranch Signing for NuGet package' @@ -74,3 +69,9 @@ jobs: signing_profile: external_distribution files_to_sign: 'Microsoft.Windows.CppWinRT.*.nupkg' search_root: $(ob_outputDirectory)\packages + + - task: NuGetCommand@2 + displayName: 'Publish NuGet package' + inputs: + command: 'custom' + arguments: 'push $(ob_outputDirectory)\packages\Microsoft.Windows.CppWinRT.$(PackageVersion).nupkg -NonInteractive -Source https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json -ApiKey VSTS' \ No newline at end of file diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index d9634ff1e..bba8dac20 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -8,6 +8,9 @@ jobs: - job: pool: type: windows + isCustom: true + name: 'Azure Pipelines' + vmImage: 'windows-2022' # (or 2019) strategy: matrix: test.x86: diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 2efa5b29c..3526712eb 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -108,8 +108,8 @@ jobs: inputs: command: sign signing_profile: external_distribution - files_to_sign: '**/Microsoft.Windows.CppWinRT.*.dll' - search_root: '$(Agent.TempDirectory)\$(VsixFilename)' + files_to_sign: '**\*.dll' + search_root: '$(Agent.TempDirectory)' - task: ArchiveFiles@2 displayName: 'Repack signed VSIX contents' diff --git a/test/test_cpp20/format.cpp b/test/test_cpp20/format.cpp index 0c40a4113..d16193328 100644 --- a/test/test_cpp20/format.cpp +++ b/test/test_cpp20/format.cpp @@ -17,17 +17,26 @@ TEST_CASE("format") winrt::hstring str = L"World"; REQUIRE(std::format(L"Hello {}", str) == L"Hello World"); } +} +TEST_CASE("format_make") +{ { winrt::Windows::Foundation::IStringable obj = winrt::make(); REQUIRE(std::format(L"This is {}", obj) == L"This is a stringable object"); } +} +TEST_CASE("format_json") +{ { winrt::Windows::Data::Json::JsonArray jsonArray; REQUIRE(std::format(L"The contents of the array are: {}", jsonArray) == L"The contents of the array are: []"); } +} +TEST_CASE("format_wstring") +{ #if __cpp_lib_format >= 202207L { std::wstring str = L"World"; From bdf6dc462bf6b827d7c8ce893e725faf5acba6b0 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 29 Mar 2024 10:42:29 -0700 Subject: [PATCH 216/305] Merlinbot baseline (#1401) * Merged PR 9973274: Auto-generated baselines by 1ES Pipeline Templates This pull request includes baselines **with an expiration date of 180 days from now** automatically generated for your 1ES PT-based pipelines. Complete this pull request as soon as possible to make sure that your pipeline becomes compliant. Longer delays in completing this PR can trigger additional emails or S360 alerts in the future. 1ES PT Auto-baselining feature helps capture existing violations in your repo and ensures to break your pipeline only for newly introduced SDL violations after baselining. Running SDL tools in break mode is required for your pipeline to be compliant. Go to https://aka.ms/1espt-autobaselining for more details. * Merged PR 9973274: Auto-generated baselines by 1ES Pipeline Templates This pull request includes baselines **with an expiration date of 180 days from now** automatically generated for your 1ES PT-based pipelines. Complete this pull request as soon as possible to make sure that your pipeline becomes compliant. Longer delays in completing this PR can trigger additional emails or S360 alerts in the future. 1ES PT Auto-baselining feature helps capture existing violations in your repo and ensures to break your pipeline only for newly introduced SDL violations after baselining. Running SDL tools in break mode is required for your pipeline to be compliant. Go to https://aka.ms/1espt-autobaselining for more details. --------- Co-authored-by: MerlinBot --- .config/1espt/PipelineAutobaseliningConfig.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .config/1espt/PipelineAutobaseliningConfig.yml diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml new file mode 100644 index 000000000..a14f9aaaa --- /dev/null +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -0,0 +1,14 @@ +## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. + +pipelines: + 98194: + retail: + source: + credscan: + lastModifiedDate: 2023-12-06 + eslint: + lastModifiedDate: 2023-12-06 + psscriptanalyzer: + lastModifiedDate: 2023-12-06 + armory: + lastModifiedDate: 2023-12-06 From adc6ef93185b2fa40e5f89d99fcd59b8b856dec7 Mon Sep 17 00:00:00 2001 From: TDBuild Date: Sun, 31 Mar 2024 05:01:31 +0000 Subject: [PATCH 217/305] TDBuild - updating localized resource files. --- .../1espt/PipelineAutobaseliningConfig.yml | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml index a14f9aaaa..4b9969c37 100644 --- a/.config/1espt/PipelineAutobaseliningConfig.yml +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -1,14 +1,14 @@ -## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. - -pipelines: - 98194: - retail: - source: - credscan: - lastModifiedDate: 2023-12-06 - eslint: - lastModifiedDate: 2023-12-06 - psscriptanalyzer: - lastModifiedDate: 2023-12-06 - armory: - lastModifiedDate: 2023-12-06 +## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. + +pipelines: + 98194: + retail: + source: + credscan: + lastModifiedDate: 2023-12-06 + eslint: + lastModifiedDate: 2023-12-06 + psscriptanalyzer: + lastModifiedDate: 2023-12-06 + armory: + lastModifiedDate: 2023-12-06 From f0ce6c67980f4617340282c352aabfef8dbdc41b Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 5 Apr 2024 07:52:22 -0500 Subject: [PATCH 218/305] Create dependabot.yml --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..47f88349d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" From dfad7ed2cae3f4d6e5c5f07c2416804245c98409 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 07:55:51 -0500 Subject: [PATCH 219/305] Bump actions/checkout from 3 to 4 (#1406) --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d37aa360..f4d0458d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: setup-llvm name: Set up LLVM (MSVC) @@ -107,7 +107,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: setup-llvm name: Set up LLVM (MSVC) @@ -260,7 +260,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install cross compiler run: | @@ -293,7 +293,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Download nuget run: | @@ -331,7 +331,7 @@ jobs: config: [Release] runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Fetch cppwinrt executables uses: actions/download-artifact@v3 @@ -381,7 +381,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Package run: | From 523eda71a6fdd73534c7910b974554ac9850830f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 07:56:22 -0500 Subject: [PATCH 220/305] Bump actions/stale from 6 to 9 (#1405) --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 20bf8f2a4..c081bdf43 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v6 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 10 From 6f7495288c4a90b29e95808ab08a0489f7d94f72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 07:59:41 -0500 Subject: [PATCH 221/305] Bump actions/upload-artifact from 3 to 4 (#1407) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4d0458d9..3351eb550 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -240,7 +240,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -279,7 +279,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -396,7 +396,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: package path: "*.nupkg" From ea187691c1c0d508399c1b069635383082fd9e5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 08:11:19 -0500 Subject: [PATCH 222/305] Bump actions/download-artifact from 3 to 4 (#1408) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3351eb550..898369f1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,14 +116,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: msvc-build-x86-Release-bin path: _build/x86/Release/ @@ -334,7 +334,7 @@ jobs: - uses: actions/checkout@v4 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From 2b8fe6e000ea9ce4402e97fa85c3919fe9a81281 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 5 Apr 2024 08:35:15 -0500 Subject: [PATCH 223/305] Revert "Bump actions/upload-artifact from 3 to 4 (#1407)" --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 898369f1c..ad5e708d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -240,7 +240,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -279,7 +279,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -396,7 +396,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: package path: "*.nupkg" From 17d095ac936f21007ef94f9594aec52d250240a6 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 5 Apr 2024 09:39:24 -0500 Subject: [PATCH 224/305] Fix build following dependabot updates (#1409) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad5e708d7..f4d0458d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,14 +116,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: msvc-build-x86-Release-bin path: _build/x86/Release/ @@ -334,7 +334,7 @@ jobs: - uses: actions/checkout@v4 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From e03bdc4e3987b8eb1425b9fe4f2ebbba548be423 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:16:37 -0400 Subject: [PATCH 225/305] Use latest upload/download actions (#1410) --- .github/workflows/ci.yml | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4d0458d9..af61bbe99 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,9 +71,9 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -116,16 +116,16 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: msvc-build-x86-Release-bin + name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ - name: Download nuget @@ -240,9 +240,9 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -279,7 +279,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -323,10 +323,12 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln build-msvc-nuget-test: - name: 'Build nuget test' + name: 'Build nuget test (${{ matrix.arch }})' needs: test-msvc-cppwinrt-build strategy: matrix: + compiler: + - MSVC arch: [x86, x64] config: [Release] runs-on: windows-latest @@ -334,9 +336,9 @@ jobs: - uses: actions/checkout@v4 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Download nuget @@ -396,7 +398,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: package path: "*.nupkg" From d2a66776bb16e1da9dac60770c977e847485e24b Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Fri, 5 Apr 2024 13:15:18 -0700 Subject: [PATCH 226/305] Remove references to stale winmd files to fix incremental builds (#1404) The original attempt at a fix for this was too aggressive: https://github.com/microsoft/cppwinrt/pull/1381/files This fix is targeted specifically at removing references to stale winmd files that have yet to be copied from referenced projects (e.g., from a runtime component to an app). --- nuget/Microsoft.Windows.CppWinRT.targets | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index f5606caec..4d861e12a 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -861,7 +861,9 @@ $(XamlMetaDataProviderPch) Condition="'@(Page)@(ApplicationDefinition)' != '' and '$(XamlLanguage)' == 'CppWinRT'" DependsOnTargets="$(CppWinRTAddXamlReferencesDependsOn);CppWinRTGetResolvedWinMD;GetCppWinRTProjectWinMDReferences"> - + + + From bc19737a14e54d9fc8a98993df2e2c9033cadd42 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:27:02 -0400 Subject: [PATCH 227/305] Use latest cache action (#1411) --- .github/actions/setup-llvm-mingw/action.yml | 4 ++-- .github/actions/setup-llvm-msvc/action.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-llvm-mingw/action.yml b/.github/actions/setup-llvm-mingw/action.yml index 9926bbe93..50fe696b7 100644 --- a/.github/actions/setup-llvm-mingw/action.yml +++ b/.github/actions/setup-llvm-mingw/action.yml @@ -19,7 +19,7 @@ runs: - name: Cache llvm-mingw (Windows) id: cache-llvm if: runner.os == 'Windows' - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: .llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} @@ -50,7 +50,7 @@ runs: - name: Cache llvm-mingw (Linux) id: cache-llvm-linux if: runner.os == 'Linux' - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /opt/llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} diff --git a/.github/actions/setup-llvm-msvc/action.yml b/.github/actions/setup-llvm-msvc/action.yml index d6a2a5faa..036d0fa28 100644 --- a/.github/actions/setup-llvm-msvc/action.yml +++ b/.github/actions/setup-llvm-msvc/action.yml @@ -14,7 +14,7 @@ runs: steps: - name: Cache LLVM and tools id: cache-llvm - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | .LLVM From 881b5614b850a03794997c6d01f5d1131594a864 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sat, 6 Apr 2024 08:17:18 -0400 Subject: [PATCH 228/305] Spelling (#1412) --- cross-mingw-toolchain.cmake | 2 +- natvis/object_visualizer.h | 2 +- nuget/Microsoft.Windows.CppWinRT.targets | 2 +- nuget/readme.md | 6 +++--- test/catch.hpp | 4 ++-- test/old_tests/Component/Component.idl | 4 ++-- test/old_tests/UnitTests/abi_guard.cpp | 12 ++++++------ test/old_tests/UnitTests/async.cpp | 2 +- test/old_tests/UnitTests/delegate.cpp | 2 +- test/old_tests/UnitTests/make_self.cpp | 2 +- test/old_tests/UnitTests/marshal.cpp | 2 +- test/old_tests/UnitTests/produce.cpp | 2 +- test/old_tests/UnitTests/produce_async.cpp | 2 +- test/old_tests/UnitTests/produce_map.cpp | 2 +- test/old_tests/UnitTests/produce_vector.cpp | 2 +- test/old_tests/UnitTests/struct.cpp | 4 ++-- test/test/abi_guard.cpp | 12 ++++++------ test/test/cmd_reader.cpp | 2 +- test/test/thread_pool.cpp | 2 +- test/test_component_base/pch.h | 2 +- 20 files changed, 35 insertions(+), 35 deletions(-) diff --git a/cross-mingw-toolchain.cmake b/cross-mingw-toolchain.cmake index d58bb278d..23156e11b 100644 --- a/cross-mingw-toolchain.cmake +++ b/cross-mingw-toolchain.cmake @@ -1,5 +1,5 @@ # This is a cmake-toolchain(5) file that can be used to cross-build -# cppwinrt.exe fron Linux or other operating systems using a mingw-w64 cross +# cppwinrt.exe from Linux or other operating systems using a mingw-w64 cross # toolchain. This should work with both GCC-based and llvm-mingw toolchains. # # Example usage with external toolchain: diff --git a/natvis/object_visualizer.h b/natvis/object_visualizer.h index 08cc40f72..ad83d79d7 100644 --- a/natvis/object_visualizer.h +++ b/natvis/object_visualizer.h @@ -26,7 +26,7 @@ enum class ObjectType Projection, }; -// Metatdata for resolving a runtime class property value +// Metadata for resolving a runtime class property value struct PropertyData { std::wstring iid; diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 4d861e12a..7fe83b14d 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -28,7 +28,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. $(CppWinRTParameters) -fastabi "$(CppWinRTPackageDir)bin\" "$(CppWinRTPackageDir)" - + true C++ diff --git a/nuget/readme.md b/nuget/readme.md index 991fd2768..9379aa716 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -41,7 +41,7 @@ It sets the following project properties and item metadata: | Link.AdditionalDependencies | WindowsApp.lib | Umbrella library for Windows Runtime imports | | Midl.AdditionalOptions | /reference ... | Enables faster compilation with winmd references (versus idl imports) | | Midl.EnableWindowsRuntime | true | Enables Windows Runtime semantics | -| Midl.MetadataFileName | Unmerged\%(Filename).winmd | Generates unmerged metadata in a tempoary location | +| Midl.MetadataFileName | Unmerged\%(Filename).winmd | Generates unmerged metadata in a temporary location | | Midl.GenerateClientFiles, GenerateServerFiles, GenerateStublessProxies, GenerateTypeLibrary, HeaderFileName, DllDataFileName, InterfaceIdentifierFileName, ProxyFileName, TypeLibraryName | *nul, *None, *false | Disable unnecessary output | \*If not already set @@ -114,7 +114,7 @@ void MyComponent::InitializeComponent() ***[Windows|Microsoft]::UI::Xaml::Markup::ComponentConnectorT*** -A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implemenation for these interfaces: +A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implementation for these interfaces: ```cpp struct DerivedPage : winrt::Windows::UI::Xaml::Markup::ComponentConnectorT> @@ -147,7 +147,7 @@ For example, if the verbosity is set to minimal, then only messages with high im The default importance of C++/WinRT build messages is 'normal', but this can be overridden with the CppWinRTVerbosity property to enable throttling of C++/WinRT messages independent of the overall verbosity level. Example: -> msbuild project.vcxproj /vebosity:minimal /property:CppWinRTVerbosity=high ... +> msbuild project.vcxproj /verbosity:minimal /property:CppWinRTVerbosity=high ... For more complex analysis of build errors, the [MSBuild Binary and Structured Log Viewer](http://msbuildlog.com/) is highly recommended. diff --git a/test/catch.hpp b/test/catch.hpp index e949ee88c..d008973a6 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -7779,7 +7779,7 @@ namespace Catch { result = -erfc_inv(2.0 * p); // result *= normal distribution standard deviation (1.0) * sqrt(2) result *= /*sd * */ ROOT_TWO; - // result += normal disttribution mean (0) + // result += normal distribution mean (0) return result; } @@ -11310,7 +11310,7 @@ namespace Catch { std::string TagInfo::all() const { size_t size = 0; for (auto const& spelling : spellings) { - // Add 2 for the brackes + // Add 2 for the brackets size += spelling.size() + 2; } diff --git a/test/old_tests/Component/Component.idl b/test/old_tests/Component/Component.idl index 157297ee9..3c306ad69 100644 --- a/test/old_tests/Component/Component.idl +++ b/test/old_tests/Component/Component.idl @@ -247,7 +247,7 @@ namespace Component runtimeclass FastInputVector { // Don't confuse this for a high-performance vector. This is for testing fast-input binding support. - // The default interface is intentionally not one of the collection intefaces to force them to be convertible for testing. + // The default interface is intentionally not one of the collection interfaces to force them to be convertible for testing. [default] interface Windows.Foundation.IClosable; interface Windows.Foundation.Collections.IVector; interface Windows.Foundation.Collections.IVectorView; @@ -265,7 +265,7 @@ namespace Component runtimeclass FastInputMap { // Don't confuse this for a high-performance map. This is for testing fast-input binding support. - // The default interface is intentionally not one of the collection intefaces to force them to be convertible for testing. + // The default interface is intentionally not one of the collection interfaces to force them to be convertible for testing. [default] interface Windows.Foundation.IClosable; interface Windows.Foundation.Collections.IMap; interface Windows.Foundation.Collections.IMapView; diff --git a/test/old_tests/UnitTests/abi_guard.cpp b/test/old_tests/UnitTests/abi_guard.cpp index 3108baf62..70800323c 100644 --- a/test/old_tests/UnitTests/abi_guard.cpp +++ b/test/old_tests/UnitTests/abi_guard.cpp @@ -12,7 +12,7 @@ using namespace Windows::Foundation; namespace { // - // This implemenetation uses the simplest abi_enter and abi_exit methods. + // This implementation uses the simplest abi_enter and abi_exit methods. // struct A : implements { @@ -60,7 +60,7 @@ namespace } // - // This implemenetation uses the abi_enter but omits the abi_exit method. + // This implementation uses the abi_enter but omits the abi_exit method. // struct B : implements { @@ -102,7 +102,7 @@ namespace } // - // This implemenetation throws from the abi_enter method. + // This implementation throws from the abi_enter method. // struct C : implements { @@ -145,7 +145,7 @@ namespace } // - // This implemenetation provides a nested abi_guard + // This implementation provides a nested abi_guard // struct D : implements { @@ -223,7 +223,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias + // This implementation use an abi_guard type alias // struct E : implements { @@ -275,7 +275,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias that thows + // This implementation use an abi_guard type alias that throws // struct F : implements { diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 979c2aac7..037e16ab7 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -1098,7 +1098,7 @@ TEST_CASE("async, Cancel_IAsyncOperationWithProgress, 2") } // -// These tests confirm the implicit cancelation behavior. The obeservable behavior should be the same as above +// These tests confirm the implicit cancelation behavior. The observable behavior should be the same as above // but the implementation relies on an exception so we confirm that the state changes occur as before. // diff --git a/test/old_tests/UnitTests/delegate.cpp b/test/old_tests/UnitTests/delegate.cpp index ab83a2a65..5951b7bf6 100644 --- a/test/old_tests/UnitTests/delegate.cpp +++ b/test/old_tests/UnitTests/delegate.cpp @@ -680,7 +680,7 @@ TEST_CASE("delegate,MapChangedEventHandler") TEST_CASE("delegate,collection") { // - // Mostly a compiliation test to ensure that we can create collections of delegates. This is a rare corner case that was + // Mostly a compilation test to ensure that we can create collections of delegates. This is a rare corner case that was // previously not working. // diff --git a/test/old_tests/UnitTests/make_self.cpp b/test/old_tests/UnitTests/make_self.cpp index f7c0b1e3e..6ac17a3c0 100644 --- a/test/old_tests/UnitTests/make_self.cpp +++ b/test/old_tests/UnitTests/make_self.cpp @@ -8,7 +8,7 @@ #endif // -// These tests ensure that the make_self function works as expected to provide direct acccess +// These tests ensure that the make_self function works as expected to provide direct access // to an implementation. // // The IMakeSelf IUnknown interface is also tested as this covers an edge case in the implements diff --git a/test/old_tests/UnitTests/marshal.cpp b/test/old_tests/UnitTests/marshal.cpp index e183aa674..b260e7528 100644 --- a/test/old_tests/UnitTests/marshal.cpp +++ b/test/old_tests/UnitTests/marshal.cpp @@ -2,7 +2,7 @@ #include "catch.hpp" // These tests do not attempt to test the FTM itself, but merely to confirm that the presence and -// absence of the non_agile marker does indeed produce the correct reponses from QueryInterface. +// absence of the non_agile marker does indeed produce the correct responses from QueryInterface. // CoMarshalInterfaceXxxx is also used to exercise the code paths. Also, these tests confirm that // the weak reference object inherits the same agility as the source. Although much of this is // tested elsewhere, it was helpful to have these tests as a set. diff --git a/test/old_tests/UnitTests/produce.cpp b/test/old_tests/UnitTests/produce.cpp index 403f0df2b..149466002 100644 --- a/test/old_tests/UnitTests/produce.cpp +++ b/test/old_tests/UnitTests/produce.cpp @@ -4,7 +4,7 @@ // // These tests cover the production of the three core interfaces namely IUnknown, IInspectable, and IActivationFactory. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_async.cpp b/test/old_tests/UnitTests/produce_async.cpp index e37842e12..ed8ee50db 100644 --- a/test/old_tests/UnitTests/produce_async.cpp +++ b/test/old_tests/UnitTests/produce_async.cpp @@ -4,7 +4,7 @@ // // These tests cover the production of the various async interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_map.cpp b/test/old_tests/UnitTests/produce_map.cpp index b456082a4..0c66a1820 100644 --- a/test/old_tests/UnitTests/produce_map.cpp +++ b/test/old_tests/UnitTests/produce_map.cpp @@ -5,7 +5,7 @@ // // These tests cover the production of the various map-related interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_vector.cpp b/test/old_tests/UnitTests/produce_vector.cpp index fbf3d3b84..16111f96d 100644 --- a/test/old_tests/UnitTests/produce_vector.cpp +++ b/test/old_tests/UnitTests/produce_vector.cpp @@ -5,7 +5,7 @@ // // These tests cover the production of the various vector-related interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/struct.cpp b/test/old_tests/UnitTests/struct.cpp index bce62e25d..995f495a4 100644 --- a/test/old_tests/UnitTests/struct.cpp +++ b/test/old_tests/UnitTests/struct.cpp @@ -10,7 +10,7 @@ using namespace Windows::Web::Http; // // This first test ensures that structures with HSTRING fields are projected correctly. // In this case, a suitable interface is provided by the Windows SDK to simplify testing. -// IControlTemplate provides the necessary methods for excercising input and output +// IControlTemplate provides the necessary methods for exercising input and output // patterns for code generation. // @@ -47,7 +47,7 @@ TEST_CASE("struct, TypeName") // // This second test ensures that structures with IReference fields are projected correctly. // In this case, a suitable interface is not available in the Windows SDK so we hand-roll the -// the necessary intput and output patterms for code generation. We also rely on a custom +// the necessary input and output patterns for code generation. We also rely on a custom // implementation of IReference so that we can additionally check that the object is // destroyed correctly. // diff --git a/test/test/abi_guard.cpp b/test/test/abi_guard.cpp index c0244a475..b2931b278 100644 --- a/test/test/abi_guard.cpp +++ b/test/test/abi_guard.cpp @@ -6,7 +6,7 @@ using namespace Windows::Foundation; namespace { // - // This implemenetation uses the simplest abi_enter and abi_exit methods + // This implementation uses the simplest abi_enter and abi_exit methods // struct Simple : implements { @@ -34,7 +34,7 @@ namespace }; // - // This implemenetation uses the abi_enter but omits the abi_exit method + // This implementation uses the abi_enter but omits the abi_exit method // struct OnlyEnter : implements { @@ -56,7 +56,7 @@ namespace }; // - // This implemenetation throws from the abi_enter method + // This implementation throws from the abi_enter method // struct Throwing : implements { @@ -83,7 +83,7 @@ namespace }; // - // This implemenetation provides a nested abi_guard + // This implementation provides a nested abi_guard // struct NestedGuard : implements { @@ -138,7 +138,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias + // This implementation use an abi_guard type alias // struct GuardAlias : implements { @@ -167,7 +167,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias that thows + // This implementation use an abi_guard type alias that throws // struct ThrowAlias : implements { diff --git a/test/test/cmd_reader.cpp b/test/test/cmd_reader.cpp index 731922fd8..a7b9a7ad1 100644 --- a/test/test/cmd_reader.cpp +++ b/test/test/cmd_reader.cpp @@ -122,7 +122,7 @@ TEST_CASE("cmd_reader") REQUIRE_FALSE(args.exists("verbose")); } - // response file #4: really really long path + // response file #4: really, really, long path { const char* argv[] = { "progname", "@respfile.txt" }; const size_t argc = _countof(argv); diff --git a/test/test/thread_pool.cpp b/test/test/thread_pool.cpp index ac75dac18..c55cffe1d 100644 --- a/test/test/thread_pool.cpp +++ b/test/test/thread_pool.cpp @@ -53,7 +53,7 @@ TEST_CASE("thread_pool") uint32_t const stable_counter = test(test_iterations, 1, 1); uint32_t const unstable_counter = test(test_iterations, 10, 10); - // This is determinstic since the queue is single-threaded. + // This is deterministic since the queue is single-threaded. REQUIRE(stable_counter == test_iterations); // This is unlikely to fail since the pool is multi-threaded. diff --git a/test/test_component_base/pch.h b/test/test_component_base/pch.h index e5c39a869..a6f43eada 100644 --- a/test/test_component_base/pch.h +++ b/test/test_component_base/pch.h @@ -4,6 +4,6 @@ #include "winrt/base.h" // get_module_lock will always return true if WINRT_NO_MODULE_LOCK is defined. -// This ensures that if the DLL unecessarily exports DllCanUnloadNow that it +// This ensures that if the DLL unnecessarily exports DllCanUnloadNow that it // will in turn return S_FALSE. static_assert(winrt::get_module_lock()); From a22626ae6f63778aafee7013de655db57ba0839d Mon Sep 17 00:00:00 2001 From: Dependabot Date: Tue, 16 Apr 2024 19:50:15 +0000 Subject: [PATCH 229/305] Merge pull request 10563206 from dependabot/nuget/vsix/Newtonsoft.Json-13.0.1 into master --- vsix/Dev16/vsix.Dev16.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index e9c5d140e..1e89b390b 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -92,6 +92,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + From 4834e605f49b4b70a52398eded2c12b1ca13eb41 Mon Sep 17 00:00:00 2001 From: Felix Patschkowski <49550034+Patschkowski@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:34:26 +0800 Subject: [PATCH 230/305] Changed visibility of `observable_map_base::call_changed` to `protected` --- strings/base_collections_base.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index b2d58f602..db84b1044 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -619,15 +619,17 @@ WINRT_EXPORT namespace winrt call_changed(Windows::Foundation::Collections::CollectionChange::Reset, impl::empty_value()); } - private: - - event> m_changed; + protected: void call_changed(Windows::Foundation::Collections::CollectionChange const change, K const& key) { m_changed(static_cast(*this), make(change, key)); } + private: + + event> m_changed; + struct args : implements> { args(Windows::Foundation::Collections::CollectionChange const change, K const& key) noexcept : From 0deecf1ea4fcc6acd10602e2340e243fcdcf4f47 Mon Sep 17 00:00:00 2001 From: Michael Maltsev <4129781+m417z@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:54:05 +0300 Subject: [PATCH 231/305] Add missing `` to `base_includes.h` (#1427) --- strings/base_includes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/strings/base_includes.h b/strings/base_includes.h index ee22bc0aa..819e3c98f 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include From 2e4bdb05da1fe86080c523a2e00f81d62f209b17 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Thu, 5 Sep 2024 10:22:01 -0700 Subject: [PATCH 232/305] Add NuGet config with public feed (#1433) --- nuget.config | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 nuget.config diff --git a/nuget.config b/nuget.config new file mode 100644 index 000000000..a7584f8d9 --- /dev/null +++ b/nuget.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 64d2a52dd5e5c11df69db2b309e0d0fe8b5a8d09 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Tue, 10 Sep 2024 14:30:54 -0700 Subject: [PATCH 233/305] Update NuGetCommand to use nuget.config (#1434) --- .pipelines/build.yml | 8 ++++++++ .pipelines/jobs/OneBranchBuild.yml | 4 ++++ .pipelines/jobs/OneBranchTest.yml | 2 ++ .pipelines/jobs/OneBranchVsix.yml | 2 ++ 4 files changed, 16 insertions(+) diff --git a/.pipelines/build.yml b/.pipelines/build.yml index 8a7ee5568..b46e36eb9 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -49,6 +49,10 @@ jobs: - task: NuGetCommand@2 displayName: NuGet restore + inputs: + command: 'restore' + feedsToUse: config + nugetConfigPath: NuGet.config - task: CmdLine@2 displayName: Build Tools @@ -322,6 +326,10 @@ jobs: - task: NuGetCommand@2 displayName: NuGet restore + inputs: + command: 'restore' + feedsToUse: config + nugetConfigPath: NuGet.config - task: DownloadPipelineArtifact@1 displayName: Download x86 Artifacts diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index 984530eba..f8ca8cedc 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -51,6 +51,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: VSBuild@1 displayName: Build fast_fwd @@ -72,6 +74,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\natvis\cppwinrtvisualizer.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: VSBuild@1 displayName: Build Component visualizer diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index bba8dac20..307f5e168 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -80,6 +80,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: PowerShell@2 displayName: Remove cppwinrt dependency from test projects diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 3526712eb..b4d23eb44 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -56,6 +56,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\vsix\vsix.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: DownloadPipelineArtifact@2 displayName: 'Download x86 binaries' From c5e0aaeb533735b641c4236b12a7fdf72cda53aa Mon Sep 17 00:00:00 2001 From: Nate Thorn Date: Mon, 16 Sep 2024 13:33:55 -0700 Subject: [PATCH 234/305] Clarify how InitializeComponent works in the template comment (#1435) --- vsix/ItemTemplates/BlankPage/BlankPage.h | 1 + vsix/ItemTemplates/BlankUserControl/BlankUserControl.h | 1 + vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h | 1 + 3 files changed, 3 insertions(+) diff --git a/vsix/ItemTemplates/BlankPage/BlankPage.h b/vsix/ItemTemplates/BlankPage/BlankPage.h index 58c0f3648..4f7b2b0dd 100644 --- a/vsix/ItemTemplates/BlankPage/BlankPage.h +++ b/vsix/ItemTemplates/BlankPage/BlankPage.h @@ -9,6 +9,7 @@ namespace winrt::$rootnamespace$::implementation $safeitemname$() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } diff --git a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h index 0ab08377a..210b99659 100644 --- a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h +++ b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h @@ -13,6 +13,7 @@ namespace winrt::$rootnamespace$::implementation $safeitemname$() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h index 92e0a689d..366ef6614 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h @@ -9,6 +9,7 @@ namespace winrt::$safeprojectname$::implementation MainPage() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } From f9ec1986083a70d2f99d726b06b00a38cb2d1054 Mon Sep 17 00:00:00 2001 From: Duncan Horn <40036384+dunhor@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:15:26 -0700 Subject: [PATCH 235/305] Silence clang-tidy warnings (#1438) --- strings/base_collections_base.h | 44 +++++++++++++++---------------- strings/base_collections_vector.h | 12 ++++----- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index db84b1044..f3ede9ed4 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -108,7 +108,7 @@ WINRT_EXPORT namespace winrt auto First() { // NOTE: iterator's constructor requires shared access - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return make(static_cast(this)); } @@ -161,7 +161,7 @@ WINRT_EXPORT namespace winrt T Current() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); this->check_version(*m_owner); if (m_current == m_end) @@ -174,14 +174,14 @@ WINRT_EXPORT namespace winrt bool HasCurrent() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); this->check_version(*m_owner); return m_current != m_end; } bool MoveNext() { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); if (m_current != m_end) { @@ -193,7 +193,7 @@ WINRT_EXPORT namespace winrt uint32_t GetMany(array_view values) { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); return GetMany(values, typename std::iterator_traits::iterator_category()); } @@ -248,7 +248,7 @@ WINRT_EXPORT namespace winrt { T GetAt(uint32_t const index) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (index >= container_size()) { throw hresult_out_of_bounds(); @@ -259,13 +259,13 @@ WINRT_EXPORT namespace winrt uint32_t Size() const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return container_size(); } bool IndexOf(T const& value, uint32_t& index) const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto first = std::find_if(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end(), [&](auto&& match) { return value == static_cast(*this).unwrap_value(match); @@ -277,7 +277,7 @@ WINRT_EXPORT namespace winrt uint32_t GetMany(uint32_t const startIndex, array_view values) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (startIndex >= container_size()) { return 0; @@ -308,7 +308,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::value_type> oldValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index >= static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -322,7 +322,7 @@ WINRT_EXPORT namespace winrt void InsertAt(uint32_t const index, T const& value) { - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index > static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -336,7 +336,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::value_type> removedValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index >= static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -350,7 +350,7 @@ WINRT_EXPORT namespace winrt void Append(T const& value) { - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); static_cast(*this).get_container().push_back(static_cast(*this).wrap_value(value)); } @@ -359,7 +359,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::value_type> removedValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (static_cast(*this).get_container().empty()) { throw hresult_out_of_bounds(); @@ -374,7 +374,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); } @@ -383,7 +383,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); assign(value.begin(), value.end()); @@ -508,7 +508,7 @@ WINRT_EXPORT namespace winrt { V Lookup(K const& key) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto pair = static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)); if (pair == static_cast(*this).get_container().end()) @@ -521,13 +521,13 @@ WINRT_EXPORT namespace winrt uint32_t Size() const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return static_cast(static_cast(*this).get_container().size()); } bool HasKey(K const& key) const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)) != static_cast(*this).get_container().end(); } @@ -550,7 +550,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::mapped_type> oldValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); auto [itr, added] = static_cast(*this).get_container().emplace(static_cast(*this).wrap_value(key), static_cast(*this).wrap_value(value)); if (!added) @@ -566,7 +566,7 @@ WINRT_EXPORT namespace winrt { typename impl::container_type_t::node_type removedNode; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); auto& container = static_cast(*this).get_container(); auto found = container.find(static_cast(*this).wrap_value(key)); if (found == container.end()) @@ -581,7 +581,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); } diff --git a/strings/base_collections_vector.h b/strings/base_collections_vector.h index ff0ad6bec..cef7ef2d3 100644 --- a/strings/base_collections_vector.h +++ b/strings/base_collections_vector.h @@ -82,7 +82,7 @@ namespace winrt::impl operator wfc::IIterator() { - auto guard = container->acquire_shared(); + [[maybe_unused]] auto guard = container->acquire_shared(); return make(container); } }; @@ -141,7 +141,7 @@ namespace winrt::impl uint32_t GetMany(uint32_t const startIndex, array_view values) const { - auto guard = this->acquire_shared(); + [[maybe_unused]] auto guard = this->acquire_shared(); if (startIndex >= m_values.size()) { return 0; @@ -239,7 +239,7 @@ namespace winrt::impl Windows::Foundation::IInspectable Current() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); check_version(*m_owner); if (m_current == m_end) { @@ -251,14 +251,14 @@ namespace winrt::impl bool HasCurrent() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); check_version(*m_owner); return m_current != m_end; } bool MoveNext() { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); if (m_current != m_end) { @@ -270,7 +270,7 @@ namespace winrt::impl uint32_t GetMany(array_view values) { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); From 2744f5cc706a8060ebe2d50a37eed190d7802c47 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 29 Oct 2024 14:40:36 -0700 Subject: [PATCH 236/305] Value-init fields of WinRT structs (#1443) --- cppwinrt/code_writers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 3c77269cd..44b889b81 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2716,7 +2716,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable static void write_struct_field(writer& w, std::pair const& field) { - w.write(" @ %;\n", + w.write(" @ % {};\n", field.second, field.first); } From b82340f3fce1ee9bbcc13151f6f74c374d03f24d Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Wed, 30 Oct 2024 09:54:35 -0700 Subject: [PATCH 237/305] Bug: Projected winrt::consume_ methods will nullptr crash if the underlying QueryInterface call fails (#1442) # Why is this change being made? The generated projection code for interfaces that the metadata declares as required for a runtimeclass assume that QueryInterface never fails. Assuming the metadata is correct in the first place, this is a valid assumption for inproc calls. However, for cross-process calls the QI can fail even if the metadata is correct and the class really does implement all of the required interfaces. It can fail with E_ACCESSDENIED and a variety of other RPC error codes. When this happens there is a nullptr crash in the generated consume method. This can be very painful to debug because the HRESULT is lost by the time it crashes. # Briefly summarize what changed This set of changes fixes the crash by detecting the QueryInterface error and throwing an exception when that occurs during one of these required casts. The try_as method was changed to capture COM error context when the QI fails. The code gen surrounding WINRT_IMPL_STUB was changed to save the result into a temporary variable and then pass it to a new check_cast_result method. check_cast_result is marked noinline so that the binary size impact of throwing exceptions is limited to a single function instead of inlining into high-volume generated code. If the cast succeeded then nothing happens. If the cast failed, returning null, then the stored COM exception is retrieved. Assuming it is available the HRESULT is pulled out of it and it is thrown. This then propagates like any other exception. Callers are free to try and catch it or let it go uncaught and crash. Now they have the choice. I also added a new file of test code that exercises this code path. The test_component IDL declares a runtimeclass that implements IStringable. And then the implementation fails to implement IStringable. When ToString is called on this object it hits the failure path. The cppwinrt code gen will not allow this to happen so I had to directly use winrt::implements. # How was this change tested? Besides the new test cases I also wrote a little console app that crashes this way. I built and ran it using the latest stable cppwinrt as well as my private new one. As expected the debugger blame is far more useful with these changes. --- cppwinrt.sln | 3 + cppwinrt/code_writers.h | 20 +- scratch/scratch.vcxproj | 255 ++-------------------- strings/base_error.h | 22 ++ strings/base_extern.h | 3 + strings/base_windows.h | 6 +- test/test/missing_required_interfaces.cpp | 25 +++ test/test/test.vcxproj | 1 + test/test_component/test_component.idl | 7 + 9 files changed, 106 insertions(+), 236 deletions(-) create mode 100644 test/test/missing_required_interfaces.cpp diff --git a/cppwinrt.sln b/cppwinrt.sln index 43e96ffab..e2ac95942 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -88,6 +88,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fast_fwd", "fast_fwd\fast_fwd.vcxproj", "{A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scratch", "scratch\scratch.vcxproj", "{E893622C-47DE-4F83-B422-0A26711590A4}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_none", "test\test_module_lock_none\test_module_lock_none.vcxproj", "{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}" ProjectSection(ProjectDependencies) = postProject diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 44b889b81..0e516b528 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1129,9 +1129,16 @@ namespace cppwinrt if (is_remove_overload(method)) { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker + // + // The `noexcept` versions will crash if check_cast_result throws but that is no different than previous + // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate + // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% - WINRT_IMPL_SHIM(%)->%(%);% + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + abiType->%(%);% } )"; } @@ -1139,7 +1146,10 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const noexcept {% - WINRT_VERIFY_(0, WINRT_IMPL_SHIM(%)->%(%));% + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + WINRT_VERIFY_(0, abiType->%(%));% } )"; } @@ -1148,7 +1158,10 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const {% - check_hresult(WINRT_IMPL_SHIM(%)->%(%));% + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + check_hresult(abiType->%(%));% } )"; } @@ -1161,6 +1174,7 @@ namespace cppwinrt bind(signature), bind(signature, false), type, + type, get_abi_name(method), bind(signature), bind(signature)); diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 4a26617b4..45122c13d 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -35,277 +36,67 @@ + true + true + true + true 16.0 {E893622C-47DE-4F83-B422-0A26711590A4} scratch scratch - - - - Application - true - - - Application - true - - Application - true + + ..\_build\$(Platform)\$(Configuration) + false - - Application - false - true - - - Application - false - true - - - Application - false - true - - - Application + + true - - Application + false true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded - - - Console - true - true - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - + - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug + $(OutputPath);Generated Files; Console - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - + MaxSpeed true true - $(OutputPath);Generated Files;..\..\..\library NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) MultiThreaded - Console true true - - - - - - - - - + - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded - - - Console - true - true - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded + Disabled + _MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug - - Console - true - true - - - - - - - - - - NotUsing - Use - Use - Use - Use - Use - Use - Use - Use + Use - Create - Create - Create - Create - Create - Create - Create - Create + Create + + + diff --git a/strings/base_error.h b/strings/base_error.h index 6e0aa103a..8a3a3a088 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -546,6 +546,28 @@ namespace winrt::impl } return result; } + + template + WINRT_IMPL_NOINLINE void check_cast_result(T* from WINRT_IMPL_SOURCE_LOCATION_ARGS) + { + if (!from) + { + com_ptr restrictedError; + if (WINRT_IMPL_GetRestrictedErrorInfo(restrictedError.put_void()) == 0) + { + WINRT_IMPL_SetRestrictedErrorInfo(restrictedError.get()); + + int32_t code; + impl::bstr_handle description; + impl::bstr_handle restrictedDescription; + impl::bstr_handle capabilitySid; + if (restrictedError->GetErrorDetails(description.put(), &code, restrictedDescription.put(), capabilitySid.put()) == 0) + { + throw hresult_error(code, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + } + } + } + } } #undef WINRT_IMPL_RETURNADDRESS diff --git a/strings/base_extern.h b/strings/base_extern.h index 92872d416..c0e83e75a 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -29,8 +29,11 @@ extern "C" int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); + int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); + int32_t __stdcall WINRT_IMPL_GetRestrictedErrorInfo(void**) noexcept WINRT_IMPL_LINK(GetRestrictedErrorInfo, 4); + int32_t __stdcall WINRT_IMPL_SetRestrictedErrorInfo(void*) noexcept WINRT_IMPL_LINK(SetRestrictedErrorInfo, 4); void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); diff --git a/strings/base_windows.h b/strings/base_windows.h index 41030d368..f5230e1c8 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -128,7 +128,11 @@ namespace winrt::impl } void* result{}; - ptr->QueryInterface(guid_of(), &result); + hresult code = ptr->QueryInterface(guid_of(), &result); + if (code < 0) + { + WINRT_IMPL_RoCaptureErrorContext(code); + } return wrap_as_result(result); } } diff --git a/test/test/missing_required_interfaces.cpp b/test/test/missing_required_interfaces.cpp new file mode 100644 index 000000000..237e4ff41 --- /dev/null +++ b/test/test/missing_required_interfaces.cpp @@ -0,0 +1,25 @@ +#include "pch.h" + +// Unset lean and mean so we can implement a type from the test_component namespace +#undef WINRT_LEAN_AND_MEAN +#include + +namespace +{ + struct LiesAboutInheritance : public winrt::implements + { + LiesAboutInheritance() = default; + void StubMethod() {} + }; +} + +TEST_CASE("missing_required_interfaces") +{ + auto lies = winrt::make_self().as(); + REQUIRE(lies); + REQUIRE_NOTHROW(lies.StubMethod()); + + // The IStringable::ToString method does not exist on this type. In previous versions of cppwinrt + // this line would crash with a nullptr deference. It now throws an exception. + REQUIRE_THROWS_AS(lies.ToString(), winrt::hresult_error); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index b75f2e219..a82465149 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -387,6 +387,7 @@ NotUsing + NotUsing NotUsing diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index fb7444889..a027c394c 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -163,6 +163,13 @@ namespace test_component static void StaticMethodWithAsyncReturn(); } + // This class declares that it implements another interface but under the covers it actually does + // not. This allows us to test the behavior when QI's that should not fail, do fail. + runtimeclass LiesAboutInheritance : Windows.Foundation.IStringable + { + void StubMethod(); + } + namespace Structs { struct All From e53db0f9f6ca8b399a521b284f1ebea65df01d94 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:53:42 -0800 Subject: [PATCH 238/305] WINRT_SOURCE_LOCATION has ODR checks that prevent mixing cpp17 and cpp20 static libraries (#1444) Why is this change being made? Someone is trying to upgrade the cppwinrt version used by a large project that has many static libraries using cppwinrt. Some binaries in that project are mixing static libs with different cpp language versions. (This seems like not a great idea generally but it is the state of the world so to some degree we have to live with it). In those binaries the ODR checks for cppwinrt source_location usage are breaking the build. For good reason, it is not safe to mix this functionality across language versions. This set of changes is aimed at making that upgrade process easier without losing any useful functionality. Briefly summarize what changed We already have winrt::impl::slim_source_location which is a lot like std::source_location, minus always containing the very impactful FUNCTION data. This type is powered by the same intrinsics as the STL version so it works as well as the STL library. The existence of this class means that we can avoid the ODR violations by always using winrt::impl::slim_source_location. Some new macros are used to control what goes into the constructor. cpp20 code that does not suppress source_location will get valid source information passed in. Code that is cpp17, or suppresses this feature, will have zero's passed in. Furthermore, when compiling as _DEBUG this will also include the FUNCTION data, matching previous behavior. The net result is that there is no more ODR violation because the function signatures are always the same. How was this change tested? build_test_all.cmd for both release and debug. I also created a little project that mixes cpp17 and cpp20 libraries. With the latest public release of cppwinrt this project does not build because of the ODR violations. With these changes it builds and runs as expected. --- strings/base_error.h | 162 ++++++++++++++++++++---------------------- strings/base_macros.h | 125 ++++++++++++++++---------------- strings/base_meta.h | 2 +- 3 files changed, 141 insertions(+), 148 deletions(-) diff --git a/strings/base_error.h b/strings/base_error.h index 8a3a3a088..21010ccb2 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -104,17 +104,17 @@ WINRT_EXPORT namespace winrt return *this; } - explicit hresult_error(hresult const code WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + explicit hresult_error(hresult const code, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { - originate(code, nullptr WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, nullptr, sourceInformation); } - hresult_error(hresult const code, param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { - originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, get_abi(message), sourceInformation); } - hresult_error(hresult const code, take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { com_ptr info; WINRT_IMPL_GetErrorInfo(0, info.put_void()); @@ -144,7 +144,7 @@ WINRT_EXPORT namespace winrt message = impl::trim_hresult_message(legacy.get(), WINRT_IMPL_SysStringLen(legacy.get())); } - originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, get_abi(message), sourceInformation); } } @@ -199,7 +199,7 @@ WINRT_EXPORT namespace winrt private: - void originate(hresult const code, void* message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept + void originate(hresult const code, void* message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept { WINRT_VERIFY(WINRT_IMPL_RoOriginateLanguageException(code, message, nullptr)); @@ -208,11 +208,7 @@ WINRT_EXPORT namespace winrt // information is available on the caller who generated the error. if (winrt_throw_hresult_handler) { -#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), code); -#else - winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), code); -#endif } com_ptr info; @@ -244,104 +240,100 @@ WINRT_EXPORT namespace winrt struct hresult_access_denied : hresult_error { - hresult_access_denied(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_access_denied WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_access_denied(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_access_denied(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_access_denied(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, sourceInformation) {} + hresult_access_denied(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, message, sourceInformation) {} + hresult_access_denied(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi, sourceInformation) {} }; struct hresult_wrong_thread : hresult_error { - hresult_wrong_thread(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_wrong_thread WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_wrong_thread(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_wrong_thread(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_wrong_thread(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, sourceInformation) {} + hresult_wrong_thread(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, message, sourceInformation) {} + hresult_wrong_thread(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi, sourceInformation) {} }; struct hresult_not_implemented : hresult_error { - hresult_not_implemented(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_not_implemented WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_not_implemented(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_not_implemented(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_not_implemented(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, sourceInformation) {} + hresult_not_implemented(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, message, sourceInformation) {} + hresult_not_implemented(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi, sourceInformation) {} }; struct hresult_invalid_argument : hresult_error { - hresult_invalid_argument(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_invalid_argument WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_invalid_argument(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_invalid_argument(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_invalid_argument(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, sourceInformation) {} + hresult_invalid_argument(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, message, sourceInformation) {} + hresult_invalid_argument(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi, sourceInformation) {} }; struct hresult_out_of_bounds : hresult_error { - hresult_out_of_bounds(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_out_of_bounds WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_out_of_bounds(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_out_of_bounds(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_out_of_bounds(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, sourceInformation) {} + hresult_out_of_bounds(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, message, sourceInformation) {} + hresult_out_of_bounds(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi, sourceInformation) {} }; struct hresult_no_interface : hresult_error { - hresult_no_interface(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_no_interface WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_no_interface(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_no_interface(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_no_interface(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, sourceInformation) {} + hresult_no_interface(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, message, sourceInformation) {} + hresult_no_interface(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi, sourceInformation) {} }; struct hresult_class_not_available : hresult_error { - hresult_class_not_available(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_available WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_available(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_available(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_available(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, sourceInformation) {} + hresult_class_not_available(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, message, sourceInformation) {} + hresult_class_not_available(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi, sourceInformation) {} }; struct hresult_class_not_registered : hresult_error { - hresult_class_not_registered(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_registered WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_registered(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_registered(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_registered(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, sourceInformation) {} + hresult_class_not_registered(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, message, sourceInformation) {} + hresult_class_not_registered(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi, sourceInformation) {} }; struct hresult_changed_state : hresult_error { - hresult_changed_state(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_changed_state WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_changed_state(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_changed_state(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_changed_state(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, sourceInformation) {} + hresult_changed_state(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, message, sourceInformation) {} + hresult_changed_state(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_method_call : hresult_error { - hresult_illegal_method_call(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_method_call WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_method_call(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_method_call(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_method_call(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, sourceInformation) {} + hresult_illegal_method_call(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, message, sourceInformation) {} + hresult_illegal_method_call(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_state_change : hresult_error { - hresult_illegal_state_change(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_state_change WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_state_change(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_state_change(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_state_change(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, sourceInformation) {} + hresult_illegal_state_change(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, message, sourceInformation) {} + hresult_illegal_state_change(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_delegate_assignment : hresult_error { - hresult_illegal_delegate_assignment(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_delegate_assignment WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_delegate_assignment(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_delegate_assignment(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_delegate_assignment(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, sourceInformation) {} + hresult_illegal_delegate_assignment(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message, sourceInformation) {} + hresult_illegal_delegate_assignment(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi, sourceInformation) {} }; struct hresult_canceled : hresult_error { - hresult_canceled(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_canceled WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_canceled(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_canceled(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_canceled(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, sourceInformation) {} + hresult_canceled(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, message, sourceInformation) {} + hresult_canceled(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi, sourceInformation) {} }; - [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) + [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (winrt_throw_hresult_handler) { -#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), result); -#else - winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), result); -#endif } if (result == impl::error_bad_alloc) @@ -351,70 +343,70 @@ WINRT_EXPORT namespace winrt if (result == impl::error_access_denied) { - throw hresult_access_denied(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_access_denied(take_ownership_from_abi, sourceInformation); } if (result == impl::error_wrong_thread) { - throw hresult_wrong_thread(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_wrong_thread(take_ownership_from_abi, sourceInformation); } if (result == impl::error_not_implemented) { - throw hresult_not_implemented(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_not_implemented(take_ownership_from_abi, sourceInformation); } if (result == impl::error_invalid_argument) { - throw hresult_invalid_argument(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_invalid_argument(take_ownership_from_abi, sourceInformation); } if (result == impl::error_out_of_bounds) { - throw hresult_out_of_bounds(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_out_of_bounds(take_ownership_from_abi, sourceInformation); } if (result == impl::error_no_interface) { - throw hresult_no_interface(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_no_interface(take_ownership_from_abi, sourceInformation); } if (result == impl::error_class_not_available) { - throw hresult_class_not_available(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_class_not_available(take_ownership_from_abi, sourceInformation); } if (result == impl::error_class_not_registered) { - throw hresult_class_not_registered(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_class_not_registered(take_ownership_from_abi, sourceInformation); } if (result == impl::error_changed_state) { - throw hresult_changed_state(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_changed_state(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_method_call) { - throw hresult_illegal_method_call(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_method_call(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_state_change) { - throw hresult_illegal_state_change(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_state_change(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_delegate_assignment) { - throw hresult_illegal_delegate_assignment(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_delegate_assignment(take_ownership_from_abi, sourceInformation); } if (result == impl::error_canceled) { - throw hresult_canceled(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_canceled(take_ownership_from_abi, sourceInformation); } - throw hresult_error(result, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_error(result, take_ownership_from_abi, sourceInformation); } inline WINRT_IMPL_NOINLINE hresult to_hresult() noexcept @@ -475,55 +467,55 @@ WINRT_EXPORT namespace winrt } } - [[noreturn]] inline void throw_last_error(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) + [[noreturn]] inline void throw_last_error(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { - throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError()) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError()), sourceInformation); } - inline hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT) + inline hresult check_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation) { if (result < 0) { - throw_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(result, sourceInformation); } return result; } template - void check_nt(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + void check_nt(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != 0) { - throw_hresult(impl::hresult_from_nt(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_nt(result), sourceInformation); } } template - void check_win32(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + void check_win32(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != 0) { - throw_hresult(impl::hresult_from_win32(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_win32(result), sourceInformation); } } template - T check_bool(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + T check_bool(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!result) { - winrt::throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); + winrt::throw_last_error(sourceInformation); } return result; } template - T* check_pointer(T* pointer WINRT_IMPL_SOURCE_LOCATION_ARGS) + T* check_pointer(T* pointer, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!pointer) { - throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); + throw_last_error(sourceInformation); } return pointer; @@ -538,17 +530,17 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { - inline hresult check_hresult_allow_bounds(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) + inline hresult check_hresult_allow_bounds(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != impl::error_out_of_bounds && result != impl::error_fail && result != impl::error_file_not_found) { - check_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); + check_hresult(result, sourceInformation); } return result; } template - WINRT_IMPL_NOINLINE void check_cast_result(T* from WINRT_IMPL_SOURCE_LOCATION_ARGS) + WINRT_IMPL_NOINLINE void check_cast_result(T* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!from) { @@ -563,7 +555,7 @@ namespace winrt::impl impl::bstr_handle capabilitySid; if (restrictedError->GetErrorDetails(description.put(), &code, restrictedDescription.put(), capabilitySid.put()) == 0) { - throw hresult_error(code, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_error(code, take_ownership_from_abi, sourceInformation); } } } diff --git a/strings/base_macros.h b/strings/base_macros.h index e0167d152..d9e19547e 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -77,14 +77,56 @@ struct IUnknown; typedef struct _GUID GUID; #endif -// std::source_location is a C++20 feature, which is above the C++17 feature floor for cppwinrt. The source location needs -// to be the calling code, not cppwinrt itself, so that it is useful to developers building on top of this library. As a -// result any public-facing method that can result in an error needs a default-constructed source_location argument. Because -// this type does not exist in C++17 we need to use a macro to optionally add parameters and forwarding wherever appropriate. +#if defined(__cpp_consteval) +#define WINRT_IMPL_CONSTEVAL consteval +#else +#define WINRT_IMPL_CONSTEVAL constexpr +#endif + +// The intrinsics (such as __builtin_FILE()) that power std::source_location are also used to power winrt:impl::slim_source_location. +// The source location needs to be for the calling code, not cppwinrt itself, so that it is useful to developers building on top of +// this library. As a result any public-facing method that can result in an error needs a default-constructed slim_source_location +// argument so that it will collect source information from the application code that is calling into cppwinrt. +// +// We do not directly use std::source_location for two reasons: +// 1) std::source_location::function_name() is unavoidable. These strings end up in the final binary, bloating their size. This +// is particularly impactful for code bases that use templates heavily. Cases of 50% binary size growth have been observed. +// 2) std::source_location is a cpp20 feature, which is above the cpp17 feature floor for cppwinrt. By defining our own version +// we can avoid ODR violations in mixed cpp17/cpp20 builds. cpp17 callers will have an ABI that matches cpp20 callers (they +// will just not have useful file/line/function information). // -// Some projects may decide to disable std::source_location support to prevent source code information from ending up in their -// release binaries, or to reduce binary size. Defining WINRT_NO_SOURCE_LOCATION will prevent this feature from activating. -#if defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) +// Some projects may decide that the source information binary size impact is not worth the benefit. Defining WINRT_NO_SOURCE_LOCATION +// will prevent this feature from activating. The slim_source_location type will be forwarded around but it will not include any +// nonzero data. That eliminates the biggest source of binary size overhead. +// +// To help with debugging the __builtin_FUNCTION() intrinsic will be used in _DEBUG builds. This will provide a bit more diagnostic +// value at the cost of binary size. The assumption is that binary size is considered less important in debug builds so this tradeoff +// is acceptable. +// +// The different behavior of the default parameters to winrt::impl::slim_source_location::current() is technically an ODR violation, +// albeit a minor one. There should be no serious consequence to this violation. In practice it means that mixing cpp17/cpp20, +// or mixing WINRT_NO_SOURCE_LOCATION with undefining it, will lead to inconsistent source location information. It may be missing +// when it is expected to be included, or it may be present when it is not expected. The behavior will depend on the linker's choice +// when there are multiple translation units with different options. This violation is tracked by https://github.com/microsoft/cppwinrt/issues/1445. + +#if !defined(__cpp_lib_source_location) || defined(WINRT_NO_SOURCE_LOCATION) +// Case1: cpp17 mode. The source_location intrinsics are not available. +// Case2: The caller has disabled source_location support. Ensure that there is no binary size overhead for line/file/function. +#define WINRT_IMPL_BUILTIN_LINE 0 +#define WINRT_IMPL_BUILTIN_FILE nullptr +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#elif _DEBUG +// cpp20 _DEBUG builds include function information, which has a heavy binary size impact, in addition to file/line. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION __builtin_FUNCTION() +#else +// Release builds in cpp20 mode get file and line information but NOT function information. Function strings +// quickly add up to a substantial binary size impact, especially when templates are heavily used. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#endif namespace winrt::impl { @@ -93,19 +135,23 @@ namespace winrt::impl // have heavy binary size overhead when templates cause many permutations to exist. struct slim_source_location { - [[nodiscard]] static consteval slim_source_location current( - const std::uint_least32_t line = __builtin_LINE(), - const char* const file = __builtin_FILE()) noexcept + [[nodiscard]] static WINRT_IMPL_CONSTEVAL slim_source_location current( + const std::uint_least32_t line = WINRT_IMPL_BUILTIN_LINE, + const char* const file = WINRT_IMPL_BUILTIN_FILE, + const char* const function = WINRT_IMPL_BUILTIN_FUNCTION) noexcept { - return slim_source_location{ line, file }; + return slim_source_location{ line, file, function }; } [[nodiscard]] constexpr slim_source_location() noexcept = default; - [[nodiscard]] constexpr slim_source_location(const std::uint_least32_t line, - const char* const file) noexcept : + [[nodiscard]] constexpr slim_source_location( + const std::uint_least32_t line, + const char* const file, + const char* const function) noexcept : m_line(line), - m_file(file) + m_file(file), + m_function(function) {} [[nodiscard]] constexpr std::uint_least32_t line() const noexcept @@ -118,63 +164,18 @@ namespace winrt::impl return m_file; } - constexpr const char* function_name() const noexcept + [[nodiscard]] constexpr const char* function_name() const noexcept { - // This is intentionally not included. See comment above. - return nullptr; + return m_function; } private: const std::uint_least32_t m_line{}; const char* const m_file{}; + const char* const m_function{}; }; } -// std::source_location includes function_name which can be helpful but creates a lot of binary size impact. Many consumers -// have defined WINRT_NO_SOURCE_LOCATION to prevent this impact, losing the value of source_location. We have defined a -// slim_source_location struct that is equivalent but excludes function_name. This should have the vast majority of the -// usefulness of source_location while having a much smaller binary impact. -// -// When building _DEBUG binary size is not usually much of a concern, so we can use the full source_location type. -#ifdef _DEBUG -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , std::source_location const& sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_ARGS , std::source_location const& sourceInformation = std::source_location::current() -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM std::source_location const& sourceInformation = std::source_location::current() - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation - -#define WINRT_SOURCE_LOCATION_ACTIVE - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true") -#endif // _MSC_VER - -#else // !_DEBUG -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , winrt::impl::slim_source_location const& sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_ARGS , winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation - -#define WINRT_SOURCE_LOCATION_ACTIVE - #ifdef _MSC_VER #pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") #endif // _MSC_VER - -#endif // _DEBUG - -#else -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT -#define WINRT_IMPL_SOURCE_LOCATION_ARGS -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false") -#endif // _MSC_VER -#endif // defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) diff --git a/strings/base_meta.h b/strings/base_meta.h index 2c1796e9c..25deb42ec 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -1,7 +1,7 @@ WINRT_EXPORT namespace winrt { - hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS); + hresult check_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()); hresult to_hresult() noexcept; template From 849498c6176b92264afdda38ed6f2492893ad5bf Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 7 Nov 2024 16:40:49 -0800 Subject: [PATCH 239/305] Latest vpack has an extra cppwinrt folder (#1447) --- .pipelines/OneBranch.Official.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 3c2ffdfcd..5ecc638b6 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -85,10 +85,10 @@ extends: - task: CopyFiles@2 displayName: 'Stage compiler vpack contents' inputs: - SourceFolder: $(Build.SourcesDirectory)/x86 + SourceFolder: $(Build.SourcesDirectory)/x86/cppwinrt Contents: | - cppwinrt/cppwinrt.exe - cppwinrt/cppwinrt.pdb + cppwinrt.exe + cppwinrt.pdb TargetFolder: $(ob_outputDirectory) - job: MSBuild_vpack From d296af6a43a1aabde45f7c9905a304414edcdcd5 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:09:14 -0800 Subject: [PATCH 240/305] Reduce the code size of generated consume methods by skipping casts when the type is already a match (#1448) Why is this change being made? I have been doing some local builds of an internal component against the latest cppwinrt.exe, which includes the fixes in #1442. I have noticed some modest (1%) binary size grown when comparing the April 2024 release and the latest. Using SizeBench to analyze binary size differences I determined that the inlined code gen seems to explain the difference. This change eliminates that increase, at least for the binary I'm testing against, and even shrinks it a bit further. Briefly summarize what changed The various winrt::impl::consume_THING methods get heavily inlined in release builds. The current code gen has some casts for when the types don't match (and is an AddRef/Release when they do match). The small amount of new cast result checking ends up at many call sites and slowly adds up a bit. I think we can do better in the cases where the types already match. This seems to have proven true in practice. Using if constexpr to determine if the type is a match allows us to skip any casts when this is true. In fact that is a net improvement over the original baseline because we don't need to AddRef/Release either. We can directly call the appropriate method. When a cast is necessary the code gen is identical to the previous baseline. The QueryInterface call is unavoidable and so is checking the result. The code writer format string is definitely starting to creak under the weight of many arguments. I don't want to refactor that as part of this PR but it would be good to simplify in the future. Also included is late feedback from the previous PR from @oldnewthing. The check_cast_result method can take void* instead of a template argument because it only null checks it. In my local measurements the optimizer already folded them so it makes no binary size difference but it is still a nice change to take. How was this change tested? Ran the full suite of cppwinrt tests locally. I also debugged into Windows.Foundation.IStringable.ToString for cases where it both is and is not the correct type. They run the expected code paths. I also checked the binary size of a large example to confirm the expected reduction. The disassembly for a Release build similarly matches expectations. --- cppwinrt/code_writers.h | 52 +++++++++++++++++++++++++++++++---------- strings/base_error.h | 3 +-- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 0e516b528..f93279a74 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1135,10 +1135,18 @@ namespace cppwinrt // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% - auto const& castedResult = static_cast<% const&>(static_cast(*this)); - auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); - abiType->%(%);% + if constexpr (!std::is_same_v) + { + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + abiType->%(%); + } + else + { + auto const abiType = *(abi_t<%>**)this; + abiType->%(%); + }% } )"; } @@ -1146,10 +1154,18 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const noexcept {% - auto const& castedResult = static_cast<% const&>(static_cast(*this)); - auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); - WINRT_VERIFY_(0, abiType->%(%));% + if constexpr (!std::is_same_v) + { + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + WINRT_VERIFY_(0, abiType->%(%)); + } + else + { + auto const abiType = *(abi_t<%>**)this; + WINRT_VERIFY_(0, abiType->%(%)); + }% } )"; } @@ -1158,10 +1174,18 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const {% - auto const& castedResult = static_cast<% const&>(static_cast(*this)); - auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); - check_hresult(abiType->%(%));% + if constexpr (!std::is_same_v) + { + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + check_hresult(abiType->%(%)); + } + else + { + auto const abiType = *(abi_t<%>**)this; + check_hresult(abiType->%(%)); + }% } )"; } @@ -1175,6 +1199,10 @@ namespace cppwinrt bind(signature, false), type, type, + type, + get_abi_name(method), + bind(signature), + type, get_abi_name(method), bind(signature), bind(signature)); diff --git a/strings/base_error.h b/strings/base_error.h index 21010ccb2..9b9624277 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -539,8 +539,7 @@ namespace winrt::impl return result; } - template - WINRT_IMPL_NOINLINE void check_cast_result(T* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) + inline WINRT_IMPL_NOINLINE void check_cast_result(void* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!from) { From 8da835950cee482af43e2d457f345a00a413d0b5 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:27:27 -0800 Subject: [PATCH 241/305] try_as casts should not store COM error context; consume method cast checking should use return codes directly (#1450) Why is this change being made? I have been trying to ingest the HEAD of cppwinrt for some large internal projects and one of them had some test failures with the new version. The failures are because there is a try_as cast in their code that fails and is handled fine, but it leaves a COM error context floating around on that thread. Subsequent code fails to originate an error because it sees a context already active on the thread and NOOP'ed. What this boils down to is that try_as should not have a behavioral change to store context when the cast fails. Briefly summarize what changed To address this problem I am taking a PR suggestion from @oldnewthing to have a new try_as_with_reason method that returns both the cast result as well as the HRESULT. The error context logic was only there to smuggle the HRESULT out of a call without an HRESULT return value, so if it is a direct return we don't need that anymore. The new method directly returns the HRESULT so there is no ambiguity. The previous approach relied on a cast operator to call try_as (or just addref when the type is already a match). Thanks to the recent if constexpr code gen change those cases are now separated out. We have a code block where we know a cast is needed so try_as_with_reason can be called unconditionally. The code path where no cast is needed already circumvents this and is nicely unaffected. This also made check_cast_result equiavelnt to check_hresult so it was deleted in favor of just calling check_hresult. How was this change tested? I did local builds of cppwinrt (both Debug and Release) and ran the tests. I am also compiling some large internal projects with it to ensure that there are no obvious breaks or regressions. I am expecting minimal to no binary size impact from this change. --- cppwinrt/code_writers.h | 14 +++++++------- strings/base_error.h | 21 --------------------- strings/base_extern.h | 2 -- strings/base_implements.h | 11 +++++++++++ strings/base_windows.h | 33 +++++++++++++++++++++++++++++---- 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index f93279a74..01f7dea10 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1130,16 +1130,16 @@ namespace cppwinrt { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker // - // The `noexcept` versions will crash if check_cast_result throws but that is no different than previous + // The `noexcept` versions will crash if check_hresult throws but that is no different than previous // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); abiType->%(%); } else @@ -1156,9 +1156,9 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); WINRT_VERIFY_(0, abiType->%(%)); } else @@ -1176,9 +1176,9 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); check_hresult(abiType->%(%)); } else diff --git a/strings/base_error.h b/strings/base_error.h index 9b9624277..85de70f63 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -538,27 +538,6 @@ namespace winrt::impl } return result; } - - inline WINRT_IMPL_NOINLINE void check_cast_result(void* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) - { - if (!from) - { - com_ptr restrictedError; - if (WINRT_IMPL_GetRestrictedErrorInfo(restrictedError.put_void()) == 0) - { - WINRT_IMPL_SetRestrictedErrorInfo(restrictedError.get()); - - int32_t code; - impl::bstr_handle description; - impl::bstr_handle restrictedDescription; - impl::bstr_handle capabilitySid; - if (restrictedError->GetErrorDetails(description.put(), &code, restrictedDescription.put(), capabilitySid.put()) == 0) - { - throw hresult_error(code, take_ownership_from_abi, sourceInformation); - } - } - } - } } #undef WINRT_IMPL_RETURNADDRESS diff --git a/strings/base_extern.h b/strings/base_extern.h index c0e83e75a..2412f9f2c 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -32,8 +32,6 @@ extern "C" int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); - int32_t __stdcall WINRT_IMPL_GetRestrictedErrorInfo(void**) noexcept WINRT_IMPL_LINK(GetRestrictedErrorInfo, 4); - int32_t __stdcall WINRT_IMPL_SetRestrictedErrorInfo(void*) noexcept WINRT_IMPL_LINK(SetRestrictedErrorInfo, 4); void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); diff --git a/strings/base_implements.h b/strings/base_implements.h index d0bb09012..0847f5019 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -792,9 +792,20 @@ namespace winrt::impl { return m_inner.operator bool(); } + + template + friend auto winrt::impl::try_as_with_reason(From ptr) noexcept; + protected: static constexpr bool is_composing = true; Windows::Foundation::IInspectable m_inner; + + private: + template + auto try_as_with_reason() const noexcept + { + return m_inner.try_as_with_reason(); + } }; template diff --git a/strings/base_windows.h b/strings/base_windows.h index f5230e1c8..a67ef0b20 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -128,12 +128,31 @@ namespace winrt::impl } void* result{}; - hresult code = ptr->QueryInterface(guid_of(), &result); - if (code < 0) + ptr->QueryInterface(guid_of(), &result); + return wrap_as_result(result); + } + + template , int> = 0> + std::pair, hresult> try_as_with_reason(From* ptr) noexcept + { +#ifdef WINRT_DIAGNOSTICS + get_diagnostics_info().add_query(); +#endif + + if (!ptr) { - WINRT_IMPL_RoCaptureErrorContext(code); + return { nullptr, 0 }; } - return wrap_as_result(result); + + void* result{}; + hresult code = ptr->QueryInterface(guid_of(), &result); + return { wrap_as_result(result), code }; + } + + template + auto try_as_with_reason(From ptr) noexcept + { + return ptr->template try_as_with_reason(); } } @@ -209,6 +228,12 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return impl::try_as(m_ptr); } + template + auto try_as_with_reason() const noexcept + { + return impl::try_as_with_reason(m_ptr); + } + template void as(To& to) const { From febda5dfa1d5840096e5d94c5f317b770f4cbf86 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:12:21 -0800 Subject: [PATCH 242/305] Try to fix the disabled/failing nuget test build step (#1451) These failures were pointed out yesterday when the CLA policy was stuck. They are not blocking but have seemingly been failing for a long time and the failure is suppressed. The issue seems to be that some of these test projects reference an old NuGet package while also referencing the props/targets that are about to go into the new NuGet package. Double-including essentially the same files twice is what caused the build breaks in these projects. Some projects also had build breaks that seem to be related to a very old Windows SDK minimum version. I increased the floor to 10.0.18362.0 (early 2019; almost 6 years ago) and that fixed the remaining breaks. The random packages.config that downloaded random builds of cppwinrt from 2019 or 2020 have been deleted too. This set of changes aims to fix the build breaks and un-suppress this failure. It now builds locally on my device but I'll need an official PR build to ensure that the GitHub Actions flow is also passing. --- .github/workflows/ci.yml | 5 ----- .../ConsoleApplication1/ConsoleApplication1.vcxproj | 9 --------- test/nuget/ConsoleApplication1/packages.config | 4 ---- .../TestRuntimeComponentCSharp.csproj | 4 ++-- .../packages.config | 4 ---- .../TestStaticLibrary7/TestStaticLibrary7.vcxproj | 11 ++--------- test/nuget/TestStaticLibrary7/packages.config | 4 ---- .../ConsoleApplication/ConsoleApplication.vcxproj | 2 +- .../VC/Windows Universal/BlankApp/BlankApp.vcxproj | 2 +- .../VC/Windows Universal/CoreApp/CoreApp.vcxproj | 2 +- .../StaticLibrary/StaticLibrary.vcxproj | 2 +- .../WindowsRuntimeComponent.vcxproj | 2 +- 12 files changed, 9 insertions(+), 42 deletions(-) delete mode 100644 test/nuget/ConsoleApplication1/packages.config delete mode 100644 test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config delete mode 100644 test/nuget/TestStaticLibrary7/packages.config diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af61bbe99..7f99be8fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -373,11 +373,6 @@ jobs: - name: Run nuget test run: | cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" test\nuget\NugetTest.sln - if ($LastExitCode -ne 0) { - echo "::warning::nuget test failed" - } - # FIXME: This build was failing from the start - exit 0 build-nuget: name: Build nuget package with MSVC diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj index 94248f8a2..15d9a8842 100644 --- a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj +++ b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj @@ -1,6 +1,5 @@ - true @@ -54,7 +53,6 @@ - @@ -121,11 +119,4 @@ - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/test/nuget/ConsoleApplication1/packages.config b/test/nuget/ConsoleApplication1/packages.config deleted file mode 100644 index be196b1fc..000000000 --- a/test/nuget/ConsoleApplication1/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index 869819889..b2a1dfbe8 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -11,8 +11,8 @@ TestRuntimeComponentCSharp en-US UAP - 10.0.18362.0 - 10.0.15063.0 + 10.0.22621.0 + 10.0.18362.0 14 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config b/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config deleted file mode 100644 index 17dbbb252..000000000 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index a8f21c356..3189c7294 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -1,6 +1,6 @@ - + true true @@ -127,13 +127,6 @@ - + - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - diff --git a/test/nuget/TestStaticLibrary7/packages.config b/test/nuget/TestStaticLibrary7/packages.config deleted file mode 100644 index c4867c30b..000000000 --- a/test/nuget/TestStaticLibrary7/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj index ad52af212..f82376473 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj @@ -10,7 +10,7 @@ Win32Proj $safeprojectname$ $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index af2b41932..c270aa038 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -14,7 +14,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index d2f2b002a..bd839b0b2 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -13,7 +13,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index 77cc1e005..accf6d492 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -15,7 +15,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 55a39d0dd..7846860c0 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -14,7 +14,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 From 2aed347fb7b54f1f01e9db53339ad9d2b4305ab9 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:52:31 -0800 Subject: [PATCH 243/305] GitHub Actions workflow cannot build arm32 after updating Windows SDK (#1454) arm32 is not supported anymore by Windows. There has not been a native arm32 OS since before Win11. The wow32 backcompat on arm64 devices to run arm32 programs was removed with Win11 24H2. Most notably, the ability to build arm32 with newer SDKs and toolsets has seemingly been removed. This is now breaking the CI build. The easiest fix is to simply remove arm32 support. --- .pipelines/OneBranch.Official.yml | 7 - .pipelines/build.yml | 18 +- .pipelines/jobs/OneBranchBuild.yml | 2 - .pipelines/jobs/OneBranchNuGet.yml | 8 +- .pipelines/jobs/OneBranchVsix.yml | 6 - Directory.Build.Props | 2 +- README.md | 2 +- build_nuget.cmd | 3 +- build_prior_projection.cmd | 1 - build_projection.cmd | 1 - build_test_all.cmd | 2 - build_vsix.cmd | 3 +- cppwinrt.sln | 86 --------- cppwinrt/cppwinrt.vcxproj | 63 ------- fast_fwd/arm/thunks.asm | 58 ------- fast_fwd/fast_fwd.vcxproj | 16 +- nuget/Microsoft.Windows.CppWinRT.nuspec | 1 - prebuild/prebuild.vcxproj | 47 ----- prepare_versionless_diffs.cmd | 1 - scratch/scratch.vcxproj | 8 - strings/base_activation.h | 8 +- .../ConsoleApplication1.vcxproj | 8 + test/nuget/Directory.Build.props | 2 +- test/nuget/NuGetTest.sln | 156 +++++++---------- test/nuget/TestApp/TestApp.vcxproj | 8 +- .../TestRuntimeComponent1.vcxproj | 8 +- .../TestRuntimeComponent2.vcxproj | 8 +- .../TestRuntimeComponent3.vcxproj | 8 +- .../TestRuntimeComponentCSharp.csproj | 18 -- .../TestRuntimeComponentCX.vcxproj | 54 ------ ...entCXReferencingWinRTStaticLibrary.vcxproj | 61 ------- .../TestRuntimeComponentEmpty.vcxproj | 8 +- ...untimeComponentNamespaceUnderscore.vcxproj | 8 +- .../TestStaticLibrary1.vcxproj | 20 +-- .../TestStaticLibrary2.vcxproj | 20 +-- .../TestStaticLibrary3.vcxproj | 20 +-- .../TestStaticLibrary4.vcxproj | 24 +-- .../TestStaticLibrary5.vcxproj | 24 +-- .../TestStaticLibrary6.vcxproj | 24 +-- .../TestStaticLibrary7.vcxproj | 8 +- test/old_tests/Component/Component.vcxproj | 120 ------------- test/old_tests/Composable/Composable.vcxproj | 118 ------------- test/old_tests/UnitTests/Tests.vcxproj | 63 ------- test/test/test.vcxproj | 77 --------- test/test_component/test_component.vcxproj | 135 --------------- .../test_component_base.vcxproj | 161 ----------------- .../test_component_derived.vcxproj | 163 ------------------ .../test_component_fast.vcxproj | 163 ------------------ .../test_component_folders.vcxproj | 161 ----------------- .../test_component_no_pch.vcxproj | 163 ------------------ test/test_cpp20/test_cpp20.vcxproj | 65 ------- .../test_cpp20_no_sourcelocation.vcxproj | 65 ------- test/test_fast/test_fast.vcxproj | 65 ------- test/test_fast_fwd/test_fast_fwd.vcxproj | 66 ------- .../test_module_lock_custom.vcxproj | 65 ------- .../test_module_lock_none.vcxproj | 65 ------- test/test_slow/test_slow.vcxproj | 63 ------- .../BlankApp/BlankApp.vcxproj | 8 - .../Windows Universal/CoreApp/CoreApp.vcxproj | 8 - .../StaticLibrary/StaticLibrary.vcxproj | 8 - .../WindowsRuntimeComponent.vcxproj | 8 - 61 files changed, 172 insertions(+), 2468 deletions(-) delete mode 100644 fast_fwd/arm/thunks.asm diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 5ecc638b6..91e686622 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -130,12 +130,6 @@ extends: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)/x64' - - task: DownloadPipelineArtifact@2 - displayName: 'Download arm artifacts' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)/arm' - - task: DownloadPipelineArtifact@2 displayName: 'Download arm64 artifacts' inputs: @@ -159,7 +153,6 @@ extends: echo d | xcopy $(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib build\native\lib\Win32 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\amd64 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\x64 - echo d | xcopy $(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib build\native\lib\arm echo d | xcopy $(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib build\native\lib\arm64 - stage: NuGet diff --git a/.pipelines/build.yml b/.pipelines/build.yml index b46e36eb9..ebe8ad041 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -31,8 +31,6 @@ jobs: buildPlatform: 'x86' x64: buildPlatform: 'x64' - arm: - buildPlatform: 'arm' arm64: buildPlatform: 'arm64' @@ -169,12 +167,6 @@ jobs: artifactName: $(BuildConfiguration)_x64 downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 displayName: Download arm64 Artifacts inputs: @@ -262,7 +254,7 @@ jobs: - task: CmdLine@2 displayName: Stage MSBuild vpack inputs: - script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" + script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" failOnStderr: true - task: PkgESVPack@12 @@ -343,12 +335,6 @@ jobs: artifactName: $(BuildConfiguration)_x64 downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 displayName: Download arm64 Artifacts inputs: @@ -430,7 +416,7 @@ jobs: command: pack searchPatternPack: nuget/Microsoft.Windows.CppWinRT.nuspec versioningScheme: byBuildNumber - buildProperties: 'target_version=$(Build.BuildNumber);cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' + buildProperties: 'target_version=$(Build.BuildNumber);cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' - task: ComponentGovernanceComponentDetection@0 displayName: Component Detection diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index f8ca8cedc..9053fc21c 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -20,8 +20,6 @@ jobs: BuildPlatform: 'x86' x64: BuildPlatform: 'x64' - arm: - BuildPlatform: 'arm' arm64: BuildPlatform: 'arm64' diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index e2a871114..4d4a7b2ea 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -43,12 +43,6 @@ jobs: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)/x64' - - task: DownloadPipelineArtifact@1 - displayName: 'Download arm artifacts' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)/arm' - - task: DownloadPipelineArtifact@1 displayName: 'Download arm64 artifacts' inputs: @@ -59,7 +53,7 @@ jobs: displayName: 'Build NuGet package' inputs: command: 'custom' - arguments: 'pack nuget/Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory $(ob_outputDirectory)\packages -Properties Configuration=release;cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib;target_version=$(PackageVersion) -Version $(PackageVersion) -Verbosity Detailed' + arguments: 'pack nuget/Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory $(ob_outputDirectory)\packages -Properties Configuration=release;cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib;target_version=$(PackageVersion) -Version $(PackageVersion) -Verbosity Detailed' - task: onebranch.pipeline.signing@1 displayName: '🔒 Onebranch Signing for NuGet package' diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index b4d23eb44..b1a6c8eeb 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -71,12 +71,6 @@ jobs: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)\x64' - - task: DownloadPipelineArtifact@2 - displayName: 'Download arm binaries' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)\arm' - - task: DownloadPipelineArtifact@2 displayName: 'Download arm64 binaries' inputs: diff --git a/Directory.Build.Props b/Directory.Build.Props index 95286d288..cff3f7bda 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -42,7 +42,7 @@ x86 $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ $(OutDir) - $(SolutionDir)_build\x86\$(Configuration)\ + $(SolutionDir)_build\x86\$(Configuration)\ diff --git a/README.md b/README.md index 691809d31..1749fea0c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you really want to build it yourself, the simplest way to do so is to run the * Open the `cppwinrt.sln` solution. * Choose a configuration (x64, x86, Release, Debug) and build projects as needed. -If you are working on an ARM64 or ARM specific issue from an x64 or x86 host, you will need to instead: +If you are working on an ARM64 specific issue from an x64 or x86 host, you will need to instead: * Open the `cppwinrt.sln` solution * Build the x86 version of the "cppwinrt" project first diff --git a/build_nuget.cmd b/build_nuget.cmd index cb950a625..3926e4d0b 100644 --- a/build_nuget.cmd +++ b/build_nuget.cmd @@ -5,9 +5,8 @@ if "%target_version%"=="" set target_version=3.0.0.0 call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -call msbuild /m /p:Configuration=Release,Platform=arm,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=arm64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt -nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%cd%\_build\arm\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib +nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib diff --git a/build_prior_projection.cmd b/build_prior_projection.cmd index c7bdf2f64..9d10f3eaa 100644 --- a/build_prior_projection.cmd +++ b/build_prior_projection.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/build_projection.cmd b/build_projection.cmd index 778fa7aca..140e6c7f8 100644 --- a/build_projection.cmd +++ b/build_projection.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/build_test_all.cmd b/build_test_all.cmd index 89967a04b..4372acfd5 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -18,8 +18,6 @@ call .nuget\nuget.exe restore test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -if "%target_platform%"=="arm" goto :eof - call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Component;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Standalone;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln diff --git a/build_vsix.cmd b/build_vsix.cmd index 111527a48..9908462ef 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -19,7 +19,6 @@ call .nuget\nuget.exe restore test\nuget\NugetTest.sln rem Build fast forwarder libs or all arches call msbuild /m /p:Configuration=%target_configuration%,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=%target_configuration%,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -call msbuild /m /p:Configuration=%target_configuration%,Platform=arm,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=%target_configuration%,Platform=arm64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd rem Build cppwinrt.exe for x86 only @@ -31,7 +30,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=x86,Deployment=%ta call msbuild /p:Configuration=%target_configuration%,Platform=arm64,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln rem Build nuget -.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%this_dir%_build\arm\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed +.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed rem Build vsix call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln diff --git a/cppwinrt.sln b/cppwinrt.sln index e2ac95942..5964f976b 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -134,346 +134,260 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM.ActiveCfg = Debug|ARM - {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM.Build.0 = Debug|ARM {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM64.Build.0 = Debug|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x64.ActiveCfg = Debug|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x64.Build.0 = Debug|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x86.ActiveCfg = Debug|Win32 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x86.Build.0 = Debug|Win32 - {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM.ActiveCfg = Release|ARM - {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM.Build.0 = Release|ARM {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM64.ActiveCfg = Release|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM64.Build.0 = Release|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x64.ActiveCfg = Release|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x64.Build.0 = Release|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x86.ActiveCfg = Release|Win32 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x86.Build.0 = Release|Win32 - {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM.ActiveCfg = Debug|ARM - {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM.Build.0 = Debug|ARM {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM64.Build.0 = Debug|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x64.ActiveCfg = Debug|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x64.Build.0 = Debug|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x86.ActiveCfg = Debug|Win32 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x86.Build.0 = Debug|Win32 - {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM.ActiveCfg = Release|ARM - {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM.Build.0 = Release|ARM {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM64.ActiveCfg = Release|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM64.Build.0 = Release|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x64.ActiveCfg = Release|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x64.Build.0 = Release|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x86.ActiveCfg = Release|Win32 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x86.Build.0 = Release|Win32 - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM.ActiveCfg = Debug|ARM - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM.Build.0 = Debug|ARM {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM64.Build.0 = Debug|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x64.ActiveCfg = Debug|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x64.Build.0 = Debug|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x86.ActiveCfg = Debug|Win32 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x86.Build.0 = Debug|Win32 - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM.ActiveCfg = Release|ARM - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM.Build.0 = Release|ARM {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM64.ActiveCfg = Release|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM64.Build.0 = Release|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x64.ActiveCfg = Release|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x64.Build.0 = Release|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x86.ActiveCfg = Release|Win32 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x86.Build.0 = Release|Win32 - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM.ActiveCfg = Debug|ARM - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM.Build.0 = Debug|ARM {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM64.ActiveCfg = Debug|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM64.Build.0 = Debug|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x64.ActiveCfg = Debug|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x64.Build.0 = Debug|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x86.ActiveCfg = Debug|Win32 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x86.Build.0 = Debug|Win32 - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM.ActiveCfg = Release|ARM - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM.Build.0 = Release|ARM {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM64.ActiveCfg = Release|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM64.Build.0 = Release|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x64.ActiveCfg = Release|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x64.Build.0 = Release|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x86.ActiveCfg = Release|Win32 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x86.Build.0 = Release|Win32 - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM.ActiveCfg = Debug|ARM - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM.Build.0 = Debug|ARM {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM64.ActiveCfg = Debug|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM64.Build.0 = Debug|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x64.ActiveCfg = Debug|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x64.Build.0 = Debug|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x86.ActiveCfg = Debug|Win32 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x86.Build.0 = Debug|Win32 - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM.ActiveCfg = Release|ARM - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM.Build.0 = Release|ARM {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM64.ActiveCfg = Release|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM64.Build.0 = Release|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x64.ActiveCfg = Release|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x64.Build.0 = Release|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x86.ActiveCfg = Release|Win32 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x86.Build.0 = Release|Win32 - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM.ActiveCfg = Debug|ARM - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM.Build.0 = Debug|ARM {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM64.Build.0 = Debug|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x64.ActiveCfg = Debug|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x64.Build.0 = Debug|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x86.ActiveCfg = Debug|Win32 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x86.Build.0 = Debug|Win32 - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM.ActiveCfg = Release|ARM - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM.Build.0 = Release|ARM {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM64.ActiveCfg = Release|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM64.Build.0 = Release|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x64.ActiveCfg = Release|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x64.Build.0 = Release|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x86.ActiveCfg = Release|Win32 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x86.Build.0 = Release|Win32 - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM.ActiveCfg = Debug|ARM - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM.Build.0 = Debug|ARM {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM64.Build.0 = Debug|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x64.ActiveCfg = Debug|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x64.Build.0 = Debug|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x86.ActiveCfg = Debug|Win32 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x86.Build.0 = Debug|Win32 - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM.ActiveCfg = Release|ARM - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM.Build.0 = Release|ARM {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM64.ActiveCfg = Release|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM64.Build.0 = Release|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x64.ActiveCfg = Release|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x64.Build.0 = Release|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x86.ActiveCfg = Release|Win32 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x86.Build.0 = Release|Win32 - {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM.ActiveCfg = Debug|ARM - {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM.Build.0 = Debug|ARM {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM64.ActiveCfg = Debug|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM64.Build.0 = Debug|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x64.ActiveCfg = Debug|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x64.Build.0 = Debug|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x86.ActiveCfg = Debug|Win32 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x86.Build.0 = Debug|Win32 - {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM.ActiveCfg = Release|ARM - {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM.Build.0 = Release|ARM {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM64.ActiveCfg = Release|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM64.Build.0 = Release|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x64.ActiveCfg = Release|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x64.Build.0 = Release|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x86.ActiveCfg = Release|Win32 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x86.Build.0 = Release|Win32 - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM.ActiveCfg = Debug|ARM - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM.Build.0 = Debug|ARM {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM64.Build.0 = Debug|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x64.ActiveCfg = Debug|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x64.Build.0 = Debug|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x86.ActiveCfg = Debug|Win32 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x86.Build.0 = Debug|Win32 - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM.ActiveCfg = Release|ARM - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM.Build.0 = Release|ARM {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM64.ActiveCfg = Release|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM64.Build.0 = Release|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x64.ActiveCfg = Release|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x64.Build.0 = Release|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x86.ActiveCfg = Release|Win32 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x86.Build.0 = Release|Win32 - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM.ActiveCfg = Debug|ARM - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM.Build.0 = Debug|ARM {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM64.ActiveCfg = Debug|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM64.Build.0 = Debug|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x64.ActiveCfg = Debug|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x64.Build.0 = Debug|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x86.ActiveCfg = Debug|Win32 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x86.Build.0 = Debug|Win32 - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM.ActiveCfg = Release|ARM - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM.Build.0 = Release|ARM {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM64.ActiveCfg = Release|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM64.Build.0 = Release|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x64.ActiveCfg = Release|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x64.Build.0 = Release|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x86.ActiveCfg = Release|Win32 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x86.Build.0 = Release|Win32 - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM.ActiveCfg = Debug|ARM - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM.Build.0 = Debug|ARM {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM64.ActiveCfg = Debug|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM64.Build.0 = Debug|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x64.ActiveCfg = Debug|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x64.Build.0 = Debug|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x86.ActiveCfg = Debug|Win32 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x86.Build.0 = Debug|Win32 - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM.ActiveCfg = Release|ARM - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM.Build.0 = Release|ARM {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM64.ActiveCfg = Release|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM64.Build.0 = Release|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x64.ActiveCfg = Release|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x64.Build.0 = Release|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x86.ActiveCfg = Release|Win32 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x86.Build.0 = Release|Win32 - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM.ActiveCfg = Debug|ARM - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM.Build.0 = Debug|ARM {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM64.ActiveCfg = Debug|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM64.Build.0 = Debug|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x64.ActiveCfg = Debug|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x64.Build.0 = Debug|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x86.ActiveCfg = Debug|Win32 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x86.Build.0 = Debug|Win32 - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM.ActiveCfg = Release|ARM - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM.Build.0 = Release|ARM {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM64.ActiveCfg = Release|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM64.Build.0 = Release|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x64.ActiveCfg = Release|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x64.Build.0 = Release|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.ActiveCfg = Release|Win32 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.Build.0 = Release|Win32 - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM.ActiveCfg = Debug|ARM - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM.Build.0 = Debug|ARM {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM64.Build.0 = Debug|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x64.ActiveCfg = Debug|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x64.Build.0 = Debug|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x86.ActiveCfg = Debug|Win32 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x86.Build.0 = Debug|Win32 - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM.ActiveCfg = Release|ARM - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM.Build.0 = Release|ARM {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM64.ActiveCfg = Release|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM64.Build.0 = Release|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x64.ActiveCfg = Release|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x64.Build.0 = Release|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x86.ActiveCfg = Release|Win32 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x86.Build.0 = Release|Win32 - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM.ActiveCfg = Debug|ARM - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM.Build.0 = Debug|ARM {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM64.ActiveCfg = Debug|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM64.Build.0 = Debug|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x64.ActiveCfg = Debug|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x64.Build.0 = Debug|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x86.ActiveCfg = Debug|Win32 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x86.Build.0 = Debug|Win32 - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM.ActiveCfg = Release|ARM - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM.Build.0 = Release|ARM {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM64.ActiveCfg = Release|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM64.Build.0 = Release|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x64.ActiveCfg = Release|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x64.Build.0 = Release|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x86.ActiveCfg = Release|Win32 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x86.Build.0 = Release|Win32 - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM.ActiveCfg = Debug|ARM - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM.Build.0 = Debug|ARM {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM64.ActiveCfg = Debug|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM64.Build.0 = Debug|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x64.ActiveCfg = Debug|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x64.Build.0 = Debug|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x86.ActiveCfg = Debug|Win32 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x86.Build.0 = Debug|Win32 - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM.ActiveCfg = Release|ARM - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM.Build.0 = Release|ARM {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM64.ActiveCfg = Release|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM64.Build.0 = Release|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x64.ActiveCfg = Release|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x64.Build.0 = Release|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x86.ActiveCfg = Release|Win32 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x86.Build.0 = Release|Win32 - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM.ActiveCfg = Debug|ARM - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM.Build.0 = Debug|ARM {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM64.Build.0 = Debug|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x64.ActiveCfg = Debug|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x64.Build.0 = Debug|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x86.ActiveCfg = Debug|Win32 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x86.Build.0 = Debug|Win32 - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM.ActiveCfg = Release|ARM - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM.Build.0 = Release|ARM {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM64.ActiveCfg = Release|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM64.Build.0 = Release|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x64.ActiveCfg = Release|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x64.Build.0 = Release|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x86.ActiveCfg = Release|Win32 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x86.Build.0 = Release|Win32 - {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM.ActiveCfg = Debug|ARM - {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM.Build.0 = Debug|ARM {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM64.Build.0 = Debug|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x64.ActiveCfg = Debug|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x64.Build.0 = Debug|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x86.ActiveCfg = Debug|Win32 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x86.Build.0 = Debug|Win32 - {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM.ActiveCfg = Release|ARM - {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM.Build.0 = Release|ARM {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM64.ActiveCfg = Release|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM64.Build.0 = Release|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x64.ActiveCfg = Release|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x64.Build.0 = Release|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x86.ActiveCfg = Release|Win32 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x86.Build.0 = Release|Win32 - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM.ActiveCfg = Debug|ARM - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM.Build.0 = Debug|ARM {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM64.Build.0 = Debug|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x64.ActiveCfg = Debug|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x64.Build.0 = Debug|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x86.ActiveCfg = Debug|Win32 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x86.Build.0 = Debug|Win32 - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM.ActiveCfg = Release|ARM - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM.Build.0 = Release|ARM {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM64.ActiveCfg = Release|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM64.Build.0 = Release|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x64.ActiveCfg = Release|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x64.Build.0 = Release|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x86.ActiveCfg = Release|Win32 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x86.Build.0 = Release|Win32 - {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM.ActiveCfg = Debug|ARM - {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM.Build.0 = Debug|ARM {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM64.ActiveCfg = Debug|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM64.Build.0 = Debug|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x64.ActiveCfg = Debug|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x64.Build.0 = Debug|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x86.ActiveCfg = Debug|Win32 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x86.Build.0 = Debug|Win32 - {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM.ActiveCfg = Release|ARM - {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM.Build.0 = Release|ARM {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM64.ActiveCfg = Release|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM64.Build.0 = Release|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.ActiveCfg = Release|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.Build.0 = Release|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.ActiveCfg = Release|Win32 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.Build.0 = Release|Win32 - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.Build.0 = Debug|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.ActiveCfg = Debug|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.Build.0 = Debug|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.ActiveCfg = Debug|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.Build.0 = Debug|Win32 - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.ActiveCfg = Release|ARM - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.Build.0 = Release|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.ActiveCfg = Release|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.Build.0 = Release|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.ActiveCfg = Release|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.Build.0 = Release|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.ActiveCfg = Release|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.Build.0 = Release|Win32 - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.ActiveCfg = Debug|ARM - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.Build.0 = Debug|ARM {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.Build.0 = Debug|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.ActiveCfg = Debug|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.Build.0 = Debug|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.ActiveCfg = Debug|Win32 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.Build.0 = Debug|Win32 - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.ActiveCfg = Release|ARM - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.Build.0 = Release|ARM {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.ActiveCfg = Release|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.Build.0 = Release|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.ActiveCfg = Release|x64 diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 46b5836e7..069f8103a 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -14,10 +10,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -132,10 +124,6 @@ Application true - - Application - true - Application true @@ -145,11 +133,6 @@ false true - - Application - false - true - Application false @@ -172,18 +155,12 @@ - - - - - - @@ -211,23 +188,6 @@ - - - Disabled - ..\inc;$(OutputPath);$(WinMDPackageDir); - MultiThreadedDebug - - - Console - - - $(OutputPath)prebuild.exe ..\strings $(OutputPath) - - - - - - Disabled @@ -285,29 +245,6 @@ - - - MaxSpeed - true - true - ..\inc;$(OutputPath);$(WinMDPackageDir); - MultiThreaded - Guard - - - Console - true - true - /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) - - - $(OutputPath)prebuild.exe ..\strings $(OutputPath) - - - - - - MaxSpeed diff --git a/fast_fwd/arm/thunks.asm b/fast_fwd/arm/thunks.asm deleted file mode 100644 index 9010908b6..000000000 --- a/fast_fwd/arm/thunks.asm +++ /dev/null @@ -1,58 +0,0 @@ -; ARM fast forwarder thunk implementations -; Calling convention: https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions - -#include "ksarm.h" - - IMPORT __guard_check_icall_fptr - - TEXTAREA - - CFG_ALIGN - NESTED_ENTRY InvokeForwarder - - ; Save enregistered args and return address - PROLOG_PUSH {r0-r4, lr} - - ; Replace forwarder abi with owner abi - ldr r1, [r0, #4] - str r1, [sp] - - ; Add offset and index (on stack) - ldr r2, [sp, #24] - ldr r3, [r0, #8] - add r2, r2, r3 - - ; Get method address from owner abi vtable - ldr r0, [r1] - ldr r4, [r0, r2, lsl #2] - mov r0, r4 - - ; Verify indirect call target - mov32 r12, __guard_check_icall_fptr - ldr r12, [r12] - blx r12 - - ; Restore method address, return address, and args - mov r12, r4 - EPILOG_POP {r0-r4, lr} - EPILOG_NOP add sp, #4 - - ; Jump to method - EPILOG_NOP bx r12 - - NESTED_END InvokeForwarder - - ; Define thunks - MACRO - WINRT_FF_THUNK $i - LEAF_ENTRY winrt_ff_thunk$i - ; Note: no scratch registers available (r12/IP is used by CFG), must use stack - mov r12, $i - push r12 - ldr pc, =InvokeForwarder - LEAF_END winrt_ff_thunk$i - MEND - -#include "thunks.inc" - - END \ No newline at end of file diff --git a/fast_fwd/fast_fwd.vcxproj b/fast_fwd/fast_fwd.vcxproj index 6d7a42d77..b9452d149 100644 --- a/fast_fwd/fast_fwd.vcxproj +++ b/fast_fwd/fast_fwd.vcxproj @@ -17,14 +17,6 @@ Release x64 - - Debug - ARM - - - Release - ARM - Debug ARM64 @@ -79,16 +71,10 @@ - true + true false !$(Platform_Arm) - - cppwinrt_fast_forwarder - - - cppwinrt_fast_forwarder - cppwinrt_fast_forwarder diff --git a/nuget/Microsoft.Windows.CppWinRT.nuspec b/nuget/Microsoft.Windows.CppWinRT.nuspec index 882931734..a63e08bf9 100644 --- a/nuget/Microsoft.Windows.CppWinRT.nuspec +++ b/nuget/Microsoft.Windows.CppWinRT.nuspec @@ -20,7 +20,6 @@ - diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index 8308ae560..e5fa52565 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -44,10 +36,6 @@ Application true - - Application - true - Application true @@ -57,11 +45,6 @@ false true - - Application - false - true - Application false @@ -84,18 +67,12 @@ - - - - - - @@ -116,16 +93,6 @@ Console - - - Disabled - ..\cppwinrt - MultiThreadedDebug - - - Console - - Disabled @@ -160,20 +127,6 @@ true - - - MaxSpeed - true - true - ..\cppwinrt - MultiThreaded - - - Console - true - true - - MaxSpeed diff --git a/prepare_versionless_diffs.cmd b/prepare_versionless_diffs.cmd index 468645657..05cb6dd0b 100644 --- a/prepare_versionless_diffs.cmd +++ b/prepare_versionless_diffs.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 45122c13d..98ed21948 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -14,10 +10,6 @@ Debug Win32 - - Release - ARM - Release ARM64 diff --git a/strings/base_activation.h b/strings/base_activation.h index bb6be5ca1..be24c6ad9 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -119,10 +119,8 @@ WINRT_EXPORT namespace winrt #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) +#if defined(__GNUC__) && defined(__aarch64__) #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER __asm__ __volatile__ ("dmb ish"); -#elif defined _M_ARM -#define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM_BARRIER_ISH)); #elif defined _M_ARM64 #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM64_BARRIER_ISH)); #endif @@ -135,7 +133,7 @@ namespace winrt::impl int32_t const result = *target; _ReadWriteBarrier(); return result; -#elif defined _M_ARM || defined _M_ARM64 +#elif defined _M_ARM64 #if defined(__GNUC__) int32_t const result = *target; #else @@ -308,7 +306,7 @@ namespace winrt::impl static_assert(std::is_standard_layout_v); -#if !defined _M_IX86 && !defined _M_X64 && !defined _M_ARM && !defined _M_ARM64 +#if !defined _M_IX86 && !defined _M_X64 && !defined _M_ARM64 #error Unsupported architecture: verify that zero-initialization of SLIST_HEADER is still safe #endif diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj index 15d9a8842..819c788d8 100644 --- a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj +++ b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj @@ -13,10 +13,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 diff --git a/test/nuget/Directory.Build.props b/test/nuget/Directory.Build.props index 9f410480b..a54887b1e 100644 --- a/test/nuget/Directory.Build.props +++ b/test/nuget/Directory.Build.props @@ -23,7 +23,7 @@ $(IntDir)Generated Files\ high $(Platform) - x86 + x86 $(SolutionDir)..\..\_build\$(CppWinRTPlatform)\$(Configuration)\ diff --git a/test/nuget/NuGetTest.sln b/test/nuget/NuGetTest.sln index db32e2b61..310b0f252 100644 --- a/test/nuget/NuGetTest.sln +++ b/test/nuget/NuGetTest.sln @@ -49,270 +49,230 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestProxyStub", "TestProxyS EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.ActiveCfg = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.Build.0 = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.Deploy.0 = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.ActiveCfg = Debug|Win32 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.Build.0 = Debug|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.Deploy.0 = Debug|ARM64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.ActiveCfg = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.Build.0 = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.Deploy.0 = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.ActiveCfg = Debug|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.Build.0 = Debug|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.Deploy.0 = Debug|Win32 - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.ActiveCfg = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.Build.0 = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.Deploy.0 = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.ActiveCfg = Release|Win32 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.ActiveCfg = Release|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.Build.0 = Release|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.Deploy.0 = Release|ARM64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.ActiveCfg = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.Build.0 = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.Deploy.0 = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.ActiveCfg = Release|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.Build.0 = Release|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.Deploy.0 = Release|Win32 - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM.ActiveCfg = Debug|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM.Build.0 = Debug|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.ActiveCfg = Debug|Win32 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.Build.0 = Debug|ARM64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x64.ActiveCfg = Debug|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x64.Build.0 = Debug|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x86.ActiveCfg = Debug|Win32 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x86.Build.0 = Debug|Win32 - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM.ActiveCfg = Release|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM.Build.0 = Release|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.ActiveCfg = Release|Win32 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.ActiveCfg = Release|ARM64 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.Build.0 = Release|ARM64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x64.ActiveCfg = Release|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x64.Build.0 = Release|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x86.ActiveCfg = Release|Win32 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x86.Build.0 = Release|Win32 - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM.ActiveCfg = Debug|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM.Build.0 = Debug|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.ActiveCfg = Debug|Win32 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.Build.0 = Debug|ARM64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x64.ActiveCfg = Debug|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x64.Build.0 = Debug|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x86.ActiveCfg = Debug|Win32 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x86.Build.0 = Debug|Win32 - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM.ActiveCfg = Release|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM.Build.0 = Release|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.ActiveCfg = Release|Win32 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.ActiveCfg = Release|ARM64 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.Build.0 = Release|ARM64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x64.ActiveCfg = Release|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x64.Build.0 = Release|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x86.ActiveCfg = Release|Win32 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x86.Build.0 = Release|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM.ActiveCfg = Debug|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.ActiveCfg = Debug|Win32 + {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.Build.0 = Debug|ARM64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x64.ActiveCfg = Debug|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x64.Build.0 = Debug|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x86.ActiveCfg = Debug|Win32 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x86.Build.0 = Debug|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM.ActiveCfg = Release|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.ActiveCfg = Release|Win32 + {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.ActiveCfg = Release|ARM64 + {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.Build.0 = Release|ARM64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x64.ActiveCfg = Release|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x64.Build.0 = Release|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x86.ActiveCfg = Release|Win32 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x86.Build.0 = Release|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM.ActiveCfg = Debug|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.ActiveCfg = Debug|Win32 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.Build.0 = Debug|ARM64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x64.ActiveCfg = Debug|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x64.Build.0 = Debug|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x86.ActiveCfg = Debug|Win32 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x86.Build.0 = Debug|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM.ActiveCfg = Release|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.ActiveCfg = Release|Win32 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.ActiveCfg = Release|ARM64 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.Build.0 = Release|ARM64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x64.ActiveCfg = Release|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x64.Build.0 = Release|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x86.ActiveCfg = Release|Win32 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x86.Build.0 = Release|Win32 - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM.ActiveCfg = Debug|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM.Build.0 = Debug|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.ActiveCfg = Debug|Win32 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.Build.0 = Debug|ARM64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x64.ActiveCfg = Debug|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x64.Build.0 = Debug|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x86.ActiveCfg = Debug|Win32 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x86.Build.0 = Debug|Win32 - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM.ActiveCfg = Release|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM.Build.0 = Release|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.ActiveCfg = Release|Win32 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.ActiveCfg = Release|ARM64 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.Build.0 = Release|ARM64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x64.ActiveCfg = Release|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x64.Build.0 = Release|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x86.ActiveCfg = Release|Win32 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x86.Build.0 = Release|Win32 - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM.ActiveCfg = Debug|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM.Build.0 = Debug|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.ActiveCfg = Debug|Win32 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.Build.0 = Debug|ARM64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x64.ActiveCfg = Debug|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x64.Build.0 = Debug|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x86.ActiveCfg = Debug|Win32 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x86.Build.0 = Debug|Win32 - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM.ActiveCfg = Release|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM.Build.0 = Release|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.ActiveCfg = Release|Win32 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.ActiveCfg = Release|ARM64 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.Build.0 = Release|ARM64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x64.ActiveCfg = Release|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x64.Build.0 = Release|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x86.ActiveCfg = Release|Win32 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x86.Build.0 = Release|Win32 - {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM.ActiveCfg = Debug|ARM - {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM.Build.0 = Debug|ARM {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM64.ActiveCfg = Debug|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM64.Build.0 = Debug|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x64.ActiveCfg = Debug|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x64.Build.0 = Debug|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x86.ActiveCfg = Debug|Win32 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x86.Build.0 = Debug|Win32 - {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM.ActiveCfg = Release|ARM - {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM.Build.0 = Release|ARM {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM64.ActiveCfg = Release|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM64.Build.0 = Release|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x64.ActiveCfg = Release|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x64.Build.0 = Release|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x86.ActiveCfg = Release|Win32 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x86.Build.0 = Release|Win32 - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM.ActiveCfg = Debug|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM.Build.0 = Debug|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.ActiveCfg = Debug|Win32 + {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.Build.0 = Debug|ARM64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x64.ActiveCfg = Debug|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x64.Build.0 = Debug|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x86.ActiveCfg = Debug|Win32 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x86.Build.0 = Debug|Win32 - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM.ActiveCfg = Release|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM.Build.0 = Release|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.ActiveCfg = Release|Win32 + {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.ActiveCfg = Release|ARM64 + {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.Build.0 = Release|ARM64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x64.ActiveCfg = Release|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x64.Build.0 = Release|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x86.ActiveCfg = Release|Win32 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x86.Build.0 = Release|Win32 - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM.ActiveCfg = Debug|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM.Build.0 = Debug|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.ActiveCfg = Debug|Win32 + {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.Build.0 = Debug|ARM64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x64.ActiveCfg = Debug|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x64.Build.0 = Debug|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x86.ActiveCfg = Debug|Win32 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x86.Build.0 = Debug|Win32 - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM.ActiveCfg = Release|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM.Build.0 = Release|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.ActiveCfg = Release|Win32 + {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.ActiveCfg = Release|ARM64 + {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.Build.0 = Release|ARM64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x64.ActiveCfg = Release|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x64.Build.0 = Release|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x86.ActiveCfg = Release|Win32 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x86.Build.0 = Release|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM.ActiveCfg = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM.Build.0 = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.ActiveCfg = Debug|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.Build.0 = Debug|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x64.ActiveCfg = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x64.Build.0 = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x86.ActiveCfg = Debug|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x86.Build.0 = Debug|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM.ActiveCfg = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM.Build.0 = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.ActiveCfg = Release|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.ActiveCfg = Release|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.Build.0 = Release|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x64.ActiveCfg = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x64.Build.0 = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x86.ActiveCfg = Release|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x86.Build.0 = Release|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM.ActiveCfg = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM.Build.0 = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.ActiveCfg = Debug|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.Build.0 = Debug|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x64.ActiveCfg = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x64.Build.0 = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x86.ActiveCfg = Debug|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x86.Build.0 = Debug|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM.ActiveCfg = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM.Build.0 = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.ActiveCfg = Release|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.ActiveCfg = Release|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.Build.0 = Release|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x64.ActiveCfg = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x64.Build.0 = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x86.ActiveCfg = Release|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x86.Build.0 = Release|Win32 - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM.ActiveCfg = Debug|ARM - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM.Build.0 = Debug|ARM {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM64.Build.0 = Debug|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x64.ActiveCfg = Debug|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x64.Build.0 = Debug|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x86.ActiveCfg = Debug|x86 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x86.Build.0 = Debug|x86 - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM.ActiveCfg = Release|ARM - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM.Build.0 = Release|ARM {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM64.ActiveCfg = Release|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM64.Build.0 = Release|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x64.ActiveCfg = Release|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x64.Build.0 = Release|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x86.ActiveCfg = Release|x86 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x86.Build.0 = Release|x86 - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM.ActiveCfg = Debug|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM.Build.0 = Debug|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.ActiveCfg = Debug|Win32 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.Build.0 = Debug|ARM64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x64.ActiveCfg = Debug|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x64.Build.0 = Debug|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x86.ActiveCfg = Debug|Win32 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x86.Build.0 = Debug|Win32 - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM.ActiveCfg = Release|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM.Build.0 = Release|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.ActiveCfg = Release|Win32 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.ActiveCfg = Release|ARM64 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.Build.0 = Release|ARM64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x64.ActiveCfg = Release|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x64.Build.0 = Release|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x86.ActiveCfg = Release|Win32 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x86.Build.0 = Release|Win32 - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM.ActiveCfg = Debug|ARM - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM.Build.0 = Debug|ARM {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM64.Build.0 = Debug|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x64.ActiveCfg = Debug|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x64.Build.0 = Debug|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x86.ActiveCfg = Debug|Win32 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x86.Build.0 = Debug|Win32 - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM.ActiveCfg = Release|ARM - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM.Build.0 = Release|ARM {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM64.ActiveCfg = Release|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM64.Build.0 = Release|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x64.ActiveCfg = Release|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x64.Build.0 = Release|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x86.ActiveCfg = Release|Win32 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x86.Build.0 = Release|Win32 - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM.ActiveCfg = Debug|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM.Build.0 = Debug|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.ActiveCfg = Debug|Win32 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.Build.0 = Debug|ARM64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x64.ActiveCfg = Debug|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x64.Build.0 = Debug|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x86.ActiveCfg = Debug|Win32 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x86.Build.0 = Debug|Win32 - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM.ActiveCfg = Release|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM.Build.0 = Release|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.ActiveCfg = Release|Win32 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.ActiveCfg = Release|ARM64 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.Build.0 = Release|ARM64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x64.ActiveCfg = Release|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x64.Build.0 = Release|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x86.ActiveCfg = Release|Win32 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x86.Build.0 = Release|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM.ActiveCfg = Debug|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.ActiveCfg = Debug|Win32 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.Build.0 = Debug|ARM64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x64.ActiveCfg = Debug|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x64.Build.0 = Debug|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x86.ActiveCfg = Debug|Win32 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x86.Build.0 = Debug|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM.ActiveCfg = Release|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.ActiveCfg = Release|Win32 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.ActiveCfg = Release|ARM64 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.Build.0 = Release|ARM64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x64.ActiveCfg = Release|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x64.Build.0 = Release|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x86.ActiveCfg = Release|Win32 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x86.Build.0 = Release|Win32 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM.ActiveCfg = Debug|x64 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM.Build.0 = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM64.ActiveCfg = Debug|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM64.Build.0 = Debug|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x64.ActiveCfg = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x64.Build.0 = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x86.ActiveCfg = Debug|Win32 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x86.Build.0 = Debug|Win32 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM.ActiveCfg = Release|x64 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM.Build.0 = Release|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM64.ActiveCfg = Release|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM64.Build.0 = Release|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x64.ActiveCfg = Release|x64 diff --git a/test/nuget/TestApp/TestApp.vcxproj b/test/nuget/TestApp/TestApp.vcxproj index 582b95103..84029a4c9 100644 --- a/test/nuget/TestApp/TestApp.vcxproj +++ b/test/nuget/TestApp/TestApp.vcxproj @@ -16,9 +16,9 @@ - + Debug - ARM + ARM64 Debug @@ -28,9 +28,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj index 7827c2b21..1b7621ea0 100644 --- a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj +++ b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj @@ -16,9 +16,9 @@ - + Debug - ARM + ARM64 Debug @@ -28,9 +28,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj index eb12311c1..48f9acfb0 100644 --- a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj +++ b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj index 24d061de0..8a876e601 100644 --- a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj +++ b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index b2a1dfbe8..57f14194d 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -36,24 +36,6 @@ false prompt - - ARM - true - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - false - prompt - - - ARM - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - false - prompt - ARM64 true diff --git a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj index 97b5c5613..237b9fcf3 100644 --- a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj +++ b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -18,10 +14,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -69,12 +61,6 @@ - - - - - - @@ -95,12 +81,6 @@ false - - false - - - false - false @@ -145,38 +125,6 @@ false - - - Use - _WINRT_DLL;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - true - - - Console - false - - - - - Use - _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - true - - - Console - false - - Use @@ -251,8 +199,6 @@ Create Create Create - Create - Create Create Create diff --git a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj index 6131345a9..68b71c94e 100644 --- a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj +++ b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -18,10 +14,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -51,10 +43,6 @@ DynamicLibrary true - - DynamicLibrary - true - DynamicLibrary true @@ -68,11 +56,6 @@ false true - - DynamicLibrary - false - true - DynamicLibrary false @@ -94,12 +77,6 @@ - - - - - - @@ -120,12 +97,6 @@ false - - false - - - false - false @@ -168,36 +139,6 @@ false - - - Use - _WINRT_DLL;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - - - Console - false - - - - - Use - _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - - - Console - false - - Use @@ -268,8 +209,6 @@ Create Create Create - Create - Create Create Create diff --git a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj index 66a6713df..7572238eb 100644 --- a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj +++ b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj index b07497f7f..693a97596 100644 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj +++ b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj index 679f4b60c..a34e7429c 100644 --- a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj +++ b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -111,7 +111,7 @@ true - + Use Level4 @@ -170,7 +170,7 @@ true - + Use Level4 @@ -202,10 +202,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary1Class.idl diff --git a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj index cb8352c96..5f3ee5220 100644 --- a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj +++ b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -111,7 +111,7 @@ true - + Use Level4 @@ -170,7 +170,7 @@ true - + Use Level4 @@ -202,10 +202,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary2Class.idl diff --git a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj index 8b2d75f40..c79a847a3 100644 --- a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj +++ b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -111,7 +111,7 @@ true - + Use Level4 @@ -170,7 +170,7 @@ true - + Use Level4 @@ -202,10 +202,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary3Class.idl diff --git a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj index 36fcfb1be..b3efe02c4 100644 --- a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj +++ b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -121,7 +121,7 @@ false - + Use false @@ -133,7 +133,7 @@ false - + Use false @@ -181,10 +181,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj index e088b38f8..bfc6db45c 100644 --- a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj +++ b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -121,7 +121,7 @@ false - + Use false @@ -133,7 +133,7 @@ false - + Use false @@ -181,10 +181,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj index 8cf328f99..89a0e55c9 100644 --- a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj +++ b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -121,7 +121,7 @@ false - + Use false @@ -133,7 +133,7 @@ false - + Use false @@ -185,10 +185,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index 3189c7294..0fdf11744 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index 9af296c51..dbc55f2d3 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -17,10 +13,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -67,12 +54,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -122,12 +97,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -140,12 +109,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -210,42 +173,6 @@ - - - false - $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files - false - MultiThreadedDebug - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - - - Console - false - module.def - true - - - - - - - - - ..\Composable - - - - - - - - - - - - - false @@ -315,41 +242,6 @@ - - - false - $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files - MultiThreaded - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - - - Console - false - module.def - true - - - - - - - - - ..\Composable - - - - - - - - - - - - - false @@ -478,50 +370,38 @@ $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd true - true true true - true true true true $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h ..\Composable - ..\Composable ..\Composable ..\Composable - ..\Composable ..\Composable ..\Composable ..\Composable true - true true true - true true true true diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index d13d779b9..3b78edce4 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -17,10 +13,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -67,12 +54,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -122,12 +97,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -140,12 +109,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -210,42 +173,6 @@ - - - false - $(ProjectDir);$(OutDir);Generated Files - false - MultiThreadedDebug - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - precomp.hpp - - - Console - false - module.def - true - - - - - - - - - - - - - - - - - - - - - false @@ -315,41 +242,6 @@ - - - false - $(ProjectDir);$(OutDir);Generated Files - MultiThreaded - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - precomp.hpp - - - Console - false - module.def - true - - - - - - - - - - - - - - - - - - - - - false @@ -470,42 +362,32 @@ $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd true - true true true - true true true true $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h true - true true true - true true true true diff --git a/test/old_tests/UnitTests/Tests.vcxproj b/test/old_tests/UnitTests/Tests.vcxproj index c0c178442..a0711f41d 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj +++ b/test/old_tests/UnitTests/Tests.vcxproj @@ -1,10 +1,6 @@  - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -146,11 +138,6 @@ true x64 - - Application - true - x64 - Application true @@ -162,12 +149,6 @@ x64 true - - Application - false - x64 - true - Application false @@ -193,18 +174,12 @@ - - - - - - @@ -240,25 +215,6 @@ $(OutDir)test_old.exe - - - Disabled - _HAS_AUTO_PTR_ETC;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; - ProgramDatabase - Default - false - false - MultiThreadedDebug - 4100;4297;4458 - - - Console - true - false - $(OutDir)test_old.exe - - Disabled @@ -316,25 +272,6 @@ $(OutDir)test_old.exe - - - MaxSpeed - true - true - _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; - MultiThreaded - 4100;4297;4458 - - - Console - true - true - true - false - $(OutDir)test_old.exe - - MaxSpeed diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index a82465149..f1035ab6c 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -147,24 +124,6 @@ - - - Disabled - $(OutputPath);Generated Files;..;..\..\cppwinrt - _MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - Disabled @@ -223,28 +182,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..;..\..\cppwinrt - _MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - MaxSpeed @@ -290,8 +227,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -300,8 +235,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -310,8 +243,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -349,8 +280,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -361,8 +290,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -374,8 +301,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -393,8 +318,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 15aa24447..b6b3aa5d4 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -183,55 +150,6 @@ true - - - Disabled - .;$(OutputPath);Generated Files - /Zc:threadSafeInit- /we4640 %(AdditionalOptions) - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component.winmd - - - - - - - - - - - $(OutputPath)test_component.h - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - Disabled @@ -357,59 +275,6 @@ true - - - MaxSpeed - true - true - .;$(OutputPath);Generated Files - /Zc:threadSafeInit- /we4640 %(AdditionalOptions) - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component.winmd - - - - - - - - - - - $(OutputPath)test_component.h - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - MaxSpeed diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index d8768de47..2a2069da0 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -195,68 +162,6 @@ $(OutputPath)test_component_base.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_base.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_base - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_base.winmd - - Disabled @@ -419,72 +324,6 @@ $(OutputPath)test_component_base.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_base.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_base - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_base.winmd - - MaxSpeed diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index e80ab4af1..e31d675a8 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -196,69 +163,6 @@ $(OutputPath)test_component_derived.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_derived.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - ..\test_component_base - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_derived.winmd -ref $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_derived - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_derived.winmd - - Disabled @@ -424,73 +328,6 @@ $(OutputPath)test_component_derived.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_derived.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - ..\test_component_base - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_derived.winmd -ref $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_derived - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_derived.winmd - - MaxSpeed diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index b9d54604b..216afea69 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -47,11 +39,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -63,12 +50,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -94,18 +75,12 @@ - - - - - - @@ -120,10 +95,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -132,10 +103,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -197,69 +164,6 @@ $(OutputPath)test_component_fast.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_fast.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_fast.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi -prefix -opt -name test_component_fast - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_fast.winmd - - Disabled @@ -425,73 +329,6 @@ $(OutputPath)test_component_fast.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_fast.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_fast.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi -prefix -opt -name test_component_fast - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_fast.winmd - - MaxSpeed diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index 0270ca257..0ddb18c6e 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -195,68 +162,6 @@ $(OutputPath)test_component_folders.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_folders.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_folders.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -name test_component_folders - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_folders.winmd - - Disabled @@ -419,72 +324,6 @@ $(OutputPath)test_component_folders.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_folders.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_folders.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -name test_component_folders - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_folders.winmd - - MaxSpeed diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 594e85592..040ab13f6 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -196,69 +163,6 @@ $(OutputPath)test_component_no_pch.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - NotUsing - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_no_pch.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_no_pch.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -pch . -name test_component_no_pch - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_no_pch.winmd - - Disabled @@ -424,73 +328,6 @@ $(OutputPath)test_component_no_pch.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - NotUsing - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_no_pch.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_no_pch.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -pch . -name test_component_no_pch - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_no_pch.winmd - - MaxSpeed diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 72d203a37..832297f7f 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,10 +38,6 @@ Application true - - Application - true - Application true @@ -59,11 +47,6 @@ false true - - Application - false - true - Application false @@ -86,18 +69,12 @@ - - - - - - @@ -150,25 +127,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -230,29 +188,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj index c71cfdc96..86a56a3b9 100644 --- a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj +++ b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,10 +38,6 @@ Application true - - Application - true - Application true @@ -59,11 +47,6 @@ false true - - Application - false - true - Application false @@ -86,18 +69,12 @@ - - - - - - @@ -156,25 +133,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -236,29 +194,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj index c256cad6b..27a7ea350 100644 --- a/test/test_fast/test_fast.vcxproj +++ b/test/test_fast/test_fast.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -149,25 +126,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\; - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - false - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - Disabled @@ -229,29 +187,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\; - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - false - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - MaxSpeed diff --git a/test/test_fast_fwd/test_fast_fwd.vcxproj b/test/test_fast_fwd/test_fast_fwd.vcxproj index c01406e38..d4b63c3fb 100644 --- a/test/test_fast_fwd/test_fast_fwd.vcxproj +++ b/test/test_fast_fwd/test_fast_fwd.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -126,30 +118,6 @@ - - - Disabled - true - true - $(CppWinRTDir);$(OutputPath);Generated Files;..\ - stdcpp17 - Use - pch.h - true - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - - - Console - windowsapp.lib - - - $(CppWinRTDir)cppwinrt -in $(CppWinRTDir)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - Disabled @@ -212,34 +180,6 @@ - - - MaxSpeed - true - true - true - true - $(CppWinRTDir);$(OutputPath);Generated Files;..\ - stdcpp17 - Use - pch.h - true - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - - - Console - true - true - windowsapp.lib - - - $(CppWinRTDir)cppwinrt -in $(CppWinRTDir)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - @@ -325,18 +265,12 @@ false MultiThreaded - - MultiThreaded - MultiThreaded MultiThreaded - - MultiThreadedDebug - MultiThreadedDebug diff --git a/test/test_module_lock_custom/test_module_lock_custom.vcxproj b/test/test_module_lock_custom/test_module_lock_custom.vcxproj index 6bb40e761..6671a1156 100644 --- a/test/test_module_lock_custom/test_module_lock_custom.vcxproj +++ b/test/test_module_lock_custom/test_module_lock_custom.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -149,25 +126,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\; - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -229,29 +187,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\; - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_module_lock_none/test_module_lock_none.vcxproj b/test/test_module_lock_none/test_module_lock_none.vcxproj index 7f460c6b2..381edbdfe 100644 --- a/test/test_module_lock_none/test_module_lock_none.vcxproj +++ b/test/test_module_lock_none/test_module_lock_none.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -149,25 +126,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -229,29 +187,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_slow/test_slow.vcxproj b/test/test_slow/test_slow.vcxproj index 75891b64b..eb6c7fc60 100644 --- a/test/test_slow/test_slow.vcxproj +++ b/test/test_slow/test_slow.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -147,24 +124,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose - - - - - - Disabled @@ -223,28 +182,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose - - - - - - MaxSpeed diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index c270aa038..30630610e 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -18,10 +18,6 @@ - - Debug - ARM - Debug ARM64 @@ -34,10 +30,6 @@ Debug x64 - - Release - ARM - Release ARM64 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index bd839b0b2..841ff85c9 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -17,10 +17,6 @@ - - Debug - ARM - Debug ARM64 @@ -33,10 +29,6 @@ Debug x64 - - Release - ARM - Release ARM64 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index accf6d492..ec8126558 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -19,10 +19,6 @@ - - Debug - ARM - Debug ARM64 @@ -35,10 +31,6 @@ Debug x64 - - Release - ARM - Release ARM64 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 7846860c0..78c477177 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -18,10 +18,6 @@ - - Debug - ARM - Debug ARM64 @@ -34,10 +30,6 @@ Debug x64 - - Release - ARM - Release ARM64 From fa079fb34b19b52dd92e215f8e58957f206c35e1 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:25:25 -0800 Subject: [PATCH 244/305] Address variable name collisions in generated consume methods (#1455) Why is this change being made? Someone discovered a subtle compatibility issue with the cast result checking changes and certain projected methods. The variables in the consume_ method, such as the generically-named code variable, can shadow the parameters to the function. This led to a build break where a function took an int16_t named code and that was shadowed by the int32_t named code with the HRESULT in it. Fortunately the compiler had our back and flagged the size truncation as a build break so it was noticed. Briefly summarize what changed The variable names in these generated functions are now much uglier (and therefore less likely to collide by coincidence). They have an underscore prefix and then lowercase which should put them into an unofficial namespace that shouldn't collide with anything else. The code variable is now named _winrt_cast_result_code for example. While I was renaming everything I realized that my previous names mismatched the cppwinrt naming convention of snake_case so I fixed them up. --- cppwinrt/code_writers.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 01f7dea10..9d75d3476 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,15 +1137,15 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); - check_hresult(code); - auto const abiType = *(abi_t<%>**)&castedResult; - abiType->%(%); + auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; + _winrt_abi_type->%(%); } else { - auto const abiType = *(abi_t<%>**)this; - abiType->%(%); + auto const _winrt_abi_type = *(abi_t<%>**)this; + _winrt_abi_type->%(%); }% } )"; @@ -1156,15 +1156,15 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); - check_hresult(code); - auto const abiType = *(abi_t<%>**)&castedResult; - WINRT_VERIFY_(0, abiType->%(%)); + auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; + WINRT_VERIFY_(0, _winrt_abi_type->%(%)); } else { - auto const abiType = *(abi_t<%>**)this; - WINRT_VERIFY_(0, abiType->%(%)); + auto const _winrt_abi_type = *(abi_t<%>**)this; + WINRT_VERIFY_(0, _winrt_abi_type->%(%)); }% } )"; @@ -1176,15 +1176,15 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); - check_hresult(code); - auto const abiType = *(abi_t<%>**)&castedResult; - check_hresult(abiType->%(%)); + auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; + check_hresult(_winrt_abi_type->%(%)); } else { - auto const abiType = *(abi_t<%>**)this; - check_hresult(abiType->%(%)); + auto const _winrt_abi_type = *(abi_t<%>**)this; + check_hresult(_winrt_abi_type->%(%)); }% } )"; From cf96df51cb808872c98301092b25e75de576c7d6 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Tue, 3 Dec 2024 19:58:26 -0500 Subject: [PATCH 245/305] Fix overloads coming from overridable interfaces (#1458) * Fix overloads coming from overridable interfaces Fixes #1457 * PR feedback --- cppwinrt/code_writers.h | 18 ++++++--- test/test_component/OverloadClass.cpp | 23 +++++++++++ test/test_component/OverloadClass.h | 21 ++++++++++ test/test_component/test_component.idl | 47 ++++++++++++++++++++++ test/test_component/test_component.vcxproj | 3 ++ test/test_component/test_overload.cpp | 19 +++++++++ 6 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 test/test_component/OverloadClass.cpp create mode 100644 test/test_component/OverloadClass.h create mode 100644 test/test_component/test_overload.cpp diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 9d75d3476..0ff1887d1 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2150,6 +2150,10 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable w.write("\n friend impl::consume_t;", name); w.write("\n friend impl::require_one;", name); } + else if (info.overridable) + { + w.write("\n friend impl::produce;", name); + } } } @@ -2275,13 +2279,13 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable static void write_class_override_usings(writer& w, get_interfaces_t const& required_interfaces) { - std::map> method_usage; + std::map> method_usage; - for (auto&& [interface_name, info] : required_interfaces) + for (auto&& interface_desc : required_interfaces) { - for (auto&& method : info.type.MethodList()) + for (auto&& method : interface_desc.second.type.MethodList()) { - method_usage[get_name(method)].insert(interface_name); + method_usage[get_name(method)].insert(interface_desc); } } @@ -2292,9 +2296,11 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable continue; } - for (auto&& interface_name : interfaces) + for (auto&& [interface_name, info] : interfaces) { - w.write(" using impl::consume_t::%;\n", + w.write(info.overridable + ? " using %T::%;\n" + : " using impl::consume_t::%;\n", interface_name, method_name); } diff --git a/test/test_component/OverloadClass.cpp b/test/test_component/OverloadClass.cpp new file mode 100644 index 000000000..d89f19ea5 --- /dev/null +++ b/test/test_component/OverloadClass.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include "OverloadClass.h" +#include "OverloadClass.g.cpp" + +namespace winrt::test_component::implementation +{ + void OverloadClass::Overload() + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int a) + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int a, int b) + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int a, int b, int c) + { + throw hresult_not_implemented(); + } +} diff --git a/test/test_component/OverloadClass.h b/test/test_component/OverloadClass.h new file mode 100644 index 000000000..1b155e801 --- /dev/null +++ b/test/test_component/OverloadClass.h @@ -0,0 +1,21 @@ +#pragma once +#include "OverloadClass.g.h" + +namespace winrt::test_component::implementation +{ + struct OverloadClass : OverloadClassT + { + OverloadClass() = default; + + void Overload(); + void Overload(int a); + void Overload(int a, int b); + void Overload(int a, int b, int c); + }; +} +namespace winrt::test_component::factory_implementation +{ + struct OverloadClass : OverloadClassT + { + }; +} diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index a027c394c..536a703f5 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -334,4 +334,51 @@ namespace test_component delegate void Delegate(); } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(EF902013-00F3-4549-9032-49E86D536C07)] + interface IOverloadClass : IInspectable + { + HRESULT Overload(); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(DFDFFB61-EA72-4977-B1A7-3F0D2C32BB58)] + interface IOverloadClassFactory : IInspectable + { + HRESULT CreateInstance([in] IInspectable* baseInterface, [out] IInspectable** innerInterface, [out][retval] test_component.OverloadClass** value); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(32510F72-9229-4C69-95BD-DE7B8189C85C)] + interface IOverloadClassOverrides : IInspectable + { + [overload("Overload")] HRESULT OverloadWithOne(int a); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(50205BCE-FAD3-4C66-801F-17AAD007B26C)] + interface IOverloadClassOverrides2 : IInspectable + { + [overload("Overload")] HRESULT OverloadWithTwo(int a, int b); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(6EDD1A3F-2616-45B7-9731-F84DA9CCECA1)] + interface IOverloadClassProtected : IInspectable + { + [overload("Overload")] HRESULT OverloadWithThree(int a, int b, int c); + } + + [composable(test_component.IOverloadClassFactory, public, 1)] + [marshaling_behavior(agile)] + [threading(both)] + [version(1)] + runtimeclass OverloadClass + { + [default] interface test_component.IOverloadClass; + [protected] interface test_component.IOverloadClassProtected; + [overridable] interface test_component.IOverloadClassOverrides; + [overridable] interface test_component.IOverloadClassOverrides2; + } } diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index b6b3aa5d4..001587bed 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -384,6 +384,8 @@ + + Create @@ -397,6 +399,7 @@ + diff --git a/test/test_component/test_overload.cpp b/test/test_component/test_overload.cpp new file mode 100644 index 000000000..9c21a06cf --- /dev/null +++ b/test/test_component/test_overload.cpp @@ -0,0 +1,19 @@ +#include "pch.h" +#include "winrt/test_component.h" + +// Simple compile-only test to validate overloads coming from overridable interfaces compile. + +using namespace winrt; +using namespace test_component; + +struct DerivedClass : OverloadClassT +{ + void Foo() + { + // make sure we can actually call the overloads (no ambiguous call errors) + Overload(); + Overload(1); + Overload(1, 2); + Overload(1, 2, 3); + } +}; \ No newline at end of file From d7c89b5f954aa90d9a74f93d21cc19a1fa687c3f Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 11 Dec 2024 17:51:18 -0800 Subject: [PATCH 246/305] Temporary std::pair sometimes causes spurious temporary dtor calls (#1462) --- cppwinrt/code_writers.h | 9 ++++++--- strings/base_implements.h | 6 +++--- strings/base_windows.h | 17 +++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 0ff1887d1..d84abeecf 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,7 +1137,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); check_hresult(_winrt_cast_result_code); auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; _winrt_abi_type->%(%); @@ -1156,7 +1157,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); check_hresult(_winrt_cast_result_code); auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; WINRT_VERIFY_(0, _winrt_abi_type->%(%)); @@ -1176,7 +1178,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); check_hresult(_winrt_cast_result_code); auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; check_hresult(_winrt_abi_type->%(%)); diff --git a/strings/base_implements.h b/strings/base_implements.h index 0847f5019..b620c6a6a 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -794,7 +794,7 @@ namespace winrt::impl } template - friend auto winrt::impl::try_as_with_reason(From ptr) noexcept; + friend auto winrt::impl::try_as_with_reason(From ptr, hresult& code) noexcept; protected: static constexpr bool is_composing = true; @@ -802,9 +802,9 @@ namespace winrt::impl private: template - auto try_as_with_reason() const noexcept + auto try_as_with_reason(hresult& code) const noexcept { - return m_inner.try_as_with_reason(); + return m_inner.try_as_with_reason(code); } }; diff --git a/strings/base_windows.h b/strings/base_windows.h index a67ef0b20..bf28440ef 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -133,7 +133,7 @@ namespace winrt::impl } template , int> = 0> - std::pair, hresult> try_as_with_reason(From* ptr) noexcept + com_ref try_as_with_reason(From* ptr, hresult& code) noexcept { #ifdef WINRT_DIAGNOSTICS get_diagnostics_info().add_query(); @@ -141,18 +141,19 @@ namespace winrt::impl if (!ptr) { - return { nullptr, 0 }; + code = 0; + return nullptr; } void* result{}; - hresult code = ptr->QueryInterface(guid_of(), &result); - return { wrap_as_result(result), code }; + code = ptr->QueryInterface(guid_of(), &result); + return wrap_as_result(result); } template - auto try_as_with_reason(From ptr) noexcept + auto try_as_with_reason(From ptr, hresult& code) noexcept { - return ptr->template try_as_with_reason(); + return ptr->template try_as_with_reason(code); } } @@ -229,9 +230,9 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } template - auto try_as_with_reason() const noexcept + auto try_as_with_reason(hresult& code) const noexcept { - return impl::try_as_with_reason(m_ptr); + return impl::try_as_with_reason(m_ptr, code); } template From fd0e95950414f5b530ecf55185b6eccc5ae35eb6 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 12 Dec 2024 11:06:42 -0800 Subject: [PATCH 247/305] Fix warnings in natvis project (#1463) --- natvis/cppwinrt_visualizer.cpp | 14 +++++++------- natvis/object_visualizer.cpp | 2 +- natvis/pch.h | 3 +++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index f6affd566..7aa845e53 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -12,7 +12,7 @@ using namespace winrt; using namespace winmd::reader; std::vector db_files; -std::unique_ptr db; +std::unique_ptr db_cache; void MetadataDiagnostic(DkmProcess* process, std::wstring const& status, std::filesystem::path const& path) { @@ -105,7 +105,7 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie if (std::find(db_files.begin(), db_files.end(), path_string) == db_files.end()) { - db->add_database(path_string, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); }); + db_cache->add_database(path_string, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); }); db_files.push_back(path_string); } } @@ -120,12 +120,12 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie TypeDef FindType(DkmProcess* process, std::string_view const& typeName) { - auto type = db->find(typeName); + auto type = db_cache->find(typeName); if (!type) { auto processPath = process->Path()->Value(); LoadMetadata(process, processPath, typeName); - type = db->find(typeName); + type = db_cache->find(typeName); if (!type) { NatvisDiagnostic(process, @@ -137,7 +137,7 @@ TypeDef FindType(DkmProcess* process, std::string_view const& typeName) TypeDef FindType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) { - auto type = db->find(typeNamespace, typeName); + auto type = db_cache->find(typeNamespace, typeName); if (!type) { std::string fullName(typeNamespace); @@ -165,7 +165,7 @@ cppwinrt_visualizer::cppwinrt_visualizer() db_files.push_back(file.path().string()); } } - db.reset(new cache(db_files, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); })); + db_cache.reset(new cache(db_files, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); })); } catch (...) { @@ -188,7 +188,7 @@ cppwinrt_visualizer::~cppwinrt_visualizer() { ClearTypeResolver(); db_files.clear(); - db.reset(); + db_cache.reset(); } HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 5308c33fc..a0803871a 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -671,7 +671,7 @@ HRESULT object_visualizer::GetItems( auto pParent = pVisualizedExpression; auto childCount = std::min(m_propertyData.size() - StartIndex, (size_t)Count); - for(auto i = 0; i < childCount; ++i) + for(size_t i = 0; i < childCount; ++i) { auto& prop = m_propertyData[i + (size_t)StartIndex]; com_ptr pPropertyVisualized; diff --git a/natvis/pch.h b/natvis/pch.h index c687b1f09..824d3aac1 100644 --- a/natvis/pch.h +++ b/natvis/pch.h @@ -4,7 +4,10 @@ #define NOMINMAX #include +#pragma warning(push) +#pragma warning(disable : 4471) #include +#pragma warning(pop) #include #include #include "base_includes.h" From 7bc7df630747922202417f24bef615a250c21d2e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 28 Jan 2025 17:22:44 -0600 Subject: [PATCH 248/305] Fix reading past end of array. (#1468) Fix a bug in the `NonDelegatingGetIids()` implementation that could cause reading past the end of the returned array. `std::copy()` returns a pointer to the next element in the array after the last element copied. The output argument `*array` was being assinged to this pointer after the first copy, causing it to no longer point to the beginning of the array. If the caller tries to access the full array after this, it will read past the end of the array and will miss the first elements of the array. To fix, introduce a new temporary `_array` variable to pass the result of the first copy as the starting point of the second copy. Also add a test that failed before the fix and passes after the fix. --- strings/base_implements.h | 4 ++-- test/old_tests/UnitTests/Composable.cpp | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index b620c6a6a..89b6c5790 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1033,8 +1033,8 @@ namespace winrt::impl { return error_bad_alloc; } - *array = std::copy(local_iids.second, local_iids.second + local_count, *array); - std::copy(inner_iids.cbegin(), inner_iids.cend(), *array); + auto next = std::copy(local_iids.second, local_iids.second + local_count, *array); + std::copy(inner_iids.cbegin(), inner_iids.cend(), next); } else { diff --git a/test/old_tests/UnitTests/Composable.cpp b/test/old_tests/UnitTests/Composable.cpp index 3cbc283d6..080e3769c 100644 --- a/test/old_tests/UnitTests/Composable.cpp +++ b/test/old_tests/UnitTests/Composable.cpp @@ -167,4 +167,20 @@ TEST_CASE("Composable conversions") { TestCalls(*make_self()); TestCalls(*make_self()); -} \ No newline at end of file +} + +TEST_CASE("Composable get_interfaces") +{ + struct Foo : Composable::BaseT { + hstring ToString() const { return L"Foo"; } + }; + + auto obj = make(); + auto iids = winrt::get_interfaces(obj); + // BaseOverrides IID gets repeated twice. There are only 4 unique interfaces. + REQUIRE(iids.size() == 5); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); +} From f2a7ffb321c6c06b1e4cdfea076dfbf1c6365fe4 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 28 Jan 2025 17:04:26 -0800 Subject: [PATCH 249/305] Fix setting of IntDir MSBuild property (#1471) --- Directory.Build.Props | 1 + Directory.Build.Targets | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 Directory.Build.Targets diff --git a/Directory.Build.Props b/Directory.Build.Props index cff3f7bda..0a8e5b37b 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -41,6 +41,7 @@ $(Platform) x86 $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ + $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\temp\$(MSBuildProjectName)\ $(OutDir) $(SolutionDir)_build\x86\$(Configuration)\ diff --git a/Directory.Build.Targets b/Directory.Build.Targets deleted file mode 100644 index 98abcdd3f..000000000 --- a/Directory.Build.Targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - $(OutDir)temp\$(ProjectName)\ - - - From e4c0b264c2dc2d31f5b2a16dcd868ab2710edcba Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 5 Feb 2025 12:47:58 -0800 Subject: [PATCH 250/305] Allow visualization of properties on generic types (#1472) --- natvis/cppwinrt_visualizer.cpp | 131 ++++++++- natvis/cppwinrt_visualizer.h | 2 +- natvis/cppwinrtvisualizer.vcxproj | 4 +- natvis/object_visualizer.cpp | 445 +++++++++++++++++++++++------- natvis/object_visualizer.h | 5 + natvis/packages.config | 2 +- natvis/pch.h | 10 +- natvis/type_resolver.cpp | 69 +++-- 8 files changed, 526 insertions(+), 142 deletions(-) diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index 7aa845e53..4b0a0c370 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -11,8 +11,39 @@ using namespace std::filesystem; using namespace winrt; using namespace winmd::reader; -std::vector db_files; -std::unique_ptr db_cache; +namespace +{ + std::vector db_files; + std::unique_ptr db_cache; + coded_index guid_TypeRef{}; +} + +coded_index FindGuidType() +{ + if (!guid_TypeRef) + { + // There is no definitive TypeDef for System.Guid. But there are a variety of TypeRefs scattered about + // This one should be relatively quick to find + auto pv = db_cache->find("Windows.Foundation", "IPropertyValue"); + for (auto&& method : pv.MethodList()) + { + if (method.Name() == "GetGuid") + { + auto const& sig = method.Signature(); + auto const& type = sig.ReturnType().Type().Type(); + XLANG_ASSERT(std::holds_alternative>(type)); + if (std::holds_alternative>(type)) + { + guid_TypeRef = std::get>(type); + XLANG_ASSERT(guid_TypeRef.type() == TypeDefOrRef::TypeRef); + XLANG_ASSERT(guid_TypeRef.TypeRef().TypeNamespace() == "System"); + XLANG_ASSERT(guid_TypeRef.TypeRef().TypeName() == "Guid"); + } + } + } + } + return guid_TypeRef; +} void MetadataDiagnostic(DkmProcess* process, std::wstring const& status, std::filesystem::path const& path) { @@ -118,8 +149,9 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie } } -TypeDef FindType(DkmProcess* process, std::string_view const& typeName) +TypeDef FindSimpleType(DkmProcess* process, std::string_view const& typeName) { + XLANG_ASSERT(typeName.find('<') == std::string_view::npos); auto type = db_cache->find(typeName); if (!type) { @@ -135,19 +167,104 @@ TypeDef FindType(DkmProcess* process, std::string_view const& typeName) return type; } -TypeDef FindType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) +TypeDef FindSimpleType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) { + XLANG_ASSERT(typeName.find('<') == std::string_view::npos); auto type = db_cache->find(typeNamespace, typeName); if (!type) { std::string fullName(typeNamespace); fullName.append("."); fullName.append(typeName); - FindType(process, fullName); + FindSimpleType(process, fullName); } return type; } +std::vector ParseTypeName(std::string_view name) +{ + DWORD count; + HSTRING* parts; + auto wide_name = winrt::to_hstring(name); + winrt::check_hresult(::RoParseTypeName(static_cast(get_abi(wide_name)), &count, &parts)); + + winrt::com_array wide_parts{ parts, count, winrt::take_ownership_from_abi }; + std::vector result; + for (auto&& part : wide_parts) + { + result.push_back(winrt::to_string(part)); + } + return result; +} + +template sent> +TypeSig ResolveGenericTypePart(DkmProcess* process, iter& it, sent const& end) +{ + constexpr std::pair elementNames[] = { + {"Boolean", ElementType::Boolean}, + {"Int8", ElementType::I1}, + {"Int16", ElementType::I2}, + {"Int32", ElementType::I4}, + {"Int64", ElementType::I8}, + {"UInt8", ElementType::U1}, + {"UInt16", ElementType::U2}, + {"UInt32", ElementType::U4}, + {"UInt64", ElementType::U8}, + {"Single", ElementType::R4}, + {"Double", ElementType::R8}, + {"String", ElementType::String}, + {"Char16", ElementType::Char}, + {"Object", ElementType::Object} + }; + std::string_view partName = *it; + auto basic_type_pos = std::find_if(std::begin(elementNames), std::end(elementNames), [&partName](auto&& elem) { return elem.first == partName; }); + if (basic_type_pos != std::end(elementNames)) + { + return TypeSig{ basic_type_pos->second }; + } + + if (partName == "Guid") + { + return TypeSig{ FindGuidType() }; + } + + TypeDef type = FindSimpleType(process, partName); + auto tickPos = partName.rfind('`'); + if (tickPos == partName.npos) + { + return TypeSig{ type.coded_index() }; + } + + int paramCount = 0; + std::from_chars(partName.data() + tickPos + 1, partName.data() + partName.size(), paramCount); + std::vector genericArgs; + for (int i = 0; i < paramCount; ++i) + { + genericArgs.push_back(ResolveGenericTypePart(process, ++it, end)); + } + return TypeSig{ GenericTypeInstSig{ type.coded_index(), std::move(genericArgs) } }; +} + +TypeSig ResolveGenericType(DkmProcess* process, std::string_view genericName) +{ + auto parts = ParseTypeName(genericName); + auto begin = parts.begin(); + return ResolveGenericTypePart(process, begin, parts.end()); +} + +TypeSig FindType(DkmProcess* process, std::string_view const& typeName) +{ + auto paramIndex = typeName.find('<'); + if (paramIndex == std::string_view::npos) + { + return TypeSig{ FindSimpleType(process, typeName).coded_index() }; + } + else + { + return ResolveGenericType(process, typeName); + } +} + cppwinrt_visualizer::cppwinrt_visualizer() { try @@ -187,13 +304,14 @@ cppwinrt_visualizer::cppwinrt_visualizer() cppwinrt_visualizer::~cppwinrt_visualizer() { ClearTypeResolver(); + guid_TypeRef = {}; db_files.clear(); db_cache.reset(); } HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( _In_ DkmVisualizedExpression* pVisualizedExpression, - _Deref_out_ DkmEvaluationResult** ppResultObject + _COM_Outptr_result_maybenull_ DkmEvaluationResult** ppResultObject ) { try @@ -233,6 +351,7 @@ HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( // unrecognized type NatvisDiagnostic(pVisualizedExpression, std::wstring(L"Unrecognized type: ") + (LPWSTR)bstrTypeName, NatvisDiagnosticLevel::Error); + *ppResultObject = nullptr; return S_OK; } diff --git a/natvis/cppwinrt_visualizer.h b/natvis/cppwinrt_visualizer.h index 5f12ec39a..924dc3cbc 100644 --- a/natvis/cppwinrt_visualizer.h +++ b/natvis/cppwinrt_visualizer.h @@ -8,7 +8,7 @@ struct cppwinrt_visualizer : winrt::implements - + Debug @@ -321,6 +321,6 @@ - + \ No newline at end of file diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index a0803871a..2e0eb3971 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -110,7 +110,7 @@ static HRESULT EvaluatePropertyExpression( wchar_t wszEvalText[500]; std::wstring propCast; PCWSTR propField; - if (prop.category < PropertyCategory::Value) + if (IsBuiltIn(prop.category)) { propField = g_categoryData[(int)prop.category].propField; } @@ -278,7 +278,7 @@ static HRESULT CreateChildVisualizedExpression( IF_FAIL_RET(DkmString::Create(prop.displayName.c_str(), pDisplayName.put())); PCWSTR displayType; - if (prop.category < PropertyCategory::Value) + if (IsBuiltIn(prop.category)) { displayType = g_categoryData[(int)prop.category].displayType; } @@ -340,19 +340,291 @@ static HRESULT CreateChildVisualizedExpression( return S_OK; } -struct property_type +std::optional GetPropertyCategory( + Microsoft::VisualStudio::Debugger::DkmProcess* process, + TypeSig const& owningType, + TypeSig const& propertyType +) +{ + std::optional propCategory; + if (auto pElementType = std::get_if(&propertyType.Type())) + { + if ((ElementType::Boolean <= *pElementType) && (*pElementType <= ElementType::String)) + { + propCategory = (PropertyCategory)(static_cast::type>(*pElementType) - + static_cast::type>(ElementType::Boolean)); + } + else if (*pElementType == ElementType::Object) + { + // result = PropertyCategory::Class; + } + } + else if (auto pIndex = std::get_if>(&propertyType.Type())) + { + auto type = ResolveType(process, *pIndex); + if (type) + { + if (get_category(type) == category::class_type || get_category(type) == category::interface_type) + { + propCategory = PropertyCategory::Class; + } + else + { + propCategory = PropertyCategory::Value; + } + } + else if (pIndex->type() == TypeDefOrRef::TypeRef) + { + auto typeRef = pIndex->TypeRef(); + if (typeRef.TypeNamespace() == "System" && typeRef.TypeName() == "Guid") + { + propCategory = PropertyCategory::Guid; + } + } + } + else if (auto pGenericInst = std::get_if(&propertyType.Type())) + { + XLANG_ASSERT(get_category(ResolveType(process, pGenericInst->GenericType())) == category::interface_type); + propCategory = PropertyCategory::Class; + } + else if (auto pGenericIndex = std::get_if(&propertyType.Type())) + { + if (auto pOwner = std::get_if(&owningType.Type())) + { + auto const& index = pGenericIndex->index; + auto const& genericArgs = pOwner->GenericArgs(); + propCategory = GetPropertyCategory(process, owningType, genericArgs.first[index]); + } + else + { + NatvisDiagnostic(process, L"Can't resolve GenericTypeIndex property on non-generic Type", NatvisDiagnosticLevel::Warning); + } + } + else + { + NatvisDiagnostic(process, L"Unsupported TypeSig encountered", NatvisDiagnosticLevel::Warning); + } + return propCategory; +} + +struct writer { - MethodDef get; - MethodDef set; + std::vector generic_params; + + std::string result; + + void write(char c) + { + result.push_back(c); + } + + void write(std::string_view const& str) + { + for (auto c : str) + { + if (c == '.') + { + write(':'); + write(':'); + } + else if (c != '`') + { + write(c); + } + else + { + return; + } + } + } + + void write(ElementType type) + { + switch (type) + { + case ElementType::Boolean: + write("bool"); + break; + case ElementType::Char: + write("wchar_t"); + break; + case ElementType::I1: + write("int8_t"); + break; + case ElementType::U1: + write("uint8_t"); + break; + case ElementType::I2: + write("int16_t"); + break; + case ElementType::U2: + write("uint16_t"); + break; + case ElementType::I4: + write("int32_t"); + break; + case ElementType::U4: + write("uint32_t"); + break; + case ElementType::I8: + write("int64_t"); + break; + case ElementType::U8: + write("uint64_t"); + break; + case ElementType::R4: + write("float"); + break; + case ElementType::R8: + write("double"); + break; + case ElementType::String: + write("winrt::hstring"); + break; + case ElementType::Object: + write("winrt::Windows::Foundation::IInspectable"); + break; + default: + XLANG_ASSERT(false); + break; + }; + } + + void write_namespace_and_type(std::string_view ns, std::string_view name) + { + if (ns == "System") + { + if (name == "Guid") + { + ns = ""; + name = "guid"; + } + } + else if (ns == "Windows.Foundation") + { + if (name == "EventRegistrationToken") + { + ns = ""; + name = "event_token"; + } + else if (name == "HResult") + { + ns = ""; + name = "hresult"; + } + } + else if (ns == "Windows.Foundation.Numerics") + { + if (name == "Matrix3x2") { name = "float3x2"; } + else if (name == "Matrix4x4") { name = "float4x4"; } + else if (name == "Plane") { name = "plane"; } + else if (name == "Quaternion") { name = "quarternion"; } + else if (name == "Vector2") { name = "float2"; } + else if (name == "Vector3") { name = "float3"; } + else if (name == "Vector4") { name = "float4"; } + } + + write("winrt::"); + if (!ns.empty()) + { + write(ns); + write("::"); + } + write(name); + } + + void write(TypeRef const& type) + { + write_namespace_and_type(type.TypeNamespace(), type.TypeName()); + } + + void write(TypeDef const& type) + { + write_namespace_and_type(type.TypeNamespace(), type.TypeName()); + } + + void write(TypeSpec const& type) + { + write(type.Signature().GenericTypeInst()); + } + + void write(coded_index type) + { + switch (type.type()) + { + case TypeDefOrRef::TypeDef: + write(type.TypeDef()); + break; + case TypeDefOrRef::TypeRef: + write(type.TypeRef()); + break; + case TypeDefOrRef::TypeSpec: + write(type.TypeSpec()); + break; + } + } + + void write(GenericTypeInstSig const& type) + { + write(type.GenericType()); + bool first = true; + write("<"); + for (auto&& elem : type.GenericArgs()) + { + if (first) + { + first = false; + } + else + { + write(", "); + } + write(elem); + } + write(">"); + } + + void write(GenericTypeIndex const& var) + { + write(generic_params[var.index]); + } + + void write(GenericMethodTypeIndex const&) + { + // Nothing + } + + void write(TypeSig const& type) + { + std::visit([this](auto&& arg) + { + write(arg); + }, type.Type()); + } }; +std::wstring string_to_wstring(std::string_view const& str) +{ + int const size = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), nullptr, 0); + if (size == 0) + { + return {}; + } + + std::wstring result(size, L'?'); + auto size_result = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), size); + XLANG_ASSERT(size == size_result); + return result; +} + void GetInterfaceData( Microsoft::VisualStudio::Debugger::DkmProcess* process, - coded_index index, + TypeSig const& typeSig, _Inout_ std::vector& propertyData, _Out_ bool& isStringable ){ - auto [type, propIid] = ResolveTypeInterface(process, index); + auto [type, propIid] = ResolveTypeInterface(process, typeSig); + if (!type) { return; @@ -375,106 +647,34 @@ void GetInterfaceData( continue; } - std::optional propCategory; - std::wstring propAbiType; - std::wstring propDisplayType; - - auto retType = method.Signature().ReturnType(); - std::visit(overloaded{ - [&](ElementType type) - { - if ((ElementType::Boolean <= type) && (type <= ElementType::String)) - { - propCategory = (PropertyCategory)(static_cast::type>(type) - - static_cast::type>(ElementType::Boolean)); - } - else if (type == ElementType::Object) - { - //propDisplayType = L"winrt::Windows::Foundation::IInspectable"; - //propCategory = PropertyCategory::Class; - //propAbiType = L"winrt::impl::inspectable_abi*"; - } - }, - [&](coded_index const& index) + std::optional propCategory = GetPropertyCategory(process, typeSig, method.Signature().ReturnType().Type()); + if (propCategory) + { + std::wstring propAbiType; + std::wstring propDisplayType; + if (!IsBuiltIn(*propCategory)) { - auto type = ResolveType(process, index); - if (!type) + writer writer; + if (auto pGenericTypeInst = std::get_if(&typeSig.Type())) { - return; + auto const& genericArgs = pGenericTypeInst->GenericArgs(); + writer.generic_params.assign(genericArgs.first, genericArgs.second); } - - auto typeName = type.TypeName(); - if (typeName == "GUID"sv) + writer.write(method.Signature().ReturnType().Type()); + propDisplayType = string_to_wstring(writer.result); + + if (*propCategory == PropertyCategory::Class) { - propCategory = PropertyCategory::Guid; + propAbiType = L"winrt::impl::inspectable_abi*"; } else { - auto ns = std::string(type.TypeNamespace()); - auto name = std::string(type.TypeName()); - - // Map numeric type names - if (ns == "Windows.Foundation.Numerics") - { - if (name == "Matrix3x2") { name = "float3x2"; } - else if (name == "Matrix4x4") { name = "float4x4"; } - else if (name == "Plane") { name = "plane"; } - else if (name == "Quaternion") { name = "quaternion"; } - else if (name == "Vector2") { name = "float2"; } - else if (name == "Vector3") { name = "float3"; } - else if (name == "Vector4") { name = "float4"; } - } - - // Types come back from winmd files with '.', need to be '::' - // Ex. Windows.Foundation.Uri needs to be Windows::Foundation::Uri - auto fullTypeName = ns + "::" + name; - wchar_t cppTypename[500]; - size_t i, j; - for (i = 0, j = 0; i < (fullTypeName.length() + 1); i++, j++) - { - if (fullTypeName[i] == L'.') - { - cppTypename[j++] = L':'; - cppTypename[j] = L':'; - } - else - { - cppTypename[j] = fullTypeName[i]; - } - } - - propDisplayType = std::wstring(L"winrt::") + cppTypename; - if(get_category(type) == category::class_type) - { - propCategory = PropertyCategory::Class; - propAbiType = L"winrt::impl::inspectable_abi*"; - } - else - { - propCategory = PropertyCategory::Value; - propAbiType = propDisplayType; - } + propAbiType = propDisplayType; } - }, - [&](GenericTypeIndex /*var*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); - }, - [&](GenericMethodTypeIndex /*var*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); - }, - [&](GenericTypeInstSig const& /*type*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); } - }, retType.Type().Type()); - if (propCategory) - { auto propName = method.Name().substr(4); - std::wstring propDisplayName(propName.cbegin(), propName.cend()); - propertyData.push_back({ propIid, propIndex, *propCategory, propAbiType, propDisplayType, propDisplayName }); + propertyData.emplace_back(propIid, propIndex, *propCategory, std::move(propAbiType), std::move(propDisplayType), string_to_wstring(propName)); } } } @@ -493,10 +693,55 @@ void object_visualizer::GetPropertyData() GetTypeProperties(process, std::string_view{ rc.data() + 2, rc.length() - 3 }); } +GenericTypeInstSig ReplaceGenericIndices(GenericTypeInstSig const& sig, std::vector const& genericArgs) +{ + std::vector replacementArgs; + for (auto&& arg : sig.GenericArgs()) + { + if (auto pGenericSig = std::get_if(&arg.Type())) + { + replacementArgs.emplace_back(ReplaceGenericIndices(*pGenericSig, genericArgs)); + } + else if (auto pGenericIndex = std::get_if(&arg.Type())) + { + replacementArgs.push_back(genericArgs[pGenericIndex->index]); + } + else + { + replacementArgs.push_back(arg); + } + } + return GenericTypeInstSig{ sig.GenericType(), std::move(replacementArgs) }; +} + +TypeSig ExpandInterfaceImplForType(coded_index impl, TypeSig const& type) +{ + if (auto pGenericInst = std::get_if(&type.Type())) + { + if (impl.type() == TypeDefOrRef::TypeSpec) + { + auto const& genericArgs = pGenericInst->GenericArgs(); + auto newSig = ReplaceGenericIndices(impl.TypeSpec().Signature().GenericTypeInst(), std::vector{ genericArgs.first, genericArgs.second }); + return TypeSig{ newSig }; + } + } + return TypeSig{ impl }; +} + void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& type_name) { // TODO: add support for direct generic interface implementations (e.g., key_value_pair) - auto type = FindType(process, type_name); + auto typeSig = FindType(process, type_name); + TypeDef type{}; + if (auto const* index = std::get_if>(&typeSig.Type())) + { + type = ResolveType(process, *index); + } + else if (auto const* genericInst = std::get_if(&typeSig.Type())) + { + type = ResolveType(process, genericInst->GenericType()); + } + if (!type) { return; @@ -516,7 +761,7 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm auto impls = type.InterfaceImpl(); for (auto&& impl : impls) { - GetInterfaceData(process, impl.Interface(), m_propertyData, m_isStringable); + GetInterfaceData(process, ExpandInterfaceImplForType(impl.Interface(), typeSig), m_propertyData, m_isStringable); } } else if (get_category(type) == category::interface_type) @@ -524,9 +769,9 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm auto impls = type.InterfaceImpl(); for (auto&& impl : impls) { - GetInterfaceData(process, impl.Interface(), m_propertyData, m_isStringable); + GetInterfaceData(process, ExpandInterfaceImplForType(impl.Interface(), typeSig), m_propertyData, m_isStringable); } - GetInterfaceData(process, type.coded_index(), m_propertyData, m_isStringable); + GetInterfaceData(process, typeSig, m_propertyData, m_isStringable); } } diff --git a/natvis/object_visualizer.h b/natvis/object_visualizer.h index ad83d79d7..6d1a0f00c 100644 --- a/natvis/object_visualizer.h +++ b/natvis/object_visualizer.h @@ -20,6 +20,11 @@ enum class PropertyCategory Class, }; +inline constexpr bool IsBuiltIn(PropertyCategory value) noexcept +{ + return PropertyCategory::Bool <= value && value < PropertyCategory::Value; +} + enum class ObjectType { Abi, diff --git a/natvis/packages.config b/natvis/packages.config index 356e82f7f..7907cba44 100644 --- a/natvis/packages.config +++ b/natvis/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/natvis/pch.h b/natvis/pch.h index 824d3aac1..95e561971 100644 --- a/natvis/pch.h +++ b/natvis/pch.h @@ -43,6 +43,7 @@ #include #include #include +#include #ifndef IF_FAIL_RET #define IF_FAIL_RET(expr) { HRESULT _hr = (expr); if(FAILED(_hr)) { return(_hr); } } @@ -91,8 +92,9 @@ inline bool starts_with(std::string_view const& value, std::string_view const& m return 0 == value.compare(0, match.size(), match); } -winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); -winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName); +winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); +winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName); +winmd::reader::TypeSig FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index index) noexcept { @@ -101,13 +103,13 @@ inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::Dkm case winmd::reader::TypeDefOrRef::TypeDef: return index.TypeDef(); case winmd::reader::TypeDefOrRef::TypeRef: - return FindType(process, index.TypeRef().TypeNamespace(), index.TypeRef().TypeName()); + return FindSimpleType(process, index.TypeRef().TypeNamespace(), index.TypeRef().TypeName()); default: //case TypeDefOrRef::TypeSpec: return winmd::reader::find_required(index.TypeSpec().Signature(). GenericTypeInst().GenericType().TypeRef()); } } -std::pair ResolveTypeInterface(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index index); +std::pair ResolveTypeInterface(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::TypeSig const& typeSig); void ClearTypeResolver(); diff --git a/natvis/type_resolver.cpp b/natvis/type_resolver.cpp index 17999997f..de8af71f4 100644 --- a/natvis/type_resolver.cpp +++ b/natvis/type_resolver.cpp @@ -98,6 +98,18 @@ struct signature_generator } } + static std::string get_signature(GenericTypeInstSig const& type) + { + std::string sig = "pinterface(" + get_guid_signature(type.GenericType()); + for (auto&& arg : type.GenericArgs()) + { + sig += ";"; + sig += get_signature(arg); + } + sig += ")"; + return sig; + } + private: static std::string get_class_signature(TypeDef const& type) { @@ -152,20 +164,8 @@ struct signature_generator case TypeDefOrRef::TypeRef: return get_guid_signature(find_required(type.TypeRef())); default: //case TypeDefOrRef::TypeSpec: - return get_guid_signature(type.TypeSpec().Signature().GenericTypeInst().GenericType()); - } - } - - static std::string get_signature(GenericTypeInstSig const& type) - { - std::string sig = "pinterface(" + get_guid_signature(type.GenericType()); - for (auto&& arg : type.GenericArgs()) - { - sig += ";"; - sig += get_signature(arg); + return get_signature(type.TypeSpec().Signature().GenericTypeInst()); } - sig += ")"; - return sig; } static std::string get_signature(TypeSig::value_type const& type) @@ -266,7 +266,7 @@ static auto calculate_sha1(std::vector const& input) return get_result(intermediate_hash); } -static guid generate_guid(coded_index const& type) +static guid generate_guid(GenericTypeInstSig const& type) { constexpr guid namespace_guid = { 0xd57af411, 0x737b, 0xc042,{ 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee } }; constexpr auto namespace_bytes = winrt::impl::to_array(namespace_guid); @@ -278,25 +278,38 @@ static guid generate_guid(coded_index const& type) return set_named_guid_fields(endian_swap(to_guid(calculate_sha1(buffer)))); } -std::pair ResolveTypeInterface(DkmProcess* process, coded_index index) +std::pair ResolveTypeInterface(DkmProcess* process, winmd::reader::TypeSig const& typeSig) { - if (auto found = _cache.find(index); found != _cache.end()) + coded_index index; + if (auto ptrIndex = std::get_if>(&typeSig.Type())) { - return found->second; - } + index = *ptrIndex; + // TODO: Cache on the whole TypeSig, not just the generic index + if (auto found = _cache.find(index); found != _cache.end()) + { + return found->second; + } - TypeDef type = ResolveType(process, index); - if (!type) - { - return {}; - } + TypeDef type = ResolveType(process, index); + if (!type) + { + return {}; + } - auto guid = index.type() == TypeDefOrRef::TypeSpec ? - format_guid(generate_guid(index)) : format_guid(get_guid(type)); + auto guid = index.type() == TypeDefOrRef::TypeSpec ? + format_guid(generate_guid(index.TypeSpec().Signature().GenericTypeInst())) : format_guid(get_guid(type)); - auto type_guid = std::pair{ type, guid }; - _cache[index] = type_guid; - return type_guid; + auto type_guid = std::pair{ type, guid }; + _cache[index] = type_guid; + return type_guid; + } + else if (auto* ptrGeneric = std::get_if(&typeSig.Type())) + { + index = ptrGeneric->GenericType(); + auto guid = format_guid(generate_guid(*ptrGeneric)); + return { ResolveType(process, index), guid }; + } + return {}; }; void ClearTypeResolver() From 153e838a32c8bf5dfe87fbb908942387e9ad0233 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 5 Feb 2025 21:04:36 -0800 Subject: [PATCH 251/305] Fix various build warnings (#1473) --- cppwinrt/component_writers.h | 3 +++ prebuild/prebuild.vcxproj | 3 +++ strings/base_composable.h | 7 +++++++ strings/base_implements.h | 7 +++++++ test/old_tests/Component/Component.idl | 4 ++++ test/test/fast_iterator.cpp | 2 +- test/test_component/OverloadClass.cpp | 6 +++--- test/test_component_base/HierarchyB.cpp | 2 ++ 8 files changed, 30 insertions(+), 4 deletions(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 4a2cce556..c52f49a13 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -175,6 +175,9 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons int32_t __stdcall WINRT_CanUnloadNow() noexcept { #ifdef _WRL_MODULE_H_ +#ifdef _MSC_VER +#pragma warning(suppress: 4324) // structure was padded due to alignment specifier +#endif if (!::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().Terminate()) { return 1; diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index e5fa52565..6e0bc4b71 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -120,6 +120,7 @@ true ..\cppwinrt MultiThreaded + Guard Console @@ -134,6 +135,7 @@ true ..\cppwinrt MultiThreaded + Guard Console @@ -148,6 +150,7 @@ true ..\cppwinrt MultiThreaded + Guard Console diff --git a/strings/base_composable.h b/strings/base_composable.h index 7f675c970..e606d1292 100644 --- a/strings/base_composable.h +++ b/strings/base_composable.h @@ -4,6 +4,10 @@ namespace winrt::impl template struct composable_factory { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // Compiler bug causing spurious "unreachable code" warnings +#endif template static I CreateInstance(const Windows::Foundation::IInspectable& outer, Windows::Foundation::IInspectable& inner, Args&&... args) { @@ -11,6 +15,9 @@ namespace winrt::impl inner = CreateInstanceImpl(outer, std::forward(args)...); return inner.as(); } +#ifdef _MSC_VER +#pragma warning(pop) +#endif private: template diff --git a/strings/base_implements.h b/strings/base_implements.h index 89b6c5790..b943c1d96 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1390,6 +1390,10 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // Compiler bug causing spurious "unreachable code" warnings +#endif template auto make(Args&&... args) { @@ -1443,6 +1447,9 @@ WINRT_EXPORT namespace winrt return { impl::create_and_initialize(std::forward(args)...), take_ownership_from_abi }; } } +#ifdef _MSC_VER +#pragma warning(pop) +#endif template inline void clear_factory_static_lifetime() diff --git a/test/old_tests/Component/Component.idl b/test/old_tests/Component/Component.idl index 3c306ad69..ad51b5303 100644 --- a/test/old_tests/Component/Component.idl +++ b/test/old_tests/Component/Component.idl @@ -243,6 +243,8 @@ namespace Component HRESULT Create([in] Windows.Foundation.Collections.IVectorView* _in, [out, retval] FastInputVector** _out); }; + midl_pragma warning(disable: 4066) // A member name has been qualified with an interface name because name collisions occurred across interface members on a runtime class. + [version(1.0), activatable(IFastInputVectorFactory, 1.0)] runtimeclass FastInputVector { @@ -271,6 +273,8 @@ namespace Component interface Windows.Foundation.Collections.IMapView; }; + midl_pragma warning(default: 4066) + // // Boxing support for enums and their underlying types. // diff --git a/test/test/fast_iterator.cpp b/test/test/fast_iterator.cpp index 71ed6a918..f9e02dcec 100644 --- a/test/test/fast_iterator.cpp +++ b/test/test/fast_iterator.cpp @@ -48,7 +48,7 @@ TEST_CASE("fast_iterator") REQUIRE(2 - (vbegin + 4) > vbegin); REQUIRE(vbegin < vbegin + 2); REQUIRE(vbegin + 2 - 2 == vbegin); - REQUIRE(end(v) - begin(v) == v.Size()); + REQUIRE(static_cast(end(v) - begin(v)) == v.Size()); REQUIRE((begin(v) + 3)[-1] == 4); } { diff --git a/test/test_component/OverloadClass.cpp b/test/test_component/OverloadClass.cpp index d89f19ea5..0f78c5a1c 100644 --- a/test/test_component/OverloadClass.cpp +++ b/test/test_component/OverloadClass.cpp @@ -8,15 +8,15 @@ namespace winrt::test_component::implementation { throw hresult_not_implemented(); } - void OverloadClass::Overload(int a) + void OverloadClass::Overload(int /*a*/) { throw hresult_not_implemented(); } - void OverloadClass::Overload(int a, int b) + void OverloadClass::Overload(int /*a*/, int /*b*/) { throw hresult_not_implemented(); } - void OverloadClass::Overload(int a, int b, int c) + void OverloadClass::Overload(int /*a*/, int /*b*/, int /*c*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/HierarchyB.cpp b/test/test_component_base/HierarchyB.cpp index 34c73104f..30b9f09ff 100644 --- a/test/test_component_base/HierarchyB.cpp +++ b/test/test_component_base/HierarchyB.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "HierarchyB.h" +#pragma warning(disable: 4702) + namespace winrt::test_component_base::implementation { HierarchyB::HierarchyB(hstring const& name) From 4bc0f82975e794cfc73306c0a023a77132324351 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 14 Feb 2025 16:16:40 -0800 Subject: [PATCH 252/305] Configure guardian, SDL, TSA, and CodeQL in Official Builds (#1474) --- .config/tsaoptions.json | 8 ++++++++ .gdn/.gdnsettings | 7 +++++++ .gdn/.gitignore | 11 +++++++++++ .pipelines/OneBranch.Official.yml | 8 +++++++- 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .config/tsaoptions.json create mode 100644 .gdn/.gdnsettings create mode 100644 .gdn/.gitignore diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 000000000..38fe35171 --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,8 @@ +{ + "instanceUrl": "https://microsoft.visualstudio.com", + "projectName": "os", + "areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\AmUse- App Metadata and User Setup Experience\\Projections\\Cppwinrt", + "notificationAliases": [ "cpp4uwpt@microsoft.com" ], + "ignoreBranchName": true, + "codebaseName": "cppwinrt" +} diff --git a/.gdn/.gdnsettings b/.gdn/.gdnsettings new file mode 100644 index 000000000..156408362 --- /dev/null +++ b/.gdn/.gdnsettings @@ -0,0 +1,7 @@ +{ + "files": { }, + "folders": { }, + "overwriteLogs": true, + "telemetryFlushTimeout": 10, + "variables": { } +} \ No newline at end of file diff --git a/.gdn/.gitignore b/.gdn/.gitignore new file mode 100644 index 000000000..decb1055f --- /dev/null +++ b/.gdn/.gitignore @@ -0,0 +1,11 @@ +## Ignore Guardian internal files +.r/ +rc/ +rs/ +i/ +p/ +c/ +o/ + +## Ignore Guardian Local settings +LocalSettings.gdn.json \ No newline at end of file diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 91e686622..fb6d68148 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -32,8 +32,14 @@ extends: enabled: false globalSdl: + asyncSdl: + enabled: true tsa: - enabled: false + enabled: true + codeql: + compiled: + enabled: true + tsaEnabled: true stages: - stage: build From 76eb09c9a1a75e89ef8f922f92d0794fffa48ccb Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 20 Feb 2025 10:49:19 -0800 Subject: [PATCH 253/305] Clean up more warnings and Component Governance (#1475) * Fix a couple more build warnings * Upgrade System.Text.Json to 6.0.10 * Better fix for unused size_result * Disable warning 4324 for all of wrl.h --- cppwinrt/component_writers.h | 1 + natvis/object_visualizer.cpp | 2 +- test/old_tests/Component/pch.h | 3 +++ vsix/Dev16/vsix.Dev16.csproj | 1 + vsix/Dev17/vsix.Dev17.csproj | 3 +++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index c52f49a13..6865d49ef 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -198,6 +198,7 @@ int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noex } #ifdef _WRL_MODULE_H_ +#pragma warning(suppress: 4324) // structure was padded due to alignment specifier return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetActivationFactory(static_cast(classId), reinterpret_cast<::IActivationFactory**>(factory)); #else return winrt::hresult_class_not_available(name).to_abi(); diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 2e0eb3971..d953a1c03 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -612,7 +612,7 @@ std::wstring string_to_wstring(std::string_view const& str) } std::wstring result(size, L'?'); - auto size_result = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), size); + [[maybe_unused]] auto size_result = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), size); XLANG_ASSERT(size == size_result); return result; } diff --git a/test/old_tests/Component/pch.h b/test/old_tests/Component/pch.h index 5d84eecb6..b73230946 100644 --- a/test/old_tests/Component/pch.h +++ b/test/old_tests/Component/pch.h @@ -8,4 +8,7 @@ #include "winrt/Composable.h" // This is used to validate WRL interop support. +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to alignment specifier #include +#pragma warning(pop) \ No newline at end of file diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index 1e89b390b..dfb870ee1 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -93,6 +93,7 @@ all + diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index 3ef30ce63..be0cf3d17 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -168,6 +168,9 @@ + + + From f89f47fa9754f31436f401c6617d9c670b063ca7 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 28 Feb 2025 16:19:34 -0800 Subject: [PATCH 254/305] Stop manually downloading hardcoded version of llvm/clang. (#1478) * Stop manually downloading different version of llvm. Just use the one included in Visual Studio * Replace "custom llvm" msbuild props with PlatformToolset=ClangCl * Also disable the custom llvm install for test runs * Overriding ExecutablePath was causing clang-cl problems --- .github/workflows/ci.yml | 14 ++------------ test/old_tests/Component/Component.vcxproj | 6 ------ test/old_tests/Composable/Composable.vcxproj | 6 ------ test/test_component/test_component.vcxproj | 6 ------ .../test_component_base.vcxproj | 6 ------ .../test_component_derived.vcxproj | 6 ------ .../test_component_fast.vcxproj | 6 ------ .../test_component_folders.vcxproj | 6 ------ .../test_component_no_pch.vcxproj | 6 ------ 9 files changed, 2 insertions(+), 60 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f99be8fb..8544bcf77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,11 +25,6 @@ jobs: steps: - uses: actions/checkout@v4 - - id: setup-llvm - name: Set up LLVM (MSVC) - uses: ./.github/actions/setup-llvm-msvc - if: matrix.compiler == 'clang-cl' - - name: Download nuget run: | mkdir ".\.nuget" @@ -49,7 +44,7 @@ jobs: $target_version = "1.2.3.4" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" + $props += ",Clang=1,PlatformToolset=ClangCl" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -109,11 +104,6 @@ jobs: steps: - uses: actions/checkout@v4 - - id: setup-llvm - name: Set up LLVM (MSVC) - uses: ./.github/actions/setup-llvm-msvc - if: matrix.compiler == 'clang-cl' - - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' uses: actions/download-artifact@v4 @@ -147,7 +137,7 @@ jobs: $target_version = "1.2.3.4" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" + $props += ",Clang=1,PlatformToolset=ClangCl" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index dbc55f2d3..6c7df9527 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -94,37 +94,31 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index 3b78edce4..4e49a255e 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -94,37 +94,31 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 001587bed..9751fb5a2 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index 2a2069da0..947c53e8f 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index e31d675a8..a1c856c90 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index 216afea69..5d646cf78 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -93,27 +93,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index 0ddb18c6e..6d642096f 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 040ab13f6..0b1a98271 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); From 8d06be20d76a6063fd572fc336f5d81da2e96f02 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 28 Feb 2025 16:45:31 -0800 Subject: [PATCH 255/305] Enable prefast and warnings checker in SDL (#1477) * Enable prefast and warning checkers * globalSdl.isNativeCode is a simple bool, not an object with 'enabled' field * Re-enable SDL in cppwinrtvisualizer --- .pipelines/OneBranch.Official.yml | 3 +++ .pipelines/OneBranch.PullRequest.yml | 3 +++ .pipelines/jobs/OneBranchBuild.yml | 4 ++++ .pipelines/jobs/OneBranchNuGet.yml | 4 ++++ .pipelines/jobs/OneBranchTest.yml | 4 ++++ .pipelines/jobs/OneBranchVsix.yml | 4 ++++ natvis/cppwinrtvisualizer.vcxproj | 6 ------ 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index fb6d68148..1bcc24550 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -32,6 +32,7 @@ extends: enabled: false globalSdl: + isNativeCode: true asyncSdl: enabled: true tsa: @@ -40,6 +41,8 @@ extends: compiled: enabled: true tsaEnabled: true + prefast: + enabled: true stages: - stage: build diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index 2ee26d1ad..b5b358702 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -32,10 +32,13 @@ extends: product: 'build_tools' globalSdl: + isNativeCode: true tsa: enabled: false sbom: enabled: true + prefast: + enabled: true stages: - stage: build diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index 9053fc21c..b5c060cb9 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -31,6 +31,10 @@ jobs: ${{ if eq(parameters.OfficialBuild, 'false') }}: ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true + ob_symbolsPublishing_enabled: ${{ parameters.OfficialBuild }} ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' ob_symbolsPublishing_searchPattern: '**\*.pdb' diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 4d4a7b2ea..02133ee03 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -17,6 +17,10 @@ jobs: ob_outputDirectory: '$(Build.SourcesDirectory)\out' PackageVersion: ${{ parameters.BuildVersion }} + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true + steps: - task: UseDotNet@2 continueOnError: true diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index 307f5e168..0aa5c934b 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -51,6 +51,10 @@ jobs: ob_artifactSuffix: $(TestExe).$(BuildPlatform) ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true + BuildPath: '$(Build.SourcesDirectory)/_build/$(BuildPlatform)/${{ parameters.BuildConfiguration }}' steps: diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index b1a6c8eeb..18b74403b 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -36,6 +36,10 @@ jobs: ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' ob_symbolsPublishing_searchPattern: '**\*.pdb' ob_symbolsPublishing_indexSources: true + + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true steps: - task: UseDotNet@2 diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index b77013ac4..cc17bf500 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -104,7 +104,6 @@ Use Level4 Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -129,7 +128,6 @@ Use Level4 Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -153,7 +151,6 @@ Use Level4 Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -179,7 +176,6 @@ MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -209,7 +205,6 @@ MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -239,7 +234,6 @@ MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 From 48e2f6186b735db4de47be9c304d1d61757a811c Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 28 Feb 2025 16:57:04 -0800 Subject: [PATCH 256/305] Merge compiler and msbuild vpacks (#1479) --- .pipelines/OneBranch.Official.yml | 53 ++++++------------------------- 1 file changed, 10 insertions(+), 43 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 1bcc24550..531076f3f 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -77,48 +77,6 @@ extends: ob_createvpack_metadata: $(Build.SourceBranchName).x86.$(Build.BuildNumber).$(Build.SourceVersion) ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt - steps: - - task: UseDotNet@2 - continueOnError: true - inputs: - packageType: 'runtime' - version: '6.x' - performMultiLevelLookup: true - - - task: DownloadPipelineArtifact@2 - displayName: 'Download x86 artifacts' - inputs: - artifactName: 'drop_build_x86' - targetPath: '$(Build.SourcesDirectory)/x86' - - - task: CopyFiles@2 - displayName: 'Stage compiler vpack contents' - inputs: - SourceFolder: $(Build.SourcesDirectory)/x86/cppwinrt - Contents: | - cppwinrt.exe - cppwinrt.pdb - TargetFolder: $(ob_outputDirectory) - - - job: MSBuild_vpack - pool: - type: windows - variables: - ob_outputDirectory: '$(Build.SourcesDirectory)\out' - - ob_createvpack_enabled: true - ob_createvpack_packagename: CppWinRT.MSBuild - ob_createvpack_owneralias: cpp4uwpt - ob_createvpack_description: C++/WinRT MSBuild - ob_createvpack_provData: true - ob_createvpack_versionAs: parts - ob_createvpack_majorVer: $(MajorVersion) - ob_createvpack_minorVer: $(MinorVersion) - ob_createvpack_patchVer: $(PatchVersion) - ob_createvpack_metadata: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) - ob_createvpack_verbose: true - ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt - steps: - task: UseDotNet@2 continueOnError: true @@ -144,6 +102,15 @@ extends: inputs: artifactName: 'drop_build_arm64' targetPath: '$(Build.SourcesDirectory)/arm64' + + - task: CopyFiles@2 + displayName: 'Stage compiler vpack contents' + inputs: + SourceFolder: $(Build.SourcesDirectory)/x86/cppwinrt + Contents: | + cppwinrt.exe + cppwinrt.pdb + TargetFolder: $(ob_outputDirectory) - task: CmdLine@2 displayName: 'Stage MSBuild vpack contents' @@ -163,7 +130,7 @@ extends: echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\amd64 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\x64 echo d | xcopy $(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib build\native\lib\arm64 - + - stage: NuGet dependsOn: build jobs: From 69c78cfc7920367c4ce9cc024cf8c5b8d217fb1b Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 3 Mar 2025 15:22:06 -0800 Subject: [PATCH 257/305] Fix vpack clobbering and update to newer Windows container image (#1480) * Update to newer Windows container image * Pass newer host version to templates * Stop clobbering compiler vpack contents --- .pipelines/OneBranch.Official.yml | 6 ++++-- .pipelines/OneBranch.PullRequest.yml | 4 ++++ .pipelines/variables/OneBranchVariables.yml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 531076f3f..552ec761b 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -27,6 +27,10 @@ extends: platform: name: 'windows_undocked' product: 'build_tools' + + featureFlags: + WindowsHostVersion: + Version: 2022 cloudvault: enabled: false @@ -117,8 +121,6 @@ extends: inputs: script: | set TargetDir=$(ob_outputDirectory) - rd /s /q %TargetDir% >nul 2>&1 - md %TargetDir% cd %TargetDir% copy $(Build.SourcesDirectory)\vsix\Microsoft.Cpp.CppWinRT.props diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index b5b358702..bc08bbddf 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -31,6 +31,10 @@ extends: name: 'windows_undocked' product: 'build_tools' + featureFlags: + WindowsHostVersion: + Version: 2022 + globalSdl: isNativeCode: true tsa: diff --git a/.pipelines/variables/OneBranchVariables.yml b/.pipelines/variables/OneBranchVariables.yml index 8e6ad8af0..ff7a98adb 100644 --- a/.pipelines/variables/OneBranchVariables.yml +++ b/.pipelines/variables/OneBranchVariables.yml @@ -10,7 +10,7 @@ variables: NUGET_XMLDOC_MODE: none # Docker image which is used to build the project https://aka.ms/obpipelines/containers - WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' + WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' Codeql.Enabled: true # CodeQL once every 3 days on the default branch for all languages its applicable to in that pipeline. GDN_USE_DOTNET: true \ No newline at end of file From 80fa82f523587ceca271a60d5b183b7411021566 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 2 Apr 2025 18:52:52 -0700 Subject: [PATCH 258/305] Enable NuGet Central Package Management (#1483) * Enable NuGet Central Package Management * Enable NuGet Central Package Management --------- Co-authored-by: MerlinBot Co-authored-by: 1ES Gardener --- Directory.Packages.props | 12 ++++++++++++ .../TestRuntimeComponentCSharp.csproj | 4 +--- vsix/Dev16/vsix.Dev16.csproj | 7 +++---- vsix/Dev17/vsix.Dev17.csproj | 6 +++--- 4 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 Directory.Packages.props diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 000000000..1d77adffd --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,12 @@ + + + true + + + + + + + + + \ No newline at end of file diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index 57f14194d..d756e19b7 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -80,9 +80,7 @@ - - 5.4.7 - + 14.0 diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index dfb870ee1..72b9b4098 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -84,16 +84,15 @@ - 16.10.31321.278 + 16.10.31321.278 compile; build; native; contentfiles; analyzers; buildtransitive - 17.3.2093 runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index be0cf3d17..3326ce6fa 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -87,10 +87,10 @@ - + compile; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -169,7 +169,7 @@ - + From 723f64b35d672200d444e6fe3615c8ef0705d5e8 Mon Sep 17 00:00:00 2001 From: Brady Hahn Date: Fri, 4 Apr 2025 14:07:09 -0700 Subject: [PATCH 259/305] Public LTO visibility for ABI type declarations (#1482) --- cppwinrt/code_writers.h | 6 +++--- strings/base_abi.h | 36 ++++++++++++++++++------------------ strings/base_delegate.h | 2 +- strings/base_fast_forward.h | 9 ++++++++- strings/base_macros.h | 8 ++++++++ 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index d84abeecf..ae2920d56 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -763,7 +763,7 @@ namespace cppwinrt { auto format = R"( template <> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { )"; @@ -773,7 +773,7 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { )"; @@ -814,7 +814,7 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : unknown_abi + struct WINRT_IMPL_ABI_DECL type : unknown_abi { virtual int32_t __stdcall Invoke(%) noexcept = 0; }; diff --git a/strings/base_abi.h b/strings/base_abi.h index d1eab2950..ec42fefe6 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -3,7 +3,7 @@ namespace winrt::impl { template <> struct abi { - struct WINRT_IMPL_NOVTABLE type + struct WINRT_IMPL_ABI_DECL type { virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; virtual uint32_t __stdcall AddRef() noexcept = 0; @@ -15,7 +15,7 @@ namespace winrt::impl template <> struct abi { - struct WINRT_IMPL_NOVTABLE type : unknown_abi + struct WINRT_IMPL_ABI_DECL type : unknown_abi { virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; @@ -27,20 +27,20 @@ namespace winrt::impl template <> struct abi { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { virtual int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; }; }; - struct WINRT_IMPL_NOVTABLE IAgileObject : unknown_abi {}; + struct WINRT_IMPL_ABI_DECL IAgileObject : unknown_abi {}; - struct WINRT_IMPL_NOVTABLE IAgileReference : unknown_abi + struct WINRT_IMPL_ABI_DECL IAgileReference : unknown_abi { virtual int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IMarshal : unknown_abi + struct WINRT_IMPL_ABI_DECL IMarshal : unknown_abi { virtual int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept = 0; virtual int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept = 0; @@ -50,20 +50,20 @@ namespace winrt::impl virtual int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IGlobalInterfaceTable : unknown_abi + struct WINRT_IMPL_ABI_DECL IGlobalInterfaceTable : unknown_abi { virtual int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, uint32_t* cookie) noexcept = 0; virtual int32_t __stdcall RevokeInterfaceFromGlobal(uint32_t cookie) noexcept = 0; virtual int32_t __stdcall GetInterfaceFromGlobal(uint32_t cookie, guid const& iid, void** object) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IStaticLifetime : inspectable_abi + struct WINRT_IMPL_ABI_DECL IStaticLifetime : inspectable_abi { virtual int32_t __stdcall unused() noexcept = 0; virtual int32_t __stdcall GetCollection(void** value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IStaticLifetimeCollection : inspectable_abi + struct WINRT_IMPL_ABI_DECL IStaticLifetimeCollection : inspectable_abi { virtual int32_t __stdcall Lookup(void*, void**) noexcept = 0; virtual int32_t __stdcall unused() noexcept = 0; @@ -74,23 +74,23 @@ namespace winrt::impl virtual int32_t __stdcall unused4() noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IWeakReference : unknown_abi + struct WINRT_IMPL_ABI_DECL IWeakReference : unknown_abi { virtual int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IWeakReferenceSource : unknown_abi + struct WINRT_IMPL_ABI_DECL IWeakReferenceSource : unknown_abi { virtual int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IRestrictedErrorInfo : unknown_abi + struct WINRT_IMPL_ABI_DECL IRestrictedErrorInfo : unknown_abi { virtual int32_t __stdcall GetErrorDetails(bstr* description, int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; virtual int32_t __stdcall GetReference(bstr* reference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IErrorInfo : unknown_abi + struct WINRT_IMPL_ABI_DECL IErrorInfo : unknown_abi { virtual int32_t __stdcall GetGUID(guid* value) noexcept = 0; virtual int32_t __stdcall GetSource(bstr* value) noexcept = 0; @@ -99,7 +99,7 @@ namespace winrt::impl virtual int32_t __stdcall GetHelpContext(uint32_t* value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE ILanguageExceptionErrorInfo2 : unknown_abi + struct WINRT_IMPL_ABI_DECL ILanguageExceptionErrorInfo2 : unknown_abi { virtual int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; virtual int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; @@ -109,12 +109,12 @@ namespace winrt::impl struct ICallbackWithNoReentrancyToApplicationSTA; - struct WINRT_IMPL_NOVTABLE IContextCallback : unknown_abi + struct WINRT_IMPL_ABI_DECL IContextCallback : unknown_abi { virtual int32_t __stdcall ContextCallback(int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IServerSecurity : unknown_abi + struct WINRT_IMPL_ABI_DECL IServerSecurity : unknown_abi { virtual int32_t __stdcall QueryBlanket(uint32_t*, uint32_t*, wchar_t**, uint32_t*, uint32_t*, void**, uint32_t*) noexcept = 0; virtual int32_t __stdcall ImpersonateClient() noexcept = 0; @@ -122,12 +122,12 @@ namespace winrt::impl virtual int32_t __stdcall IsImpersonating() noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IBufferByteAccess : unknown_abi + struct WINRT_IMPL_ABI_DECL IBufferByteAccess : unknown_abi { virtual int32_t __stdcall Buffer(uint8_t** value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IMemoryBufferByteAccess : unknown_abi + struct WINRT_IMPL_ABI_DECL IMemoryBufferByteAccess : unknown_abi { virtual int32_t __stdcall GetBuffer(uint8_t** value, uint32_t* capacity) noexcept = 0; }; diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 8902b3cc6..3d1457c2e 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -109,7 +109,7 @@ namespace winrt::impl } template - struct WINRT_IMPL_NOVTABLE variadic_delegate_abi : unknown_abi + struct WINRT_IMPL_ABI_DECL variadic_delegate_abi : unknown_abi { virtual R invoke(Args const& ...) = 0; }; diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 88d99469a..7291ab2af 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -10,6 +10,12 @@ #define WINRT_IMPL_FF_NOVTABLE #endif +#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#define WINRT_IMPL_FF_PUBLIC __attribute__((lto_visibility_public)) +#else +#define WINRT_IMPL_FF_PUBLIC +#endif + #if !defined(WINRT_FAST_ABI_SIZE) #define WINRT_FAST_ABI_SIZE % #endif @@ -36,7 +42,7 @@ namespace winrt::impl } }; - struct WINRT_IMPL_FF_NOVTABLE inspectable + struct WINRT_IMPL_FF_NOVTABLE WINRT_IMPL_FF_PUBLIC inspectable { virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; virtual uint32_t __stdcall AddRef() noexcept = 0; @@ -137,3 +143,4 @@ namespace winrt #undef WINRT_IMPL_STRING #undef WINRT_IMPL_STRING_1 #undef WINRT_IMPL_FF_NOVTABLE +#undef WINRT_IMPL_FF_PUBLIC diff --git a/strings/base_macros.h b/strings/base_macros.h index d9e19547e..42e958649 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -61,6 +61,14 @@ #define WINRT_IMPL_NOVTABLE #endif +#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#define WINRT_IMPL_PUBLIC __attribute__((lto_visibility_public)) +#else +#define WINRT_IMPL_PUBLIC +#endif + +#define WINRT_IMPL_ABI_DECL WINRT_IMPL_NOVTABLE WINRT_IMPL_PUBLIC + #if defined(__clang__) #define WINRT_IMPL_HAS_DECLSPEC_UUID __has_declspec_attribute(uuid) #elif defined(_MSC_VER) From 46fd3ed1ce7b2264fcdef8199794828094dfcd88 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Fri, 25 Apr 2025 11:39:39 -0700 Subject: [PATCH 260/305] All cppwinrt vcxproj should build with /W4 and /WX (warnings turned up, treated as error). Fix existing violations. (#1487) Why is this change being made? The most recent PR introduced a warning for non-Clang consumers. Many projects build with warnings-as-errors so this is a build break for those projects. Because cppwinrt is widely used by many such projects it should itself build with warnings as errors enabled so that this doesn't happen again in the future. Plus it is general goodness to build with warnings cranked up and blocking. Briefly summarize what changed I added /WX to every single vcxproj in this repo (which required a whole lot of redundant edits). Many of them didn't have /W4 so I added it wherever it was missing. The project files definitely need some refactoring to reduce duplication. But for this change I decided to modify them as-is without also including a refactoring. I also fixed the newly-blocking warnings. MSVC only had the one new warning to fix. Clang had a whole bunch of previously-unknown warnings that needed to be fixed or suppressed to get the build passing again. I also removed a typo'd (warning is singular, not plural) that was trying to disable warnings in one specific project. It has no warnings so we might as well baseline them as blocking. I also added a new clang-only test file to try and exercise the LTO public visibility annotation. How was this change tested? It builds locally (x64 Debug+Release, MSVC + Clang). --- Directory.Build.Props | 1 + cppwinrt/component_writers.h | 2 +- cppwinrt/cppwinrt.vcxproj | 12 ++++++++++ natvis/cppwinrtvisualizer.vcxproj | 6 +++++ prebuild/prebuild.vcxproj | 12 ++++++++++ scratch/scratch.vcxproj | 2 ++ strings/base_activation.h | 3 +-- strings/base_fast_forward.h | 16 +++++++++++-- strings/base_macros.h | 6 ++++- strings/base_string.h | 4 ++-- .../ConsoleApplication1.vcxproj | 1 + test/nuget/TestApp/TestApp.vcxproj | 1 + .../nuget/TestProxyStub/TestProxyStub.vcxproj | 3 ++- .../TestRuntimeComponent1.vcxproj | 1 + .../TestRuntimeComponent2.vcxproj | 1 + .../TestRuntimeComponent3.vcxproj | 1 + .../TestRuntimeComponentCX.vcxproj | 12 ++++++++++ ...entCXReferencingWinRTStaticLibrary.vcxproj | 12 ++++++++++ .../TestRuntimeComponentEmpty.vcxproj | 1 + ...untimeComponentNamespaceUnderscore.vcxproj | 1 + .../TestStaticLibrary1.vcxproj | 6 +++++ .../TestStaticLibrary2.vcxproj | 6 +++++ .../TestStaticLibrary3.vcxproj | 6 +++++ .../TestStaticLibrary4.vcxproj | 12 ++++++++++ .../TestStaticLibrary5.vcxproj | 12 ++++++++++ .../TestStaticLibrary6.vcxproj | 12 ++++++++++ .../TestStaticLibrary7.vcxproj | 1 + test/old_tests/Component/Component.vcxproj | 12 ++++++++++ test/old_tests/Composable/Base.cpp | 2 +- test/old_tests/Composable/Composable.vcxproj | 12 ++++++++++ test/old_tests/UnitTests/Boxing2.cpp | 10 ++++---- test/old_tests/UnitTests/Composable.cpp | 2 +- .../IInspectable_GetRuntimeClassName.cpp | 7 ++++++ test/old_tests/UnitTests/Tests.vcxproj | 12 ++++++++++ test/old_tests/UnitTests/array.cpp | 2 +- test/old_tests/UnitTests/produce.cpp | 7 ++++++ test/old_tests/UnitTests/smart_pointers.cpp | 6 +++++ test/test/disconnected.cpp | 2 +- test/test/event_deferral.cpp | 14 +++++++---- test/test/inspectable_interop.cpp | 7 ++++++ test/test/multi_threaded_map.cpp | 2 +- test/test/out_params.cpp | 4 ++-- test/test/return_params_abi.cpp | 7 ++++++ test/test/struct_delegate.cpp | 2 +- test/test/test.vcxproj | 12 ++++++++++ test/test_component/Class.cpp | 7 ++++++ test/test_component/test_component.vcxproj | 12 ++++++++++ test/test_component_base/HierarchyA.cpp | 4 ++-- test/test_component_base/HierarchyB.cpp | 2 +- .../test_component_base.vcxproj | 12 ++++++++++ .../Nested.HierarchyD.cpp | 2 +- .../test_component_derived.vcxproj | 12 ++++++++++ .../test_component_fast.vcxproj | 12 ++++++++++ .../test_component_folders.vcxproj | 12 ++++++++++ .../test_component_no_pch.vcxproj | 12 ++++++++++ test/test_cpp20/array_span.cpp | 2 +- test/test_cpp20/clang_only.cpp | 23 +++++++++++++++++++ test/test_cpp20/test_cpp20.vcxproj | 19 +++++++++++++++ .../custom_error.cpp | 2 +- .../test_cpp20_no_sourcelocation.vcxproj | 2 ++ test/test_fast/Nomadic.cpp | 8 +++++++ test/test_fast/test_fast.vcxproj | 12 ++++++++++ test/test_fast_fwd/test_fast_fwd.vcxproj | 12 ++++++++++ .../test_module_lock_custom.vcxproj | 12 ++++++++++ test/test_module_lock_none/main.cpp | 7 ++++++ .../test_module_lock_none.vcxproj | 12 ++++++++++ test/test_slow/test_slow.vcxproj | 12 ++++++++++ .../ConsoleApplication.vcxproj | 1 + .../WindowsApplication.vcxproj | 1 + .../BlankApp/BlankApp.vcxproj | 1 + .../Windows Universal/CoreApp/CoreApp.vcxproj | 1 + .../StaticLibrary/StaticLibrary.vcxproj | 1 + .../WindowsRuntimeComponent.vcxproj | 1 + 73 files changed, 458 insertions(+), 33 deletions(-) create mode 100644 test/test_cpp20/clang_only.cpp diff --git a/Directory.Build.Props b/Directory.Build.Props index 0a8e5b37b..9088021c1 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -49,6 +49,7 @@ Level4 + true true true stdcpp17 diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 6865d49ef..cb748917d 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -754,7 +754,7 @@ catch (...) { return winrt::to_hresult(); } using implements_type = typename %_base::implements_type; using implements_type::implements_type; %% - hstring GetRuntimeClassName() const + hstring GetRuntimeClassName() const override { return L"%.%"; } diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 069f8103a..b8beed890 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -176,6 +176,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -193,6 +195,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -210,6 +214,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -230,6 +236,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console @@ -253,6 +261,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console @@ -276,6 +286,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index cc17bf500..af3fbcf1f 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -103,6 +103,7 @@ Use Level4 + true Disabled VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) @@ -127,6 +128,7 @@ Use Level4 + true Disabled VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) @@ -150,6 +152,7 @@ Use Level4 + true Disabled VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) @@ -173,6 +176,7 @@ Use Level4 + true MaxSpeed true true @@ -202,6 +206,7 @@ Use Level4 + true MaxSpeed true true @@ -231,6 +236,7 @@ Use Level4 + true MaxSpeed true true diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index 6e0bc4b71..9fad91fd8 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -88,6 +88,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -98,6 +100,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -108,6 +112,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -121,6 +127,8 @@ ..\cppwinrt MultiThreaded Guard + Level4 + true Console @@ -136,6 +144,8 @@ ..\cppwinrt MultiThreaded Guard + Level4 + true Console @@ -151,6 +161,8 @@ ..\cppwinrt MultiThreaded Guard + Level4 + true Console diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 98ed21948..84f6ce3d8 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -53,6 +53,8 @@ $(OutputPath);Generated Files; + Level4 + true Console diff --git a/strings/base_activation.h b/strings/base_activation.h index be24c6ad9..586df32e9 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -257,8 +257,7 @@ namespace winrt::impl } private: - - size_t& m_count; + [[maybe_unused]] size_t& m_count; // Field is unused when WINRT_NO_MODULE_LOCK is defined. }; struct factory_cache_entry_base diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 7291ab2af..3ca34dba7 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -10,10 +10,14 @@ #define WINRT_IMPL_FF_NOVTABLE #endif -#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(__lto_visibility_public__) #define WINRT_IMPL_FF_PUBLIC __attribute__((lto_visibility_public)) #else #define WINRT_IMPL_FF_PUBLIC +#endif // __has_attribute(__lto_visibility_public__) +#else +#define WINRT_IMPL_FF_PUBLIC #endif #if !defined(WINRT_FAST_ABI_SIZE) @@ -59,7 +63,7 @@ namespace winrt::impl std::atomic m_references{ 1 }; fast_abi_forwarder(void* owner, guid const& iid, std::size_t offset) noexcept : - m_vfptr(s_vtable), m_owner(static_cast(owner)), m_iid(iid), m_offset(offset) + m_vfptr(s_vtable), m_owner(static_cast(owner)), m_offset(offset), m_iid(iid) { m_owner->AddRef(); } @@ -112,6 +116,11 @@ namespace winrt::impl return self->m_owner->GetTrustLevel(level); } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmicrosoft-cast" +#endif static inline void* const s_vtable[] = { QueryInterface, @@ -121,6 +130,9 @@ namespace winrt::impl GetRuntimeClassName, GetTrustLevel, % }; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; // Enforce assumptions made by thunk asm code diff --git a/strings/base_macros.h b/strings/base_macros.h index 42e958649..0c4357b1e 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -61,10 +61,14 @@ #define WINRT_IMPL_NOVTABLE #endif -#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(__lto_visibility_public__) #define WINRT_IMPL_PUBLIC __attribute__((lto_visibility_public)) #else #define WINRT_IMPL_PUBLIC +#endif // __has_attribute(__lto_visibility_public__) +#else +#define WINRT_IMPL_PUBLIC #endif #define WINRT_IMPL_ABI_DECL WINRT_IMPL_NOVTABLE WINRT_IMPL_PUBLIC diff --git a/strings/base_string.h b/strings/base_string.h index e70eed925..81229e3d5 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -574,8 +574,8 @@ namespace winrt::impl // when non-const (e.g. ranges::filter_view) so taking a const reference // as parameter wouldn't work for all scenarios. auto const size = std::formatted_size(args...); - WINRT_ASSERT(size < UINT_MAX); - auto const size32 = static_cast(size); + WINRT_ASSERT(size < INT_MAX); + auto const size32 = static_cast(size); hstring_builder builder(size32); WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj index 819c788d8..38f3ee4cc 100644 --- a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj +++ b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj @@ -70,6 +70,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/test/nuget/TestApp/TestApp.vcxproj b/test/nuget/TestApp/TestApp.vcxproj index 84029a4c9..f14bd9f0b 100644 --- a/test/nuget/TestApp/TestApp.vcxproj +++ b/test/nuget/TestApp/TestApp.vcxproj @@ -70,6 +70,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj diff --git a/test/nuget/TestProxyStub/TestProxyStub.vcxproj b/test/nuget/TestProxyStub/TestProxyStub.vcxproj index 899a5c11c..69e41cfba 100644 --- a/test/nuget/TestProxyStub/TestProxyStub.vcxproj +++ b/test/nuget/TestProxyStub/TestProxyStub.vcxproj @@ -35,7 +35,6 @@ 10.0.22621.0 10.0.18362.0 - false false @@ -55,6 +54,8 @@ Use pch.h %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + Level4 + true Windows diff --git a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj index 1b7621ea0..b1ee4f43f 100644 --- a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj +++ b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj @@ -74,6 +74,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj index 48f9acfb0..c27db2602 100644 --- a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj +++ b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj index 8a876e601..01c84d830 100644 --- a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj +++ b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj index 237b9fcf3..819cff52b 100644 --- a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj +++ b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj @@ -103,6 +103,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -119,6 +121,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -135,6 +139,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -151,6 +157,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -167,6 +175,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -183,6 +193,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console diff --git a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj index 68b71c94e..6ce188345 100644 --- a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj +++ b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj @@ -117,6 +117,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -132,6 +134,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -147,6 +151,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -162,6 +168,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -177,6 +185,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -192,6 +202,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 diff --git a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj index 7572238eb..60786eddb 100644 --- a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj +++ b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj index 693a97596..fb8146340 100644 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj +++ b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj index a34e7429c..13ac4e201 100644 --- a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj +++ b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -115,6 +117,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -174,6 +179,7 @@ Use Level4 + true MaxSpeed true true diff --git a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj index 5f3ee5220..b419d183e 100644 --- a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj +++ b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -115,6 +117,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -174,6 +179,7 @@ Use Level4 + true MaxSpeed true true diff --git a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj index c79a847a3..210802841 100644 --- a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj +++ b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -115,6 +117,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -174,6 +179,7 @@ Use Level4 + true MaxSpeed true true diff --git a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj index b3efe02c4..357d0ca70 100644 --- a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj +++ b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -126,6 +130,8 @@ Use false true + Level4 + true Console @@ -138,6 +144,8 @@ Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console diff --git a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj index bfc6db45c..d93446a05 100644 --- a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj +++ b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -126,6 +130,8 @@ Use false true + Level4 + true Console @@ -138,6 +144,8 @@ Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console diff --git a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj index 89a0e55c9..626e60dab 100644 --- a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj +++ b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -126,6 +130,8 @@ Use false true + Level4 + true Console @@ -138,6 +144,8 @@ Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index 0fdf11744..85d6bec7f 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -76,6 +76,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index 6c7df9527..162c8fec7 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -140,6 +140,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -174,6 +176,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -209,6 +213,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -242,6 +248,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -278,6 +286,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -311,6 +321,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 diff --git a/test/old_tests/Composable/Base.cpp b/test/old_tests/Composable/Base.cpp index a1a1678ff..af2423569 100644 --- a/test/old_tests/Composable/Base.cpp +++ b/test/old_tests/Composable/Base.cpp @@ -43,7 +43,7 @@ namespace winrt::Composable::implementation int32_t Base::ProtectedMethod() { - return 0xDEADBEEF; + return static_cast(0xDEADBEEF); } hstring Base::Name() const diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index 4e49a255e..fcfd095fc 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -140,6 +140,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -174,6 +176,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -209,6 +213,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -242,6 +248,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -278,6 +286,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -311,6 +321,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp diff --git a/test/old_tests/UnitTests/Boxing2.cpp b/test/old_tests/UnitTests/Boxing2.cpp index cd912ce58..43ca7efd9 100644 --- a/test/old_tests/UnitTests/Boxing2.cpp +++ b/test/old_tests/UnitTests/Boxing2.cpp @@ -41,19 +41,19 @@ namespace REQUIRE(unbox_value_or(wrong_type, v2) == v2); } - REQUIRE(object.as() == v1); - REQUIRE(object.try_as() == v1); - REQUIRE(nothing.try_as() == std::nullopt); + REQUIRE(object.template as() == v1); + REQUIRE(object.template try_as() == v1); + REQUIRE(nothing.template try_as() == std::nullopt); REQUIRE(wrong_type.try_as() == std::nullopt); T result{ v2 }; - object.as(result); + object.template as(result); REQUIRE(result == v1); result = v1; REQUIRE(v1 != empty()); // Test must pass a v1 that is not equal to the empty value. - REQUIRE(!nothing.try_as(result)); + REQUIRE(!nothing.template try_as(result)); REQUIRE(result == empty()); // try_as explicitly empties the result on failure result = v1; diff --git a/test/old_tests/UnitTests/Composable.cpp b/test/old_tests/UnitTests/Composable.cpp index 080e3769c..a9d354c08 100644 --- a/test/old_tests/UnitTests/Composable.cpp +++ b/test/old_tests/UnitTests/Composable.cpp @@ -14,7 +14,7 @@ namespace constexpr auto Base_OverridableMethod{ L"Base::OverridableMethod"sv }; constexpr auto Base_OverridableVirtualMethod{ L"Base::OverridableVirtualMethod"sv }; constexpr auto Base_OverridableNoexceptMethod{ 42 }; - constexpr auto Base_ProtectedMethod{ 0xDEADBEEF }; + constexpr auto Base_ProtectedMethod{ static_cast(0xDEADBEEF) }; constexpr auto Derived_VirtualMethod{ L"Derived::VirtualMethod"sv }; constexpr auto Derived_OverridableVirtualMethod{ L"Derived::OverridableVirtualMethod"sv }; diff --git a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp index 7db7ed869..53b5260fb 100644 --- a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp +++ b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp @@ -18,10 +18,17 @@ struct Test_GetRuntimeClassName_NoOverride : implements { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" +#endif hstring GetRuntimeClassName() { return L"GetRuntimeClassName"; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; TEST_CASE("Test_GetRuntimeClassName_NoOverride") diff --git a/test/old_tests/UnitTests/Tests.vcxproj b/test/old_tests/UnitTests/Tests.vcxproj index a0711f41d..c5169ad4d 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj +++ b/test/old_tests/UnitTests/Tests.vcxproj @@ -206,6 +206,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -225,6 +227,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -244,6 +248,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -261,6 +267,8 @@ _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 @@ -280,6 +288,8 @@ _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 @@ -299,6 +309,8 @@ _HAS_AUTO_PTR_ETC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 diff --git a/test/old_tests/UnitTests/array.cpp b/test/old_tests/UnitTests/array.cpp index f6a7654f3..2b5952004 100644 --- a/test/old_tests/UnitTests/array.cpp +++ b/test/old_tests/UnitTests/array.cpp @@ -17,7 +17,7 @@ using namespace Windows::Security::Cryptography::Certificates; // // This is a helper to create a data reader for use in testing arrays. // -static IAsyncOperation CreateDataReader(std::initializer_list values) +static IAsyncOperation CreateDataReader(std::initializer_list /*values*/) { InMemoryRandomAccessStream stream; DataWriter writer(stream); diff --git a/test/old_tests/UnitTests/produce.cpp b/test/old_tests/UnitTests/produce.cpp index 149466002..9ac76ad18 100644 --- a/test/old_tests/UnitTests/produce.cpp +++ b/test/old_tests/UnitTests/produce.cpp @@ -124,10 +124,17 @@ struct produce_IInspectable_No_RuntimeClassName : implements { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" +#endif hstring GetRuntimeClassName() { return L"produce_IInspectable_RuntimeClassName"; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; TEST_CASE("produce_IInspectable_RuntimeClassName") diff --git a/test/old_tests/UnitTests/smart_pointers.cpp b/test/old_tests/UnitTests/smart_pointers.cpp index fc760fb48..92dca1396 100644 --- a/test/old_tests/UnitTests/smart_pointers.cpp +++ b/test/old_tests/UnitTests/smart_pointers.cpp @@ -7,6 +7,12 @@ using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Component; + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wself-assign-overloaded" +#pragma clang diagnostic ignored "-Wself-move" +#endif + namespace { struct Type : implements diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 53dfbd142..be356fcb3 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -148,7 +148,7 @@ struct non_agile_abandoned_action : implements disconnect) : m_disconnect(disconnect) {} - static fire_and_forget final_release(std::unique_ptr self) + static fire_and_forget final_release(std::unique_ptr /*self*/) { // The C++/WinRT m_handler is agile but not context-aware, // so we need to make sure to release it from the context it diff --git a/test/test/event_deferral.cpp b/test/test/event_deferral.cpp index 9b83a2602..e5b538ca2 100644 --- a/test/test/event_deferral.cpp +++ b/test/test/event_deferral.cpp @@ -38,7 +38,7 @@ namespace // This exercises the short-circuit logic in deferrable_event_args. auto NoDeferralHandler() { - return [=](Class const& sender, DeferrableEventArgs const& args) + return [this](Class const& sender, DeferrableEventArgs const& args) { REQUIRE(sender == c); args.IncrementCounter(); @@ -50,7 +50,7 @@ namespace // deferrable_event_args. auto PointlessDeferralHandler() { - return [=](Class const& sender, DeferrableEventArgs const& args) + return [this](Class const& sender, DeferrableEventArgs const& args) { REQUIRE(sender == c); auto deferral = args.GetDeferral(); @@ -61,15 +61,19 @@ namespace auto TakeDeferralHandler(int startState, int finishState) { - return [=](Class sender, DeferrableEventArgs args) -> fire_and_forget + return [this, startState, finishState](Class sender, DeferrableEventArgs args) -> fire_and_forget { + // Captures will go out of scope after the first co_await call. Copy anything needed after that point. + const auto startStateCopy = startState; + const auto finishStateCopy = finishState; + REQUIRE(sender == c); auto deferral = args.GetDeferral(); co_await resume_background(); - wait_for_state(startState); + wait_for_state(startStateCopy); args.IncrementCounter(); deferral.Complete(); - go_to_state(finishState); + go_to_state(finishStateCopy); }; } }; diff --git a/test/test/inspectable_interop.cpp b/test/test/inspectable_interop.cpp index e9094ca77..6a8db907a 100644 --- a/test/test/inspectable_interop.cpp +++ b/test/test/inspectable_interop.cpp @@ -41,11 +41,18 @@ namespace #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" #endif Windows::Foundation::TrustLevel GetTrustLevel() const noexcept { return Windows::Foundation::TrustLevel::PartialTrust; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index b2b143f11..d0f68c1e2 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -90,7 +90,7 @@ namespace using const_reverse_iterator = std::reverse_iterator; using node_type = typename inner::node_type; - mapped_type& operator[](const key_type& key) + mapped_type& operator[](const key_type& /*key*/) { auto guard = concurrency_guard::lock_nonconst(); concurrency_guard::call_hook(collection_action::at); diff --git a/test/test/out_params.cpp b/test/test/out_params.cpp index 7aafb63ae..7fd2f536e 100644 --- a/test/test/out_params.cpp +++ b/test/test/out_params.cpp @@ -134,7 +134,7 @@ TEST_CASE("out_params") REQUIRE(value[3] == nullptr); } { - std::array value{ {L"First", L"Second"} }; + std::array value{ { { L"First" }, { L"Second"} } }; object.RefStructArray(value); REQUIRE(value[0].First == L"1"); REQUIRE(value[0].Second == L"2"); @@ -260,7 +260,7 @@ TEST_CASE("out_params") REQUIRE(value[3] == nullptr); } { - std::array value{ {L"First", L"Second"} }; + std::array value{ { { L"First" }, { L"Second"} } }; REQUIRE_THROWS_AS(object.RefStructArray(value), hresult_invalid_argument); REQUIRE(value[0].First == L""); REQUIRE(value[0].Second == L""); diff --git a/test/test/return_params_abi.cpp b/test/test/return_params_abi.cpp index 1d4af9a9f..5e7c11cd3 100644 --- a/test/test/return_params_abi.cpp +++ b/test/test/return_params_abi.cpp @@ -12,12 +12,19 @@ using namespace winrt; namespace { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif hstring to_hstring(::IInspectable* raw) { winrt::IInspectable object; copy_from_abi(object, raw); return object.as().ToString(); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } TEST_CASE("return_params_abi") diff --git a/test/test/struct_delegate.cpp b/test/test/struct_delegate.cpp index 26fcd9e64..785a0fb0a 100644 --- a/test/test/struct_delegate.cpp +++ b/test/test/struct_delegate.cpp @@ -1,5 +1,5 @@ #include "pch.h" -#include "winrt/test_component.delegates.h" +#include "winrt/test_component.Delegates.h" using namespace winrt; using namespace test_component; diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index f1035ab6c..7840f17eb 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -112,6 +114,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -130,6 +134,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -148,6 +154,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -168,6 +176,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -190,6 +200,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_component/Class.cpp b/test/test_component/Class.cpp index 4f36df5c1..3f68d96c3 100644 --- a/test/test_component/Class.cpp +++ b/test/test_component/Class.cpp @@ -519,7 +519,14 @@ namespace winrt::test_component::implementation namespace { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif void ValidateStaticEventAutoRevoke() { auto x = winrt::test_component::Simple::StaticEvent(winrt::auto_revoke, [](auto&&, auto&&) {}); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } \ No newline at end of file diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 9751fb5a2..3ffdb8f97 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -114,6 +114,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -150,6 +152,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -199,6 +203,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -237,6 +243,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true @@ -277,6 +285,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true @@ -330,6 +340,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true diff --git a/test/test_component_base/HierarchyA.cpp b/test/test_component_base/HierarchyA.cpp index 887b31bc9..45b3e6098 100644 --- a/test/test_component_base/HierarchyA.cpp +++ b/test/test_component_base/HierarchyA.cpp @@ -3,11 +3,11 @@ namespace winrt::test_component_base::implementation { - HierarchyA::HierarchyA(hstring const& name) + HierarchyA::HierarchyA(hstring const& /*name*/) { throw hresult_not_implemented(); } - HierarchyA::HierarchyA(int32_t dummy, hstring const& name) + HierarchyA::HierarchyA(int32_t /*dummy*/, hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/HierarchyB.cpp b/test/test_component_base/HierarchyB.cpp index 30b9f09ff..b56988f73 100644 --- a/test/test_component_base/HierarchyB.cpp +++ b/test/test_component_base/HierarchyB.cpp @@ -5,7 +5,7 @@ namespace winrt::test_component_base::implementation { - HierarchyB::HierarchyB(hstring const& name) + HierarchyB::HierarchyB(hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index 947c53e8f..90577a2c5 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -114,6 +114,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -162,6 +164,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -224,6 +228,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -274,6 +280,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true @@ -326,6 +334,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true @@ -392,6 +402,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true diff --git a/test/test_component_derived/Nested.HierarchyD.cpp b/test/test_component_derived/Nested.HierarchyD.cpp index bad2cf1ce..8011e73e6 100644 --- a/test/test_component_derived/Nested.HierarchyD.cpp +++ b/test/test_component_derived/Nested.HierarchyD.cpp @@ -3,7 +3,7 @@ namespace winrt::test_component_derived::Nested::implementation { - HierarchyD::HierarchyD(hstring const& name) + HierarchyD::HierarchyD(hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index a1c856c90..837d8821e 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -112,6 +112,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -161,6 +163,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -224,6 +228,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -275,6 +281,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded @@ -328,6 +336,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded @@ -395,6 +405,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index 5d646cf78..ed5a36222 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -114,6 +114,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -163,6 +165,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -226,6 +230,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -277,6 +283,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded @@ -330,6 +338,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded @@ -397,6 +407,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index 6d642096f..14c12f8f9 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -112,6 +112,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -160,6 +162,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -222,6 +226,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -272,6 +278,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded @@ -324,6 +332,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded @@ -390,6 +400,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 0b1a98271..117be2d00 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -112,6 +112,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -161,6 +163,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -224,6 +228,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -275,6 +281,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded @@ -328,6 +336,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded @@ -395,6 +405,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded diff --git a/test/test_cpp20/array_span.cpp b/test/test_cpp20/array_span.cpp index dff5a2ec5..8cebc4a1e 100644 --- a/test/test_cpp20/array_span.cpp +++ b/test/test_cpp20/array_span.cpp @@ -10,7 +10,7 @@ using namespace Windows::Data::Json; // // This is a helper to create a data reader for use in testing arrays. // -static IAsyncOperation CreateDataReader(std::initializer_list values) +static IAsyncOperation CreateDataReader(std::initializer_list /*values*/) { InMemoryRandomAccessStream stream; DataWriter writer(stream); diff --git a/test/test_cpp20/clang_only.cpp b/test/test_cpp20/clang_only.cpp new file mode 100644 index 000000000..45aa4b380 --- /dev/null +++ b/test/test_cpp20/clang_only.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include + +#ifdef __clang__ + +using namespace winrt; +using namespace Windows::Foundation; +using namespace Windows::Storage::Pickers; + +TEST_CASE("clang_lto_visibility") +{ + // A previous bug report (https://github.com/microsoft/cppwinrt/pull/1482) represented a problem when some linker + // options (-O3 -flto -fwhole-program-vtables) were used with cppwinrt generated code. The lack of public annotation + // caused methods to be removed from the binary, leading to a crash. This test case aims to be a regression test for + // that problem. + FileOpenPicker picker{}; + picker.ViewMode(PickerViewMode::Thumbnail); + picker.FileTypeFilter().Append(L".png"); // This line would trigger the crash. + + REQUIRE(true); +} + +#endif // __clang__ \ No newline at end of file diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 832297f7f..4eaee0a18 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -93,6 +93,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -114,6 +117,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -133,6 +139,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -152,6 +161,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -173,6 +185,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -196,6 +211,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -217,6 +235,7 @@ + diff --git a/test/test_cpp20_no_sourcelocation/custom_error.cpp b/test/test_cpp20_no_sourcelocation/custom_error.cpp index 43e5f16d9..d9905ea04 100644 --- a/test/test_cpp20_no_sourcelocation/custom_error.cpp +++ b/test/test_cpp20_no_sourcelocation/custom_error.cpp @@ -53,7 +53,7 @@ TEST_CASE("custom_error_logger") REQUIRE(s_loggerArgs.functionName == nullptr); REQUIRE(s_loggerArgs.returnAddress); - REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + REQUIRE(s_loggerArgs.result == static_cast(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) // Remove global handler winrt_throw_hresult_handler = nullptr; diff --git a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj index 86a56a3b9..85c3e1532 100644 --- a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj +++ b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj @@ -89,6 +89,8 @@ WINRT_NO_SOURCE_LOCATION;%(PreprocessorDefinitions) + Level4 + true diff --git a/test/test_fast/Nomadic.cpp b/test/test_fast/Nomadic.cpp index 98753c06d..c29150e17 100644 --- a/test/test_fast/Nomadic.cpp +++ b/test/test_fast/Nomadic.cpp @@ -11,7 +11,15 @@ hstring invoke_by_interface_vtable_offset(Nomadic const& nomadic, ptrdiff_t offs // that IInspectable has 6 functions in total (including those inherited from IUnknown) auto insp = static_cast<::IInspectable*>(get_abi(nomadic)); auto vtable = *reinterpret_cast(insp); + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmicrosoft-cast" +#endif auto fn_ptr = static_cast(vtable[6 + offset]); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif HSTRING hstr; check_hresult(fn_ptr(insp, &hstr)); diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj index 27a7ea350..c01907348 100644 --- a/test/test_fast/test_fast.vcxproj +++ b/test/test_fast/test_fast.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -113,6 +115,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -132,6 +136,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -151,6 +157,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -172,6 +180,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -195,6 +205,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_fast_fwd/test_fast_fwd.vcxproj b/test/test_fast_fwd/test_fast_fwd.vcxproj index d4b63c3fb..6d049b1a9 100644 --- a/test/test_fast_fwd/test_fast_fwd.vcxproj +++ b/test/test_fast_fwd/test_fast_fwd.vcxproj @@ -59,6 +59,8 @@ true $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -86,6 +88,8 @@ pch.h true WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -106,6 +110,8 @@ Disabled $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -123,6 +129,8 @@ Disabled $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -146,6 +154,8 @@ pch.h true WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -166,6 +176,8 @@ true $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console diff --git a/test/test_module_lock_custom/test_module_lock_custom.vcxproj b/test/test_module_lock_custom/test_module_lock_custom.vcxproj index 6671a1156..64da0d8bc 100644 --- a/test/test_module_lock_custom/test_module_lock_custom.vcxproj +++ b/test/test_module_lock_custom/test_module_lock_custom.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -113,6 +115,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -132,6 +136,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -151,6 +157,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -172,6 +180,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -195,6 +205,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_module_lock_none/main.cpp b/test/test_module_lock_none/main.cpp index ca8eab7ac..9648ad8be 100644 --- a/test/test_module_lock_none/main.cpp +++ b/test/test_module_lock_none/main.cpp @@ -57,11 +57,18 @@ TEST_CASE("module_lock_none") // Validates that test_component_base is pinned by virtue of it defining WINRT_NO_MODULE_LOCK. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-mismatch" +#endif auto can_unload = reinterpret_cast(GetProcAddress(LoadLibraryA("test_component_base.dll"), "DllCanUnloadNow")); REQUIRE(can_unload() == S_FALSE); auto cannot_unload = reinterpret_cast(GetProcAddress(LoadLibraryA("test_component_derived.dll"), "DllCanUnloadNow")); REQUIRE(cannot_unload() == S_OK); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } int main(int const argc, char** argv) diff --git a/test/test_module_lock_none/test_module_lock_none.vcxproj b/test/test_module_lock_none/test_module_lock_none.vcxproj index 381edbdfe..d9242a281 100644 --- a/test/test_module_lock_none/test_module_lock_none.vcxproj +++ b/test/test_module_lock_none/test_module_lock_none.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -113,6 +115,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -132,6 +136,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -151,6 +157,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -172,6 +180,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -195,6 +205,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_slow/test_slow.vcxproj b/test/test_slow/test_slow.vcxproj index eb6c7fc60..5b753a17a 100644 --- a/test/test_slow/test_slow.vcxproj +++ b/test/test_slow/test_slow.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -112,6 +114,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -130,6 +134,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -148,6 +154,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -168,6 +176,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -190,6 +200,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj index f82376473..f205306b8 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj @@ -67,6 +67,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj index 8b8cb03ce..e4a05cdc7 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj @@ -67,6 +67,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index 30630610e..ae3d074f2 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -76,6 +76,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index 841ff85c9..2d891ef11 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index ec8126558..2afea1c00 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -81,6 +81,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 78c477177..da87bf2fb 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -80,6 +80,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) From 4c9e03fe1e3d7cbfbf742ec237e9af5b30add68a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 4 May 2025 13:51:28 -0500 Subject: [PATCH 261/305] fix indent in generated code (#1489) Fix a line that was indented too much in the generated code. --- cppwinrt/code_writers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index ae2920d56..ffc0ee948 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1868,7 +1868,7 @@ namespace cppwinrt { auto param_name = param.Name(); - w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); + w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); } } } From 1a678d68b9e3ad25722318127d15057d377dac16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:06:52 -0700 Subject: [PATCH 262/305] Bump actions/checkout from 4 to 5 (#1502) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8544bcf77..11fc05c26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Download nuget run: | @@ -102,7 +102,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' @@ -250,7 +250,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install cross compiler run: | @@ -283,7 +283,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Download nuget run: | @@ -323,7 +323,7 @@ jobs: config: [Release] runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Fetch cppwinrt executables uses: actions/download-artifact@v4 @@ -368,7 +368,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Package run: | From a338c862c43e16ee8c3ba77bcae92d821be2deb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:35:09 -0700 Subject: [PATCH 263/305] Bump actions/download-artifact from 4 to 5 (#1501) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11fc05c26..866fddd7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v5 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From 34fba98b48cc4cf98e069f7f2c1f7f51122894cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 13:59:36 -0500 Subject: [PATCH 264/305] Bump actions/stale from 9 to 10 (#1507) --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c081bdf43..b686df568 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 10 From ebace4abb8f48b6b9a612e8b84667e6044976a47 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 16 Oct 2025 09:33:43 -0700 Subject: [PATCH 265/305] Fix CI build by using latest Windows SDK in C# project (#1516) * Attempt "latest SDK" setting * Update TargetPlatformVersion to use WindowsSDKVersion * Fix TargetPlatformVersion trimming in project file --- .../TestRuntimeComponentCSharp.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index d756e19b7..167b32ad9 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -11,7 +11,7 @@ TestRuntimeComponentCSharp en-US UAP - 10.0.22621.0 + $(WindowsSDKVersion.TrimEnd('\')) 10.0.18362.0 14 512 @@ -93,4 +93,4 @@ --> - \ No newline at end of file + From dcaa98c8d2abeb47ab5ce9ef1f96171e93d0ff9b Mon Sep 17 00:00:00 2001 From: antmor <43587397+antmor@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:59:16 -0700 Subject: [PATCH 266/305] Remove throwing/originating errors in expected scenarios (Lookup/TryLookup and Cancel) (#1512) * non-originating error compiles * fix with test cases * and remove ignore * add runsettings to run tests from visual studio tester, modified readme, make shouldOrigiante a template param. * change map shouldOriginate to template parameter. Note, could be a breakig change for usages of map that are not default (i.e. custom std::less) if so, might need to split up templates into separate template, or spin out into separate pr. changed bool to template parameter in hresult_error, as the char*-to-bool decaying conversion failed the old tests. also fixed runsettings, added note in readme. * settle on avoid_originate as naming scheme * add a printf only to Lookup so we can add SFINAE or something like that. * weird templating magic required... still not working, has error 1>G:\source\repos\cppwinrt\_build\x64\Debug\winrt\Windows.Foundation.Collections.h(868,51): error C3878: syntax error: unexpected token '>' following 'simple-type-specifier' 1>(compiling source file '/Class.cpp') 1> G:\source\repos\cppwinrt\_build\x64\Debug\winrt\Windows.Foundation.Collections.h(868,51): 1> missing one of: '(' '{' ? * trylookup exists to avoid throwing an error, and let's avoid avoid_originate now. * remove test. * cleaned up and correctness. * undo changes to untouched files * spacing changes , change do declval. * added special tag to parameter list to make sure not to break existing TryLookup impls, added test to verify this. * address avoid_oritinate comment, no need for a different name, resuse existing hresult_cancelled * change out async to a new name, with it being true by default. add new unittest to test nullable lookup. * Address hresult comments by adding tests and removing source_locatoin, special-cased further by checking the typename. * add unittest without specialization, make sure that the behaviour is opt-in --------- Co-authored-by: Chris Guzak --- .runsettings | 24 +++++ README.md | 5 + cppwinrt/code_writers.h | 80 ++++++++++++++-- strings/base_collections_base.h | 15 +++ strings/base_coroutine_foundation.h | 22 ++++- strings/base_coroutine_threadpool.h | 11 +++ strings/base_error.h | 8 ++ strings/base_meta.h | 16 ++++ test/old_tests/UnitTests/Errors.cpp | 1 + test/old_tests/UnitTests/TryLookup.cpp | 127 ++++++++++++++++++++++++- test/test/async_check_cancel.cpp | 80 +++++++++++++++- test/test_cpp20/custom_error.cpp | 63 +++++++++++- 12 files changed, 437 insertions(+), 15 deletions(-) create mode 100644 .runsettings diff --git a/.runsettings b/.runsettings new file mode 100644 index 000000000..5f10e44f8 --- /dev/null +++ b/.runsettings @@ -0,0 +1,24 @@ + + + + .\TestResults + 60000 + true + + + + + + + Single + (?i:Test) + true + on + true + Verbose + AdditionalInfo + ShortInfo + , + 20000 + + \ No newline at end of file diff --git a/README.md b/README.md index 1749fea0c..19e1493dc 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,8 @@ a dev command prompt at the root of the repo _after_ following the above build i * Run `build_prior_projection.cmd` in the dev command prompt as well * Run `prepare_versionless_diffs.cmd` which removes version stamps on both current and prior projection * Use a directory-level differencing tool to compare `_build\$(arch)\$(flavor)\winrt` and `_reference\$(arch)\$(flavor)\winrt` + +## Testing +This repository uses the [Catch2](https://github.com/catchorg/Catch2) testing framework. +- From a Visual Studio command line, you should run `build_tests_all.cmd` to build and run the tests. To Debug the tests, you can debug the associated `_build\$(arch)\$(flavor)\.exe` under the debugger of your choice. +- Optionally, you can install the [Catch2Adapter](https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01) to run the tests from Visual Studio. \ No newline at end of file diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index ffc0ee948..35e9935d0 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1873,7 +1873,37 @@ namespace cppwinrt } } - static void write_produce_method(writer& w, MethodDef const& method) + static void write_produce_upcall_TryLookup(writer& w, std::string_view const& upcall, method_signature const& method_signature) + { + auto name = method_signature.return_param_name(); + + w.write("auto out_param_val = %(%, trylookup_from_abi);", + upcall, + bind(method_signature)); + w.write(R"( + if (out_param_val.has_value()) + { + *% = detach_from<%>(std::move(*out_param_val)); + } + else + { + return impl::error_out_of_bounds; + } +)", + name, method_signature.return_signature()); + + for (auto&& [param, param_signature] : method_signature.params()) + { + if (param.Flags().Out() && !param_signature->Type().is_szarray() && is_object(param_signature->Type())) + { + auto param_name = param.Name(); + + w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); + } + } + } + + static void write_produce_method(writer& w, MethodDef const& method, TypeDef const& type) { std::string_view format; @@ -1902,13 +1932,45 @@ namespace cppwinrt method_signature signature{ method }; auto async_types_guard = w.push_async_types(signature.is_async()); std::string upcall = "this->shim()."; - upcall += get_name(method); + auto name = get_name(method); + upcall += name; - w.write(format, - get_abi_name(method), - bind(signature), - bind(signature), - bind(upcall, signature)); + auto typeName = type.TypeName(); + if (((typeName == "IMapView`2") || (typeName == "IMap`2")) + && (name == "Lookup")) + { + // Special-case IMap*::Lookup to look for a TryLookup here, to avoid extranous throw/originates + std::string tryLookupUpCall = "this->shim().TryLookup"; + format = R"( int32_t __stdcall %(%) noexcept final try + { +% typename D::abi_guard guard(this->shim()); + if constexpr (has_TryLookup_v) + { + % + } + else + { + % + } + return 0; + } + catch (...) { return to_hresult(); } +)"; + w.write(format, + get_abi_name(method), + bind(signature), + bind(signature), // clear_abi + bind(tryLookupUpCall, signature), + bind(upcall, signature)); + } + else + { + w.write(format, + get_abi_name(method), + bind(signature), + bind(signature), + bind(upcall, signature)); + } } static void write_fast_produce_methods(writer& w, TypeDef const& default_interface) @@ -1951,7 +2013,7 @@ namespace cppwinrt break; } - w.write_each(info.type.MethodList()); + w.write_each(info.type.MethodList(), info.type); } } @@ -1973,7 +2035,7 @@ namespace cppwinrt bind(generics), type, type, - bind_each(type.MethodList()), + bind_each(type.MethodList(), type), bind(type)); } diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index f3ede9ed4..fec3de660 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -506,6 +506,20 @@ WINRT_EXPORT namespace winrt template struct map_view_base : iterable_base, Version> { + // specialization of Lookup that avoids throwing the hresult + std::optional TryLookup(K const& key, trylookup_from_abi_t) const + { + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); + auto pair = static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)); + + if (pair == static_cast(*this).get_container().end()) + { + return std::nullopt; + } + + return static_cast(*this).unwrap_value(pair->second); + } + V Lookup(K const& key) const { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); @@ -536,6 +550,7 @@ WINRT_EXPORT namespace winrt first = nullptr; second = nullptr; } + }; template diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 670a65403..87aaed24e 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -351,6 +351,10 @@ namespace winrt::impl return m_promise->enable_cancellation_propagation(value); } + bool originate_on_cancel(bool value = true) const noexcept + { + return m_promise->originate_on_cancel(value); + } private: Promise* m_promise; @@ -484,7 +488,14 @@ namespace winrt::impl if (m_status.load(std::memory_order_relaxed) == AsyncStatus::Started) { m_status.store(AsyncStatus::Canceled, std::memory_order_relaxed); - m_exception = std::make_exception_ptr(hresult_canceled()); + if (cancellable_promise::originate_on_cancel()) + { + m_exception = std::make_exception_ptr(hresult_canceled()); + } + else + { + m_exception = std::make_exception_ptr(hresult_canceled(hresult_error::no_originate)); + } cancel = std::move(m_cancel); } } @@ -628,7 +639,14 @@ namespace winrt::impl { if (Status() == AsyncStatus::Canceled) { - throw winrt::hresult_canceled(); + if (cancellable_promise::originate_on_cancel()) + { + throw winrt::hresult_canceled(); + } + else + { + throw winrt::hresult_canceled(hresult_error::no_originate); + } } return std::forward(expression); diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 0faaa1acd..7fa8789c7 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -180,12 +180,23 @@ WINRT_EXPORT namespace winrt return m_propagate_cancellation; } + bool originate_on_cancel(bool value = true) noexcept + { + return std::exchange(m_originate_on_cancel, value); + } + + bool should_originate_on_cancel() const noexcept + { + return m_originate_on_cancel; + } + private: static inline auto const cancelling_ptr = reinterpret_cast(1); std::atomic m_canceller{ nullptr }; void* m_context{ nullptr }; bool m_propagate_cancellation{ false }; + bool m_originate_on_cancel{ true }; // By default, will call RoOriginateError before throwing a cancel error code. }; template diff --git a/strings/base_error.h b/strings/base_error.h index 85de70f63..41929336b 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -84,6 +84,9 @@ WINRT_EXPORT namespace winrt { struct hresult_error { + struct no_originate_t {}; + static constexpr no_originate_t no_originate{}; + using from_abi_t = take_ownership_from_abi_t; static constexpr auto from_abi{ take_ownership_from_abi }; @@ -109,6 +112,10 @@ WINRT_EXPORT namespace winrt originate(code, nullptr, sourceInformation); } + explicit hresult_error(hresult const code, no_originate_t) noexcept : m_code(verify_error(code)) + { + } + hresult_error(hresult const code, param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { originate(code, get_abi(message), sourceInformation); @@ -325,6 +332,7 @@ WINRT_EXPORT namespace winrt struct hresult_canceled : hresult_error { hresult_canceled(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, sourceInformation) {} + hresult_canceled(hresult_error::no_originate_t) noexcept : hresult_error(impl::error_canceled, hresult_error::no_originate) {} hresult_canceled(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, message, sourceInformation) {} hresult_canceled(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi, sourceInformation) {} }; diff --git a/strings/base_meta.h b/strings/base_meta.h index 25deb42ec..7dbb4c386 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -10,6 +10,10 @@ WINRT_EXPORT namespace winrt struct take_ownership_from_abi_t {}; inline constexpr take_ownership_from_abi_t take_ownership_from_abi{}; + // Map implementations can implement TryLookup with trylookup_from_abi_t as an optimization + struct trylookup_from_abi_t {}; + inline constexpr trylookup_from_abi_t trylookup_from_abi{}; + template struct com_ptr; @@ -298,4 +302,16 @@ namespace winrt::impl return (func(Types{}) || ...); } }; + + template + struct has_TryLookup + { + template ().TryLookup(std::declval(), trylookup_from_abi))> static constexpr bool get_value(int) { return true; } + template static constexpr bool get_value(...) { return false; } + public: + static constexpr bool value = get_value(0); + }; + + template + inline constexpr bool has_TryLookup_v = has_TryLookup::value; } diff --git a/test/old_tests/UnitTests/Errors.cpp b/test/old_tests/UnitTests/Errors.cpp index 472d633f1..f8656a508 100644 --- a/test/old_tests/UnitTests/Errors.cpp +++ b/test/old_tests/UnitTests/Errors.cpp @@ -233,6 +233,7 @@ TEST_CASE("Errors") // Make sure trimming works. hresult_error e(E_FAIL, L":) is \u263A \n \t "); + auto x = e.message(); REQUIRE(e.message() == L":) is \u263A"); // Make sure delegates propagate correctly. diff --git a/test/old_tests/UnitTests/TryLookup.cpp b/test/old_tests/UnitTests/TryLookup.cpp index 3c6c54580..350fa9006 100644 --- a/test/old_tests/UnitTests/TryLookup.cpp +++ b/test/old_tests/UnitTests/TryLookup.cpp @@ -143,4 +143,129 @@ TEST_CASE("TryLookup TryRemove error") REQUIRE(!map.TryLookup(123)); REQUIRE(!map.TryRemove(123)); -} \ No newline at end of file +} + +TEST_CASE("trylookup_from_abi specialization") +{ + // A map that throws a specific error, used to verify various edge cases. + // and implements tryLookup, to take advantage of an optimization to avoid a throw. + struct map_with_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + bool shouldThrowOnTryLookup{ false }; + std::optional TryLookup(int, trylookup_from_abi_t) + { + if (shouldThrowOnTryLookup) + { + throw_hresult(codeToThrow); + } + else + { + return { std::nullopt }; + } + } + int Lookup(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Make sure that we use the TryLookup specialization, and don't throw an unexpected exception. + self->shouldThrowOnTryLookup = false; + REQUIRE(!map.TryLookup(123)); + // make sure regular lookup stll throws bounds + REQUIRE_THROWS_AS(map.Lookup(123), hresult_out_of_bounds); + + // Simulate a non-agile map that is being accessed from the wrong thread. + // "Try" operations should throw rather than erroneously report "not found". + // Because they didn't even try. The operation never got off the ground. + self->shouldThrowOnTryLookup = true; + self->codeToThrow = RPC_E_WRONG_THREAD; + REQUIRE_THROWS_AS(map.TryLookup(123), hresult_wrong_thread); + // regular lookup should throw the same error + REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread); +} + +TEST_CASE("trylookup_from_abi NOT opt-in, no special tag") +{ + // Makes sure that an existing TryLookup method is not called without the trylookup_from_abi_t tag. + struct map_without_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + std::optional TryLookup(int) // notice no trylookup_from_abi_t, so no opt-in + { + // throw an unexpectd hresult, this should not be called. + throw_hresult(RPC_E_WRONG_THREAD); + } + int Lookup(int) { return 42; } // Behave as if the item was found + + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Make sure that we don't use the TryLookup specialization, we use the Successful Lookup + REQUIRE(map.TryLookup(123).value() == 42); + REQUIRE(map.Lookup(123) == 42); +} + +TEST_CASE("trylookup_from_abi specialization with IInspectable") +{ + // A map that throws a specific error, used to verify various edge cases. + // and implements tryLookup, to take advantage of an optimization to avoid a throw. + struct map_with_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + bool shouldThrowOnTryLookup{ false }; + bool returnNullptr{ false }; + std::optional TryLookup(int, trylookup_from_abi_t) + { + if (returnNullptr) + { + return { nullptr }; + } + else if (shouldThrowOnTryLookup) + { + throw_hresult(codeToThrow); + } + else + { + return { std::nullopt }; + } + } + IInspectable Lookup(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Ensure that we return a value on nullptr, a nullptr is a valid IInspectable in the Map + self->returnNullptr = true; + REQUIRE(map.TryLookup(123) == IInspectable{nullptr}); + REQUIRE(map.Lookup(123) == IInspectable{nullptr}); + + // Make sure that we use the TryLookup specialization, and don't throw an unexpected exception. + self->shouldThrowOnTryLookup = false; + self->returnNullptr = false; + REQUIRE(map.TryLookup(123) == IInspectable{nullptr}); + // make sure regular lookup stll throws bounds + REQUIRE_THROWS_AS(map.Lookup(123), hresult_out_of_bounds); + + // Simulate a non-agile map that is being accessed from the wrong thread. + // "Try" operations should throw rather than erroneously report "not found". + // Because they didn't even try. The operation never got off the ground. + self->shouldThrowOnTryLookup = true; + self->codeToThrow = RPC_E_WRONG_THREAD; + REQUIRE_THROWS_AS(map.TryLookup(123), hresult_wrong_thread); + // regular lookup should throw the same error + REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread); +} diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index 7547609f6..d88fdcaf0 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -11,6 +11,28 @@ namespace using std::experimental::suspend_never; #endif + static bool s_exceptionLoggerCalled = false; + + static struct { + uint32_t lineNumber; + char const* fileName; + char const* functionName; + void* returnAddress; + winrt::hresult result; + } s_exceptionLoggerArgs{}; + + void __stdcall exceptionLogger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept + { + s_exceptionLoggerArgs = { + /*.lineNumber =*/ lineNumber, + /*.fileName =*/ fileName, + /*.functionName =*/ functionName, + /*.returnAddress =*/ returnAddress, + /*.result =*/ result, + }; + s_exceptionLoggerCalled = true; + } + // // Checks that manual cancellation checks work. // @@ -61,6 +83,7 @@ namespace co_return 1; } + IAsyncOperationWithProgress OperationWithProgress(HANDLE event, bool& canceled) { co_await resume_on_signal(event); @@ -77,6 +100,59 @@ namespace co_return 1; } + IAsyncAction OperationCancelLogged(HANDLE event, bool& canceled) + { + REQUIRE(!s_exceptionLoggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = exceptionLogger; + + co_await resume_on_signal(event); + auto cancel = co_await get_cancellation_token(); + + if (cancel()) + { + REQUIRE(!canceled); + canceled = true; + REQUIRE(s_exceptionLoggerCalled); + REQUIRE(s_exceptionLoggerArgs.result == HRESULT_FROM_WIN32(ERROR_CANCELLED)); + } + + winrt_throw_hresult_handler = nullptr; + s_exceptionLoggerCalled = false; + + co_await suspend_never(); + + REQUIRE(false); + co_return; + } + + IAsyncAction OperationAvoidLoggingCancel(HANDLE event, bool& canceled) + { + REQUIRE(!s_exceptionLoggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = exceptionLogger; + + auto cancel = co_await get_cancellation_token(); + cancel.originate_on_cancel(false); + + co_await resume_on_signal(event); + + if (cancel()) + { + REQUIRE(!canceled); + canceled = true; + REQUIRE(!s_exceptionLoggerCalled); + } + + winrt_throw_hresult_handler = nullptr; + s_exceptionLoggerCalled = false; + + co_await suspend_never(); + + REQUIRE(false); + co_return; + } + template void Check(F make) { @@ -96,7 +172,7 @@ namespace async.Cancel(); SetEvent(start.get()); - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); + REQUIRE(WaitForSingleObject(completed.get(), IsDebuggerPresent() ? INFINITE : 1000) == WAIT_OBJECT_0); REQUIRE(async.Status() == AsyncStatus::Canceled); REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED)); @@ -115,4 +191,6 @@ TEST_CASE("async_check_cancel") Check(ActionWithProgress); Check(Operation); Check(OperationWithProgress); + Check(OperationCancelLogged); + Check(OperationAvoidLoggingCancel); } diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index d7b055e47..b925628d9 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -37,9 +37,9 @@ namespace #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000 // not available in libc++ before LLVM 16 -TEST_CASE("custom_error_logger", "[!shouldfail]") +TEST_CASE("custom_error_logger_on_throw", "[!shouldfail]") #else -TEST_CASE("custom_error_logger") +TEST_CASE("custom_error_logger_on_throw") #endif { // Set up global handler @@ -72,3 +72,62 @@ TEST_CASE("custom_error_logger") winrt_throw_hresult_handler = nullptr; s_loggerCalled = false; } +template +void HresultOnLine80(Args... args) +{ + // Validate that handler translated on creating an HRESULT +#line 80 // Force next line to be reported as line number 80 + winrt::hresult_canceled(std::forward(args)...); +} + +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000 +// not available in libc++ before LLVM 16 +TEST_CASE("custom_error_logger_on_originate", "[!shouldfail]") +#else +TEST_CASE("custom_error_logger_on_originate") +#endif +{ + // Set up global handler + REQUIRE(!s_loggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = logger; + + HresultOnLine80(); + REQUIRE(s_loggerCalled); + // In C++20 these fields should be filled in by std::source_location + REQUIRE(s_loggerArgs.lineNumber == 80); + const auto fileNameSv = std::string_view(s_loggerArgs.fileName); + REQUIRE(!fileNameSv.empty()); + REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); +#ifdef _DEBUG + const auto functionNameSv = std::string_view(s_loggerArgs.functionName); + REQUIRE(!functionNameSv.empty()); + // Every compiler has a slightly different naming approach for this function, and even the same + // compiler can change its mind over time. Instead of matching the entire function name just + // match against the part we care about. + REQUIRE((functionNameSv.find("HresultOnLine80") != std::string_view::npos)); +#else + REQUIRE(s_loggerArgs.functionName == nullptr); +#endif // _DEBUG + + REQUIRE(s_loggerArgs.returnAddress); + REQUIRE(s_loggerArgs.result == HRESULT_FROM_WIN32(ERROR_CANCELLED)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + + s_loggerCalled = false; + s_loggerArgs.lineNumber = 0; + // verify HRESULT with a custom message + HresultOnLine80(L"with custom message"); + REQUIRE(s_loggerCalled); + REQUIRE(s_loggerArgs.lineNumber == 80); + + s_loggerCalled = false; + s_loggerArgs.lineNumber = 0; + // verify that no_originate does _not_ call the logger. + HresultOnLine80(winrt::hresult_error::no_originate); + REQUIRE(!s_loggerCalled); + REQUIRE(s_loggerArgs.lineNumber == 0); + + // Remove global handler + winrt_throw_hresult_handler = nullptr; + s_loggerCalled = false; +} From 584a0e09b2cce0450bb5b0e2c3ee122c383a34bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 08:49:08 -0600 Subject: [PATCH 267/305] Bump actions/download-artifact from 5 to 6 (#1519) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 866fddd7d..6f2745772 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v5 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From a0fcdc8a6db6283b19c16da04a920bf4de202c32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 10:41:58 -0600 Subject: [PATCH 268/305] Bump actions/upload-artifact from 4 to 5 (#1518) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f2745772..37611ce0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -230,7 +230,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -269,7 +269,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -383,7 +383,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: package path: "*.nupkg" From 1ccb7e1494b9c55f45f2a306d9a4dbc62317dc4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 17:48:07 -0800 Subject: [PATCH 269/305] Bump actions/checkout from 5 to 6 (#1523) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37611ce0e..4ece2a7df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Download nuget run: | @@ -102,7 +102,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' @@ -250,7 +250,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install cross compiler run: | @@ -283,7 +283,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Download nuget run: | @@ -323,7 +323,7 @@ jobs: config: [Release] runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Fetch cppwinrt executables uses: actions/download-artifact@v6 @@ -368,7 +368,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Package run: | From ac422060b70014180021d73974fc99ed0676ee3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 11:18:32 -0600 Subject: [PATCH 270/305] Bump actions/upload-artifact from 5 to 6 (#1525) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ece2a7df..d0b327169 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -230,7 +230,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -269,7 +269,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -383,7 +383,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: package path: "*.nupkg" From 6d87b8463a5608aca62b3f439f30dbe38dc11620 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 11:45:29 -0600 Subject: [PATCH 271/305] Bump actions/download-artifact from 6 to 7 (#1526) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0b327169..aeed4106c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v6 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From a7a5cd97ccc16bf606a20108bc9bda33f09bdb7f Mon Sep 17 00:00:00 2001 From: Vineeth Thomas Alex Date: Tue, 3 Feb 2026 13:48:20 -0600 Subject: [PATCH 272/305] Enable PreFast for build stage in OneBranch pipeline (#1533) Re-enable PreFast for build stage in pipeline. --- .pipelines/OneBranch.Official.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 552ec761b..56fada628 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -45,8 +45,6 @@ extends: compiled: enabled: true tsaEnabled: true - prefast: - enabled: true stages: - stage: build @@ -59,6 +57,8 @@ extends: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) OfficialBuild: true + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: "Guardian" # Enabling PreFast only for build stage - stage: vpack dependsOn: build From 3a596b513eb14d374c55d8f79a15906fbdfafc3f Mon Sep 17 00:00:00 2001 From: Vineeth Thomas Alex Date: Tue, 3 Feb 2026 16:57:59 -0600 Subject: [PATCH 273/305] Update PreFast run stage in OneBranchBuild.yml to "Guardian" to avoid race condition with build. (#1534) * Remove PreFast settings from OneBranch pipeline Removed PreFast parameters from build configuration. * Update PreFast run stage in OneBranchBuild.yml Changed PreFast run stage from 'Build' to 'Guardian' to enable it only during the Guardian stage. * Correct indentation for PreFast configuration Fix indentation for ob_sdl_prefast_runDuring in OneBranchBuild.yml --- .pipelines/OneBranch.Official.yml | 3 --- .pipelines/jobs/OneBranchBuild.yml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 56fada628..996f2a607 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -57,8 +57,6 @@ extends: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) OfficialBuild: true - ob_sdl_prefast_enabled: true - ob_sdl_prefast_runDuring: "Guardian" # Enabling PreFast only for build stage - stage: vpack dependsOn: build @@ -68,7 +66,6 @@ extends: type: windows variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ob_createvpack_enabled: true ob_createvpack_packagename: CppWinRT.Compiler ob_createvpack_owneralias: cpp4uwpt diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index b5c060cb9..dfee85edf 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -32,7 +32,7 @@ jobs: ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' ob_sdl_prefast_enabled: true - ob_sdl_prefast_runDuring: 'Build' + ob_sdl_prefast_runDuring: "Guardian" ob_sdl_checkCompliantCompilerWarnings: true ob_symbolsPublishing_enabled: ${{ parameters.OfficialBuild }} From 0f3e9f7b8d80a86f2ab3e9f8da47e217c5736ad1 Mon Sep 17 00:00:00 2001 From: Vineeth Thomas Alex Date: Thu, 5 Feb 2026 13:06:33 -0600 Subject: [PATCH 274/305] Remove Windows pool from build stage (#1535) * Remove Windows pool from build stage Removed Windows pool configuration from build stage, since template job defines pool * Remove prefast in OneBranch.PullRequest.yml Prefast is enabled in the build stage template job * Add -SkipDuplicate option to NuGet push arguments * Update .pipelines/jobs/OneBranchNuGet.yml Co-authored-by: Ryan Shepherd * Update NuGet push command arguments Removed the -SkipDuplicate option from the NuGet push command. * Set pre-release NuGet version in VSIX build * Change ob_sdl_prefast_runDuring to 'Guardian' --------- Co-authored-by: Ryan Shepherd --- .pipelines/OneBranch.Official.yml | 3 --- .pipelines/OneBranch.PullRequest.yml | 2 -- .pipelines/jobs/OneBranchNuGet.yml | 9 ++++++--- .pipelines/jobs/OneBranchVsix.yml | 7 ++++++- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 996f2a607..cf2928151 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -48,9 +48,6 @@ extends: stages: - stage: build - pool: - type: windows - jobs: - template: .pipelines/jobs/OneBranchBuild.yml@self parameters: diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index bc08bbddf..ea4884329 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -41,8 +41,6 @@ extends: enabled: false sbom: enabled: true - prefast: - enabled: true stages: - stage: build diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 02133ee03..867202891 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -15,10 +15,13 @@ jobs: variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - PackageVersion: ${{ parameters.BuildVersion }} + ${{ if eq(parameters.OfficialBuild, true) }}: + PackageVersion: ${{ parameters.BuildVersion }} + ${{ else }}: + PackageVersion: ${{ parameters.BuildVersion }}-unofficial ob_sdl_prefast_enabled: true - ob_sdl_prefast_runDuring: 'Build' + ob_sdl_prefast_runDuring: 'Guardian' ob_sdl_checkCompliantCompilerWarnings: true steps: @@ -72,4 +75,4 @@ jobs: displayName: 'Publish NuGet package' inputs: command: 'custom' - arguments: 'push $(ob_outputDirectory)\packages\Microsoft.Windows.CppWinRT.$(PackageVersion).nupkg -NonInteractive -Source https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json -ApiKey VSTS' \ No newline at end of file + arguments: 'push $(ob_outputDirectory)\packages\Microsoft.Windows.CppWinRT.$(PackageVersion).nupkg -NonInteractive -Source https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json -ApiKey VSTS' diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 18b74403b..1b03f71d0 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -27,6 +27,11 @@ jobs: VsixFilename: Microsoft.Windows.CppWinRT variables: + ${{ if eq(parameters.OfficialBuild, true) }}: + PackageVersion: ${{ parameters.BuildVersion }} + ${{ else }}: + PackageVersion: ${{ parameters.BuildVersion }}-unofficial + ob_outputDirectory: $(Build.SourcesDirectory)\out ob_artifactSuffix: $(VsVersion)_$(Deployment) @@ -91,7 +96,7 @@ jobs: displayName: Build VSIX inputs: solution: $(Build.SourcesDirectory)\vsix\vsix.sln - msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog + msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=$(PackageVersion),clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog platform: 'Any CPU' configuration: ${{ parameters.BuildConfiguration }} From 1a5cd652058cb2e3162732da42c7a478c2b8ccc8 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 10 Feb 2026 11:59:31 -0800 Subject: [PATCH 275/305] Only sign the VSIX contents instead of the entire temp directory (#1537) --- .pipelines/jobs/OneBranchVsix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 1b03f71d0..8c49ccf5b 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -114,7 +114,7 @@ jobs: command: sign signing_profile: external_distribution files_to_sign: '**\*.dll' - search_root: '$(Agent.TempDirectory)' + search_root: '$(Agent.TempDirectory)\$(VsixFilename)' - task: ArchiveFiles@2 displayName: 'Repack signed VSIX contents' From da8a3761306c037e6ba5b0d29e6e2a4923c4488c Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 10 Feb 2026 12:00:40 -0800 Subject: [PATCH 276/305] Fix handling of NuGet package version in VSIX (#1536) * Allow vsix to have prerelease nupkg * Fix nuget template invocation * Missed one case of NuGet vs VSIX version --- .pipelines/OneBranch.Official.yml | 6 ++++-- .pipelines/OneBranch.PullRequest.yml | 3 ++- .pipelines/jobs/OneBranchNuGet.yml | 7 ++----- .pipelines/jobs/OneBranchVsix.yml | 9 +++------ .pipelines/variables/version.yml | 12 +++++++++++- build_vsix.cmd | 4 ++-- vsix/Dev16/Component/source.extension.vsixmanifest | 2 +- vsix/Dev16/Standalone/source.extension.vsixmanifest | 2 +- vsix/Dev16/vsix.Dev16.csproj | 4 ++-- vsix/Dev17/Component/source.extension.vsixmanifest | 2 +- vsix/Dev17/Standalone/source.extension.vsixmanifest | 2 +- vsix/Dev17/vsix.Dev17.csproj | 4 ++-- vsix/Extension.targets | 4 +++- 13 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index cf2928151..64f762d81 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -6,6 +6,8 @@ parameters: # parameters are shown up in ADO UI in a build queue time variables: - template: variables/version.yml + parameters: + OfficialBuild: true - template: variables/OneBranchVariables.yml parameters: debug: ${{ parameters.debug }} @@ -132,8 +134,7 @@ extends: jobs: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: - BuildConfiguration: $(BuildConfiguration) - BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true - stage: Test @@ -151,4 +152,5 @@ extends: parameters: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index ea4884329..9e18821b4 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -56,7 +56,7 @@ extends: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: BuildConfiguration: $(BuildConfiguration) - BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) - stage: Test dependsOn: build @@ -73,3 +73,4 @@ extends: parameters: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 867202891..36ec3144b 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -2,7 +2,7 @@ parameters: - name: BuildConfiguration type: string - - name: BuildVersion + - name: NugetPackageVersion type: string - name: OfficialBuild type: boolean @@ -15,10 +15,7 @@ jobs: variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ${{ if eq(parameters.OfficialBuild, true) }}: - PackageVersion: ${{ parameters.BuildVersion }} - ${{ else }}: - PackageVersion: ${{ parameters.BuildVersion }}-unofficial + PackageVersion: ${{ parameters.NugetPackageVersion }} ob_sdl_prefast_enabled: true ob_sdl_prefast_runDuring: 'Guardian' diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 8c49ccf5b..696b7e292 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -3,6 +3,8 @@ parameters: type: string - name: BuildVersion type: string + - name: NugetPackageVersion + type: string - name: OfficialBuild type: boolean default: false @@ -27,11 +29,6 @@ jobs: VsixFilename: Microsoft.Windows.CppWinRT variables: - ${{ if eq(parameters.OfficialBuild, true) }}: - PackageVersion: ${{ parameters.BuildVersion }} - ${{ else }}: - PackageVersion: ${{ parameters.BuildVersion }}-unofficial - ob_outputDirectory: $(Build.SourcesDirectory)\out ob_artifactSuffix: $(VsVersion)_$(Deployment) @@ -96,7 +93,7 @@ jobs: displayName: Build VSIX inputs: solution: $(Build.SourcesDirectory)\vsix\vsix.sln - msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=$(PackageVersion),clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog + msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=${{ parameters.BuildVersion }},NugetPackageVersion=${{ parameters.NugetPackageVersion }},clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog platform: 'Any CPU' configuration: ${{ parameters.BuildConfiguration }} diff --git a/.pipelines/variables/version.yml b/.pipelines/variables/version.yml index 576d896eb..15382e7df 100644 --- a/.pipelines/variables/version.yml +++ b/.pipelines/variables/version.yml @@ -1,7 +1,17 @@ +parameters: + - name: OfficialBuild + type: boolean + default: false + variables: MajorVersion: "2" MinorVersion: "0" VersionDate: $[format('{0:yyMMdd}', pipeline.startTime)] VersionCounter: $[counter(variables['VersionDate'], 1)] BuildVersion: $(MajorVersion).$(MinorVersion).$(VersionDate).$(VersionCounter) - PatchVersion: $(VersionDate)$(VersionCounter) \ No newline at end of file + PatchVersion: $(VersionDate)$(VersionCounter) + + ${{ if eq(parameters.OfficialBuild, true) }}: + NugetPackageVersion: $(BuildVersion) + ${{ else }}: + NugetPackageVersion: $(BuildVersion)-unofficial diff --git a/build_vsix.cmd b/build_vsix.cmd index 9908462ef..aefc84df1 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -30,7 +30,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=x86,Deployment=%ta call msbuild /p:Configuration=%target_configuration%,Platform=arm64,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln rem Build nuget -.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed +.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib;target_version=%target_version% -version %target_version% -Verbosity Detailed rem Build vsix -call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln +call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NugetPackageVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln diff --git a/vsix/Dev16/Component/source.extension.vsixmanifest b/vsix/Dev16/Component/source.extension.vsixmanifest index afd96cf1f..a7ab21972 100644 --- a/vsix/Dev16/Component/source.extension.vsixmanifest +++ b/vsix/Dev16/Component/source.extension.vsixmanifest @@ -29,7 +29,7 @@ - + diff --git a/vsix/Dev16/Standalone/source.extension.vsixmanifest b/vsix/Dev16/Standalone/source.extension.vsixmanifest index e3c2ac995..b38c06cf8 100644 --- a/vsix/Dev16/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev16/Standalone/source.extension.vsixmanifest @@ -29,7 +29,7 @@ - + diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index 72b9b4098..94a6836c3 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -41,8 +41,8 @@ %(Filename)%(Extension) true - - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg + + Packages\Microsoft.Windows.CppWinRT.$(NugetPackageVersion).nupkg true diff --git a/vsix/Dev17/Component/source.extension.vsixmanifest b/vsix/Dev17/Component/source.extension.vsixmanifest index bcbfa9c8b..063dfcbc7 100644 --- a/vsix/Dev17/Component/source.extension.vsixmanifest +++ b/vsix/Dev17/Component/source.extension.vsixmanifest @@ -35,7 +35,7 @@ - + diff --git a/vsix/Dev17/Standalone/source.extension.vsixmanifest b/vsix/Dev17/Standalone/source.extension.vsixmanifest index 56ea4b86f..89e178c82 100644 --- a/vsix/Dev17/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev17/Standalone/source.extension.vsixmanifest @@ -35,7 +35,7 @@ - + diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index 3326ce6fa..02f3e0bb8 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -44,8 +44,8 @@ %(Filename)%(Extension) true - - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg + + Packages\Microsoft.Windows.CppWinRT.$(NugetPackageVersion).nupkg true diff --git a/vsix/Extension.targets b/vsix/Extension.targets index 7a7b6c2b8..442f03a53 100644 --- a/vsix/Extension.targets +++ b/vsix/Extension.targets @@ -1,8 +1,10 @@ + + @@ -27,7 +29,7 @@ - + From 129c9258fedbae96a0155f634bf56b68f6f75053 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 11 Feb 2026 11:55:11 -0800 Subject: [PATCH 277/305] Fix accidentally deleted parameter (#1538) --- .pipelines/OneBranch.Official.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 64f762d81..7a73b263b 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -134,6 +134,7 @@ extends: jobs: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: + BuildConfiguration: $(BuildConfiguration) NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true From dcbdcc856f43be2f119a7b83005387894959e0db Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 1 Mar 2026 08:15:25 -0800 Subject: [PATCH 278/305] Delete stale.yml (#1543) --- .github/workflows/stale.yml | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index b686df568..000000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Mark stale issues and pull requests - -on: - schedule: - - cron: '0 0 * * *' - -jobs: - stale: - - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - - steps: - - uses: actions/stale@v10 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - days-before-stale: 10 - days-before-close: 5 - stale-issue-message: 'This issue is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - stale-pr-message: 'This pull request is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' From 6bf188e1ab4ec5d089f093043f7df34de76bb31f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:24:20 -0800 Subject: [PATCH 279/305] Bump actions/download-artifact from 7 to 8 (#1541) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aeed4106c..eb37051b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v6 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From 751a57bd33b92d67ada681d9084fa6a452364317 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:34:58 -0800 Subject: [PATCH 280/305] Bump actions/upload-artifact from 6 to 7 (#1542) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb37051b5..6356b8095 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -230,7 +230,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -269,7 +269,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -383,7 +383,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: package path: "*.nupkg" From bb0a408e7764f6b5ed8ac050459d07896c3f5f91 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Tue, 10 Mar 2026 07:56:46 +0800 Subject: [PATCH 281/305] Simplify the definition of the consume function (#1544) --- cppwinrt/code_writers.h | 59 +++++++++-------------------------------- strings/base_windows.h | 57 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 47 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 35e9935d0..1d0f8fe92 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -619,10 +619,15 @@ namespace cppwinrt } } - static void write_abi_args(writer& w, method_signature const& method_signature) + static void write_abi_args(writer& w, method_signature const& method_signature, bool start_comma) { separator s{ w }; + if (start_comma) + { + s(); + } + for (auto&& [param, param_signature] : method_signature.params()) { s(); @@ -1135,19 +1140,7 @@ namespace cppwinrt // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% - if constexpr (!std::is_same_v) - { - winrt::hresult _winrt_cast_result_code; - auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); - check_hresult(_winrt_cast_result_code); - auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; - _winrt_abi_type->%(%); - } - else - { - auto const _winrt_abi_type = *(abi_t<%>**)this; - _winrt_abi_type->%(%); - }% + consume_noexcept_remove_overload<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1155,19 +1148,7 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const noexcept {% - if constexpr (!std::is_same_v) - { - winrt::hresult _winrt_cast_result_code; - auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); - check_hresult(_winrt_cast_result_code); - auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; - WINRT_VERIFY_(0, _winrt_abi_type->%(%)); - } - else - { - auto const _winrt_abi_type = *(abi_t<%>**)this; - WINRT_VERIFY_(0, _winrt_abi_type->%(%)); - }% + consume_noexcept<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1176,19 +1157,7 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const {% - if constexpr (!std::is_same_v) - { - winrt::hresult _winrt_cast_result_code; - auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); - check_hresult(_winrt_cast_result_code); - auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; - check_hresult(_winrt_abi_type->%(%)); - } - else - { - auto const _winrt_abi_type = *(abi_t<%>**)this; - check_hresult(_winrt_abi_type->%(%)); - }% + consume_general<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1202,12 +1171,8 @@ namespace cppwinrt bind(signature, false), type, type, - type, - get_abi_name(method), - bind(signature), - type, get_abi_name(method), - bind(signature), + bind(signature, true), bind(signature)); if (is_add_overload(method)) @@ -2750,7 +2715,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable bind(signature, true), type_name, bind_list(", ", generics), - bind(signature), + bind(signature, false), bind(signature)); } else @@ -2822,7 +2787,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable bind(signature), bind(signature, true), type_name, - bind(signature), + bind(signature, false), bind(signature)); } } diff --git a/strings/base_windows.h b/strings/base_windows.h index bf28440ef..831e1b1fe 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -451,3 +451,60 @@ WINRT_EXPORT namespace winrt::Windows::Foundation IInspectable(void* ptr, take_ownership_from_abi_t) noexcept : IUnknown(ptr, take_ownership_from_abi) {} }; } + +WINRT_EXPORT namespace winrt::impl +{ + template + void consume_noexcept_remove_overload(Derive const* d, MemberPointer mptr, Args&&... args) noexcept + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + (_winrt_abi_type->*mptr)(std::forward(args)...); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + (_winrt_abi_type->*mptr)(std::forward(args)...); + } + } + + template + void consume_noexcept(Derive const* d, MemberPointer mptr, Args&&... args) noexcept + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + WINRT_VERIFY_(0, (_winrt_abi_type->*mptr)(std::forward(args)...)); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + WINRT_VERIFY_(0, (_winrt_abi_type->*mptr)(std::forward(args)...)); + } + } + + template + void consume_general(Derive const* d, MemberPointer mptr, Args&&... args) + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + check_hresult((_winrt_abi_type->*mptr)(std::forward(args)...)); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + check_hresult((_winrt_abi_type->*mptr)(std::forward(args)...)); + } + } +} From 8864ac6ef07952e2ed10c3cec1445474b748a332 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 16 Mar 2026 00:23:52 -0400 Subject: [PATCH 282/305] Remove experimental coroutines support (#1521) * Remove experimental coroutines support Replace CppWinRTEnableLegacyCoroutines with CppWinRTEnableCpp17Coroutines Remove base_coroutine_system_winui.h, hasn't worked since PR 0.8 Support and test building with no coroutines Remove implementation selection machinery * Fix clang-cl mismatching signedness error * Require coroutine support for C++/WinRT Add error message for missing coroutine support in C++. * Revert "Require coroutine support for C++/WinRT" This reverts commit de710f17fe9b7da34bf228b8b296f34c483e9a33. * Include an error message if /await is used --------- Co-authored-by: Ryan Shepherd --- .github/workflows/ci.yml | 2 +- .pipelines/jobs/OneBranchTest.yml | 4 + Directory.Build.Props | 4 +- build_test_all.cmd | 1 + cppwinrt.sln | 18 ++ cppwinrt/code_writers.h | 4 - nuget/CppWinrtRules.Project.xml | 6 +- nuget/Microsoft.Windows.CppWinRT.targets | 2 +- run_tests.cmd | 1 + strings/base_coroutine_foundation.h | 28 ++- strings/base_coroutine_system.h | 6 +- strings/base_coroutine_system_winui.h | 50 ----- strings/base_coroutine_threadpool.h | 59 +++--- strings/base_coroutine_ui_core.h | 6 +- strings/base_deferral.h | 16 +- strings/base_includes.h | 28 +-- strings/base_macros.h | 2 +- test/CMakeLists.txt | 1 + test/old_tests/UnitTests/async.cpp | 14 +- test/old_tests/UnitTests/weak.cpp | 8 +- test/test/async_auto_cancel.cpp | 16 +- test/test/async_cancel_callback.cpp | 14 +- test/test/async_check_cancel.cpp | 18 +- test/test/when.cpp | 8 +- test/test_nocoro/CMakeLists.txt | 35 ++++ test/test_nocoro/get.cpp | 74 +++++++ test/test_nocoro/main.cpp | 22 +++ test/test_nocoro/pch.cpp | 1 + test/test_nocoro/pch.h | 6 + test/test_nocoro/test_nocoro.vcxproj | 241 +++++++++++++++++++++++ 30 files changed, 489 insertions(+), 206 deletions(-) delete mode 100644 strings/base_coroutine_system_winui.h create mode 100644 test/test_nocoro/CMakeLists.txt create mode 100644 test/test_nocoro/get.cpp create mode 100644 test/test_nocoro/main.cpp create mode 100644 test/test_nocoro/pch.cpp create mode 100644 test/test_nocoro/pch.h create mode 100644 test/test_nocoro/test_nocoro.vcxproj diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6356b8095..a42f2c5b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] exclude: - arch: arm64 config: Debug diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index 0aa5c934b..2fb3a4bd1 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -17,6 +17,10 @@ jobs: TestExe: 'test' TestProject: 'test' BuildPlatform: 'x86' + test_nocoro.x86: + TestExe: 'test_nocoro' + TestProject: 'test_nocoro' + BuildPlatform: 'x86' test_cpp20.x86: TestExe: 'test_cpp20' TestProject: 'test_cpp20' diff --git a/Directory.Build.Props b/Directory.Build.Props index 9088021c1..5f530da91 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -30,7 +30,7 @@ ClangCL - + 20 false @@ -60,7 +60,7 @@ CATCH_CONFIG_COLOUR_ANSI;%(PreprocessorDefinitions) true /bigobj - /await %(AdditionalOptions) + /await:strict %(AdditionalOptions) -Wno-unused-command-line-argument -fno-delayed-template-parsing -mcx16 diff --git a/build_test_all.cmd b/build_test_all.cmd index 4372acfd5..649f4dc69 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -28,6 +28,7 @@ call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platfor call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_nocoro call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20_no_sourcelocation call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast diff --git a/cppwinrt.sln b/cppwinrt.sln index 5964f976b..3bcfb33bc 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -119,6 +119,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocatio {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nocoro", "test\test_nocoro\test_nocoro.vcxproj", "{9E392830-805A-4AAF-932D-C493143EFACA}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}" ProjectSection(SolutionItems) = preProject build_nuget.cmd = build_nuget.cmd @@ -394,6 +399,18 @@ Global {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.Build.0 = Release|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.ActiveCfg = Release|Win32 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.Build.0 = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.Build.0 = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.ActiveCfg = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.Build.0 = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.ActiveCfg = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.Build.0 = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.ActiveCfg = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.Build.0 = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.ActiveCfg = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.Build.0 = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.ActiveCfg = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -417,6 +434,7 @@ Global {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {9E392830-805A-4AAF-932D-C493143EFACA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 1d0f8fe92..e24cfd302 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3442,10 +3442,6 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { w.write(strings::base_coroutine_system); } - else if (namespace_name == "Microsoft.System") - { - w.write(strings::base_coroutine_system_winui); - } else if (namespace_name == "Windows.UI.Core") { w.write(strings::base_coroutine_ui_core); diff --git a/nuget/CppWinrtRules.Project.xml b/nuget/CppWinrtRules.Project.xml index 7f69fcd74..73f32c6d3 100644 --- a/nuget/CppWinrtRules.Project.xml +++ b/nuget/CppWinrtRules.Project.xml @@ -81,9 +81,9 @@ Description="Enables or disables the default for copying binaries to the output folder to be false" Category="General" /> - diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 7fe83b14d..188e56835 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -882,7 +882,7 @@ $(XamlMetaDataProviderPch) %(AdditionalOptions) /bigobj - %(AdditionalOptions) /await + %(AdditionalOptions) /await:strict %(AdditionalIncludeDirectories);$(GeneratedFilesDir) diff --git a/run_tests.cmd b/run_tests.cmd index 77d883642..58e3c5524 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Debug call :run_test test +call :run_test test_nocoro call :run_test test_cpp20 call :run_test test_cpp20_no_sourcelocation call :run_test test_fast diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 87aaed24e..a5816a85b 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -99,12 +99,13 @@ namespace winrt::impl return async.GetResults(); } +#ifdef WINRT_IMPL_COROUTINES struct ignore_apartment_context {}; template struct disconnect_aware_handler : private std::conditional_t { - disconnect_aware_handler(Awaiter* awaiter, coroutine_handle<> handle) noexcept + disconnect_aware_handler(Awaiter* awaiter, std::coroutine_handle<> handle) noexcept : m_awaiter(awaiter), m_handle(handle) { } disconnect_aware_handler(disconnect_aware_handler&& other) = default; @@ -123,7 +124,7 @@ namespace winrt::impl private: movable_primitive m_awaiter; - movable_primitive, nullptr> m_handle; + movable_primitive, nullptr> m_handle; void Complete() { @@ -149,7 +150,6 @@ namespace winrt::impl } }; -#ifdef WINRT_IMPL_COROUTINES template struct await_adapter : cancellable_awaiter> { @@ -175,7 +175,7 @@ namespace winrt::impl } template - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle handle) { this->set_cancellable_promise_from_handle(handle); return register_completed_callback(handle); @@ -189,7 +189,7 @@ namespace winrt::impl } private: - bool register_completed_callback(coroutine_handle<> handle) + bool register_completed_callback(std::coroutine_handle<> handle) { if constexpr (!preserve_context) { @@ -294,7 +294,6 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return{ async }; } } -#endif WINRT_EXPORT namespace winrt { @@ -327,7 +326,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -373,7 +372,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -411,7 +410,7 @@ namespace winrt::impl if (remaining == 0) { std::atomic_thread_fence(std::memory_order_acquire); - coroutine_handle::from_promise(*static_cast(this)).destroy(); + std::coroutine_handle::from_promise(*static_cast(this)).destroy(); } return remaining; @@ -577,7 +576,7 @@ namespace winrt::impl } } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } @@ -595,7 +594,7 @@ namespace winrt::impl { } - bool await_suspend(coroutine_handle<>) const noexcept + bool await_suspend(std::coroutine_handle<>) const noexcept { promise->set_completed(); uint32_t const remaining = promise->subtract_reference(); @@ -705,11 +704,7 @@ namespace winrt::impl }; } -#ifdef __cpp_lib_coroutine namespace std -#else -namespace std::experimental -#endif { template struct coroutine_traits @@ -844,7 +839,6 @@ namespace std::experimental WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template Windows::Foundation::IAsyncAction when_all(T... async) { @@ -890,5 +884,5 @@ WINRT_EXPORT namespace winrt impl::check_status_canceled(shared->status); co_return shared->result.GetResults(); } -#endif } +#endif diff --git a/strings/base_coroutine_system.h b/strings/base_coroutine_system.h index b893bd1b5..f79fe0671 100644 --- a/strings/base_coroutine_system.h +++ b/strings/base_coroutine_system.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -23,7 +24,7 @@ WINRT_EXPORT namespace winrt return m_queued; } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_dispatcher.TryEnqueue(m_priority, [handle, this] { @@ -41,10 +42,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::System::DispatcherQueue const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_coroutine_system_winui.h b/strings/base_coroutine_system_winui.h deleted file mode 100644 index ecb3cf766..000000000 --- a/strings/base_coroutine_system_winui.h +++ /dev/null @@ -1,50 +0,0 @@ - -WINRT_EXPORT namespace winrt -{ - [[nodiscard]] inline auto resume_foreground( - Microsoft::System::DispatcherQueue const& dispatcher, - Microsoft::System::DispatcherQueuePriority const priority = Microsoft::System::DispatcherQueuePriority::Normal) noexcept - { - struct awaitable - { - awaitable(Microsoft::System::DispatcherQueue const& dispatcher, Microsoft::System::DispatcherQueuePriority const priority) noexcept : - m_dispatcher(dispatcher), - m_priority(priority) - { - } - - bool await_ready() const noexcept - { - return false; - } - - bool await_resume() const noexcept - { - return m_queued; - } - - bool await_suspend(impl::coroutine_handle<> handle) - { - return m_dispatcher.TryEnqueue(m_priority, [handle, this] - { - m_queued = true; - handle(); - }); - } - - private: - Microsoft::System::DispatcherQueue const& m_dispatcher; - Microsoft::System::DispatcherQueuePriority const m_priority; - bool m_queued{}; - }; - - return awaitable{ dispatcher, priority }; - }; - -#ifdef WINRT_IMPL_COROUTINES - inline auto operator co_await(Microsoft::System::DispatcherQueue const& dispatcher) - { - return resume_foreground(dispatcher); - } -#endif -} diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 7fa8789c7..e59fcadb2 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -1,6 +1,7 @@ namespace winrt::impl { +#ifdef WINRT_IMPL_COROUTINES inline auto submit_threadpool_callback(void(__stdcall* callback)(void*, void* context), void* context) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, context, nullptr)) @@ -11,13 +12,14 @@ namespace winrt::impl inline void __stdcall resume_background_callback(void*, void* context) noexcept { - coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); }; - inline auto resume_background(coroutine_handle<> handle) + inline auto resume_background(std::coroutine_handle<> handle) { submit_threadpool_callback(resume_background_callback, handle.address()); } +#endif inline std::pair get_apartment_type() noexcept { @@ -48,6 +50,7 @@ namespace winrt::impl return false; } +#ifdef WINRT_IMPL_COROUTINES struct resume_apartment_context { resume_apartment_context() = default; @@ -64,11 +67,11 @@ namespace winrt::impl inline int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept { - coroutine_handle<>::from_address(args->data)(); + std::coroutine_handle<>::from_address(args->data)(); return 0; }; - [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) { com_callback_args args{}; args.data = handle.address(); @@ -85,10 +88,10 @@ namespace winrt::impl struct threadpool_resume { - threadpool_resume(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) : + threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) : m_context(context), m_handle(handle), m_failure(failure) { } com_ptr m_context; - coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; int32_t* m_failure; }; @@ -101,14 +104,14 @@ namespace winrt::impl } } - inline void resume_apartment_on_threadpool(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) { auto state = std::make_unique(context, handle, failure); submit_threadpool_callback(fallback_submit_threadpool_callback, state.get()); state.release(); } - [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, int32_t* failure) { WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) @@ -130,8 +133,10 @@ namespace winrt::impl return resume_apartment_sync(context.m_context, handle, failure); } } +#endif } +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { struct cancellable_promise @@ -217,7 +222,7 @@ WINRT_EXPORT namespace winrt protected: template - void set_cancellable_promise_from_handle(impl::coroutine_handle const& handle) + void set_cancellable_promise_from_handle(std::coroutine_handle const& handle) { if constexpr (std::is_base_of_v) { @@ -237,10 +242,7 @@ WINRT_EXPORT namespace winrt cancellable_promise* m_promise = nullptr; }; -} -WINRT_EXPORT namespace winrt -{ [[nodiscard]] inline auto resume_background() noexcept { struct awaitable @@ -254,7 +256,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { impl::resume_background(handle); } @@ -281,7 +283,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> resume) + void await_suspend(std::coroutine_handle<> resume) { m_resume = resume; @@ -301,7 +303,7 @@ WINRT_EXPORT namespace winrt } T const& m_context; - impl::coroutine_handle<> m_resume{ nullptr }; + std::coroutine_handle<> m_resume{ nullptr }; }; return awaitable{ context }; @@ -336,7 +338,7 @@ namespace winrt::impl check_hresult(failure); } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { auto context_copy = context; return impl::resume_apartment(context_copy.context, handle, &failure); @@ -381,7 +383,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle handle) + void await_suspend(std::coroutine_handle handle) { set_cancellable_promise_from_handle(handle); @@ -445,7 +447,7 @@ namespace winrt::impl handle_type m_timer; Windows::Foundation::TimeSpan m_duration; - impl::coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; std::atomic m_state{ state::idle }; }; @@ -489,7 +491,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle resume) + void await_suspend(std::coroutine_handle resume) { set_cancellable_promise_from_handle(resume); @@ -559,31 +561,27 @@ namespace winrt::impl Windows::Foundation::TimeSpan m_timeout; void* m_handle; uint32_t m_result{}; - impl::coroutine_handle<> m_resume{ nullptr }; + std::coroutine_handle<> m_resume{ nullptr }; std::atomic m_state{ state::idle }; }; } WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES inline impl::apartment_awaiter operator co_await(apartment_context const& context) { return{ context }; } -#endif [[nodiscard]] inline impl::timespan_awaiter resume_after(Windows::Foundation::TimeSpan duration) noexcept { return impl::timespan_awaiter{ duration }; } -#ifdef WINRT_IMPL_COROUTINES inline impl::timespan_awaiter operator co_await(Windows::Foundation::TimeSpan duration) { return resume_after(duration); } -#endif [[nodiscard]] inline impl::signal_awaiter resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) noexcept { @@ -613,7 +611,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, handle.address(), &m_environment)) { @@ -625,7 +623,7 @@ WINRT_EXPORT namespace winrt static void __stdcall callback(void*, void* context) noexcept { - impl::coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); } struct pool_traits @@ -673,11 +671,7 @@ WINRT_EXPORT namespace winrt struct fire_and_forget {}; } -#ifdef __cpp_lib_coroutine namespace std -#else -namespace std::experimental -#endif { template struct coroutine_traits @@ -693,12 +687,12 @@ namespace std::experimental { } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } - suspend_never final_suspend() const noexcept + std::suspend_never final_suspend() const noexcept { return{}; } @@ -710,3 +704,4 @@ namespace std::experimental }; }; } +#endif diff --git a/strings/base_coroutine_ui_core.h b/strings/base_coroutine_ui_core.h index dab34c8de..7efed5174 100644 --- a/strings/base_coroutine_ui_core.h +++ b/strings/base_coroutine_ui_core.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -22,7 +23,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { m_dispatcher.RunAsync(m_priority, [handle] { @@ -39,10 +40,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::UI::Core::CoreDispatcher const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_deferral.h b/strings/base_deferral.h index ceab1cd4b..6976db4a6 100644 --- a/strings/base_deferral.h +++ b/strings/base_deferral.h @@ -1,7 +1,7 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template struct deferrable_event_args { @@ -22,9 +22,9 @@ WINRT_EXPORT namespace winrt [[nodiscard]] Windows::Foundation::IAsyncAction wait_for_deferrals() { - struct awaitable : impl::suspend_always + struct awaitable : std::suspend_always { - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_deferrable.await_suspend(handle); } @@ -37,11 +37,9 @@ WINRT_EXPORT namespace winrt private: - using coroutine_handle = impl::coroutine_handle<>; - void one_deferral_completed() { - coroutine_handle resume = nullptr; + std::coroutine_handle<> resume = nullptr; { slim_lock_guard const guard(m_lock); @@ -62,7 +60,7 @@ WINRT_EXPORT namespace winrt } } - bool await_suspend(coroutine_handle handle) noexcept + bool await_suspend(std::coroutine_handle<> handle) noexcept { slim_lock_guard const guard(m_lock); m_handle = handle; @@ -71,7 +69,7 @@ WINRT_EXPORT namespace winrt slim_mutex m_lock; int32_t m_outstanding_deferrals = 0; - coroutine_handle m_handle = nullptr; + std::coroutine_handle<> m_handle = nullptr; }; -#endif } +#endif diff --git a/strings/base_includes.h b/strings/base_includes.h index 819e3c98f..a3bf308d1 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -48,31 +48,7 @@ #endif #ifdef __cpp_lib_coroutine - #include - -namespace winrt::impl -{ - template - using coroutine_handle = std::coroutine_handle; - - using suspend_always = std::suspend_always; - using suspend_never = std::suspend_never; -} - -#elif __has_include() - -#include - -namespace winrt::impl -{ - template - using coroutine_handle = std::experimental::coroutine_handle; - - using suspend_always = std::experimental::suspend_always; - using suspend_never = std::experimental::suspend_never; -} - -#else -#error C++/WinRT requires coroutine support, which is currently missing. Try enabling C++20 in your compiler. +#elif defined(_RESUMABLE_FUNCTIONS_SUPPORTED) +#error "C++/WinRT no longer supports pre-standardization coroutines. If you use co_await, switch to /await:strict or upgrade to C++20. If you do not, remove /await from the compiler flags." #endif diff --git a/strings/base_macros.h b/strings/base_macros.h index 0c4357b1e..3dc01fa2d 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -23,7 +23,7 @@ #pragma warning(disable : 4268) #endif -#if defined(__cpp_lib_coroutine) || defined(__cpp_coroutines) || defined(_RESUMABLE_FUNCTIONS_SUPPORTED) +#if defined(__cpp_lib_coroutine) #define WINRT_IMPL_COROUTINES #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ed1515526..e5ca6e0fb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,6 +105,7 @@ set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.") add_subdirectory(test) +add_subdirectory(test_nocoro) add_subdirectory(test_cpp20) add_subdirectory(test_cpp20_no_sourcelocation) diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 037e16ab7..7a7382004 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -14,12 +14,6 @@ using namespace std::chrono; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - IAsyncAction NoSuspend_IAsyncAction() { co_await 0s; @@ -1118,7 +1112,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1126,7 +1120,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1134,7 +1128,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } @@ -1143,7 +1137,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index 55c40dbe6..46b89bf6f 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -99,13 +99,13 @@ namespace // Returns an IAsyncAction that has not completed. // Call the resume() handle to complete it. - winrt::Windows::Foundation::IAsyncAction SuspendAction(impl::coroutine_handle<>& resume) + winrt::Windows::Foundation::IAsyncAction SuspendAction(std::coroutine_handle<>& resume) { struct awaiter { - impl::coroutine_handle<>& resume; + std::coroutine_handle<>& resume; bool await_ready() { return false; } - void await_suspend(impl::coroutine_handle<> handle) { resume = handle; } + void await_suspend(std::coroutine_handle<> handle) { resume = handle; } void await_resume() {} }; @@ -516,7 +516,7 @@ TEST_CASE("weak,coroutine") // Start a coroutine but don't complete it yet. // Confirm that weak references resolve. - impl::coroutine_handle<> resume; + std::coroutine_handle<> resume; weak = winrt::weak_ref(SuspendAction(resume)); REQUIRE(weak.get() != nullptr); // Now complete the coroutine. Confirm that weak references no longer resolve. diff --git a/test/test/async_auto_cancel.cpp b/test/test/async_auto_cancel.cpp index bffcb6e44..b0a541535 100644 --- a/test/test/async_auto_cancel.cpp +++ b/test/test/async_auto_cancel.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the coroutine is automatically canceled when reaching a suspension point. // @@ -18,21 +12,21 @@ namespace IAsyncAction Action(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncActionWithProgress ActionWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncOperation Operation(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -40,7 +34,7 @@ namespace IAsyncOperationWithProgress OperationWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -54,7 +48,7 @@ namespace auto cancel = co_await get_cancellation_token(); cancel.callback(nullptr); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } diff --git a/test/test/async_cancel_callback.cpp b/test/test/async_cancel_callback.cpp index c99e1dad4..75a3aac0c 100644 --- a/test/test/async_cancel_callback.cpp +++ b/test/test/async_cancel_callback.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the cancellation callback is invoked. // @@ -29,7 +23,7 @@ namespace }(); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -44,7 +38,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -59,7 +53,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -75,7 +69,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index d88fdcaf0..c98519f06 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - static bool s_exceptionLoggerCalled = false; static struct { @@ -48,7 +42,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -63,7 +57,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -78,7 +72,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -95,7 +89,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -120,7 +114,7 @@ namespace winrt_throw_hresult_handler = nullptr; s_exceptionLoggerCalled = false; - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return; @@ -147,7 +141,7 @@ namespace winrt_throw_hresult_handler = nullptr; s_exceptionLoggerCalled = false; - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return; diff --git a/test/test/when.cpp b/test/test/when.cpp index 35c9287a8..0b1151abc 100644 --- a/test/test/when.cpp +++ b/test/test/when.cpp @@ -5,13 +5,7 @@ using namespace concurrency; using namespace winrt; using namespace Windows::Foundation; -#ifdef __cpp_lib_coroutine -using std::suspend_never; -#else -using std::experimental::suspend_never; -#endif - -struct CommaStruct : suspend_never +struct CommaStruct : std::suspend_never { // If the comma operator is invoked, we will get a build failure. CommaStruct operator,(CommaStruct) = delete; diff --git a/test/test_nocoro/CMakeLists.txt b/test/test_nocoro/CMakeLists.txt new file mode 100644 index 000000000..ee234f146 --- /dev/null +++ b/test/test_nocoro/CMakeLists.txt @@ -0,0 +1,35 @@ +set(CMAKE_CXX_STANDARD 17) + +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +list(APPEND BROKEN_TESTS + # No broken tests. +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_nocoro main.cpp ${TEST_SRCS}) + +target_compile_definitions(test_nocoro PRIVATE WINRT_NO_SOURCE_LOCATION) + +target_precompile_headers(test_nocoro PRIVATE pch.h) +set_source_files_properties( + main.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_nocoro build-cppwinrt-projection) + +add_test( + NAME test_nocoro + COMMAND "$" ${TEST_COLOR_ARG} +) diff --git a/test/test_nocoro/get.cpp b/test/test_nocoro/get.cpp new file mode 100644 index 000000000..11339e10b --- /dev/null +++ b/test/test_nocoro/get.cpp @@ -0,0 +1,74 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; + +template +struct async_completion_source : implements, IAsyncOperation, IAsyncInfo> +{ + void set_result(TResult result) + { + m_result = std::move(result); + m_status = AsyncStatus::Completed; + m_completed(*this, m_status); + } + + void Completed(AsyncOperationCompletedHandler completed) + { + m_completed = completed; + } + + AsyncOperationCompletedHandler Completed() const noexcept + { + return m_completed; + } + + TResult GetResults() + { + return m_result.value(); + } + + uint32_t Id() const + { + return 1; + } + + AsyncStatus Status() const + { + return m_status; + } + + hresult ErrorCode() const + { + return hresult(0); // S_OK + } + + void Cancel() const + { + throw hresult_error(0x80070032); // E_NOT_SUPPORTED + } + + void Close() const + { + } + +private: + AsyncStatus m_status = AsyncStatus::Started; + AsyncOperationCompletedHandler m_completed; + std::optional m_result; +}; + +TEST_CASE("get") +{ + auto acs = winrt::make_self>(); + + std::thread worker([acs] + { + std::this_thread::sleep_for(1s); + acs->set_result(0xDEADBEEF); + }); + + worker.detach(); + + REQUIRE(acs.as>().get() == 0xDEADBEEF); +} diff --git a/test/test_nocoro/main.cpp b/test/test_nocoro/main.cpp new file mode 100644 index 000000000..7590df7e1 --- /dev/null +++ b/test/test_nocoro/main.cpp @@ -0,0 +1,22 @@ +#include +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#include "winrt/base.h" + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_nocoro/pch.cpp b/test/test_nocoro/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_nocoro/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_nocoro/pch.h b/test/test_nocoro/pch.h new file mode 100644 index 000000000..7ff48a37c --- /dev/null +++ b/test/test_nocoro/pch.h @@ -0,0 +1,6 @@ +#pragma once + +#include "catch.hpp" +#include "winrt/Windows.Foundation.h" + +using namespace std::literals; diff --git a/test/test_nocoro/test_nocoro.vcxproj b/test/test_nocoro/test_nocoro.vcxproj new file mode 100644 index 000000000..7efc28066 --- /dev/null +++ b/test/test_nocoro/test_nocoro.vcxproj @@ -0,0 +1,241 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {9E392830-805A-4AAF-932D-C493143EFACA} + unittests + test_nocoro + false + + + + Application + true + + + Application + true + + + Application + false + true + + + Application + false + true + + + Application + true + + + Application + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + + + + + NotUsing + + + Create + + + + + + \ No newline at end of file From 481f8f40816dd7c49a073de4b5d09191e5140e7f Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Tue, 17 Mar 2026 13:54:27 +0800 Subject: [PATCH 283/305] =?UTF-8?q?Add=20missing=20headers=20and=20std=20q?= =?UTF-8?q?ualification,=20use=20std::numeric=5Flimits=20in=E2=80=A6=20(#1?= =?UTF-8?q?546)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add missing headers and std qualification, use std::numeric_limits instead of macros, and use std::memcpy/std::swprintf instead of the non-standard memcpy_s/swprintf_s * Remove a accidentally added redundant comment * Add some headers as suggested by Copilot * Use std::copy_n instead of std::memcpy, and protect std::numeric_limits::max from the max macro --- cppwinrt/cmd_reader.h | 31 +-- cppwinrt/code_writers.h | 84 +++--- cppwinrt/component_writers.h | 20 +- cppwinrt/helpers.h | 30 +-- cppwinrt/text_writer.h | 27 +- cppwinrt/type_writers.h | 22 +- strings/base_abi.h | 96 +++---- strings/base_activation.h | 74 +++--- strings/base_agile_ref.h | 4 +- strings/base_array.h | 64 ++--- strings/base_chrono.h | 10 +- strings/base_collections.h | 6 +- strings/base_collections_base.h | 50 ++-- strings/base_collections_map.h | 6 +- strings/base_collections_vector.h | 18 +- strings/base_com_ptr.h | 8 +- strings/base_coroutine_foundation.h | 14 +- strings/base_coroutine_threadpool.h | 52 ++-- strings/base_deferral.h | 2 +- strings/base_delegate.h | 18 +- strings/base_error.h | 22 +- strings/base_events.h | 26 +- strings/base_extern.h | 98 +++---- strings/base_fast_forward.h | 42 +-- strings/base_identity.h | 240 +++++++++--------- strings/base_implements.h | 150 +++++------ strings/base_includes.h | 5 + strings/base_iterator.h | 10 +- strings/base_lock.h | 2 +- strings/base_marshaler.h | 20 +- strings/base_natvis.h | 34 +-- strings/base_reference_produce.h | 126 ++++----- strings/base_security.h | 2 +- strings/base_std_hash.h | 22 +- strings/base_string.h | 84 +++--- strings/base_string_input.h | 8 +- strings/base_string_operators.h | 6 +- strings/base_types.h | 52 ++-- strings/base_version.h | 4 +- strings/base_windows.h | 6 +- strings/base_xaml_component_connector.h | 4 +- strings/base_xaml_component_connector_winui.h | 4 +- strings/base_xaml_typename.h | 16 +- 43 files changed, 814 insertions(+), 805 deletions(-) diff --git a/cppwinrt/cmd_reader.h b/cppwinrt/cmd_reader.h index 7faf49e4f..e2787b7d4 100644 --- a/cppwinrt/cmd_reader.h +++ b/cppwinrt/cmd_reader.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -203,7 +204,7 @@ namespace cppwinrt while (true) { - DWORD actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); + DWORD actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); if (actual_size < 1 + path.size()) { @@ -237,12 +238,12 @@ namespace cppwinrt } auto key = open_sdk(); - uint32_t index{}; + std::uint32_t index{}; std::array subkey; std::array version_parts{}; std::string result; - while (0 == RegEnumKeyA(key.handle, index++, subkey.data(), static_cast(subkey.size()))) + while (0 == RegEnumKeyA(key.handle, index++, subkey.data(), static_cast(subkey.size()))) { if (!std::regex_match(subkey.data(), match, rx)) { @@ -258,7 +259,7 @@ namespace cppwinrt char* next_part = subkey.data(); bool force_newer = false; - for (size_t i = 0; ; ++i) + for (std::size_t i = 0; ; ++i) { auto version_part = strtoul(next_part, &next_part, 10); @@ -312,19 +313,19 @@ namespace cppwinrt struct option { - static constexpr uint32_t no_min = 0; - static constexpr uint32_t no_max = UINT_MAX; + static constexpr std::uint32_t no_min = 0; + static constexpr std::uint32_t no_max = (std::numeric_limits::max)(); std::string_view name; - uint32_t min{ no_min }; - uint32_t max{ no_max }; + std::uint32_t min{ no_min }; + std::uint32_t max{ no_max }; std::string_view arg{}; std::string_view desc{}; }; struct reader { - template + template reader(C const argc, V const argv, const option(& options)[numOptions]) { #ifdef _DEBUG @@ -449,9 +450,9 @@ namespace cppwinrt #if defined(_WIN32) || defined(_WIN64) std::array local{}; #ifdef _WIN64 - ExpandEnvironmentStringsA("%windir%\\System32\\WinMetadata", local.data(), static_cast(local.size())); + ExpandEnvironmentStringsA("%windir%\\System32\\WinMetadata", local.data(), static_cast(local.size())); #else - ExpandEnvironmentStringsA("%windir%\\SysNative\\WinMetadata", local.data(), static_cast(local.size())); + ExpandEnvironmentStringsA("%windir%\\SysNative\\WinMetadata", local.data(), static_cast(local.size())); #endif add_directory(local.data()); #else /* defined(_WIN32) || defined(_WIN64) */ @@ -586,7 +587,7 @@ namespace cppwinrt std::filesystem::path response_path{ std::string{ arg } }; std::string extension = response_path.extension().generic_string(); std::transform(extension.begin(), extension.end(), extension.begin(), - [](auto c) { return static_cast(::tolower(c)); }); + [](auto c) { return static_cast(std::tolower(c)); }); // Check if misuse of @ prefix, so if directory or metadata file instead of response file. if (is_directory(response_path) || extension == ".winmd") @@ -597,12 +598,12 @@ namespace cppwinrt std::ifstream response_file(absolute(response_path)); while (getline(response_file, line_buf)) { - size_t argc = 0; + std::size_t argc = 0; std::vector argv; parse_command_line(line_buf.data(), argv, &argc); - for (size_t i = 0; i < argc; i++) + for (std::size_t i = 0; i < argc; i++) { extract_option(argv[i], options, last); } @@ -610,7 +611,7 @@ namespace cppwinrt } template - static void parse_command_line(Character* cmdstart, std::vector& argv, size_t* argument_count) + static void parse_command_line(Character* cmdstart, std::vector& argv, std::size_t* argument_count) { std::string arg; diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index e24cfd302..0a4c4638e 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -359,17 +359,17 @@ namespace cppwinrt using std::get; w.write_printf("0x%08X,0x%04X,0x%04X,{ 0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X }", - get(get(args[0].value).value), - get(get(args[1].value).value), - get(get(args[2].value).value), - get(get(args[3].value).value), - get(get(args[4].value).value), - get(get(args[5].value).value), - get(get(args[6].value).value), - get(get(args[7].value).value), - get(get(args[8].value).value), - get(get(args[9].value).value), - get(get(args[10].value).value)); + get(get(args[0].value).value), + get(get(args[1].value).value), + get(get(args[2].value).value), + get(get(args[3].value).value), + get(get(args[4].value).value), + get(get(args[5].value).value), + get(get(args[6].value).value), + get(get(args[7].value).value), + get(get(args[8].value).value), + get(get(args[9].value).value), + get(get(args[10].value).value)); } static void write_guid_comment(writer& w, std::vector const& args) @@ -377,17 +377,17 @@ namespace cppwinrt using std::get; w.write_printf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", - get(get(args[0].value).value), - get(get(args[1].value).value), - get(get(args[2].value).value), - get(get(args[3].value).value), - get(get(args[4].value).value), - get(get(args[5].value).value), - get(get(args[6].value).value), - get(get(args[7].value).value), - get(get(args[8].value).value), - get(get(args[9].value).value), - get(get(args[10].value).value)); + get(get(args[0].value).value), + get(get(args[1].value).value), + get(get(args[2].value).value), + get(get(args[3].value).value), + get(get(args[4].value).value), + get(get(args[5].value).value), + get(get(args[6].value).value), + get(get(args[7].value).value), + get(get(args[8].value).value), + get(get(args[9].value).value), + get(get(args[10].value).value)); } static void write_category(writer& w, TypeDef const& type, std::string_view const& category) @@ -561,15 +561,15 @@ namespace cppwinrt if (param.Flags().In()) { - format = "uint32_t%, %"; + format = "std::uint32_t%, %"; } else if (param_signature->ByRef()) { - format = "uint32_t*%, %*"; + format = "std::uint32_t*%, %*"; } else { - format = "uint32_t%, %"; + format = "std::uint32_t%, %"; } w.write(format, bind(param), bind(param_signature->Type())); @@ -605,7 +605,7 @@ namespace cppwinrt if (type.is_szarray()) { - w.write("uint32_t* __%Size, %**", method_signature.return_param_name(), type); + w.write("std::uint32_t* __%Size, %**", method_signature.return_param_name(), type); } else { @@ -748,7 +748,7 @@ namespace cppwinrt break; } - auto format = R"( virtual int32_t __stdcall %(%) noexcept = 0; + auto format = R"( virtual std::int32_t __stdcall %(%) noexcept = 0; )"; for (auto&& method : info.type.MethodList()) @@ -788,7 +788,7 @@ namespace cppwinrt } - auto format = R"( virtual int32_t __stdcall %(%) noexcept = 0; + auto format = R"( virtual std::int32_t __stdcall %(%) noexcept = 0; )"; auto abi_guard = w.push_abi_types(true); @@ -821,7 +821,7 @@ namespace cppwinrt { struct WINRT_IMPL_ABI_DECL type : unknown_abi { - virtual int32_t __stdcall Invoke(%) noexcept = 0; + virtual std::int32_t __stdcall Invoke(%) noexcept = 0; }; }; )"; @@ -1054,7 +1054,7 @@ namespace cppwinrt if (category == param_category::array_type) { auto format = R"( - uint32_t %_impl_size{}; + std::uint32_t %_impl_size{}; %* %{};)"; auto abi_guard = w.push_abi_types(true); @@ -1317,7 +1317,7 @@ namespace cppwinrt w.write(R"( auto data() const { - uint8_t* data{}; + std::uint8_t* data{}; static_cast(*this).template as()->Buffer(&data); return data; } @@ -1328,8 +1328,8 @@ namespace cppwinrt w.write(R"( auto data() const { - uint8_t* data{}; - uint32_t capacity{}; + std::uint8_t* data{}; + std::uint32_t capacity{}; check_hresult(static_cast(*this).template as()->GetBuffer(&data, &capacity)); return data; } @@ -1480,7 +1480,7 @@ namespace cppwinrt using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = T; - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = T; )"); @@ -1491,7 +1491,7 @@ namespace cppwinrt using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = Windows::Foundation::IInspectable; - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = Windows::Foundation::IInspectable; )"); @@ -1874,7 +1874,7 @@ namespace cppwinrt if (is_noexcept(method)) { - format = R"( int32_t __stdcall %(%) noexcept final + format = R"( std::int32_t __stdcall %(%) noexcept final { % typename D::abi_guard guard(this->shim()); % @@ -1884,7 +1884,7 @@ namespace cppwinrt } else { - format = R"( int32_t __stdcall %(%) noexcept final try + format = R"( std::int32_t __stdcall %(%) noexcept final try { % typename D::abi_guard guard(this->shim()); % @@ -1906,7 +1906,7 @@ namespace cppwinrt { // Special-case IMap*::Lookup to look for a TryLookup here, to avoid extranous throw/originates std::string tryLookupUpCall = "this->shim().TryLookup"; - format = R"( int32_t __stdcall %(%) noexcept final try + format = R"( std::int32_t __stdcall %(%) noexcept final try { % typename D::abi_guard guard(this->shim()); if constexpr (has_TryLookup_v) @@ -2596,7 +2596,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { delegate(H&& handler) : implements_delegate<%, H>(std::forward(handler)) {} - int32_t __stdcall Invoke(%) noexcept final try + std::int32_t __stdcall Invoke(%) noexcept final try { % % return 0; @@ -2801,7 +2801,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable static void write_struct_equality(writer& w, std::vector> const& fields) { - for (size_t i = 0; i != fields.size(); ++i) + for (std::size_t i = 0; i != fields.size(); ++i) { w.write(" left.% == right.%", fields[i].first, fields[i].first); @@ -2877,9 +2877,9 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable return false; }; - for (size_t left = 0; left < structs.size(); ++left) + for (std::size_t left = 0; left < structs.size(); ++left) { - for (size_t right = left + 1; right < structs.size(); ++right) + for (std::size_t right = left + 1; right < structs.size(); ++right) { if (depends(w, structs[left], structs[right])) { diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index cb748917d..3966cad6c 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -172,7 +172,7 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons } format = R"( -int32_t __stdcall WINRT_CanUnloadNow() noexcept +std::int32_t __stdcall WINRT_CanUnloadNow() noexcept { #ifdef _WRL_MODULE_H_ #ifdef _MSC_VER @@ -187,7 +187,7 @@ int32_t __stdcall WINRT_CanUnloadNow() noexcept return %_can_unload_now() ? 0 : 1; } -int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept try +std::int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept try { std::wstring_view const name{ *reinterpret_cast(&classId) }; *factory = %_get_activation_factory(name); @@ -640,7 +640,7 @@ catch (...) { return winrt::to_hresult(); } } )"; - size_t offset = get_bases(type).size(); + std::size_t offset = get_bases(type).size(); auto interfaces = get_interfaces(w, type); for (auto&& [name, info] : interfaces) @@ -685,7 +685,7 @@ catch (...) { return winrt::to_hresult(); } if (has_base) { auto format = R"( - int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override + std::int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override {% return B::query_interface_tearoff(id, result); } @@ -701,7 +701,7 @@ catch (...) { return winrt::to_hresult(); } } auto format = R"( - int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override + std::int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override {% return impl::error_no_interface; } @@ -779,8 +779,8 @@ catch (...) { return winrt::to_hresult(); } { composable_base_name = w.write_temp("using composable_base = %;", base_type); auto base_interfaces = get_interfaces(w, base_type); - uint32_t base_interfaces_count{}; - uint32_t protected_base_interfaces_count{}; + std::uint32_t base_interfaces_count{}; + std::uint32_t protected_base_interfaces_count{}; external_requires = ",\n impl::require(::toupper(c)); }); + std::transform(upper.begin(), upper.end(), upper.begin(), [](char c) {return static_cast(std::toupper(c)); }); auto include_path = get_generated_component_filename(type); @@ -1240,7 +1240,7 @@ namespace winrt::@::implementation static void write_component_fast_abi_thunk(writer& w) { - for (uint32_t slot = 6; slot < 1024; ++slot) + for (std::uint32_t slot = 6; slot < 1024; ++slot) { auto format = R"( extern "C" void __stdcall winrt_ff_thunk%(); )"; @@ -1251,7 +1251,7 @@ namespace winrt::@::implementation static void write_component_fast_abi_vtable(writer& w) { - for (uint32_t slot = 6; slot < 1024; ++slot) + for (std::uint32_t slot = 6; slot < 1024; ++slot) { auto format = R"( #if WINRT_FAST_ABI_SIZE > % diff --git a/cppwinrt/helpers.h b/cppwinrt/helpers.h index 522d0bcd1..2dc152a74 100644 --- a/cppwinrt/helpers.h +++ b/cppwinrt/helpers.h @@ -31,7 +31,7 @@ namespace cppwinrt ++params.first; } - for (uint32_t i{}; i != size(m_signature.Params()); ++i) + for (std::uint32_t i{}; i != size(m_signature.Params()); ++i) { m_params.emplace_back(params.first + i, &m_signature.Params().first[i]); } @@ -193,7 +193,7 @@ namespace cppwinrt } template - auto get_attribute_value(CustomAttribute const& attribute, uint32_t const arg) + auto get_attribute_value(CustomAttribute const& attribute, std::uint32_t const arg) { return get_attribute_value(attribute.Value().FixedArgs()[arg]); } @@ -330,15 +330,15 @@ namespace cppwinrt struct contract_version { std::string_view name; - uint32_t version; + std::uint32_t version; }; struct previous_contract { std::string_view contract_from; std::string_view contract_to; - uint32_t version_low; - uint32_t version_high; + std::uint32_t version_low; + std::uint32_t version_high; }; struct contract_history @@ -359,7 +359,7 @@ namespace cppwinrt assert(args.size() == 2); contract_version result{}; - result.version = get_integer_attribute(args[1]); + result.version = get_integer_attribute(args[1]); call(std::get(args[0].value).value, [&](ElemSig::SystemType t) { @@ -388,8 +388,8 @@ namespace cppwinrt previous_contract result{}; result.contract_from = get_attribute_value(args[0]); - result.version_low = get_integer_attribute(args[1]); - result.version_high = get_integer_attribute(args[2]); + result.version_low = get_integer_attribute(args[1]); + result.version_high = get_integer_attribute(args[2]); if (args.size() == 4) { result.contract_to = get_attribute_value(args[3]); @@ -452,7 +452,7 @@ namespace cppwinrt // is not a contract version if (current_contract.name.empty()) { - current_contract.version = get_attribute_value(attribute, 0); + current_contract.version = get_attribute_value(attribute, 0); } } } @@ -509,7 +509,7 @@ namespace cppwinrt } assert(result.previous_contracts.back().contract_to == result.current_contract.name); - for (size_t size = result.previous_contracts.size() - 1; size; --size) + for (std::size_t size = result.previous_contracts.size() - 1; size; --size) { auto& last = result.previous_contracts[size]; auto itr = std::find_if(result.previous_contracts.begin(), result.previous_contracts.begin() + size, [&](auto const& prev) @@ -537,7 +537,7 @@ namespace cppwinrt // in relative to the contract history of the class. E.g. if a class goes from contract 'A' to 'B' to 'C', // 'relativeContract' would be '0' for an interface introduced in contract 'A', '1' for an interface introduced // in contract 'B', etc. This is only set/valid for 'fastabi' interfaces - std::pair relative_version{}; + std::pair relative_version{}; std::vector> generic_param_stack{}; }; @@ -660,7 +660,7 @@ namespace cppwinrt } auto history = get_contract_history(type); - size_t count = 0; + std::size_t count = 0; for (auto& pair : result) { if (pair.second.exclusive && !pair.second.base && !pair.second.overridable) @@ -676,12 +676,12 @@ namespace cppwinrt }); if (itr != history.previous_contracts.end()) { - pair.second.relative_version.first = static_cast(itr - history.previous_contracts.begin()); + pair.second.relative_version.first = static_cast(itr - history.previous_contracts.begin()); } else { assert(history.current_contract.name == introduced.name); - pair.second.relative_version.first = static_cast(history.previous_contracts.size()); + pair.second.relative_version.first = static_cast(history.previous_contracts.size()); } } } @@ -863,7 +863,7 @@ namespace cppwinrt { if (auto visibility = std::get_if(&std::get(arg.value).value)) { - info.visible = std::get(visibility->value) == 2; + info.visible = std::get(visibility->value) == 2; break; } } diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index 0b7c07a4e..a274d11ce 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -66,7 +67,7 @@ namespace cppwinrt #if defined(_DEBUG) if (debug_trace) { - ::printf("%.*s", static_cast(value.size()), value.data()); + std::printf("%.*s", static_cast(value.size()), value.data()); } #endif } @@ -78,7 +79,7 @@ namespace cppwinrt #if defined(_DEBUG) if (debug_trace) { - ::printf("%c", value); + std::printf("%c", value); } #endif } @@ -139,12 +140,12 @@ namespace cppwinrt { char buffer[128]; #if defined(_WIN32) || defined(_WIN64) - size_t const size = sprintf_s(buffer, format, args...); + std::size_t const size = sprintf_s(buffer, format, args...); #else - size_t size = snprintf(buffer, sizeof(buffer), format, args...); + std::size_t size = std::snprintf(buffer, sizeof(buffer), format, args...); if (size > sizeof(buffer) - 1) { - fprintf(stderr, "\n*** WARNING: writer_base::write_printf -- buffer too small\n"); + std::fprintf(stderr, "\n*** WARNING: writer_base::write_printf -- buffer too small\n"); size = sizeof(buffer) - 1; } #endif @@ -167,8 +168,8 @@ namespace cppwinrt void flush_to_console(bool to_stdout = true) noexcept { - fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_first.size()), m_first.data()); - fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_second.size()), m_second.data()); + std::fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_first.size()), m_first.data()); + std::fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_second.size()), m_second.data()); m_first.clear(); m_second.clear(); } @@ -243,9 +244,9 @@ namespace cppwinrt private: - static constexpr uint32_t count_placeholders(std::string_view const& format) noexcept + static constexpr std::uint32_t count_placeholders(std::string_view const& format) noexcept { - uint32_t count{}; + std::uint32_t count{}; bool escape{}; for (auto c : format) @@ -332,7 +333,7 @@ namespace cppwinrt { struct indent_guard { - indent_guard(indented_writer_base& w, int32_t offset = 1) noexcept : m_writer(w), m_offset(offset) + indent_guard(indented_writer_base& w, std::int32_t offset = 1) noexcept : m_writer(w), m_offset(offset) { m_writer.m_indent += m_offset; } @@ -344,13 +345,13 @@ namespace cppwinrt private: indented_writer_base& m_writer; - int32_t m_offset{}; + std::int32_t m_offset{}; }; void write_indent() { - for (int32_t i = 0; i < m_indent; i++) + for (std::int32_t i = 0; i < m_indent; i++) { writer_base::write_impl(" "); } @@ -418,7 +419,7 @@ namespace cppwinrt return result; } - int32_t m_indent{}; + std::int32_t m_indent{}; }; diff --git a/cppwinrt/type_writers.h b/cppwinrt/type_writers.h index 0fa3e5f8d..df17450f1 100644 --- a/cppwinrt/type_writers.h +++ b/cppwinrt/type_writers.h @@ -232,12 +232,12 @@ namespace cppwinrt return member_value_guard(this, &writer::delegate_types, value); } - void write_value(int32_t value) + void write_value(std::int32_t value) { write_printf("%d", value); } - void write_value(uint32_t value) + void write_value(std::uint32_t value) { write_printf("%#0x", value); } @@ -309,7 +309,7 @@ namespace cppwinrt { if ((name == "DateTime" || name == "TimeSpan") && ns == "Windows.Foundation") { - write("int64_t"); + write("std::int64_t"); } else if ((name == "Point" || name == "Size" || name == "Rect") && ns == "Windows.Foundation") { @@ -473,14 +473,14 @@ namespace cppwinrt { if (type == ElementType::Boolean) { write("bool"); } else if (type == ElementType::Char) { write("char16_t"); } - else if (type == ElementType::I1) { write("int8_t"); } - else if (type == ElementType::U1) { write("uint8_t"); } - else if (type == ElementType::I2) { write("int16_t"); } - else if (type == ElementType::U2) { write("uint16_t"); } - else if (type == ElementType::I4) { write("int32_t"); } - else if (type == ElementType::U4) { write("uint32_t"); } - else if (type == ElementType::I8) { write("int64_t"); } - else if (type == ElementType::U8) { write("uint64_t"); } + else if (type == ElementType::I1) { write("std::int8_t"); } + else if (type == ElementType::U1) { write("std::uint8_t"); } + else if (type == ElementType::I2) { write("std::int16_t"); } + else if (type == ElementType::U2) { write("std::uint16_t"); } + else if (type == ElementType::I4) { write("std::int32_t"); } + else if (type == ElementType::U4) { write("std::uint32_t"); } + else if (type == ElementType::I8) { write("std::int64_t"); } + else if (type == ElementType::U8) { write("std::uint64_t"); } else if (type == ElementType::R4) { write("float"); } else if (type == ElementType::R8) { write("double"); } else if (type == ElementType::String) diff --git a/strings/base_abi.h b/strings/base_abi.h index ec42fefe6..72946a3fa 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -5,9 +5,9 @@ namespace winrt::impl { struct WINRT_IMPL_ABI_DECL type { - virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; - virtual uint32_t __stdcall AddRef() noexcept = 0; - virtual uint32_t __stdcall Release() noexcept = 0; + virtual std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; + virtual std::uint32_t __stdcall AddRef() noexcept = 0; + virtual std::uint32_t __stdcall Release() noexcept = 0; }; }; @@ -17,9 +17,9 @@ namespace winrt::impl { struct WINRT_IMPL_ABI_DECL type : unknown_abi { - virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; - virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; - virtual int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* level) noexcept = 0; + virtual std::int32_t __stdcall GetIids(std::uint32_t* count, guid** ids) noexcept = 0; + virtual std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; + virtual std::int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* level) noexcept = 0; }; }; @@ -29,7 +29,7 @@ namespace winrt::impl { struct WINRT_IMPL_ABI_DECL type : inspectable_abi { - virtual int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; + virtual std::int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; }; }; @@ -37,109 +37,109 @@ namespace winrt::impl struct WINRT_IMPL_ABI_DECL IAgileReference : unknown_abi { - virtual int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; + virtual std::int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IMarshal : unknown_abi { - virtual int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept = 0; - virtual int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept = 0; - virtual int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags) noexcept = 0; - virtual int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept = 0; - virtual int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept = 0; - virtual int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept = 0; + virtual std::int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, guid* pCid) noexcept = 0; + virtual std::int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, std::uint32_t* pSize) noexcept = 0; + virtual std::int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags) noexcept = 0; + virtual std::int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept = 0; + virtual std::int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept = 0; + virtual std::int32_t __stdcall DisconnectObject(std::uint32_t dwReserved) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IGlobalInterfaceTable : unknown_abi { - virtual int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, uint32_t* cookie) noexcept = 0; - virtual int32_t __stdcall RevokeInterfaceFromGlobal(uint32_t cookie) noexcept = 0; - virtual int32_t __stdcall GetInterfaceFromGlobal(uint32_t cookie, guid const& iid, void** object) noexcept = 0; + virtual std::int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, std::uint32_t* cookie) noexcept = 0; + virtual std::int32_t __stdcall RevokeInterfaceFromGlobal(std::uint32_t cookie) noexcept = 0; + virtual std::int32_t __stdcall GetInterfaceFromGlobal(std::uint32_t cookie, guid const& iid, void** object) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IStaticLifetime : inspectable_abi { - virtual int32_t __stdcall unused() noexcept = 0; - virtual int32_t __stdcall GetCollection(void** value) noexcept = 0; + virtual std::int32_t __stdcall unused() noexcept = 0; + virtual std::int32_t __stdcall GetCollection(void** value) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IStaticLifetimeCollection : inspectable_abi { - virtual int32_t __stdcall Lookup(void*, void**) noexcept = 0; - virtual int32_t __stdcall unused() noexcept = 0; - virtual int32_t __stdcall unused2() noexcept = 0; - virtual int32_t __stdcall unused3() noexcept = 0; - virtual int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0; - virtual int32_t __stdcall Remove(void*) noexcept = 0; - virtual int32_t __stdcall unused4() noexcept = 0; + virtual std::int32_t __stdcall Lookup(void*, void**) noexcept = 0; + virtual std::int32_t __stdcall unused() noexcept = 0; + virtual std::int32_t __stdcall unused2() noexcept = 0; + virtual std::int32_t __stdcall unused3() noexcept = 0; + virtual std::int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0; + virtual std::int32_t __stdcall Remove(void*) noexcept = 0; + virtual std::int32_t __stdcall unused4() noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IWeakReference : unknown_abi { - virtual int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; + virtual std::int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IWeakReferenceSource : unknown_abi { - virtual int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; + virtual std::int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IRestrictedErrorInfo : unknown_abi { - virtual int32_t __stdcall GetErrorDetails(bstr* description, int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; - virtual int32_t __stdcall GetReference(bstr* reference) noexcept = 0; + virtual std::int32_t __stdcall GetErrorDetails(bstr* description, std::int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; + virtual std::int32_t __stdcall GetReference(bstr* reference) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IErrorInfo : unknown_abi { - virtual int32_t __stdcall GetGUID(guid* value) noexcept = 0; - virtual int32_t __stdcall GetSource(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetDescription(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetHelpFile(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetHelpContext(uint32_t* value) noexcept = 0; + virtual std::int32_t __stdcall GetGUID(guid* value) noexcept = 0; + virtual std::int32_t __stdcall GetSource(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetDescription(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetHelpFile(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetHelpContext(std::uint32_t* value) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL ILanguageExceptionErrorInfo2 : unknown_abi { - virtual int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; - virtual int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; - virtual int32_t __stdcall CapturePropagationContext(void* exception) noexcept = 0; - virtual int32_t __stdcall GetPropagationContextHead(ILanguageExceptionErrorInfo2** head) noexcept = 0; + virtual std::int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; + virtual std::int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; + virtual std::int32_t __stdcall CapturePropagationContext(void* exception) noexcept = 0; + virtual std::int32_t __stdcall GetPropagationContextHead(ILanguageExceptionErrorInfo2** head) noexcept = 0; }; struct ICallbackWithNoReentrancyToApplicationSTA; struct WINRT_IMPL_ABI_DECL IContextCallback : unknown_abi { - virtual int32_t __stdcall ContextCallback(int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; + virtual std::int32_t __stdcall ContextCallback(std::int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IServerSecurity : unknown_abi { - virtual int32_t __stdcall QueryBlanket(uint32_t*, uint32_t*, wchar_t**, uint32_t*, uint32_t*, void**, uint32_t*) noexcept = 0; - virtual int32_t __stdcall ImpersonateClient() noexcept = 0; - virtual int32_t __stdcall RevertToSelf() noexcept = 0; - virtual int32_t __stdcall IsImpersonating() noexcept = 0; + virtual std::int32_t __stdcall QueryBlanket(std::uint32_t*, std::uint32_t*, wchar_t**, std::uint32_t*, std::uint32_t*, void**, std::uint32_t*) noexcept = 0; + virtual std::int32_t __stdcall ImpersonateClient() noexcept = 0; + virtual std::int32_t __stdcall RevertToSelf() noexcept = 0; + virtual std::int32_t __stdcall IsImpersonating() noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IBufferByteAccess : unknown_abi { - virtual int32_t __stdcall Buffer(uint8_t** value) noexcept = 0; + virtual std::int32_t __stdcall Buffer(std::uint8_t** value) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IMemoryBufferByteAccess : unknown_abi { - virtual int32_t __stdcall GetBuffer(uint8_t** value, uint32_t* capacity) noexcept = 0; + virtual std::int32_t __stdcall GetBuffer(std::uint8_t** value, std::uint32_t* capacity) noexcept = 0; }; template <> struct abi { - using type = int64_t; + using type = std::int64_t; }; template <> struct abi { - using type = int64_t; + using type = std::int64_t; }; template <> inline constexpr guid guid_v{ 0x00000000, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } }; diff --git a/strings/base_activation.h b/strings/base_activation.h index 586df32e9..1a195d865 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -30,7 +30,7 @@ namespace winrt::impl if (hr == impl::error_not_initialized) { - auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); + auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); if (!usage) { @@ -65,7 +65,7 @@ namespace winrt::impl continue; } - auto library_call = reinterpret_cast(WINRT_IMPL_GetProcAddress(library.get(), "DllGetActivationFactory")); + auto library_call = reinterpret_cast(WINRT_IMPL_GetProcAddress(library.get(), "DllGetActivationFactory")); if (!library_call) { @@ -127,17 +127,17 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { - inline int32_t interlocked_read_32(int32_t const volatile* target) noexcept + inline std::int32_t interlocked_read_32(std::int32_t const volatile* target) noexcept { #if defined _M_IX86 || defined _M_X64 - int32_t const result = *target; + std::int32_t const result = *target; _ReadWriteBarrier(); return result; #elif defined _M_ARM64 #if defined(__GNUC__) - int32_t const result = *target; + std::int32_t const result = *target; #else - int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); + std::int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); #endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; @@ -147,17 +147,17 @@ namespace winrt::impl } #if defined _WIN64 - inline int64_t interlocked_read_64(int64_t const volatile* target) noexcept + inline std::int64_t interlocked_read_64(std::int64_t const volatile* target) noexcept { #if defined _M_X64 - int64_t const result = *target; + std::int64_t const result = *target; _ReadWriteBarrier(); return result; #elif defined _M_ARM64 #if defined(__GNUC__) - int64_t const result = *target; + std::int64_t const result = *target; #else - int64_t const result = __iso_volatile_load64(target); + std::int64_t const result = __iso_volatile_load64(target); #endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; @@ -177,14 +177,14 @@ namespace winrt::impl T* interlocked_read_pointer(T* const volatile* target) noexcept { #ifdef _WIN64 - return (T*)interlocked_read_64((int64_t*)target); + return (T*)interlocked_read_64((std::int64_t*)target); #else - return (T*)interlocked_read_32((int32_t*)target); + return (T*)interlocked_read_32((std::int32_t*)target); #endif } #ifdef _WIN64 - inline constexpr uint32_t memory_allocation_alignment{ 16 }; + inline constexpr std::uint32_t memory_allocation_alignment{ 16 }; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4324) // structure was padded due to alignment specifier @@ -197,34 +197,34 @@ namespace winrt::impl { struct { - uint64_t reserved1; - uint64_t reserved2; + std::uint64_t reserved1; + std::uint64_t reserved2; } reserved1; struct { - uint64_t reserved1 : 16; - uint64_t reserved2 : 48; - uint64_t reserved3 : 4; - uint64_t reserved4 : 60; + std::uint64_t reserved1 : 16; + std::uint64_t reserved2 : 48; + std::uint64_t reserved3 : 4; + std::uint64_t reserved4 : 60; } reserved2; }; #ifdef _MSC_VER #pragma warning(pop) #endif #else - inline constexpr uint32_t memory_allocation_alignment{ 8 }; + inline constexpr std::uint32_t memory_allocation_alignment{ 8 }; struct slist_entry { slist_entry* next; }; union slist_header { - uint64_t reserved1; + std::uint64_t reserved1; struct { slist_entry reserved1; - uint16_t reserved2; - uint16_t reserved3; + std::uint16_t reserved2; + std::uint16_t reserved3; } reserved2; }; #endif @@ -234,11 +234,11 @@ namespace winrt::impl factory_count_guard(factory_count_guard const&) = delete; factory_count_guard& operator=(factory_count_guard const&) = delete; - explicit factory_count_guard(size_t& count) noexcept : m_count(count) + explicit factory_count_guard(std::size_t& count) noexcept : m_count(count) { #ifndef WINRT_NO_MODULE_LOCK #ifdef _WIN64 - _InterlockedIncrement64((int64_t*)&m_count); + _InterlockedIncrement64((std::int64_t*)&m_count); #else _InterlockedIncrement((long*)&m_count); #endif @@ -249,7 +249,7 @@ namespace winrt::impl { #ifndef WINRT_NO_MODULE_LOCK #ifdef _WIN64 - _InterlockedDecrement64((int64_t*)&m_count); + _InterlockedDecrement64((std::int64_t*)&m_count); #else _InterlockedDecrement((long*)&m_count); #endif @@ -257,7 +257,7 @@ namespace winrt::impl } private: - [[maybe_unused]] size_t& m_count; // Field is unused when WINRT_NO_MODULE_LOCK is defined. + [[maybe_unused]] std::size_t& m_count; // Field is unused when WINRT_NO_MODULE_LOCK is defined. }; struct factory_cache_entry_base @@ -265,7 +265,7 @@ namespace winrt::impl struct alignas(sizeof(void*) * 2) object_and_count { unknown_abi* object; - size_t count; + std::size_t count; }; object_and_count m_value; @@ -286,16 +286,16 @@ namespace winrt::impl #if defined(__GNUC__) bool exchanged = __sync_bool_compare_and_swap((__int128*)this, *(__int128*)¤t_value, (__int128)0); #else - bool exchanged = 1 == _InterlockedCompareExchange128((int64_t*)this, 0, 0, (int64_t*)¤t_value); + bool exchanged = 1 == _InterlockedCompareExchange128((std::int64_t*)this, 0, 0, (std::int64_t*)¤t_value); #endif if (exchanged) { pointer_value->Release(); } #else - int64_t const result = _InterlockedCompareExchange64((int64_t*)this, 0, *(int64_t*)¤t_value); + std::int64_t const result = _InterlockedCompareExchange64((std::int64_t*)this, 0, *(std::int64_t*)¤t_value); - if (result == *(int64_t*)¤t_value) + if (result == *(std::int64_t*)¤t_value) { pointer_value->Release(); } @@ -330,7 +330,7 @@ namespace winrt::impl // entry->next must be read before entry->clear() is called since the InterlockedCompareExchange // inside clear() will allow another thread to add the entry back to the cache. slist_entry* next = entry->next; - reinterpret_cast(reinterpret_cast(entry) - offsetof(factory_cache_entry_base, m_next))->clear(); + reinterpret_cast(reinterpret_cast(entry) - offsetof(factory_cache_entry_base, m_next))->clear(); entry = next; } } @@ -443,7 +443,7 @@ namespace winrt::impl template struct produce : produce_base { - int32_t __stdcall ActivateInstance(void** instance) noexcept final try + std::int32_t __stdcall ActivateInstance(void** instance) noexcept final try { *instance = nullptr; typename D::abi_guard guard(this->shim()); @@ -456,7 +456,7 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { - enum class apartment_type : int32_t + enum class apartment_type : std::int32_t { multi_threaded = 0, single_threaded = 2, @@ -464,7 +464,7 @@ WINRT_EXPORT namespace winrt inline void init_apartment(apartment_type const type = apartment_type::multi_threaded) { - hresult const result = WINRT_IMPL_CoInitializeEx(nullptr, static_cast(type)); + hresult const result = WINRT_IMPL_CoInitializeEx(nullptr, static_cast(type)); if (result < 0) { @@ -519,13 +519,13 @@ WINRT_EXPORT namespace winrt } template - auto try_create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) + auto try_create_instance(guid const& clsid, std::uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) { return try_capture(WINRT_IMPL_CoCreateInstance, clsid, outer, context); } template - auto create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) + auto create_instance(guid const& clsid, std::uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) { return capture(WINRT_IMPL_CoCreateInstance, clsid, outer, context); } diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index b85cb7e61..88fbea065 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -10,12 +10,12 @@ WINRT_EXPORT namespace winrt { struct lock { - constexpr uint32_t operator++() noexcept + constexpr std::uint32_t operator++() noexcept { return 1; } - constexpr uint32_t operator--() noexcept + constexpr std::uint32_t operator--() noexcept { return 0; } diff --git a/strings/base_array.h b/strings/base_array.h index a4f570614..9544dcf8c 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -5,7 +5,7 @@ WINRT_EXPORT namespace winrt struct array_view { using value_type = T; - using size_type = uint32_t; + using size_type = std::uint32_t; using reference = value_type&; using const_reference = value_type const&; using pointer = value_type*; @@ -32,11 +32,11 @@ WINRT_EXPORT namespace winrt {} #ifdef __cpp_lib_span - template + template array_view(std::span span) noexcept : array_view(span.data(), static_cast(span.size())) { - WINRT_ASSERT(span.size() <= UINT_MAX); + WINRT_ASSERT(span.size() <= (std::numeric_limits::max)()); } operator std::span() const noexcept @@ -62,12 +62,12 @@ WINRT_EXPORT namespace winrt { } - template + template array_view(std::array& value) noexcept : array_view(value.data(), static_cast(value.size())) {} - template + template array_view(std::array const& value) noexcept : array_view(value.data(), static_cast(value.size())) {} @@ -231,15 +231,15 @@ WINRT_EXPORT namespace winrt } }; - template array_view(C(&value)[N]) -> array_view; + template array_view(C(&value)[N]) -> array_view; template array_view(std::vector& value) -> array_view; template array_view(std::vector const& value) -> array_view; - template array_view(std::array& value) -> array_view; - template array_view(std::array const& value) -> array_view; + template array_view(std::array& value) -> array_view; + template array_view(std::array const& value) -> array_view; #ifdef __cpp_lib_span - template array_view(std::span& value) -> array_view; - template array_view(std::span const& value) -> array_view; + template array_view(std::span& value) -> array_view; + template array_view(std::span const& value) -> array_view; #endif template @@ -265,7 +265,7 @@ WINRT_EXPORT namespace winrt com_array(count, value_type()) {} - com_array(void* ptr, uint32_t const count, take_ownership_from_abi_t) noexcept : + com_array(void* ptr, std::uint32_t const count, take_ownership_from_abi_t) noexcept : array_view(static_cast(ptr), static_cast(ptr) + count) { } @@ -288,21 +288,21 @@ WINRT_EXPORT namespace winrt com_array(value.begin(), value.end()) {} - template + template explicit com_array(std::array const& value) : com_array(value.begin(), value.end()) {} #ifdef __cpp_lib_span - template + template explicit com_array(std::span span) noexcept : com_array(span.data(), span.data() + span.size()) { - WINRT_ASSERT(span.size() <= UINT_MAX); + WINRT_ASSERT(span.size() <= (std::numeric_limits::max)()); } #endif - template + template explicit com_array(U const(&value)[N]) : com_array(value, value + N) {} @@ -374,17 +374,17 @@ WINRT_EXPORT namespace winrt } } - std::pair> detach_abi() noexcept + std::pair> detach_abi() noexcept { #ifdef _MSC_VER // https://github.com/microsoft/cppwinrt/pull/1165 - std::pair> result; - memset(&result, 0, sizeof(result)); + std::pair> result; + std::memset(&result, 0, sizeof(result)); result.first = this->size(); result.second = *reinterpret_cast*>(this); - memset(this, 0, sizeof(com_array)); + std::memset(this, 0, sizeof(com_array)); #else - std::pair> result(this->size(), *reinterpret_cast*>(this)); + std::pair> result(this->size(), *reinterpret_cast*>(this)); this->m_data = nullptr; this->m_size = 0; #endif @@ -392,19 +392,19 @@ WINRT_EXPORT namespace winrt } template - friend std::pair> detach_abi(com_array& object) noexcept; + friend std::pair> detach_abi(com_array& object) noexcept; }; - template com_array(uint32_t, C const&) -> com_array>; + template com_array(std::uint32_t, C const&) -> com_array>; template ::difference_type>> com_array(InIt, InIt) -> com_array::value_type>>; template com_array(std::vector const&) -> com_array>; - template com_array(std::array const&) -> com_array>; - template com_array(C const(&)[N]) -> com_array>; + template com_array(std::array const&) -> com_array>; + template com_array(C const(&)[N]) -> com_array>; template com_array(std::initializer_list) -> com_array>; #ifdef __cpp_lib_span - template com_array(std::span const& value) -> com_array>; + template com_array(std::span const& value) -> com_array>; #endif @@ -471,7 +471,7 @@ WINRT_EXPORT namespace winrt } template - std::pair> detach_abi(com_array& object) noexcept + std::pair> detach_abi(com_array& object) noexcept { return object.detach_abi(); } @@ -496,10 +496,10 @@ namespace winrt::impl ~array_size_proxy() noexcept { WINRT_ASSERT(m_value.data() || (!m_value.data() && m_size == 0)); - *reinterpret_cast(reinterpret_cast(&m_value) + 1) = m_size; + *reinterpret_cast(reinterpret_cast(&m_value) + 1) = m_size; } - operator uint32_t*() noexcept + operator std::uint32_t*() noexcept { return &m_size; } @@ -512,7 +512,7 @@ namespace winrt::impl private: com_array& m_value; - uint32_t m_size{ 0 }; + std::uint32_t m_size{ 0 }; }; template @@ -524,7 +524,7 @@ namespace winrt::impl template struct com_array_proxy { - com_array_proxy(uint32_t* size, winrt::impl::arg_out* value) noexcept : m_size(size), m_value(value) + com_array_proxy(std::uint32_t* size, winrt::impl::arg_out* value) noexcept : m_size(size), m_value(value) {} ~com_array_proxy() noexcept @@ -545,7 +545,7 @@ namespace winrt::impl private: - uint32_t* m_size; + std::uint32_t* m_size; arg_out* m_value; com_array m_temp; }; @@ -554,7 +554,7 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { template - auto detach_abi(uint32_t* __valueSize, impl::arg_out* value) noexcept + auto detach_abi(std::uint32_t* __valueSize, impl::arg_out* value) noexcept { return impl::com_array_proxy(__valueSize, value); } diff --git a/strings/base_chrono.h b/strings/base_chrono.h index d48cd703b..7934ac5b2 100644 --- a/strings/base_chrono.h +++ b/strings/base_chrono.h @@ -3,17 +3,17 @@ WINRT_EXPORT namespace winrt { struct file_time { - uint64_t value{}; + std::uint64_t value{}; file_time() noexcept = default; - constexpr explicit file_time(uint64_t const value) noexcept : value(value) + constexpr explicit file_time(std::uint64_t const value) noexcept : value(value) { } #ifdef _FILETIME_ constexpr file_time(FILETIME const& value) noexcept - : value(value.dwLowDateTime | (static_cast(value.dwHighDateTime) << 32)) + : value(value.dwLowDateTime | (static_cast(value.dwHighDateTime) << 32)) { } @@ -26,7 +26,7 @@ WINRT_EXPORT namespace winrt struct clock { - using rep = int64_t; + using rep = std::int64_t; using period = impl::filetime_period; using duration = Windows::Foundation::TimeSpan; using time_point = Windows::Foundation::DateTime; @@ -52,7 +52,7 @@ WINRT_EXPORT namespace winrt static file_time to_file_time(time_point const& time) noexcept { - return file_time{ static_cast(time.time_since_epoch().count()) }; + return file_time{ static_cast(time.time_since_epoch().count()) }; } static time_point from_file_time(file_time const& time) noexcept diff --git a/strings/base_collections.h b/strings/base_collections.h index cba0864b3..4e1af51eb 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -101,10 +101,10 @@ namespace winrt::impl private: - uint32_t const m_snapshot; + std::uint32_t const m_snapshot; }; - uint32_t get_version() const noexcept + std::uint32_t get_version() const noexcept { return m_version; } @@ -116,7 +116,7 @@ namespace winrt::impl private: - std::atomic m_version{}; + std::atomic m_version{}; }; template diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index fec3de660..6fe10fa64 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -191,7 +191,7 @@ WINRT_EXPORT namespace winrt return m_current != m_end; } - uint32_t GetMany(array_view values) + std::uint32_t GetMany(array_view values) { [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); @@ -213,15 +213,15 @@ WINRT_EXPORT namespace winrt } } - uint32_t GetMany(array_view values, std::random_access_iterator_tag) + std::uint32_t GetMany(array_view values, std::random_access_iterator_tag) { - uint32_t const actual = (std::min)(static_cast(m_end - m_current), values.size()); + std::uint32_t const actual = (std::min)(static_cast(m_end - m_current), values.size()); m_owner->copy_n(m_current, actual, values.begin()); m_current += actual; return actual; } - uint32_t GetMany(array_view values, std::input_iterator_tag) + std::uint32_t GetMany(array_view values, std::input_iterator_tag) { auto output = values.begin(); @@ -232,7 +232,7 @@ WINRT_EXPORT namespace winrt ++m_current; } - return static_cast(output - values.begin()); + return static_cast(output - values.begin()); } using iterator_type = decltype(std::declval().get_container().begin()); @@ -246,7 +246,7 @@ WINRT_EXPORT namespace winrt template struct vector_view_base : iterable_base { - T GetAt(uint32_t const index) const + T GetAt(std::uint32_t const index) const { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (index >= container_size()) @@ -257,13 +257,13 @@ WINRT_EXPORT namespace winrt return static_cast(*this).unwrap_value(*std::next(static_cast(*this).get_container().begin(), index)); } - uint32_t Size() const noexcept + std::uint32_t Size() const noexcept { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return container_size(); } - bool IndexOf(T const& value, uint32_t& index) const noexcept + bool IndexOf(T const& value, std::uint32_t& index) const noexcept { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto first = std::find_if(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end(), [&](auto&& match) @@ -271,11 +271,11 @@ WINRT_EXPORT namespace winrt return value == static_cast(*this).unwrap_value(match); }); - index = static_cast(first - static_cast(*this).get_container().begin()); + index = static_cast(first - static_cast(*this).get_container().begin()); return index < container_size(); } - uint32_t GetMany(uint32_t const startIndex, array_view values) const + std::uint32_t GetMany(std::uint32_t const startIndex, array_view values) const { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (startIndex >= container_size()) @@ -283,16 +283,16 @@ WINRT_EXPORT namespace winrt return 0; } - uint32_t const actual = (std::min)(container_size() - startIndex, values.size()); + std::uint32_t const actual = (std::min)(container_size() - startIndex, values.size()); this->copy_n(static_cast(*this).get_container().begin() + startIndex, actual, values.begin()); return actual; } private: - uint32_t container_size() const noexcept + std::uint32_t container_size() const noexcept { - return static_cast(std::distance(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end())); + return static_cast(std::distance(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end())); } }; @@ -304,7 +304,7 @@ WINRT_EXPORT namespace winrt return static_cast(*this); } - void SetAt(uint32_t const index, T const& value) + void SetAt(std::uint32_t const index, T const& value) { impl::removed_value::value_type> oldValue; @@ -320,7 +320,7 @@ WINRT_EXPORT namespace winrt pos = static_cast(*this).wrap_value(value); } - void InsertAt(uint32_t const index, T const& value) + void InsertAt(std::uint32_t const index, T const& value) { [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index > static_cast(*this).get_container().size()) @@ -332,7 +332,7 @@ WINRT_EXPORT namespace winrt static_cast(*this).get_container().insert(static_cast(*this).get_container().begin() + index, static_cast(*this).wrap_value(value)); } - void RemoveAt(uint32_t const index) + void RemoveAt(std::uint32_t const index) { impl::removed_value::value_type> removedValue; @@ -425,19 +425,19 @@ WINRT_EXPORT namespace winrt m_changed.remove(cookie); } - void SetAt(uint32_t const index, T const& value) + void SetAt(std::uint32_t const index, T const& value) { vector_base::SetAt(index, value); call_changed(Windows::Foundation::Collections::CollectionChange::ItemChanged, index); } - void InsertAt(uint32_t const index, T const& value) + void InsertAt(std::uint32_t const index, T const& value) { vector_base::InsertAt(index, value); call_changed(Windows::Foundation::Collections::CollectionChange::ItemInserted, index); } - void RemoveAt(uint32_t const index) + void RemoveAt(std::uint32_t const index) { vector_base::RemoveAt(index); call_changed(Windows::Foundation::Collections::CollectionChange::ItemRemoved, index); @@ -469,7 +469,7 @@ WINRT_EXPORT namespace winrt protected: - void call_changed(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) + void call_changed(Windows::Foundation::Collections::CollectionChange const change, std::uint32_t const index) { m_changed(static_cast(*this), make(change, index)); } @@ -480,7 +480,7 @@ WINRT_EXPORT namespace winrt struct args : implements { - args(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) noexcept : + args(Windows::Foundation::Collections::CollectionChange const change, std::uint32_t const index) noexcept : m_change(change), m_index(index) { @@ -491,7 +491,7 @@ WINRT_EXPORT namespace winrt return m_change; } - uint32_t Index() const noexcept + std::uint32_t Index() const noexcept { return m_index; } @@ -499,7 +499,7 @@ WINRT_EXPORT namespace winrt private: Windows::Foundation::Collections::CollectionChange const m_change; - uint32_t const m_index; + std::uint32_t const m_index; }; }; @@ -533,10 +533,10 @@ WINRT_EXPORT namespace winrt return static_cast(*this).unwrap_value(pair->second); } - uint32_t Size() const noexcept + std::uint32_t Size() const noexcept { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); - return static_cast(static_cast(*this).get_container().size()); + return static_cast(static_cast(*this).get_container().size()); } bool HasKey(K const& key) const noexcept diff --git a/strings/base_collections_map.h b/strings/base_collections_map.h index f4bd74baf..fa769fb88 100644 --- a/strings/base_collections_map.h +++ b/strings/base_collections_map.h @@ -120,11 +120,11 @@ namespace std { template struct tuple_size> - : integral_constant + : integral_constant { }; - template + template struct tuple_element> { static_assert(Idx < 2, "key-value pair index out of bounds"); @@ -134,7 +134,7 @@ namespace std namespace winrt::Windows::Foundation::Collections { - template + template std::tuple_element_t> get(IKeyValuePair const& kvp) { static_assert(Idx < 2, "key-value pair index out of bounds"); diff --git a/strings/base_collections_vector.h b/strings/base_collections_vector.h index cef7ef2d3..3e9c1b254 100644 --- a/strings/base_collections_vector.h +++ b/strings/base_collections_vector.h @@ -90,12 +90,12 @@ namespace winrt::impl return result{ this }; } - auto GetAt(uint32_t const index) const + auto GetAt(std::uint32_t const index) const { struct result { base_type const* container; - uint32_t const index; + std::uint32_t const index; operator T() const { @@ -113,7 +113,7 @@ namespace winrt::impl using base_type::IndexOf; - bool IndexOf(Windows::Foundation::IInspectable const& value, uint32_t& index) const + bool IndexOf(Windows::Foundation::IInspectable const& value, std::uint32_t& index) const { if constexpr (is_com_interface_v) { @@ -139,7 +139,7 @@ namespace winrt::impl using base_type::GetMany; - uint32_t GetMany(uint32_t const startIndex, array_view values) const + std::uint32_t GetMany(std::uint32_t const startIndex, array_view values) const { [[maybe_unused]] auto guard = this->acquire_shared(); if (startIndex >= m_values.size()) @@ -147,7 +147,7 @@ namespace winrt::impl return 0; } - uint32_t const actual = (std::min)(static_cast(m_values.size() - startIndex), values.size()); + std::uint32_t const actual = (std::min)(static_cast(m_values.size() - startIndex), values.size()); std::transform(m_values.begin() + startIndex, m_values.begin() + startIndex + actual, values.begin(), [&](auto && value) { @@ -179,14 +179,14 @@ namespace winrt::impl using base_type::SetAt; - void SetAt(uint32_t const index, Windows::Foundation::IInspectable const& value) + void SetAt(std::uint32_t const index, Windows::Foundation::IInspectable const& value) { SetAt(index, unbox_value(value)); } using base_type::InsertAt; - void InsertAt(uint32_t const index, Windows::Foundation::IInspectable const& value) + void InsertAt(std::uint32_t const index, Windows::Foundation::IInspectable const& value) { InsertAt(index, unbox_value(value)); } @@ -268,11 +268,11 @@ namespace winrt::impl return m_current != m_end; } - uint32_t GetMany(array_view values) + std::uint32_t GetMany(array_view values) { [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); - uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); + std::uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); std::transform(m_current, m_current + actual, values.begin(), [&](auto && value) { diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 14a9a0851..27496789a 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -19,19 +19,19 @@ namespace winrt::impl }; template - int32_t capture_to(void**result, F function, Args&& ...args) + std::int32_t capture_to(void**result, F function, Args&& ...args) { return function(args..., guid_of(), capture_decay{ result }); } template || std::is_union_v, int> = 0> - int32_t capture_to(void** result, O* object, M method, Args&& ...args) + std::int32_t capture_to(void** result, O* object, M method, Args&& ...args) { return (object->*method)(args..., guid_of(), capture_decay{ result }); } template - int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args); + std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args); } WINRT_EXPORT namespace winrt @@ -352,7 +352,7 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { template - int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) + std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) { return (object.get()->*(method))(args..., guid_of(), capture_decay{ result }); } diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index a5816a85b..4f1c8d0b6 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -47,7 +47,7 @@ namespace winrt::impl } template - auto wait_for_completed(Async const& async, uint32_t const timeout) + auto wait_for_completed(Async const& async, std::uint32_t const timeout) { struct shared_type { @@ -72,8 +72,8 @@ namespace winrt::impl { check_sta_blocking_wait(); auto const milliseconds = std::chrono::duration_cast(timeout).count(); - WINRT_ASSERT((milliseconds >= 0) && (static_cast(milliseconds) < 0xFFFFFFFFull)); // Within uint32_t range and not INFINITE - return wait_for_completed(async, static_cast(milliseconds)); + WINRT_ASSERT((milliseconds >= 0) && (static_cast(milliseconds) < 0xFFFFFFFFull)); // Within std::uint32_t range and not INFINITE + return wait_for_completed(async, static_cast(milliseconds)); } inline void check_status_canceled(Windows::Foundation::AsyncStatus status) @@ -158,7 +158,7 @@ namespace winrt::impl std::conditional_t async; Windows::Foundation::AsyncStatus status = Windows::Foundation::AsyncStatus::Started; - int32_t failure = 0; + std::int32_t failure = 0; std::atomic suspending = true; void enable_cancellation(cancellable_promise* promise) @@ -405,7 +405,7 @@ namespace winrt::impl unsigned long __stdcall Release() noexcept { - uint32_t const remaining = this->subtract_reference(); + std::uint32_t const remaining = this->subtract_reference(); if (remaining == 0) { @@ -450,7 +450,7 @@ namespace winrt::impl return m_completed; } - uint32_t Id() const noexcept + std::uint32_t Id() const noexcept { return 1; } @@ -597,7 +597,7 @@ namespace winrt::impl bool await_suspend(std::coroutine_handle<>) const noexcept { promise->set_completed(); - uint32_t const remaining = promise->subtract_reference(); + std::uint32_t const remaining = promise->subtract_reference(); if (remaining == 0) { diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index e59fcadb2..6748906ca 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -21,10 +21,10 @@ namespace winrt::impl } #endif - inline std::pair get_apartment_type() noexcept + inline std::pair get_apartment_type() noexcept { - int32_t aptType; - int32_t aptTypeQualifier; + std::int32_t aptType; + std::int32_t aptTypeQualifier; if (0 == WINRT_IMPL_CoGetApartmentType(&aptType, &aptTypeQualifier)) { return { aptType, aptTypeQualifier }; @@ -62,16 +62,16 @@ namespace winrt::impl } com_ptr m_context = try_capture(WINRT_IMPL_CoGetObjectContext); - movable_primitive m_context_type = get_apartment_type().first; + movable_primitive m_context_type = get_apartment_type().first; }; - inline int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept + inline std::int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept { std::coroutine_handle<>::from_address(args->data)(); return 0; }; - [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) { com_callback_args args{}; args.data = handle.address(); @@ -88,11 +88,11 @@ namespace winrt::impl struct threadpool_resume { - threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) : + threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) : m_context(context), m_handle(handle), m_failure(failure) { } com_ptr m_context; std::coroutine_handle<> m_handle; - int32_t* m_failure; + std::int32_t* m_failure; }; inline void __stdcall fallback_submit_threadpool_callback(void*, void* p) noexcept @@ -104,14 +104,14 @@ namespace winrt::impl } } - inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) + inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) { auto state = std::make_unique(context, handle, failure); submit_threadpool_callback(fallback_submit_threadpool_callback, state.get()); state.release(); } - [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, std::int32_t* failure) { WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) @@ -326,7 +326,7 @@ namespace winrt::impl struct apartment_awaiter { apartment_context const& context; - int32_t failure = 0; + std::int32_t failure = 0; bool await_ready() const noexcept { @@ -403,7 +403,7 @@ namespace winrt::impl void create_threadpool_timer() { m_timer.attach(check_pointer(WINRT_IMPL_CreateThreadpoolTimer(callback, this, nullptr))); - int64_t relative_count = -m_duration.count(); + std::int64_t relative_count = -m_duration.count(); WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); state expected = state::idle; @@ -417,7 +417,7 @@ namespace winrt::impl { if (WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), nullptr, 0, 0)) { - int64_t now = 0; + std::int64_t now = 0; WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); } } @@ -513,8 +513,8 @@ namespace winrt::impl void create_threadpool_wait() { m_wait.attach(check_pointer(WINRT_IMPL_CreateThreadpoolWait(callback, this, nullptr))); - int64_t relative_count = -m_timeout.count(); - int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; + std::int64_t relative_count = -m_timeout.count(); + std::int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), m_handle, file_time); state expected = state::idle; @@ -528,12 +528,12 @@ namespace winrt::impl { if (WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), nullptr, nullptr, nullptr)) { - int64_t now = 0; + std::int64_t now = 0; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); } } - static void __stdcall callback(void*, void* context, void*, uint32_t result) noexcept + static void __stdcall callback(void*, void* context, void*, std::uint32_t result) noexcept { auto that = static_cast(context); that->m_result = result; @@ -560,7 +560,7 @@ namespace winrt::impl handle_type m_wait; Windows::Foundation::TimeSpan m_timeout; void* m_handle; - uint32_t m_result{}; + std::uint32_t m_result{}; std::coroutine_handle<> m_resume{ nullptr }; std::atomic m_state{ state::idle }; }; @@ -596,7 +596,7 @@ WINRT_EXPORT namespace winrt m_environment.Pool = m_pool.get(); } - void thread_limits(uint32_t const high, uint32_t const low) + void thread_limits(std::uint32_t const high, std::uint32_t const low) { WINRT_IMPL_SetThreadpoolThreadMaximum(m_pool.get(), high); check_bool(WINRT_IMPL_SetThreadpoolThreadMinimum(m_pool.get(), low)); @@ -643,7 +643,7 @@ WINRT_EXPORT namespace winrt struct environment // TP_CALLBACK_ENVIRON { - uint32_t Version{ 3 }; + std::uint32_t Version{ 3 }; void* Pool{}; void* CleanupGroup{}; void* CleanupGroupCancelCallback{}; @@ -652,16 +652,16 @@ WINRT_EXPORT namespace winrt void* FinalizationCallback{}; union { - uint32_t Flags{}; + std::uint32_t Flags{}; struct { - uint32_t LongFunction : 1; - uint32_t Persistent : 1; - uint32_t Private : 30; + std::uint32_t LongFunction : 1; + std::uint32_t Persistent : 1; + std::uint32_t Private : 30; } s; } u; - int32_t CallbackPriority{ 1 }; - uint32_t Size{ sizeof(environment) }; + std::int32_t CallbackPriority{ 1 }; + std::uint32_t Size{ sizeof(environment) }; }; handle_type m_pool; diff --git a/strings/base_deferral.h b/strings/base_deferral.h index 6976db4a6..cc6f724e5 100644 --- a/strings/base_deferral.h +++ b/strings/base_deferral.h @@ -68,7 +68,7 @@ WINRT_EXPORT namespace winrt } slim_mutex m_lock; - int32_t m_outstanding_deferrals = 0; + std::int32_t m_outstanding_deferrals = 0; std::coroutine_handle<> m_handle = nullptr; }; } diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 3d1457c2e..1cfe58710 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -8,17 +8,17 @@ namespace winrt::impl struct implements_delegate_base { - WINRT_IMPL_NOINLINE uint32_t increment_reference() noexcept + WINRT_IMPL_NOINLINE std::uint32_t increment_reference() noexcept { return ++m_references; } - WINRT_IMPL_NOINLINE uint32_t decrement_reference() noexcept + WINRT_IMPL_NOINLINE std::uint32_t decrement_reference() noexcept { return --m_references; } - WINRT_IMPL_NOINLINE uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept + WINRT_IMPL_NOINLINE std::uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept { if (id == derivedId || is_guid_of(id) || is_guid_of(id)) { @@ -47,17 +47,17 @@ namespace winrt::impl { } - int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final { return query_interface(id, result, static_cast*>(this), guid_of()); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return increment_reference(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = decrement_reference(); @@ -133,17 +133,17 @@ namespace winrt::impl } } - int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final { return query_interface(id, result, static_cast(this), guid_of()); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return increment_reference(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = decrement_reference(); diff --git a/strings/base_error.h b/strings/base_error.h index 41929336b..c58635e5d 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -41,11 +41,11 @@ namespace winrt::impl using bstr_handle = handle_type; - inline hstring trim_hresult_message(wchar_t const* const message, uint32_t size) noexcept + inline hstring trim_hresult_message(wchar_t const* const message, std::uint32_t size) noexcept { wchar_t const* back = message + size - 1; - while (size&& iswspace(*back)) + while (size && std::iswspace(*back)) { --size; --back; @@ -58,7 +58,7 @@ namespace winrt::impl { handle_type message; - uint32_t const size = WINRT_IMPL_FormatMessageW(0x00001300, // FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS + std::uint32_t const size = WINRT_IMPL_FormatMessageW(0x00001300, // FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS nullptr, code, 0x00000400, // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) @@ -69,14 +69,14 @@ namespace winrt::impl return trim_hresult_message(message.get(), size); } - constexpr int32_t hresult_from_win32(uint32_t const x) noexcept + constexpr std::int32_t hresult_from_win32(std::uint32_t const x) noexcept { - return (int32_t)(x) <= 0 ? (int32_t)(x) : (int32_t)(((x) & 0x0000FFFF) | (7 << 16) | 0x80000000); + return (std::int32_t)(x) <= 0 ? (std::int32_t)(x) : (std::int32_t)(((x) & 0x0000FFFF) | (7 << 16) | 0x80000000); } - constexpr int32_t hresult_from_nt(uint32_t const x) noexcept + constexpr std::int32_t hresult_from_nt(std::uint32_t const x) noexcept { - return ((int32_t)((x) | 0x10000000)); + return ((std::int32_t)((x) | 0x10000000)); } } @@ -164,7 +164,7 @@ WINRT_EXPORT namespace winrt { if (m_info) { - int32_t code{}; + std::int32_t code{}; impl::bstr_handle fallback; impl::bstr_handle message; impl::bstr_handle unused; @@ -236,7 +236,7 @@ WINRT_EXPORT namespace winrt #endif impl::bstr_handle m_debug_reference; - uint32_t m_debug_magic{ 0xAABBCCDD }; + std::uint32_t m_debug_magic{ 0xAABBCCDD }; hresult m_code{ impl::error_fail }; com_ptr m_info; @@ -471,7 +471,7 @@ WINRT_EXPORT namespace winrt } catch (...) { - abort(); + std::abort(); } } @@ -532,7 +532,7 @@ WINRT_EXPORT namespace winrt [[noreturn]] inline void terminate() noexcept { WINRT_IMPL_RoFailFastWithErrorContext(to_hresult()); - abort(); + std::abort(); } } diff --git a/strings/base_events.h b/strings/base_events.h index 77952474e..f7e2e6976 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -3,7 +3,7 @@ WINRT_EXPORT namespace winrt { struct event_token { - int64_t value{}; + std::int64_t value{}; explicit operator bool() const noexcept { @@ -22,7 +22,7 @@ WINRT_EXPORT namespace winrt template struct event_revoker { - using method_type = int32_t(__stdcall impl::abi_t::*)(winrt::event_token); + using method_type = std::int32_t(__stdcall impl::abi_t::*)(winrt::event_token); event_revoker() noexcept = default; event_revoker(event_revoker const&) = delete; @@ -77,7 +77,7 @@ WINRT_EXPORT namespace winrt template struct factory_event_revoker { - using method_type = int32_t(__stdcall impl::abi_t::*)(winrt::event_token); + using method_type = std::int32_t(__stdcall impl::abi_t::*)(winrt::event_token); factory_event_revoker() noexcept = default; factory_event_revoker(factory_event_revoker const&) = delete; @@ -267,7 +267,7 @@ namespace winrt::impl using pointer = value_type*; using iterator = value_type*; - explicit event_array(uint32_t const count) noexcept : m_size(count) + explicit event_array(std::uint32_t const count) noexcept : m_size(count) { std::uninitialized_fill_n(data(), count, value_type()); } @@ -306,7 +306,7 @@ namespace winrt::impl return data() + m_size; } - uint32_t size() const noexcept + std::uint32_t size() const noexcept { return m_size; } @@ -324,11 +324,11 @@ namespace winrt::impl } atomic_ref_count m_references{ 1 }; - uint32_t m_size{ 0 }; + std::uint32_t m_size{ 0 }; }; template - com_ptr> make_event_array(uint32_t const capacity) + com_ptr> make_event_array(std::uint32_t const capacity) { void* raw = ::operator new(sizeof(event_array) + (sizeof(T)* capacity)); #ifdef _MSC_VER @@ -339,12 +339,12 @@ namespace winrt::impl WINRT_IMPL_NOINLINE inline bool report_failed_invoke() { - int32_t const code = to_hresult(); + std::int32_t const code = to_hresult(); WINRT_IMPL_RoTransformError(code, 0, nullptr); - if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED - code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) - code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE + if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED + code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) + code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE { return false; } @@ -402,7 +402,7 @@ WINRT_EXPORT namespace winrt return; } - uint32_t available_slots = m_targets->size() - 1; + std::uint32_t available_slots = m_targets->size() - 1; delegate_array new_targets; bool removed = false; @@ -516,7 +516,7 @@ WINRT_EXPORT namespace winrt event_token get_token(delegate_type const& delegate) const noexcept { - return event_token{ reinterpret_cast(WINRT_IMPL_EncodePointer(get_abi(delegate))) }; + return event_token{ reinterpret_cast(WINRT_IMPL_EncodePointer(get_abi(delegate))) }; } using delegate_array = com_ptr>; diff --git a/strings/base_extern.h b/strings/base_extern.h index 2412f9f2c..84e2943c4 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -1,8 +1,8 @@ -__declspec(selectany) int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; +__declspec(selectany) std::int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; __declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; -__declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; -__declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; +__declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(std::uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; +__declspec(selectany) std::int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; #if defined(_MSC_VER) #ifdef _M_HYBRID @@ -24,88 +24,88 @@ __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId extern "C" { - int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12); - int32_t __stdcall WINRT_IMPL_RoGetAgileReference(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16); - int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); - int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); - int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); - int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); - void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); - int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); + std::int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12); + std::int32_t __stdcall WINRT_IMPL_RoGetAgileReference(std::uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, std::uint32_t, std::uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); + std::int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(std::int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); + std::int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(std::int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); + void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(std::int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); + std::int32_t __stdcall WINRT_IMPL_RoTransformError(std::int32_t, std::int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); - void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); - int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); + void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, std::uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); + std::int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8); - int32_t __stdcall WINRT_IMPL_SetErrorInfo(uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8); - int32_t __stdcall WINRT_IMPL_GetErrorInfo(uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); - int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); + std::int32_t __stdcall WINRT_IMPL_SetErrorInfo(std::uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8); + std::int32_t __stdcall WINRT_IMPL_GetErrorInfo(std::uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); + std::int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, std::uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); void __stdcall WINRT_IMPL_CoUninitialize() noexcept WINRT_IMPL_LINK(CoUninitialize, 0); - int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); - int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); - int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetCallContext, 8); - int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetObjectContext, 8); - int32_t __stdcall WINRT_IMPL_CoGetApartmentType(int32_t* type, int32_t* qualifier) noexcept WINRT_IMPL_LINK(CoGetApartmentType, 8); + std::int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); + std::int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, std::uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); + std::int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetCallContext, 8); + std::int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetObjectContext, 8); + std::int32_t __stdcall WINRT_IMPL_CoGetApartmentType(std::int32_t* type, std::int32_t* qualifier) noexcept WINRT_IMPL_LINK(CoGetApartmentType, 8); void* __stdcall WINRT_IMPL_CoTaskMemAlloc(std::size_t size) noexcept WINRT_IMPL_LINK(CoTaskMemAlloc, 4); void __stdcall WINRT_IMPL_CoTaskMemFree(void* ptr) noexcept WINRT_IMPL_LINK(CoTaskMemFree, 4); winrt::impl::bstr __stdcall WINRT_IMPL_SysAllocString(wchar_t const* value) noexcept WINRT_IMPL_LINK(SysAllocString, 4); void __stdcall WINRT_IMPL_SysFreeString(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysFreeString, 4); - uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysStringLen, 4); - int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept WINRT_IMPL_LINK(IIDFromString, 8); - int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(uint32_t codepage, uint32_t flags, char const* in_string, int32_t in_size, wchar_t* out_string, int32_t out_size) noexcept WINRT_IMPL_LINK(MultiByteToWideChar, 24); - int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(uint32_t codepage, uint32_t flags, wchar_t const* int_string, int32_t in_size, char* out_string, int32_t out_size, char const* default_char, int32_t* default_used) noexcept WINRT_IMPL_LINK(WideCharToMultiByte, 32); - void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, uint32_t flags, size_t bytes) noexcept WINRT_IMPL_LINK(HeapAlloc, 12); - int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, uint32_t flags, void* value) noexcept WINRT_IMPL_LINK(HeapFree, 12); + std::uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysStringLen, 4); + std::int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept WINRT_IMPL_LINK(IIDFromString, 8); + std::int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(std::uint32_t codepage, std::uint32_t flags, char const* in_string, std::int32_t in_size, wchar_t* out_string, std::int32_t out_size) noexcept WINRT_IMPL_LINK(MultiByteToWideChar, 24); + std::int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(std::uint32_t codepage, std::uint32_t flags, wchar_t const* int_string, std::int32_t in_size, char* out_string, std::int32_t out_size, char const* default_char, std::int32_t* default_used) noexcept WINRT_IMPL_LINK(WideCharToMultiByte, 32); + void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, std::uint32_t flags, std::size_t bytes) noexcept WINRT_IMPL_LINK(HeapAlloc, 12); + std::int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, std::uint32_t flags, void* value) noexcept WINRT_IMPL_LINK(HeapFree, 12); void* __stdcall WINRT_IMPL_GetProcessHeap() noexcept WINRT_IMPL_LINK(GetProcessHeap, 0); - uint32_t __stdcall WINRT_IMPL_FormatMessageW(uint32_t flags, void const* source, uint32_t code, uint32_t language, wchar_t* buffer, uint32_t size, va_list* arguments) noexcept WINRT_IMPL_LINK(FormatMessageW, 28); - uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept WINRT_IMPL_LINK(GetLastError, 0); + std::uint32_t __stdcall WINRT_IMPL_FormatMessageW(std::uint32_t flags, void const* source, std::uint32_t code, std::uint32_t language, wchar_t* buffer, std::uint32_t size, va_list* arguments) noexcept WINRT_IMPL_LINK(FormatMessageW, 28); + std::uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept WINRT_IMPL_LINK(GetLastError, 0); void __stdcall WINRT_IMPL_GetSystemTimePreciseAsFileTime(void* result) noexcept WINRT_IMPL_LINK(GetSystemTimePreciseAsFileTime, 4); - uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, uintptr_t length) noexcept WINRT_IMPL_LINK(VirtualQuery, 12); + std::uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, std::uintptr_t length) noexcept WINRT_IMPL_LINK(VirtualQuery, 12); void* __stdcall WINRT_IMPL_EncodePointer(void* ptr) noexcept WINRT_IMPL_LINK(EncodePointer, 4); - int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, uint32_t access, void** token) noexcept WINRT_IMPL_LINK(OpenProcessToken, 12); + std::int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, std::uint32_t access, void** token) noexcept WINRT_IMPL_LINK(OpenProcessToken, 12); void* __stdcall WINRT_IMPL_GetCurrentProcess() noexcept WINRT_IMPL_LINK(GetCurrentProcess, 0); - int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, uint32_t level, void** duplicate) noexcept WINRT_IMPL_LINK(DuplicateToken, 12); - int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, uint32_t access, int32_t self, void** token) noexcept WINRT_IMPL_LINK(OpenThreadToken, 16); + std::int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, std::uint32_t level, void** duplicate) noexcept WINRT_IMPL_LINK(DuplicateToken, 12); + std::int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, std::uint32_t access, std::int32_t self, void** token) noexcept WINRT_IMPL_LINK(OpenThreadToken, 16); void* __stdcall WINRT_IMPL_GetCurrentThread() noexcept WINRT_IMPL_LINK(GetCurrentThread, 0); - int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept WINRT_IMPL_LINK(SetThreadToken, 8); + std::int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept WINRT_IMPL_LINK(SetThreadToken, 8); void __stdcall WINRT_IMPL_AcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockExclusive, 4); void __stdcall WINRT_IMPL_AcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockShared, 4); - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4); - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4); + std::uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4); + std::uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4); void __stdcall WINRT_IMPL_ReleaseSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockExclusive, 4); void __stdcall WINRT_IMPL_ReleaseSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockShared, 4); - int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, uint32_t milliseconds, uint32_t flags) noexcept WINRT_IMPL_LINK(SleepConditionVariableSRW, 16); + std::int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, std::uint32_t milliseconds, std::uint32_t flags) noexcept WINRT_IMPL_LINK(SleepConditionVariableSRW, 16); void __stdcall WINRT_IMPL_WakeConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeConditionVariable, 4); void __stdcall WINRT_IMPL_WakeAllConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeAllConditionVariable, 4); void* __stdcall WINRT_IMPL_InterlockedPushEntrySList(void* head, void* entry) noexcept WINRT_IMPL_LINK(InterlockedPushEntrySList, 8); void* __stdcall WINRT_IMPL_InterlockedFlushSList(void* head) noexcept WINRT_IMPL_LINK(InterlockedFlushSList, 4); - void* __stdcall WINRT_IMPL_CreateEventW(void*, int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(CreateEventW, 16); - int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept WINRT_IMPL_LINK(SetEvent, 4); - int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept WINRT_IMPL_LINK(CloseHandle, 4); - uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, uint32_t milliseconds) noexcept WINRT_IMPL_LINK(WaitForSingleObject, 8); + void* __stdcall WINRT_IMPL_CreateEventW(void*, std::int32_t, std::int32_t, void*) noexcept WINRT_IMPL_LINK(CreateEventW, 16); + std::int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept WINRT_IMPL_LINK(SetEvent, 4); + std::int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept WINRT_IMPL_LINK(CloseHandle, 4); + std::uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, std::uint32_t milliseconds) noexcept WINRT_IMPL_LINK(WaitForSingleObject, 8); - int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12); + std::int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12); winrt::impl::ptp_timer __stdcall WINRT_IMPL_CreateThreadpoolTimer(void(__stdcall *callback)(void*, void* context, void*), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolTimer, 12); - void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept WINRT_IMPL_LINK(SetThreadpoolTimer, 16); + void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, std::uint32_t period, std::uint32_t window) noexcept WINRT_IMPL_LINK(SetThreadpoolTimer, 16); void __stdcall WINRT_IMPL_CloseThreadpoolTimer(winrt::impl::ptp_timer timer) noexcept WINRT_IMPL_LINK(CloseThreadpoolTimer, 4); - winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, uint32_t result), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolWait, 12); + winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, std::uint32_t result), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolWait, 12); void __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept WINRT_IMPL_LINK(SetThreadpoolWait, 12); void __stdcall WINRT_IMPL_CloseThreadpoolWait(winrt::impl::ptp_wait wait) noexcept WINRT_IMPL_LINK(CloseThreadpoolWait, 4); - winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolIo, 16); + winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, std::uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolIo, 16); void __stdcall WINRT_IMPL_StartThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(StartThreadpoolIo, 4); void __stdcall WINRT_IMPL_CancelThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CancelThreadpoolIo, 4); void __stdcall WINRT_IMPL_CloseThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CloseThreadpoolIo, 4); winrt::impl::ptp_pool __stdcall WINRT_IMPL_CreateThreadpool(void* reserved) noexcept WINRT_IMPL_LINK(CreateThreadpool, 4); - void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8); - int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8); + void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, std::uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, std::uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8); void __stdcall WINRT_IMPL_CloseThreadpool(winrt::impl::ptp_pool pool) noexcept WINRT_IMPL_LINK(CloseThreadpool, 4); - int32_t __stdcall WINRT_CanUnloadNow() noexcept; - int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; + std::int32_t __stdcall WINRT_CanUnloadNow() noexcept; + std::int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; } #undef WINRT_IMPL_LINK diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 3ca34dba7..dc89fe6ce 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -1,5 +1,7 @@ #include #include +#include +#include #define WINRT_IMPL_STRING_1(expression) #expression #define WINRT_IMPL_STRING(expression) WINRT_IMPL_STRING_1(expression) @@ -36,31 +38,31 @@ namespace winrt::impl { struct guid { - uint32_t Data1; - uint16_t Data2; - uint16_t Data3; - uint8_t Data4[8]; + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; inline bool operator!=(guid const& right) const noexcept { - return memcmp(this, &right, sizeof(guid)); + return std::memcmp(this, &right, sizeof(guid)); } }; struct WINRT_IMPL_FF_NOVTABLE WINRT_IMPL_FF_PUBLIC inspectable { - virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; - virtual uint32_t __stdcall AddRef() noexcept = 0; - virtual uint32_t __stdcall Release() noexcept = 0; - virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; - virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; - virtual int32_t __stdcall GetTrustLevel(uint32_t* level) noexcept = 0; + virtual std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; + virtual std::uint32_t __stdcall AddRef() noexcept = 0; + virtual std::uint32_t __stdcall Release() noexcept = 0; + virtual std::int32_t __stdcall GetIids(std::uint32_t* count, guid** ids) noexcept = 0; + virtual std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; + virtual std::int32_t __stdcall GetTrustLevel(std::uint32_t* level) noexcept = 0; }; void* const* m_vfptr; inspectable* m_owner; std::size_t m_offset; guid m_iid; - std::atomic m_references{ 1 }; + std::atomic m_references{ 1 }; fast_abi_forwarder(void* owner, guid const& iid, std::size_t offset) noexcept : m_vfptr(s_vtable), m_owner(static_cast(owner)), m_offset(offset), m_iid(iid) @@ -73,7 +75,7 @@ namespace winrt::impl m_owner->Release(); } - static int32_t __stdcall QueryInterface(fast_abi_forwarder* self, guid const& iid, void** object) noexcept + static std::int32_t __stdcall QueryInterface(fast_abi_forwarder* self, guid const& iid, void** object) noexcept { if (iid != self->m_iid) { @@ -85,14 +87,14 @@ namespace winrt::impl } // Note: COM interfaces use stdcall, not thiscall, ('this' gets no special treatment), permitting static implementations - static uint32_t __stdcall AddRef(fast_abi_forwarder* self) noexcept + static std::uint32_t __stdcall AddRef(fast_abi_forwarder* self) noexcept { return 1 + self->m_references.fetch_add(1, std::memory_order_relaxed); } - static uint32_t __stdcall Release(fast_abi_forwarder* self) noexcept + static std::uint32_t __stdcall Release(fast_abi_forwarder* self) noexcept { - uint32_t const remaining = self->m_references.fetch_sub(1, std::memory_order_release) - 1; + std::uint32_t const remaining = self->m_references.fetch_sub(1, std::memory_order_release) - 1; if (remaining == 0) { std::atomic_thread_fence(std::memory_order_acquire); @@ -101,17 +103,17 @@ namespace winrt::impl return remaining; } - static uint32_t __stdcall GetIids(fast_abi_forwarder* self, uint32_t* count, guid** iids) noexcept + static std::uint32_t __stdcall GetIids(fast_abi_forwarder* self, std::uint32_t* count, guid** iids) noexcept { return self->m_owner->GetIids(count, iids); } - static uint32_t __stdcall GetRuntimeClassName(fast_abi_forwarder* self, void** name) noexcept + static std::uint32_t __stdcall GetRuntimeClassName(fast_abi_forwarder* self, void** name) noexcept { return self->m_owner->GetRuntimeClassName(name); } - static uint32_t __stdcall GetTrustLevel(fast_abi_forwarder* self, uint32_t* level) noexcept + static std::uint32_t __stdcall GetTrustLevel(fast_abi_forwarder* self, std::uint32_t* level) noexcept { return self->m_owner->GetTrustLevel(level); } @@ -144,7 +146,7 @@ namespace winrt::impl namespace winrt { template - auto make_fast_abi_forwarder(void* owner, TGuid const& guid, size_t offset) + auto make_fast_abi_forwarder(void* owner, TGuid const& guid, std::size_t offset) { using ff_guid = impl::fast_abi_forwarder::guid; static_assert(sizeof(ff_guid) == sizeof(TGuid)); diff --git a/strings/base_identity.h b/strings/base_identity.h index 0f4a163b6..30830bc5a 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -19,31 +19,31 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { - template + template constexpr std::array to_array(T const* value, std::index_sequence const) noexcept { return { value[Index]... }; } - template + template constexpr auto to_array(std::array const& value) noexcept { return value; } - template + template constexpr auto to_array(char const(&value)[Size]) noexcept { return to_array(value, std::make_index_sequence()); } - template + template constexpr auto to_array(wchar_t const(&value)[Size]) noexcept { return to_array(value, std::make_index_sequence()); } - template + template constexpr std::array concat( [[maybe_unused]] std::array const& left, [[maybe_unused]] std::array const& right, @@ -53,31 +53,31 @@ namespace winrt::impl return { left[LeftIndex]..., right[RightIndex]... }; } - template + template constexpr auto concat(std::array const& left, std::array const& right) noexcept { return concat(left, right, std::make_index_sequence(), std::make_index_sequence()); } - template + template constexpr auto concat(std::array const& left, T const(&right)[RightSize]) noexcept { return concat(left, to_array(right)); } - template + template constexpr auto concat(T const(&left)[LeftSize], std::array const& right) noexcept { return concat(to_array(left), right); } - template + template constexpr auto concat(std::array const& left, T const right) noexcept { return concat(left, std::array{right}); } - template + template constexpr auto concat(T const left, std::array const& right) noexcept { return concat(std::array{left}, right); @@ -96,31 +96,31 @@ namespace winrt::impl } } - template + template constexpr std::array zconcat_base(std::array const& left, std::array const& right, std::index_sequence const, std::index_sequence const) noexcept { return { left[LI]..., right[RI]..., T{} }; } - template + template constexpr auto zconcat(std::array const& left, std::array const& right) noexcept { return zconcat_base(left, right, std::make_index_sequence(), std::make_index_sequence()); } - template + template constexpr std::array to_zarray_base(T const(&value)[S], std::index_sequence const) noexcept { return { value[I]... }; } - template + template constexpr auto to_zarray(T const(&value)[S]) noexcept { return to_zarray_base(value, std::make_index_sequence()); } - template + template constexpr auto to_zarray(std::array const& value) noexcept { return value; @@ -139,43 +139,43 @@ namespace winrt::impl } } - constexpr std::array to_array(uint32_t value) noexcept + constexpr std::array to_array(std::uint32_t value) noexcept { - return { static_cast(value & 0x000000ff), static_cast((value & 0x0000ff00) >> 8), static_cast((value & 0x00ff0000) >> 16), static_cast((value & 0xff000000) >> 24) }; + return { static_cast(value & 0x000000ff), static_cast((value & 0x0000ff00) >> 8), static_cast((value & 0x00ff0000) >> 16), static_cast((value & 0xff000000) >> 24) }; } - constexpr std::array to_array(uint16_t value) noexcept + constexpr std::array to_array(std::uint16_t value) noexcept { - return { static_cast(value & 0x00ff), static_cast((value & 0xff00) >> 8) }; + return { static_cast(value & 0x00ff), static_cast((value & 0xff00) >> 8) }; } constexpr auto to_array(guid const& value) noexcept { return combine(to_array(value.Data1), to_array(value.Data2), to_array(value.Data3), - std::array{ value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7] }); + std::array{ value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7] }); } template - constexpr T to_hex_digit(uint8_t value) noexcept + constexpr T to_hex_digit(std::uint8_t value) noexcept { value &= 0xF; return value < 10 ? static_cast('0') + value : static_cast('a') + (value - 10); } template - constexpr std::array uint8_to_hex(uint8_t const value) noexcept + constexpr std::array uint8_to_hex(std::uint8_t const value) noexcept { return { to_hex_digit(value >> 4), to_hex_digit(value & 0xF) }; } template - constexpr auto uint16_to_hex(uint16_t value) noexcept + constexpr auto uint16_to_hex(std::uint16_t value) noexcept { - return combine(uint8_to_hex(static_cast(value >> 8)), uint8_to_hex(value & 0xFF)); + return combine(uint8_to_hex(static_cast(value >> 8)), uint8_to_hex(value & 0xFF)); } template - constexpr auto uint32_to_hex(uint32_t const value) noexcept + constexpr auto uint32_to_hex(std::uint32_t const value) noexcept { return combine(uint16_to_hex(value >> 16), uint16_to_hex(value & 0xFFFF)); } @@ -197,18 +197,18 @@ namespace winrt::impl ); } - constexpr uint32_t to_guid(uint8_t a, uint8_t b, uint8_t c, uint8_t d) noexcept + constexpr std::uint32_t to_guid(std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) noexcept { - return (static_cast(d) << 24) | (static_cast(c) << 16) | (static_cast(b) << 8) | static_cast(a); + return (static_cast(d) << 24) | (static_cast(c) << 16) | (static_cast(b) << 8) | static_cast(a); } - constexpr uint16_t to_guid(uint8_t a, uint8_t b) noexcept + constexpr std::uint16_t to_guid(std::uint8_t a, std::uint8_t b) noexcept { - return (static_cast(b) << 8) | static_cast(a); + return (static_cast(b) << 8) | static_cast(a); } - template - constexpr guid to_guid(std::array const& arr) noexcept + template + constexpr guid to_guid(std::array const& arr) noexcept { return { @@ -219,12 +219,12 @@ namespace winrt::impl }; } - constexpr uint32_t endian_swap(uint32_t value) noexcept + constexpr std::uint32_t endian_swap(std::uint32_t value) noexcept { return (value & 0xFF000000) >> 24 | (value & 0x00FF0000) >> 8 | (value & 0x0000FF00) << 8 | (value & 0x000000FF) << 24; } - constexpr uint16_t endian_swap(uint16_t value) noexcept + constexpr std::uint16_t endian_swap(std::uint16_t value) noexcept { return (value & 0xFF00) >> 8 | (value & 0x00FF) << 8; } @@ -239,51 +239,51 @@ namespace winrt::impl constexpr guid set_named_guid_fields(guid value) noexcept { - value.Data3 = static_cast((value.Data3 & 0x0fff) | (5 << 12)); - value.Data4[0] = static_cast((value.Data4[0] & 0x3f) | 0x80); + value.Data3 = static_cast((value.Data3 & 0x0fff) | (5 << 12)); + value.Data4[0] = static_cast((value.Data4[0] & 0x3f) | 0x80); return value; } - template - constexpr std::array char_to_byte_array(std::array const& value, std::index_sequence const) noexcept + template + constexpr std::array char_to_byte_array(std::array const& value, std::index_sequence const) noexcept { - return { static_cast(value[Index])... }; + return { static_cast(value[Index])... }; } - constexpr auto sha1_rotl(uint8_t bits, uint32_t word) noexcept + constexpr auto sha1_rotl(std::uint8_t bits, std::uint32_t word) noexcept { return (word << bits) | (word >> (32 - bits)); } - constexpr auto sha_ch(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_ch(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return (x & y) ^ ((~x) & z); } - constexpr auto sha_parity(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_parity(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return x ^ y ^ z; } - constexpr auto sha_maj(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_maj(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return (x & y) ^ (x & z) ^ (y & z); } - constexpr std::array process_msg_block(uint8_t const* input, size_t start_pos, std::array const& intermediate_hash) noexcept + constexpr std::array process_msg_block(std::uint8_t const* input, std::size_t start_pos, std::array const& intermediate_hash) noexcept { - uint32_t const K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; - std::array W = {}; + std::uint32_t const K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; + std::array W = {}; - size_t t = 0; - uint32_t temp = 0; + std::size_t t = 0; + std::uint32_t temp = 0; for (t = 0; t < 16; t++) { - W[t] = static_cast(input[start_pos + t * 4]) << 24; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 1]) << 16; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 2]) << 8; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 3]); + W[t] = static_cast(input[start_pos + t * 4]) << 24; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 1]) << 16; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 2]) << 8; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 3]); } for (t = 16; t < 80; t++) @@ -291,11 +291,11 @@ namespace winrt::impl W[t] = sha1_rotl(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); } - uint32_t A = intermediate_hash[0]; - uint32_t B = intermediate_hash[1]; - uint32_t C = intermediate_hash[2]; - uint32_t D = intermediate_hash[3]; - uint32_t E = intermediate_hash[4]; + std::uint32_t A = intermediate_hash[0]; + std::uint32_t B = intermediate_hash[1]; + std::uint32_t C = intermediate_hash[2]; + std::uint32_t D = intermediate_hash[3]; + std::uint32_t E = intermediate_hash[4]; for (t = 0; t < 20; t++) { @@ -340,54 +340,54 @@ namespace winrt::impl return { intermediate_hash[0] + A, intermediate_hash[1] + B, intermediate_hash[2] + C, intermediate_hash[3] + D, intermediate_hash[4] + E }; } - template - constexpr std::array process_msg_block(std::array const& input, size_t start_pos, std::array const& intermediate_hash) noexcept + template + constexpr std::array process_msg_block(std::array const& input, std::size_t start_pos, std::array const& intermediate_hash) noexcept { return process_msg_block(input.data(), start_pos, intermediate_hash); } - constexpr std::array size_to_bytes(size_t size) noexcept + constexpr std::array size_to_bytes(std::size_t size) noexcept { return { - static_cast((size & 0xff00000000000000) >> 56), - static_cast((size & 0x00ff000000000000) >> 48), - static_cast((size & 0x0000ff0000000000) >> 40), - static_cast((size & 0x000000ff00000000) >> 32), - static_cast((size & 0x00000000ff000000) >> 24), - static_cast((size & 0x0000000000ff0000) >> 16), - static_cast((size & 0x000000000000ff00) >> 8), - static_cast((size & 0x00000000000000ff) >> 0) + static_cast((size & 0xff00000000000000) >> 56), + static_cast((size & 0x00ff000000000000) >> 48), + static_cast((size & 0x0000ff0000000000) >> 40), + static_cast((size & 0x000000ff00000000) >> 32), + static_cast((size & 0x00000000ff000000) >> 24), + static_cast((size & 0x0000000000ff0000) >> 16), + static_cast((size & 0x000000000000ff00) >> 8), + static_cast((size & 0x00000000000000ff) >> 0) }; } - template - constexpr std::array make_remaining([[maybe_unused]] std::array const& input, [[maybe_unused]] size_t start_pos, std::index_sequence) noexcept + template + constexpr std::array make_remaining([[maybe_unused]] std::array const& input, [[maybe_unused]] std::size_t start_pos, std::index_sequence) noexcept { return { input[Index + start_pos]..., 0x80 }; } - template - constexpr auto make_remaining(std::array const& input, size_t start_pos) noexcept + template + constexpr auto make_remaining(std::array const& input, std::size_t start_pos) noexcept { constexpr auto remaining_size = Size % 64; return make_remaining(input, start_pos, std::make_index_sequence()); } - template - constexpr auto make_buffer(std::array const& remaining_buffer) noexcept + template + constexpr auto make_buffer(std::array const& remaining_buffer) noexcept { constexpr auto message_length = (RemainderSize + 8 <= 64) ? 64 : 64 * 2; constexpr auto padding_length = message_length - RemainderSize - 8; - auto padding_buffer = std::array{}; + auto padding_buffer = std::array{}; auto length_buffer = size_to_bytes(InputSize * 8); return combine(remaining_buffer, padding_buffer, length_buffer); } - template - constexpr std::array finalize_remaining_buffer(std::array const& input, std::array const& intermediate_hash) noexcept + template + constexpr std::array finalize_remaining_buffer(std::array const& input, std::array const& intermediate_hash) noexcept { if constexpr (Size == 64) { @@ -399,22 +399,22 @@ namespace winrt::impl } } - template - constexpr std::array get_result(std::array const& intermediate_hash, std::index_sequence) noexcept + template + constexpr std::array get_result(std::array const& intermediate_hash, std::index_sequence) noexcept { - return { static_cast(intermediate_hash[Index >> 2] >> (8 * (3 - (Index & 0x03))))... }; + return { static_cast(intermediate_hash[Index >> 2] >> (8 * (3 - (Index & 0x03))))... }; } - constexpr auto get_result(std::array const& intermediate_hash) noexcept + constexpr auto get_result(std::array const& intermediate_hash) noexcept { return get_result(intermediate_hash, std::make_index_sequence<20>{}); } - template - constexpr auto calculate_sha1(std::array const& input) noexcept + template + constexpr auto calculate_sha1(std::array const& input) noexcept { - std::array intermediate_hash{ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; - size_t i = 0; + std::array intermediate_hash{ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; + std::size_t i = 0; while (i + 64 <= Size) { @@ -426,7 +426,7 @@ namespace winrt::impl return get_result(intermediate_hash); } - template + template constexpr guid generate_guid(std::array const& value) noexcept { guid namespace_guid = { 0xd57af411, 0x737b, 0xc042,{ 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee } }; @@ -472,7 +472,7 @@ namespace winrt::impl ) }; - constexpr size_t to_utf8_size(wchar_t const value) noexcept + constexpr std::size_t to_utf8_size(wchar_t const value) noexcept { if (value <= 0x7F) { @@ -487,7 +487,7 @@ namespace winrt::impl return 3; } - constexpr size_t to_utf8(wchar_t const value, char* buffer) noexcept + constexpr std::size_t to_utf8(wchar_t const value, char* buffer) noexcept { if (value <= 0x7F) { @@ -509,10 +509,10 @@ namespace winrt::impl } template - constexpr size_t to_utf8_size() noexcept + constexpr std::size_t to_utf8_size() noexcept { auto input = to_array(name_v); - size_t length = 0; + std::size_t length = 0; for (wchar_t const element : input) { @@ -527,7 +527,7 @@ namespace winrt::impl { auto input = to_array(name_v); std::array()> output{}; - size_t offset{}; + std::size_t offset{}; for (wchar_t const element : input) { @@ -544,14 +544,14 @@ namespace winrt::impl constexpr auto& basic_signature_v = ""; template <> inline constexpr auto& basic_signature_v = "b1"; - template <> inline constexpr auto& basic_signature_v = "i1"; - template <> inline constexpr auto& basic_signature_v = "i2"; - template <> inline constexpr auto& basic_signature_v = "i4"; - template <> inline constexpr auto& basic_signature_v = "i8"; - template <> inline constexpr auto& basic_signature_v = "u1"; - template <> inline constexpr auto& basic_signature_v = "u2"; - template <> inline constexpr auto& basic_signature_v = "u4"; - template <> inline constexpr auto& basic_signature_v = "u8"; + template <> inline constexpr auto& basic_signature_v = "i1"; + template <> inline constexpr auto& basic_signature_v = "i2"; + template <> inline constexpr auto& basic_signature_v = "i4"; + template <> inline constexpr auto& basic_signature_v = "i8"; + template <> inline constexpr auto& basic_signature_v = "u1"; + template <> inline constexpr auto& basic_signature_v = "u2"; + template <> inline constexpr auto& basic_signature_v = "u4"; + template <> inline constexpr auto& basic_signature_v = "u8"; template <> inline constexpr auto& basic_signature_v = "f4"; template <> inline constexpr auto& basic_signature_v = "f8"; template <> inline constexpr auto& basic_signature_v = "c2"; @@ -560,14 +560,14 @@ namespace winrt::impl template <> inline constexpr auto& basic_signature_v = "cinterface(IInspectable)"; template <> inline constexpr auto& name_v = L"Boolean"; - template <> inline constexpr auto& name_v = L"Int8"; - template <> inline constexpr auto& name_v = L"Int16"; - template <> inline constexpr auto& name_v = L"Int32"; - template <> inline constexpr auto& name_v = L"Int64"; - template <> inline constexpr auto& name_v = L"UInt8"; - template <> inline constexpr auto& name_v = L"UInt16"; - template <> inline constexpr auto& name_v = L"UInt32"; - template <> inline constexpr auto& name_v = L"UInt64"; + template <> inline constexpr auto& name_v = L"Int8"; + template <> inline constexpr auto& name_v = L"Int16"; + template <> inline constexpr auto& name_v = L"Int32"; + template <> inline constexpr auto& name_v = L"Int64"; + template <> inline constexpr auto& name_v = L"UInt8"; + template <> inline constexpr auto& name_v = L"UInt16"; + template <> inline constexpr auto& name_v = L"UInt32"; + template <> inline constexpr auto& name_v = L"UInt64"; template <> inline constexpr auto& name_v = L"Single"; template <> inline constexpr auto& name_v = L"Double"; template <> inline constexpr auto& name_v = L"Char16"; @@ -581,23 +581,23 @@ namespace winrt::impl template <> inline constexpr auto& name_v = L"IAgileObject"; template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; - template <> struct category { using type = struct_category; }; - template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; template <> struct category { using type = basic_category; }; - template <> struct category { using type = struct_category; }; - template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; template struct category_signature @@ -642,13 +642,13 @@ namespace winrt::impl constexpr static auto data{ combine("delegate(", to_array(guid_of()), ")") }; }; - template + template constexpr std::wstring_view to_wstring_view(std::array const& value) noexcept { return { value.data(), Size - 1 }; } - template + template constexpr std::wstring_view to_wstring_view(wchar_t const (&value)[Size]) noexcept { return { value, Size - 1 }; diff --git a/strings/base_implements.h b/strings/base_implements.h index b943c1d96..7edf32149 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -216,11 +216,11 @@ namespace winrt::impl } template - void zero_abi([[maybe_unused]] void* ptr, [[maybe_unused]] uint32_t const capacity) noexcept + void zero_abi([[maybe_unused]] void* ptr, [[maybe_unused]] std::uint32_t const capacity) noexcept { if constexpr (!std::is_trivially_destructible_v) { - memset(ptr, 0, sizeof(T) * capacity); + std::memset(ptr, 0, sizeof(T) * capacity); } } @@ -229,7 +229,7 @@ namespace winrt::impl { if constexpr (!std::is_trivially_destructible_v) { - memset(ptr, 0, sizeof(T)); + std::memset(ptr, 0, sizeof(T)); } } } @@ -522,32 +522,32 @@ namespace winrt::impl return*static_cast(reinterpret_cast*>(this)); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept override + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept override { return shim().QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept override + std::uint32_t __stdcall AddRef() noexcept override { return shim().AddRef(); } - uint32_t __stdcall Release() noexcept override + std::uint32_t __stdcall Release() noexcept override { return shim().Release(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept override + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept override { return shim().GetIids(reinterpret_cast(count), reinterpret_cast(array)); } - int32_t __stdcall GetRuntimeClassName(void** name) noexcept override + std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept override { return shim().abi_GetRuntimeClassName(name); } - int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept final + std::int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept final { return shim().abi_GetTrustLevel(trustLevel); } @@ -579,27 +579,27 @@ namespace winrt::impl template struct produce : produce_base { - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { return this->shim().NonDelegatingQueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return this->shim().NonDelegatingAddRef(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { return this->shim().NonDelegatingRelease(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept final + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept final { return this->shim().NonDelegatingGetIids(count, array); } - int32_t __stdcall GetRuntimeClassName(void** name) noexcept final + std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept final { return this->shim().NonDelegatingGetRuntimeClassName(name); } @@ -619,7 +619,7 @@ namespace winrt::impl return static_cast*>(reinterpret_cast*>(this)); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id)) { @@ -631,17 +631,17 @@ namespace winrt::impl return that()->m_object->QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return that()->increment_strong(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { return that()->m_object->Release(); } - int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept final + std::int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept final { *weakReference = that(); that()->AddRef(); @@ -659,14 +659,14 @@ namespace winrt::impl template struct weak_ref final : IWeakReference, weak_source_producer { - weak_ref(unknown_abi* object, uint32_t const strong) noexcept : + weak_ref(unknown_abi* object, std::uint32_t const strong) noexcept : m_object(object), m_strong(strong) { WINRT_ASSERT(object); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id) || is_guid_of(id)) { @@ -694,14 +694,14 @@ namespace winrt::impl return error_no_interface; } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return 1 + m_weak.fetch_add(1, std::memory_order_relaxed); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { - uint32_t const target = m_weak.fetch_sub(1, std::memory_order_relaxed) - 1; + std::uint32_t const target = m_weak.fetch_sub(1, std::memory_order_relaxed) - 1; if (target == 0) { @@ -711,9 +711,9 @@ namespace winrt::impl return target; } - int32_t __stdcall Resolve(guid const& id, void** objectReference) noexcept final + std::int32_t __stdcall Resolve(guid const& id, void** objectReference) noexcept final { - uint32_t target = m_strong.load(std::memory_order_relaxed); + std::uint32_t target = m_strong.load(std::memory_order_relaxed); while (true) { @@ -725,26 +725,26 @@ namespace winrt::impl if (m_strong.compare_exchange_weak(target, target + 1, std::memory_order_acquire, std::memory_order_relaxed)) { - int32_t hr = m_object->QueryInterface(id, objectReference); + std::int32_t hr = m_object->QueryInterface(id, objectReference); m_strong.fetch_sub(1, std::memory_order_relaxed); return hr; } } } - void set_strong(uint32_t const count) noexcept + void set_strong(std::uint32_t const count) noexcept { m_strong = count; } - uint32_t increment_strong() noexcept + std::uint32_t increment_strong() noexcept { return 1 + m_strong.fetch_add(1, std::memory_order_relaxed); } - uint32_t decrement_strong() noexcept + std::uint32_t decrement_strong() noexcept { - uint32_t const target = m_strong.fetch_sub(1, std::memory_order_release) - 1; + std::uint32_t const target = m_strong.fetch_sub(1, std::memory_order_release) - 1; if (target == 0) { @@ -767,8 +767,8 @@ namespace winrt::impl static_assert(sizeof(weak_source_producer) == sizeof(weak_source)); unknown_abi* m_object{}; - std::atomic m_strong{ 1 }; - std::atomic m_weak{ 1 }; + std::atomic m_strong{ 1 }; + std::atomic m_weak{ 1 }; }; template @@ -842,14 +842,14 @@ namespace winrt::impl using IInspectable = Windows::Foundation::IInspectable; using root_implements_type = root_implements; - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept { if (this->outer()) { return this->outer()->QueryInterface(id, object); } - int32_t result = query_interface(id, object); + std::int32_t result = query_interface(id, object); if (result == error_no_interface && this->m_inner) { @@ -859,7 +859,7 @@ namespace winrt::impl return result; } - uint32_t __stdcall AddRef() noexcept + std::uint32_t __stdcall AddRef() noexcept { if (this->outer()) { @@ -869,7 +869,7 @@ namespace winrt::impl return NonDelegatingAddRef(); } - uint32_t __stdcall Release() noexcept + std::uint32_t __stdcall Release() noexcept { if (this->outer()) { @@ -907,7 +907,7 @@ namespace winrt::impl protected: - virtual int32_t query_interface_tearoff(guid const&, void**) const noexcept + virtual std::int32_t query_interface_tearoff(guid const&, void**) const noexcept { return error_no_interface; } @@ -922,7 +922,7 @@ namespace winrt::impl subtract_final_reference(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept { if (this->outer()) { @@ -932,7 +932,7 @@ namespace winrt::impl return NonDelegatingGetIids(count, array); } - int32_t __stdcall abi_GetRuntimeClassName(void** name) noexcept + std::int32_t __stdcall abi_GetRuntimeClassName(void** name) noexcept { if (this->outer()) { @@ -942,7 +942,7 @@ namespace winrt::impl return NonDelegatingGetRuntimeClassName(name); } - int32_t __stdcall abi_GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept + std::int32_t __stdcall abi_GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept { if (this->outer()) { @@ -952,11 +952,11 @@ namespace winrt::impl return NonDelegatingGetTrustLevel(trustLevel); } - uint32_t __stdcall NonDelegatingAddRef() noexcept + std::uint32_t __stdcall NonDelegatingAddRef() noexcept { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); while (true) { @@ -965,11 +965,11 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->increment_strong(); } - uintptr_t const target = count_or_pointer + 1; + std::uintptr_t const target = count_or_pointer + 1; if (m_references.compare_exchange_weak(count_or_pointer, target, std::memory_order_relaxed)) { - return static_cast(target); + return static_cast(target); } } } @@ -979,9 +979,9 @@ namespace winrt::impl } } - uint32_t __stdcall NonDelegatingRelease() noexcept + std::uint32_t __stdcall NonDelegatingRelease() noexcept { - uint32_t const target = subtract_reference(); + std::uint32_t const target = subtract_reference(); if (target == 0) { @@ -998,7 +998,7 @@ namespace winrt::impl return target; } - int32_t __stdcall NonDelegatingQueryInterface(guid const& id, void** object) noexcept + std::int32_t __stdcall NonDelegatingQueryInterface(guid const& id, void** object) noexcept { if (is_guid_of(id) || is_guid_of(id)) { @@ -1008,7 +1008,7 @@ namespace winrt::impl return 0; } - int32_t result = query_interface(id, object); + std::int32_t result = query_interface(id, object); if (result == error_no_interface && this->m_inner) { @@ -1018,10 +1018,10 @@ namespace winrt::impl return result; } - int32_t __stdcall NonDelegatingGetIids(uint32_t* count, guid** array) noexcept + std::int32_t __stdcall NonDelegatingGetIids(std::uint32_t* count, guid** array) noexcept { auto const& local_iids = static_cast(this)->get_local_iids(); - uint32_t const& local_count = local_iids.first; + std::uint32_t const& local_count = local_iids.first; if constexpr (root_implements_type::is_composing) { if (local_count > 0) @@ -1062,25 +1062,25 @@ namespace winrt::impl return 0; } - int32_t __stdcall NonDelegatingGetRuntimeClassName(void** name) noexcept try + std::int32_t __stdcall NonDelegatingGetRuntimeClassName(void** name) noexcept try { *name = detach_abi(static_cast(this)->GetRuntimeClassName()); return 0; } catch (...) { return to_hresult(); } - int32_t __stdcall NonDelegatingGetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept try + std::int32_t __stdcall NonDelegatingGetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept try { *trustLevel = static_cast(this)->GetTrustLevel(); return 0; } catch (...) { return to_hresult(); } - uint32_t subtract_final_reference() noexcept + std::uint32_t subtract_final_reference() noexcept { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); while (true) { @@ -1089,11 +1089,11 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->decrement_strong(); } - uintptr_t const target = count_or_pointer - 1; + std::uintptr_t const target = count_or_pointer - 1; if (m_references.compare_exchange_weak(count_or_pointer, target, std::memory_order_release, std::memory_order_relaxed)) { - return static_cast(target); + return static_cast(target); } } } @@ -1103,9 +1103,9 @@ namespace winrt::impl } } - uint32_t subtract_reference() noexcept + std::uint32_t subtract_reference() noexcept { - uint32_t result = subtract_final_reference(); + std::uint32_t result = subtract_final_reference(); if (result == 0) { @@ -1155,9 +1155,9 @@ namespace winrt::impl using use_module_lock = std::negation...>>; using weak_ref_t = impl::weak_ref; - std::atomic> m_references{ 1 }; + std::atomic> m_references{ 1 }; - int32_t query_interface(guid const& id, void** object) noexcept + std::int32_t query_interface(guid const& id, void** object) noexcept { *object = static_cast(this)->find_interface(id); @@ -1170,7 +1170,7 @@ namespace winrt::impl return query_interface_common(id, object); } - WINRT_IMPL_NOINLINE int32_t query_interface_common(guid const& id, void** object) noexcept + WINRT_IMPL_NOINLINE std::int32_t query_interface_common(guid const& id, void** object) noexcept { if (is_guid_of(id)) { @@ -1220,21 +1220,21 @@ namespace winrt::impl { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); if (is_weak_ref(count_or_pointer)) { return decode_weak_ref(count_or_pointer)->get_source(); } - com_ptr weak_ref(new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)), take_ownership_from_abi); + com_ptr weak_ref(new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)), take_ownership_from_abi); if (!weak_ref) { return nullptr; } - uintptr_t const encoding = encode_weak_ref(weak_ref.get()); + std::uintptr_t const encoding = encode_weak_ref(weak_ref.get()); while (true) { @@ -1250,7 +1250,7 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->get_source(); } - weak_ref->set_strong(static_cast(count_or_pointer)); + weak_ref->set_strong(static_cast(count_or_pointer)); } } else @@ -1260,28 +1260,28 @@ namespace winrt::impl } } - static bool is_weak_ref(intptr_t const value) noexcept + static bool is_weak_ref(std::intptr_t const value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return value < 0; } - static weak_ref_t* decode_weak_ref(uintptr_t const value) noexcept + static weak_ref_t* decode_weak_ref(std::uintptr_t const value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return reinterpret_cast(value << 1); } - static uintptr_t encode_weak_ref(weak_ref_t* value) noexcept + static std::uintptr_t encode_weak_ref(weak_ref_t* value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); - constexpr uintptr_t pointer_flag = static_cast(1) << ((sizeof(uintptr_t) * 8) - 1); - WINRT_ASSERT((reinterpret_cast(value) & 1) == 0); - return (reinterpret_cast(value) >> 1) | pointer_flag; + constexpr std::uintptr_t pointer_flag = static_cast(1) << ((sizeof(std::uintptr_t) * 8) - 1); + WINRT_ASSERT((reinterpret_cast(value) & 1) == 0); + return (reinterpret_cast(value) >> 1) | pointer_flag; } virtual unknown_abi* get_unknown() const noexcept = 0; - virtual std::pair get_local_iids() const noexcept = 0; + virtual std::pair get_local_iids() const noexcept = 0; virtual hstring GetRuntimeClassName() const = 0; virtual void* find_interface(guid const&) const noexcept = 0; virtual inspectable_abi* find_inspectable() const noexcept = 0; @@ -1528,7 +1528,7 @@ WINRT_EXPORT namespace winrt impl::hresult_type __stdcall GetIids(impl::count_type* count, impl::guid_type** iids) noexcept { - return root_implements_type::GetIids(reinterpret_cast(count), reinterpret_cast(iids)); + return root_implements_type::GetIids(reinterpret_cast(count), reinterpret_cast(iids)); } impl::hresult_type __stdcall GetRuntimeClassName(impl::hstring_type* value) noexcept @@ -1556,11 +1556,11 @@ WINRT_EXPORT namespace winrt return impl::find_inspectable(static_cast(this)); } - std::pair get_local_iids() const noexcept override + std::pair get_local_iids() const noexcept override { using interfaces = impl::uncloaked_interfaces; using local_iids = impl::uncloaked_iids; - return { static_cast(local_iids::value.size()), local_iids::value.data() }; + return { static_cast(local_iids::value.size()), local_iids::value.data() }; } private: diff --git a/strings/base_includes.h b/strings/base_includes.h index a3bf308d1..d6808792b 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -6,9 +6,14 @@ #include #include #include +#include +#include #include +#include +#include #include #include +#include #include #include #include diff --git a/strings/base_iterator.h b/strings/base_iterator.h index b0ad7836d..acb0ebd42 100644 --- a/strings/base_iterator.h +++ b/strings/base_iterator.h @@ -7,13 +7,13 @@ namespace winrt::impl using iterator_concept = std::random_access_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = decltype(std::declval().GetAt(0)); - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = value_type; fast_iterator() noexcept = default; - fast_iterator(T const& collection, uint32_t const index) noexcept : + fast_iterator(T const& collection, std::uint32_t const index) noexcept : m_collection(&collection), m_index(index) {} @@ -46,7 +46,7 @@ namespace winrt::impl fast_iterator& operator+=(difference_type n) noexcept { - m_index += static_cast(n); + m_index += static_cast(n); return *this; } @@ -78,7 +78,7 @@ namespace winrt::impl reference operator[](difference_type n) const { - return m_collection->GetAt(m_index + static_cast(n)); + return m_collection->GetAt(m_index + static_cast(n)); } bool operator==(fast_iterator const& other) const noexcept @@ -127,7 +127,7 @@ namespace winrt::impl private: T const* m_collection = nullptr; - uint32_t m_index = 0; + std::uint32_t m_index = 0; }; template diff --git a/strings/base_lock.h b/strings/base_lock.h index cf70a001a..a0d6261e4 100644 --- a/strings/base_lock.h +++ b/strings/base_lock.h @@ -117,7 +117,7 @@ WINRT_EXPORT namespace winrt return false; } - if (!WINRT_IMPL_SleepConditionVariableSRW(&m_cv, x.get(), static_cast(milliseconds), 0)) + if (!WINRT_IMPL_SleepConditionVariableSRW(&m_cv, x.get(), static_cast(milliseconds), 0)) { return predicate(); } diff --git a/strings/base_marshaler.h b/strings/base_marshaler.h index 359cf3b47..526f4d4c3 100644 --- a/strings/base_marshaler.h +++ b/strings/base_marshaler.h @@ -1,7 +1,7 @@ namespace winrt::impl { - inline int32_t make_marshaler(unknown_abi* outer, void** result) noexcept + inline std::int32_t make_marshaler(unknown_abi* outer, void** result) noexcept { struct marshaler final : IMarshal { @@ -10,7 +10,7 @@ namespace winrt::impl m_object.copy_from(object); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id)) { @@ -22,12 +22,12 @@ namespace winrt::impl return m_object->QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return ++m_references; } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = --m_references; @@ -39,7 +39,7 @@ namespace winrt::impl return remaining; } - int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept final + std::int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, guid* pCid) noexcept final { if (m_marshaler) { @@ -49,7 +49,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept final + std::int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, std::uint32_t* pSize) noexcept final { if (m_marshaler) { @@ -59,7 +59,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags) noexcept final + std::int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags) noexcept final { if (m_marshaler) { @@ -69,7 +69,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept final + std::int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept final { if (m_marshaler) { @@ -80,7 +80,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept final + std::int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept final { if (m_marshaler) { @@ -90,7 +90,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept final + std::int32_t __stdcall DisconnectObject(std::uint32_t dwReserved) noexcept final { if (m_marshaler) { diff --git a/strings/base_natvis.h b/strings/base_natvis.h index 8ff4bd145..60c5f5548 100644 --- a/strings/base_natvis.h +++ b/strings/base_natvis.h @@ -15,19 +15,19 @@ namespace winrt::impl { bool b; wchar_t c; - int8_t i1; - int16_t i2; - int32_t i4; - int64_t i8; - uint8_t u1; - uint16_t u2; - uint32_t u4; - uint64_t u8; + std::int8_t i1; + std::int16_t i2; + std::int32_t i4; + std::int64_t i8; + std::uint8_t u1; + std::uint16_t u2; + std::uint32_t u4; + std::uint64_t u8; float r4; double r8; guid g; void* s; - uint8_t v[1024]; + std::uint8_t v[1024]; } value; value.s = 0; @@ -38,16 +38,16 @@ namespace winrt::impl { void* base_address; void* allocation_base; - uint32_t allocation_protect; + std::uint32_t allocation_protect; #ifdef _WIN64 - uint32_t __alignment1; + std::uint32_t __alignment1; #endif - uintptr_t region_size; - uint32_t state; - uint32_t protect; - uint32_t type; + std::uintptr_t region_size; + std::uint32_t state; + std::uint32_t protect; + std::uint32_t type; #ifdef _WIN64 - uint32_t __alignment2; + std::uint32_t __alignment2; #endif }; memory_basic_information info; @@ -66,7 +66,7 @@ namespace winrt::impl // validate method pointer is executable if ((WINRT_IMPL_VirtualQuery(vfunc, &info, sizeof(info)) != 0) && ((info.protect & 0xF0) != 0)) { - typedef int32_t(__stdcall inspectable_abi:: * PropertyAccessor)(void*); + typedef std::int32_t(__stdcall inspectable_abi:: * PropertyAccessor)(void*); (pinsp->**(PropertyAccessor*)&vfunc)(&value); pinsp->Release(); } diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 8ea2de5b9..570ba42e0 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -23,39 +23,39 @@ namespace winrt::impl return std::is_arithmetic_v || std::is_enum_v; } - uint8_t GetUInt8() const + std::uint8_t GetUInt8() const { - return to_scalar(); + return to_scalar(); } - int16_t GetInt16() const + std::int16_t GetInt16() const { - return to_scalar(); + return to_scalar(); } - uint16_t GetUInt16() const + std::uint16_t GetUInt16() const { - return to_scalar(); + return to_scalar(); } - int32_t GetInt32() const + std::int32_t GetInt32() const { - return to_scalar(); + return to_scalar(); } - uint32_t GetUInt32() const + std::uint32_t GetUInt32() const { - return to_scalar(); + return to_scalar(); } - int64_t GetInt64() const + std::int64_t GetInt64() const { - return to_scalar(); + return to_scalar(); } - uint64_t GetUInt64() const + std::uint64_t GetUInt64() const { - return to_scalar(); + return to_scalar(); } float GetSingle() { throw hresult_not_implemented(); } @@ -69,13 +69,13 @@ namespace winrt::impl Windows::Foundation::Point GetPoint() { throw hresult_not_implemented(); } Windows::Foundation::Size GetSize() { throw hresult_not_implemented(); } Windows::Foundation::Rect GetRect() { throw hresult_not_implemented(); } - void GetUInt8Array(com_array &) { throw hresult_not_implemented(); } - void GetInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt64Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt8Array(com_array &) { throw hresult_not_implemented(); } + void GetInt16Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt16Array(com_array &) { throw hresult_not_implemented(); } + void GetInt32Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt32Array(com_array &) { throw hresult_not_implemented(); } + void GetInt64Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt64Array(com_array &) { throw hresult_not_implemented(); } void GetSingleArray(com_array &) { throw hresult_not_implemented(); } void GetDoubleArray(com_array &) { throw hresult_not_implemented(); } void GetChar16Array(com_array &) { throw hresult_not_implemented(); } @@ -115,52 +115,52 @@ namespace winrt::impl }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } + using itf = Windows::Foundation::IReference; }; template <> @@ -255,52 +255,52 @@ namespace winrt::impl }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> diff --git a/strings/base_security.h b/strings/base_security.h index 8160f11ad..a912487e4 100644 --- a/strings/base_security.h +++ b/strings/base_security.h @@ -18,7 +18,7 @@ WINRT_EXPORT namespace winrt if (!WINRT_IMPL_OpenThreadToken(WINRT_IMPL_GetCurrentThread(), 0x0004 /*TOKEN_IMPERSONATE*/, 1, token.put())) { - uint32_t const error = WINRT_IMPL_GetLastError(); + std::uint32_t const error = WINRT_IMPL_GetLastError(); if (error != 1008 /*ERROR_NO_TOKEN*/) { diff --git a/strings/base_std_hash.h b/strings/base_std_hash.h index eb97db0e9..864c31b13 100644 --- a/strings/base_std_hash.h +++ b/strings/base_std_hash.h @@ -1,19 +1,19 @@ namespace winrt::impl { - inline size_t hash_data(void const* ptr, size_t const bytes) noexcept + inline std::size_t hash_data(void const* ptr, std::size_t const bytes) noexcept { #ifdef _WIN64 - constexpr size_t fnv_offset_basis = 14695981039346656037ULL; - constexpr size_t fnv_prime = 1099511628211ULL; + constexpr std::size_t fnv_offset_basis = 14695981039346656037ULL; + constexpr std::size_t fnv_prime = 1099511628211ULL; #else - constexpr size_t fnv_offset_basis = 2166136261U; - constexpr size_t fnv_prime = 16777619U; + constexpr std::size_t fnv_offset_basis = 2166136261U; + constexpr std::size_t fnv_prime = 16777619U; #endif - size_t result = fnv_offset_basis; - uint8_t const* const buffer = static_cast(ptr); + std::size_t result = fnv_offset_basis; + std::uint8_t const* const buffer = static_cast(ptr); - for (size_t next = 0; next < bytes; ++next) + for (std::size_t next = 0; next < bytes; ++next) { result ^= buffer[next]; result *= fnv_prime; @@ -24,7 +24,7 @@ namespace winrt::impl struct hash_base { - size_t operator()(Windows::Foundation::IUnknown const& value) const noexcept + std::size_t operator()(Windows::Foundation::IUnknown const& value) const noexcept { void* const abi_value = get_abi(value.try_as()); return std::hash{}(abi_value); @@ -36,7 +36,7 @@ namespace std { template<> struct hash { - size_t operator()(winrt::hstring const& value) const noexcept + std::size_t operator()(winrt::hstring const& value) const noexcept { return std::hash{}(value); } @@ -48,7 +48,7 @@ namespace std template<> struct hash { - size_t operator()(winrt::guid const& value) const noexcept + std::size_t operator()(winrt::guid const& value) const noexcept { return winrt::impl::hash_data(&value, sizeof(value)); } diff --git a/strings/base_string.h b/strings/base_string.h index 81229e3d5..c2ba6c742 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -5,21 +5,21 @@ namespace winrt::impl { atomic_ref_count() noexcept = default; - explicit atomic_ref_count(uint32_t count) noexcept : m_count(count) + explicit atomic_ref_count(std::uint32_t count) noexcept : m_count(count) { } - uint32_t operator=(uint32_t count) noexcept + std::uint32_t operator=(std::uint32_t count) noexcept { return m_count = count; } - uint32_t operator++() noexcept + std::uint32_t operator++() noexcept { - return static_cast(m_count.fetch_add(1, std::memory_order_relaxed) + 1); + return static_cast(m_count.fetch_add(1, std::memory_order_relaxed) + 1); } - uint32_t operator--() noexcept + std::uint32_t operator--() noexcept { auto const remaining = m_count.fetch_sub(1, std::memory_order_release) - 1; @@ -29,30 +29,30 @@ namespace winrt::impl } else if (remaining < 0) { - abort(); + std::abort(); } - return static_cast(remaining); + return static_cast(remaining); } - operator uint32_t() const noexcept + operator std::uint32_t() const noexcept { - return static_cast(m_count); + return static_cast(m_count); } private: - std::atomic m_count; + std::atomic m_count; }; - constexpr uint32_t hstring_reference_flag{ 1 }; + constexpr std::uint32_t hstring_reference_flag{ 1 }; struct hstring_header { - uint32_t flags; - uint32_t length; - uint32_t padding1; - uint32_t padding2; + std::uint32_t flags; + std::uint32_t length; + std::uint32_t padding1; + std::uint32_t padding2; wchar_t const* ptr; }; @@ -72,12 +72,12 @@ namespace winrt::impl } } - inline shared_hstring_header* precreate_hstring_on_heap(uint32_t length) + inline shared_hstring_header* precreate_hstring_on_heap(std::uint32_t length) { WINRT_ASSERT(length != 0); - uint64_t bytes_required = static_cast(sizeof(shared_hstring_header)) + static_cast(sizeof(wchar_t)) * static_cast(length); + std::uint64_t bytes_required = static_cast(sizeof(shared_hstring_header)) + static_cast(sizeof(wchar_t)) * static_cast(length); - if (bytes_required > UINT_MAX) + if (bytes_required > (std::numeric_limits::max)()) { throw std::invalid_argument("length"); } @@ -97,7 +97,7 @@ namespace winrt::impl return header; } - inline hstring_header* create_hstring_on_heap(wchar_t const* value, uint32_t length) + inline hstring_header* create_hstring_on_heap(wchar_t const* value, std::uint32_t length) { if (!length) { @@ -105,18 +105,18 @@ namespace winrt::impl } auto header = precreate_hstring_on_heap(length); - memcpy_s(header->buffer, sizeof(wchar_t) * length, value, sizeof(wchar_t) * length); + std::copy_n(value, length, header->buffer); return header; } - inline void create_hstring_on_stack(hstring_header& header, wchar_t const* value, uint32_t length) noexcept + inline void create_hstring_on_stack(hstring_header& header, wchar_t const* value, std::uint32_t length) noexcept { WINRT_ASSERT(value); WINRT_ASSERT(length != 0); if (value[length] != 0) { - abort(); + std::abort(); } header.flags = hstring_reference_flag; @@ -162,7 +162,7 @@ WINRT_EXPORT namespace winrt struct hstring { using value_type = wchar_t; - using size_type = uint32_t; + using size_type = std::uint32_t; using const_reference = value_type const&; using pointer = value_type*; using const_pointer = value_type const*; @@ -191,7 +191,7 @@ WINRT_EXPORT namespace winrt hstring& operator=(std::nullptr_t) = delete; hstring(std::initializer_list value) : - hstring(value.begin(), static_cast(value.size())) + hstring(value.begin(), static_cast(value.size())) {} hstring(wchar_t const* value) : @@ -428,12 +428,12 @@ WINRT_EXPORT namespace winrt inline void* detach_abi(std::wstring_view const& value) { - return impl::create_hstring_on_heap(value.data(), static_cast(value.size())); + return impl::create_hstring_on_heap(value.data(), static_cast(value.size())); } inline void* detach_abi(wchar_t const* const value) { - return impl::create_hstring_on_heap(value, static_cast(wcslen(value))); + return impl::create_hstring_on_heap(value, static_cast(std::wcslen(value))); } } @@ -459,7 +459,7 @@ namespace winrt::impl hstring_builder(hstring_builder const&) = delete; hstring_builder& operator=(hstring_builder const&) = delete; - explicit hstring_builder(uint32_t const size) : + explicit hstring_builder(std::uint32_t const size) : m_handle(impl::precreate_hstring_on_heap(size)) { } @@ -574,8 +574,8 @@ namespace winrt::impl // when non-const (e.g. ranges::filter_view) so taking a const reference // as parameter wouldn't work for all scenarios. auto const size = std::formatted_size(args...); - WINRT_ASSERT(size < INT_MAX); - auto const size32 = static_cast(size); + WINRT_ASSERT(size < static_cast((std::numeric_limits::max)())); + auto const size32 = static_cast(size); hstring_builder builder(size32); WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); @@ -608,42 +608,42 @@ WINRT_EXPORT namespace winrt }); } - inline hstring to_hstring(uint8_t value) + inline hstring to_hstring(std::uint8_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int8_t value) + inline hstring to_hstring(std::int8_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint16_t value) + inline hstring to_hstring(std::uint16_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int16_t value) + inline hstring to_hstring(std::int16_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint32_t value) + inline hstring to_hstring(std::uint32_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int32_t value) + inline hstring to_hstring(std::int32_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint64_t value) + inline hstring to_hstring(std::uint64_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int64_t value) + inline hstring to_hstring(std::int64_t value) { return impl::hstring_convert(value); } @@ -688,7 +688,7 @@ WINRT_EXPORT namespace winrt { wchar_t buffer[40]; //{00000000-0000-0000-0000-000000000000} - swprintf_s(buffer, L"{%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}", + std::swprintf(buffer, std::size(buffer), L"{%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}", value.Data1, value.Data2, value.Data3, value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7]); return hstring{ buffer }; @@ -698,7 +698,7 @@ WINRT_EXPORT namespace winrt hstring to_hstring(T const& value) { std::string_view const view(value); - int const size = WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), nullptr, 0); + int const size = WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), nullptr, 0); if (size == 0) { @@ -706,13 +706,13 @@ WINRT_EXPORT namespace winrt } impl::hstring_builder result(size); - WINRT_VERIFY_(size, WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), result.data(), size)); + WINRT_VERIFY_(size, WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), result.data(), size)); return result.to_hstring(); } inline std::string to_string(std::wstring_view value) { - int const size = WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), nullptr, 0, nullptr, nullptr); + int const size = WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), nullptr, 0, nullptr, nullptr); if (size == 0) { @@ -720,7 +720,7 @@ WINRT_EXPORT namespace winrt } std::string result(size, '?'); - WINRT_VERIFY_(size, WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), result.data(), size, nullptr, nullptr)); + WINRT_VERIFY_(size, WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), result.data(), size, nullptr, nullptr)); return result; } } diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 8cfea212b..5ac0221f6 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::param hstring(wchar_t const* const value) noexcept { - create_string_reference(value, wcslen(value)); + create_string_reference(value, std::wcslen(value)); } operator winrt::hstring const&() const noexcept @@ -39,10 +39,10 @@ WINRT_EXPORT namespace winrt::param } private: - void create_string_reference(wchar_t const* const data, size_t size) noexcept + void create_string_reference(wchar_t const* const data, std::size_t size) noexcept { - WINRT_ASSERT(size < UINT_MAX); - auto size32 = static_cast(size); + WINRT_ASSERT(size < (std::numeric_limits::max)()); + auto size32 = static_cast(size); if (size32 == 0) { diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index b00150f92..25e2eccce 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -98,14 +98,14 @@ namespace winrt::impl { inline hstring concat_hstring(std::wstring_view const& left, std::wstring_view const& right) { - auto size = static_cast(left.size() + right.size()); + auto size = static_cast(left.size() + right.size()); if (size == 0) { return{}; } hstring_builder text(size); - memcpy_s(text.data(), left.size() * sizeof(wchar_t), left.data(), left.size() * sizeof(wchar_t)); - memcpy_s(text.data() + left.size(), right.size() * sizeof(wchar_t), right.data(), right.size() * sizeof(wchar_t)); + std::copy_n(left.data(), left.size(), text.data()); + std::copy_n(right.data(), right.size(), text.data() + left.size()); return text.to_hstring(); } } diff --git a/strings/base_types.h b/strings/base_types.h index 84cf22f5d..18529e116 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -14,25 +14,25 @@ namespace winrt::impl struct com_callback_args { - uint32_t reserved1; - uint32_t reserved2; + std::uint32_t reserved1; + std::uint32_t reserved2; void* data; }; template - constexpr uint8_t hex_to_uint(T const c) + constexpr std::uint8_t hex_to_uint(T const c) { if (c >= '0' && c <= '9') { - return static_cast(c - '0'); + return static_cast(c - '0'); } else if (c >= 'A' && c <= 'F') { - return static_cast(10 + c - 'A'); + return static_cast(10 + c - 'A'); } else if (c >= 'a' && c <= 'f') { - return static_cast(10 + c - 'a'); + return static_cast(10 + c - 'a'); } else { @@ -41,20 +41,20 @@ namespace winrt::impl } template - constexpr uint8_t hex_to_uint8(T const a, T const b) + constexpr std::uint8_t hex_to_uint8(T const a, T const b) { return (hex_to_uint(a) << 4) | hex_to_uint(b); } - constexpr uint16_t uint8_to_uint16(uint8_t a, uint8_t b) + constexpr std::uint16_t uint8_to_uint16(std::uint8_t a, std::uint8_t b) { - return (static_cast(a) << 8) | static_cast(b); + return (static_cast(a) << 8) | static_cast(b); } - constexpr uint32_t uint8_to_uint32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) + constexpr std::uint32_t uint8_to_uint32(std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) { - return (static_cast(uint8_to_uint16(a, b)) << 16) | - static_cast(uint8_to_uint16(c, d)); + return (static_cast(uint8_to_uint16(a, b)) << 16) | + static_cast(uint8_to_uint16(c, d)); } } @@ -66,15 +66,15 @@ WINRT_EXPORT namespace winrt struct hresult { - int32_t value{}; + std::int32_t value{}; constexpr hresult() noexcept = default; - constexpr hresult(int32_t const value) noexcept : value(value) + constexpr hresult(std::int32_t const value) noexcept : value(value) { } - constexpr operator int32_t() const noexcept + constexpr operator std::int32_t() const noexcept { return value; } @@ -133,14 +133,14 @@ WINRT_EXPORT namespace winrt public: - uint32_t Data1; - uint16_t Data2; - uint16_t Data3; - uint8_t Data4[8]; + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; guid() noexcept = default; - constexpr guid(uint32_t const Data1, uint16_t const Data2, uint16_t const Data3, std::array const& Data4) noexcept : + constexpr guid(std::uint32_t const Data1, std::uint16_t const Data2, std::uint16_t const Data3, std::array const& Data4) noexcept : Data1(Data1), Data2(Data2), Data3(Data3), @@ -178,7 +178,7 @@ WINRT_EXPORT namespace winrt inline bool operator==(guid const& left, guid const& right) noexcept { - return !memcmp(&left, &right, sizeof(left)); + return !std::memcmp(&left, &right, sizeof(left)); } inline bool operator!=(guid const& left, guid const& right) noexcept @@ -188,13 +188,13 @@ WINRT_EXPORT namespace winrt inline bool operator<(guid const& left, guid const& right) noexcept { - return memcmp(&left, &right, sizeof(left)) < 0; + return std::memcmp(&left, &right, sizeof(left)) < 0; } } WINRT_EXPORT namespace winrt::Windows::Foundation { - enum class TrustLevel : int32_t + enum class TrustLevel : std::int32_t { BaseTrust, PartialTrust, @@ -204,7 +204,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation struct IUnknown; struct IInspectable; struct IActivationFactory; - using TimeSpan = std::chrono::duration; + using TimeSpan = std::chrono::duration; using DateTime = std::chrono::time_point; } @@ -215,8 +215,8 @@ namespace winrt::impl using count_type = unsigned long; using guid_type = GUID; #else - using hresult_type = int32_t; - using count_type = uint32_t; + using hresult_type = std::int32_t; + using count_type = std::uint32_t; using guid_type = guid; #endif diff --git a/strings/base_version.h b/strings/base_version.h index adb3608da..4a6b68e66 100644 --- a/strings/base_version.h +++ b/strings/base_version.h @@ -16,7 +16,7 @@ char const * const WINRT_version = "C++/WinRT version:" CPPWINRT_VERSION; WINRT_EXPORT namespace winrt { - template + template constexpr bool check_version(char const(&base)[BaseSize], char const(&component)[ComponentSize]) noexcept { if constexpr (BaseSize != ComponentSize) @@ -24,7 +24,7 @@ WINRT_EXPORT namespace winrt return false; } - for (size_t i = 0; i != BaseSize - 1; ++i) + for (std::size_t i = 0; i != BaseSize - 1; ++i) { if (base[i] != component[i]) { diff --git a/strings/base_windows.h b/strings/base_windows.h index 831e1b1fe..21c4163e5 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -6,12 +6,12 @@ namespace winrt::impl struct factory_diagnostics_info { bool is_agile{ true }; - uint32_t requests{ 0 }; + std::uint32_t requests{ 0 }; }; struct diagnostics_info { - std::map queries; + std::map queries; std::map factories; }; @@ -163,7 +163,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation { IUnknown() noexcept = default; IUnknown(std::nullptr_t) noexcept {} - void* operator new(size_t) = delete; + void* operator new(std::size_t) = delete; IUnknown(void* ptr, take_ownership_from_abi_t) noexcept : m_ptr(static_cast(ptr)) { diff --git a/strings/base_xaml_component_connector.h b/strings/base_xaml_component_connector.h index 366e18e22..092944613 100644 --- a/strings/base_xaml_component_connector.h +++ b/strings/base_xaml_component_connector.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + void Connect(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { diff --git a/strings/base_xaml_component_connector_winui.h b/strings/base_xaml_component_connector_winui.h index 4a1f0326a..312f5af29 100644 --- a/strings/base_xaml_component_connector_winui.h +++ b/strings/base_xaml_component_connector_winui.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + void Connect(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { diff --git a/strings/base_xaml_typename.h b/strings/base_xaml_typename.h index 4a782fc72..b7b3a954a 100644 --- a/strings/base_xaml_typename.h +++ b/strings/base_xaml_typename.h @@ -66,42 +66,42 @@ namespace winrt::impl static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; From b9553a9f0faf9a1395ac98aea65716c6f44e9fca Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 19 Mar 2026 11:27:29 -0700 Subject: [PATCH 284/305] Fix race condition in multi_threaded_observable_map test (#1550) * Fix race condition in multi_threaded_observable_map test * Hook the other iterator movement methods. --- test/test/multi_threaded_common.h | 15 +++++++++++++-- test/test/multi_threaded_map.cpp | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/test/test/multi_threaded_common.h b/test/test/multi_threaded_common.h index 026cb3264..3ed687743 100644 --- a/test/test/multi_threaded_common.h +++ b/test/test/multi_threaded_common.h @@ -45,7 +45,7 @@ namespace concurrent_collections // for the first time on the background thread. enum class collection_action { - none, push_back, insert, erase, at, lookup + none, push_back, insert, erase, at, lookup, advance }; // All of our concurrency tests consists of starting an @@ -165,16 +165,23 @@ namespace concurrent_collections return owner->dereference_iterator(inner()); } - // inherited: pointer operator->() const; + pointer operator->() const + { + auto guard = owner->lock_const(); + owner->call_hook(collection_action::at); + return iterator::operator->(); + } concurrency_checked_random_access_iterator& operator++() { + owner->call_hook(collection_action::advance); ++inner(); return *this; } concurrency_checked_random_access_iterator& operator++(int) { + owner->call_hook(collection_action::advance); auto prev = *this; ++inner(); return prev; @@ -182,12 +189,14 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator--() { + owner->call_hook(collection_action::advance); --inner(); return *this; } concurrency_checked_random_access_iterator& operator--(int) { + owner->call_hook(collection_action::advance); auto prev = *this; --inner(); return prev; @@ -195,6 +204,7 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator+=(difference_type offset) { + owner->call_hook(collection_action::advance); inner() += offset; return *this; } @@ -206,6 +216,7 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator-=(difference_type offset) { + owner->call_hook(collection_action::advance); inner() -= offset; return *this; } diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index d0f68c1e2..ffa9988ba 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -237,7 +237,7 @@ namespace { // MoveNext vs Remove bool moved = false; - race(collection_action::at, [&] + race(collection_action::advance, [&] { try { @@ -273,7 +273,7 @@ namespace { // MoveNext vs Insert bool moved = false; - race(collection_action::at, [&] + race(collection_action::advance, [&] { try { From 16a1c29b5351ca5212f4235d1db5776bdd13ae78 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 23 Mar 2026 12:46:53 -0400 Subject: [PATCH 285/305] Fix integer fields causing impl promotion (#1551) --- cppwinrt/code_writers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 0a4c4638e..fc5081bef 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2916,7 +2916,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable for (auto&& field : type.fields) { - if (field.second.find(':') == std::string::npos) + if (field.second.find(':') == std::string::npos || starts_with(field.second, "std::")) { continue; } From 3893ce8c3d0af7676c36f5f933707d442c53050b Mon Sep 17 00:00:00 2001 From: justanotheranonymoususer Date: Thu, 2 Apr 2026 02:00:22 +0300 Subject: [PATCH 286/305] box_value constructor: Replace param::hstring with hstring (#1530) * box_value constructor: Replace param::hstring with hstring * Update base_reference_produce.h * Fix and add tests * Fix github.dev bug --- strings/base_reference_produce.h | 7 +++-- test/test/box_string.cpp | 53 ++++++++++++++++++++++++++++++++ test/test/test.vcxproj | 1 + 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 test/test/box_string.cpp diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 570ba42e0..2820aff50 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -509,12 +509,13 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { - inline Windows::Foundation::IInspectable box_value(param::hstring const& value) + template , int> = 0> + Windows::Foundation::IInspectable box_value(T&& value) { - return Windows::Foundation::IReference(*(hstring*)(&value)); + return Windows::Foundation::IReference(hstring(std::forward(value))); } - template , int> = 0> + template , int> = 0> Windows::Foundation::IInspectable box_value(T const& value) { if constexpr (std::is_base_of_v) diff --git a/test/test/box_string.cpp b/test/test/box_string.cpp new file mode 100644 index 000000000..efff92160 --- /dev/null +++ b/test/test/box_string.cpp @@ -0,0 +1,53 @@ +#include "pch.h" + +TEST_CASE("box_string") +{ + // hstring + { + winrt::hstring value = L"hstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"hstring"); + } + + // wchar_t const* (string literal) + { + auto boxed = winrt::box_value(L"literal"); + REQUIRE(winrt::unbox_value(boxed) == L"literal"); + } + + // std::wstring + { + std::wstring value = L"wstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"wstring"); + } + + // std::wstring_view (null-terminated) + { + std::wstring_view value = L"view"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"view"); + } + + // std::wstring_view (not null-terminated) + // Regression test for https://github.com/microsoft/cppwinrt/issues/1527 + { + std::wstring source = L"ABCDE"; + std::wstring_view value(source.data(), 3); // "ABC" + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"ABC"); + } + + // Empty string + { + auto boxed = winrt::box_value(winrt::hstring{}); + REQUIRE(winrt::unbox_value(boxed) == L""); + } + + // Empty wstring_view + { + std::wstring_view value; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L""); + } +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 7840f17eb..43928dab2 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -233,6 +233,7 @@ + NotUsing From d254f72ed6d4060f0028221e3e59ee1b2f5e6efc Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:23:17 -0700 Subject: [PATCH 287/305] fix: normalize CRLF to LF in test/test/box_string.cpp (#1557) * Initial plan * fix: convert CRLF to LF in test/test/box_string.cpp Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/9b31d4ec-f1c5-4859-89a1-3249eb553c5c Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> * Add workflow to check line endings in pull requests --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> Co-authored-by: Ryan Shepherd --- .github/workflows/check-line-endings.yml | 32 +++++++ test/test/box_string.cpp | 106 +++++++++++------------ 2 files changed, 85 insertions(+), 53 deletions(-) create mode 100644 .github/workflows/check-line-endings.yml diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml new file mode 100644 index 000000000..a0705cf58 --- /dev/null +++ b/.github/workflows/check-line-endings.yml @@ -0,0 +1,32 @@ +name: Check Line Endings + +on: + pull_request: + push: + branches: + - master + +jobs: + check-line-endings: + name: Enforce .gitattributes line endings + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Check for line ending violations + run: | + # Re-normalize all files according to .gitattributes + git add --renormalize . + + # Check if renormalization changed anything + if git diff --cached --name-only | grep -q .; then + echo "::error::The following files have line endings that don't match .gitattributes settings:" + git diff --cached --name-only + echo "" + echo "To fix, run:" + echo " git add --renormalize ." + echo " git commit -m 'Normalize line endings'" + exit 1 + fi + + echo "All files have correct line endings." diff --git a/test/test/box_string.cpp b/test/test/box_string.cpp index efff92160..7294eeb79 100644 --- a/test/test/box_string.cpp +++ b/test/test/box_string.cpp @@ -1,53 +1,53 @@ -#include "pch.h" - -TEST_CASE("box_string") -{ - // hstring - { - winrt::hstring value = L"hstring"; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"hstring"); - } - - // wchar_t const* (string literal) - { - auto boxed = winrt::box_value(L"literal"); - REQUIRE(winrt::unbox_value(boxed) == L"literal"); - } - - // std::wstring - { - std::wstring value = L"wstring"; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"wstring"); - } - - // std::wstring_view (null-terminated) - { - std::wstring_view value = L"view"; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"view"); - } - - // std::wstring_view (not null-terminated) - // Regression test for https://github.com/microsoft/cppwinrt/issues/1527 - { - std::wstring source = L"ABCDE"; - std::wstring_view value(source.data(), 3); // "ABC" - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"ABC"); - } - - // Empty string - { - auto boxed = winrt::box_value(winrt::hstring{}); - REQUIRE(winrt::unbox_value(boxed) == L""); - } - - // Empty wstring_view - { - std::wstring_view value; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L""); - } -} +#include "pch.h" + +TEST_CASE("box_string") +{ + // hstring + { + winrt::hstring value = L"hstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"hstring"); + } + + // wchar_t const* (string literal) + { + auto boxed = winrt::box_value(L"literal"); + REQUIRE(winrt::unbox_value(boxed) == L"literal"); + } + + // std::wstring + { + std::wstring value = L"wstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"wstring"); + } + + // std::wstring_view (null-terminated) + { + std::wstring_view value = L"view"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"view"); + } + + // std::wstring_view (not null-terminated) + // Regression test for https://github.com/microsoft/cppwinrt/issues/1527 + { + std::wstring source = L"ABCDE"; + std::wstring_view value(source.data(), 3); // "ABC" + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"ABC"); + } + + // Empty string + { + auto boxed = winrt::box_value(winrt::hstring{}); + REQUIRE(winrt::unbox_value(boxed) == L""); + } + + // Empty wstring_view + { + std::wstring_view value; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L""); + } +} From f23b41e92176052bff519f00d44f6497e0845413 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 2 Apr 2026 16:46:32 -0700 Subject: [PATCH 288/305] Breaking coroutines means v3.0 (#1547) * Start moving to v3.0 * Set more obvious placeholder version numbers --- .github/workflows/ci.yml | 8 ++++---- .pipelines/OneBranch.Official.yml | 2 +- .pipelines/OneBranch.PullRequest.yml | 2 +- .pipelines/variables/version.yml | 2 +- CMakeLists.txt | 4 ++-- Directory.Build.Props | 2 +- build_nuget.cmd | 2 +- build_test_all.cmd | 2 +- build_vsix.cmd | 2 +- prebuild/main.cpp | 18 ++++++++++++++---- 10 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a42f2c5b7..cb8cafd2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" @@ -134,7 +134,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" @@ -301,7 +301,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" - name: Restore nuget packages @@ -347,7 +347,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" - name: Restore nuget packages diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 7a73b263b..158d3bf4e 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -12,7 +12,7 @@ variables: parameters: debug: ${{ parameters.debug }} -name: 2.0.$(date:yyMMdd)$(rev:.r) +name: 3.0.$(date:yyMMdd)$(rev:.r) trigger: none diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index 9e18821b4..d92dccaa2 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -10,7 +10,7 @@ variables: parameters: debug: ${{ parameters.debug }} -name: PullRequest_2.0.$(date:yyMMdd)$(rev:.r) +name: PullRequest_3.0.$(date:yyMMdd)$(rev:.r) trigger: none diff --git a/.pipelines/variables/version.yml b/.pipelines/variables/version.yml index 15382e7df..46a535ee0 100644 --- a/.pipelines/variables/version.yml +++ b/.pipelines/variables/version.yml @@ -4,7 +4,7 @@ parameters: default: false variables: - MajorVersion: "2" + MajorVersion: "3" MinorVersion: "0" VersionDate: $[format('{0:yyMMdd}', pipeline.startTime)] VersionCounter: $[counter(variables['VersionDate'], 1)] diff --git a/CMakeLists.txt b/CMakeLists.txt index 139da8379..b0089e7ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ project(cppwinrt LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) -set(CPPWINRT_BUILD_VERSION "2.3.4.5" CACHE STRING "The version string used for cppwinrt.") -if(CPPWINRT_BUILD_VERSION STREQUAL "2.3.4.5" OR CPPWINRT_BUILD_VERSION STREQUAL "0.0.0.0") +set(CPPWINRT_BUILD_VERSION "999.999.999.999" CACHE STRING "The version string used for cppwinrt.") +if(CPPWINRT_BUILD_VERSION STREQUAL "999.999.999.999" OR CPPWINRT_BUILD_VERSION STREQUAL "0.0.0.0") message(WARNING "CPPWINRT_BUILD_VERSION has been set to a dummy version string. Do not use in production!") endif() message(STATUS "Using version string: ${CPPWINRT_BUILD_VERSION}") diff --git a/Directory.Build.Props b/Directory.Build.Props index 5f530da91..c98cd5dd0 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -37,7 +37,7 @@ - 2.3.4.5 + 999.999.999.999 $(Platform) x86 $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ diff --git a/build_nuget.cmd b/build_nuget.cmd index 3926e4d0b..99e193311 100644 --- a/build_nuget.cmd +++ b/build_nuget.cmd @@ -1,7 +1,7 @@ rem @echo off set target_version=%1 -if "%target_version%"=="" set target_version=3.0.0.0 +if "%target_version%"=="" set target_version=999.999.999.999 call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd diff --git a/build_test_all.cmd b/build_test_all.cmd index 649f4dc69..c9beb852c 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -7,7 +7,7 @@ set clean_intermediate_files=%4 if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Release -if "%target_version%"=="" set target_version=1.2.3.4 +if "%target_version%"=="" set target_version=999.999.999.999 if not exist ".\.nuget" mkdir ".\.nuget" if not exist ".\.nuget\nuget.exe" powershell -Command "$ProgressPreference = 'SilentlyContinue' ; Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\.nuget\nuget.exe" diff --git a/build_vsix.cmd b/build_vsix.cmd index aefc84df1..0a47f6bd6 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -6,7 +6,7 @@ set target_version=%2 set target_deployment=%3 if "%target_configuration%"=="" set target_configuration=Release -if "%target_version%"=="" set target_version=1.2.3.4 +if "%target_version%"=="" set target_version=999.999.999.999 if "%target_deployment%"=="" set target_deployment=Standalone if not exist ".\.nuget" mkdir ".\.nuget" diff --git a/prebuild/main.cpp b/prebuild/main.cpp index 3e427d32b..1295f8f69 100644 --- a/prebuild/main.cpp +++ b/prebuild/main.cpp @@ -77,12 +77,19 @@ namespace cppwinrt::strings { writer version_rc; + // Extract major.minor substrings from CPPWINRT_VERSION_STRING (e.g. "3.0.250316.1") + std::string_view const full_version{ CPPWINRT_VERSION_STRING }; + auto const first_dot = full_version.find('.'); + auto const second_dot = full_version.find('.', first_dot + 1); + auto const ver_major = full_version.substr(0, first_dot); + auto const ver_minor = full_version.substr(first_dot + 1, second_dot - first_dot - 1); + version_rc.write(R"( #include "winres.h" VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,0 - PRODUCTVERSION 2,0,0,0 + FILEVERSION %,%,0,0 + PRODUCTVERSION %,%,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -99,7 +106,7 @@ BEGIN BEGIN VALUE "CompanyName", "Microsoft Corporation" VALUE "FileDescription", "C++/WinRT" - VALUE "FileVersion", "2.0.0.0" + VALUE "FileVersion", "%.%.0.0" VALUE "LegalCopyright", "Microsoft Corporation. All rights reserved." VALUE "OriginalFilename", "cppwinrt.exe" VALUE "ProductName", "C++/WinRT" @@ -112,7 +119,10 @@ BEGIN END END )", - CPPWINRT_VERSION_STRING); + ver_major, ver_minor, // FILEVERSION + ver_major, ver_minor, // PRODUCTVERSION + ver_major, ver_minor, // FileVersion string + CPPWINRT_VERSION_STRING); // ProductVersion string std::filesystem::create_directories(argv[2]); auto const output = std::filesystem::canonical(argv[2]); From 748d1e0876cf64a512dccbedd6ca72ee3bcda813 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Tue, 21 Apr 2026 03:55:48 +0800 Subject: [PATCH 289/305] Add inline for hstring_reference_flag (#1571) --- strings/base_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_string.h b/strings/base_string.h index c2ba6c742..92295e81c 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -45,7 +45,7 @@ namespace winrt::impl std::atomic m_count; }; - constexpr std::uint32_t hstring_reference_flag{ 1 }; + inline constexpr std::uint32_t hstring_reference_flag{ 1 }; struct hstring_header { From a5e9452e6858849496e61c166ab8510d3acaec2a Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 16:01:47 -0700 Subject: [PATCH 290/305] CI: test against VS2022 (v143) and VS2026 (v145) in parallel (#1573) * Run Windows CI matrix on 2025 and 2025-vs2026 toolsets Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/b78f8378-0fed-463c-97ac-e16f18e532a9 Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> * Simplify CI: drop vswhere version/prerelease fields, keep platform_toolset Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/d084d7e4-1d03-4234-a219-7b58887d42d5 Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> * Fix clang-cl v145 build: exclude clang from memset path in com_array::detach_abi Clang 19+ (VS2026/v145) treats memset on non-trivially-copyable types as a hard error. clang-cl defines _MSC_VER, so it was taking the memset workaround path meant only for MSVC. Guard with !defined(__clang__) so clang-cl uses the safe member-assignment branch instead. Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/d433cd66-3565-4257-9c9d-23ec477f8c4d Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> --- .github/workflows/ci.yml | 43 +++++++++++++++++++++++++++++----------- strings/base_array.h | 2 +- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb8cafd2b..d660400a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,12 +8,17 @@ on: jobs: test-msvc-cppwinrt-build: - name: '${{ matrix.compiler }}: Build (${{ matrix.arch }}, ${{ matrix.config }})' + name: '${{ matrix.compiler }}: Build (${{ matrix.arch }}, ${{ matrix.config }}, ${{ matrix.toolchain.platform_toolset }})' strategy: matrix: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] + toolchain: + - image: windows-2025 + platform_toolset: v143 + - image: windows-2025-vs2026 + platform_toolset: v145 exclude: - arch: arm64 config: Debug @@ -21,7 +26,7 @@ jobs: arch: arm64 - compiler: clang-cl config: Release - runs-on: windows-latest + runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 @@ -45,6 +50,8 @@ jobs: $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" + } else { + $props += ",PlatformToolset=${{ matrix.toolchain.platform_toolset }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -68,7 +75,7 @@ jobs: - name: Upload built executables uses: actions/upload-artifact@v7 with: - name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -84,7 +91,7 @@ jobs: & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose test-msvc-cppwinrt-test: - name: '${{ matrix.compiler }}: Test [${{ matrix.test_exe }}] (${{ matrix.arch }}, ${{ matrix.config }})' + name: '${{ matrix.compiler }}: Test [${{ matrix.test_exe }}] (${{ matrix.arch }}, ${{ matrix.config }}, ${{ matrix.toolchain.platform_toolset }})' needs: test-msvc-cppwinrt-build strategy: fail-fast: false @@ -93,6 +100,11 @@ jobs: arch: [x86, x64, arm64] config: [Debug, Release] test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + toolchain: + - image: windows-2025 + platform_toolset: v143 + - image: windows-2025-vs2026 + platform_toolset: v145 exclude: - arch: arm64 config: Debug @@ -100,7 +112,7 @@ jobs: arch: arm64 - compiler: clang-cl config: Release - runs-on: windows-latest + runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 @@ -108,14 +120,14 @@ jobs: if: matrix.arch != 'arm64' uses: actions/download-artifact@v8 with: - name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' uses: actions/download-artifact@v8 with: - name: msvc-build-${{ matrix.compiler}}-x86-Release-bin + name: msvc-build-${{ matrix.compiler}}-x86-Release-${{ matrix.toolchain.platform_toolset }}-bin path: _build/x86/Release/ - name: Download nuget @@ -138,6 +150,8 @@ jobs: $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" + } else { + $props += ",PlatformToolset=${{ matrix.toolchain.platform_toolset }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -232,7 +246,7 @@ jobs: if: matrix.arch == 'arm64' uses: actions/upload-artifact@v7 with: - name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -313,7 +327,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln build-msvc-nuget-test: - name: 'Build nuget test (${{ matrix.arch }})' + name: 'Build nuget test (${{ matrix.arch }}, ${{ matrix.toolchain.platform_toolset }})' needs: test-msvc-cppwinrt-build strategy: matrix: @@ -321,14 +335,19 @@ jobs: - MSVC arch: [x86, x64] config: [Release] - runs-on: windows-latest + toolchain: + - image: windows-2025 + platform_toolset: v143 + - image: windows-2025-vs2026 + platform_toolset: v145 + runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 - name: Fetch cppwinrt executables uses: actions/download-artifact@v8 with: - name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Download nuget @@ -348,7 +367,7 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" $target_version = "999.999.999.999" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version,PlatformToolset=${{ matrix.toolchain.platform_toolset }}" - name: Restore nuget packages run: | diff --git a/strings/base_array.h b/strings/base_array.h index 9544dcf8c..48d10c6ce 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -376,7 +376,7 @@ WINRT_EXPORT namespace winrt std::pair> detach_abi() noexcept { -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) // https://github.com/microsoft/cppwinrt/pull/1165 std::pair> result; std::memset(&result, 0, sizeof(result)); From 58811e1efe1589b0d022137c3246fc5e703df3a4 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Fri, 15 May 2026 00:27:24 +0800 Subject: [PATCH 291/305] Move operator<< to winrt::Windows::Foundation (#1576) --- strings/base_stringable_streams.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/strings/base_stringable_streams.h b/strings/base_stringable_streams.h index 52b481d6f..fa17b0f3e 100644 --- a/strings/base_stringable_streams.h +++ b/strings/base_stringable_streams.h @@ -1,8 +1,11 @@ #ifndef WINRT_LEAN_AND_MEAN -inline std::wostream& operator<<(std::wostream& stream, winrt::Windows::Foundation::IStringable const& stringable) +namespace winrt::Windows::Foundation { - stream << stringable.ToString(); - return stream; + inline std::wostream& operator<<(std::wostream& stream, winrt::Windows::Foundation::IStringable const& stringable) + { + stream << stringable.ToString(); + return stream; + } } #endif From 55f1b452aca069d6ac7eaad3e05cc1058fc39d27 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 20 May 2026 13:17:10 -0700 Subject: [PATCH 292/305] C++20 module support v2 (#1575) * Initial implementation of vs modules based on cppwinrtplus fork * Rename WINRT_MODULE -> WINRT_IMPL_BUILD_MODULE; WINRT_CONSUME_MODULE -> WINRT_IMPORT_MODULE * Namespace modules are winrt.Namespace. Non-namespace modules are winrt_base/winrt_numerics Co-authored-by: Copilot * Bootstrap basic unit test Co-authored-by: Copilot * Fix coroutine export. A few more unit tests. Co-authored-by: Copilot * module_include, module_exclude Co-authored-by: Copilot * Rename test_module to test_cpp20_module * Nuget test project with module include/exclude Co-authored-by: Copilot * Refine generated files in component. Co-authored-by: Copilot * Added a type deriving from DependencyObject Co-authored-by: Copilot * Basic module build/consume support Co-authored-by: Copilot * Prefix namespace ixx files with "winrt." for consistency with module names and built ifc files. Co-authored-by: Copilot * IFC needs better per-project scoping. Now it fully works end to end. * Minor fix to TestModuleComponent2 * Documentation and polish. Co-authored-by: YexuanXiao Co-authored-by: Copilot * Fix CI failures Co-authored-by: Copilot * Try for better std hygiene * Address some PR feedback * Better automation of AdditionalBMIDirectories Co-authored-by: Copilot * Missed fallback definition of WINRT_IMPL_STD_EXPORT * Wrap base.h and extern the handler pointers * Uniform namespace filtering * Write trailing comments for #endif * Clarify language version requirement * Add source_location test Co-authored-by: Copilot * Refactor/cleanup some string writers Co-authored-by: Copilot * Add arm64 configs and replace bogus project guids with real guids. Co-authored-by: Copilot * More cleanup of strings. Collected common macros into base_macros.h, generates into winrt/macros.h Co-authored-by: Copilot * More strings cleanup. Emit a canonical winrt/base_macros.h Co-authored-by: Copilot * More clarifications about guidance when sharing pre-built modules Co-authored-by: Copilot * Ensure structured bindings are exported for IKeyValuePair Co-authored-by: Copilot * Fix up module namespace exclude logic so it still generates import statements. * intrin.h and only needed by base, not namespace modules * Tidy up a few codegen bits * Fix sln config on test_cpp20_module project * Namespace modules now check version against imported winrt_base Co-authored-by: Copilot * PR feedback: Test format, hash, natvis hook visibility, message on old compiler Co-authored-by: Copilot * Clean up some handling of numerics-related code and add some numerics smoke tests * De-duplicate windowsnumerics.impl.h logic * A little more WINRT_IMPORT_MODULE cleanup * Use write_depends in SCC writers --------- Co-authored-by: Copilot Co-authored-by: YexuanXiao --- .github/instructions/cppwinrt.instructions.md | 58 +++ .github/instructions/modules.instructions.md | 40 ++ .github/workflows/ci.yml | 9 + cppwinrt.sln | 18 + cppwinrt/code_writers.h | 57 ++- cppwinrt/component_writers.h | 5 +- cppwinrt/file_writers.h | 374 ++++++++++++++++-- cppwinrt/main.cpp | 203 +++++++++- cppwinrt/settings.h | 6 + docs/modules-design.md | 190 +++++++++ natvis/pch.h | 1 + nuget/Microsoft.Windows.CppWinRT.targets | 95 ++++- nuget/modules.md | 179 +++++++++ nuget/readme.md | 12 + strings/base_abi.h | 2 +- strings/base_activation.h | 6 +- strings/base_agile_ref.h | 2 +- strings/base_array.h | 2 +- strings/base_collections.h | 2 +- strings/base_collections_base.h | 2 +- strings/base_collections_input_iterable.h | 2 +- strings/base_collections_input_map.h | 2 +- strings/base_collections_input_map_view.h | 2 +- strings/base_collections_input_vector.h | 2 +- strings/base_collections_input_vector_view.h | 2 +- strings/base_collections_map.h | 6 +- strings/base_collections_vector.h | 2 +- strings/base_com_ptr.h | 4 +- strings/base_composable.h | 2 +- strings/base_coroutine_foundation.h | 6 +- strings/base_coroutine_threadpool.h | 6 +- strings/base_delegate.h | 2 +- strings/base_detect_numerics.h | 4 + strings/base_error.h | 4 +- strings/base_events.h | 2 +- strings/base_extern.h | 11 +- strings/base_fast_forward.h | 6 +- strings/base_foundation.h | 2 +- strings/base_identity.h | 2 +- strings/base_implements.h | 6 +- strings/base_include_numerics.h | 19 + strings/base_includes.h | 5 - strings/base_iterator.h | 2 +- strings/base_macros.h | 146 ++----- strings/base_marshaler.h | 2 +- strings/base_meta.h | 2 +- strings/base_module_base_ixx.h | 13 + strings/base_module_ixx_preamble.h | 11 + strings/base_module_numerics_ixx.h | 6 + strings/base_natvis.h | 2 +- strings/base_reference_produce.h | 4 +- strings/base_source_location.h | 97 +++++ strings/base_std_hash.h | 4 +- strings/base_string.h | 4 +- strings/base_string_input.h | 2 +- strings/base_string_operators.h | 2 +- strings/base_types.h | 4 +- strings/base_version.h | 2 + strings/base_windows.h | 2 +- strings/base_xaml_typename.h | 2 +- test/nuget/NuGetTest.sln | 69 +++- .../TestModuleApp/CustomDependencyObject.cpp | 8 + .../TestModuleApp/CustomDependencyObject.h | 23 ++ test/nuget/TestModuleApp/ModuleTestHelper.cpp | 7 + test/nuget/TestModuleApp/ModuleTestHelper.h | 27 ++ test/nuget/TestModuleApp/PropertySheet.props | 7 + test/nuget/TestModuleApp/TestModuleApp.def | 3 + test/nuget/TestModuleApp/TestModuleApp.idl | 20 + .../nuget/TestModuleApp/TestModuleApp.vcxproj | 127 ++++++ test/nuget/TestModuleApp/main.cpp | 42 ++ test/nuget/TestModuleApp/pch.cpp | 1 + test/nuget/TestModuleApp/pch.h | 1 + .../TestModuleBuilder/PropertySheet.props | 7 + .../TestModuleBuilder.vcxproj | 67 ++++ test/nuget/TestModuleBuilder/pch.cpp | 1 + test/nuget/TestModuleBuilder/pch.h | 1 + test/nuget/TestModuleComponent1/Greeter.cpp | 8 + test/nuget/TestModuleComponent1/Greeter.h | 25 ++ .../TestModuleComponent1/PropertySheet.props | 7 + .../TestModuleComponent1.def | 3 + .../TestModuleComponent1.idl | 12 + .../TestModuleComponent1.vcxproj | 92 +++++ test/nuget/TestModuleComponent1/pch.cpp | 1 + test/nuget/TestModuleComponent1/pch.h | 1 + .../TestModuleComponent2/GreeterGroup.cpp | 9 + .../nuget/TestModuleComponent2/GreeterGroup.h | 36 ++ .../TestModuleComponent2/PropertySheet.props | 7 + .../TestModuleComponent2.def | 3 + .../TestModuleComponent2.idl | 10 + .../TestModuleComponent2.vcxproj | 93 +++++ test/nuget/TestModuleComponent2/pch.cpp | 1 + test/nuget/TestModuleComponent2/pch.h | 1 + .../TestModuleConsumerApp/PropertySheet.props | 7 + .../TestModuleConsumerApp.vcxproj | 76 ++++ test/nuget/TestModuleConsumerApp/main.cpp | 32 ++ test/nuget/TestModuleConsumerApp/pch.cpp | 1 + test/nuget/TestModuleConsumerApp/pch.h | 1 + test/test_cpp20_module/collections.cpp | 57 +++ test/test_cpp20_module/com_interop.cpp | 84 ++++ test/test_cpp20_module/coroutines.cpp | 58 +++ test/test_cpp20_module/format.cpp | 49 +++ test/test_cpp20_module/foundation.cpp | 68 ++++ test/test_cpp20_module/hash.cpp | 73 ++++ test/test_cpp20_module/main.cpp | 24 ++ test/test_cpp20_module/natvis.cpp | 58 +++ test/test_cpp20_module/numerics.cpp | 129 ++++++ test/test_cpp20_module/pch.cpp | 1 + test/test_cpp20_module/pch.h | 3 + test/test_cpp20_module/range_for.cpp | 135 +++++++ test/test_cpp20_module/source_location.cpp | 13 + .../test_cpp20_module.vcxproj | 112 ++++++ 111 files changed, 3146 insertions(+), 224 deletions(-) create mode 100644 .github/instructions/cppwinrt.instructions.md create mode 100644 .github/instructions/modules.instructions.md create mode 100644 docs/modules-design.md create mode 100644 nuget/modules.md create mode 100644 strings/base_detect_numerics.h create mode 100644 strings/base_include_numerics.h create mode 100644 strings/base_module_base_ixx.h create mode 100644 strings/base_module_ixx_preamble.h create mode 100644 strings/base_module_numerics_ixx.h create mode 100644 strings/base_source_location.h create mode 100644 test/nuget/TestModuleApp/CustomDependencyObject.cpp create mode 100644 test/nuget/TestModuleApp/CustomDependencyObject.h create mode 100644 test/nuget/TestModuleApp/ModuleTestHelper.cpp create mode 100644 test/nuget/TestModuleApp/ModuleTestHelper.h create mode 100644 test/nuget/TestModuleApp/PropertySheet.props create mode 100644 test/nuget/TestModuleApp/TestModuleApp.def create mode 100644 test/nuget/TestModuleApp/TestModuleApp.idl create mode 100644 test/nuget/TestModuleApp/TestModuleApp.vcxproj create mode 100644 test/nuget/TestModuleApp/main.cpp create mode 100644 test/nuget/TestModuleApp/pch.cpp create mode 100644 test/nuget/TestModuleApp/pch.h create mode 100644 test/nuget/TestModuleBuilder/PropertySheet.props create mode 100644 test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj create mode 100644 test/nuget/TestModuleBuilder/pch.cpp create mode 100644 test/nuget/TestModuleBuilder/pch.h create mode 100644 test/nuget/TestModuleComponent1/Greeter.cpp create mode 100644 test/nuget/TestModuleComponent1/Greeter.h create mode 100644 test/nuget/TestModuleComponent1/PropertySheet.props create mode 100644 test/nuget/TestModuleComponent1/TestModuleComponent1.def create mode 100644 test/nuget/TestModuleComponent1/TestModuleComponent1.idl create mode 100644 test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj create mode 100644 test/nuget/TestModuleComponent1/pch.cpp create mode 100644 test/nuget/TestModuleComponent1/pch.h create mode 100644 test/nuget/TestModuleComponent2/GreeterGroup.cpp create mode 100644 test/nuget/TestModuleComponent2/GreeterGroup.h create mode 100644 test/nuget/TestModuleComponent2/PropertySheet.props create mode 100644 test/nuget/TestModuleComponent2/TestModuleComponent2.def create mode 100644 test/nuget/TestModuleComponent2/TestModuleComponent2.idl create mode 100644 test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj create mode 100644 test/nuget/TestModuleComponent2/pch.cpp create mode 100644 test/nuget/TestModuleComponent2/pch.h create mode 100644 test/nuget/TestModuleConsumerApp/PropertySheet.props create mode 100644 test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj create mode 100644 test/nuget/TestModuleConsumerApp/main.cpp create mode 100644 test/nuget/TestModuleConsumerApp/pch.cpp create mode 100644 test/nuget/TestModuleConsumerApp/pch.h create mode 100644 test/test_cpp20_module/collections.cpp create mode 100644 test/test_cpp20_module/com_interop.cpp create mode 100644 test/test_cpp20_module/coroutines.cpp create mode 100644 test/test_cpp20_module/format.cpp create mode 100644 test/test_cpp20_module/foundation.cpp create mode 100644 test/test_cpp20_module/hash.cpp create mode 100644 test/test_cpp20_module/main.cpp create mode 100644 test/test_cpp20_module/natvis.cpp create mode 100644 test/test_cpp20_module/numerics.cpp create mode 100644 test/test_cpp20_module/pch.cpp create mode 100644 test/test_cpp20_module/pch.h create mode 100644 test/test_cpp20_module/range_for.cpp create mode 100644 test/test_cpp20_module/source_location.cpp create mode 100644 test/test_cpp20_module/test_cpp20_module.vcxproj diff --git a/.github/instructions/cppwinrt.instructions.md b/.github/instructions/cppwinrt.instructions.md new file mode 100644 index 000000000..ba5d66212 --- /dev/null +++ b/.github/instructions/cppwinrt.instructions.md @@ -0,0 +1,58 @@ +# C++/WinRT Codebase — Agent Instructions + +## Repository Structure + +- `cppwinrt/` — The cppwinrt.exe code generator (C++ source) + - `main.cpp` — CLI parsing, namespace iteration, SCC detection, .ixx orchestration + - `file_writers.h` — All file generation functions (headers, .ixx modules, component stubs) + - `code_writers.h` — Code-level writing utilities (guards, namespace wrappers, type writers) + - `type_writers.h` — Type formatting (ABI signatures, names, GUIDs) + - `component_writers.h` — Component authoring code generation + - `helpers.h` — Metadata reading helpers + - `settings.h` — Global settings populated from CLI args + - `text_writer.h` — Core text writer infrastructure +- `strings/` — String literal `.h` files embedded by the prebuild step. Changes require: delete prebuild.exe → rebuild solution +- `nuget/` — MSBuild targets, props, and NuGet packaging + - `Microsoft.Windows.CppWinRT.targets` — Main MSBuild integration (projections, module support) +- `test/` — Test projects + - `test/test_cpp20_module/` — Standalone module test (in main solution) + - `test/nuget/` — NuGet integration tests (multi-project module chain) +- `docs/` — Documentation +- `natvis/` — Visual Studio debug visualizer (includes strings/*.h in its pch.h — add new files there too) + +## Build Process + +- Use VS Developer Shell for correct toolset environment +- `cmake --build build --config Release --target cppwinrt` for cppwinrt.exe (or MSBuild: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64`) +- NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` +- Module test projects require v145 toolset (VS 2026). Directory.Build.Props sets v143 by default — override with `v145` in Configuration PropertyGroup + +## Key Patterns + +### Prebuild Embedding +The `strings/*.h` files are embedded as string literals by the prebuild step. If you modify any `strings/*.h` file, you must delete `prebuild.exe` and rebuild the entire solution for changes to take effect. + +### Module Guard Macros +- `WINRT_IMPL_BUILD_MODULE` — Defined in .ixx global fragment. Makes `WINRT_EXPORT` expand to `export extern "C++"` and suppresses `#include` of dependencies +- `WINRT_IMPORT_MODULE` — Defined by consumers who import modules. Makes namespace headers and base.h no-op (types come from module import) +- `WINRT_EXPORT` — Empty in header mode, `export extern "C++"` in module mode. Defined in `winrt/base_macros.h` +- `WINRT_IMPL_STD_EXPORT` — Empty in header mode, `extern "C++"` (without export) in module mode. Used for `namespace std` specializations + +### Generated Header Structure +Each namespace produces four header files: +- `impl/.0.h` — Forward declarations, ABIs, GUIDs, categories +- `impl/.1.h` — Interface definitions +- `impl/.2.h` — Delegates, structs, class implementations +- `.h` — Public API surface (consume definitions, class wrappers, operators) + +### Dependency Collection +When generating headers with `-modules`, writer.depends is inspected after each header to build a namespace dependency graph. This graph drives SCC detection and module import lists. + +## Common Gotchas + +- Module IFCs are NOT compatible across toolset versions — always clean rebuild when switching +- PCH and modules can coexist but PCH should NOT include winrt headers when using modules +- `/ifcSearchDir` works for the module dependency scanner to find IFCs, but cross-component modules may need explicit `/reference "name=path.ifc"` flags +- `import std;` requires `BuildStlModules=true` +- `strings/base_macros.h` is the single source of truth for shared macros (generated as `winrt/base_macros.h`). New macros go in `base_macros.h` only +- When adding, removing, or heavily refactoring `strings/*.h` files, always rebuild the natvis project (`natvis/cppwinrtvisualizer.sln`) to verify — it includes strings/*.h directly in its pch.h diff --git a/.github/instructions/modules.instructions.md b/.github/instructions/modules.instructions.md new file mode 100644 index 000000000..3deee2955 --- /dev/null +++ b/.github/instructions/modules.instructions.md @@ -0,0 +1,40 @@ +# C++/WinRT Modules — Agent Instructions + +## Module Architecture (v2 — Per-Namespace) + +Each WinRT namespace gets its own C++20 named module (`winrt.`). Base infrastructure is in `winrt_base` and `winrt_numerics`. + +### Code Generator Flow + +1. `-modules` flag enables .ixx generation in cppwinrt.exe +2. `-module_include`/`-module_exclude` filter which namespaces get modules +3. Headers are generated with dependency tracking (deps_ptr parameter) +4. Tarjan's SCC algorithm detects cyclic namespace groups +5. Standalone namespaces get individual .ixx; cyclic groups get consolidated SCC owner + re-export stubs + +### MSBuild Flow + +1. `CppWinRTBuildModule=true` adds `-modules` to cppwinrt.exe invocations +2. `CppWinRTAddModuleInterfaces` discovers `$(GeneratedFilesDir)winrt\*.ixx` and adds to ClCompile +3. `CppWinRTConsumeModule` metadata on ProjectReference controls per-reference IFC sharing +4. `CppWinRTResolveModuleReferences` calls `CppWinRTGetModuleOutputs` on tagged references +5. Platform projection suppresses `-modules` when consuming pre-built IFCs + +### Critical Invariants + +- Module guards are unconditional in codegen — `-modules` controls .ixx generation and component codegen (module.g.cpp, stub .cpp) +- SCC owner is alphabetically first namespace in the cycle +- All .ixx filenames use `winrt` prefix: `winrt.Windows.Foundation.ixx`, `winrt_base.ixx` +- Shared macros live in `strings/base_module.h` → generates `winrt/macros.h`. `base_macros.h` includes it via `#include "winrt/macros.h"` + +### Testing Changes + +After modifying cppwinrt.exe code: +1. Rebuild cppwinrt.exe: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64` +2. Run standalone test: build `test_cpp20_module` in main solution +3. Run NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` + +After modifying targets: +1. Clean NuGet test obj dirs +2. Build with `/v:normal` and check "Module providers:" diagnostic messages +3. Inspect `.rsp` files in `obj/` to verify correct `-modules` flag placement diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d660400a0..6c2a04353 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -379,6 +379,15 @@ jobs: $target_platform = "${{ matrix.arch }}" & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose + - name: Remove module test projects on v143 + if: matrix.toolchain.platform_toolset == 'v143' + run: | + # Module test projects require v145 toolset + mv test\nuget\NugetTest.sln test\nuget\NugetTest.sln.orig + Get-Content test\nuget\NugetTest.sln.orig | + Where-Object { -not ($_ -match 'TestModule') } | + Set-Content test\nuget\NugetTest.sln + - name: Run nuget test run: | cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" test\nuget\NugetTest.sln diff --git a/cppwinrt.sln b/cppwinrt.sln index 3bcfb33bc..700e9f5ea 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -124,6 +124,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nocoro", "test\test_no {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_module", "test\test_cpp20_module\test_cpp20_module.vcxproj", "{B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}" ProjectSection(SolutionItems) = preProject build_nuget.cmd = build_nuget.cmd @@ -411,6 +416,18 @@ Global {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.Build.0 = Release|x64 {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.ActiveCfg = Release|Win32 {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.Build.0 = Release|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|ARM64.Build.0 = Debug|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x64.ActiveCfg = Debug|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x64.Build.0 = Debug|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x86.ActiveCfg = Debug|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x86.Build.0 = Debug|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|ARM64.ActiveCfg = Release|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|ARM64.Build.0 = Release|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x64.ActiveCfg = Release|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x64.Build.0 = Release|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x86.ActiveCfg = Release|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -435,6 +452,7 @@ Global {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {9E392830-805A-4AAF-932D-C493143EFACA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index fc5081bef..ab119ae89 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -5,9 +5,9 @@ namespace cppwinrt struct finish_with { writer& w; - void (*finisher)(writer&); + std::function finisher; - finish_with(writer& w, void (*finisher)(writer&)) : w(w), finisher(finisher) {} + finish_with(writer& w, std::function finisher) : w(w), finisher(std::move(finisher)) {} finish_with(finish_with const&)= delete; void operator=(finish_with const&) = delete; @@ -35,6 +35,35 @@ namespace cppwinrt } } + static void write_endif(writer& w, std::string_view macro = {}) + { + if (macro.empty()) + { + w.write("#endif\n"); + } + else + { + w.write("#endif // %\n", macro); + } + } + + // When modules are enabled, wraps a block of #include directives in + // #ifndef WINRT_IMPL_BUILD_MODULE ... #endif so that in module builds (where + // WINRT_IMPL_BUILD_MODULE is defined in the global module fragment), textual + // includes are suppressed — dependencies come via import instead. + [[nodiscard]] static finish_with wrap_module_aware_includes_guard(writer& w, bool modules_enabled) + { + if (modules_enabled) + { + w.write("#ifndef WINRT_IMPL_BUILD_MODULE\n"); + return { w, [](writer& w) { write_endif(w, "WINRT_IMPL_BUILD_MODULE"); } }; + } + else + { + return { w, write_nothing }; + } + } + static void write_version_assert(writer& w) { w.write_root_include("base"); @@ -52,14 +81,6 @@ namespace cppwinrt w.write(format); } - static void write_endif(writer& w) - { - auto format = R"(#endif -)"; - - w.write(format); - } - static void write_close_file_guard(writer& w) { write_endif(w); @@ -105,7 +126,7 @@ namespace cppwinrt w.write(format); - return { w, write_endif }; + return { w, [](writer& w) { write_endif(w, "WINRT_LEAN_AND_MEAN"); } }; } else { @@ -120,7 +141,17 @@ namespace cppwinrt w.write(format, macro); - return { w, write_endif }; + return { w, [macro = std::string(macro)](writer& w) { write_endif(w, macro); } }; + } + + [[nodiscard]] static finish_with wrap_ifndef(writer& w, std::string_view macro) + { + auto format = R"(#ifndef % +)"; + + w.write(format, macro); + + return { w, [macro = std::string(macro)](writer& w) { write_endif(w, macro); } }; } static void write_parent_depends(writer& w, cache const& c, std::string_view const& type_namespace) @@ -166,7 +197,7 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_impl_namespace(writer& w) { - auto format = R"(namespace winrt::impl + auto format = R"(WINRT_EXPORT namespace winrt::impl { )"; diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 3966cad6c..af5626d14 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -136,7 +136,10 @@ namespace cppwinrt static void write_module_g_cpp(writer& w, std::vector const& classes) { - w.write_root_include("base"); + if (!settings.modules) + { + w.write_root_include("base"); + } auto format = R"(% bool __stdcall %_can_unload_now() noexcept { diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index ed9386b4e..fd9833cb1 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -9,9 +9,16 @@ namespace cppwinrt w.write(strings::base_version_odr, CPPWINRT_VERSION_STRING); { auto wrap_file_guard = wrap_open_file_guard(w, "BASE"); + auto wrap_import = wrap_ifndef(w, "WINRT_IMPORT_MODULE"); - w.write(strings::base_includes); - w.write(strings::base_macros); + { + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + w.write(strings::base_includes); + w.write(strings::base_detect_numerics); + w.write(strings::base_include_numerics); + } + w.write_root_include("base_macros"); + w.write(strings::base_source_location); w.write(strings::base_types); w.write(strings::base_extern); w.write(strings::base_meta); @@ -65,7 +72,15 @@ namespace cppwinrt w.flush_to_file(settings.output_folder + "winrt/fast_forward.h"); } - static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members) + static void collect_writer_deps(writer const& w, std::set& out) + { + for (auto&& [dep_ns, _] : w.depends) + { + out.insert(std::string(dep_ns)); + } + } + + static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -118,10 +133,11 @@ namespace cppwinrt w.write_each(depends.second); } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('0'); } - static void write_namespace_1_h(std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_1_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -137,16 +153,20 @@ namespace cppwinrt write_preamble(w); write_open_file_guard(w, ns, '1'); - for (auto&& depends : w.depends) { - w.write_depends(depends.first, '0'); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, '0'); + } - w.write_depends(w.type_namespace, '0'); + w.write_depends(w.type_namespace, '0'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('1'); } - static void write_namespace_2_h(std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_2_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -167,16 +187,20 @@ namespace cppwinrt char const impl = promote ? '2' : '1'; - for (auto&& depends : w.depends) { - w.write_depends(depends.first, impl); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, impl); + } - w.write_depends(w.type_namespace, '1'); + w.write_depends(w.type_namespace, '1'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('2'); } - static void write_namespace_h(cache const& c, std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_h(cache const& c, std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -216,18 +240,28 @@ namespace cppwinrt write_namespace_special(w, ns); write_close_file_guard(w); + // The #ifndef WINRT_IMPORT_MODULE / #endif pair spans across w.swap(). + // The body is written first (above), then swap() prepends the header prefix (below). + // In the final output, #ifndef opens before the includes and #endif closes after + // the file guard, mirroring the write_open_file_guard / write_close_file_guard pair. + w.write("#endif // WINRT_IMPORT_MODULE\n"); w.swap(); write_preamble(w); write_open_file_guard(w, ns); - write_version_assert(w); - write_parent_depends(w, c, ns); - - for (auto&& depends : w.depends) + w.write("#ifndef WINRT_IMPORT_MODULE\n\n"); { - w.write_depends(depends.first, '2'); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + write_version_assert(w); + write_parent_depends(w, c, ns); - w.write_depends(w.type_namespace, '2'); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, '2'); + } + + w.write_depends(w.type_namespace, '2'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header(); } @@ -236,6 +270,28 @@ namespace cppwinrt writer w; write_preamble(w); write_pch(w); + + if (settings.modules) + { + // In module builds, import std and winrt_base instead of #include "winrt/base.h". + // std is needed for std::wstring_view, std::equal, std::int32_t used in + // the activation factory lookup code. + w.write("\nimport std;\n"); + w.write("import winrt_base;\n"); + + // Collect all unique namespaces from the component classes + std::set namespaces; + for (auto&& type : classes) + { + namespaces.insert(std::string(type.TypeNamespace())); + } + for (auto&& ns : namespaces) + { + w.write("import winrt.%;\n", ns); + } + w.write("\n"); + } + write_module_g_cpp(w, classes); w.flush_to_file(settings.output_folder + "module.g.cpp"); } @@ -250,9 +306,19 @@ namespace cppwinrt write_preamble(w); write_include_guard(w); - for (auto&& depends : w.depends) { - w.write_depends(depends.first); + auto wrap = wrap_ifdef(w, "WINRT_IMPORT_MODULE"); + w.write_root_include("base_macros"); + for (auto&& depends : w.depends) + { + w.write("import winrt.%;\n", depends.first); + } + w.write("#else // WINRT_IMPORT_MODULE\n"); + + for (auto&& depends : w.depends) + { + w.write_depends(depends.first); + } } auto filename = settings.output_folder + get_generated_component_filename(type) + ".g.h"; @@ -316,7 +382,269 @@ namespace cppwinrt writer w; write_pch(w); + + if (settings.modules) + { + // The .g.h handles its own imports, but the implementation .h + // needs the types available in scope, so we import them here. + writer dep_scanner; + dep_scanner.add_depends(type); + write_component_g_h(dep_scanner, type); + + w.write("\n#define WINRT_IMPORT_MODULE\n"); + for (auto&& depends : dep_scanner.depends) + { + w.write("import winrt.%;\n", depends.first); + } + w.write("\n"); + } + write_component_cpp(w, type); w.flush_to_file(path); } + + // --- Per-namespace C++20 module interface unit (.ixx) writers --- + + // Emits the common global module fragment used by all generated .ixx files. + // Defines WINRT_IMPL_BUILD_MODULE so generated headers switch WINRT_EXPORT + // to 'export extern "C++"' and suppress textual #includes of dependencies + // (dependencies arrive via module imports instead). + // Includes minimal headers needed for macros, intrinsics, and debug assertions. + static void write_module_preamble(writer& w) + { + write_preamble(w); + w.write(strings::base_module_ixx_preamble); + w.write_root_include("base_macros"); + } + + // Emits $(out)/winrt/base_macros.h + // This header provides the core macros shared between header and module builds. + // In header builds, base.h includes base_macros.h inline (via the prebuild-embedded string). + // In module builds, each .ixx file includes this in its global module fragment. + static void write_macros_h() + { + writer w; + write_preamble(w); + w.write(strings::base_macros, CPPWINRT_VERSION_STRING); + w.flush_to_file(settings.output_folder + "winrt/base_macros.h"); + } + + static void write_base_ixx() + { + writer w; + write_module_preamble(w); + w.write(strings::base_module_base_ixx); + w.write(strings::base_detect_numerics); + w.write("\n"); + w.write_root_include("base"); + w.flush_to_file(settings.output_folder + "winrt/winrt_base.ixx"); + } + + static void write_numerics_ixx() + { + writer w; + write_module_preamble(w); + // GMF: detect numerics and pre-include directxmath so it's not pulled + // into the module purview by windowsnumerics.impl.h + w.write(strings::base_detect_numerics); + { + auto wrap = wrap_ifdef(w, "WINRT_IMPL_NUMERICS"); + w.write("#include \n"); + } + w.write(strings::base_module_numerics_ixx); + // Module declaration + w.write("\nexport module winrt_numerics;\n"); + // Include windowsnumerics.impl.h in the module purview (exports the types). + // directxmath.h is already included in the GMF above, so the #include inside + // base_include_numerics is a no-op (header guard). + { + auto wrap = wrap_ifdef(w, "_MSC_VER"); + w.write("#pragma warning(push)\n"); + w.write("#pragma warning(disable : 5244)\n"); + } + w.write(strings::base_include_numerics); + { + auto wrap = wrap_ifdef(w, "_MSC_VER"); + w.write("#pragma warning(pop)\n"); + } + w.flush_to_file(settings.output_folder + "winrt/winrt_numerics.ixx"); + } + + // Emits a per-namespace module interface unit for namespaces that are NOT + // part of a dependency cycle (standalone module). + // Output: $(out)/winrt/winrt..ixx (export module winrt.;) + // + // The generated .ixx: + // 1. Starts with the global module fragment (WINRT_IMPL_BUILD_MODULE, minimal includes) + // 2. Declares 'export module winrt.;' + // 3. Imports std and re-exports winrt_base + // 4. Imports each dependent namespace module (computed from type references in headers) + // 5. Includes the impl headers (*.0.h, *.1.h, *.2.h) and public header (.h) + // in the module purview, where WINRT_EXPORT causes declarations to be exported + static void write_namespace_ixx( + std::string_view const& ns, + std::set const& deps) + { + writer w; + write_module_preamble(w); + + // Module declaration + w.write("export module winrt.%;\n\n", ns); + + // Document dependencies + w.write("// Module dependencies:\n"); + w.write("// - std\n"); + w.write("// - winrt_base (re-exported)\n"); + if (deps.empty()) + { + w.write("// - (no additional namespace imports)\n"); + } + else + { + for (auto& dep : deps) + { + w.write("// - winrt.%\n", dep); + } + } + w.write("\n"); + + // Import std and base + w.write("import std;\n"); + w.write("export import winrt_base;\n"); + + // Import dependency namespace modules + for (auto& dep : deps) + { + w.write("import winrt.%;\n", dep); + } + + // Version mismatch check: ensure this namespace module was generated by the + // same version of cppwinrt.exe as the winrt_base module it imports. + // winrt::cppwinrt_version is exported from winrt_base; CPPWINRT_VERSION is + // the macro from this module's own base_macros.h in the global module fragment. + w.write("\nstatic_assert(winrt::check_version(winrt::cppwinrt_version, CPPWINRT_VERSION), \"Mismatched C++/WinRT headers.\");\n\n"); + + // Include namespace headers in module purview + w.write_depends(ns, '0'); + w.write_depends(ns, '1'); + w.write_depends(ns, '2'); + w.write_root_include(ns); + + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(ns) + ".ixx"); + } + + // Emits the SCC (Strongly Connected Component) owner module interface unit. + // When multiple namespaces form a dependency cycle, they cannot each have their + // own independent module (circular imports are illegal in C++20 modules). + // Instead, one namespace is chosen as the "owner" (alphabetically first in the SCC), + // and ALL cyclic namespaces' declarations are consolidated into this single module. + // The other namespaces in the SCC get thin re-export stubs (see write_namespace_reexport_ixx). + // + // Output: $(out)/winrt/winrt..ixx (export module winrt.;) + // + // The owner module: + // 1. Imports external dependencies (deps outside the SCC) + // 2. Forward-declares all projected types for ALL SCC namespaces before any + // impl headers — this breaks the type reference cycles + // 3. Includes impl headers in stable phase order: all *.0.h, then all *.1.h, + // then all *.2.h, then all public headers — preserving the original header + // layering while keeping SCC compilation deterministic + static void write_namespace_scc_owner_ixx( + cache const& c, + std::string_view const& owner, + std::vector const& scc_members, + std::set const& external_deps) + { + writer w; + write_module_preamble(w); + + // Module declaration (owner namespace) + w.write("// This module is an SCC owner (cycle breaker). The following namespaces\n"); + w.write("// form a dependency cycle and are consolidated into this single module:\n"); + for (auto& ns : scc_members) + { + w.write("// - %\n", ns); + } + w.write("// Other SCC namespaces are emitted as re-export stubs.\n\n"); + w.write("export module winrt.%;\n\n", owner); + + // Import std and base + w.write("import std;\n"); + w.write("export import winrt_base;\n"); + + // Import external dependency modules (outside the SCC) + for (auto& dep : external_deps) + { + w.write("import winrt.%;\n", dep); + } + + // Version mismatch check: ensure this namespace module was generated by the + // same version of cppwinrt.exe as the winrt_base module it imports. + // winrt::cppwinrt_version is exported from winrt_base; CPPWINRT_VERSION is + // the macro from this module's own base_macros.h in the global module fragment. + w.write("\nstatic_assert(winrt::check_version(winrt::cppwinrt_version, CPPWINRT_VERSION), \"Mismatched C++/WinRT headers.\");\n"); + + // Forward declarations for all projected types in this SCC. + // This is required because SCC members have cyclic type references, + // and generated headers suppress dependent #includes when WINRT_IMPL_BUILD_MODULE + // is defined. Forward declarations provide the names needed before definitions. + for (auto& ns : scc_members) + { + auto found = c.namespaces().find(ns); + if (found == c.namespaces().end()) + { + continue; + } + auto& members = found->second; + + auto wrap_type = wrap_type_namespace(w, ns); + w.write_each(members.enums); + w.write_each(members.interfaces); + w.write_each(members.classes); + w.write_each(members.structs); + w.write_each(members.delegates); + w.write_each(members.contracts); + } + + // Include all SCC members' headers in stable phase order. + // All *.0.h (forward decls + ABIs), then all *.1.h (interfaces), + // then all *.2.h (delegates/structs/classes), then all public headers. + // This preserves the original header layering while keeping compilation deterministic. + for (auto& ns : scc_members) + { + w.write_depends(ns, '0'); + } + for (auto& ns : scc_members) + { + w.write_depends(ns, '1'); + } + for (auto& ns : scc_members) + { + w.write_depends(ns, '2'); + } + for (auto& ns : scc_members) + { + w.write_root_include(ns); + } + + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(owner) + ".ixx"); + } + + // Emits a thin re-export stub module for SCC non-owner namespaces. + // This allows 'import winrt.;' to work even though the actual declarations + // live in the SCC owner module. The stub simply re-exports the owner. + // Output: $(out)/winrt/winrt..ixx (export module winrt.; export import winrt.;) + static void write_namespace_reexport_ixx( + std::string_view const& ns, + std::string_view const& owner) + { + writer w; + write_preamble(w); + w.write("\n// NOTE: This module does not define declarations of its own.\n"); + w.write("// It re-exports all declarations from the 'winrt.%' module. This is used to break cycles in the\n", owner); + w.write("// WinRT namespace module dependency graph (SCC owner consolidation).\n\n"); + w.write("export module winrt.%;\n", ns); + w.write("export import winrt.%;\n", owner); + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(ns) + ".ixx"); + } } diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 70a55b076..33bb9248e 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include +#include #include "strings.h" #include "settings.h" #include "type_writers.h" @@ -39,6 +40,9 @@ namespace cppwinrt { "fastabi", 0, 0 }, // Enable support for the Fast ABI { "ignore_velocity", 0, 0 }, // Ignore feature staging metadata and always include implementations { "synchronous", 0, 0 }, // Instructs cppwinrt to run on a single thread to avoid file system issues in batch builds + { "modules", 0, 0, {}, "Generate per-namespace C++20 module interface units (.ixx)" }, + { "module_include", 0, option::no_max, "", "Filter which namespaces are included in module .ixx generation" }, + { "module_exclude", 0, option::no_max, "", "Filter which namespaces are excluded from module .ixx generation" }, }; static void print_usage(writer& w) @@ -85,6 +89,7 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder { settings.verbose = args.exists("verbose"); settings.fastabi = args.exists("fastabi"); + settings.modules = args.exists("modules"); settings.input = args.files("input", database::is_database); settings.reference = args.files("reference", database::is_database); @@ -92,6 +97,15 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder settings.component = args.exists("component"); settings.base = args.exists("base"); + for (auto&& ns : args.values("module_include")) + { + settings.module_include.insert(ns); + } + for (auto&& ns : args.values("module_exclude")) + { + settings.module_exclude.insert(ns); + } + settings.license = args.exists("license"); settings.brackets = args.exists("brackets"); @@ -199,6 +213,13 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder static void build_filters(cache const& c) { + // Build module_filter from -module_include / -module_exclude args. + // This controls which namespaces get .ixx files without affecting header generation. + if (!settings.module_include.empty() || !settings.module_exclude.empty()) + { + settings.module_filter = { settings.module_include, settings.module_exclude }; + } + if (settings.reference.empty()) { return; @@ -281,6 +302,79 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder c.remove_type("Windows.Foundation.Numerics", "Vector4"); } + // Tarjan's algorithm for finding strongly connected components in the + // namespace dependency graph. Namespaces in an SCC have cyclic deps and + // must be combined into a single module. + static std::vector> find_sccs( + std::map, std::less<>> const& graph) + { + struct context + { + std::map index_of; + std::map lowlink; + std::map on_stack; + std::vector stack; + int next_index = 0; + std::vector> result; + + void strongconnect(std::string const& v, + std::map, std::less<>> const& g) + { + index_of[v] = next_index; + lowlink[v] = next_index; + next_index++; + stack.push_back(v); + on_stack[v] = true; + + auto it = g.find(v); + if (it != g.end()) + { + for (auto& w : it->second) + { + if (g.find(w) == g.end()) + { + continue; // dep not in graph (not a projected namespace) + } + + if (index_of.find(w) == index_of.end()) + { + strongconnect(w, g); + lowlink[v] = (std::min)(lowlink[v], lowlink[w]); + } + else if (on_stack[w]) + { + lowlink[v] = (std::min)(lowlink[v], index_of[w]); + } + } + } + + if (lowlink[v] == index_of[v]) + { + std::vector scc; + std::string w; + do + { + w = stack.back(); + stack.pop_back(); + on_stack[w] = false; + scc.push_back(std::move(w)); + } while (scc.back() != v); + result.push_back(std::move(scc)); + } + } + }; + + context ctx; + for (auto& [node, _] : graph) + { + if (ctx.index_of.find(node) == ctx.index_of.end()) + { + ctx.strongconnect(node, graph); + } + } + return std::move(ctx.result); + } + static int run(int const argc, char** argv) { int result{}; @@ -342,11 +436,30 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder w.flush_to_console(); task_group group; group.synchronous(args.exists("synchronous")); - writer ixx; - write_preamble(ixx); - ixx.write("module;\n"); - ixx.write(strings::base_includes); - ixx.write("\nexport module winrt;\n#define WINRT_EXPORT export\n\n"); + + // Dependency collection for per-namespace modules (v2) + std::map, std::less<>> ns_deps_map; + std::set projected_namespaces; + std::mutex ns_deps_mutex; + + // First pass: determine which namespaces will be in the module. + // This includes namespaces from this invocation AND those from other invocations + // (e.g., platform namespaces when building a component). The module_filter + // tells us which namespaces have modules across all invocations. + if (settings.modules) + { + for (auto&& [ns, members] : c.namespaces()) + { + if (!has_projected_types(members)) + { + continue; + } + if (settings.module_filter.empty() || settings.module_filter.includes(members)) + { + projected_namespaces.insert(std::string(ns)); + } + } + } for (auto&&[ns, members] : c.namespaces()) { @@ -355,21 +468,29 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder continue; } - ixx.write("#include \"winrt/%.h\"\n", ns); - group.add([&, &ns = ns, &members = members] { - write_namespace_0_h(ns, members); - write_namespace_1_h(ns, members); - write_namespace_2_h(ns, members); - write_namespace_h(c, ns, members); + bool in_module = projected_namespaces.count(std::string(ns)) > 0; + std::set ns_deps; + auto* deps_ptr = (settings.modules && in_module) ? &ns_deps : nullptr; + + write_namespace_0_h(ns, members, deps_ptr); + write_namespace_1_h(ns, members, deps_ptr); + write_namespace_2_h(ns, members, deps_ptr); + write_namespace_h(c, ns, members, deps_ptr); + + if (settings.modules && in_module) + { + std::lock_guard lock(ns_deps_mutex); + ns_deps_map[std::string(ns)] = std::move(ns_deps); + } }); } if (settings.base) { write_base_h(); - ixx.flush_to_file(settings.output_folder + "winrt/winrt.ixx"); + write_macros_h(); } if (settings.component) @@ -404,6 +525,64 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder group.get(); + // Generate per-namespace module interface files (.ixx) + // + // Each projected namespace gets its own C++20 named module (winrt.). + // Namespaces that form dependency cycles are detected using Tarjan's SCC algorithm + // and consolidated: one namespace "owns" the SCC module (containing all declarations), + // while others get thin re-export stubs so 'import winrt.;' always works. + // + // Base infrastructure modules (winrt_base, winrt_numerics) are only generated + // for platform projection builds (-base flag). + if (settings.modules) + { + if (settings.base) + { + write_numerics_ixx(); + write_base_ixx(); + } + + // Tarjan's SCC algorithm for cyclic namespace dependencies + auto sccs = find_sccs(ns_deps_map); + + for (auto& scc : sccs) + { + if (scc.size() == 1) + { + // Standalone namespace module + auto& ns = scc[0]; + write_namespace_ixx(ns, ns_deps_map[ns]); + } + else + { + // SCC: choose owner (alphabetically first), others re-export + std::sort(scc.begin(), scc.end()); + auto& owner = scc[0]; + + // External deps = union of all SCC members' deps, minus SCC members themselves + std::set external_deps; + std::set scc_set(scc.begin(), scc.end()); + for (auto& ns : scc) + { + for (auto& dep : ns_deps_map[ns]) + { + if (!scc_set.count(dep)) + { + external_deps.insert(dep); + } + } + } + + write_namespace_scc_owner_ixx(c, owner, scc, external_deps); + + for (size_t i = 1; i < scc.size(); ++i) + { + write_namespace_reexport_ixx(scc[i], owner); + } + } + } + } + if (settings.verbose) { w.write(" time: %ms\n", get_elapsed_time(start)); diff --git a/cppwinrt/settings.h b/cppwinrt/settings.h index e07df4ea2..110e64917 100644 --- a/cppwinrt/settings.h +++ b/cppwinrt/settings.h @@ -31,6 +31,12 @@ namespace cppwinrt bool fastabi{}; std::map fastabi_cache; + + bool modules{}; // Generate per-namespace C++20 module interface units (.ixx) + + std::set module_include; + std::set module_exclude; + winmd::reader::filter module_filter; }; extern settings_type settings; diff --git a/docs/modules-design.md b/docs/modules-design.md new file mode 100644 index 000000000..8327231a7 --- /dev/null +++ b/docs/modules-design.md @@ -0,0 +1,190 @@ +# C++/WinRT Per-Namespace Modules: Design & Internals + +This document describes the design and implementation of per-namespace C++20 module support in C++/WinRT. It is intended for cppwinrt maintainers and contributors. + +## Architecture Overview + +The module system generates one C++20 named module per WinRT namespace. Each module encapsulates the same content as the traditional header files but exports declarations via `WINRT_EXPORT` in module purview. + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ winrt_numerics.ixx ── export module winrt_numerics; │ +│ winrt_base.ixx ── export module winrt_base; │ +│ export import winrt_numerics; │ +│ winrt.Windows.Foundation.ixx │ +│ ── export module winrt.Windows.Foundation; │ +│ import std; export import winrt_base; │ +│ import winrt.Windows.Foundation.Collections; │ +│ #include "winrt/impl/Windows.Foundation.0.h" │ +│ ... │ +│ #include "winrt/Windows.Foundation.h" │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Key Design Decisions + +### Unconditional Guards + +Module guards (`WINRT_IMPL_BUILD_MODULE`, `WINRT_IMPORT_MODULE`) are emitted unconditionally in generated projection headers — they are always present regardless of whether `-modules` was passed to cppwinrt.exe. The `-modules` flag controls `.ixx` generation and whether generated component files (`module.g.cpp`, stub `.cpp`) use module imports. This means: + +- Projection headers generated without `-modules` still work correctly when later compiled inside a module interface unit +- No regeneration of projection headers needed when switching between header and module consumption + +### WINRT_EXPORT Macro + +`WINRT_EXPORT` is defined in `base_macros.h` (generated as `winrt/base_macros.h`): +- When `WINRT_IMPL_BUILD_MODULE` is defined (inside `.ixx` compilation): `export extern "C++"` +- Otherwise (header mode): empty + +All `namespace winrt::impl` and `namespace std` blocks use `WINRT_EXPORT` so they export correctly from modules. The `extern "C++"` wrapping enables include-before-import compatibility (same technique as MSVC STL). + +### Per-Namespace vs Monolithic + +Unlike the v1 approach (single `import winrt;`), v2 generates one module per namespace. This provides: + +- **Finer granularity**: Import only what you need +- **Better parallelism**: Independent modules compile in parallel +- **Component module support**: Component namespaces get their own modules + +The trade-off is handling dependency cycles between namespaces (see SCC below). + +This is enforced via the MSBuild `CppWinRTConsumeModule` metadata on ProjectReference — it only points at the platform module builder, not at component projects. + +## Code Generator Pipeline + +### Entry Point: `main.cpp` + +1. **Namespace enumeration**: First pass determines which namespaces are module-eligible using `module_filter` (from `-module_include`/`-module_exclude`) + +2. **Header generation**: Standard header generation with optional dependency collection. When `-modules` is active and a namespace is in the module, `write_namespace_*_h()` functions populate `ns_deps` sets via the `deps_ptr` parameter + +3. **Dependency graph construction**: After all headers are generated, `ns_deps_map` contains the full namespace dependency graph + +4. **SCC detection**: Tarjan's algorithm (`find_sccs()`) identifies strongly-connected components + +5. **Module generation**: For each SCC: + - Size 1: `write_namespace_ixx()` — standalone module + - Size > 1: `write_namespace_scc_owner_ixx()` for the owner (alphabetically first) + `write_namespace_reexport_ixx()` for others + +### CLI Options + +| Flag | Description | +|-|-| +| `-modules` | Enable `.ixx` generation | +| `-module_include ...` | Only generate modules for these namespace prefixes | +| `-module_exclude ...` | Skip these namespace prefixes | + +The `module_filter` is populated from these flags and checked against ALL cache namespaces (not just the projection filter). This is important for component builds where the platform namespaces are not being projected but their modules exist from a prior builder invocation. + +### Generated Files + +| File | When Generated | Purpose | +|-|-|-| +| `winrt/base_macros.h` | Always with `-base` | Macros for module builds (WINRT_EXPORT, etc.) | +| `winrt/winrt_base.ixx` | `-modules -base` | Core types module | +| `winrt/winrt_numerics.ixx` | `-modules -base` | Numerics module | +| `winrt/winrt..ixx` | `-modules` | Per-namespace module | + +## SCC (Strongly Connected Components) + +### The Problem + +WinRT namespaces have cyclic dependencies. For example: +- `Windows.Foundation` depends on `Windows.Foundation.Collections` (via `IVector`, `IMap`, etc.) +- `Windows.Foundation.Collections` depends on `Windows.Foundation` (via `IAsyncOperation`, `Uri`, etc.) + +C++20 modules cannot have circular imports. If module A imports module B, then module B cannot import module A. + +### The Solution: SCC Consolidation + +Tarjan's algorithm identifies groups of namespaces that form dependency cycles. These groups (SCCs) are consolidated: + +1. **Owner selection**: The alphabetically first namespace in the SCC becomes the "owner" +2. **Owner module**: Contains ALL declarations from ALL SCC namespaces. Forward-declares all types first, then includes headers in phase order (all `*.0.h`, then `*.1.h`, then `*.2.h`, then public headers) +3. **Re-export stubs**: Other SCC members get thin `.ixx` files that just re-export the owner module + +This means `import winrt.Windows.Foundation;` and `import winrt.Windows.Foundation.Collections;` both work — they resolve to the same underlying module. + +### Example Generated Files + +**Owner** (`winrt.Windows.Foundation.ixx`): +```cpp +module; +#define WINRT_IMPL_BUILD_MODULE +#include "winrt/base_macros.h" +// ... + +// This module is an SCC owner (cycle breaker). The following namespaces +// form a dependency cycle and are consolidated into this single module: +// - Windows.Foundation +// - Windows.Foundation.Collections +// Other SCC namespaces are emitted as re-export stubs. + +export module winrt.Windows.Foundation; + +import std; +export import winrt_base; + +// Forward declarations for all SCC namespaces... +// #include all impl headers in phase order... +``` + +**Re-export stub** (`winrt.Windows.Foundation.Collections.ixx`): +```cpp +// NOTE: This module does not define declarations of its own. +// It re-exports all declarations from the 'winrt.Windows.Foundation' module. +export module winrt.Windows.Foundation.Collections; +export import winrt.Windows.Foundation; +``` + +## MSBuild Integration + +### Targets Flow + +``` +CppWinRTResolveModuleReferences (resolves IFC paths from ProjectReference metadata) + ↓ +CppWinRTMakePlatformProjection (generates headers + .ixx for platform types) +CppWinRTMakeReferenceProjection (generates headers + .ixx for referenced WinMDs) +CppWinRTMakeComponentProjection (generates headers + .ixx for component types) + ↓ +CppWinRTAddModuleInterfaces (discovers .ixx files, adds to ClCompile items) + ↓ +FixupCLCompileOptions (MSVC module dependency scanner processes .ixx) + ↓ +ClCompile (compiles .ixx → .ifc + .obj) +``` + +### Key Properties + +- `CppWinRTBuildModule`: Enables `-modules` for all three projections (platform, reference, component), causing `.ixx` generation and compilation. +- `CppWinRTConsumeModule` (ProjectReference metadata): Per-reference opt-in for IFC consumption. When set, suppresses `-modules` on the platform projection so the consumer uses pre-built IFCs from the referenced project instead of generating its own. +- `_CppWinRTConsumesPlatformModules`: Internal property set by `CppWinRTResolveModuleReferences` when any ProjectReference has `CppWinRTConsumeModule=true`. Controls whether the platform projection receives `-modules`. + +### Cross-Project IFC Resolution + +MSVC's module dependency scanner uses `/ifcSearchDir` for within-project module resolution. For cross-project modules, the scanner generates explicit `/reference "module.name=path.ifc"` entries based on the dependency scan results. The `/ifcSearchDir` pointing to the builder's `$(IntDir)` allows the scanner to find the pre-built IFCs. + +## Dependency Collection + +During header generation, when `-modules` is active, each `write_namespace_*_h()` function receives a `deps_ptr` parameter. The writer's `w.depends` map is inspected to find referenced namespaces. Only namespaces that: +1. Exist in the cache +2. Have projected types +3. Are in the module namespace set (or set is empty) + +are added to the dependency set. Self-references are excluded. The union of dependencies from all four header files (`*.0.h`, `*.1.h`, `*.2.h`, `.h`) gives the complete dependency set for a namespace module. + +## Testing + +### test/test_cpp20_module/ (in-repo) + +Standalone test built by the main solution. Uses a PreBuildEvent to run cppwinrt.exe with `-modules -base -module_include "Windows.Foundation"`. Tests URI, events, collections, and coroutines. + +### test/nuget/ (NuGet integration) + +Multi-project solution: +- **TestModuleBuilder**: Static library that pre-builds platform modules +- **TestModuleComponent1**: Component DLL (Greeter class), consumes builder's modules +- **TestModuleComponent2**: Component DLL (GreeterGroup), depends on Component1 +- **TestModuleConsumerApp**: Console app, consumes builder + both components +- **TestModuleApp**: Single-project that builds and consumes its own modules diff --git a/natvis/pch.h b/natvis/pch.h index 95e561971..3de6807b3 100644 --- a/natvis/pch.h +++ b/natvis/pch.h @@ -12,6 +12,7 @@ #include #include "base_includes.h" #include "base_macros.h" +#include "base_source_location.h" #include "base_types.h" #include "base_extern.h" #include "base_meta.h" diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 188e56835..a297258f3 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -26,6 +26,10 @@ Copyright (C) Microsoft Corporation. All rights reserved. $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)))..\..\ $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory))) $(CppWinRTParameters) -fastabi + + -modules + -module_include $(CppWinRTModuleInclude.Replace(';', ' ')) + $(CppWinRTCommandModuleFilter) -module_exclude $(CppWinRTModuleExclude.Replace(';', ' ')) "$(CppWinRTPackageDir)bin\" "$(CppWinRTPackageDir)" @@ -651,6 +655,9 @@ $(XamlMetaDataProviderPch) <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + + <_CppwinrtParameters Condition="'$(_CppWinRTConsumesPlatformModules)'!='true'">$(_CppwinrtParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." @@ -729,7 +736,7 @@ $(XamlMetaDataProviderPch) <_CppwinrtRefRefs Include="@(CppWinRTPlatformWinMDReferences)"/> - <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefRefs->'-ref "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." @@ -835,7 +842,7 @@ $(XamlMetaDataProviderPch) <_CppwinrtCompRefs Include="@(CppWinRTPlatformWinMDReferences)"/> - <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) -overwrite -name $(RootNamespace) $(CppWinRTCommandPrecompiledHeader) $(CppWinRTCommandUsePrefixes) -comp "$(GeneratedFilesDir)sources" + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) -overwrite -name $(RootNamespace) $(CppWinRTCommandPrecompiledHeader) $(CppWinRTCommandUsePrefixes) -comp "$(GeneratedFilesDir)sources" <_CppwinrtParameters Condition="'$(CppWinRTOptimized)'=='true'">$(_CppwinrtParameters) -opt <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompRefs->'-ref "%(WinMDPath)"', ' ') @@ -895,4 +902,88 @@ $(XamlMetaDataProviderPch) + + + + + CompileAsCppModule + true + NotUsing + + + + + + + + + $(GeneratedFilesDir) + $(IntDir) + $(OutDir) + + + + + + + + + <_CppWinRTModuleProviders Remove="@(_CppWinRTModuleProviders)" /> + <_CppWinRTModuleProviders Include="@(ProjectReference)" + Condition="'%(ProjectReference.CppWinRTConsumeModule)' == 'true'" /> + + + + + <_CppWinRTConsumesPlatformModules>true + + + + + + + + + + + + + <_CppWinRTModuleIfcSearchDirs>@(_CppWinRTResolvedModuleRefs->'%(CppWinRTModuleIfcDir)') + + + + $(_CppWinRTModuleIfcSearchDirs);%(ClCompile.AdditionalBMIDirectories) + + + + diff --git a/nuget/modules.md b/nuget/modules.md new file mode 100644 index 000000000..479781252 --- /dev/null +++ b/nuget/modules.md @@ -0,0 +1,179 @@ +# C++/WinRT C++20 Modules Guide + +## Overview + +C++/WinRT can generate per-namespace C++20 named modules (`.ixx` files) alongside the traditional projection headers. This allows you to write: + +```cpp +import winrt.Windows.Foundation; +``` + +instead of: + +```cpp +#include +``` + +Modules provide faster builds through pre-compiled module interfaces (IFCs) and better isolation of macro and declaration scopes. + +## Quick Start — Single Project + +For a project that builds and consumes its own modules: + +1. Set `CppWinRTBuildModule` to `true` in your project: + ```xml + + true + + ``` + +2. Optionally limit which namespaces get modules: + ```xml + + Windows.Foundation;Windows.Storage + + ``` + +3. Enable `BuildStlModules` for `import std;` support: + ```xml + + true + + ``` + +4. In your `.cpp` files: + ```cpp + import winrt.Windows.Foundation; + + int main() { + winrt::init_apartment(); + winrt::Windows::Foundation::Uri uri(L"https://example.com"); + } + ``` + +## Quick Start — Multi-Project (Recommended) + +For larger solutions, compile platform modules once in a dedicated "builder" static library, and share the pre-built IFCs with other projects. + +### Module Builder (static library) + +```xml + + StaticLibrary + true + Windows.Foundation + +``` + +### Consumer (exe or dll) + +```xml + + true + + + + true + + +``` + +The `CppWinRTConsumeModule` metadata on the ProjectReference tells the build system to: +- Use the builder's pre-built platform IFCs instead of compiling platform `.ixx` files again +- Skip generating platform `.ixx` files in the consumer's own projection + +### Component DLLs + +WinRT component projects can also use modules. Set `CppWinRTBuildModule=true` and all three projections (platform, reference, component) will generate `.ixx` files. + +```xml + + true + MyComponent + + + + true + + +``` + +### Consuming Components from Other Projects + +If project A references a component DLL from project B, project A builds its own reference projection modules from B's `.winmd`: + +```cpp +// These modules are built locally from the component's .winmd +import winrt.MyComponent; + +auto obj = winrt::MyComponent::MyClass(); +``` + +## MSBuild Properties + +| Property | Default | Description | +|-|-|-| +| `CppWinRTBuildModule` | false | Generate `.ixx` module interface units from projections | +| `CppWinRTModuleInclude` | (all) | Semicolon-delimited namespace prefixes to include in module generation | +| `CppWinRTModuleExclude` | (none) | Semicolon-delimited namespace prefixes to exclude from module generation | + +| ProjectReference Metadata | Default | Description | +|-|-|-| +| `CppWinRTConsumeModule` | false | Consume pre-built platform module IFCs from this project reference | + +## Module Filtering and Transitive Dependencies + +`CppWinRTModuleInclude` and `CppWinRTModuleExclude` control which namespace `.ixx` files are **generated**, but they do not suppress `import` statements for dependencies. If namespace A is included in the filter and depends on namespace B, the generated `winrt.A.ixx` will contain `import winrt.B;` even if B is excluded from the filter. This is by design — the module for B must exist *somewhere* (either from the same project or from a referenced project). + +This has important implications: + +- **Transitive closure must be satisfied.** If you filter to a subset of namespaces, any dependencies that fall outside the filter must be available from another source (e.g., a module builder project referenced via `CppWinRTConsumeModule`, or MSBuild's automatic `ReferencedModuleBMIs` from a static library reference). Otherwise, compilation will fail with "could not find module" errors. + +- **Use `CppWinRTModuleExclude` to avoid generating modules that have unsatisfied dependencies.** For example, `Windows.Foundation.Diagnostics` depends on `Windows.Storage`. If you filter to `CppWinRTModuleInclude=Windows.Foundation`, the Diagnostics `.ixx` will be generated (it matches the prefix) but will fail to compile because `winrt.Windows.Storage` doesn't exist. Add `CppWinRTModuleExclude=Windows.Foundation.Diagnostics` to prevent this. + +- **In multi-project scenarios with static libraries, use `CppWinRTModuleExclude` to avoid duplicate modules.** MSBuild automatically propagates all module IFCs from static library references to consuming projects (via the `AllProjectBMIsArePublic` property, which defaults to `true` for static libraries). If project A is a static library that builds modules for namespace X, and project B references A, then B already has A's IFCs available. If B also has `CppWinRTBuildModule=true`, its reference projection will generate a second `winrt.X.ixx`, causing an ambiguous module error. Set `CppWinRTModuleExclude=X` on project B to prevent this. B's own `.ixx` files will still emit `import winrt.X;`, which resolves to A's IFC via MSBuild's automatic propagation. Note: this issue does not affect DLL references — MSBuild does not propagate module IFCs from DLLs by default. + +## Module Names + +| Module | Contents | +|-|-| +| `winrt_base` | Core C++/WinRT types (`hstring`, `com_ptr`, `IUnknown`, etc.) — re-exported by all namespace modules | +| `winrt_numerics` | `Windows::Foundation::Numerics` types — re-exported by `winrt_base` | +| `winrt.` | Per-namespace projection (e.g., `winrt.Windows.Foundation`) | + +## Requirements + +- MSVC v145 toolset (Visual Studio 2026) or later recommended +- C++20 or later (`/std:c++20` or newer) +- `BuildStlModules=true` for `import std;` support + +## Limitations + +- Module IFCs are not compatible across toolset versions. All projects must use the same toolset. +- Cyclic namespace dependencies (e.g., `Windows.Foundation` ↔ `Windows.Foundation.Collections`) are handled automatically via SCC consolidation, but the resulting module name is chosen alphabetically. Adding new APIs could change SCC groupings. + +## Caution: Module Reuse Across Projects + +Pre-built IFCs (via `CppWinRTConsumeModule`) should only be shared when the builder and consumer use the same compilation context. In particular: + +- **Component modules are project-private.** A component projection built with `CppWinRTOptimized=true` generates modules that bypass activation factories for in-component type instantiation (`-opt`). If a consuming project accidentally imports these modules instead of building its own reference projection, the consumer will attempt direct instantiation across DLL boundaries, resulting in linker errors or incorrect behavior. Each project should build its own modules from the component's `.winmd` — do not tag component ProjectReferences with `CppWinRTConsumeModule`. + +- **`CppWinRTConsumeModule` is intended for platform module builders only.** The builder project is a dedicated static library whose sole purpose is compiling platform SDK modules. Its compilation flags (no `-opt`, no `-comp`) produce modules safe for any consumer. Only tag this builder's ProjectReference with `CppWinRTConsumeModule=true`. + +- **Module filter scope matters.** `CppWinRTModuleInclude` / `CppWinRTModuleExclude` applies to all three projections (platform, reference, component). If you set `CppWinRTModuleInclude=MyComponent`, only `MyComponent` namespaces will get `.ixx` files — platform and reference namespace modules will not be generated. Make sure your filter includes all namespaces you intend to import as modules, or use `CppWinRTConsumeModule` to get platform modules from a builder that was configured with the appropriate filter. + +- **Compilation settings must be compatible between builder and consumer.** Module IFCs encode assumptions about the compilation environment. While the compiler may not always diagnose mismatches, the following differences between the module builder and consumer may cause subtle or hard-to-diagnose issues: + - **Debug vs Release** — Mixing Debug and Release configurations can produce mismatched code generation, iterator debugging levels, and runtime library selections. + - **Preprocessor definitions** — Definitions that affect type layout, conditional compilation, or feature flags should match between builder and consumer. + - **Struct alignment / packing** — Different `/Zp` settings between projects can change struct layout, causing silent ABI mismatches. + - **Language standard** — While C++20 and later are generally compatible, mixing `/std:c++20` and `/std:c++23` and/or `/std:c++latest` if there are language features that affect type definitions. + + As a general rule, the module builder project try to use the same configuration, preprocessor definitions, and compiler options as its consumers. + +## Troubleshooting + +**"could not find module 'winrt.X'"** — Ensure the `.ixx` was generated (check `$(GeneratedFilesDir)winrt\`) and that `CppWinRTBuildModule=true` is set. For cross-project references, verify the consuming project's `ProjectReference` to the builder has `CppWinRTConsumeModule=true`, and that the builder's `IntDir` is accessible via `/ifcSearchDir`. + +**Linker errors for component constructors** — You may be importing a component's internal module instead of building your own reference projection. Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd`. + +**Redefinition errors** — Don't mix `#include` and `import` for the same namespace in the same translation unit. Use `import` consistently. diff --git a/nuget/readme.md b/nuget/readme.md index 9379aa716..c8c0b9537 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -70,6 +70,9 @@ C++/WinRT behavior can be customized with these project properties: | CppWinRTOptimized | true \| *false | Enables component projection [optimization features](https://kennykerr.ca/2019/06/07/cppwinrt-optimizing-components/) | | CppWinRTGenerateWindowsMetadata | true \| *false | Indicates whether this project produces Windows Metadata | | CppWinRTEnableDefaultPrivateFalse | true \| *false | Indicates whether this project uses C++/WinRT optimized default for copying binaries to the output directory | +| CppWinRTBuildModule | true \| *false | Generates per-namespace C++20 module interface units (.ixx) alongside projection headers | +| CppWinRTModuleInclude | namespace list | Semicolon-delimited namespaces to include in module generation (default: all) | +| CppWinRTModuleExclude | namespace list | Semicolon-delimited namespaces to exclude from module generation | \*Default value To customize common C++/WinRT project properties: @@ -132,6 +135,15 @@ void DerivedPage::InitializeComponent() } ``` +## C++20 Modules + +C++/WinRT supports C++20 named modules as an alternative to `#include`-based consumption. Instead of `#include `, you can write `import winrt.Windows.Foundation;`. See [modules.md](modules.md) for the full guide. + +| ProjectReference metadata | Description | +|-|-| +| CppWinRTConsumeModule | true \| *false | When set on a ProjectReference, consumes pre-built platform module IFCs from the referenced project | +\*Default value + ## Troubleshooting The msbuild verbosity level maps to msbuild message importance as follows: diff --git a/strings/base_abi.h b/strings/base_abi.h index 72946a3fa..4b7b8f77f 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> struct abi { diff --git a/strings/base_activation.h b/strings/base_activation.h index 1a195d865..c657c692d 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct library_traits { @@ -125,7 +125,7 @@ WINRT_EXPORT namespace winrt #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM64_BARRIER_ISH)); #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline std::int32_t interlocked_read_32(std::int32_t const volatile* target) noexcept { @@ -548,7 +548,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template T fast_activate(Windows::Foundation::IActivationFactory const& factory) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index 88fbea065..14447706a 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -47,7 +47,7 @@ WINRT_EXPORT namespace winrt #endif } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct module_lock_updater; diff --git a/strings/base_array.h b/strings/base_array.h index 48d10c6ce..d29bee883 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -483,7 +483,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct array_size_proxy diff --git a/strings/base_collections.h b/strings/base_collections.h index 4e1af51eb..7d8dc2e77 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { namespace wfc = Windows::Foundation::Collections; diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index 6fe10fa64..d299cc0c8 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -1,4 +1,4 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct nop_lock_guard {}; diff --git a/strings/base_collections_input_iterable.h b/strings/base_collections_input_iterable.h index e75211c30..e9d3af251 100644 --- a/strings/base_collections_input_iterable.h +++ b/strings/base_collections_input_iterable.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_iterable : diff --git a/strings/base_collections_input_map.h b/strings/base_collections_input_map.h index b33975fe6..3fe146bf6 100644 --- a/strings/base_collections_input_map.h +++ b/strings/base_collections_input_map.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct map_impl : diff --git a/strings/base_collections_input_map_view.h b/strings/base_collections_input_map_view.h index bfd8d82a9..d79eed61d 100644 --- a/strings/base_collections_input_map_view.h +++ b/strings/base_collections_input_map_view.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_map_view : diff --git a/strings/base_collections_input_vector.h b/strings/base_collections_input_vector.h index b5b76de38..a06e73b33 100644 --- a/strings/base_collections_input_vector.h +++ b/strings/base_collections_input_vector.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct vector_impl : diff --git a/strings/base_collections_input_vector_view.h b/strings/base_collections_input_vector_view.h index 3793e239a..30768c18e 100644 --- a/strings/base_collections_input_vector_view.h +++ b/strings/base_collections_input_vector_view.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_vector_view : diff --git a/strings/base_collections_map.h b/strings/base_collections_map.h index fa769fb88..6bf884236 100644 --- a/strings/base_collections_map.h +++ b/strings/base_collections_map.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using multi_threaded_map = map_impl; @@ -116,7 +116,7 @@ WINRT_EXPORT namespace winrt } } -namespace std +WINRT_EXPORT namespace std { template struct tuple_size> @@ -132,7 +132,7 @@ namespace std }; } -namespace winrt::Windows::Foundation::Collections +WINRT_EXPORT namespace winrt::Windows::Foundation::Collections { template std::tuple_element_t> get(IKeyValuePair const& kvp) diff --git a/strings/base_collections_vector.h b/strings/base_collections_vector.h index 3e9c1b254..3388806af 100644 --- a/strings/base_collections_vector.h +++ b/strings/base_collections_vector.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using multi_threaded_vector = vector_impl; diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 27496789a..0f02fabeb 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -5,7 +5,7 @@ WINRT_EXPORT namespace winrt struct com_ptr; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct capture_decay { @@ -349,7 +349,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) diff --git a/strings/base_composable.h b/strings/base_composable.h index e606d1292..5a7712ef7 100644 --- a/strings/base_composable.h +++ b/strings/base_composable.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct composable_factory diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 4f1c8d0b6..5cefad836 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct async_completed_handler; @@ -312,7 +312,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct cancellation_token @@ -704,7 +704,7 @@ namespace winrt::impl }; } -namespace std +WINRT_IMPL_STD_EXPORT namespace std { template struct coroutine_traits diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 6748906ca..057d5b548 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_IMPL_COROUTINES inline auto submit_threadpool_callback(void(__stdcall* callback)(void*, void* context), void* context) @@ -321,7 +321,7 @@ WINRT_EXPORT namespace winrt }; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct apartment_awaiter { @@ -671,7 +671,7 @@ WINRT_EXPORT namespace winrt struct fire_and_forget {}; } -namespace std +WINRT_IMPL_STD_EXPORT namespace std { template struct coroutine_traits diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 1cfe58710..1fe00ecd1 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #if defined(_MSC_VER) #pragma warning(push) diff --git a/strings/base_detect_numerics.h b/strings/base_detect_numerics.h new file mode 100644 index 000000000..6a93a8ffa --- /dev/null +++ b/strings/base_detect_numerics.h @@ -0,0 +1,4 @@ + +#if __has_include() +#define WINRT_IMPL_NUMERICS +#endif diff --git a/strings/base_error.h b/strings/base_error.h index c58635e5d..d42ca516b 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -7,7 +7,7 @@ #define WINRT_IMPL_RETURNADDRESS() nullptr #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct heap_traits { @@ -536,7 +536,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline hresult check_hresult_allow_bounds(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { diff --git a/strings/base_events.h b/strings/base_events.h index f7e2e6976..c21124e9c 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -130,7 +130,7 @@ WINRT_EXPORT namespace winrt }; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct event_revoker diff --git a/strings/base_extern.h b/strings/base_extern.h index 84e2943c4..a17908ac4 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -1,8 +1,11 @@ -__declspec(selectany) std::int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; -__declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; -__declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(std::uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; -__declspec(selectany) std::int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; +// These global function pointers must use WINRT_EXPORT (which expands to +// 'export extern "C++"' in module builds) so that module and non-module TUs +// in the same binary share the same instances. +WINRT_EXPORT __declspec(selectany) std::int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; +WINRT_EXPORT __declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; +WINRT_EXPORT __declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(std::uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; +WINRT_EXPORT __declspec(selectany) std::int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; #if defined(_MSC_VER) #ifdef _M_HYBRID diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index dc89fe6ce..a73e70a04 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -30,7 +30,11 @@ static_assert(WINRT_FAST_ABI_SIZE >= %); #pragma detect_mismatch("WINRT_FAST_ABI_SIZE", WINRT_IMPL_STRING(WINRT_FAST_ABI_SIZE)) -namespace winrt::impl +#ifndef WINRT_EXPORT +#define WINRT_EXPORT +#endif // WINRT_EXPORT + +WINRT_EXPORT namespace winrt::impl { // Thunk definitions are in arch-specific assembly sources % diff --git a/strings/base_foundation.h b/strings/base_foundation.h index ea8881edc..083252753 100644 --- a/strings/base_foundation.h +++ b/strings/base_foundation.h @@ -100,7 +100,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> inline constexpr auto& name_v = L"Windows.Foundation.Point"; template <> inline constexpr auto& name_v = L"Windows.Foundation.Size"; diff --git a/strings/base_identity.h b/strings/base_identity.h index 30830bc5a..7c61c83e2 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template constexpr std::array to_array(T const* value, std::index_sequence const) noexcept diff --git a/strings/base_implements.h b/strings/base_implements.h index 7edf32149..0eb8db0bd 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -6,7 +6,7 @@ #endif #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct marker { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt struct implements; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); @@ -267,7 +267,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct interface_list; diff --git a/strings/base_include_numerics.h b/strings/base_include_numerics.h new file mode 100644 index 000000000..4b7658fff --- /dev/null +++ b/strings/base_include_numerics.h @@ -0,0 +1,19 @@ + +// Includes when WINRT_IMPL_NUMERICS is defined. +// Requires to already be included (via base_detect_numerics). +// The types are redirected into winrt::Windows::Foundation::Numerics via macro wrapping. +// Uses WINRT_EXPORT for the namespace declaration, which resolves to 'export extern "C++"' +// in module builds and nothing in header builds. +#ifdef WINRT_IMPL_NUMERICS +#ifndef WINRT_EXPORT +#define WINRT_EXPORT +#endif +#include +#define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_END_NAMESPACE_ +#include +#undef _WINDOWS_NUMERICS_NAMESPACE_ +#undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ +#undef _WINDOWS_NUMERICS_END_NAMESPACE_ +#endif // WINRT_IMPL_NUMERICS diff --git a/strings/base_includes.h b/strings/base_includes.h index d6808792b..287a09709 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -31,11 +31,6 @@ #include #endif -#if __has_include() -#define WINRT_IMPL_NUMERICS -#include -#endif - #ifndef WINRT_LEAN_AND_MEAN #include #endif diff --git a/strings/base_iterator.h b/strings/base_iterator.h index acb0ebd42..46c0c6b63 100644 --- a/strings/base_iterator.h +++ b/strings/base_iterator.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct fast_iterator diff --git a/strings/base_macros.h b/strings/base_macros.h index 3dc01fa2d..91b0121d9 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -1,3 +1,6 @@ +#pragma once +#ifndef WINRT_BASE_MACROS_H +#define WINRT_BASE_MACROS_H #ifdef _DEBUG @@ -11,7 +14,11 @@ #define WINRT_VERIFY(expression) (void)(expression) #define WINRT_VERIFY_(result, expression) (void)(expression) -#endif +#endif // _DEBUG + +#if defined(__cpp_lib_coroutine) +#define WINRT_IMPL_COROUTINES +#endif // __cpp_lib_coroutine #define WINRT_IMPL_SHIM(...) (*(abi_t<__VA_ARGS__>**)&static_cast<__VA_ARGS__ const&>(static_cast(*this))) @@ -21,25 +28,30 @@ // Note: this is a workaround for a false-positive warning produced by the Visual C++ 16.3 compiler. #pragma warning(disable : 4268) -#endif -#if defined(__cpp_lib_coroutine) -#define WINRT_IMPL_COROUTINES -#endif +// C++ module warnings by /W4 +#pragma warning(disable : 4499) +#pragma warning(disable : 4630) +#endif // _MSC_VER #ifndef WINRT_EXPORT +#ifdef WINRT_IMPL_BUILD_MODULE +#define WINRT_EXPORT export extern "C++" +#else #define WINRT_EXPORT -#endif - -#ifdef WINRT_IMPL_NUMERICS -#define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_END_NAMESPACE_ -#include -#undef _WINDOWS_NUMERICS_NAMESPACE_ -#undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ -#undef _WINDOWS_NUMERICS_END_NAMESPACE_ -#endif +#endif // WINRT_IMPL_BUILD_MODULE +#endif // WINRT_EXPORT + +// Template specializations in namespace std (hash, coroutine_traits) need extern "C++" +// linkage in module builds for proper merging with the std module, but must NOT be +// exported — exporting namespace std would make all of std transitively visible. +#ifndef WINRT_IMPL_STD_EXPORT +#ifdef WINRT_IMPL_BUILD_MODULE +#define WINRT_IMPL_STD_EXPORT extern "C++" +#else +#define WINRT_IMPL_STD_EXPORT +#endif // WINRT_IMPL_BUILD_MODULE +#endif // WINRT_IMPL_STD_EXPORT #if defined(_MSC_VER) #define WINRT_IMPL_NOINLINE __declspec(noinline) @@ -81,7 +93,7 @@ #define WINRT_IMPL_HAS_DECLSPEC_UUID 0 #endif -#ifdef __IUnknown_INTERFACE_DEFINED__ +#if defined(__IUnknown_INTERFACE_DEFINED__) || defined(WINRT_ENABLE_LEGACY_COM) #define WINRT_IMPL_IUNKNOWN_DEFINED #else // Forward declare so we can talk about it. @@ -95,99 +107,11 @@ typedef struct _GUID GUID; #define WINRT_IMPL_CONSTEVAL constexpr #endif -// The intrinsics (such as __builtin_FILE()) that power std::source_location are also used to power winrt:impl::slim_source_location. -// The source location needs to be for the calling code, not cppwinrt itself, so that it is useful to developers building on top of -// this library. As a result any public-facing method that can result in an error needs a default-constructed slim_source_location -// argument so that it will collect source information from the application code that is calling into cppwinrt. -// -// We do not directly use std::source_location for two reasons: -// 1) std::source_location::function_name() is unavoidable. These strings end up in the final binary, bloating their size. This -// is particularly impactful for code bases that use templates heavily. Cases of 50% binary size growth have been observed. -// 2) std::source_location is a cpp20 feature, which is above the cpp17 feature floor for cppwinrt. By defining our own version -// we can avoid ODR violations in mixed cpp17/cpp20 builds. cpp17 callers will have an ABI that matches cpp20 callers (they -// will just not have useful file/line/function information). -// -// Some projects may decide that the source information binary size impact is not worth the benefit. Defining WINRT_NO_SOURCE_LOCATION -// will prevent this feature from activating. The slim_source_location type will be forwarded around but it will not include any -// nonzero data. That eliminates the biggest source of binary size overhead. -// -// To help with debugging the __builtin_FUNCTION() intrinsic will be used in _DEBUG builds. This will provide a bit more diagnostic -// value at the cost of binary size. The assumption is that binary size is considered less important in debug builds so this tradeoff -// is acceptable. -// -// The different behavior of the default parameters to winrt::impl::slim_source_location::current() is technically an ODR violation, -// albeit a minor one. There should be no serious consequence to this violation. In practice it means that mixing cpp17/cpp20, -// or mixing WINRT_NO_SOURCE_LOCATION with undefining it, will lead to inconsistent source location information. It may be missing -// when it is expected to be included, or it may be present when it is not expected. The behavior will depend on the linker's choice -// when there are multiple translation units with different options. This violation is tracked by https://github.com/microsoft/cppwinrt/issues/1445. - -#if !defined(__cpp_lib_source_location) || defined(WINRT_NO_SOURCE_LOCATION) -// Case1: cpp17 mode. The source_location intrinsics are not available. -// Case2: The caller has disabled source_location support. Ensure that there is no binary size overhead for line/file/function. -#define WINRT_IMPL_BUILTIN_LINE 0 -#define WINRT_IMPL_BUILTIN_FILE nullptr -#define WINRT_IMPL_BUILTIN_FUNCTION nullptr -#elif _DEBUG -// cpp20 _DEBUG builds include function information, which has a heavy binary size impact, in addition to file/line. -#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() -#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() -#define WINRT_IMPL_BUILTIN_FUNCTION __builtin_FUNCTION() -#else -// Release builds in cpp20 mode get file and line information but NOT function information. Function strings -// quickly add up to a substantial binary size impact, especially when templates are heavily used. -#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() -#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() -#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +// CPPWINRT_VERSION is defined here so it is available in module global fragments. +// In header builds, base_version_odr.h defines it first (before base_macros.h is included), +// so the #ifndef guard prevents redefinition. +#ifndef CPPWINRT_VERSION +#define CPPWINRT_VERSION "%" #endif -namespace winrt::impl -{ - // This struct is intended to be highly similar to std::source_location. The key difference is - // that function_name is NOT included. Function names do not fold to identical strings and can - // have heavy binary size overhead when templates cause many permutations to exist. - struct slim_source_location - { - [[nodiscard]] static WINRT_IMPL_CONSTEVAL slim_source_location current( - const std::uint_least32_t line = WINRT_IMPL_BUILTIN_LINE, - const char* const file = WINRT_IMPL_BUILTIN_FILE, - const char* const function = WINRT_IMPL_BUILTIN_FUNCTION) noexcept - { - return slim_source_location{ line, file, function }; - } - - [[nodiscard]] constexpr slim_source_location() noexcept = default; - - [[nodiscard]] constexpr slim_source_location( - const std::uint_least32_t line, - const char* const file, - const char* const function) noexcept : - m_line(line), - m_file(file), - m_function(function) - {} - - [[nodiscard]] constexpr std::uint_least32_t line() const noexcept - { - return m_line; - } - - [[nodiscard]] constexpr const char* file_name() const noexcept - { - return m_file; - } - - [[nodiscard]] constexpr const char* function_name() const noexcept - { - return m_function; - } - - private: - const std::uint_least32_t m_line{}; - const char* const m_file{}; - const char* const m_function{}; - }; -} - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") -#endif // _MSC_VER +#endif // WINRT_BASE_MACROS_H diff --git a/strings/base_marshaler.h b/strings/base_marshaler.h index 526f4d4c3..9be6959c9 100644 --- a/strings/base_marshaler.h +++ b/strings/base_marshaler.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline std::int32_t make_marshaler(unknown_abi* outer, void** result) noexcept { diff --git a/strings/base_meta.h b/strings/base_meta.h index 7dbb4c386..6b28640ef 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -48,7 +48,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { using namespace std::literals; diff --git a/strings/base_module_base_ixx.h b/strings/base_module_base_ixx.h new file mode 100644 index 000000000..5930f54ea --- /dev/null +++ b/strings/base_module_base_ixx.h @@ -0,0 +1,13 @@ + +#include +#include + +#ifdef WINRT_ENABLE_LEGACY_COM +#include +#include +#endif + +export module winrt_base; + +import std; +export import winrt_numerics; diff --git a/strings/base_module_ixx_preamble.h b/strings/base_module_ixx_preamble.h new file mode 100644 index 000000000..114873dc7 --- /dev/null +++ b/strings/base_module_ixx_preamble.h @@ -0,0 +1,11 @@ +module; +#define WINRT_IMPL_BUILD_MODULE + +#if defined(_MSC_VER) && _MSC_VER < 1950 +#pragma message("warning: C++/WinRT modules require MSVC toolset v14.50 (v145) or later. Building with an older toolset is not supported and may produce unexpected errors.") +#endif + +#include +#ifdef _DEBUG +#include +#endif // _DEBUG diff --git a/strings/base_module_numerics_ixx.h b/strings/base_module_numerics_ixx.h new file mode 100644 index 000000000..f1ade01ff --- /dev/null +++ b/strings/base_module_numerics_ixx.h @@ -0,0 +1,6 @@ + +#include + +#if defined(_MSC_VER) +#pragma detect_mismatch("C++/WinRT version", CPPWINRT_VERSION) +#endif diff --git a/strings/base_natvis.h b/strings/base_natvis.h index 60c5f5548..9e78563cb 100644 --- a/strings/base_natvis.h +++ b/strings/base_natvis.h @@ -5,7 +5,7 @@ #ifdef WINRT_NATVIS -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct natvis { diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 2820aff50..abffb3384 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct reference : implements, Windows::Foundation::IReference, Windows::Foundation::IPropertyValue> @@ -420,7 +420,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template T unbox_value_type(From&& value) diff --git a/strings/base_source_location.h b/strings/base_source_location.h new file mode 100644 index 000000000..c0fd81f9f --- /dev/null +++ b/strings/base_source_location.h @@ -0,0 +1,97 @@ + +// The intrinsics (such as __builtin_FILE()) that power std::source_location are also used to power winrt:impl::slim_source_location. +// The source location needs to be for the calling code, not cppwinrt itself, so that it is useful to developers building on top of +// this library. As a result any public-facing method that can result in an error needs a default-constructed slim_source_location +// argument so that it will collect source information from the application code that is calling into cppwinrt. +// +// We do not directly use std::source_location for two reasons: +// 1) std::source_location::function_name() is unavoidable. These strings end up in the final binary, bloating their size. This +// is particularly impactful for code bases that use templates heavily. Cases of 50% binary size growth have been observed. +// 2) std::source_location is a cpp20 feature, which is above the cpp17 feature floor for cppwinrt. By defining our own version +// we can avoid ODR violations in mixed cpp17/cpp20 builds. cpp17 callers will have an ABI that matches cpp20 callers (they +// will just not have useful file/line/function information). +// +// Some projects may decide that the source information binary size impact is not worth the benefit. Defining WINRT_NO_SOURCE_LOCATION +// will prevent this feature from activating. The slim_source_location type will be forwarded around but it will not include any +// nonzero data. That eliminates the biggest source of binary size overhead. +// +// To help with debugging the __builtin_FUNCTION() intrinsic will be used in _DEBUG builds. This will provide a bit more diagnostic +// value at the cost of binary size. The assumption is that binary size is considered less important in debug builds so this tradeoff +// is acceptable. +// +// The different behavior of the default parameters to winrt::impl::slim_source_location::current() is technically an ODR violation, +// albeit a minor one. There should be no serious consequence to this violation. In practice it means that mixing cpp17/cpp20, +// or mixing WINRT_NO_SOURCE_LOCATION with undefining it, will lead to inconsistent source location information. It may be missing +// when it is expected to be included, or it may be present when it is not expected. The behavior will depend on the linker's choice +// when there are multiple translation units with different options. This violation is tracked by https://github.com/microsoft/cppwinrt/issues/1445. + +#if !defined(__cpp_lib_source_location) || defined(WINRT_NO_SOURCE_LOCATION) +// Case1: cpp17 mode. The source_location intrinsics are not available. +// Case2: The caller has disabled source_location support. Ensure that there is no binary size overhead for line/file/function. +#define WINRT_IMPL_BUILTIN_LINE 0 +#define WINRT_IMPL_BUILTIN_FILE nullptr +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#elif _DEBUG +// cpp20 _DEBUG builds include function information, which has a heavy binary size impact, in addition to file/line. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION __builtin_FUNCTION() +#else +// Release builds in cpp20 mode get file and line information but NOT function information. Function strings +// quickly add up to a substantial binary size impact, especially when templates are heavily used. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#endif + +WINRT_EXPORT namespace winrt::impl +{ + // This struct is intended to be highly similar to std::source_location. The key difference is + // that function_name is NOT included. Function names do not fold to identical strings and can + // have heavy binary size overhead when templates cause many permutations to exist. + struct slim_source_location + { + [[nodiscard]] static WINRT_IMPL_CONSTEVAL slim_source_location current( + const std::uint_least32_t line = WINRT_IMPL_BUILTIN_LINE, + const char* const file = WINRT_IMPL_BUILTIN_FILE, + const char* const function = WINRT_IMPL_BUILTIN_FUNCTION) noexcept + { + return slim_source_location{ line, file, function }; + } + + [[nodiscard]] constexpr slim_source_location() noexcept = default; + + [[nodiscard]] constexpr slim_source_location( + const std::uint_least32_t line, + const char* const file, + const char* const function) noexcept : + m_line(line), + m_file(file), + m_function(function) + {} + + [[nodiscard]] constexpr std::uint_least32_t line() const noexcept + { + return m_line; + } + + [[nodiscard]] constexpr const char* file_name() const noexcept + { + return m_file; + } + + [[nodiscard]] constexpr const char* function_name() const noexcept + { + return m_function; + } + + private: + const std::uint_least32_t m_line{}; + const char* const m_file{}; + const char* const m_function{}; + }; +} + +#ifdef _MSC_VER +#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") +#endif // _MSC_VER diff --git a/strings/base_std_hash.h b/strings/base_std_hash.h index 864c31b13..4777f8082 100644 --- a/strings/base_std_hash.h +++ b/strings/base_std_hash.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline std::size_t hash_data(void const* ptr, std::size_t const bytes) noexcept { @@ -32,7 +32,7 @@ namespace winrt::impl }; } -namespace std +WINRT_IMPL_STD_EXPORT namespace std { template<> struct hash { diff --git a/strings/base_string.h b/strings/base_string.h index 92295e81c..6b1fb37b5 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct atomic_ref_count { @@ -442,7 +442,7 @@ template<> struct std::formatter : std::formatter {}; #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> struct abi { diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 5ac0221f6..71cd5f3c0 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -65,7 +65,7 @@ WINRT_EXPORT namespace winrt::param } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using param_type = std::conditional_t, param::hstring, T>; diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index 25e2eccce..223769d01 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -94,7 +94,7 @@ WINRT_EXPORT namespace winrt bool operator>=(std::nullptr_t left, hstring const& right) = delete; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline hstring concat_hstring(std::wstring_view const& left, std::wstring_view const& right) { diff --git a/strings/base_types.h b/strings/base_types.h index 18529e116..dc2b13632 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { using ptp_io = struct tp_io*; using ptp_timer = struct tp_timer*; @@ -208,7 +208,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation using DateTime = std::chrono::time_point; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_IMPL_IUNKNOWN_DEFINED using hresult_type = long; diff --git a/strings/base_version.h b/strings/base_version.h index 4a6b68e66..13d21fb2a 100644 --- a/strings/base_version.h +++ b/strings/base_version.h @@ -16,6 +16,8 @@ char const * const WINRT_version = "C++/WinRT version:" CPPWINRT_VERSION; WINRT_EXPORT namespace winrt { + inline constexpr char cppwinrt_version[] = CPPWINRT_VERSION; + template constexpr bool check_version(char const(&base)[BaseSize], char const(&component)[ComponentSize]) noexcept { diff --git a/strings/base_windows.h b/strings/base_windows.h index 21c4163e5..dcd164574 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_DIAGNOSTICS diff --git a/strings/base_xaml_typename.h b/strings/base_xaml_typename.h index b7b3a954a..2cc45b0bb 100644 --- a/strings/base_xaml_typename.h +++ b/strings/base_xaml_typename.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct xaml_typename_name diff --git a/test/nuget/NuGetTest.sln b/test/nuget/NuGetTest.sln index 310b0f252..c836b2551 100644 --- a/test/nuget/NuGetTest.sln +++ b/test/nuget/NuGetTest.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33516.290 @@ -47,6 +47,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConsoleApplication1", "Cons EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestProxyStub", "TestProxyStub\TestProxyStub.vcxproj", "{98E28FC8-2EB7-4544-9B6A-941462C6D3E2}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleApp", "TestModuleApp\TestModuleApp.vcxproj", "{8679913F-D38D-468F-A8B7-75B187A7A8BC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleBuilder", "TestModuleBuilder\TestModuleBuilder.vcxproj", "{AEE91B86-AA17-4C22-B0C2-08B2C287E375}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleComponent1", "TestModuleComponent1\TestModuleComponent1.vcxproj", "{F54D9A50-84D7-4953-8350-BEFE73CC36F6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleComponent2", "TestModuleComponent2\TestModuleComponent2.vcxproj", "{126E9412-E861-47C6-8684-C8F9BF32C0BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleConsumerApp", "TestModuleConsumerApp\TestModuleConsumerApp.vcxproj", "{FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}" + ProjectSection(ProjectDependencies) = postProject + {AEE91B86-AA17-4C22-B0C2-08B2C287E375} = {AEE91B86-AA17-4C22-B0C2-08B2C287E375} + {F54D9A50-84D7-4953-8350-BEFE73CC36F6} = {F54D9A50-84D7-4953-8350-BEFE73CC36F6} + {126E9412-E861-47C6-8684-C8F9BF32C0BD} = {126E9412-E861-47C6-8684-C8F9BF32C0BD} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -279,6 +294,58 @@ Global {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x64.Build.0 = Release|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x86.ActiveCfg = Release|Win32 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x86.Build.0 = Release|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|ARM64.Build.0 = Debug|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x64.ActiveCfg = Debug|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x64.Build.0 = Debug|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x86.ActiveCfg = Debug|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x86.Build.0 = Debug|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|ARM64.ActiveCfg = Release|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|ARM64.Build.0 = Release|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x64.ActiveCfg = Release|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x64.Build.0 = Release|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x86.ActiveCfg = Release|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x86.Build.0 = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|ARM64.ActiveCfg = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x64.ActiveCfg = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x64.Build.0 = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x86.ActiveCfg = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|ARM64.ActiveCfg = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|ARM64.Build.0 = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x64.ActiveCfg = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x64.Build.0 = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x86.ActiveCfg = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x86.Build.0 = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|ARM64.ActiveCfg = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x64.ActiveCfg = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x64.Build.0 = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x86.ActiveCfg = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|ARM64.ActiveCfg = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|ARM64.Build.0 = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x64.ActiveCfg = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x64.Build.0 = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x86.ActiveCfg = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x86.Build.0 = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|ARM64.ActiveCfg = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x64.ActiveCfg = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x64.Build.0 = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x86.ActiveCfg = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|ARM64.ActiveCfg = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|ARM64.Build.0 = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x64.ActiveCfg = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x64.Build.0 = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x86.ActiveCfg = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x86.Build.0 = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|ARM64.ActiveCfg = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x64.ActiveCfg = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x64.Build.0 = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x86.ActiveCfg = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|ARM64.ActiveCfg = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|ARM64.Build.0 = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x64.ActiveCfg = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x64.Build.0 = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x86.ActiveCfg = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/nuget/TestModuleApp/CustomDependencyObject.cpp b/test/nuget/TestModuleApp/CustomDependencyObject.cpp new file mode 100644 index 000000000..81631e387 --- /dev/null +++ b/test/nuget/TestModuleApp/CustomDependencyObject.cpp @@ -0,0 +1,8 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt.Windows.Foundation; +import winrt.Windows.UI.Xaml; + +#include "CustomDependencyObject.h" +#include "CustomDependencyObject.g.cpp" diff --git a/test/nuget/TestModuleApp/CustomDependencyObject.h b/test/nuget/TestModuleApp/CustomDependencyObject.h new file mode 100644 index 000000000..79fd6b1ff --- /dev/null +++ b/test/nuget/TestModuleApp/CustomDependencyObject.h @@ -0,0 +1,23 @@ +#pragma once +#include "CustomDependencyObject.g.h" + +namespace winrt::TestModuleApp::implementation +{ + struct CustomDependencyObject : CustomDependencyObjectT + { + CustomDependencyObject() = default; + + hstring Name() { return m_name; } + void Name(hstring const& value) { m_name = value; } + + private: + hstring m_name; + }; +} + +namespace winrt::TestModuleApp::factory_implementation +{ + struct CustomDependencyObject : CustomDependencyObjectT + { + }; +} diff --git a/test/nuget/TestModuleApp/ModuleTestHelper.cpp b/test/nuget/TestModuleApp/ModuleTestHelper.cpp new file mode 100644 index 000000000..1e3d7bc1a --- /dev/null +++ b/test/nuget/TestModuleApp/ModuleTestHelper.cpp @@ -0,0 +1,7 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt.Windows.Foundation; + +#include "ModuleTestHelper.h" +#include "ModuleTestHelper.g.cpp" diff --git a/test/nuget/TestModuleApp/ModuleTestHelper.h b/test/nuget/TestModuleApp/ModuleTestHelper.h new file mode 100644 index 000000000..c5a699c6b --- /dev/null +++ b/test/nuget/TestModuleApp/ModuleTestHelper.h @@ -0,0 +1,27 @@ +#pragma once +#include "ModuleTestHelper.g.h" + +namespace winrt::TestModuleApp::implementation +{ + struct ModuleTestHelper : ModuleTestHelperT + { + ModuleTestHelper() = default; + + Windows::Foundation::Uri CreateUri(hstring const& url) + { + return Windows::Foundation::Uri(url); + } + + Windows::Foundation::IAsyncOperation GetStringAsync() + { + co_return L"hello from module"; + } + }; +} + +namespace winrt::TestModuleApp::factory_implementation +{ + struct ModuleTestHelper : ModuleTestHelperT + { + }; +} diff --git a/test/nuget/TestModuleApp/PropertySheet.props b/test/nuget/TestModuleApp/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleApp/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleApp/TestModuleApp.def b/test/nuget/TestModuleApp/TestModuleApp.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleApp/TestModuleApp.idl b/test/nuget/TestModuleApp/TestModuleApp.idl new file mode 100644 index 000000000..ab3c56707 --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.idl @@ -0,0 +1,20 @@ +namespace TestModuleApp +{ + // A type that inherits from Windows.UI.Xaml.DependencyObject to exercise + // cross-namespace inheritance in module builds. + [default_interface] + unsealed runtimeclass CustomDependencyObject : Windows.UI.Xaml.DependencyObject + { + CustomDependencyObject(); + String Name{ get; set; }; + } + + // A simple runtime class using platform SDK types. + [default_interface] + runtimeclass ModuleTestHelper + { + ModuleTestHelper(); + Windows.Foundation.Uri CreateUri(String url); + Windows.Foundation.IAsyncOperation GetStringAsync(); + } +} diff --git a/test/nuget/TestModuleApp/TestModuleApp.vcxproj b/test/nuget/TestModuleApp/TestModuleApp.vcxproj new file mode 100644 index 000000000..522e0d911 --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.vcxproj @@ -0,0 +1,127 @@ + + + + + true + true + true + Windows;TestModuleApp + true + {8679913F-D38D-468F-A8B7-75B187A7A8BC} + TestModuleApp + TestModuleApp + en-US + 14.0 + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + ARM64 + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v145 + Unicode + + + true + + + false + true + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + 5311;28204 + NOMINMAX;%(PreprocessorDefinitions) + true + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + + TestModuleApp.idl + + + TestModuleApp.idl + + + + + Create + + + + TestModuleApp.idl + + + TestModuleApp.idl + + + + + + + + + + + + + diff --git a/test/nuget/TestModuleApp/main.cpp b/test/nuget/TestModuleApp/main.cpp new file mode 100644 index 000000000..907e4afed --- /dev/null +++ b/test/nuget/TestModuleApp/main.cpp @@ -0,0 +1,42 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import std; +import winrt.Windows.Foundation; +import winrt.Windows.UI.Xaml; + +#include "ModuleTestHelper.h" +#include "CustomDependencyObject.h" + +using namespace winrt; +using namespace Windows::Foundation; + +int main() +{ + init_apartment(); + + // Test ModuleTestHelper + auto helper = TestModuleApp::ModuleTestHelper(); + auto uri = helper.CreateUri(L"https://example.com"); + std::printf("URI: %ls\n", uri.AbsoluteUri().c_str()); + + auto str = helper.GetStringAsync().get(); + std::printf("Async: %ls\n", str.c_str()); + + // Test CustomDependencyObject (inherits from DependencyObject) + // Note: DependencyObject requires XAML runtime, which isn't available in a console app. + // We verify the type compiles and links correctly; runtime creation would need a XAML host. + try + { + auto obj = winrt::make(); + obj.Name(L"test"); + std::printf("Name: %ls\n", obj.Name().c_str()); + } + catch (winrt::hresult_error const& e) + { + std::printf("CustomDependencyObject: expected runtime error (no XAML host): %ls\n", e.message().c_str()); + } + + std::printf("All module tests passed.\n"); + return 0; +} diff --git a/test/nuget/TestModuleApp/pch.cpp b/test/nuget/TestModuleApp/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleApp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleApp/pch.h b/test/nuget/TestModuleApp/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleApp/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleBuilder/PropertySheet.props b/test/nuget/TestModuleBuilder/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleBuilder/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj b/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj new file mode 100644 index 000000000..d2d852240 --- /dev/null +++ b/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj @@ -0,0 +1,67 @@ + + + + + true + Windows.Foundation + Windows.Foundation.Diagnostics + true + {AEE91B86-AA17-4C22-B0C2-08B2C287E375} + TestModuleBuilder + TestModuleBuilder + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + StaticLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + NOMINMAX;%(PreprocessorDefinitions) + + + + + + + + Create + + + + + diff --git a/test/nuget/TestModuleBuilder/pch.cpp b/test/nuget/TestModuleBuilder/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleBuilder/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleBuilder/pch.h b/test/nuget/TestModuleBuilder/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleBuilder/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleComponent1/Greeter.cpp b/test/nuget/TestModuleComponent1/Greeter.cpp new file mode 100644 index 000000000..04c668e10 --- /dev/null +++ b/test/nuget/TestModuleComponent1/Greeter.cpp @@ -0,0 +1,8 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt_base; +import winrt.Windows.Foundation; + +#include "Greeter.h" +#include "Greeter.g.cpp" diff --git a/test/nuget/TestModuleComponent1/Greeter.h b/test/nuget/TestModuleComponent1/Greeter.h new file mode 100644 index 000000000..726fb7d22 --- /dev/null +++ b/test/nuget/TestModuleComponent1/Greeter.h @@ -0,0 +1,25 @@ +#pragma once +#include "Greeter.g.h" + +namespace winrt::TestModuleComponent1::implementation +{ + struct Greeter : GreeterT + { + Greeter() : m_name(L"World") {} + Greeter(hstring const& name) : m_name(name) {} + + hstring Name() { return m_name; } + hstring Greet() { return L"Hello, " + m_name + L"!"; } + Windows::Foundation::Uri Homepage() { return Windows::Foundation::Uri(L"https://example.com/" + m_name); } + + private: + hstring m_name; + }; +} + +namespace winrt::TestModuleComponent1::factory_implementation +{ + struct Greeter : GreeterT + { + }; +} diff --git a/test/nuget/TestModuleComponent1/PropertySheet.props b/test/nuget/TestModuleComponent1/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleComponent1/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.def b/test/nuget/TestModuleComponent1/TestModuleComponent1.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.idl b/test/nuget/TestModuleComponent1/TestModuleComponent1.idl new file mode 100644 index 000000000..73a983ee2 --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.idl @@ -0,0 +1,12 @@ +namespace TestModuleComponent1 +{ + [default_interface] + runtimeclass Greeter + { + Greeter(); + Greeter(String name); + String Name{ get; }; + String Greet(); + Windows.Foundation.Uri Homepage{ get; }; + } +} diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj b/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj new file mode 100644 index 000000000..669b25ff0 --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj @@ -0,0 +1,92 @@ + + + + + true + true + true + true + {F54D9A50-84D7-4953-8350-BEFE73CC36F6} + TestModuleComponent1 + TestModuleComponent1 + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + DynamicLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + _WINRT_DLL;NOMINMAX;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + TestModuleComponent1.def + + + + + + TestModuleComponent1.idl + + + + + Create + + + TestModuleComponent1.idl + + + + + + + + + + + + + true + + + + + diff --git a/test/nuget/TestModuleComponent1/pch.cpp b/test/nuget/TestModuleComponent1/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleComponent1/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleComponent1/pch.h b/test/nuget/TestModuleComponent1/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleComponent1/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleComponent2/GreeterGroup.cpp b/test/nuget/TestModuleComponent2/GreeterGroup.cpp new file mode 100644 index 000000000..7c6410b44 --- /dev/null +++ b/test/nuget/TestModuleComponent2/GreeterGroup.cpp @@ -0,0 +1,9 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import std; +import winrt.Windows.Foundation; +import winrt.TestModuleComponent1; + +#include "GreeterGroup.h" +#include "GreeterGroup.g.cpp" diff --git a/test/nuget/TestModuleComponent2/GreeterGroup.h b/test/nuget/TestModuleComponent2/GreeterGroup.h new file mode 100644 index 000000000..461570425 --- /dev/null +++ b/test/nuget/TestModuleComponent2/GreeterGroup.h @@ -0,0 +1,36 @@ +#pragma once +#include "GreeterGroup.g.h" + +namespace winrt::TestModuleComponent2::implementation +{ + struct GreeterGroup : GreeterGroupT + { + GreeterGroup() = default; + + void Add(winrt::TestModuleComponent1::Greeter const& greeter) + { + m_greeters.push_back(greeter); + } + + hstring GreetAll() + { + hstring result; + for (auto const& g : m_greeters) + { + if (!result.empty()) result = result + L", "; + result = result + g.Greet(); + } + return result; + } + + private: + std::vector m_greeters; + }; +} + +namespace winrt::TestModuleComponent2::factory_implementation +{ + struct GreeterGroup : GreeterGroupT + { + }; +} diff --git a/test/nuget/TestModuleComponent2/PropertySheet.props b/test/nuget/TestModuleComponent2/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleComponent2/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.def b/test/nuget/TestModuleComponent2/TestModuleComponent2.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.idl b/test/nuget/TestModuleComponent2/TestModuleComponent2.idl new file mode 100644 index 000000000..e45eed438 --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.idl @@ -0,0 +1,10 @@ +namespace TestModuleComponent2 +{ + [default_interface] + runtimeclass GreeterGroup + { + GreeterGroup(); + void Add(TestModuleComponent1.Greeter greeter); + String GreetAll(); + } +} diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj b/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj new file mode 100644 index 000000000..ff4982965 --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj @@ -0,0 +1,93 @@ + + + + + true + true + true + true + {126E9412-E861-47C6-8684-C8F9BF32C0BD} + TestModuleComponent2 + TestModuleComponent2 + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + DynamicLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + _WINRT_DLL;NOMINMAX;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + TestModuleComponent2.def + + + + + + TestModuleComponent2.idl + + + + + Create + + + TestModuleComponent2.idl + + + + + + + + + + + + + true + + + + + + diff --git a/test/nuget/TestModuleComponent2/pch.cpp b/test/nuget/TestModuleComponent2/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleComponent2/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleComponent2/pch.h b/test/nuget/TestModuleComponent2/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleComponent2/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleConsumerApp/PropertySheet.props b/test/nuget/TestModuleConsumerApp/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj b/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj new file mode 100644 index 000000000..910586a0c --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj @@ -0,0 +1,76 @@ + + + + + true + true + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9} + TestModuleConsumerApp + TestModuleConsumerApp + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + NOMINMAX;%(PreprocessorDefinitions) + + + Console + + + + + + + + Create + + + + + + true + + + + + + + diff --git a/test/nuget/TestModuleConsumerApp/main.cpp b/test/nuget/TestModuleConsumerApp/main.cpp new file mode 100644 index 000000000..da930703b --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/main.cpp @@ -0,0 +1,32 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; +import winrt.TestModuleComponent1; +import winrt.TestModuleComponent2; + +using namespace winrt; +using namespace Windows::Foundation; + +int main() +{ + init_apartment(); + + // Platform types from pre-built modules + Uri uri(L"https://example.com/consumer"); + std::printf("URI: %ls\n", uri.AbsoluteUri().c_str()); + + // Component1 + auto greeter = TestModuleComponent1::Greeter(L"Modules"); + std::printf("Greet: %ls\n", greeter.Greet().c_str()); + std::printf("Homepage: %ls\n", greeter.Homepage().AbsoluteUri().c_str()); + + // Component2 (depends on Component1) + auto group = TestModuleComponent2::GreeterGroup(); + group.Add(TestModuleComponent1::Greeter(L"Alice")); + group.Add(TestModuleComponent1::Greeter(L"Bob")); + std::printf("GreetAll: %ls\n", group.GreetAll().c_str()); + + std::printf("All consumer tests passed.\n"); + return 0; +} diff --git a/test/nuget/TestModuleConsumerApp/pch.cpp b/test/nuget/TestModuleConsumerApp/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleConsumerApp/pch.h b/test/nuget/TestModuleConsumerApp/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/test_cpp20_module/collections.cpp b/test/test_cpp20_module/collections.cpp new file mode 100644 index 000000000..b80e123d2 --- /dev/null +++ b/test/test_cpp20_module/collections.cpp @@ -0,0 +1,57 @@ +#include "pch.h" + +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation::Collections; + +TEST_CASE("module_vector") +{ + auto vec = single_threaded_vector(); + vec.Append(10); + vec.Append(20); + vec.Append(30); + REQUIRE(vec.Size() == 3); + REQUIRE(vec.GetAt(0) == 10); + REQUIRE(vec.GetAt(2) == 30); + + vec.RemoveAtEnd(); + REQUIRE(vec.Size() == 2); +} + +TEST_CASE("module_map") +{ + auto map = single_threaded_map(); + map.Insert(L"key1", L"value1"); + map.Insert(L"key2", L"value2"); + REQUIRE(map.Size() == 2); + REQUIRE(map.Lookup(L"key1") == L"value1"); + REQUIRE(map.HasKey(L"key2")); + REQUIRE(!map.HasKey(L"key3")); +} + +TEST_CASE("module_observable_vector") +{ + auto vec = single_threaded_observable_vector(); + int change_count = 0; + auto token = vec.VectorChanged([&](auto&&, auto&&) { ++change_count; }); + vec.Append(1); + vec.Append(2); + REQUIRE(change_count == 2); + vec.VectorChanged(token); +} + +TEST_CASE("module_iterable") +{ + auto vec = single_threaded_vector(); + vec.Append(1); + vec.Append(2); + vec.Append(3); + + int sum = 0; + for (auto v : vec) + { + sum += v; + } + REQUIRE(sum == 6); +} diff --git a/test/test_cpp20_module/com_interop.cpp b/test/test_cpp20_module/com_interop.cpp new file mode 100644 index 000000000..3035d2a05 --- /dev/null +++ b/test/test_cpp20_module/com_interop.cpp @@ -0,0 +1,84 @@ +#include "pch.h" +#include +#include + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that COM interop — including legacy (non-WinRT) COM types +// from the Windows SDK — works correctly when consumed via modules. +// +// Note: We avoid 'using namespace Windows::Foundation' here because it brings +// IInspectable/IUnknown into scope and collides with the SDK types of the same name. +// + +using namespace winrt; + +TEST_CASE("module_com_ptr_round_trip") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + // Detach to raw ABI pointer and re-attach + void* abi = detach_abi(uri); + REQUIRE(abi != nullptr); + + Windows::Foundation::Uri uri2{ nullptr }; + attach_abi(uri2, abi); + REQUIRE(uri2.AbsoluteUri() == L"https://example.com/"); +} + +TEST_CASE("module_sdk_iunknown_interop") +{ + // Interop between winrt projected types and the Windows SDK ::IUnknown + Windows::Foundation::Uri uri(L"https://example.com"); + + // Get the SDK IUnknown pointer from a projected type + ::IUnknown* raw = nullptr; + copy_to_abi(uri, *reinterpret_cast(&raw)); + REQUIRE(raw != nullptr); + + // QI for IInspectable through the raw SDK pointer + ::IInspectable* inspectable = nullptr; + REQUIRE(raw->QueryInterface(IID_IInspectable, reinterpret_cast(&inspectable)) == S_OK); + REQUIRE(inspectable != nullptr); + inspectable->Release(); + + // Round-trip back to a projected type + Windows::Foundation::Uri uri2{ nullptr }; + copy_from_abi(uri2, raw); + REQUIRE(uri2.AbsoluteUri() == L"https://example.com/"); + + raw->Release(); +} + +TEST_CASE("module_com_ptr_sdk_type") +{ + // winrt::com_ptr wrapping a Windows SDK ::IUnknown + Windows::Foundation::Uri uri(L"https://example.com"); + + com_ptr<::IUnknown> unknown; + copy_to_abi(uri, *reinterpret_cast(unknown.put())); + REQUIRE(unknown.get() != nullptr); +} + +TEST_CASE("module_iunknown_identity") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + auto unknown1 = uri.as(); + auto unknown2 = uri.as(); + REQUIRE(unknown1 == unknown2); +} + +TEST_CASE("module_try_as") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + auto stringable = uri.try_as(); + REQUIRE(stringable != nullptr); + REQUIRE(!stringable.ToString().empty()); + + auto closable = uri.try_as(); + REQUIRE(closable == nullptr); +} diff --git a/test/test_cpp20_module/coroutines.cpp b/test/test_cpp20_module/coroutines.cpp new file mode 100644 index 000000000..1553b1c6d --- /dev/null +++ b/test/test_cpp20_module/coroutines.cpp @@ -0,0 +1,58 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation; + +IAsyncAction do_nothing_async() +{ + co_return; +} + +IAsyncOperation return_42_async() +{ + co_return 42; +} + +IAsyncOperation return_string_async() +{ + co_return L"module coroutine"; +} + +IAsyncAction chain_async() +{ + auto result = co_await return_string_async(); + REQUIRE(!result.empty()); +} + +IAsyncOperation slow_operation() +{ + co_await resume_after(std::chrono::hours(1)); + co_return 0; +} + +TEST_CASE("module_async_action") +{ + auto action = do_nothing_async(); + action.get(); + REQUIRE(action.Status() == AsyncStatus::Completed); +} + +TEST_CASE("module_async_operation") +{ + REQUIRE(return_42_async().get() == 42); +} + +TEST_CASE("module_async_chain") +{ + chain_async().get(); +} + +TEST_CASE("module_async_cancel") +{ + auto op = slow_operation(); + op.Cancel(); + REQUIRE(op.Status() == AsyncStatus::Canceled); +} diff --git a/test/test_cpp20_module/format.cpp b/test/test_cpp20_module/format.cpp new file mode 100644 index 000000000..0c4570300 --- /dev/null +++ b/test/test_cpp20_module/format.cpp @@ -0,0 +1,49 @@ +#include "pch.h" + +#ifdef __cpp_lib_format + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that std::format and std::formatter specializations work +// correctly when consumed via modules. Mirrors test/test_cpp20/format.cpp. +// + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_format_hstring") +{ + hstring str = L"World"; + REQUIRE(std::format(L"Hello {}", str) == L"Hello World"); +} + +TEST_CASE("module_format_IStringable") +{ + // Uri implements IStringable — exercises the generated + // std::formatter specialization through modules. + Uri uri(L"https://example.com/path"); + IStringable stringable = uri; + REQUIRE(std::format(L"Visit: {}", stringable) == L"Visit: https://example.com/path"); +} + +TEST_CASE("module_format_projected_class") +{ + // Exercises the generated std::formatter specialization + // (inherits from formatter) through modules. + Uri uri(L"https://example.com"); + REQUIRE(std::format(L"URL: {}", uri) == L"URL: https://example.com/"); +} + +#if __cpp_lib_format >= 202207L +TEST_CASE("module_format_winrt_format") +{ + // winrt::format helper (C++23 formattable concept) + std::wstring str = L"World"; + REQUIRE(winrt::format(L"Hello {}", str) == L"Hello World"); + REQUIRE(winrt::format(L"C++/WinRT #{:d}", 1) == L"C++/WinRT #1"); +} +#endif + +#endif // __cpp_lib_format diff --git a/test/test_cpp20_module/foundation.cpp b/test/test_cpp20_module/foundation.cpp new file mode 100644 index 000000000..d26c55244 --- /dev/null +++ b/test/test_cpp20_module/foundation.cpp @@ -0,0 +1,68 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_uri") +{ + Uri uri(L"https://example.com/path?query=1"); + REQUIRE(!uri.AbsoluteUri().empty()); + REQUIRE(uri.Host() == L"example.com"); + REQUIRE(uri.Path() == L"/path"); +} + +TEST_CASE("module_property_value") +{ + auto pv = PropertyValue::CreateInt32(42); + REQUIRE(pv.as().GetInt32() == 42); + + auto pvs = PropertyValue::CreateString(L"hello"); + REQUIRE(pvs.as().GetString() == L"hello"); +} + +TEST_CASE("module_hstring") +{ + hstring text = L"C++/WinRT modules"; + REQUIRE(!text.empty()); + REQUIRE(text.size() == 17); + + hstring empty; + REQUIRE(empty.empty()); + REQUIRE(empty.size() == 0); +} + +TEST_CASE("module_events") +{ + winrt::event> my_event; + int received = 0; + auto token = my_event.add([&](auto&&, int value) { received = value; }); + my_event(nullptr, 42); + REQUIRE(received == 42); + my_event.remove(token); +} + +TEST_CASE("module_foundation_point") +{ + Point p{ 5.0f, 10.0f }; + REQUIRE(p.X == 5.0f); + REQUIRE(p.Y == 10.0f); +} + +TEST_CASE("module_foundation_size") +{ + Size s{ 800.0f, 600.0f }; + REQUIRE(s.Width == 800.0f); + REQUIRE(s.Height == 600.0f); +} + +TEST_CASE("module_foundation_rect") +{ + Point origin{ 0.0f, 0.0f }; + Size extent{ 100.0f, 200.0f }; + Rect r(origin, extent); + REQUIRE(r.X == 0.0f); + REQUIRE(r.Width == 100.0f); +} diff --git a/test/test_cpp20_module/hash.cpp b/test/test_cpp20_module/hash.cpp new file mode 100644 index 000000000..bb7594104 --- /dev/null +++ b/test/test_cpp20_module/hash.cpp @@ -0,0 +1,73 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that std::hash specializations work correctly +// when consumed via modules, enabling use in unordered containers. +// + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_hash_hstring") +{ + std::unordered_set set; + set.insert(L"hello"); + set.insert(L"world"); + set.insert(L"hello"); // duplicate + REQUIRE(set.size() == 2); + REQUIRE(set.contains(L"hello")); + REQUIRE(set.contains(L"world")); +} + +TEST_CASE("module_hash_IUnknown") +{ + Uri uri(L"https://example.com"); + auto unknown = uri.as(); + + std::unordered_set set; + set.insert(unknown); + set.insert(unknown); // duplicate — same identity + REQUIRE(set.size() == 1); + + // A different object should hash differently (almost certainly) + Uri uri2(L"https://other.com"); + set.insert(uri2.as()); + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_projected_type") +{ + // Projected types like Uri should be hashable via the generated + // std::hash specialization (inherits from hash_base). + std::unordered_set set; + Uri u1(L"https://one.com"); + Uri u2(L"https://two.com"); + set.insert(u1); + set.insert(u2); + set.insert(u1); // duplicate + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_guid") +{ + std::unordered_set set; + guid g1{ 0x01020304, 0x0506, 0x0708, { 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 } }; + guid g2{ 0x11121314, 0x1516, 0x1718, { 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 } }; + set.insert(g1); + set.insert(g2); + set.insert(g1); // duplicate + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_map_with_hstring_key") +{ + std::unordered_map map; + map[L"one"] = 1; + map[L"two"] = 2; + map[L"three"] = 3; + REQUIRE(map.size() == 3); + REQUIRE(map[L"two"] == 2); +} diff --git a/test/test_cpp20_module/main.cpp b/test/test_cpp20_module/main.cpp new file mode 100644 index 000000000..415e26f0f --- /dev/null +++ b/test/test_cpp20_module/main.cpp @@ -0,0 +1,24 @@ +#include +#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_WINDOWS_SEH +#include "catch.hpp" + +import winrt_base; + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_cpp20_module/natvis.cpp b/test/test_cpp20_module/natvis.cpp new file mode 100644 index 000000000..470654d07 --- /dev/null +++ b/test/test_cpp20_module/natvis.cpp @@ -0,0 +1,58 @@ +#include "pch.h" +#include + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that the natvis infrastructure (winrt::impl::natvis) +// is reachable through modules, ensuring the debugger visualizer can function. +// natvis is only active in _DEBUG builds. +// + +using namespace winrt; +using namespace Windows::Foundation; + +#ifdef _DEBUG + +TEST_CASE("module_natvis_get_val") +{ + // Verify impl::natvis::get_val is callable through the module. + Uri uri(L"http://example.com/"); + IInspectable inspectable = uri; + + // IStringable IID: {96369F54-8EB6-48F0-ABCE-C1B211E627C3} + // Method index 0 = ToString + auto result = impl::natvis::get_val(&inspectable, L"{96369F54-8EB6-48F0-ABCE-C1B211E627C3}", 0); + + // Compare the natvis result with the direct call + hstring expected = uri.ToString(); + uint32_t expected_len = 0; + auto expected_buf = WindowsGetStringRawBuffer(static_cast(get_abi(expected)), &expected_len); + uint32_t actual_len = 0; + auto actual_buf = WindowsGetStringRawBuffer(static_cast(result.s), &actual_len); + REQUIRE(expected_len == actual_len); + REQUIRE(memcmp(expected_buf, actual_buf, expected_len * sizeof(wchar_t)) == 0); +} + +TEST_CASE("module_natvis_uri_properties") +{ + Uri uri(L"http://moderncpp.com/path"); + IInspectable inspectable = uri; + + // IUriRuntimeClass IID: {9E365E57-48B2-4160-956F-C7385120BBFC} + // Method 5 = Host, Method 7 = Path, Method 11 = SchemeName + auto host_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 5); + hstring host_expected = uri.Host(); + REQUIRE(host_expected == hstring{ WindowsGetStringRawBuffer(static_cast(host_val.s), nullptr) }); + + auto path_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 7); + hstring path_expected = uri.Path(); + REQUIRE(path_expected == hstring{ WindowsGetStringRawBuffer(static_cast(path_val.s), nullptr) }); + + auto scheme_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 11); + hstring scheme_expected = uri.SchemeName(); + REQUIRE(scheme_expected == hstring{ WindowsGetStringRawBuffer(static_cast(scheme_val.s), nullptr) }); +} + +#endif // _DEBUG diff --git a/test/test_cpp20_module/numerics.cpp b/test/test_cpp20_module/numerics.cpp new file mode 100644 index 000000000..0f7dcc7fb --- /dev/null +++ b/test/test_cpp20_module/numerics.cpp @@ -0,0 +1,129 @@ +#include "pch.h" + +#if __has_include() + +import std; +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Numerics; + +// +// These tests exercise the SDK numerics types (float2, float3, etc.) from +// . These are exported by winrt_numerics and +// transitively available from winrt_base (and thus any namespace module). +// The Point/Size ↔ float2 conversions and name_v/category specializations +// are compiled in winrt_base. +// + +using namespace winrt; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Numerics; + +// --- SDK math types (from winrt_numerics, re-exported via winrt_base) --- + +TEST_CASE("module_numerics_float2") +{ + float2 a{ 1.0f, 2.0f }; + float2 b{ 3.0f, 4.0f }; + + auto c = a + b; + REQUIRE(c.x == 4.0f); + REQUIRE(c.y == 6.0f); + + REQUIRE(length(a) > 0.0f); +} + +TEST_CASE("module_numerics_float3") +{ + float3 v{ 1.0f, 0.0f, 0.0f }; + float3 up{ 0.0f, 1.0f, 0.0f }; + + REQUIRE(dot(v, up) == 0.0f); + REQUIRE(cross(v, up).z != 0.0f); +} + +TEST_CASE("module_numerics_float4x4") +{ + auto identity = float4x4::identity(); + REQUIRE(identity.m11 == 1.0f); + REQUIRE(identity.m12 == 0.0f); + + auto t = make_float4x4_translation({ 10.0f, 20.0f, 30.0f }); + REQUIRE(t.m41 == 10.0f); +} + +TEST_CASE("module_numerics_quaternion") +{ + auto identity = quaternion::identity(); + REQUIRE(identity.w == 1.0f); + REQUIRE(length(identity) == 1.0f); +} + +// --- Point/Size ↔ float2 conversions (compiled in winrt_base) --- + +TEST_CASE("module_numerics_point_from_float2") +{ + Point p(float2{ 3.0f, 7.0f }); + REQUIRE(p.X == 3.0f); + REQUIRE(p.Y == 7.0f); +} + +TEST_CASE("module_numerics_point_to_float2") +{ + float2 v = Point{ 10.0f, 20.0f }; + REQUIRE(v.x == 10.0f); + REQUIRE(v.y == 20.0f); +} + +TEST_CASE("module_numerics_size_from_float2") +{ + Size s(float2{ 100.0f, 200.0f }); + REQUIRE(s.Width == 100.0f); + REQUIRE(s.Height == 200.0f); +} + +TEST_CASE("module_numerics_size_to_float2") +{ + float2 v = Size{ 640.0f, 480.0f }; + REQUIRE(v.x == 640.0f); + REQUIRE(v.y == 480.0f); +} + +// --- WinRT projection metadata (name_v/category, compiled in winrt_base) --- +// Verify that the projection machinery produces correct IReference GUIDs +// for numerics types. This exercises name_v, category, and the SHA-1 based +// GUID computation across module boundaries, at compile time. + +namespace +{ + constexpr bool equal(guid const& left, guid const& right) noexcept + { + return left.Data1 == right.Data1 && + left.Data2 == right.Data2 && + left.Data3 == right.Data3 && + left.Data4[0] == right.Data4[0] && + left.Data4[1] == right.Data4[1] && + left.Data4[2] == right.Data4[2] && + left.Data4[3] == right.Data4[3] && + left.Data4[4] == right.Data4[4] && + left.Data4[5] == right.Data4[5] && + left.Data4[6] == right.Data4[6] && + left.Data4[7] == right.Data4[7]; + } +} + +#define REQUIRE_EQUAL_GUID(left, ...) STATIC_REQUIRE(equal(guid(left), guid_of<__VA_ARGS__>())); + +TEST_CASE("module_numerics_ireference_guids") +{ + REQUIRE_EQUAL_GUID("48F6A69E-8465-57AE-9400-9764087F65AD", IReference); + REQUIRE_EQUAL_GUID("1EE770FF-C954-59CA-A754-6199A9BE282C", IReference); + REQUIRE_EQUAL_GUID("A5E843C9-ED20-5339-8F8D-9FE404CF3654", IReference); + REQUIRE_EQUAL_GUID("76358CFD-2CBD-525B-A49E-90EE18247B71", IReference); + REQUIRE_EQUAL_GUID("DACBFFDC-68EF-5FD0-B657-782D0AC9807E", IReference); + REQUIRE_EQUAL_GUID("B27004BB-C014-5DCE-9A21-799C5A3C1461", IReference); + REQUIRE_EQUAL_GUID("46D542A1-52F7-58E7-ACFC-9A6D364DA022", IReference); +} + +#undef REQUIRE_EQUAL_GUID + +#endif // __has_include() diff --git a/test/test_cpp20_module/pch.cpp b/test/test_cpp20_module/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_cpp20_module/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_cpp20_module/pch.h b/test/test_cpp20_module/pch.h new file mode 100644 index 000000000..d0eb301ac --- /dev/null +++ b/test/test_cpp20_module/pch.h @@ -0,0 +1,3 @@ +#pragma once + +#include "catch.hpp" diff --git a/test/test_cpp20_module/range_for.cpp b/test/test_cpp20_module/range_for.cpp new file mode 100644 index 000000000..962c97179 --- /dev/null +++ b/test/test_cpp20_module/range_for.cpp @@ -0,0 +1,135 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation.Collections; + +// +// These tests confirm that C++/WinRT collections support range-based for loop iteration +// and structured bindings when consumed via modules. +// + +using namespace winrt; +using namespace Windows::Foundation::Collections; + +TEST_CASE("module_range_for_IIterable") +{ + IIterable c = single_threaded_vector({ 1, 2, 3 }); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_range_for_IVector") +{ + IVector c = single_threaded_vector({ 1, 2, 3 }); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_range_for_IVectorView") +{ + IVectorView c = single_threaded_vector({ 1, 2, 3 }).GetView(); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_structured_bindings_IKeyValuePair") +{ + std::map values + { + { 1, L"one"}, + { 2, L"two"}, + { 3, L"three"}, + }; + + IIterable> c = single_threaded_map(std::map(values)); + std::map result; + + for (IKeyValuePair i : c) + { + result[i.Key()] = i.Value(); + + // Structured binding on IKeyValuePair + auto const [key, value] = i; + REQUIRE(key == i.Key()); + REQUIRE(value == i.Value()); + } + + REQUIRE(result == values); + + // Range-for with structured bindings + result.clear(); + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} + +TEST_CASE("module_range_for_IMap") +{ + std::map values + { + { 1, L"one" }, + { 2, L"two" }, + { 3, L"three" }, + }; + + IMap c = single_threaded_map(std::map(values)); + std::map result; + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} + +TEST_CASE("module_range_for_IMapView") +{ + std::map values + { + { 1, L"one" }, + { 2, L"two" }, + { 3, L"three" }, + }; + + IMapView c = single_threaded_map(std::map(values)).GetView(); + std::map result; + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} diff --git a/test/test_cpp20_module/source_location.cpp b/test/test_cpp20_module/source_location.cpp new file mode 100644 index 000000000..ebf5139c3 --- /dev/null +++ b/test/test_cpp20_module/source_location.cpp @@ -0,0 +1,13 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +TEST_CASE("module_source_location") +{ + // Verify that slim_source_location works across the module boundary + auto loc = winrt::impl::slim_source_location::current(); + REQUIRE(loc.line() > 0); + std::string_view file(loc.file_name()); + REQUIRE(file.find("source_location.cpp") != std::string_view::npos); +} diff --git a/test/test_cpp20_module/test_cpp20_module.vcxproj b/test/test_cpp20_module/test_cpp20_module.vcxproj new file mode 100644 index 000000000..1e76c487b --- /dev/null +++ b/test/test_cpp20_module/test_cpp20_module.vcxproj @@ -0,0 +1,112 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + 16.0 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} + test_cpp20_module + test_cpp20_module + 10.0 + v145 + + + + Application + v145 + + + true + + + false + true + + + + + + + + + $(IntDir)Generated Files\ + + + + Use + pch.h + stdcpplatest + $(CppWinRTGenDir);..\;%(AdditionalIncludeDirectories) + NOMINMAX;%(PreprocessorDefinitions) + Level4 + true + 5311 + /bigobj + true + true + + + Console + ole32.lib;windowsapp.lib;%(AdditionalDependencies) + + + "$(CppWinRTDir)cppwinrt.exe" -in local -out "$(CppWinRTGenDir)." -modules -base -verbose -module_include "Windows.Foundation" -module_exclude "Windows.Foundation.Diagnostics" + + + + + + + CompileAsCppModule + true + NotUsing + + + + + + + + + Create + + + NotUsing + + + + + + + + + + + + + + \ No newline at end of file From c4cf531f6a8ec29c0e7eb19ed817043405ba9fa7 Mon Sep 17 00:00:00 2001 From: Mathias Berchtold Date: Mon, 1 Jun 2026 05:07:50 +0200 Subject: [PATCH 293/305] base_identity.h: added missing constexpr (#1589) Added missing constexpr to is_guid_of helper. guid_of is already constexpr: constexpr:https://github.com/microsoft/cppwinrt/blob/55f1b452aca069d6ac7eaad3e05cc1058fc39d27/strings/base_identity.h#L8 and find_iid_traits::test is constexpr and calls is_guid_of: https://github.com/microsoft/cppwinrt/blob/55f1b452aca069d6ac7eaad3e05cc1058fc39d27/strings/base_implements.h#L397 --- strings/base_identity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_identity.h b/strings/base_identity.h index 7c61c83e2..4a5bedbb1 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -11,7 +11,7 @@ WINRT_EXPORT namespace winrt } template - bool is_guid_of(guid const& id) noexcept + constexpr bool is_guid_of(guid const& id) noexcept { return ((id == guid_of()) || ...); } From 478111fc4a4a74937508cf8915436ff2b97b3ca6 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 23 Jun 2026 16:00:37 -0700 Subject: [PATCH 294/305] Stop exporting winrt::impl::get_marshaler to workaround MSVC modules bug (#1592) * Stop exporting winrt::impl::get_marshaler to workaround MSVC modules bug * Include base.h in marshal.cpp to verify that include-then-import still works --- strings/base_marshaler.h | 2 +- test/test_cpp20_module/marshal.cpp | 25 +++++++++++++++++++ .../test_cpp20_module.vcxproj | 4 ++- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/test_cpp20_module/marshal.cpp diff --git a/strings/base_marshaler.h b/strings/base_marshaler.h index 9be6959c9..526f4d4c3 100644 --- a/strings/base_marshaler.h +++ b/strings/base_marshaler.h @@ -1,5 +1,5 @@ -WINRT_EXPORT namespace winrt::impl +namespace winrt::impl { inline std::int32_t make_marshaler(unknown_abi* outer, void** result) noexcept { diff --git a/test/test_cpp20_module/marshal.cpp b/test/test_cpp20_module/marshal.cpp new file mode 100644 index 000000000..d47f8c3cb --- /dev/null +++ b/test/test_cpp20_module/marshal.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include +#include + +import std; +import winrt.Windows.Foundation.Collections; + +using namespace winrt; + +struct S : implements +{ + hstring ToString() + { + return L"S"; + } +}; + +// When winrt::impl::get_marshaler was being exported, an MSVC bug caused the marshaler +// object to have a null vtable, which caused a crash when calling any method on the marshaler. +// This test ensures that the marshaler vtable is properly initialized. +TEST_CASE("IMarshal") +{ + auto s = make(); + auto marshal = s.as(); +} diff --git a/test/test_cpp20_module/test_cpp20_module.vcxproj b/test/test_cpp20_module/test_cpp20_module.vcxproj index 1e76c487b..f5c20a35d 100644 --- a/test/test_cpp20_module/test_cpp20_module.vcxproj +++ b/test/test_cpp20_module/test_cpp20_module.vcxproj @@ -25,7 +25,8 @@ Release x64 - + + 16.0 {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} test_cpp20_module @@ -91,6 +92,7 @@ + Create From b7eb2eacfd857c6334cd688306ab543ac4e96864 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:21:55 -0700 Subject: [PATCH 295/305] Migrate GitHub CI off VS 2022, add C++20 module test, dynamic v143/v145 toolset (#1601) * Migrate GitHub CI off VS 2022 (v143) to v145/VS 2026 * Add C++20 module test to CI; dynamic v143/v145 toolset selection --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- .github/instructions/cppwinrt.instructions.md | 2 +- .github/workflows/ci.yml | 26 +++++-------------- Directory.Build.Props | 3 +++ .../nuget/TestProxyStub/TestProxyStub.vcxproj | 1 - 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/.github/instructions/cppwinrt.instructions.md b/.github/instructions/cppwinrt.instructions.md index ba5d66212..eae2fc3c6 100644 --- a/.github/instructions/cppwinrt.instructions.md +++ b/.github/instructions/cppwinrt.instructions.md @@ -25,7 +25,7 @@ - Use VS Developer Shell for correct toolset environment - `cmake --build build --config Release --target cppwinrt` for cppwinrt.exe (or MSBuild: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64`) - NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` -- Module test projects require v145 toolset (VS 2026). Directory.Build.Props sets v143 by default — override with `v145` in Configuration PropertyGroup +- Module test projects require v145 toolset (VS 2026). Directory.Build.Props selects v145 when VisualStudioVersion >= 18.0 (VS 2026) and falls back to v143 otherwise; override `` in the Configuration PropertyGroup to force a specific toolset ## Key Patterns diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c2a04353..37f42ab70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,8 +15,6 @@ jobs: arch: [x86, x64, arm64] config: [Debug, Release] toolchain: - - image: windows-2025 - platform_toolset: v143 - image: windows-2025-vs2026 platform_toolset: v145 exclude: @@ -99,10 +97,8 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_cpp20_module, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] toolchain: - - image: windows-2025 - platform_toolset: v143 - image: windows-2025-vs2026 platform_toolset: v145 exclude: @@ -112,6 +108,9 @@ jobs: arch: arm64 - compiler: clang-cl config: Release + # C++20 named modules require the MSVC v145 toolset; clang-cl is not supported. + - compiler: clang-cl + test_exe: test_cpp20_module runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 @@ -295,7 +294,7 @@ jobs: arch: [x86, x64, arm64] config: [Release] Deployment: [Component, Standalone] - runs-on: windows-latest + runs-on: windows-2025-vs2026 steps: - uses: actions/checkout@v6 @@ -316,7 +315,7 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" $target_version = "999.999.999.999" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version,PlatformToolset=v145" - name: Restore nuget packages run: | @@ -336,8 +335,6 @@ jobs: arch: [x86, x64] config: [Release] toolchain: - - image: windows-2025 - platform_toolset: v143 - image: windows-2025-vs2026 platform_toolset: v145 runs-on: ${{ matrix.toolchain.image }} @@ -378,15 +375,6 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose - - - name: Remove module test projects on v143 - if: matrix.toolchain.platform_toolset == 'v143' - run: | - # Module test projects require v145 toolset - mv test\nuget\NugetTest.sln test\nuget\NugetTest.sln.orig - Get-Content test\nuget\NugetTest.sln.orig | - Where-Object { -not ($_ -match 'TestModule') } | - Set-Content test\nuget\NugetTest.sln - name: Run nuget test run: | @@ -394,7 +382,7 @@ jobs: build-nuget: name: Build nuget package with MSVC - runs-on: windows-latest + runs-on: windows-2025-vs2026 steps: - uses: actions/checkout@v6 diff --git a/Directory.Build.Props b/Directory.Build.Props index c98cd5dd0..5972803c0 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -3,7 +3,10 @@ + v143 + v145 10.0 10.0.18362.0 diff --git a/test/nuget/TestProxyStub/TestProxyStub.vcxproj b/test/nuget/TestProxyStub/TestProxyStub.vcxproj index 69e41cfba..cd646da7f 100644 --- a/test/nuget/TestProxyStub/TestProxyStub.vcxproj +++ b/test/nuget/TestProxyStub/TestProxyStub.vcxproj @@ -40,7 +40,6 @@ DynamicLibrary - v143 Unicode From 5bf26503d49a7454442a8a569ae9e00d043c583e Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 24 Jun 2026 11:34:23 -0700 Subject: [PATCH 296/305] Massive speedup to file_equal and file_to_string (#1584) * Massive speedup to file_equal and file_to_string * Properly cast the result of tellg() and handle filesystem errors more gracefully. --- cppwinrt/text_writer.h | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index a274d11ce..c6fc380b3 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -13,8 +13,26 @@ namespace cppwinrt { inline std::string file_to_string(std::string const& filename) { - std::ifstream file(filename, std::ios::binary); - return static_cast(std::stringstream() << file.rdbuf()).str(); + std::ifstream file(filename, std::ios::binary | std::ios::ate); + if (!file) { return{}; } + + const auto stream_size = file.tellg(); + if (stream_size == std::ifstream::pos_type(-1)) + { + return {}; + } + + file.seekg(0); + + auto size = static_cast(stream_size); + std::string result(size, '\0'); + file.read(result.data(), size); + if (!file) + { + result.resize(static_cast(file.gcount())); + } + + return result; } template @@ -218,18 +236,15 @@ namespace cppwinrt bool file_equal(std::string const& filename) const { - if (!std::filesystem::exists(filename)) + // Non-throwing file_size returns uintmax_t(-1) on errors, which shouldn't ever be the size of m_first or m_second + std::error_code ec; + if (std::filesystem::file_size(filename, ec) != m_first.size() + m_second.size()) { return false; } auto file = file_to_string(filename); - if (file.size() != m_first.size() + m_second.size()) - { - return false; - } - if (!std::equal(m_first.begin(), m_first.end(), file.begin(), file.begin() + m_first.size())) { return false; From 77b1e4e02057e4cfff1ce850e40024e9fbc0f7fb Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 24 Jun 2026 11:45:53 -0700 Subject: [PATCH 297/305] Improve module docs, ship them in the nuget, and add missing properties to Visual Studio proejct properties page (#1586) --- nuget/CppWinrtRules.Project.xml | 21 ++ nuget/Microsoft.Windows.CppWinRT.nuspec | 3 + nuget/modules.md | 415 ++++++++++++++++++++++-- nuget/readme.md | 4 +- nuget/readme.txt | 3 + 5 files changed, 410 insertions(+), 36 deletions(-) diff --git a/nuget/CppWinrtRules.Project.xml b/nuget/CppWinrtRules.Project.xml index 73f32c6d3..43a712d21 100644 --- a/nuget/CppWinrtRules.Project.xml +++ b/nuget/CppWinrtRules.Project.xml @@ -3,6 +3,7 @@ + @@ -86,4 +87,24 @@ Description="Enables the /await:strict compiler option" Category="General" /> + + + + + + + + diff --git a/nuget/Microsoft.Windows.CppWinRT.nuspec b/nuget/Microsoft.Windows.CppWinRT.nuspec index a63e08bf9..52151fc08 100644 --- a/nuget/Microsoft.Windows.CppWinRT.nuspec +++ b/nuget/Microsoft.Windows.CppWinRT.nuspec @@ -12,6 +12,7 @@ native C++ WinRT nativepackage © Microsoft Corporation. All rights reserved. LICENSE + readme.md https://github.com/Microsoft/cppwinrt https://aka.ms/cppwinrt.ico @@ -25,5 +26,7 @@ + + diff --git a/nuget/modules.md b/nuget/modules.md index 479781252..4f0eebb95 100644 --- a/nuget/modules.md +++ b/nuget/modules.md @@ -14,11 +14,41 @@ instead of: #include ``` -Modules provide faster builds through pre-compiled module interfaces (IFCs) and better isolation of macro and declaration scopes. +Benefits include: + +- **Smaller intermediate artifacts.** The IFC representation of a C++/WinRT projection is significantly smaller than the equivalent precompiled header (PCH). +- **Shared compilation across projects.** PCHs eliminate redundant parsing *within* a project, but each project rebuilds its own PCH. Module IFCs can be built once in a shared module builder project and consumed by all dependent projects, eliminating redundant work across the entire solution. +- **Better isolation.** Module imports don't leak macros into the importing translation unit. + +> **Real-world experience:** The guidance in this document was hardened against a prototype conversion of the Windows Terminal codebase (~250 files across 15+ projects) from textual `#include`s to module imports. + +## Prerequisites + +- **MSVC v145 toolset** (Visual Studio 2026) or later with C++20 module support +- **C++/WinRT 3.x** NuGet package with `CppWinRTBuildModule` support +- `/std:c++20` or later (`/std:c++latest` recommended for `import std;`) +- `BuildStlModules=true` for `import std;` support + +## Three Fundamental Constraints + +These three rules drive almost every pattern in this guide. Understanding them up front makes the rest of the document much easier to follow: + +1. **`import` in a PCH breaks the compiler.** MSVC cannot handle module `import` declarations inside a precompiled header — it produces internal compiler errors (ICE). All module imports must live outside the PCH. + +2. **Include-then-import is safe, but has a cost.** MSVC handles the case where you `#include` a header and then `import` the same content. For STL headers this is a reasonable workaround (the compilation cost is modest), but C++/WinRT projection headers can be extremely expensive to parse textually. Include-then-import with winrt headers defeats the build-cost improvements of adopting modules, so it should be avoided where possible. + +3. **Import-then-include is not supported.** When a module has already been imported, `#include`-ing a header that declares the same types causes errors — the compiler sees conflicting declarations. C++/WinRT provides a workaround: defining `WINRT_IMPORT_MODULE` before including a winrt header causes the header to be (mostly) a no-op, defining only its include-guard macro. This makes it safe to include winrt headers *after* importing modules, which is essential for lighting up header-guard-based features in libraries like WIL, and for interoperating with external code that includes winrt headers out of your control (e.g. the XAML compiler). STL headers do not have an equivalent workaround, but can fall back on the "generally safe" include-then-import pattern. + +The patterns throughout this guide are direct consequences of these constraints: + +- The PCH is stripped of all winrt content. +- A separate "module preamble" header centralizes imports. +- Wrapper headers define `WINRT_IMPORT_MODULE` before including winrt headers. +- STL headers are sometimes pre-included in the PCH, but only as a workaround. ## Quick Start — Single Project -For a project that builds and consumes its own modules: +For a small project that builds and consumes its own modules: 1. Set `CppWinRTBuildModule` to `true` in your project: ```xml @@ -34,6 +64,8 @@ For a project that builds and consumes its own modules: ``` + By default, C++/WinRT generates and builds `.ixx` files for **every** namespace reachable from your WinMD inputs — for a typical Windows SDK projection, that's hundreds of namespaces and can add upwards of a minute to your build. If build speed matters, prune the set with `CppWinRTModuleInclude` (or `CppWinRTModuleExclude`) so that only the namespaces you actually `import` are produced. See [Understanding the Include and Exclude Filters](#understanding-the-include-and-exclude-filters) for the full discussion. + 3. Enable `BuildStlModules` for `import std;` support: ```xml @@ -51,25 +83,40 @@ For a project that builds and consumes its own modules: } ``` -## Quick Start — Multi-Project (Recommended) +For a single vcxproj — or a handful of projects that don't share many namespaces — this is all you need. A dedicated module builder is only worth the overhead when multiple projects need the same platform and third-party WinRT modules. + +## Architecture — Module Builder (Recommended for Multi-Project Solutions) + +For solutions with multiple projects, the recommended approach is a dedicated **module builder** project that builds the shared IFC files once, consumed by all other projects. This avoids each project redundantly compiling the same module interfaces. -For larger solutions, compile platform modules once in a dedicated "builder" static library, and share the pre-built IFCs with other projects. +### The Module Builder Project -### Module Builder (static library) +Create a dedicated static library project whose sole purpose is to build the shared platform module IFC files. This project has no source files of its own — the C++/WinRT NuGet targets generate `.ixx` files automatically. ```xml StaticLibrary true - Windows.Foundation + true ``` -### Consumer (exe or dll) +Key configuration: + +- **`CppWinRTBuildModule=true`** generates per-namespace `.ixx` module interface files. +- **`BuildStlModules=true`** is required because the generated `.ixx` files use `import std;`. +- **`WINRT_ENABLE_LEGACY_COM`** — define this preprocessor macro if your project uses classic COM interfaces (`IUnknown`, `IInspectable`). It causes `` and `` to be included within the `winrt_base` module. +- **PCH**: don't bother. The module builder can use a PCH, but there is little benefit — its content is almost entirely C++/WinRT headers, and most non-C++/WinRT headers are only used once in `winrt_base`. + +### Consumer Project Configuration + +Each project that uses modules needs: ```xml true + MyCompany.MyComponent + Microsoft.UI;Microsoft.Web @@ -78,9 +125,25 @@ For larger solutions, compile platform modules once in a dedicated "builder" sta ``` -The `CppWinRTConsumeModule` metadata on the ProjectReference tells the build system to: -- Use the builder's pre-built platform IFCs instead of compiling platform `.ixx` files again -- Skip generating platform `.ixx` files in the consumer's own projection +- **`CppWinRTBuildModule=true`** is required on consumers too. It enables the C++/WinRT targets to generate `.ixx` module interface files for the project's own component namespaces (filtered by `CppWinRTModuleInclude` / `CppWinRTModuleExclude`) and wires up module consumption from referenced projects. +- **`CppWinRTConsumeModule=true`** on the `ProjectReference` tells the build system to use the builder's pre-built platform IFCs instead of compiling platform `.ixx` files again, and skip generating platform `.ixx` files in the consumer's own projection. + +### Adding Third-Party WinMDs to the Module Builder + +If your project uses third-party WinRT components (e.g., WinUI/MUX, WebView2), build their modules in the shared builder by adding their WinMDs as platform inputs: + +```xml + + + + + + +``` + +**Important:** Add these WinMDs as `CppWinRTPlatformWinMDReferences`, **not** as NuGet `` items. In practice, adding third-party WinMDs via NuGet `` items on the module builder has been observed to cause empty path errors in the reference projection step. Adding them directly as `CppWinRTPlatformWinMDReferences` feeds them into the platform projection, which is the correct pipeline for a module builder project. ### Component DLLs @@ -98,8 +161,6 @@ WinRT component projects can also use modules. Set `CppWinRTBuildModule=true` an ``` -### Consuming Components from Other Projects - If project A references a component DLL from project B, project A builds its own reference projection modules from B's `.winmd`: ```cpp @@ -113,19 +174,53 @@ auto obj = winrt::MyComponent::MyClass(); | Property | Default | Description | |-|-|-| -| `CppWinRTBuildModule` | false | Generate `.ixx` module interface units from projections | +| `CppWinRTBuildModule` | `false` | Generate `.ixx` module interface units from projections | | `CppWinRTModuleInclude` | (all) | Semicolon-delimited namespace prefixes to include in module generation | | `CppWinRTModuleExclude` | (none) | Semicolon-delimited namespace prefixes to exclude from module generation | -| ProjectReference Metadata | Default | Description | +| `ProjectReference` Metadata | Default | Description | |-|-|-| -| `CppWinRTConsumeModule` | false | Consume pre-built platform module IFCs from this project reference | +| `CppWinRTConsumeModule` | `false` | Consume pre-built platform module IFCs from this project reference | + +### Understanding the Include and Exclude Filters + +These filters control which C++/WinRT module `.ixx` files are generated from WinMD inputs. They only affect modules produced by the C++/WinRT NuGet targets from `.winmd` files — hand-authored modules or modules unrelated to WinRT are not affected. + +- **`CppWinRTModuleInclude`** — semicolon-separated namespace prefixes. Only matching namespaces will have `.ixx` files generated. Without this, *all* namespaces from the project's WinMD inputs are candidates. +- **`CppWinRTModuleExclude`** — semicolon-separated namespace prefixes to suppress `.ixx` generation for. **Import statements are still generated** in the modules that remain; only the `.ixx` file creation is suppressed. -## Module Filtering and Transitive Dependencies +#### Why Filter at All? + +There are three distinct reasons to set these filters. Most non-trivial projects will hit more than one: + +1. **Build performance.** By default, enabling `CppWinRTBuildModule=true` generates and compiles `.ixx` files for *every* namespace reachable from your WinMD inputs. For a typical Windows SDK projection that's hundreds of namespaces, and the IFC compilation step can easily add upwards of a minute to a clean build. Use `CppWinRTModuleInclude` to narrow generation to namespaces you (or your consumers) actually `import`, or `CppWinRTModuleExclude` to drop large subtrees you don't use (e.g., `Windows.Devices`, `Windows.Media`). For a dedicated module builder project that other projects consume, this is typically the dominant reason to filter. + +2. **Avoiding ambiguous IFC errors (C7684).** An IFC is ambiguous when the same module name resolves to two different `.ifc` files — typically one built locally and one from a referenced project. See [When to Set an Exclude for Ambiguity](#when-to-set-an-exclude-for-ambiguity) below. + +3. **Avoiding modules with unsatisfied dependencies.** Filtering to a subset of namespaces does *not* prune the `import` statements those modules emit for their dependencies — so a generated module whose dependencies fall outside your filter will fail to compile. See [Module Filtering and Transitive Dependencies](#module-filtering-and-transitive-dependencies) below. + +#### When to Set an Exclude for Ambiguity + +Exclude a namespace when its IFC is already provided by a project you reference: + +| Scenario | Action | +|----------|--------| +| You reference a **static library** with `CppWinRTBuildModule=true` | Exclude namespaces that static lib produces (its IFCs propagate via `AdditionalBMIDirectories`) | +| You reference a **DLL** with `CppWinRTBuildModule=true` | **No exclude needed** — DLL IFCs don't propagate by default | +| The **module builder** produces a namespace (e.g., `Microsoft.UI`) | Exclude it — the module builder's IFCs propagate via `CppWinRTConsumeModule` | + +Example — a project that references both the module builder (which provides `Microsoft.UI.*`) and a `TerminalCore` static library (which provides `Microsoft.Terminal.Core`): + +```xml +Microsoft.Terminal +Microsoft.Terminal.Core;Microsoft.UI;Microsoft.Web +``` + +### Module Filtering and Transitive Dependencies `CppWinRTModuleInclude` and `CppWinRTModuleExclude` control which namespace `.ixx` files are **generated**, but they do not suppress `import` statements for dependencies. If namespace A is included in the filter and depends on namespace B, the generated `winrt.A.ixx` will contain `import winrt.B;` even if B is excluded from the filter. This is by design — the module for B must exist *somewhere* (either from the same project or from a referenced project). -This has important implications: +Implications: - **Transitive closure must be satisfied.** If you filter to a subset of namespaces, any dependencies that fall outside the filter must be available from another source (e.g., a module builder project referenced via `CppWinRTConsumeModule`, or MSBuild's automatic `ReferencedModuleBMIs` from a static library reference). Otherwise, compilation will fail with "could not find module" errors. @@ -141,39 +236,289 @@ This has important implications: | `winrt_numerics` | `Windows::Foundation::Numerics` types — re-exported by `winrt_base` | | `winrt.` | Per-namespace projection (e.g., `winrt.Windows.Foundation`) | -## Requirements +## Converting an Existing Project: Step by Step -- MSVC v145 toolset (Visual Studio 2026) or later recommended -- C++20 or later (`/std:c++20` or newer) -- `BuildStlModules=true` for `import std;` support +### 1. Strip winrt from the PCH -## Limitations +Module `import` declarations inside a precompiled header cause compiler ICEs. All C++/WinRT content must be moved out of the PCH and into the module preamble header (see next step). -- Module IFCs are not compatible across toolset versions. All projects must use the same toolset. -- Cyclic namespace dependencies (e.g., `Windows.Foundation` ↔ `Windows.Foundation.Collections`) are handled automatically via SCC consolidation, but the resulting module name is chosen alphabetically. Adding new APIs could change SCC groupings. +Remove the following from your PCH: + +- `#include ` — all winrt projection headers +- `#include ` and `` +- Any header that depends on C++/WinRT types, **including headers that conditionally enable behavior based on C++/WinRT header guards.** For example, `wil/cppwinrt_helpers.h` checks for `WINRT_Windows_UI_Core_H` and uses types from `Windows.UI.Core` when defined — this header must move out of the PCH. + +**Keep** in the PCH: + +- Platform SDK headers (``, ``, etc.) +- Non-winrt third-party headers + +**STL headers and `import std;`** — STL headers are safe to include *before* `import std;` (include-then-import works). Problems arise when STL headers are included *after* `import std;`, which can cause redefinition warnings (C4348, C5028). In most cases it is preferable to use `import std;` instead of putting STL headers in the PCH. However, if you depend on libraries that internally `#include` STL headers *after* modules have been imported, you may need to pre-include the offending STL headers in the PCH to make the later inclusion inert: + +```cpp +// Pre-include STL headers that other libraries include after import std; +#include +#include +``` + +Ideally, the offending library code would also adopt `import std;`, but that's not always immediately practical. + +### 2. Create a Module Preamble Header + +A module preamble header centralizes the module imports and library setup that are shared across a project's source files. It is not strictly required — you could add imports directly to each `.cpp` file — but it speeds up migration significantly and becomes necessary if you need to deal with generated files outside your control (see [XAML Projects](#xaml-projects)). + +Create a preamble header in each project that contains the module imports commonly used across that project: + +```cpp +// ModulePreamble.h (or whatever name you prefer) +#pragma once + +#define WINRT_IMPORT_MODULE + +// Import the C++/WinRT namespaces used across this project +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Collections; +import winrt.Windows.System; +// ... other namespaces your project needs + +// Component modules +import winrt.MyCompany.MyComponent; +``` + +Importing modules is cheap, so don't hesitate to list every namespace the project uses. You can add library wrapper headers and other setup to this file as needed (see next section). + +Include the preamble in each `.cpp` file after the PCH: + +```cpp +#include "pch.h" +#include "ModulePreamble.h" +// ... rest of the file +``` + +### 3. Wrap Library Headers That Depend on C++/WinRT Types + +Libraries like WIL use `#ifdef WINRT_Windows_Foundation_H` guards to conditionally enable winrt-dependent features. With modules, those header guards are never defined because the winrt headers are never textually included. To light up this behavior, define the appropriate header guards before including the library header — or, equivalently, include the now-inert winrt headers under `WINRT_IMPORT_MODULE`, which defines the guards as a side effect. + +You can do this directly in the module preamble: + +```cpp +// In your module preamble header +import winrt.Windows.Foundation; +#define WINRT_IMPORT_MODULE +#define WINRT_Windows_Foundation_H // Lights up WIL's Foundation support +#include +``` + +If you include the library from many places, you can author a **wrapper header** that bundles the imports, guard definitions, and library include together: + +```cpp +// wil_cppwinrt_module.h +#pragma once + +import winrt_base; +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Collections; + +#define WINRT_IMPORT_MODULE +// Define header guards to light up WIL's conditional winrt features. +// You can either define the guards directly, or include the now-inert +// winrt headers (which define the guards as a side effect): +#include +#include + +#include +#include +``` + +Include this wrapper in your module preamble as needed. Re-importing modules and re-defining header guards is harmless, so there's no issue with including the wrapper from multiple places. + +This pattern applies to any library that conditionally uses winrt types based on header include guards. + +### 4. Update the vcxproj + +```xml + +true +MyCompany.MyComponent +Microsoft.UI;Microsoft.Web + + + + true + +``` + +### 5. Add Solution Build Dependency + +If using `.slnx` or `.sln`, add a build dependency to ensure the module builder, if using, compiles first: + +```xml + +``` + +## Special Cases + +### XAML Projects + +XAML projects have a two-pass compilation model that complicates module adoption. The XAML compiler generates source files (`XamlTypeInfo.g.cpp`, `XamlTypeInfo.Impl.g.cpp`, `XamlMetaDataProvider.cpp`) that use winrt types but don't know about modules. + +The solution is to inject `ModulePreamble.h` via the `/FI` (forced include) compiler flag on these generated files, using MSBuild targets: + +```xml + + + + + NotUsing + $(MSBuildProjectDirectory)\ModulePreamble.h + + + +``` + +For static library projects, the XAML build system has a second compilation pass (`CompileXamlGeneratedFiles`) that runs after `ClCompile` but before `Lib`. For DLLs and EXEs, the same targets run after the build compile phase. In either case, you need a second target to ensure the `/FI` metadata is applied before `CompileXamlGeneratedFiles`: + +```xml + + + + NotUsing + $(MSBuildProjectDirectory)\ModulePreamble.h + + + +``` + +**Critical MSBuild detail:** Use ``, not just ``. Without `Update`, MSBuild adds new items instead of modifying metadata on existing ones. + +**Why the preamble header needs `#include "pch.h"` for XAML:** When used as `/FI`, the preamble header is processed *before* the generated file's own `#include "pch.h"`. Adding `#include "pch.h"` at the top of the preamble ensures platform headers are available. For regular `.cpp` files that already include pch.h before the preamble, it's a `#pragma once` no-op. If your project doesn't use the `/FI` approach for XAML, you don't need pch.h in the preamble. + +#### Understanding the XAML Build Order + +The XAML build targets schedule `MarkupCompilePass2` and `CompileXamlGeneratedFiles` differently depending on project type: + +- **Static libraries** (`AfterClCompileTargets`): Pass2 runs after `ClCompile`, before `Lib` +- **DLLs/EXEs** (`AfterBuildCompileTargets`): Pass2 runs after the build compile phase, before `Link` + +In both cases, the order is: + +1. **MarkupCompilePass1** (before `ClCompile`): Generates `.xaml.g.h` declarations +2. **ClCompile**: Compiles your source files +3. **MarkupCompilePass2**: Generates `.xaml.g.hpp` implementations +4. **CompileXamlGeneratedFiles**: Compiles `XamlTypeInfo.g.cpp` (which `#include`s the `.xaml.g.hpp` files) + +The XAML-generated items (`XamlTypeInfo.g.cpp`, etc.) are added to `ClCompile` by the `ComputeXamlGeneratedCompileInputs` target, which is why the `/FI` target uses `AfterTargets="ComputeXamlGeneratedCompileInputs"`. + +### Headers with Conditional winrt Conversions + +If you have utility types (like a `color` struct) with conversion operators gated behind winrt header guards: + +```cpp +#ifdef WINRT_Windows_UI_H + operator winrt::Windows::UI::Color() const { ... } +#endif +``` + +These guards must be defined **before** the header is first included (`#pragma once` means it won't be processed again). Create a dedicated wrapper that imports the module, sets the guard, then re-includes the header: + +```cpp +// color_module.h +#pragma once +import winrt.Windows.UI; +#define WINRT_IMPORT_MODULE +#include // Sets WINRT_Windows_UI_H +#include // Now sees the guard, enables converters +``` + +Include this wrapper in your `ModulePreamble.h` **before** any other header that might include the guarded file. + +### Win32 Macro Conflicts + +Some Win32 macros (e.g., `GetObject` from `wingdi.h`) conflict with WinRT method names. With headers, the macro was applied to both the projection types and the call site. With modules, the WinRT types don't have the macro applied (they were compiled in the module without the macro), but your source file still has the macro defined. Use: + +```cpp +#pragma push_macro("GetObject") +#undef GetObject +// ... code using winrt types with GetObject method +#pragma pop_macro("GetObject") +``` ## Caution: Module Reuse Across Projects Pre-built IFCs (via `CppWinRTConsumeModule`) should only be shared when the builder and consumer use the same compilation context. In particular: -- **Component modules are project-private.** A component projection built with `CppWinRTOptimized=true` generates modules that bypass activation factories for in-component type instantiation (`-opt`). If a consuming project accidentally imports these modules instead of building its own reference projection, the consumer will attempt direct instantiation across DLL boundaries, resulting in linker errors or incorrect behavior. Each project should build its own modules from the component's `.winmd` — do not tag component ProjectReferences with `CppWinRTConsumeModule`. +- **Component modules are project-private.** A component projection built with `CppWinRTOptimized=true` generates modules that bypass activation factories for in-component type instantiation (`-opt`). If a consuming project accidentally imports these modules instead of building its own reference projection, the consumer will attempt direct instantiation across DLL boundaries, resulting in linker errors or incorrect behavior. Each project should build its own modules from the component's `.winmd` — do not tag component `ProjectReference`s with `CppWinRTConsumeModule`. -- **`CppWinRTConsumeModule` is intended for platform module builders only.** The builder project is a dedicated static library whose sole purpose is compiling platform SDK modules. Its compilation flags (no `-opt`, no `-comp`) produce modules safe for any consumer. Only tag this builder's ProjectReference with `CppWinRTConsumeModule=true`. +- **`CppWinRTConsumeModule` is intended for platform module builders only.** The builder project is a dedicated static library whose sole purpose is compiling platform SDK modules. Its compilation flags (no `-opt`, no `-comp`) produce modules safe for any consumer. Only tag this builder's `ProjectReference` with `CppWinRTConsumeModule=true`. - **Module filter scope matters.** `CppWinRTModuleInclude` / `CppWinRTModuleExclude` applies to all three projections (platform, reference, component). If you set `CppWinRTModuleInclude=MyComponent`, only `MyComponent` namespaces will get `.ixx` files — platform and reference namespace modules will not be generated. Make sure your filter includes all namespaces you intend to import as modules, or use `CppWinRTConsumeModule` to get platform modules from a builder that was configured with the appropriate filter. - **Compilation settings must be compatible between builder and consumer.** Module IFCs encode assumptions about the compilation environment. While the compiler may not always diagnose mismatches, the following differences between the module builder and consumer may cause subtle or hard-to-diagnose issues: - - **Debug vs Release** — Mixing Debug and Release configurations can produce mismatched code generation, iterator debugging levels, and runtime library selections. - - **Preprocessor definitions** — Definitions that affect type layout, conditional compilation, or feature flags should match between builder and consumer. - - **Struct alignment / packing** — Different `/Zp` settings between projects can change struct layout, causing silent ABI mismatches. - - **Language standard** — While C++20 and later are generally compatible, mixing `/std:c++20` and `/std:c++23` and/or `/std:c++latest` if there are language features that affect type definitions. + - **Debug vs Release** — mixing Debug and Release configurations can produce mismatched code generation, iterator debugging levels, and runtime library selections. + - **Preprocessor definitions** — definitions that affect type layout, conditional compilation, or feature flags should match between builder and consumer. + - **Struct alignment / packing** — different `/Zp` settings between projects can change struct layout, causing silent ABI mismatches. + - **Language standard** — while C++20 and later are generally compatible, mixing `/std:c++20` and `/std:c++23` and/or `/std:c++latest` can affect type definitions if language features differ. + + As a general rule, the module builder project should try to use the same configuration, preprocessor definitions, and compiler options as its consumers. + +## Limitations + +- Module IFCs are not compatible across toolset versions. All projects must use the same toolset. +- Cyclic namespace dependencies (e.g., `Windows.Foundation` ↔ `Windows.Foundation.Collections`) are handled automatically via SCC consolidation, but the resulting module name is chosen alphabetically. Adding new APIs could change SCC groupings. + +## Common Errors and Solutions + +| Error | Cause | Solution | +|-------|-------|----------| +| **C2230**: could not find module `winrt.X` | Missing import or the module IFC wasn't built | Add the import; verify the module builder or consumer produces it; check `CppWinRTModuleInclude` | +| **C7684**: ambiguous resolution to IFC | Same module built by multiple projects visible to the consumer | Add the namespace to `CppWinRTModuleExclude` | +| **C4348**: redefinition of default parameter | STL header included after `import std;` | Pre-include the STL header in the PCH (e.g., `#include `) | +| **C5028**: alignment specified in prior declaration | Same root cause as C4348 | Pre-include the STL header (e.g., `#include `) | +| **C4430 / C2039**: missing type / not a member | Type not visible because module not imported | Add the missing `import winrt.Namespace;` to ModulePreamble | +| **LNK2019**: unresolved external for `InitializeComponent` | XAML-generated code compiled without module imports | Ensure the `/FI` targets are present and use `Update="@(ClCompile)"` | +| **LNK2005**: symbol already defined | XAML-generated file compiled both directly and via a wrapper | Use the `/FI` injection approach instead of wrapper `.cpp` files | +| Redefinition errors when mixing `#include` and `import` | Same namespace included textually after being imported | Define `WINRT_IMPORT_MODULE` before the winrt header, or remove the `#include` | +| **"could not find module 'winrt.X'"** in cross-project consumer | Builder's `IntDir` not visible to consumer | Verify `ProjectReference` to the builder has `CppWinRTConsumeModule=true` | +| Linker errors for component constructors | Importing a component's internal module instead of building your own reference projection | Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd` | + +## Tips + +- **Clean build after configuration changes.** Stale IFC files from previous builds cause confusing ambiguity errors. Clean the intermediate directory when changing module include/exclude filters. +- **Start from leaf projects.** Convert projects with no WinRT component dependencies first (e.g., utility libraries), then work up the dependency graph. +- **One project at a time.** Each conversion may surface new missing imports or exclude requirements. Building incrementally makes errors easier to diagnose. +- **Watch for transitive IFC propagation.** Static library IFCs become visible to all consumers in the reference chain. This is correct behavior but requires `CppWinRTModuleExclude` entries in consumers. +- **`CppWinRTModuleInclude` is usually needed.** Without it, projects with `CppWinRTModuleExclude` may not generate any `.ixx` files at all. Specify the namespace prefix for your component (e.g., `Microsoft.Terminal`). +- **DLL wrapper projects typically need no changes.** If you have a pattern of "static lib + thin DLL wrapper", the DLL wrapper usually just links the lib and doesn't need module conversion. + +## Approaches Tried and Abandoned + +For posterity, these patterns were attempted during the Terminal prototype but proved problematic. Avoid them. + +### Wrapper `.module.cpp` files for XAML-generated code + +The idea was to create wrapper `.cpp` files that would `#include` the XAML-generated files after setting up module imports, then remove the original generated items from `ClCompile` and replace them with the wrappers. + +**Why it failed:** The XAML build system generates files across two compilation passes. `XamlTypeInfo.g.cpp` `#include`s `.xaml.g.hpp` files that don't exist until Pass2, but the wrapper needed to compile during the first `ClCompile` pass. `__has_include` guards to make wrappers compile empty initially and recompile later proved unreliable — `CompileXamlGeneratedFiles` is a separate compilation step, and the wrapper items weren't correctly routed through it. + +**The `/FI` approach works** because it modifies the compiler flags on the *existing* generated items rather than replacing them, working with the XAML build system's two-pass compilation. + +### `AllProjectBMIsArePublic=false` on static libraries - As a general rule, the module builder project try to use the same configuration, preprocessor definitions, and compiler options as its consumers. +The idea was to prevent IFC propagation from static libraries by setting `AllProjectBMIsArePublic=false`, hiding the static lib's IFCs from consumers. -## Troubleshooting +**Why we moved away:** This fights against the intended VC++ build model. If a project consumes a static library, it should also consume that library's IFC files. Using different IFCs for the same types risks ODR violations. The `CppWinRTModuleExclude` approach is better — the consumer avoids building duplicate IFCs while still consuming the producer's IFCs. -**"could not find module 'winrt.X'"** — Ensure the `.ixx` was generated (check `$(GeneratedFilesDir)winrt\`) and that `CppWinRTBuildModule=true` is set. For cross-project references, verify the consuming project's `ProjectReference` to the builder has `CppWinRTConsumeModule=true`, and that the builder's `IntDir` is accessible via `/ifcSearchDir`. +### Moving wrapper items into MSBuild targets -**Linker errors for component constructors** — You may be importing a component's internal module instead of building your own reference projection. Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd`. +The idea was to add wrapper `.cpp` `ClCompile` items inside a `` (dynamically) instead of a static ``, so they'd only enter `ClCompile` after generated files existed. -**Redefinition errors** — Don't mix `#include` and `import` for the same namespace in the same translation unit. Use `import` consistently. +**Why it failed:** Items added inside targets don't get the same metadata processing (module dependency scanning, IFC reference resolution) as items in static `ItemGroup`s. The compiler couldn't find any modules. diff --git a/nuget/readme.md b/nuget/readme.md index c8c0b9537..16eb5d2bb 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -137,7 +137,9 @@ void DerivedPage::InitializeComponent() ## C++20 Modules -C++/WinRT supports C++20 named modules as an alternative to `#include`-based consumption. Instead of `#include `, you can write `import winrt.Windows.Foundation;`. See [modules.md](modules.md) for the full guide. +C++/WinRT supports C++20 named modules as an alternative to `#include`-based consumption. Instead of `#include `, you can write `import winrt.Windows.Foundation;`. + +See the [C++/WinRT C++20 Modules Guide](https://github.com/microsoft/cppwinrt/blob/master/nuget/modules.md) for the full guide (also shipped alongside this file as `modules.md`). | ProjectReference metadata | Description | |-|-| diff --git a/nuget/readme.txt b/nuget/readme.txt index 049ab13b8..8d2681b6b 100644 --- a/nuget/readme.txt +++ b/nuget/readme.txt @@ -19,4 +19,7 @@ In addition, C++/WinRT generates templates and skeleton implementations for each ======================================================================== For more information, visit: https://github.com/Microsoft/cppwinrt/tree/master/nuget + +The full documentation is also included in this package as readme.md, and +the C++20 modules guide as modules.md. ======================================================================== From a31a05cedeee239995bbb09ea6867fbda9bb0fab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:56:29 -0700 Subject: [PATCH 298/305] Bump actions/checkout from 6 to 7 (#1600) Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ryan Shepherd --- .github/workflows/check-line-endings.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml index a0705cf58..dea958274 100644 --- a/.github/workflows/check-line-endings.yml +++ b/.github/workflows/check-line-endings.yml @@ -11,7 +11,7 @@ jobs: name: Enforce .gitattributes line endings runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check for line ending violations run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37f42ab70..afdeed462 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: config: Release runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Download nuget run: | @@ -113,7 +113,7 @@ jobs: test_exe: test_cpp20_module runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' @@ -263,7 +263,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Install cross compiler run: | @@ -296,7 +296,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Download nuget run: | @@ -339,7 +339,7 @@ jobs: platform_toolset: v145 runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Fetch cppwinrt executables uses: actions/download-artifact@v8 @@ -384,7 +384,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Package run: | From a535d38f083e6a428b64ac47e3144653c9739bc5 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:38:40 -0700 Subject: [PATCH 299/305] Fix C4819 warning: replace non-ASCII em dash in base_macros.h comment (#1606) * Initial plan * Fix C4819 warning: replace non-ASCII em dash with ASCII hyphen in base_macros.h comment --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- strings/base_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_macros.h b/strings/base_macros.h index 91b0121d9..850d0c627 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -44,7 +44,7 @@ // Template specializations in namespace std (hash, coroutine_traits) need extern "C++" // linkage in module builds for proper merging with the std module, but must NOT be -// exported — exporting namespace std would make all of std transitively visible. +// exported - exporting namespace std would make all of std transitively visible. #ifndef WINRT_IMPL_STD_EXPORT #ifdef WINRT_IMPL_BUILD_MODULE #define WINRT_IMPL_STD_EXPORT extern "C++" From d3d92d70e3e089307ab6d6deb5ed39c7a534fec2 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 27 Jul 2026 09:39:55 -0700 Subject: [PATCH 300/305] Fix race condition in cancellation setup/teardown (#1609) The code failed to handle three cases. 1. A cancellation is in progress when a cancellable awaitable begins. 2. A cancellation is in progress when a cancellable awaitable ends. 3. A cancellation is in progress when a cancel() request is made. The m_canceller member has one of these three values: * nullptr, meaning that there is nothing to cancel. It has this value when the coroutine is not awaiting, or if it is awaiting something that cannot be cancelled. * cancelling_ptr, meaning that another thread (not the coroutine thread) is in the middle of cancellation request. * function pointer, representing the function to call to cancel the await. In case 1, we should not overwrite the canceling_ptr with the function pointer, because only the code doing the cancel() can transition into/out of cancelling_ptr. In case 2, we intended to spin until the m_canceller is no longer cancelling_ptr, but we used m_canceller.exchange(nullptr) in a loop, which means that if m_canceller was cancelling_ptr, we overwrite it with nullptr. As a result, the "while" loop always exits after one iteration. We need to spin on the m_canceller without modifying it if it is cancelling_ptr. In case 3, cancel() function resets m_cancelling back to nullptr, even if the value was cancelling_ptr on entry, prematurely declaring that the existing cancel() has completed. If the original value was cancelling_ptr, we should leave it that way. There are still other cases not handled: * Coroutine already cancelled when a co_await starts. In this case, we never call the canceller, so the coroutine fails to propagate cancellation. This will require a broader fix, so I'm not going to fix it in this PR. This PR is primarily about fixing the crash caused by case 2. Cases 1 and 3 were fixed opportunistically. --- strings/base_coroutine_threadpool.h | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 057d5b548..c901b94ba 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -146,32 +146,42 @@ WINRT_EXPORT namespace winrt void set_canceller(canceller_t canceller, void* context) { m_context = context; - m_canceller.store(canceller, std::memory_order_release); + canceller_t expected = nullptr; + m_canceller.compare_exchange_strong(expected, canceller, std::memory_order_release, std::memory_order_relaxed); } void revoke_canceller() { - while (m_canceller.exchange(nullptr, std::memory_order_acquire) == cancelling_ptr) + auto existing = m_canceller.load(std::memory_order_relaxed); + do { - std::this_thread::yield(); + while (existing == cancelling_ptr) + { + std::this_thread::yield(); + existing = m_canceller.load(std::memory_order_relaxed); + } } + while (!m_canceller.compare_exchange_weak(existing, nullptr, std::memory_order_acquire, std::memory_order_relaxed)); } void cancel() { auto canceller = m_canceller.exchange(cancelling_ptr, std::memory_order_acquire); - struct unique_cancellation_lock + if (canceller != cancelling_ptr) { - cancellable_promise* promise; - ~unique_cancellation_lock() + struct unique_cancellation_lock + { + cancellable_promise* promise; + ~unique_cancellation_lock() + { + promise->m_canceller.store(nullptr, std::memory_order_release); + } + } lock{ this }; + + if (canceller != nullptr) { - promise->m_canceller.store(nullptr, std::memory_order_release); + canceller(m_context); } - } lock{ this }; - - if ((canceller != nullptr) && (canceller != cancelling_ptr)) - { - canceller(m_context); } } From d6cff316a991152071038668fb586a8b5ab1d51f Mon Sep 17 00:00:00 2001 From: Derek Morris Date: Mon, 27 Jul 2026 18:15:40 -0700 Subject: [PATCH 301/305] Add header to base_includes.h (#1612) base_types.h uses std::ratio_multiply, which is defined in . Under strict include-what-you-use rules not referencing this header can lead to weird build breaks. --- strings/base_includes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/strings/base_includes.h b/strings/base_includes.h index 287a09709..bac7358bd 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include From a7f0233d64620801fd281ae970fe39a2943eca34 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Thu, 20 Aug 2026 01:49:04 +0800 Subject: [PATCH 302/305] Remove WINRT_EXPORT in Component.g.cpp (#1597) Co-authored-by: Ryan Shepherd --- cppwinrt/code_writers.h | 11 +++++++++++ cppwinrt/component_writers.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index ab119ae89..b3855c097 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -226,6 +226,17 @@ namespace cppwinrt return { w, write_close_namespace }; } + [[nodiscard]] static finish_with wrap_type_namespace_without_export(writer& w, std::string_view const& ns) + { + auto format = R"(namespace winrt::@ +{ +)"; + + w.write(format, ns); + + return { w, write_close_namespace }; + } + static void write_enum_field(writer& w, Field const& field) { auto format = R"( % = %, diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index af5626d14..94e20e53e 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -400,7 +400,7 @@ catch (...) { return winrt::to_hresult(); } return; } - auto wrap_type = wrap_type_namespace(w, type_namespace); + auto wrap_type = wrap_type_namespace_without_export(w, type_namespace); for (auto&&[factory_name, factory] : get_factories(w, type)) { From 74a13c5617c04ddc8ae42e087cfb1dd1617bcfaa Mon Sep 17 00:00:00 2001 From: Jon Wiswall Date: Mon, 24 Aug 2026 14:51:11 -0700 Subject: [PATCH 303/305] C++/WinRT ABI interop improvements (#1608) * Add _hs literal for compile-time fast-pass HSTRING Passing a wide string literal to a WinRT API that takes an hstring runs wcslen and fills a seven-field HSTRING_HEADER on the stack on every call (via param::hstring -> create_hstring_on_stack). For a literal, all of that is knowable at compile time and only needs to happen once. Add a `_hs` user-defined literal that builds the fast-pass reference header as a constexpr static, so `L"value"_hs` reduces to a single pointer load at the call site with no per-call wcslen or header fill. The literal-operator-template is keyed on the characters themselves via a C++20 non-type template parameter (hstring_literal_storage), so each distinct literal gets its own static header with static lifetime. It returns a non-owning winrt::hstring_reference (a plain winrt::hstring would assert/free the reference header in its destructor). A matching param::hstring constructor lets the result bind to projected setters in a single user-defined conversion. A bare `param::hstring(wchar_t const(&)[N])` overload is deliberately not added: it would also bind non-literal arrays (e.g. a partially-filled wchar_t buf[260]) and infer length N-1 past the null, silently corrupting; and a runtime constructor cannot produce a content-specific static anyway. `_hs` is the explicit, safe opt-in; bare literal calls keep their unchanged wcslen path. Gated on __cpp_nontype_template_args >= 201911L. Tested under C++20 in test_cpp20/hstring_literal.cpp; the non-gated types build under C++17. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Add make_ready for pre-completed async operations Returning an already-available value through an async-typed API (a cache hit, a fast path, or an API async-typed only for interface uniformity) still pays the full coroutine cost when written as `co_return value`: a heap-allocated coroutine frame plus a promise that is a complete COM object implementing IAsyncOperation and IAsyncInfo, carrying a slim_mutex, an agile completed-handler slot, an atomic status, and cancel machinery, all built and torn down on every call. Add winrt::make_ready(value) and winrt::make_ready() that return a minimal already-completed IAsyncOperation / IAsyncAction: it holds just the value with a fixed Completed status and no coroutine frame, no slim_mutex, no handler slot, and no cancel machinery. Setting a Completed handler on it invokes immediately, and Status()/GetResults() satisfy both the .get() and co_await consumer paths, so it is a drop-in for the synchronous-result case. `co_return` remains correct for genuinely suspending work, where the frame is doing real work and the overhead is amortized to noise. The one-shot Completed assignment is guarded with a lock-free atomic flag rather than a lock. Tested in test/make_ready.cpp. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Buffer range-for iteration over non-GetAt collections Range-for over a collection that lacks GetAt (a plain IIterable, or a map yielding IKeyValuePair) drove the projected IIterator one element per ABI crossing via Current/MoveNext. For a large sequence that is one vtable call per item. Route that path through a buffered_iterator that pulls a block of elements with a single IIterator::GetMany call into a small stack buffer and yields from it, refilling only when the buffer is drained. Existing `for (auto&& x : v)` code gets the speedup with no source change. The block is sized like windows-rs' BufferedIterator -- clamp(2048 / sizeof(T), 1, 128) -- to cap the buffer near 1-2 KB and bound over-fetch for large element types. Only the non-GetAt path changes. Collections with GetAt (IVector, IVectorView) keep the existing random-access fast_iterator, so no iterator-category guarantees are affected. The iterator is single-pass, matching IIterator's own semantics. Tested in test/buffered_iterator.cpp (multi-block, block boundary, empty, and a non-trivial element type). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Perfect-forward make_ready value Use TResult&& + decay_t so make_ready forwards its argument into the operation instead of taking it by value, saving a move and matching the make_unique/make_shared idiom. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Make _hs a constant expression Move the fast-pass header from a function-local static into an inline constexpr variable template and mark hstring_reference and the operator constexpr, so `constexpr auto s = L"x"_hs;` is a genuine compile-time construction rather than per-call work. Add a constexpr construction to the test to prove it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Box scalars locally instead of via combase PropertyValue box_value on a scalar routed through the cached Windows.Foundation. PropertyValue activation factory into combase, which allocates a general IPropertyValue carrying the discriminated-union machinery for all property types. For the common scalar cases that round-trip is pure overhead. Point the scalar reference_traits (u8..u64, float, double, bool, char16, hstring, guid) at the in-process impl::reference that already backs non-scalar IReference, and make that type a correct IPropertyValue: report the right PropertyType per T (was always OtherType), fix IsNumericScalar (was true for bool), and return the value from the matching typed getter (GetString/GetGuid/GetBoolean/GetChar16/GetSingle/GetDouble previously threw). Mismatched numeric getters keep combase-style conversion (GetInt16 on a boxed int32 converts), so consumers see the same behavior minus the combase hop. This mirrors windows-rs' StockReference. Composite/array/inspectable cases (DateTime, TimeSpan, Point, Size, Rect, IReferenceArray, IInspectable) stay on combase PropertyValue. Two honest deltas vs combase, both matching windows-rs: GetRuntimeClassName is now the IReference`1 name rather than Windows.Foundation. PropertyValue, and cross-process the value marshals as an IReference proxy rather than by value. Tested in test/reference_boxing.cpp. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Marshal boxed scalars by value via combase PropertyValue The in-proc scalar reference introduced in the prior commit is agile via the free-threaded marshaler, so cross-process it marshals by reference (an IReference proxy) rather than by value the way combase PropertyValue does. Mirror windows-rs and combase: for the stock scalar types, mark reference non_agile and supply IMarshal from query_interface_tearoff by lazily building the equivalent combase PropertyValue and delegating marshaling to it, so the destination materializes a real PropertyValue copy. IAgileObject is still advertised (the reference is immutable and thread-safe) to keep the agile fast path. The combase hop is paid only on marshal, never on box_value/unbox_value. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Box DateTime, TimeSpan, and Point in-process too Extend the in-proc reference to cover DateTime, TimeSpan, and Point: report the correct PropertyType, return the value from the matching typed getter, and mark them stock so they still marshal by value through combase PropertyValue. Drop their combase reference_traits specializations so box_value routes to the local reference like the other scalars. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Buffer range-for over GetAt collections (batch IVector via GetMany) fast_iterator (used for random-access, GetAt-capable collections like IVector/ IVectorView) now prefetches a block with a single GetMany call and serves in-window reads from it, so range-for crosses the ABI ~once per block instead of one GetAt per element. Random access is preserved: an out-of-window index re-anchors the block, and an at/after-end index defers to GetAt so E_BOUNDS behavior is unchanged. Elements are copied out (no move-out) so an index may be read repeatedly, as the random-access contract requires. This extends the non-GetAt buffering to vectors, closing the IterateVector gap to windows-rs. * Fix MSVC and clang-cl build breaks from the interop fast paths Three portability breaks surfaced by CI across MSVC and clang-cl: - Iterator batching assumed every collection/iterator has GetMany and every element type is default-constructible. IBindableVectorView has GetAt but no GetMany, IBindableIterator has no GetMany, and types like JsonValue have no default constructor. Gate the GetMany block buffer on both a GetMany detector and default-constructibility (can_batch); otherwise fall back to per-element GetAt / Current+MoveNext. The block buffer is elided entirely when unused. - reference::query_interface_tearoff called .as() on a dependent expression; clang requires .template as(). - hstring_reference::m_handle is only read via layout punning in get_abi, so clang -Werror,-Wunused-private-field rejected it. Mark it [[maybe_unused]]. Verified: msbuild cppwinrt + test/test_old (MSVC) and test/test_nocoro/test_old (clang-cl), x64 Debug, all build clean. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Add optional clang compiler arg to build_test_all.cmd build_test_all.cmd only built the MSVC toolset, so a local pass did not catch clang-cl -Werror breaks that CI's clang-cl leg rejects. Add an optional 5th positional arg (default msvc); pass clang/clang-cl to append Clang=1,PlatformToolset=ClangCl to the cppwinrt.sln compiler and test builds, matching CI. natvis and NugetTest.sln stay on MSVC, as the clang CI leg does not cover them. Also fix a stray trailing quote on the nuget restore line and document the arg in README. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Guard _hs test's literals using-directive for non-conforming NTTP compilers hstring_literal.cpp had an unconditional using-directive for winrt::literals, but that namespace and its operator ""_hs only exist under __cpp_nontype_template_args >= 201911L. clang-cl reports 201411L (no class-type NTTP), so the namespace is absent and the using-directive failed to compile ("expected namespace name"), breaking the clang-cl test_cpp20 leg. Move the using-directive inside the same feature guard the rest of the test already uses. Verified: full CI test-project set builds clean on both MSVC v145 and clang-cl, x64 Debug. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Remove buffered-iterator and ready-async helpers Drop the batched range-for iterator (base_iterator.h) and the already-completed make_ready/ready_async async helpers (base_coroutine_foundation.h), reverting both headers to their base state. These will be reintroduced in wil/cppwinrt.h. Removes the buffered_iterator.cpp and make_ready.cpp tests accordingly. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Simplify reference_base_t and test in-proc agility Collapse reference_base_t to a single implements<> whose trailing marker is conditional (non_agile for stock scalars, an inert marker placeholder otherwise), instead of duplicating the interface list across a conditional_t. implements<> ignores non-interface, non-marker type parameters, so the placeholder is a no-op. Add a test that boxes a scalar in one STA and fetches it from another via the Global Interface Table, asserting the object identity is preserved - proving the IAgileObject in-proc fast path. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Box arrays locally and address review feedback Add an in-process reference_array (IReferenceArray + IPropertyValue), the array counterpart to reference, so box_value/unbox_value of the stock array element types no longer builds a combase PropertyValue. hstring, TimeSpan, DateTime (projected type != ABI) and IInspectable/Size/Rect stay on combase. Collapse every IPropertyValue getter on both types into one internal get_as() that holds the constexpr type check and throw, and share a scalar_property_type()/array_property_type() helper. Also fold in the earlier review fixes: single implements<> with a conditional trailing marker for reference_base_t, GetSize/GetRect fast paths, an _hs null-termination static_assert, and drop the duplicate test_module_lock_none build in build_test_all.cmd. Extend reference_boxing.cpp with array boxing, array marshal-by-value, and cross-STA agile identity coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Share a producer base, drop comments and build-script changes Fold the duplicated IPropertyValue getters and IMarshal tearoff shared by reference and reference_array into a reference_producer CRTP base; the two leaves just supply storage, get_as, and create_property_value. Same codegen and per-instance footprint as the two-template version, ~80 fewer source lines. Per review feedback, strip the newly-added implementation comments from base_reference_produce.h and base_string.h, and revert the build_test_all.cmd compiler-selection helper and its README note so this PR carries only the projection/boxing functionality. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jon Wiswall <18537118+jonwis@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 --- strings/base_reference_produce.h | 423 ++++++++++++++++------------ strings/base_string.h | 80 ++++++ strings/base_string_input.h | 4 + test/test/reference_boxing.cpp | 268 ++++++++++++++++++ test/test/test.vcxproj | 1 + test/test_cpp20/hstring_literal.cpp | 68 +++++ test/test_cpp20/test_cpp20.vcxproj | 1 + 7 files changed, 660 insertions(+), 185 deletions(-) create mode 100644 test/test/reference_boxing.cpp create mode 100644 test/test_cpp20/hstring_literal.cpp diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index abffb3384..db9639cc3 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -2,99 +2,197 @@ WINRT_EXPORT namespace winrt::impl { template - struct reference : implements, Windows::Foundation::IReference, Windows::Foundation::IPropertyValue> + struct reference; + + template + struct reference_array; + + template + inline constexpr bool is_stock_reference_v = + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; + + template + constexpr Windows::Foundation::PropertyType scalar_property_type() noexcept + { + using pt = Windows::Foundation::PropertyType; + + if constexpr (std::is_same_v) { return pt::UInt8; } + else if constexpr (std::is_same_v) { return pt::Int16; } + else if constexpr (std::is_same_v) { return pt::UInt16; } + else if constexpr (std::is_same_v) { return pt::Int32; } + else if constexpr (std::is_same_v) { return pt::UInt32; } + else if constexpr (std::is_same_v) { return pt::Int64; } + else if constexpr (std::is_same_v) { return pt::UInt64; } + else if constexpr (std::is_same_v) { return pt::Single; } + else if constexpr (std::is_same_v) { return pt::Double; } + else if constexpr (std::is_same_v) { return pt::Char16; } + else if constexpr (std::is_same_v) { return pt::Boolean; } + else if constexpr (std::is_same_v) { return pt::String; } + else if constexpr (std::is_same_v) { return pt::Inspectable; } + else if constexpr (std::is_same_v) { return pt::Guid; } + else if constexpr (std::is_same_v) { return pt::DateTime; } + else if constexpr (std::is_same_v) { return pt::TimeSpan; } + else if constexpr (std::is_same_v) { return pt::Point; } + else if constexpr (std::is_same_v) { return pt::Size; } + else if constexpr (std::is_same_v) { return pt::Rect; } + else { return pt::OtherType; } + } + + template + constexpr Windows::Foundation::PropertyType array_property_type() noexcept { - reference(T const& value) : m_value(value) - { - } + return static_cast( + static_cast(scalar_property_type()) + 1024); + } - T Value() const - { - return m_value; - } + template + inline constexpr bool is_numeric_scalar_v = + (std::is_arithmetic_v && !std::is_same_v && !std::is_same_v) || std::is_enum_v; + template + struct reference_producer : implements, non_agile, marker>> + { Windows::Foundation::PropertyType Type() const noexcept { - return Windows::Foundation::PropertyType::OtherType; + if constexpr (IsArray) { return array_property_type(); } + else { return scalar_property_type(); } } static constexpr bool IsNumericScalar() noexcept { - return std::is_arithmetic_v || std::is_enum_v; + return !IsArray && is_numeric_scalar_v; } - std::uint8_t GetUInt8() const - { - return to_scalar(); - } + std::uint8_t GetUInt8() const { return derived()->template get_as(); } + std::int16_t GetInt16() const { return derived()->template get_as(); } + std::uint16_t GetUInt16() const { return derived()->template get_as(); } + std::int32_t GetInt32() const { return derived()->template get_as(); } + std::uint32_t GetUInt32() const { return derived()->template get_as(); } + std::int64_t GetInt64() const { return derived()->template get_as(); } + std::uint64_t GetUInt64() const { return derived()->template get_as(); } + float GetSingle() const { return derived()->template get_as(); } + double GetDouble() const { return derived()->template get_as(); } + char16_t GetChar16() const { return derived()->template get_as(); } + bool GetBoolean() const { return derived()->template get_as(); } + hstring GetString() const { return derived()->template get_as(); } + guid GetGuid() const { return derived()->template get_as(); } + Windows::Foundation::DateTime GetDateTime() const { return derived()->template get_as(); } + Windows::Foundation::TimeSpan GetTimeSpan() const { return derived()->template get_as(); } + Windows::Foundation::Point GetPoint() const { return derived()->template get_as(); } + Windows::Foundation::Size GetSize() const { return derived()->template get_as(); } + Windows::Foundation::Rect GetRect() const { return derived()->template get_as(); } + void GetUInt8Array(com_array& value) const { derived()->get_as(value); } + void GetInt16Array(com_array& value) const { derived()->get_as(value); } + void GetUInt16Array(com_array& value) const { derived()->get_as(value); } + void GetInt32Array(com_array& value) const { derived()->get_as(value); } + void GetUInt32Array(com_array& value) const { derived()->get_as(value); } + void GetInt64Array(com_array& value) const { derived()->get_as(value); } + void GetUInt64Array(com_array& value) const { derived()->get_as(value); } + void GetSingleArray(com_array& value) const { derived()->get_as(value); } + void GetDoubleArray(com_array& value) const { derived()->get_as(value); } + void GetChar16Array(com_array& value) const { derived()->get_as(value); } + void GetBooleanArray(com_array& value) const { derived()->get_as(value); } + void GetStringArray(com_array& value) const { derived()->get_as(value); } + void GetInspectableArray(com_array& value) const { derived()->get_as(value); } + void GetGuidArray(com_array& value) const { derived()->get_as(value); } + void GetDateTimeArray(com_array& value) const { derived()->get_as(value); } + void GetTimeSpanArray(com_array& value) const { derived()->get_as(value); } + void GetPointArray(com_array& value) const { derived()->get_as(value); } + void GetSizeArray(com_array& value) const { derived()->get_as(value); } + void GetRectArray(com_array& value) const { derived()->get_as(value); } - std::int16_t GetInt16() const - { - return to_scalar(); - } + private: - std::uint16_t GetUInt16() const - { - return to_scalar(); - } + Derived const* derived() const noexcept { return static_cast(this); } - std::int32_t GetInt32() const + std::int32_t query_interface_tearoff(guid const& id, void** object) const noexcept override { - return to_scalar(); - } + if constexpr (is_stock_reference_v) + { + if (is_guid_of(id)) + { + try + { + auto marshal = derived()->create_property_value().template as(); + *object = detach_abi(marshal); + return error_ok; + } + catch (...) + { + *object = nullptr; + return to_hresult(); + } + } - std::uint32_t GetUInt32() const - { - return to_scalar(); + if (is_guid_of(id)) + { + auto unknown = reinterpret_cast(to_abi(derived())); + unknown->AddRef(); + *object = unknown; + return error_ok; + } + } + + *object = nullptr; + return error_no_interface; } + }; - std::int64_t GetInt64() const + template + struct reference : reference_producer, T, Windows::Foundation::IReference, false> + { + reference(T const& value) : m_value(value) { - return to_scalar(); } - std::uint64_t GetUInt64() const + T Value() const { - return to_scalar(); + return m_value; } - float GetSingle() { throw hresult_not_implemented(); } - double GetDouble() { throw hresult_not_implemented(); } - char16_t GetChar16() { throw hresult_not_implemented(); } - bool GetBoolean() { throw hresult_not_implemented(); } - hstring GetString() { throw hresult_not_implemented(); } - guid GetGuid() { throw hresult_not_implemented(); } - Windows::Foundation::DateTime GetDateTime() { throw hresult_not_implemented(); } - Windows::Foundation::TimeSpan GetTimeSpan() { throw hresult_not_implemented(); } - Windows::Foundation::Point GetPoint() { throw hresult_not_implemented(); } - Windows::Foundation::Size GetSize() { throw hresult_not_implemented(); } - Windows::Foundation::Rect GetRect() { throw hresult_not_implemented(); } - void GetUInt8Array(com_array &) { throw hresult_not_implemented(); } - void GetInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetSingleArray(com_array &) { throw hresult_not_implemented(); } - void GetDoubleArray(com_array &) { throw hresult_not_implemented(); } - void GetChar16Array(com_array &) { throw hresult_not_implemented(); } - void GetBooleanArray(com_array &) { throw hresult_not_implemented(); } - void GetStringArray(com_array &) { throw hresult_not_implemented(); } - void GetInspectableArray(com_array &) { throw hresult_not_implemented(); } - void GetGuidArray(com_array &) { throw hresult_not_implemented(); } - void GetDateTimeArray(com_array &) { throw hresult_not_implemented(); } - void GetTimeSpanArray(com_array &) { throw hresult_not_implemented(); } - void GetPointArray(com_array &) { throw hresult_not_implemented(); } - void GetSizeArray(com_array &) { throw hresult_not_implemented(); } - void GetRectArray(com_array &) { throw hresult_not_implemented(); } - private: + template friend struct reference_producer; + + Windows::Foundation::IInspectable create_property_value() const + { + using pv = Windows::Foundation::PropertyValue; + + if constexpr (std::is_same_v) { return pv::CreateUInt8(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt32(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt32(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt64(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt64(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateSingle(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDouble(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateChar16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateBoolean(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateString(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateGuid(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDateTime(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateTimeSpan(m_value); } + else if constexpr (std::is_same_v) { return pv::CreatePoint(m_value); } + else { return nullptr; } + } + template - To to_scalar() const + To get_as() const { - if constexpr (IsNumericScalar()) + if constexpr (std::is_same_v) + { + return m_value; + } + else if constexpr (is_numeric_scalar_v && is_numeric_scalar_v) { return static_cast(m_value); } @@ -104,98 +202,81 @@ WINRT_EXPORT namespace winrt::impl } } + template + void get_as(com_array const&) const + { + throw hresult_not_implemented(); + } + T m_value; }; template - struct reference_traits - { - static auto make(T const& value) { return winrt::make>(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(std::uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(std::uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits + struct reference_array : reference_producer, T, Windows::Foundation::IReferenceArray, true> { - static auto make(std::int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } - using itf = Windows::Foundation::IReference; - }; + reference_array(array_view const& value) : m_value(value.begin(), value.end()) + { + } - template <> - struct reference_traits - { - static auto make(std::uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } - using itf = Windows::Foundation::IReference; - }; + com_array Value() const + { + return com_array(m_value.begin(), m_value.end()); + } - template <> - struct reference_traits - { - static auto make(std::int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } - using itf = Windows::Foundation::IReference; - }; + private: - template <> - struct reference_traits - { - static auto make(std::uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } - using itf = Windows::Foundation::IReference; - }; + template friend struct reference_producer; - template <> - struct reference_traits - { - static auto make(std::int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(float value) { return Windows::Foundation::PropertyValue::CreateSingle(value); } - using itf = Windows::Foundation::IReference; - }; + Windows::Foundation::IInspectable create_property_value() const + { + using pv = Windows::Foundation::PropertyValue; + + if constexpr (std::is_same_v) { return pv::CreateUInt8Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt32Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt32Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt64Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt64Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateSingleArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDoubleArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateChar16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateBooleanArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateStringArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateGuidArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDateTimeArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateTimeSpanArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreatePointArray(m_value); } + else { return nullptr; } + } - template <> - struct reference_traits - { - static auto make(double value) { return Windows::Foundation::PropertyValue::CreateDouble(value); } - using itf = Windows::Foundation::IReference; - }; + template + To get_as() const + { + throw hresult_not_implemented(); + } - template <> - struct reference_traits - { - static auto make(char16_t value) { return Windows::Foundation::PropertyValue::CreateChar16(value); } - using itf = Windows::Foundation::IReference; - }; + template + void get_as(com_array& value) const + { + if constexpr (std::is_same_v) + { + value = com_array(m_value.begin(), m_value.end()); + } + else + { + throw hresult_not_implemented(); + } + } - template <> - struct reference_traits - { - static auto make(bool value) { return Windows::Foundation::PropertyValue::CreateBoolean(value); } - using itf = Windows::Foundation::IReference; + com_array m_value; }; - template <> - struct reference_traits + template + struct reference_traits { - static auto make(hstring const& value) { return Windows::Foundation::PropertyValue::CreateString(value); } - using itf = Windows::Foundation::IReference; + static auto make(T const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReference; }; template <> @@ -205,41 +286,13 @@ WINRT_EXPORT namespace winrt::impl using itf = Windows::Foundation::IInspectable; }; - template <> - struct reference_traits - { - static auto make(guid const& value) { return Windows::Foundation::PropertyValue::CreateGuid(value); } - using itf = Windows::Foundation::IReference; - }; - template <> struct reference_traits { - static auto make(GUID const& value) { return Windows::Foundation::PropertyValue::CreateGuid(reinterpret_cast(value)); } + static auto make(GUID const& value) { return reference_traits::make(reinterpret_cast(value)); } using itf = Windows::Foundation::IReference; }; - template <> - struct reference_traits - { - static auto make(Windows::Foundation::DateTime value) { return Windows::Foundation::PropertyValue::CreateDateTime(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(Windows::Foundation::TimeSpan value) { return Windows::Foundation::PropertyValue::CreateTimeSpan(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(Windows::Foundation::Point const& value) { return Windows::Foundation::PropertyValue::CreatePoint(value); } - using itf = Windows::Foundation::IReference; - }; - template <> struct reference_traits { @@ -257,77 +310,77 @@ WINRT_EXPORT namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } + static auto make(com_array const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateSingleArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateDoubleArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateChar16Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateBooleanArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; @@ -348,14 +401,14 @@ WINRT_EXPORT namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(reinterpret_cast const&>(value)); } + static auto make(array_view const& value) { return winrt::make>(reinterpret_cast const&>(value)); } using itf = Windows::Foundation::IReferenceArray; }; @@ -376,7 +429,7 @@ WINRT_EXPORT namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreatePointArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; diff --git a/strings/base_string.h b/strings/base_string.h index 6b1fb37b5..50a248c02 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -155,6 +155,24 @@ WINRT_EXPORT namespace winrt::impl return nullptr; } }; + + template + struct hstring_literal_storage + { + static constexpr std::size_t size = N; + wchar_t value[N]; + + constexpr hstring_literal_storage(wchar_t const (&str)[N]) noexcept + { + for (std::size_t i = 0; i != N; ++i) + { + value[i] = str[i]; + } + } + }; + + template + hstring_literal_storage(wchar_t const (&)[N]) -> hstring_literal_storage; } WINRT_EXPORT namespace winrt @@ -386,6 +404,30 @@ WINRT_EXPORT namespace winrt handle_type m_handle; }; + struct hstring_reference + { + constexpr hstring_reference() noexcept = default; + + constexpr explicit hstring_reference(impl::hstring_header const* header) noexcept : + m_handle(const_cast(header)) + { + } + + operator hstring const&() const noexcept + { + return *reinterpret_cast(this); + } + + private: + + [[maybe_unused]] void* m_handle{}; + }; + + inline void* get_abi(hstring_reference const& object) noexcept + { + return *(void**)(&object); + } + inline void* get_abi(hstring const& object) noexcept { return *(void**)(&object); @@ -437,6 +479,44 @@ WINRT_EXPORT namespace winrt } } +#if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L + +WINRT_EXPORT namespace winrt::impl +{ + template + inline constexpr hstring_header hstring_literal_header + { + hstring_reference_flag, + static_cast(Literal.size - 1), + 0, + 0, + Literal.value + }; +} + +WINRT_EXPORT namespace winrt +{ + inline namespace literals + { + template + constexpr hstring_reference operator ""_hs() noexcept + { + static_assert(Literal.value[Literal.size - 1] == L'\0', "_hs requires a null-terminated wide string literal"); + + if constexpr (Literal.size <= 1) + { + return hstring_reference{}; + } + else + { + return hstring_reference{ &impl::hstring_literal_header }; + } + } + } +} + +#endif + #ifdef __cpp_lib_format template<> struct std::formatter : std::formatter {}; diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 71cd5f3c0..ccf955547 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -18,6 +18,10 @@ WINRT_EXPORT namespace winrt::param { } + hstring(winrt::hstring_reference const& value) noexcept : m_handle(get_abi(value)) + { + } + hstring(std::wstring_view const& value) noexcept { create_string_reference(value.data(), value.size()); diff --git a/test/test/reference_boxing.cpp b/test/test/reference_boxing.cpp new file mode 100644 index 000000000..c6e300886 --- /dev/null +++ b/test/test/reference_boxing.cpp @@ -0,0 +1,268 @@ +#include "pch.h" +#include +#include +#include + +using namespace winrt; +using namespace Windows::Foundation; + +// Scalar box_value now produces a local IReference/IPropertyValue instead of hopping to +// combase PropertyValue. These confirm it reports the correct PropertyType, keeps combase-style +// numeric conversion on mismatched getters, and round-trips through unbox_value. +TEST_CASE("reference_boxing") +{ + { + auto boxed = box_value(42); + auto pv = boxed.as(); + REQUIRE(pv.Type() == PropertyType::Int32); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetInt32() == 42); + REQUIRE(pv.GetInt16() == 42); + REQUIRE(pv.GetDouble() == 42.0); + // A scalar reference holds no array, so every array getter routes through get_as and throws. + { + com_array ints; + REQUIRE_THROWS_AS(pv.GetInt32Array(ints), hresult_not_implemented); + com_array strings; + REQUIRE_THROWS_AS(pv.GetStringArray(strings), hresult_not_implemented); + } + REQUIRE(unbox_value(boxed) == 42); + } + + { + auto pv = box_value(3.5).as(); + REQUIRE(pv.Type() == PropertyType::Double); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetDouble() == 3.5); + REQUIRE(pv.GetSingle() == 3.5f); + } + + { + auto pv = box_value(hstring{ L"hello" }).as(); + REQUIRE(pv.Type() == PropertyType::String); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetString() == L"hello"); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + auto pv = box_value(true).as(); + REQUIRE(pv.Type() == PropertyType::Boolean); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetBoolean()); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + guid const g{ 0x11223344, 0x5566, 0x7788, { 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } }; + auto pv = box_value(g).as(); + REQUIRE(pv.Type() == PropertyType::Guid); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetGuid() == g); + } + + { + auto pv = box_value(static_cast(7)).as(); + REQUIRE(pv.Type() == PropertyType::UInt8); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetUInt8() == 7); + REQUIRE(unbox_value(box_value(static_cast(7))) == 7); + } + + // DateTime, TimeSpan, and Point are also boxed in-process now (they still marshal by value). + { + Point const point{ 3.0f, 4.0f }; + auto pv = box_value(point).as(); + REQUIRE(pv.Type() == PropertyType::Point); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetPoint().X == point.X); + REQUIRE(pv.GetPoint().Y == point.Y); + auto const round_tripped = unbox_value(box_value(point)); + REQUIRE(round_tripped.X == point.X); + REQUIRE(round_tripped.Y == point.Y); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + TimeSpan const span{ std::chrono::seconds{ 90 } }; + auto pv = box_value(span).as(); + REQUIRE(pv.Type() == PropertyType::TimeSpan); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetTimeSpan() == span); + REQUIRE(unbox_value(box_value(span)) == span); + } + + { + DateTime const when{ TimeSpan{ std::chrono::seconds{ 1000 } } }; + auto pv = box_value(when).as(); + REQUIRE(pv.Type() == PropertyType::DateTime); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetDateTime() == when); + REQUIRE(unbox_value(box_value(when)) == when); + } +} + +// Array boxing produces a local IReferenceArray / IPropertyValue (no combase PropertyValue) for the +// stock element types. Confirm the array PropertyType, round-trips, and the get_as throw behavior. +TEST_CASE("reference_boxing arrays") +{ + { + int32_t values[]{ 0, 42, 1729, -1 }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + auto pv = boxed.as(); + REQUIRE(pv.Type() == PropertyType::Int32Array); + REQUIRE(!pv.IsNumericScalar()); + + com_array out; + pv.GetInt32Array(out); + REQUIRE(out == array_view{ values }); + + // A scalar getter on an array PV throws, and so does a mismatched-element array getter. + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + com_array wrong; + REQUIRE_THROWS_AS(pv.GetDoubleArray(wrong), hresult_not_implemented); + + REQUIRE(unbox_value>(boxed) == array_view{ values }); + REQUIRE(boxed.as>().Value() == array_view{ values }); + } + + // guid arrays are local too. + { + guid values[]{ + { 0x11223344, 0x5566, 0x7788, { 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } }, + { 0x00112233, 0x4455, 0x6677, { 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } } }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + REQUIRE(boxed.as().Type() == PropertyType::GuidArray); + REQUIRE(unbox_value>(boxed) == array_view{ values }); + } +} + +// The local array reference must marshal by value across processes just like the scalar one: its +// IMarshal reports the same unmarshal class as a genuine combase array PropertyValue, and not the +// free-threaded (by-reference) class. +TEST_CASE("reference_boxing array marshal by value") +{ + int32_t values[]{ 1, 2, 3 }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + REQUIRE(boxed.try_as()); + auto ours = boxed.as(); + + auto genuine = PropertyValue::CreateInt32Array(values); + auto reference = genuine.as(); + + guid our_clsid{}; + guid reference_clsid{}; + check_hresult(ours->GetUnmarshalClass(guid_of(), get_unknown(boxed), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &our_clsid)); + check_hresult(reference->GetUnmarshalClass(guid_of(), get_unknown(genuine), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &reference_clsid)); + + REQUIRE(our_clsid == reference_clsid); + + guid const free_threaded_marshaler{ 0x0000033A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; + REQUIRE(our_clsid != free_threaded_marshaler); +} + +// The in-proc reference stays agile but must marshal by value across processes, exactly like a real +// combase PropertyValue. Prove it by confirming our IMarshal reports the SAME unmarshal class as a +// genuine PropertyValue - i.e. we forward marshaling to combase - and specifically NOT the +// free-threaded (marshal-by-reference) class the default agile path would have used. +TEST_CASE("reference_boxing marshal by value") +{ + auto boxed = box_value(42); + REQUIRE(boxed.try_as()); + auto ours = boxed.as(); + + auto genuine = PropertyValue::CreateInt32(42); + auto reference = genuine.as(); + + guid our_clsid{}; + guid reference_clsid{}; + check_hresult(ours->GetUnmarshalClass(guid_of(), get_unknown(boxed), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &our_clsid)); + check_hresult(reference->GetUnmarshalClass(guid_of(), get_unknown(genuine), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &reference_clsid)); + + REQUIRE(our_clsid == reference_clsid); + + // CLSID_InProcFreeMarshaler - the by-reference class the agile FTM would have produced. + guid const free_threaded_marshaler{ 0x0000033A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; + REQUIRE(our_clsid != free_threaded_marshaler); +} + +// The in-proc reference advertises IAgileObject, so handing it between two single-threaded +// apartments in the same process must resolve to the *same* object pointer - no proxy. The Global +// Interface Table returns an agile object's original pointer directly, but hands back a proxy (a +// different identity) for a non-agile object, so pointer equality here confirms the agile fast path. +TEST_CASE("reference_boxing agile in-proc identity across apartments") +{ + auto identity_of = [](::IUnknown* raw) -> void* + { + com_ptr<::IUnknown> identity; + check_hresult(raw->QueryInterface(IID_PPV_ARGS(identity.put()))); + return identity.get(); + }; + + com_ptr git; + check_hresult(CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(git.put()))); + + Windows::Foundation::IInspectable boxed{ nullptr }; + DWORD cookie{}; + void* original_identity{}; + void* marshaled_identity{}; + HRESULT sta1_hr = S_OK; + HRESULT sta2_hr = S_OK; + + handle registered{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; + handle fetched{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; + + std::thread sta1([&] + { + sta1_hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(sta1_hr)) + { + boxed = box_value(42); + auto unknown = reinterpret_cast<::IUnknown*>(get_abi(boxed)); + original_identity = identity_of(unknown); + sta1_hr = git->RegisterInterfaceInGlobal(unknown, IID_IUnknown, &cookie); + } + SetEvent(registered.get()); + + WaitForSingleObject(fetched.get(), INFINITE); + if (SUCCEEDED(sta1_hr)) + { + CoUninitialize(); + } + }); + + std::thread sta2([&] + { + WaitForSingleObject(registered.get(), INFINITE); + if (SUCCEEDED(sta1_hr)) + { + sta2_hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(sta2_hr)) + { + ::IUnknown* raw{}; + sta2_hr = git->GetInterfaceFromGlobal(cookie, IID_IUnknown, reinterpret_cast(&raw)); + if (SUCCEEDED(sta2_hr)) + { + marshaled_identity = identity_of(raw); + raw->Release(); + } + git->RevokeInterfaceFromGlobal(cookie); + CoUninitialize(); + } + } + SetEvent(fetched.get()); + }); + + sta1.join(); + sta2.join(); + + REQUIRE(SUCCEEDED(sta1_hr)); + REQUIRE(SUCCEEDED(sta2_hr)); + REQUIRE(original_identity != nullptr); + REQUIRE(original_identity == marshaled_identity); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 43928dab2..f95584d99 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -324,6 +324,7 @@ NotUsing + diff --git a/test/test_cpp20/hstring_literal.cpp b/test/test_cpp20/hstring_literal.cpp new file mode 100644 index 000000000..2ba0f3ad7 --- /dev/null +++ b/test/test_cpp20/hstring_literal.cpp @@ -0,0 +1,68 @@ +#include "pch.h" + +using namespace winrt; +using namespace std::literals; + +#if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L + +using namespace winrt::literals; + +namespace +{ + // Exercises the hstring_reference -> param::hstring conversion that projected + // setters rely on, and duplicates into an owning hstring on the way out. + winrt::hstring copy_via_param(winrt::param::hstring const& value) + { + winrt::hstring const& as_hstring = value; + return as_hstring; + } +} + +TEST_CASE("hstring_literal") +{ + // The literal is a genuine constant expression: the fast-pass header is built at + // compile time, so an hstring_reference can be constructed in a constexpr context. + { + constexpr winrt::hstring_reference lit = L"kittens"_hs; + winrt::hstring const& value = lit; + REQUIRE(value == L"kittens"sv); + REQUIRE(value.size() == 7); + } + + // Content and length match the literal. + { + winrt::hstring_reference const lit = L"kittens"_hs; + winrt::hstring const& value = lit; + REQUIRE(value == L"kittens"sv); + REQUIRE(value.size() == 7); + REQUIRE(wcslen(value.c_str()) == 7); + } + + // Built as a fast-pass reference string (no heap allocation). + { + winrt::hstring_reference const lit = L"puppies"_hs; + auto const header = static_cast(winrt::get_abi(lit)); + REQUIRE(header != nullptr); + REQUIRE((header->flags & winrt::impl::hstring_reference_flag) != 0); + REQUIRE(header->length == 7); + } + + // Empty literal projects as the empty (null) HSTRING. + { + winrt::hstring_reference const lit = L""_hs; + winrt::hstring const& value = lit; + REQUIRE(value.empty()); + REQUIRE(value.size() == 0); + REQUIRE(winrt::get_abi(value) == nullptr); + } + + // Binds to a projected setter parameter in a single conversion, and copying + // into an owning hstring duplicates correctly. + { + winrt::hstring const copied = copy_via_param(L"waffles"_hs); + REQUIRE(copied == L"waffles"sv); + REQUIRE(copied.size() == 7); + } +} + +#endif diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 4eaee0a18..b13becd23 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -239,6 +239,7 @@ + NotUsing From 9cf9564cf31638e41149016f2ca7a07b3f97adb6 Mon Sep 17 00:00:00 2001 From: Chris Guzak Date: Wed, 26 Aug 2026 16:14:48 -0700 Subject: [PATCH 304/305] Add get_unchecked() to async operations (#1565) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add get_only_safe_from_non_presenting_sta() to async operations Add a peer to .get() on IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, and IAsyncOperationWithProgress that skips the _DEBUG-only STA blocking assert. The existing .get() asserts !is_sta_thread() to guard against blocking UI threads. However, not all STAs are UI threads — some never present UI, haven't presented yet, or never will. The assert is also _DEBUG-only, making it invisible to codebases that don't build with _DEBUG (e.g. the Windows OS). The new method get_only_safe_from_non_presenting_sta() is functionally identical to .get() but omits the STA check. The intentionally long name communicates the risk to callers. Changes: - strings/base_coroutine_foundation.h: Add wait_get_bypass_sta_check() impl helper and get_only_safe_from_non_presenting_sta() for all 4 async consume templates - cppwinrt/code_writers.h: Add declaration to generated code for all 4 async types - test/test_nocoro: Add test calling the new method from an STA thread using a real WinRT async operation (PathIO::ReadTextAsync on C:\Windows\win.ini) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename STA bypassing async get method Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix STA test cleanup and assertions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Chris Guzak (WINDOWS) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cppwinrt/code_writers.h | 12 +++++++++ strings/base_coroutine_foundation.h | 33 ++++++++++++++++++++++++ test/test_nocoro/get.cpp | 40 +++++++++++++++++++++++++++++ test/test_nocoro/pch.h | 1 + 4 files changed, 86 insertions(+) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index b3855c097..a9aa5bc78 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1475,24 +1475,36 @@ namespace cppwinrt else if (type_name == "Windows.Foundation.IAsyncAction") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncOperation`1") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncActionWithProgress`1") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncOperationWithProgress`2") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 5cefad836..82582ee64 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -99,6 +99,19 @@ WINRT_EXPORT namespace winrt::impl return async.GetResults(); } + template + auto wait_get_bypass_sta_check(Async const& async) + { + auto status = async.Status(); + if (status == Windows::Foundation::AsyncStatus::Started) + { + status = wait_for_completed(async, 0xFFFFFFFF); // INFINITE + } + check_status_canceled(status); + + return async.GetResults(); + } + #ifdef WINRT_IMPL_COROUTINES struct ignore_apartment_context {}; @@ -220,6 +233,11 @@ WINRT_EXPORT namespace winrt::impl impl::wait_get(static_cast(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncAction::get_unchecked() const + { + impl::wait_get_bypass_sta_check(static_cast(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncAction::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast(static_cast(*this)), timeout); @@ -231,6 +249,11 @@ WINRT_EXPORT namespace winrt::impl return impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncOperation::get_unchecked() const + { + return impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncOperation::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); @@ -242,6 +265,11 @@ WINRT_EXPORT namespace winrt::impl impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncActionWithProgress::get_unchecked() const + { + impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncActionWithProgress::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); @@ -253,6 +281,11 @@ WINRT_EXPORT namespace winrt::impl return impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncOperationWithProgress::get_unchecked() const + { + return impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncOperationWithProgress::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); diff --git a/test/test_nocoro/get.cpp b/test/test_nocoro/get.cpp index 11339e10b..4fd85fe3e 100644 --- a/test/test_nocoro/get.cpp +++ b/test/test_nocoro/get.cpp @@ -2,6 +2,7 @@ using namespace winrt; using namespace Windows::Foundation; +using namespace Windows::Storage; template struct async_completion_source : implements, IAsyncOperation, IAsyncInfo> @@ -72,3 +73,42 @@ TEST_CASE("get") REQUIRE(acs.as>().get() == 0xDEADBEEF); } + +TEST_CASE("get_unchecked") +{ + // Call a real WinRT async operation from an STA thread. + // This is the scenario the new API is designed for: an STA that is not + // presenting UI, where a synchronous blocking wait is safe. + std::exception_ptr failure{}; + bool content_available = false; + std::thread sta_thread([&failure, &content_available] + { + try + { + winrt::init_apartment(winrt::apartment_type::single_threaded); + struct apartment_guard + { + ~apartment_guard() + { + winrt::uninit_apartment(); + } + } guard; + + auto content = PathIO::ReadTextAsync(L"C:\\Windows\\win.ini").get_unchecked(); + content_available = content.size() > 0; + } + catch (...) + { + failure = std::current_exception(); + } + }); + + sta_thread.join(); + + if (failure) + { + std::rethrow_exception(failure); + } + + REQUIRE(content_available); +} diff --git a/test/test_nocoro/pch.h b/test/test_nocoro/pch.h index 7ff48a37c..30a6d3079 100644 --- a/test/test_nocoro/pch.h +++ b/test/test_nocoro/pch.h @@ -2,5 +2,6 @@ #include "catch.hpp" #include "winrt/Windows.Foundation.h" +#include "winrt/Windows.Storage.h" using namespace std::literals; From 856eaff70a48d6b053c2ad3dffec15b81ca34b10 Mon Sep 17 00:00:00 2001 From: Dan Fiedler <151573964+danfiedler-msft@users.noreply.github.com> Date: Wed, 26 Aug 2026 19:33:15 -0400 Subject: [PATCH 305/305] Pin GitHub Actions to full-length commit SHAs (#1618) --- .github/actions/setup-llvm-mingw/action.yml | 4 ++-- .github/actions/setup-llvm-msvc/action.yml | 2 +- .github/dependabot.yml | 2 ++ .github/workflows/check-line-endings.yml | 2 +- .github/workflows/ci.yml | 26 ++++++++++----------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/.github/actions/setup-llvm-mingw/action.yml b/.github/actions/setup-llvm-mingw/action.yml index 50fe696b7..d36b48a75 100644 --- a/.github/actions/setup-llvm-mingw/action.yml +++ b/.github/actions/setup-llvm-mingw/action.yml @@ -19,7 +19,7 @@ runs: - name: Cache llvm-mingw (Windows) id: cache-llvm if: runner.os == 'Windows' - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: .llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} @@ -50,7 +50,7 @@ runs: - name: Cache llvm-mingw (Linux) id: cache-llvm-linux if: runner.os == 'Linux' - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: /opt/llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} diff --git a/.github/actions/setup-llvm-msvc/action.yml b/.github/actions/setup-llvm-msvc/action.yml index 036d0fa28..e5a696a9f 100644 --- a/.github/actions/setup-llvm-msvc/action.yml +++ b/.github/actions/setup-llvm-msvc/action.yml @@ -14,7 +14,7 @@ runs: steps: - name: Cache LLVM and tools id: cache-llvm - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | .LLVM diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 47f88349d..9557baa7a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,3 +8,5 @@ updates: directory: "/" schedule: interval: "daily" + cooldown: + default-days: 7 diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml index dea958274..3891aec09 100644 --- a/.github/workflows/check-line-endings.yml +++ b/.github/workflows/check-line-endings.yml @@ -11,7 +11,7 @@ jobs: name: Enforce .gitattributes line endings runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Check for line ending violations run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afdeed462..5e2677fed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: config: Release runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download nuget run: | @@ -71,7 +71,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | @@ -113,18 +113,18 @@ jobs: test_exe: test_cpp20_module runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-${{ matrix.toolchain.platform_toolset }}-bin path: _build/x86/Release/ @@ -243,7 +243,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | @@ -263,7 +263,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install cross compiler run: | @@ -282,7 +282,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -296,7 +296,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download nuget run: | @@ -339,10 +339,10 @@ jobs: platform_toolset: v145 runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ @@ -384,7 +384,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Package run: | @@ -399,7 +399,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: package path: "*.nupkg"