Skip to content

Commit 0951648

Browse files
committed
IRGen: Fix handling of empty fields in Clang-imported types.
Clang allows C structs to have zero-sized array fields for things like trailing buffers. Lower these correctly into Swift types in IRGen so that Swift codegen knows to treat them as empty types. Fixes rdar://problem/31042794.
1 parent ff7dde6 commit 0951648

File tree

3 files changed

+25
-6
lines changed

3 files changed

+25
-6
lines changed

lib/IRGen/GenStruct.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ namespace {
164164
llvm::Constant *getConstantFieldOffset(IRGenModule &IGM,
165165
VarDecl *field) const {
166166
auto &fieldInfo = getFieldInfo(field);
167-
if (fieldInfo.getKind() == ElementLayout::Kind::Fixed) {
167+
if (fieldInfo.getKind() == ElementLayout::Kind::Fixed
168+
|| fieldInfo.getKind() == ElementLayout::Kind::Empty) {
168169
return llvm::ConstantInt::get(IGM.SizeTy,
169170
fieldInfo.getFixedByteOffset().getValue());
170171
}
@@ -773,14 +774,22 @@ class ClangRecordLowering {
773774
unsigned explosionEnd = NextExplosionIndex;
774775

775776
ElementLayout layout = ElementLayout::getIncomplete(fieldType);
776-
layout.completeFixed(fieldType.isPOD(ResilienceExpansion::Maximal),
777-
NextOffset, LLVMFields.size());
777+
auto isEmpty = fieldType.isKnownEmpty(ResilienceExpansion::Maximal);
778+
if (isEmpty)
779+
layout.completeEmpty(fieldType.isPOD(ResilienceExpansion::Maximal),
780+
NextOffset);
781+
else
782+
layout.completeFixed(fieldType.isPOD(ResilienceExpansion::Maximal),
783+
NextOffset, LLVMFields.size());
778784

779785
FieldInfos.push_back(
780786
ClangFieldInfo(swiftField, layout, explosionBegin, explosionEnd));
781-
LLVMFields.push_back(fieldType.getStorageType());
782-
NextOffset += fieldType.getFixedSize();
783-
SpareBits.append(fieldType.getSpareBits());
787+
788+
if (!isEmpty) {
789+
LLVMFields.push_back(fieldType.getStorageType());
790+
NextOffset += fieldType.getFixedSize();
791+
SpareBits.append(fieldType.getSpareBits());
792+
}
784793
}
785794

786795
/// Add padding to get up to the given offset.

test/IRGen/Inputs/clang_empty_type.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct TrailingArray {
2+
int size;
3+
char buffer[0];
4+
};

test/IRGen/clang_empty_type.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-swift-frontend -emit-ir -verify -import-objc-header %S/Inputs/clang_empty_type.h %s
2+
3+
public func projectTrailingArray(x: inout TrailingArray) {
4+
x.size = 2
5+
x.buffer = ()
6+
}

0 commit comments

Comments
 (0)