Make QuicFrame a standard-layout struct.

C++ provides certain guarantees about the way union fields interact, which are only valid for standard-layout types.  Standard-layout types are not allowed to have data members in both base and derived types; this fixes that by moving QuicInlinedFrame::type into individual frames.

Also, before C++17, using offsetof() on non-standard-layout types is undefined behavor.

Thanks to Stephan Hartmann <stha09@googlemail.com> for pointing this problem out in <https://quiche-review.googlesource.com/c/quiche/+/10600>.

PiperOrigin-RevId: 320195673
Change-Id: I179634af3e3a199b7b7320a031b42898a5644824
diff --git a/quic/core/frames/quic_inlined_frame.h b/quic/core/frames/quic_inlined_frame.h
index 08c4869..cfa32dc 100644
--- a/quic/core/frames/quic_inlined_frame.h
+++ b/quic/core/frames/quic_inlined_frame.h
@@ -5,6 +5,8 @@
 #ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_
 #define QUICHE_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_
 
+#include <type_traits>
+
 #include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
 
@@ -16,13 +18,15 @@
 // inline and out-of-line frame types.
 template <typename DerivedT>
 struct QUIC_EXPORT_PRIVATE QuicInlinedFrame {
-  QuicInlinedFrame(QuicFrameType type) : type(type) {
+  QuicInlinedFrame(QuicFrameType type) {
+    static_cast<DerivedT*>(this)->type = type;
+    static_assert(std::is_standard_layout<DerivedT>::value,
+                  "Inlined frame must have a standard layout");
     static_assert(offsetof(DerivedT, type) == 0,
                   "type must be the first field.");
     static_assert(sizeof(DerivedT) <= 24,
                   "Frames larger than 24 bytes should not be inlined.");
   }
-  QuicFrameType type;
 };
 
 }  // namespace quic