Skip to content

Commit 2b37471

Browse files
authored
[API notes] Allow SwiftConformsTo on Typedefs
SwiftConformsTo specifies an additional conformance that should be applied on import. Allow this on typedefs, because those can be imported as wrapper types.
1 parent a02444f commit 2b37471

File tree

11 files changed

+58
-31
lines changed

11 files changed

+58
-31
lines changed

clang/include/clang/APINotes/Types.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ class CommonTypeInfo : public CommonEntityInfo {
141141
/// The NS error domain for this type.
142142
std::optional<std::string> NSErrorDomain;
143143

144+
/// The Swift protocol that this type should be automatically conformed to.
145+
std::optional<std::string> SwiftConformance;
146+
144147
public:
145148
CommonTypeInfo() {}
146149

@@ -165,6 +168,14 @@ class CommonTypeInfo : public CommonEntityInfo {
165168
: std::nullopt;
166169
}
167170

171+
std::optional<std::string> getSwiftConformance() const {
172+
return SwiftConformance;
173+
}
174+
175+
void setSwiftConformance(std::optional<std::string> conformance) {
176+
SwiftConformance = conformance;
177+
}
178+
168179
friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &);
169180

170181
CommonTypeInfo &operator|=(const CommonTypeInfo &RHS) {
@@ -175,6 +186,8 @@ class CommonTypeInfo : public CommonEntityInfo {
175186
setSwiftBridge(RHS.getSwiftBridge());
176187
if (!NSErrorDomain)
177188
setNSErrorDomain(RHS.getNSErrorDomain());
189+
if (SwiftConformance)
190+
setSwiftConformance(RHS.getSwiftConformance());
178191

179192
return *this;
180193
}
@@ -185,7 +198,8 @@ class CommonTypeInfo : public CommonEntityInfo {
185198
inline bool operator==(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
186199
return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
187200
LHS.SwiftBridge == RHS.SwiftBridge &&
188-
LHS.NSErrorDomain == RHS.NSErrorDomain;
201+
LHS.NSErrorDomain == RHS.NSErrorDomain &&
202+
LHS.SwiftConformance == RHS.SwiftConformance;
189203
}
190204

191205
inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
@@ -739,9 +753,6 @@ class TagInfo : public CommonTypeInfo {
739753
std::optional<std::string> SwiftReleaseOp;
740754
std::optional<std::string> SwiftDefaultOwnership;
741755

742-
/// The Swift protocol that this type should be automatically conformed to.
743-
std::optional<std::string> SwiftConformance;
744-
745756
std::optional<EnumExtensibilityKind> EnumExtensibility;
746757

747758
TagInfo()
@@ -790,9 +801,6 @@ class TagInfo : public CommonTypeInfo {
790801
if (!SwiftDefaultOwnership)
791802
SwiftDefaultOwnership = RHS.SwiftDefaultOwnership;
792803

793-
if (!SwiftConformance)
794-
SwiftConformance = RHS.SwiftConformance;
795-
796804
if (!HasFlagEnum)
797805
setFlagEnum(RHS.isFlagEnum());
798806

@@ -819,7 +827,6 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
819827
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
820828
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
821829
LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership &&
822-
LHS.SwiftConformance == RHS.SwiftConformance &&
823830
LHS.isFlagEnum() == RHS.isFlagEnum() &&
824831
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
825832
LHS.isSwiftEscapable() == RHS.isSwiftEscapable() &&

clang/lib/APINotes/APINotesFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0;
2424
/// API notes file minor version number.
2525
///
2626
/// When the format changes IN ANY WAY, this number should be incremented.
27-
const uint16_t VERSION_MINOR = 35; // SwiftDefaultOwnership
27+
const uint16_t VERSION_MINOR = 36; // Typedef SwiftConformsTo
2828

2929
const uint8_t kSwiftConforms = 1;
3030
const uint8_t kSwiftDoesNotConform = 2;

clang/lib/APINotes/APINotesReader.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
134134
reinterpret_cast<const char *>(Data), ErrorDomainLength - 1)));
135135
Data += ErrorDomainLength - 1;
136136
}
137+
138+
if (unsigned ConformanceLength =
139+
endian::readNext<uint16_t, llvm::endianness::little>(Data)) {
140+
Info.setSwiftConformance(std::string(reinterpret_cast<const char *>(Data),
141+
ConformanceLength - 1));
142+
Data += ConformanceLength - 1;
143+
}
137144
}
138145

