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).