Enable copying invalid variants

There was a bug where if you attempted to copy a variant that was not
valid (i.e. did not hold an object), a seg fault could happen. This has
been changed to set the target variant to also be invalid.
This commit is contained in:
Kenneth Moreland 2022-06-29 12:34:02 -06:00
parent 22ee3c3fa5
commit 5e476d7030
3 changed files with 38 additions and 5 deletions

@ -0,0 +1,5 @@
# Fix bug with copying invalid variants
There was a bug where if you attempted to copy a `Variant` that was not
valid (i.e. did not hold an object); a seg fault could happen. This has
been changed to set the target variant to also be invalid.

@ -431,6 +431,23 @@ void TestCastAndCall()
VTKM_TEST_ASSERT(test_equal(result, TestValue(26, vtkm::FloatDefault{}))); VTKM_TEST_ASSERT(test_equal(result, TestValue(26, vtkm::FloatDefault{})));
} }
void TestCopyInvalid()
{
std::cout << "Test copy invalid variant" << std::endl;
using VariantType = vtkm::exec::internal::Variant<TypePlaceholder<0>, NonTrivial>;
VariantType source;
source.Reset();
VariantType destination1(source);
VTKM_TEST_ASSERT(!destination1.IsValid());
VariantType destination2(TypePlaceholder<0>{});
destination2 = source;
VTKM_TEST_ASSERT(!destination2.IsValid());
}
struct CountConstructDestruct struct CountConstructDestruct
{ {
vtkm::Id* Count; vtkm::Id* Count;
@ -577,6 +594,7 @@ void RunTest()
TestTriviallyCopyable(); TestTriviallyCopyable();
TestGet(); TestGet();
TestCastAndCall(); TestCastAndCall();
TestCopyInvalid();
TestCopyDestroy(); TestCopyDestroy();
TestEmplace(); TestEmplace();
TestConstructDestruct(); TestConstructDestruct();

@ -256,21 +256,31 @@ struct VariantConstructorImpl<vtkm::VTK_M_NAMESPACE::internal::Variant<Ts...>,
VTK_M_DEVICE VariantConstructorImpl(const VariantConstructorImpl& src) noexcept VTK_M_DEVICE VariantConstructorImpl(const VariantConstructorImpl& src) noexcept
: VariantStorageImpl<Ts...>(vtkm::internal::NullType{}) : VariantStorageImpl<Ts...>(vtkm::internal::NullType{})
{ {
src.CastAndCall(VariantCopyConstructFunctor{}, this->Storage); if (src.IsValid())
{
src.CastAndCall(VariantCopyConstructFunctor{}, this->Storage);
}
this->Index = src.Index; this->Index = src.Index;
} }
VTK_M_DEVICE VariantConstructorImpl& operator=(const VariantConstructorImpl& src) noexcept VTK_M_DEVICE VariantConstructorImpl& operator=(const VariantConstructorImpl& src) noexcept
{ {
if (this->GetIndex() == src.GetIndex()) if (src.IsValid())
{ {
src.CastAndCall(detail::VariantCopyFunctor{}, this->Storage); if (this->GetIndex() == src.GetIndex())
{
src.CastAndCall(detail::VariantCopyFunctor{}, this->Storage);
}
else
{
this->Reset();
src.CastAndCall(detail::VariantCopyConstructFunctor{}, this->Storage);
this->Index = src.Index;
}
} }
else else
{ {
this->Reset(); this->Reset();
src.CastAndCall(detail::VariantCopyConstructFunctor{}, this->Storage);
this->Index = src.Index;
} }
return *this; return *this;
} }