Skip to content

Commit 01b28c4

Browse files
committed
[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. Clang side of rdar://156290361
1 parent 6e2683c commit 01b28c4

File tree

9 files changed

+46
-31
lines changed

9 files changed

+46
-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) {
@@ -824,9 +838,6 @@ class TagInfo : public CommonTypeInfo {
824838
std::optional<std::string> SwiftRetainOp;
825839
std::optional<std::string> SwiftReleaseOp;
826840

827-
/// The Swift protocol that this type should be automatically conformed to.
828-
std::optional<std::string> SwiftConformance;
829-
830841
std::optional<EnumExtensibilityKind> EnumExtensibility;
831842

832843
TagInfo()
@@ -873,9 +884,6 @@ class TagInfo : public CommonTypeInfo {
873884
if (!SwiftReleaseOp)
874885
SwiftReleaseOp = RHS.SwiftReleaseOp;
875886

876-
if (!SwiftConformance)
877-
SwiftConformance = RHS.SwiftConformance;
878-
879887
if (!HasFlagEnum)
880888
setFlagEnum(RHS.isFlagEnum());
881889

@@ -901,7 +909,6 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
901909
LHS.SwiftImportAs == RHS.SwiftImportAs &&
902910
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
903911
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
904-
LHS.SwiftConformance == RHS.SwiftConformance &&
905912
LHS.isFlagEnum() == RHS.isFlagEnum() &&
906913
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
907914
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; // BoundsSafety
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
@@ -136,6 +136,13 @@ void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
136136
reinterpret_cast<const char *>(Data), ErrorDomainLength - 1)));
137137
Data += ErrorDomainLength - 1;
138138
}
139+
140+
if (unsigned ConformanceLength =
141+
endian::readNext<uint16_t, llvm::endianness::little>(Data)) {
142+
Info.setSwiftConformance(std::string(reinterpret_cast<const char *>(Data),
143+
ConformanceLength - 1));
144+
Data += ConformanceLength - 1;
145+
}
139146
}
140147

141148
/// Used to deserialize the on-disk identifier table.
@@ -663,12 +670,6 @@ class TagTableInfo
663670
ReleaseOpLength - 1);
664671
Data += ReleaseOpLength - 1;
665672
}
666-
if (unsigned ConformanceLength =
667-
endian::readNext<uint16_t, llvm::endianness::little>(Data)) {
668-
Info.SwiftConformance = std::string(reinterpret_cast<const char *>(Data),
669-
ConformanceLength - 1);
670-
Data += ConformanceLength - 1;
671-
}
672673

673674
ReadCommonTypeInfo(Data, Info);
674675
return Info;

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,8 @@ unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) {
553553
// in on-disk hash tables.
554554
unsigned getCommonTypeInfoSize(const CommonTypeInfo &CTI) {
555555
return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
556-
(CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) +
556+
(CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
557+
(CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
557558
getCommonEntityInfoSize(CTI);
558559
}
559560

@@ -574,6 +575,12 @@ void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
574575
} else {
575576
writer.write<uint16_t>(0);
576577
}
578+
if (auto conformance = CTI.getSwiftConformance()) {
579+
writer.write<uint16_t>(conformance->size() + 1);
580+
OS.write(conformance->c_str(), conformance->size());
581+
} else {
582+
writer.write<uint16_t>(0);
583+
}
577584
}
578585

579586
/// Used to serialize the on-disk Objective-C property table.
@@ -1341,7 +1348,6 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13411348
return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
13421349
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
13431350
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1344-
2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) +
13451351
3 + getCommonTypeInfoSize(TI);
13461352
// clang-format on
13471353
}
@@ -1389,12 +1395,6 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13891395
} else {
13901396
writer.write<uint16_t>(0);
13911397
}
1392-
if (auto Conformance = TI.SwiftConformance) {
1393-
writer.write<uint16_t>(Conformance->size() + 1);
1394-
OS.write(Conformance->c_str(), Conformance->size());
1395-
} else {
1396-
writer.write<uint16_t>(0);
1397-
}
13981398

13991399
emitCommonTypeInfo(OS, TI);
14001400
}

