Skip to content

Commit 859f60d

Browse files
authored
Merge pull request #84120 from Xazax-hun/no-vwt-for-anon-types-on-6.2
[6.2][cxx-interop] Basic support for anonymous structs with non-copyable fields
2 parents a4a95f5 + 95ff51c commit 859f60d

File tree

8 files changed

+69
-7
lines changed

8 files changed

+69
-7
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3073,11 +3073,11 @@ namespace {
30733073
}
30743074
}
30753075
}
3076-
if (copyCtor) {
3076+
if (copyCtor && !decl->isAnonymousStructOrUnion()) {
30773077
clangSema.DefineImplicitCopyConstructor(clang::SourceLocation(),
30783078
copyCtor);
30793079
}
3080-
if (moveCtor) {
3080+
if (moveCtor && !decl->isAnonymousStructOrUnion()) {
30813081
clangSema.DefineImplicitMoveConstructor(clang::SourceLocation(),
30823082
moveCtor);
30833083
}
@@ -4607,6 +4607,10 @@ namespace {
46074607
// FIXME: Temporarily unreachable because of check above.
46084608
markAsVariant(result, *correctSwiftName);
46094609

4610+
if (decl->isAnonymousStructOrUnion())
4611+
Impl.markUnavailable(
4612+
result, "refer to the members of the anonymous type instead");
4613+
46104614
return result;
46114615
}
46124616

lib/IRGen/GenMeta.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6936,7 +6936,13 @@ namespace {
69366936
}
69376937

69386938
void addValueWitnessTable() {
6939-
auto vwtPointer = emitValueWitnessTable(/*relative*/ false).getValue();
6939+
llvm::Constant* vwtPointer = nullptr;
6940+
if (auto cd = Target->getClangDecl())
6941+
if (auto rd = dyn_cast<clang::RecordDecl>(cd))
6942+
if (rd->isAnonymousStructOrUnion())
6943+
vwtPointer = llvm::Constant::getNullValue(IGM.WitnessTablePtrTy);
6944+
if (!vwtPointer)
6945+
vwtPointer = emitValueWitnessTable(/*relative*/ false).getValue();
69406946
B.addSignedPointer(vwtPointer,
69416947
IGM.getOptions().PointerAuth.ValueWitnessTable,
69426948
PointerAuthEntity());

lib/IRGen/StructLayout.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -590,10 +590,17 @@ unsigned irgen::getNumFields(const NominalTypeDecl *target) {
590590
}
591591

592592
bool irgen::isExportableField(Field field) {
593-
if (field.getKind() == Field::Kind::Var &&
594-
field.getVarDecl()->getClangDecl() &&
595-
field.getVarDecl()->getFormalAccess() == AccessLevel::Private)
596-
return false;
593+
if (field.getKind() == Field::Kind::Var) {
594+
if (field.getVarDecl()->getClangDecl() &&
595+
field.getVarDecl()->getFormalAccess() == AccessLevel::Private)
596+
return false;
597+
// We should not be able to refer to anonymous types.
598+
if (const auto *vd = dyn_cast_or_null<clang::ValueDecl>(
599+
field.getVarDecl()->getClangDecl()))
600+
if (const auto *rd = vd->getType()->getAsRecordDecl())
601+
if (rd->isAnonymousStructOrUnion())
602+
return false;
603+
}
597604
// All other fields are exportable
598605
return true;
599606
}

test/Interop/Cxx/class/Inputs/simple-structs.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ struct HasPublicFieldsOnly {
1717
HasPublicFieldsOnly(int i1, int i2) : publ1(i1), publ2(i2) {}
1818
};
1919

20+
struct HasAnonymousType {
21+
HasAnonymousType(int a, int b, int c) : a(a), b(b), c(c) {}
22+
23+
struct {
24+
int a, b;
25+
};
26+
int c;
27+
};
28+
2029
struct HasPrivatePublicProtectedFields {
2130
private:
2231
int priv1;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -swift-version 6 -cxx-interoperability-mode=upcoming-swift
2+
3+
// CHECK: Foobar
4+
5+
import SimpleStructs
6+
7+
let s = HasAnonymousType(1, 2, 3)
8+
let _ = s.__Anonymous_field0 // expected-error {{'__Anonymous_field0' is unavailable: refer to the members of the anonymous type instead}}
9+
// Referring to the members of the anonymous type directly.
10+
let _ = s.a
11+
let _ = s.b
12+
let _ = s.c

test/Interop/Cxx/class/move-only/Inputs/move-only-cxx-value-type.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,16 @@ struct NonCopyableHolderDerivedDerived: NonCopyableHolderDerived {
5656
inline NonCopyable *getNonCopyablePtr() { return nullptr; }
5757
inline NonCopyableDerived *getNonCopyableDerivedPtr() { return nullptr; }
5858

59+
template <typename T>
60+
struct FieldInAnonStruct {
61+
FieldInAnonStruct() : field(5) {}
62+
FieldInAnonStruct(const FieldInAnonStruct &) = delete;
63+
FieldInAnonStruct(FieldInAnonStruct &&) = default;
64+
struct {
65+
T field;
66+
};
67+
};
68+
69+
using FieldInAnonStructNC = FieldInAnonStruct<NonCopyable>;
70+
5971
#endif // TEST_INTEROP_CXX_CLASS_MOVE_ONLY_VT_H

test/Interop/Cxx/class/move-only/move-only-cxx-value-type.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,8 @@ MoveOnlyCxxValueType.test("Test move only field access in derived holder") {
7676
}
7777
#endif
7878

79+
MoveOnlyCxxValueType.test("Test move only field in anonymous struct") {
80+
let a = FieldInAnonStructNC()
81+
let b = a
82+
}
7983
runAllTests()

test/Interop/Cxx/class/print-simple-structs.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ func printCxxStructNested() {
2424
print(s)
2525
}
2626

27+
func printCxxStructWithAnonType() {
28+
let s = HasAnonymousType(1, 2, 3)
29+
print(s)
30+
}
31+
2732
printCxxStructPrivateFields()
2833
// CHECK: HasPrivateFieldsOnly()
2934

@@ -35,3 +40,6 @@ printCxxStructPrivatePublicProtectedFields()
3540

3641
printCxxStructNested()
3742
// CHECK: Outer(publStruct: {{.*}}.HasPrivatePublicProtectedFields(publ1: 8, publ2: 12))
43+
44+
printCxxStructWithAnonType()
45+
// CHECK: HasAnonymousType(c: 3)

0 commit comments

Comments
 (0)