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

Back to Bug 1060421 Comment 11