Skip to content

Commit ee0c0ef

Browse files
Merge pull request #473 from adrian-prantl/unions-next
Add support for C unions in Swift.
2 parents e0bca07 + 24af35a commit ee0c0ef

File tree

6 files changed

+77
-0
lines changed

6 files changed

+77
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
SWIFT_SOURCES := main.swift
2+
SWIFTFLAGS_EXTRAS = -I$(SRCDIR)
3+
4+
include Makefile.rules
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbtest as lldbtest
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import os
6+
import unittest2
7+
8+
9+
class TestSwiftAnyType(lldbtest.TestBase):
10+
11+
mydir = lldbtest.TestBase.compute_mydir(__file__)
12+
13+
@swiftTest
14+
def test_c_unions(self):
15+
self.build()
16+
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
17+
self, 'break here', lldb.SBFileSpec('main.swift'))
18+
self.expect("target variable -- i", substrs=['42'])
19+
self.expect("target variable -- d", substrs=['23'])
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import U
2+
3+
func use<T>(_ t : T) {}
4+
5+
let i = IntDoubleUnion(i: 42)
6+
let d = IntDoubleUnion(d: 23)
7+
use((i, d)) // break here
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module U { header "union.h" }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
union IntDoubleUnion {
2+
int i;
3+
double d;
4+
};

lldb/source/Symbol/SwiftASTContext.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6599,6 +6599,16 @@ uint32_t SwiftASTContext::GetNumFields(void *type) {
65996599
case swift::TypeKind::BoundGenericClass:
66006600
case swift::TypeKind::BoundGenericStruct: {
66016601
auto nominal = swift_can_type->getAnyNominal();
6602+
// Imported unions don't have stored properties.
6603+
if (auto *ntd =
6604+
llvm::dyn_cast_or_null<swift::NominalTypeDecl>(nominal->getDecl()))
6605+
if (auto *rd = llvm::dyn_cast_or_null<clang::RecordDecl>(ntd->getClangDecl()))
6606+
if (rd->isUnion()) {
6607+
swift::DeclRange ms = ntd->getMembers();
6608+
return std::count_if(ms.begin(), ms.end(), [](swift::Decl *D) {
6609+
return llvm::isa<swift::VarDecl>(D);
6610+
});
6611+
}
66026612
return GetStoredProperties(nominal).size();
66036613
}
66046614

@@ -7246,6 +7256,38 @@ CompilerType SwiftASTContext::GetChildCompilerTypeAtIndex(
72467256
case swift::TypeKind::Struct:
72477257
case swift::TypeKind::BoundGenericStruct: {
72487258
auto nominal = swift_can_type->getAnyNominal();
7259+
7260+
// Imported unions don't have stored properties, iterate over the
7261+
// VarDecls instead.
7262+
if (auto *ntd =
7263+
llvm::dyn_cast_or_null<swift::NominalTypeDecl>(nominal->getDecl()))
7264+
if (auto *rd = llvm::dyn_cast_or_null<clang::RecordDecl>(ntd->getClangDecl()))
7265+
if (rd->isUnion()) {
7266+
unsigned count = 0;
7267+
for (swift::Decl *D : ntd->getMembers()) {
7268+
auto *VD = llvm::dyn_cast_or_null<swift::VarDecl>(D);
7269+
if (!VD)
7270+
continue;
7271+
if (count++ < idx)
7272+
continue;
7273+
7274+
swift::Type child_swift_type = VD->getType();
7275+
7276+
CompilerType child_type =
7277+
ToCompilerType(VD->getType().getPointer());
7278+
child_name = VD->getNameStr();
7279+
if (!get_type_size(child_byte_size, child_type))
7280+
return {};
7281+
child_is_base_class = false;
7282+
child_is_deref_of_parent = false;
7283+
child_byte_offset = 0;
7284+
child_bitfield_bit_size = 0;
7285+
child_bitfield_bit_offset = 0;
7286+
return child_type;
7287+
}
7288+
return {};
7289+
}
7290+
72497291
auto stored_properties = GetStoredProperties(nominal);
72507292
if (idx >= stored_properties.size())
72517293
break;

0 commit comments

Comments
 (0)