Skip to content

Commit 1cde254

Browse files
author
Gabor Horvath
committed
[cxx-interop] Restrict the uses of anonymous types
Make sure they are excluded from the reflection metadata (although in the future we want to make sure indirect fields are included). Make sure the users cannot refer to the anonymous field, only its members.
1 parent b72ef8e commit 1cde254

File tree

5 files changed

+44
-4
lines changed

5 files changed

+44
-4
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4546,6 +4546,10 @@ namespace {
45464546
// FIXME: Temporarily unreachable because of check above.
45474547
markAsVariant(result, *correctSwiftName);
45484548

4549+
if (decl->isAnonymousStructOrUnion())
4550+
Impl.markUnavailable(
4551+
result, "refer to the members of the anonymous type instead");
4552+
45494553
return result;
45504554
}
45514555

lib/IRGen/StructLayout.cpp

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

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

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/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)