139146
/// Used to deserialize the on-disk identifier table.
@@ -629,12 +636,6 @@ class TagTableInfo
629636
reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
630637
Data += DefaultOwnershipLength - 1;
631638
}
632-
if (unsigned ConformanceLength =
633-
endian::readNext<uint16_t, llvm::endianness::little>(Data)) {
634-
Info.SwiftConformance = std::string(reinterpret_cast<const char *>(Data),
635-
ConformanceLength - 1);
636-
Data += ConformanceLength - 1;
637-
}
638639

639640
ReadCommonTypeInfo(Data, Info);
640641
return Info;

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,8 @@ unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) {
536536
// in on-disk hash tables.
537537
unsigned getCommonTypeInfoSize(const CommonTypeInfo &CTI) {
538538
return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
539-
(CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) +
539+
(CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
540+
(CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
540541
getCommonEntityInfoSize(CTI);
541542
}
542543

@@ -557,6 +558,12 @@ void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
557558
} else {
558559
writer.write<uint16_t>(0);
559560
}
561+
if (auto conformance = CTI.getSwiftConformance()) {
562+
writer.write<uint16_t>(conformance->size() + 1);
563+
OS.write(conformance->c_str(), conformance->size());
564+
} else {
565+
writer.write<uint16_t>(0);
566+
}
560567
}
561568

562569
/// Used to serialize the on-disk Objective-C property table.
@@ -1274,7 +1281,6 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
12741281
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
12751282
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
12761283
2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
1277-
2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) +
12781284
3 + getCommonTypeInfoSize(TI);
12791285
// clang-format on
12801286
}
@@ -1328,12 +1334,6 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13281334
} else {
13291335
writer.write<uint16_t>(0);
13301336
}
1331-
if (auto Conformance = TI.SwiftConformance) {
1332-
writer.write<uint16_t>(Conformance->size() + 1);
1333-
OS.write(Conformance->c_str(), Conformance->size());
1334-
} else {
1335-
writer.write<uint16_t>(0);
1336-
}
13371337

13381338
emitCommonTypeInfo(OS, TI);
13391339
}

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ struct Class {
251251
std::optional<StringRef> NSErrorDomain;
252252
std::optional<bool> SwiftImportAsNonGeneric;
253253
std::optional<bool> SwiftObjCMembers;
254+
std::optional<std::string> SwiftConformance;
254255
MethodsSeq Methods;
255256
PropertiesSeq Properties;
256257
};
@@ -275,6 +276,7 @@ template <> struct MappingTraits<Class> {
275276
IO.mapOptional("NSErrorDomain", C.NSErrorDomain);
276277
IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric);
277278
IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers);
279+
IO.mapOptional("SwiftConformsTo", C.SwiftConformance);
278280
IO.mapOptional("Methods", C.Methods);
279281
IO.mapOptional("Properties", C.Properties);
280282
}
@@ -525,6 +527,7 @@ struct Typedef {
525527
std::optional<StringRef> SwiftBridge;
526528
std::optional<StringRef> NSErrorDomain;
527529
std::optional<SwiftNewTypeKind> SwiftType;
530+
std::optional<std::string> SwiftConformance;
528531
};
529532

530533
typedef std::vector<Typedef> TypedefsSeq;
@@ -553,6 +556,7 @@ template <> struct MappingTraits<Typedef> {
553556
IO.mapOptional("SwiftBridge", T.SwiftBridge);
554557
IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
555558
IO.mapOptional("SwiftWrapper", T.SwiftType);
559+
IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
556560
}
557561
};
558562
} // namespace yaml
@@ -802,6 +806,8 @@ class YAMLConverter {
802806
if (Common.SwiftBridge)
803807
Info.setSwiftBridge(std::string(*Common.SwiftBridge));
804808
Info.setNSErrorDomain(Common.NSErrorDomain);
809+
if (auto conformance = Common.SwiftConformance)
810+
Info.setSwiftConformance(conformance);
805811
}
806812

