mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
In C++, a primary base class that is placed in the beginning of the type's memory layout isn't always the type that is the first in the list of bases – the base types might be laid out in memory in a different order. This makes sure that IRGen handles base types of C++ structs in the correct order. This fixes an assertion in asserts-enabled compilers, and an out-of-memory error in asserts-disabled compilers. The issue was happening for both value types and foreign reference types. This change also includes a small refactoring to reuse the logic between the two code paths. rdar://140848603
159 lines
3.3 KiB
C++
159 lines
3.3 KiB
C++
struct HasThreeFields {
|
|
int a = 1;
|
|
int b = 2;
|
|
int c = 3;
|
|
};
|
|
|
|
struct DerivedWithSameField : HasThreeFields {
|
|
int a = 2;
|
|
};
|
|
|
|
struct DerivedWithOneField : HasThreeFields {
|
|
int d = 4;
|
|
};
|
|
|
|
struct HasOneField {
|
|
int e = 5;
|
|
};
|
|
|
|
struct DerivedFromAll : HasOneField, DerivedWithOneField {
|
|
int f = 6;
|
|
};
|
|
|
|
struct OneField {
|
|
int value = 42;
|
|
};
|
|
|
|
struct DerivedFromOneField : OneField {};
|
|
|
|
// Non trivial types:
|
|
|
|
struct __attribute__((swift_attr("import_unsafe"))) NonTrivial {
|
|
NonTrivial() {}
|
|
NonTrivial(const NonTrivial &) {}
|
|
~NonTrivial() {}
|
|
};
|
|
|
|
struct NonTrivialHasThreeFields : NonTrivial {
|
|
int a = 1;
|
|
int b = 2;
|
|
int c = 3;
|
|
};
|
|
|
|
struct NonTrivialDerivedWithOneField : NonTrivialHasThreeFields {
|
|
int d = 4;
|
|
};
|
|
|
|
struct __attribute__((swift_attr("import_unsafe"))) NonTrivialHasOneField {
|
|
NonTrivialHasOneField() {}
|
|
NonTrivialHasOneField(const NonTrivialHasOneField &other) : e(other.e) {}
|
|
~NonTrivialHasOneField() {}
|
|
|
|
int e = 5;
|
|
};
|
|
|
|
struct __attribute__((swift_attr("import_unsafe"))) NonTrivialDerivedFromAll
|
|
: NonTrivialHasOneField,
|
|
NonTrivialDerivedWithOneField {
|
|
int f = 6;
|
|
};
|
|
|
|
// Templates:
|
|
|
|
template<class T>
|
|
struct ClassTemplate {
|
|
T value;
|
|
};
|
|
|
|
struct DerivedFromClassTemplate : ClassTemplate<int> {};
|
|
|
|
int &getCopyCounter() {
|
|
static int copyCounter = 0;
|
|
return copyCounter;
|
|
}
|
|
|
|
class CopyTrackedBaseClass {
|
|
public:
|
|
CopyTrackedBaseClass(int x) : x(x) {}
|
|
CopyTrackedBaseClass(const CopyTrackedBaseClass &other) : x(other.x) {
|
|
++getCopyCounter();
|
|
}
|
|
|
|
int x;
|
|
};
|
|
|
|
class CopyTrackedDerivedClass: public CopyTrackedBaseClass {
|
|
public:
|
|
CopyTrackedDerivedClass(int x) : CopyTrackedBaseClass(x) {}
|
|
};
|
|
|
|
class NonEmptyBase {
|
|
public:
|
|
int getY() const {
|
|
return y;
|
|
}
|
|
private:
|
|
int y = 11;
|
|
};
|
|
|
|
class CopyTrackedDerivedDerivedClass: public NonEmptyBase, public CopyTrackedDerivedClass {
|
|
public:
|
|
CopyTrackedDerivedDerivedClass(int x) : CopyTrackedDerivedClass(x) {}
|
|
};
|
|
|
|
// Types with virtual methods, make sure field offsets are right. rdar://126754931
|
|
|
|
struct HasOneFieldWithVirtualMethod {
|
|
int a;
|
|
virtual ~HasOneFieldWithVirtualMethod() {}
|
|
};
|
|
|
|
struct HasTwoFieldsWithVirtualMethod {
|
|
bool b;
|
|
bool c;
|
|
virtual ~HasTwoFieldsWithVirtualMethod() = default;
|
|
};
|
|
|
|
struct InheritFromStructsWithVirtualMethod: HasOneFieldWithVirtualMethod, HasTwoFieldsWithVirtualMethod {
|
|
int d;
|
|
virtual ~InheritFromStructsWithVirtualMethod() = default;
|
|
};
|
|
|
|
// MARK: Types that pack their fields into tail padding of a base class.
|
|
|
|
struct BaseAlign8 {
|
|
long long field8 = 123;
|
|
}; // sizeof=8, dsize=8, align=8
|
|
|
|
struct DerivedHasTailPadding : public BaseAlign8 {
|
|
int field4 = 456;
|
|
}; // sizeof=16, dsize=12, align=8
|
|
|
|
struct DerivedUsesBaseTailPadding : public DerivedHasTailPadding {
|
|
short field2 = 789;
|
|
}; // sizeof=16, dsize=14, align=8
|
|
|
|
// MARK: Types with an out-of-order inheritance.
|
|
|
|
struct BaseWithVirtualDestructor {
|
|
int baseField = 123;
|
|
|
|
virtual ~BaseWithVirtualDestructor() {}
|
|
};
|
|
|
|
struct DerivedWithVirtualDestructor : public BaseWithVirtualDestructor {
|
|
int derivedField = 456;
|
|
|
|
~DerivedWithVirtualDestructor() override {}
|
|
};
|
|
|
|
struct DerivedOutOfOrder : public HasOneField,
|
|
public DerivedWithVirtualDestructor {
|
|
// DerivedWithVirtualDestructor is the primary base class despite being the
|
|
// second one the list.
|
|
|
|
int leafField = 789;
|
|
|
|
~DerivedOutOfOrder() override {}
|
|
};
|