Skip to content

Commit 0235967

Browse files
committed
ClangImporter: Support unnamed struct and union types
This covers this case: struct foo { struct { int x; int y; } bar; union { void *ptr; float num; } baz; }; Based on the original patch by Graham Batty. Progress on <rdar://problem/21683348> -- anonymous unnamed unions are still not supported (struct foo { union { int x, y }; };). Swift SVN r31924
1 parent 7434e7d commit 0235967

File tree

6 files changed

+232
-102
lines changed

6 files changed

+232
-102
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 151 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -867,8 +867,8 @@ makeUnionFieldAccessors(ClangImporter::Implementation &Impl,
867867

868868
static clang::DeclarationName
869869
getAccessorDeclarationName(clang::ASTContext &Ctx,
870-
clang::RecordDecl *structDecl,
871-
clang::FieldDecl *fieldDecl,
870+
StructDecl *structDecl,
871+
VarDecl *fieldDecl,
872872
const char *suffix) {
873873
std::string id;
874874
llvm::raw_string_ostream IdStream(id);
@@ -906,8 +906,8 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
906906
auto fieldNameInfo = clang::DeclarationNameInfo(fieldDecl->getDeclName(),
907907
clang::SourceLocation());
908908

909-
auto cGetterName = getAccessorDeclarationName(Ctx, structDecl, fieldDecl,
910-
"getter");
909+
auto cGetterName = getAccessorDeclarationName(Ctx, importedStructDecl,
910+
importedFieldDecl, "getter");
911911
auto cGetterType = Ctx.getFunctionType(fieldDecl->getType(),
912912
recordType,
913913
clang::FunctionProtoType::ExtProtoInfo());
@@ -933,8 +933,8 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
933933
cSetterParamTypes.push_back(fieldType);
934934
cSetterParamTypes.push_back(recordPointerType);
935935

936-
auto cSetterName = getAccessorDeclarationName(Ctx, structDecl, fieldDecl,
937-
"setter");
936+
auto cSetterName = getAccessorDeclarationName(Ctx, importedStructDecl,
937+
importedFieldDecl, "setter");
938938
auto cSetterType = Ctx.getFunctionType(Ctx.VoidTy,
939939
cSetterParamTypes,
940940
clang::FunctionProtoType::ExtProtoInfo());
@@ -1062,6 +1062,62 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
10621062
return { getterDecl, setterDecl };
10631063
}
10641064

1065+
// Fake a declaration name for anonymous enums, unions and structs.
1066+
static Identifier getClangDeclName(ClangImporter::Implementation &Impl,
1067+
const clang::TagDecl *decl) {
1068+
Identifier name;
1069+
if (decl->getDeclName())
1070+
name = Impl.importName(decl);
1071+
else if (auto *typedefForAnon = decl->getTypedefNameForAnonDecl())
1072+
name = Impl.importName(typedefForAnon);
1073+
1074+
// If the type has no name and no structure name, but is not anonymous,
1075+
// generate a name for it. Specifically this is for cases like:
1076+
// struct a {
1077+
// struct {} z;
1078+
// }
1079+
// Where the member z is an unnamed struct, but does have a member-name
1080+
// and is accessible as a member of struct a.
1081+
if (name.empty() && decl->isRecord()) {
1082+
auto dc = decl->getParent();
1083+
if (!dc->isRecord())
1084+
return name;
1085+
1086+
auto recordDecl = cast<clang::RecordDecl>(dc);
1087+
1088+
for (auto m : recordDecl->decls()) {
1089+
auto field = dyn_cast<clang::FieldDecl>(m);
1090+
if (!field)
1091+
continue;
1092+
1093+
if (auto recordType = dyn_cast<clang::RecordType>(field->getType().getCanonicalType())) {
1094+
if (recordType->getDecl() == decl) {
1095+
// We found the field. It better not be anonymous.
1096+
assert(!field->isAnonymousStructOrUnion());
1097+
1098+
// Create a name for the structure from the field name.
1099+
std::string Id;
1100+
llvm::raw_string_ostream IdStream(Id);
1101+
1102+
const char *kind;
1103+
if (decl->isStruct())
1104+
kind = "struct";
1105+
else if (decl->isUnion())
1106+
kind = "union";
1107+
else
1108+
assert(false && "unknown decl kind");
1109+
1110+
IdStream << "__Unnamed_" << kind
1111+
<< "_" << field->getName();
1112+
return Impl.SwiftContext.getIdentifier(IdStream.str());
1113+
}
1114+
}
1115+
}
1116+
}
1117+
1118+
return name;
1119+
}
1120+
10651121
namespace {
10661122
class CFPointeeInfo {
10671123
bool IsValid;
@@ -2078,12 +2134,7 @@ namespace {
20782134
return nullptr;
20792135
}
20802136

2081-
Identifier name;
2082-
if (decl->getDeclName())
2083-
name = Impl.importName(decl);
2084-
else if (auto *typedefForAnon = decl->getTypedefNameForAnonDecl())
2085-
name = Impl.importName(typedefForAnon);
2086-
2137+
auto name = getClangDeclName(Impl, decl);
20872138
if (name.empty())
20882139
return nullptr;
20892140

@@ -2338,12 +2389,7 @@ namespace {
23382389
return nullptr;
23392390
}
23402391

2341-
Identifier name;
2342-
if (decl->getDeclName())
2343-
name = Impl.importName(decl);
2344-
else if (auto *typedefForAnon = decl->getTypedefNameForAnonDecl())
2345-
name = Impl.importName(typedefForAnon);
2346-
2392+
auto name = getClangDeclName(Impl, decl);
23472393
if (name.empty())
23482394
return nullptr;
23492395

@@ -2370,105 +2416,108 @@ namespace {
23702416

23712417
// FIXME: Import anonymous union fields and support field access when
23722418
// it is nested in a struct.
2373-
if (!(decl->isUnion() && decl->isAnonymousStructOrUnion())) {
2374-
for (auto m = decl->decls_begin(), mEnd = decl->decls_end();
2375-
m != mEnd; ++m) {
2376-
auto nd = dyn_cast<clang::NamedDecl>(*m);
2377-
if (!nd) {
2378-
// We couldn't import the member, so we can't reference it in Swift.
2379-
hasUnreferenceableStorage = true;
2380-
hasMemberwiseInitializer = false;
2381-
continue;
2382-
}
23832419

2420+
for (auto m = decl->decls_begin(), mEnd = decl->decls_end();
2421+
m != mEnd; ++m) {
2422+
auto nd = dyn_cast<clang::NamedDecl>(*m);
2423+
if (!nd) {
2424+
// We couldn't import the member, so we can't reference it in Swift.
2425+
hasUnreferenceableStorage = true;
2426+
hasMemberwiseInitializer = false;
2427+
continue;
2428+
}
2429+
2430+
if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
23842431
// Skip anonymous structs or unions; they'll be dealt with via the
23852432
// IndirectFieldDecls.
2386-
if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
2387-
if (field->isAnonymousStructOrUnion())
2388-
continue;
2433+
if (field->isAnonymousStructOrUnion())
2434+
continue;
23892435

2390-
// Non-nullable pointers can't be zero-initialized.
2391-
if (auto nullability = field->getType()
2392-
->getNullability(Impl.getClangASTContext())) {
2393-
if (*nullability == clang::NullabilityKind::NonNull)
2394-
hasZeroInitializableStorage = false;
2395-
}
2396-
// TODO: If we had the notion of a closed enum with no private
2397-
// cases or resilience concerns, then complete NS_ENUMs with
2398-
// no case corresponding to zero would also not be zero-
2399-
// initializable.
2400-
2401-
// Unnamed bitfields are just for padding and should not
2402-
// inhibit creation of a memberwise initializer.
2403-
if (field->isUnnamedBitfield()) {
2404-
hasUnreferenceableStorage = true;
2405-
continue;
2406-
}
2436+
// Non-nullable pointers can't be zero-initialized.
2437+
if (auto nullability = field->getType()
2438+
->getNullability(Impl.getClangASTContext())) {
2439+
if (*nullability == clang::NullabilityKind::NonNull)
2440+
hasZeroInitializableStorage = false;
24072441
}
2408-
2409-
auto member = Impl.importDecl(nd);
2410-
if (!member || !isa<VarDecl>(member)) {
2411-
// We don't import nested struct decls from C as nested structs,
2412-
// which wouldn't match C or ObjC semantics. It's OK to skip these.
2413-
// TODO: For C++ types we *would* want to preserve the nesting.
2414-
if (dyn_cast_or_null<TypeDecl>(member))
2415-
continue;
2416-
2417-
// Otherwise, we don't know what this field is. Assume it may be
2418-
// important in C.
2442+
// TODO: If we had the notion of a closed enum with no private
2443+
// cases or resilience concerns, then complete NS_ENUMs with
2444+
// no case corresponding to zero would also not be zero-
2445+
// initializable.
2446+
2447+
// Unnamed bitfields are just for padding and should not
2448+
// inhibit creation of a memberwise initializer.
2449+
if (field->isUnnamedBitfield()) {
24192450
hasUnreferenceableStorage = true;
2420-
hasMemberwiseInitializer = false;
24212451
continue;
24222452
}
2423-
2424-
auto VD = cast<VarDecl>(member);
2453+
}
24252454

2426-
// Bitfields are imported as computed properties with Clang-generated
2427-
// accessors.
2428-
if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
2429-
if (field->isUnnamedBitfield())
2430-
continue;
2455+
auto member = Impl.importDecl(nd);
2456+
if (!member) {
2457+
// We don't know what this field is. Assume it may be important in C.
2458+
hasUnreferenceableStorage = true;
2459+
hasMemberwiseInitializer = false;
2460+
continue;
2461+
}
2462+
2463+
if (isa<TypeDecl>(member)) {
2464+
// A struct nested inside another struct will either be logically
2465+
// a sibling of the outer struct, or contained inside of it, depending
2466+
// on if it has a declaration name or not.
2467+
//
2468+
// struct foo { struct bar { ... } baz; } // sibling
2469+
// struct foo { struct { ... } baz; } // child
2470+
//
2471+
// In the latter case, we add the imported type as a nested type
2472+
// of the parent.
2473+
//
2474+
// TODO: C++ types have different rules.
2475+
if (auto nominalDecl = dyn_cast<NominalTypeDecl>(member->getDeclContext()))
2476+
nominalDecl->addMember(member);
2477+
continue;
2478+
}
24312479

2432-
if (field->isBitField()) {
2433-
// We can't represent this struct completely in SIL anymore,
2434-
// but we're still able to define a memberwise initializer.
2435-
hasUnreferenceableStorage = true;
2480+
auto VD = cast<VarDecl>(member);
24362481

2437-
makeBitFieldAccessors(Impl,
2438-
const_cast<clang::RecordDecl *>(decl),
2439-
result,
2440-
const_cast<clang::FieldDecl *>(field),
2441-
VD);
2442-
}
2482+
// Bitfields are imported as computed properties with Clang-generated
2483+
// accessors.
2484+
if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
2485+
if (field->isBitField()) {
2486+
// We can't represent this struct completely in SIL anymore,
2487+
// but we're still able to define a memberwise initializer.
2488+
hasUnreferenceableStorage = true;
2489+
2490+
makeBitFieldAccessors(Impl,
2491+
const_cast<clang::RecordDecl *>(decl),
2492+
result,
2493+
const_cast<clang::FieldDecl *>(field),
2494+
VD);
24432495
}
2496+
}
24442497

2445-
if (decl->isUnion()) {
2446-
// Union fields should only be available indirectly via a computed
2447-
// property. Since the union is made of all of the fields at once,
2448-
// this is a trivial accessor that casts self to the correct
2449-
// field type.
2498+
if (decl->isUnion()) {
2499+
// Union fields should only be available indirectly via a computed
2500+
// property. Since the union is made of all of the fields at once,
2501+
// this is a trivial accessor that casts self to the correct
2502+
// field type.
24502503

2451-
// FIXME: Allow indirect field access of anonymous structs.
2452-
if (isa<clang::IndirectFieldDecl>(nd))
2453-
continue;
2504+
// FIXME: Allow indirect field access of anonymous structs.
2505+
if (isa<clang::IndirectFieldDecl>(nd))
2506+
continue;
24542507

2455-
VD->setLet(false);
2456-
Decl *getter, *setter;
2457-
std::tie(getter, setter) = makeUnionFieldAccessors(Impl,
2458-
result,
2459-
VD);
2460-
members.push_back(VD);
2461-
2462-
// Create labeled inititializers for unions that take one of the
2463-
// fields, which only initializes the data for that field.
2464-
auto valueCtor =
2465-
createValueConstructor(result, VD,
2466-
/*want param names*/true,
2467-
/*wantBody=*/!Impl.hasFinishedTypeChecking());
2468-
ctors.push_back(valueCtor);
2469-
} else {
2470-
members.push_back(VD);
2471-
}
2508+
Decl *getter, *setter;
2509+
std::tie(getter, setter) = makeUnionFieldAccessors(Impl, result, VD);
2510+
members.push_back(VD);
2511+
2512+
// Create labeled inititializers for unions that take one of the
2513+
// fields, which only initializes the data for that field.
2514+
auto valueCtor =
2515+
createValueConstructor(result, VD,
2516+
/*want param names*/true,
2517+
/*wantBody=*/!Impl.hasFinishedTypeChecking());
2518+
ctors.push_back(valueCtor);
2519+
} else {
2520+
members.push_back(VD);
24722521
}
24732522
}
24742523

test/ClangModules/ctypes_parse.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,21 @@ func testAnonStructs() {
5858
a_s.c = 7.5
5959
}
6060

61+
func testUnnamedStructs() {
62+
var u_s: UnnamedStructs
63+
u_s.x.a = 1
64+
u_s.x.b = 3.14
65+
u_s.x.c = "error" // expected-error{{value of type 'UnnamedStructs.__Unnamed_struct_x' has no member 'c'}}
66+
u_s.y.a = 3.14
67+
u_s.y.b = 2
68+
u_s.y.c = "error" // expected-error{{value of type 'UnnamedStructs.__Unnamed_struct_y' has no member 'c'}}
69+
u_s.y.z.c = 3
70+
u_s.y.z.d = "error" // expected-error{{value of type 'UnnamedStructs.__Unnamed_struct_y.__Unnamed_struct_z' has no member 'd'}}
71+
72+
let _ = u_s.x
73+
let _: UnnamedStructs.__Unnamed_struct_x = u_s.x
74+
}
75+
6176
// FIXME: Import pointers to opaque types as unique types.
6277

6378
func testPointers() {

test/Inputs/clang-importer-sdk/platform/any/usr/include/bitfields.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ typedef struct ModRM {
66
unsigned opcode;
77
} ModRM;
88

9+
struct AnonStructWithBitfields {
10+
struct {
11+
int first: 2;
12+
int second: 2;
13+
} left;
14+
struct {
15+
int first: 2;
16+
int second: 2;
17+
} right;
18+
};

test/Inputs/clang-importer-sdk/usr/include/ctypes.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ typedef struct {
3232
};
3333
} AnonStructs;
3434

35+
typedef struct {
36+
struct {
37+
int a;
38+
float b;
39+
} x;
40+
struct {
41+
float a;
42+
int b;
43+
struct {
44+
int c;
45+
} z;
46+
} y;
47+
} UnnamedStructs;
48+
3549
typedef void const *HWND;
3650

3751
typedef struct {

test/Interpreter/c_bitfields.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ BitfieldTestSuite.test("Simple") {
2222
expectEqual(44, new.opcode)
2323
}
2424

25+
BitfieldTestSuite.test("Anonymous Struct") {
26+
var new = AnonStructWithBitfields()
27+
new.left.first = 1
28+
new.left.second = -1
29+
new.right.first = -1
30+
new.right.second = 1
31+
32+
expectEqual(1, new.left.first)
33+
expectEqual(-1, new.left.second)
34+
expectEqual(-1, new.right.first)
35+
expectEqual(1, new.right.second)
36+
}
37+
2538
BitfieldTestSuite.test("Initializer") {
2639
let new = ModRM(rm: 6, reg: 4, mod: 2, opcode: 33)
2740

0 commit comments

Comments
 (0)