From 4f65ef92c271b6fd65a4a23ea487cc532b0606c4 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Mon, 22 Aug 2016 13:37:13 -0700 Subject: [PATCH] Runtime: Don't clobber the compiler-emitted layout of empty fields. Otherwise, we try to dirty constant memory for classes emitted as constant-layout by the compiler. Fixes rdar://problem/27951346. --- stdlib/public/runtime/Metadata.cpp | 3 ++ .../generic_class_empty_field.swift | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 test/Interpreter/generic_class_empty_field.swift diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 51023676d55d1..6ee8b3413663f 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -1764,6 +1764,9 @@ swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self, // Okay, now do layout. for (unsigned i = 0; i != numFields; ++i) { + // Skip empty fields. + if (fieldOffsets[i] == 0 && fieldLayouts[i].Size == 0) + continue; auto offset = roundUpToAlignMask(size, fieldLayouts[i].AlignMask); fieldOffsets[i] = offset; size = offset + fieldLayouts[i].Size; diff --git a/test/Interpreter/generic_class_empty_field.swift b/test/Interpreter/generic_class_empty_field.swift new file mode 100644 index 0000000000000..da980ed4459f0 --- /dev/null +++ b/test/Interpreter/generic_class_empty_field.swift @@ -0,0 +1,47 @@ +// RUN: rm -rf %t && mkdir %t +// RUN: %target-build-swift %s -o %t/a.out +// RUN: %target-run %t/a.out | %FileCheck %s +// REQUIRES: executable_test + +class Outer { + class Foo { + var zim = Bar() + var bas = Outer() + } + class Boo { + var bas = Outer() + var zim = Bar() + } + + required init() {} +} + +protocol Initable { init() } +extension Outer: Initable {} + +class GFoo { + var zim = Bar() + var bas = T() +} +class GBoo { + var bas = T() + var zim = Bar() +} +class GFos { + var bar = T() + var zim = Bar() + var bas = T() +} + +struct Bar { } + +do { + let a = Outer.Foo() + let b = Outer.Boo() + let c = GFoo() + let d = GBoo() + let e = GFos() +} + +// CHECK: Job's finished +print("Job's finished")