Doesn't look like an `__attribute__ ((__packed__))` issue. Here's a crass simplification of the Mozilla code: ```c++ #include <cstdint> #include <iostream> template <class T, class Sub, class Coord = T> struct BasePoint { union { struct { Coord x, y; } s; Coord components[2] = {}; } u; constexpr BasePoint() = default; }; template <class T, class Sub> struct BaseCoord { T value; }; template <class Units, class Rep> struct IntCoordTyped : public BaseCoord<Rep, IntCoordTyped<Units, Rep>> , public Units { }; template <class Units> struct IntPointTyped : public BasePoint<int32_t, IntPointTyped<Units>, IntCoordTyped<Units, int32_t> >, public Units { constexpr IntPointTyped() { std::cout << "sizeof(IntPointTyped): " << sizeof(IntPointTyped) << "\nsizeof(int32_t) * 2: " << sizeof(int32_t) * 2 << "\nsizeof(u.s.x): " << sizeof(this->u.s.x) << "\nsizeof(u.s): " << sizeof(this->u.s) << "\nsizeof(u.components): " << sizeof(this->u.components) << "\nsizeof(Units): " << sizeof(Units) << std::endl; } }; struct UnknownUnits {}; typedef IntPointTyped<UnknownUnits> IntPoint; int main() { IntPoint ip; } ``` This outputs: ``` sizeof(IntPointTyped): 12 sizeof(int32_t) * 2: 8 sizeof(u.s.x): 4 sizeof(u.s): 8 sizeof(u.components): 8 sizeof(Units): 1 ``` The problem is that `IntPointTyped` inherits from the empty base `Units`, as does `IntCoordTyped`, and the C++ standard apparently wants the compiler to have different addresses for the two subobjects. The transformation from the extra 1 byte in size to 4 is just alignment. [Here's](https://eel.is/c++draft/class.derived.general#7) the relevant part of the ISO C++ standard: "A base class subobject can be of zero size; however, two subobjects that have the same class type and that belong to the same most derived object cannot be allocated at the same address." If either `IntPointTyped` or `IntCoordTyped` stops inheriting `Units`, the problem goes away (in my test, at least).
Bug 1060421 Comment 11 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
Doesn't look like an `__attribute__ ((__packed__))` issue. Here's a crass simplification of the Mozilla code: ```c++ #include <cstdint> #include <iostream> template <class T, class Sub, class Coord = T> struct BasePoint { union { struct { Coord x, y; } s; Coord components[2] = {}; } u; constexpr BasePoint() = default; }; template <class T, class Sub> struct BaseCoord { T value; }; template <class Units, class Rep> struct IntCoordTyped : public BaseCoord<Rep, IntCoordTyped<Units, Rep>>, public Units { }; template <class Units> struct IntPointTyped : public BasePoint<int32_t, IntPointTyped<Units>, IntCoordTyped<Units, int32_t> >, public Units { constexpr IntPointTyped() { std::cout << "sizeof(IntPointTyped): " << sizeof(IntPointTyped) << "\nsizeof(int32_t) * 2: " << sizeof(int32_t) * 2 << "\nsizeof(u.s.x): " << sizeof(this->u.s.x) << "\nsizeof(u.s): " << sizeof(this->u.s) << "\nsizeof(u.components): " << sizeof(this->u.components) << "\nsizeof(Units): " << sizeof(Units) << std::endl; } }; struct UnknownUnits {}; typedef IntPointTyped<UnknownUnits> IntPoint; int main() { IntPoint ip; } ``` This outputs: ``` sizeof(IntPointTyped): 12 sizeof(int32_t) * 2: 8 sizeof(u.s.x): 4 sizeof(u.s): 8 sizeof(u.components): 8 sizeof(Units): 1 ``` The problem is that `IntPointTyped` inherits from the empty base `Units`, as does `IntCoordTyped`, and the C++ standard apparently wants the compiler to have different addresses for the two subobjects. The transformation from the extra 1 byte in size to 4 is just alignment. [Here's](https://eel.is/c++draft/class.derived.general#7) the relevant part of the ISO C++ standard: "A base class subobject can be of zero size; however, two subobjects that have the same class type and that belong to the same most derived object cannot be allocated at the same address." If either `IntPointTyped` or `IntCoordTyped` stops inheriting `Units`, the problem goes away (in my test, at least).
Doesn't look like an `__attribute__ ((__packed__))` issue. Here's a crass simplification of the Mozilla code: ```c++ #include <cstdint> #include <iostream> template <class T, class Sub, class Coord = T> struct BasePoint { union { struct { Coord x, y; } s; Coord components[2] = {}; } u; constexpr BasePoint() = default; }; template <class T, class Sub> struct BaseCoord { T value; }; template <class Units, class Rep> struct IntCoordTyped : public BaseCoord<Rep, IntCoordTyped<Units, Rep>>, public Units { }; template <class Units> struct IntPointTyped : public BasePoint<int32_t, IntPointTyped<Units>, IntCoordTyped<Units, int32_t> >, public Units { constexpr IntPointTyped() { std::cout << "sizeof(IntPointTyped): " << sizeof(IntPointTyped) << "\nsizeof(int32_t) * 2: " << sizeof(int32_t) * 2 << "\nsizeof(u.s.x): " << sizeof(this->u.s.x) << "\nsizeof(u.s): " << sizeof(this->u.s) << "\nsizeof(u.components): " << sizeof(this->u.components) << "\nsizeof(Units): " << sizeof(Units) << std::endl; } }; struct UnknownUnits {}; typedef IntPointTyped<UnknownUnits> IntPoint; int main() { IntPoint ip; } ``` This outputs: ``` sizeof(IntPointTyped): 12 sizeof(int32_t) * 2: 8 sizeof(u.s.x): 4 sizeof(u.s): 8 sizeof(u.components): 8 sizeof(Units): 1 ``` The problem is that `IntPointTyped` inherits from the empty base `Units`, as does `IntCoordTyped`, and the C++ standard apparently wants the compiler to have different addresses for the two subobjects. The transformation from the extra 1 byte in size to 4 is just alignment. [Here's](https://eel.is/c++draft/class.derived.general#7) the relevant part of the ISO C++ standard: *"A base class subobject can be of zero size; however, two subobjects that have the same class type and that belong to the same most derived object cannot be allocated at the same address."* If either `IntPointTyped` or `IntCoordTyped` stops inheriting `Units`, the problem goes away (in my test, at least).
Doesn't look like an `__attribute__ ((__packed__))` issue. Here's a crass simplification of the Mozilla code: ```c++ #include <cstdint> #include <iostream> template <class T, class Sub, class Coord = T> struct BasePoint { union { struct { Coord x, y; } s; Coord components[2] = {}; } u; constexpr BasePoint() = default; }; template <class T, class Sub> struct BaseCoord { T value; }; template <class Units, class Rep> struct IntCoordTyped : public BaseCoord<Rep, IntCoordTyped<Units, Rep>>, public Units { }; template <class Units> struct IntPointTyped : public BasePoint<int32_t, IntPointTyped<Units>, IntCoordTyped<Units, int32_t> >, public Units { constexpr IntPointTyped() { std::cout << "sizeof(IntPointTyped): " << sizeof(IntPointTyped) << "\nsizeof(int32_t) * 2: " << sizeof(int32_t) * 2 << "\nsizeof(u.s.x): " << sizeof(this->u.s.x) << "\nsizeof(u.s): " << sizeof(this->u.s) << "\nsizeof(u.components): " << sizeof(this->u.components) << "\nsizeof(Units): " << sizeof(Units) << std::endl; } }; struct UnknownUnits {}; typedef IntPointTyped<UnknownUnits> IntPoint; int main() { IntPoint ip; } ``` This outputs: ``` sizeof(IntPointTyped): 12 sizeof(int32_t) * 2: 8 sizeof(u.s.x): 4 sizeof(u.s): 8 sizeof(u.components): 8 sizeof(Units): 1 ``` The problem is that `IntPointTyped` inherits from the empty base `Units`, as does `IntCoordTyped`, and the C++ standard apparently wants the compiler to have different addresses for the subobjects. The transformation from the extra 1 byte in size to 4 is just alignment. [Here's](https://eel.is/c++draft/class.derived.general#7) the relevant part of the ISO C++ standard: *"A base class subobject can be of zero size; however, two subobjects that have the same class type and that belong to the same most derived object cannot be allocated at the same address."* If either `IntPointTyped` or `IntCoordTyped` stops inheriting `Units`, the problem goes away (in my test, at least).
Doesn't look like an `__attribute__ ((__packed__))` issue. Here's a crass simplification of the Mozilla code: ```c++ #include <cstdint> #include <iostream> template <class T, class Sub, class Coord = T> struct BasePoint { union { struct { Coord x, y; } s; Coord components[2] = {}; } u; constexpr BasePoint() = default; }; template <class T, class Sub> struct BaseCoord { T value; }; template <class Units, class Rep> struct IntCoordTyped : public BaseCoord<Rep, IntCoordTyped<Units, Rep>>, public Units { }; template <class Units> struct IntPointTyped : public BasePoint<int32_t, IntPointTyped<Units>, IntCoordTyped<Units, int32_t> >, public Units { constexpr IntPointTyped() { std::cout << "sizeof(IntPointTyped): " << sizeof(IntPointTyped) << "\nsizeof(int32_t) * 2: " << sizeof(int32_t) * 2 << "\nsizeof(u.s.x): " << sizeof(this->u.s.x) << "\nsizeof(u.s): " << sizeof(this->u.s) << "\nsizeof(u.components): " << sizeof(this->u.components) << "\nsizeof(Units): " << sizeof(Units) << std::endl; } }; struct UnknownUnits {}; typedef IntPointTyped<UnknownUnits> IntPoint; int main() { IntPoint ip; } ``` This outputs: ``` sizeof(IntPointTyped): 12 sizeof(int32_t) * 2: 8 sizeof(u.s.x): 4 sizeof(u.s): 8 sizeof(u.components): 8 sizeof(Units): 1 ``` The problem is that `IntPointTyped` inherits from the empty base `Units`, as does `IntCoordTyped`, and the C++ standard apparently wants the compiler to have different addresses for the subobjects. The transformation from the extra 1 byte in size to 4 is just padding. [Here's](https://eel.is/c++draft/class.derived.general#7) the relevant part of the ISO C++ standard: *"A base class subobject can be of zero size; however, two subobjects that have the same class type and that belong to the same most derived object cannot be allocated at the same address."* If either `IntPointTyped` or `IntCoordTyped` stops inheriting `Units`, the problem goes away (in my test, at least).