clang/lib/APINotes/APINotesYAMLCompiler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ struct Class {
413413
std::optional<StringRef> NSErrorDomain;
414414
std::optional<bool> SwiftImportAsNonGeneric;
415415
std::optional<bool> SwiftObjCMembers;
416+
std::optional<std::string> SwiftConformance;
416417
MethodsSeq Methods;
417418
PropertiesSeq Properties;
418419
};
@@ -437,6 +438,7 @@ template <> struct MappingTraits<Class> {
437438
IO.mapOptional("NSErrorDomain", C.NSErrorDomain);
438439
IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric);
439440
IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers);
441+
IO.mapOptional("SwiftConformsTo", C.SwiftConformance);
440442
IO.mapOptional("Methods", C.Methods);
441443
IO.mapOptional("Properties", C.Properties);
442444
}
@@ -691,6 +693,7 @@ struct Typedef {
691693
std::optional<StringRef> SwiftBridge;
692694
std::optional<StringRef> NSErrorDomain;
693695
std::optional<SwiftNewTypeKind> SwiftType;
696+
std::optional<std::string> SwiftConformance;
694697
};
695698

696699
typedef std::vector<Typedef> TypedefsSeq;
@@ -719,6 +722,7 @@ template <> struct MappingTraits<Typedef> {
719722
IO.mapOptional("SwiftBridge", T.SwiftBridge);
720723
IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
721724
IO.mapOptional("SwiftWrapper", T.SwiftType);
725+
IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
722726
}
723727
};
724728
} // namespace yaml
@@ -977,6 +981,8 @@ class YAMLConverter {
977981
if (Common.SwiftBridge)
978982
Info.setSwiftBridge(std::string(*Common.SwiftBridge));
979983
Info.setNSErrorDomain(Common.NSErrorDomain);
984+
if (auto conformance = Common.SwiftConformance)
985+
Info.setSwiftConformance(conformance);
980986
}
981987

982988
// Translate from Method into ObjCMethodInfo and write it out.
@@ -1174,8 +1180,6 @@ class YAMLConverter {
11741180
TI.SwiftRetainOp = T.SwiftRetainOp;
11751181
if (T.SwiftReleaseOp)
11761182
TI.SwiftReleaseOp = T.SwiftReleaseOp;
1177-
if (T.SwiftConformance)
1178-
TI.SwiftConformance = T.SwiftConformance;
11791183

11801184
if (T.SwiftCopyable)
11811185
TI.setSwiftCopyable(T.SwiftCopyable);

clang/lib/Sema/SemaAPINotes.cpp

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

341+
if (auto ConformsTo = Info.getSwiftConformance())
342+
D->addAttr(
343+
SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
344+
341345
ProcessAPINotes(S, D, static_cast<const api_notes::CommonEntityInfo &>(Info),
342346
Metadata);
343347
}
@@ -776,10 +780,6 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
776780
D->addAttr(
777781
SwiftAttrAttr::Create(S.Context, "release:" + ReleaseOp.value()));
778782

779-
if (auto ConformsTo = Info.SwiftConformance)
780-
D->addAttr(
781-
SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
782-
783783
if (auto Copyable = Info.isSwiftCopyable()) {
784784
if (!*Copyable)
785785
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/swift-import-as.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
// CHECK-OPAQUE-REF-COUNTED-NOT: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:
4444
// CHECK-NON-COPYABLE: Dumping NonCopyableType:
4545
// CHECK-NON-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct NonCopyableType
46-
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"
4746
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "~Copyable"
47+
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"
4848

4949
// CHECK-COPYABLE: Dumping CopyableType:
5050
// CHECK-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct CopyableType

clang/test/APINotes/yaml-roundtrip.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ CHECK-NEXT: 25c26
2424
CHECK-NEXT: < Nullability: S
2525
CHECK-NEXT: ---
2626
CHECK-NEXT: > Nullability: Unspecified
27-
CHECK-NEXT: 28c29,30
27+
CHECK-NEXT: 28c29
2828
CHECK-NEXT: < Nullability: Scalar
2929
CHECK-NEXT: ---
3030
CHECK-NEXT: > Nullability: Unspecified

0 commit comments

Comments
 (0)