807813
// Translate from Method into ObjCMethodInfo and write it out.
@@ -990,8 +996,6 @@ class YAMLConverter {
990996
TI.SwiftRetainOp = T.SwiftRetainOp;
991997
if (T.SwiftReleaseOp)
992998
TI.SwiftReleaseOp = T.SwiftReleaseOp;
993-
if (T.SwiftConformance)
994-
TI.SwiftConformance = T.SwiftConformance;
995999
if (T.SwiftDefaultOwnership)
9961000
TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership;
9971001

clang/lib/Sema/SemaAPINotes.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,10 @@ static void ProcessAPINotes(Sema &S, Decl *D,
336336
});
337337
}
338338

339+
if (auto ConformsTo = Info.getSwiftConformance())
340+
D->addAttr(
341+
SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
342+
339343
ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
340344
Metadata);
341345
}
@@ -698,10 +702,6 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
698702
D->addAttr(SwiftAttrAttr::Create(
699703
S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));
700704

701-
if (auto ConformsTo = Info.SwiftConformance)
702-
D->addAttr(
703-
SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
704-
705705
if (auto Copyable = Info.isSwiftCopyable()) {
706706
if (!*Copyable)
707707
D->addAttr(SwiftAttrAttr::Create(S.Context, "~Copyable"));

clang/test/APINotes/Inputs/Frameworks/Simple.framework/Headers/Simple.apinotes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ Classes:
2626
- Name: scalarNewProperty
2727
PropertyKind: Instance
2828
Nullability: Scalar
29+
Typedefs:
30+
- Name: MyTypedef
31+
SwiftConformsTo: Swift.Equatable

clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@ Functions:
3939
SwiftReturnOwnership: unretained
4040
- Name: functionReturningFrt_returns_retained
4141
SwiftReturnOwnership: retained
42+
Typedefs:
43+
- Name: WrappedOptions
44+
SwiftWrapper: struct
45+
SwiftConformsTo: Swift.OptionSet

clang/test/APINotes/Inputs/Headers/SwiftImportAs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ struct OpaqueRefCountedType; // redeclaration
2929

3030
inline void ORCRetain(struct OpaqueRefCountedType *x);
3131
inline void ORCRelease(struct OpaqueRefCountedType *x);
32+
33+
typedef unsigned WrappedOptions;

clang/test/APINotes/swift-import-as.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter methodReturningFrt__ | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT %s
1515
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter methodReturningFrt_returns_unretained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-UNRETAINED %s
1616
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter methodReturningFrt_returns_retained | FileCheck -check-prefix=CHECK-METHOD-RETURNING-FRT-RETAINED %s
17+
// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter WrappedOptions | FileCheck -check-prefix=CHECK-WRAPPED-OPTIONS %s
1718

1819
#include <SwiftImportAs.h>
1920

@@ -51,8 +52,8 @@
5152
// CHECK-OPAQUE-REF-COUNTED-NOT: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:
5253
// CHECK-NON-COPYABLE: Dumping NonCopyableType:
5354
// CHECK-NON-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct NonCopyableType
54-
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"
5555
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "~Copyable"
56+
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"
5657

5758
// CHECK-COPYABLE: Dumping CopyableType:
5859
// CHECK-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct CopyableType
@@ -91,3 +92,8 @@
9192
// CHECK-METHOD-RETURNING-FRT-RETAINED: Dumping ImmortalRefType::methodReturningFrt_returns_retained:
9293
// CHECK-METHOD-RETURNING-FRT-RETAINED: CXXMethodDecl {{.+}} imported in SwiftImportAs methodReturningFrt_returns_retained 'ImmortalRefType *()'
9394
// CHECK-METHOD-RETURNING-FRT-RETAINED: `-SwiftAttrAttr {{.+}} "returns_retained"
95+
96+
// CHECK-WRAPPED-OPTIONS: Dumping WrappedOptions
97+
// CHECK-WRAPPED-OPTIONS: TypedefDecl{{.*}}WrappedOptions 'unsigned int'
98+
// CHECK-WRAPPED-OPTIONS: SwiftNewTypeAttr {{.*}} swift_wrapper NK_Struct
99+
// CHECK-WRAPPED-OPTIONS: SwiftAttrAttr {{.*}} "conforms_to:Swift.OptionSet"

0 commit comments

Comments
 (0)