Skip to content

Commit 2302f59

Browse files
authored
Merge pull request #6531 from Fruneau/indirect-fields
Clang Importer: import all indirect fields.
2 parents a37fa88 + 68bc423 commit 2302f59

File tree

3 files changed

+185
-129
lines changed

3 files changed

+185
-129
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 164 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,122 @@ static FuncDecl *makeFieldSetterDecl(ClangImporter::Implementation &Impl,
598598
return setterDecl;
599599
}
600600

601+
/// Build the indirect field getter and setter.
602+
///
603+
/// \code
604+
/// struct SomeImportedIndirectField {
605+
/// struct __Unnamed_struct___Anonymous_field_1 {
606+
/// var myField : Int
607+
/// }
608+
/// var __Anonymous_field_1 : __Unnamed_struct___Anonymous_field_1
609+
/// var myField : Int {
610+
/// get {
611+
/// __Anonymous_field_1.myField
612+
/// }
613+
/// set(newValue) {
614+
/// __Anonymous_field_1.myField = newValue
615+
/// }
616+
/// }
617+
/// }
618+
/// \endcode
619+
///
620+
/// \returns a pair of getter and setter function decls.
621+
static std::pair<FuncDecl *, FuncDecl *>
622+
makeIndirectFieldAccessors(ClangImporter::Implementation &Impl,
623+
const clang::IndirectFieldDecl *indirectField,
624+
ArrayRef<VarDecl *> members,
625+
StructDecl *importedStructDecl,
626+
VarDecl *importedFieldDecl) {
627+
auto &C = Impl.SwiftContext;
628+
629+
auto getterDecl = makeFieldGetterDecl(Impl,
630+
importedStructDecl,
631+
importedFieldDecl);
632+
633+
auto setterDecl = makeFieldSetterDecl(Impl,
634+
importedStructDecl,
635+
importedFieldDecl);
636+
637+
importedFieldDecl->makeComputed(SourceLoc(), getterDecl, setterDecl, nullptr,
638+
SourceLoc());
639+
640+
auto containingField = indirectField->chain().front();
641+
VarDecl *anonymousFieldDecl = nullptr;
642+
643+
// Reverse scan of the members because indirect field are generated just
644+
// after the corresponding anonymous type, so a reverse scan allows
645+
// swiftching from O(n) to O(1) here.
646+
for (auto decl : reverse(members)) {
647+
if (decl->getClangDecl() == containingField) {
648+
anonymousFieldDecl = cast<VarDecl>(decl);
649+
break;
650+
}
651+
}
652+
assert (anonymousFieldDecl && "anonymous field not generated");
653+
654+
auto anonymousFieldType = anonymousFieldDecl->getInterfaceType();
655+
auto anonymousFieldTypeDecl = anonymousFieldType->getStructOrBoundGenericStruct();
656+
657+
VarDecl *anonymousInnerFieldDecl = nullptr;
658+
for (auto decl : anonymousFieldTypeDecl->lookupDirect(importedFieldDecl->getName())) {
659+
if (isa<VarDecl>(decl)) {
660+
anonymousInnerFieldDecl = cast<VarDecl>(decl);
661+
break;
662+
}
663+
}
664+
assert (anonymousInnerFieldDecl && "cannot find field in anonymous generated structure");
665+
666+
// Don't bother synthesizing the body if we've already finished type-checking.
667+
if (Impl.hasFinishedTypeChecking())
668+
return { getterDecl, setterDecl };
669+
670+
// Synthesize the getter body
671+
{
672+
auto selfDecl = getterDecl->getImplicitSelfDecl();
673+
Expr *expr = new (C) DeclRefExpr(selfDecl, DeclNameLoc(),
674+
/*implicit*/true);
675+
expr = new (C) MemberRefExpr(expr, SourceLoc(), anonymousFieldDecl,
676+
DeclNameLoc(), /*implicit*/true);
677+
678+
expr = new (C) MemberRefExpr(expr, SourceLoc(), anonymousInnerFieldDecl,
679+
DeclNameLoc(), /*implicit*/true);
680+
681+
auto ret = new (C) ReturnStmt(SourceLoc(), expr);
682+
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
683+
/*implicit*/ true);
684+
getterDecl->setBody(body);
685+
getterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
686+
C.addExternalDecl(getterDecl);
687+
}
688+
689+
// Synthesize the setter body
690+
{
691+
auto selfDecl = setterDecl->getImplicitSelfDecl();
692+
Expr *lhs = new (C) DeclRefExpr(selfDecl, DeclNameLoc(),
693+
/*implicit*/true);
694+
lhs = new (C) MemberRefExpr(lhs, SourceLoc(), anonymousFieldDecl,
695+
DeclNameLoc(), /*implicit*/true);
696+
697+
lhs = new (C) MemberRefExpr(lhs, SourceLoc(), anonymousInnerFieldDecl,
698+
DeclNameLoc(), /*implicit*/true);
699+
700+
auto newValueDecl = setterDecl->getParameterList(1)->get(0);
701+
702+
auto rhs = new (C) DeclRefExpr(newValueDecl, DeclNameLoc(),
703+
/*implicit*/ true);
704+
705+
auto assign = new (C) AssignExpr(lhs, SourceLoc(), rhs, /*implicit*/true);
706+
707+
auto body = BraceStmt::create(C, SourceLoc(), { assign }, SourceLoc(),
708+
/*implicit*/ true);
709+
setterDecl->setBody(body);
710+
setterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
711+
C.addExternalDecl(setterDecl);
712+
}
713+
714+
return { getterDecl, setterDecl };
715+
}
716+
601717
/// Build the union field getter and setter.
602718
///
603719
/// \code
@@ -971,6 +1087,11 @@ createValueConstructor(ClangImporter::Implementation &Impl,
9711087
// Construct the set of parameters from the list of members.
9721088
SmallVector<ParamDecl *, 8> valueParameters;
9731089
for (auto var : members) {
1090+
// TODO create value constructor with indirect fields instead of the
1091+
// generated __Anonymous_field.
1092+
if (var->hasClangNode() && isa<clang::IndirectFieldDecl>(var->getClangDecl()))
1093+
continue;
1094+
9741095
Identifier argName = wantCtorParamNames ? var->getName() : Identifier();
9751096
auto param = new (context)
9761097
ParamDecl(/*IsLet*/ true, SourceLoc(), SourceLoc(), argName,
@@ -1014,6 +1135,10 @@ createValueConstructor(ClangImporter::Implementation &Impl,
10141135
for (unsigned pass = 0; pass < 2; pass++) {
10151136
for (unsigned i = 0, e = members.size(); i < e; i++) {
10161137
auto var = members[i];
1138+
1139+
if (var->hasClangNode() && isa<clang::IndirectFieldDecl>(var->getClangDecl()))
1140+
continue;
1141+
10171142
if (var->hasStorage() == (pass != 0))
10181143
continue;
10191144

@@ -1751,10 +1876,6 @@ namespace {
17511876
decl->getLexicalDeclContext())) {
17521877
for (auto field : recordDecl->fields()) {
17531878
if (field->getType()->getAsTagDecl() == decl) {
1754-
// We found the field. The field should not be anonymous, since we are
1755-
// using its name to derive the generated declaration name.
1756-
assert(!field->isAnonymousStructOrUnion());
1757-
17581879
// Create a name for the declaration from the field name.
17591880
std::string Id;
17601881
llvm::raw_string_ostream IdStream(Id);
@@ -1767,8 +1888,12 @@ namespace {
17671888
else
17681889
llvm_unreachable("unknown decl kind");
17691890

1770-
IdStream << "__Unnamed_" << kind
1771-
<< "_" << field->getName();
1891+
IdStream << "__Unnamed_" << kind << "_";
1892+
if (field->isAnonymousStructOrUnion()) {
1893+
IdStream << "__Anonymous_field" << field->getFieldIndex();
1894+
} else {
1895+
IdStream << field->getName();
1896+
}
17721897
ImportedName Result;
17731898
Result.setDeclName(Impl.SwiftContext.getIdentifier(IdStream.str()));
17741899
Result.setEffectiveContext(decl->getDeclContext());
@@ -2433,11 +2558,6 @@ namespace {
24332558
if (decl->isInterface())
24342559
return nullptr;
24352560

2436-
// The types of anonymous structs or unions are never imported; their
2437-
// fields are dumped directly into the enclosing class.
2438-
if (decl->isAnonymousStructOrUnion())
2439-
return nullptr;
2440-
24412561
// FIXME: Figure out how to deal with incomplete types, since that
24422562
// notion doesn't exist in Swift.
24432563
decl = decl->getDefinition();
@@ -2494,11 +2614,6 @@ namespace {
24942614
}
24952615

24962616
if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
2497-
// Skip anonymous structs or unions; they'll be dealt with via the
2498-
// IndirectFieldDecls.
2499-
if (field->isAnonymousStructOrUnion())
2500-
continue;
2501-
25022617
// Non-nullable pointers can't be zero-initialized.
25032618
if (auto nullability = field->getType()
25042619
->getNullability(Impl.getClangASTContext())) {
@@ -2547,6 +2662,15 @@ namespace {
25472662

25482663
auto VD = cast<VarDecl>(member);
25492664

2665+
if (isa<clang::IndirectFieldDecl>(nd) || decl->isUnion()) {
2666+
// Don't import unavailable fields that have no associated storage.
2667+
if (VD->getAttrs().isUnavailable(Impl.SwiftContext)) {
2668+
continue;
2669+
}
2670+
}
2671+
2672+
members.push_back(VD);
2673+
25502674
// Bitfields are imported as computed properties with Clang-generated
25512675
// accessors.
25522676
if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
@@ -2563,19 +2687,16 @@ namespace {
25632687
}
25642688
}
25652689

2566-
if (decl->isUnion()) {
2690+
if (auto ind = dyn_cast<clang::IndirectFieldDecl>(nd)) {
2691+
// Indirect fields are created as computed property accessible the
2692+
// fields on the anonymous field from which they are injected.
2693+
makeIndirectFieldAccessors(Impl, ind, members, result, VD);
2694+
} else if (decl->isUnion()) {
25672695
// Union fields should only be available indirectly via a computed
25682696
// property. Since the union is made of all of the fields at once,
25692697
// this is a trivial accessor that casts self to the correct
25702698
// field type.
2571-
2572-
// FIXME: Allow indirect field access of anonymous structs.
2573-
if (isa<clang::IndirectFieldDecl>(nd))
2574-
continue;
2575-
2576-
Decl *getter, *setter;
2577-
std::tie(getter, setter) = makeUnionFieldAccessors(Impl, result, VD);
2578-
members.push_back(VD);
2699+
makeUnionFieldAccessors(Impl, result, VD);
25792700

25802701
// Create labeled initializers for unions that take one of the
25812702
// fields, which only initializes the data for that field.
@@ -2584,8 +2705,6 @@ namespace {
25842705
/*want param names*/true,
25852706
/*wantBody=*/!Impl.hasFinishedTypeChecking());
25862707
ctors.push_back(valueCtor);
2587-
} else {
2588-
members.push_back(VD);
25892708
}
25902709
}
25912710

@@ -2761,16 +2880,6 @@ namespace {
27612880
}
27622881

27632882
Decl *VisitIndirectFieldDecl(const clang::IndirectFieldDecl *decl) {
2764-
// Check whether the context of any of the fields in the chain is a
2765-
// union. If so, don't import this field.
2766-
for (auto f = decl->chain_begin(), fEnd = decl->chain_end(); f != fEnd;
2767-
++f) {
2768-
if (auto record = dyn_cast<clang::RecordDecl>((*f)->getDeclContext())) {
2769-
if (record->isUnion())
2770-
return nullptr;
2771-
}
2772-
}
2773-
27742883
Optional<ImportedName> correctSwiftName;
27752884
auto importedName = importFullName(decl, correctSwiftName);
27762885
if (!importedName) return nullptr;
@@ -2977,8 +3086,24 @@ namespace {
29773086
Decl *VisitFieldDecl(const clang::FieldDecl *decl) {
29783087
// Fields are imported as variables.
29793088
Optional<ImportedName> correctSwiftName;
2980-
auto importedName = importFullName(decl, correctSwiftName);
2981-
if (!importedName) return nullptr;
3089+
ImportedName importedName;
3090+
3091+
if (!decl->isAnonymousStructOrUnion()) {
3092+
importedName = importFullName(decl, correctSwiftName);
3093+
if (!importedName) {
3094+
return nullptr;
3095+
}
3096+
} else {
3097+
// Generate a field name for anonymous fields, this will be used in
3098+
// order to be able to expose the indirect fields injected from there
3099+
// as computed properties forwarding the access to the subfield.
3100+
std::string Id;
3101+
llvm::raw_string_ostream IdStream(Id);
3102+
3103+
IdStream << "__Anonymous_field" << decl->getFieldIndex();
3104+
importedName.setDeclName(Impl.SwiftContext.getIdentifier(IdStream.str()));
3105+
importedName.setEffectiveContext(decl->getDeclContext());
3106+
}
29823107

29833108
auto name = importedName.getDeclName().getBaseName();
29843109

stdlib/public/SDK/GLKit/GLKMath.swift.gyb

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,6 @@
2020
// This overlay generates Swift accessors for the GLKit matrix and vector
2121
// types.
2222

23-
%{
24-
# Each element of the array is a tuple of the element labels and the minimum
25-
# vector length at which to apply them.
26-
vectorElementNames = [
27-
(['x', 'y', 'z', 'w'], 2),
28-
(['s', 't', 'p', 'q'], 2),
29-
(['r', 'g', 'b', 'a'], 3),
30-
]
31-
}%
32-
3323
// Do dirty pointer manipulations to index an opaque struct like an array.
3424
@inline(__always)
3525
public func _indexHomogeneousValue<TTT, T>(_ aggregate: UnsafePointer<TTT>,
@@ -58,69 +48,15 @@ def defineSubscript(Type, limit):
5848
% for size in [2, 3, 4]:
5949

6050
extension GLKMatrix${size} {
61-
public typealias _Tuple = (${ ', '.join(['Float'] * (size * size)) })
62-
public var _tuple: _Tuple {
63-
@inline(__always) get { return unsafeBitCast(self, to: _Tuple.self) }
64-
}
65-
% for i in xrange(0, size):
66-
% for j in xrange(0, size):
67-
public var m${i}${j}: Float {
68-
@inline(__always) get { return _tuple.${i * size + j} }
69-
}
70-
% end
71-
% end
72-
7351
${ defineSubscript("GLKMatrix" + str(size), size * size) }
7452
}
7553

7654
extension GLKVector${size} {
77-
public typealias _Tuple = (${ ', '.join(['Float'] * size) })
78-
public var _tuple: _Tuple {
79-
@inline(__always) get { return unsafeBitCast(self, to: _Tuple.self) }
80-
}
81-
82-
% for (names, minSize) in vectorElementNames:
83-
% for i in xrange(0, size if size >= minSize else 0):
84-
public var ${names[i]}: Float {
85-
@inline(__always) get { return _tuple.${i} }
86-
}
87-
% end
88-
% end
89-
9055
${ defineSubscript("GLKVector" + str(size), size) }
9156
}
9257

9358
% end
9459

9560
extension GLKQuaternion {
96-
public typealias _Tuple = (Float, Float, Float, Float)
97-
public var _tuple: _Tuple {
98-
@inline(__always) get { return unsafeBitCast(self, to: _Tuple.self) }
99-
}
100-
101-
public var v: GLKVector3 {
102-
@inline(__always) get {
103-
let (i, j, k, _) = _tuple
104-
return GLKVector3Make(i, j, k)
105-
}
106-
}
107-
108-
public var s: Float {
109-
@inline(__always) get { return _tuple.3 }
110-
}
111-
112-
public var x: Float {
113-
@inline(__always) get { return _tuple.0 }
114-
}
115-
public var y: Float {
116-
@inline(__always) get { return _tuple.1 }
117-
}
118-
public var z: Float {
119-
@inline(__always) get { return _tuple.2 }
120-
}
121-
public var w: Float {
122-
@inline(__always) get { return _tuple.3 }
123-
}
124-
12561
${ defineSubscript("GLKQuaternion", 4) }
12662
}

0 commit comments

Comments
 (0)