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
`assert`s get stripped away in release builds. To make sure the checks in tests still run in release builds, this switches to `expectTrue`/`expectFalse` instead of `assert`.
For types imported from C++, the original clang::TypeDecl is saved in
the swift::Type and reused for conversions back to clang::QualType.
However, the conversion did not account for foreign reference types,
which should be mapped to a pointer to the C++ record type, rather than
the record type itself.
This bug first appeared as a function template instantiation failure
due to a sanity check performed by SwiftDeclConverter::foreignReferenceTypePassedByRef()
but may also affect other round-tripping type conversions.
The added test case demonstrates the template instantiation scenario,
where templates were being used to overcome Swift/C++ interop's current
lack of support for class inheritance.
rdar://134979343