[fidl][hlcpp] Fix bug in flexible union move constructor

This CL fixes a bug in HLCPP's move constructor for flexible unions. It
was only copying the unknown_data_.bytes rather than the entire
unknown_data_, leaving the handles field uninitialized. This manifested
as a misaligned pointer crash in the union's destructor.

Test: fx test fidl-hlcpp-conformance-test
Fixed: 62819
Change-Id: I8c0a213310a8dc99dcf662a9be56b4aed6fb5b0e
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/443495
Commit-Queue: Mitchell Kember <mkember@google.com>
Reviewed-by: Felix Zhu <fcz@google.com>
Testability-Review: Felix Zhu <fcz@google.com>
diff --git a/garnet/go/src/fidl/compiler/backend/goldens/doc_comments.test.json.cc.golden b/garnet/go/src/fidl/compiler/backend/goldens/doc_comments.test.json.cc.golden
index 861bc57..bea952b 100644
--- a/garnet/go/src/fidl/compiler/backend/goldens/doc_comments.test.json.cc.golden
+++ b/garnet/go/src/fidl/compiler/backend/goldens/doc_comments.test.json.cc.golden
@@ -453,8 +453,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
diff --git a/garnet/go/src/fidl/compiler/backend/goldens/handles_in_types.test.json.cc.golden b/garnet/go/src/fidl/compiler/backend/goldens/handles_in_types.test.json.cc.golden
index 2ab1026..319d5ef 100644
--- a/garnet/go/src/fidl/compiler/backend/goldens/handles_in_types.test.json.cc.golden
+++ b/garnet/go/src/fidl/compiler/backend/goldens/handles_in_types.test.json.cc.golden
@@ -43,8 +43,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
diff --git a/garnet/go/src/fidl/compiler/backend/goldens/placement_of_attributes.test.json.cc.golden b/garnet/go/src/fidl/compiler/backend/goldens/placement_of_attributes.test.json.cc.golden
index 371582e..39acce4 100644
--- a/garnet/go/src/fidl/compiler/backend/goldens/placement_of_attributes.test.json.cc.golden
+++ b/garnet/go/src/fidl/compiler/backend/goldens/placement_of_attributes.test.json.cc.golden
@@ -156,8 +156,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
diff --git a/garnet/go/src/fidl/compiler/backend/goldens/request_flexible_envelope.test.json.cc.golden b/garnet/go/src/fidl/compiler/backend/goldens/request_flexible_envelope.test.json.cc.golden
index 917de76..7158dcf 100644
--- a/garnet/go/src/fidl/compiler/backend/goldens/request_flexible_envelope.test.json.cc.golden
+++ b/garnet/go/src/fidl/compiler/backend/goldens/request_flexible_envelope.test.json.cc.golden
@@ -223,8 +223,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
diff --git a/garnet/go/src/fidl/compiler/backend/goldens/union.test.json.cc.golden b/garnet/go/src/fidl/compiler/backend/goldens/union.test.json.cc.golden
index a1456fb..f5bd192 100644
--- a/garnet/go/src/fidl/compiler/backend/goldens/union.test.json.cc.golden
+++ b/garnet/go/src/fidl/compiler/backend/goldens/union.test.json.cc.golden
@@ -1646,8 +1646,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
@@ -2043,8 +2043,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
@@ -2564,8 +2564,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
@@ -2806,8 +2806,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
@@ -3046,8 +3046,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
@@ -3382,8 +3382,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
@@ -3931,8 +3931,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
@@ -4153,8 +4153,8 @@
       case static_cast<fidl_xunion_tag_t>(Tag::Invalid):
         break;
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_ = std::move(other.unknown_data_);
         break;
     }
   }
diff --git a/src/tests/fidl/conformance_suite/union.gidl b/src/tests/fidl/conformance_suite/union.gidl
index 078bdf0..2448b30 100644
--- a/src/tests/fidl/conformance_suite/union.gidl
+++ b/src/tests/fidl/conformance_suite/union.gidl
@@ -96,8 +96,7 @@
 success("FlexibleResourceUnionUnknownValue") {
     // llcpp is tested by hand since it cannot construct unknown unions (and
     // they do not store bytes & handles), see fxr/423117
-    // TODO(fxbug.dev/62819): Fix crash in HLCPP.
-    bindings_denylist = [llcpp,hlcpp],
+    bindings_denylist = [llcpp],
     value = TestFlexibleResourceXUnionInStruct {
         xu: SampleResourceXUnion{
             1234: {
@@ -117,8 +116,7 @@
 
 success("FlexibleResourceUnionUnknownValueWithHandles") {
     // TODO(fxbug.dev/36441): Implement handles in all backends.
-    // TODO(fxbug.dev/62819): Fix crash in HLCPP.
-    bindings_denylist = [llcpp,hlcpp],
+    bindings_denylist = [llcpp],
     handle_defs = {
         #0 = event(),
         #1 = event(),
diff --git a/tools/fidl/fidlgen_hlcpp/codegen/union.tmpl.go b/tools/fidl/fidlgen_hlcpp/codegen/union.tmpl.go
index 4f85309..1543433 100644
--- a/tools/fidl/fidlgen_hlcpp/codegen/union.tmpl.go
+++ b/tools/fidl/fidlgen_hlcpp/codegen/union.tmpl.go
@@ -255,8 +255,8 @@
         break;
     {{- if .IsFlexible }}
       default:
-        new (&unknown_data_.bytes) decltype(unknown_data_.bytes);
-        unknown_data_.bytes = std::move(other.unknown_data_.bytes);
+        new (&unknown_data_) decltype(unknown_data_);
+        unknown_data_= std::move(other.unknown_data_);
         break;
     {{- end }}
     }