Skip to content

Commit d817854

Browse files
committed
gcc: Fix -Wclass-memaccess warning
`detach_abi(com_array<T>&)` uses two `memset` calls to zero two objects, one is an `std::pair` (from [microsoft#1165]), the other is a `winrt::com_array` (to clear its data pointer to prevent its destructor from freeing the array). GCC rightfully warns about this because these types are not trivially copyable, so calling memset on it is UB. This change fixes the UB and the GCC warning by reverting the first `memset` back to using the `std::pair` constructor as before [microsoft#1165], and changing the second `memset` to setting the member fields directly. Since this requires access to protected members, the function body is moved into a private member function, then the `winrt::detach_abi` free function is made `friend` of `com_array` to allow it to call the member function. This fix is not applied when `_MSC_VER` is defined in order to preserve the current behaviour on MSVC, in case [microsoft#1165] is still relevant. [microsoft#1165]: microsoft#1165
1 parent 9fe0157 commit d817854

1 file changed

Lines changed: 22 additions & 7 deletions

File tree

strings/base_array.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,26 @@ WINRT_EXPORT namespace winrt
345345
this->m_size = size;
346346
}
347347
}
348+
349+
std::pair<uint32_t, impl::arg_out<T>> detach_abi() noexcept
350+
{
351+
#ifdef _MSC_VER
352+
// https://github.com/microsoft/cppwinrt/pull/1165
353+
std::pair<uint32_t, impl::arg_out<T>> result;
354+
memset(&result, 0, sizeof(result));
355+
result.first = this->size();
356+
result.second = *reinterpret_cast<impl::arg_out<T>*>(this);
357+
memset(&object, 0, sizeof(com_array<T>));
358+
#else
359+
std::pair<uint32_t, impl::arg_out<T>> result(this->size(), *reinterpret_cast<impl::arg_out<T>*>(this));
360+
this->m_data = nullptr;
361+
this->m_size = 0;
362+
#endif
363+
return result;
364+
}
365+
366+
template <typename U>
367+
friend std::pair<uint32_t, impl::arg_out<U>> detach_abi(com_array<U>& object) noexcept;
348368
};
349369

350370
template <typename C> com_array(uint32_t, C const&) -> com_array<std::decay_t<C>>;
@@ -418,14 +438,9 @@ WINRT_EXPORT namespace winrt
418438
}
419439

420440
template <typename T>
421-
auto detach_abi(com_array<T>& object) noexcept
441+
std::pair<uint32_t, impl::arg_out<T>> detach_abi(com_array<T>& object) noexcept
422442
{
423-
std::pair<uint32_t, impl::arg_out<T>> result;
424-
memset(&result, 0, sizeof(result));
425-
result.first = object.size();
426-
result.second = *reinterpret_cast<impl::arg_out<T>*>(&object);
427-
memset(&object, 0, sizeof(com_array<T>));
428-
return result;
443+
return object.detach_abi();
429444
}
430445

431446
template <typename T>

0 commit comments

Comments
 (0)