Skip to content

Commit 3cf7fe3

Browse files
DougGregorAnthonyLatsis
authored andcommitted
[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 (cherry picked from commit 01b28c4)
1 parent 41eba88 commit 3cf7fe3

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) {
@@ -825,9 +839,6 @@ class TagInfo : public CommonTypeInfo {
825839
std::optional<std::string> SwiftReleaseOp;
826840
std::optional<std::string> SwiftDefaultOwnership;
827841

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

833844
TagInfo()
@@ -876,9 +887,6 @@ class TagInfo : public CommonTypeInfo {
876887
if (!SwiftDefaultOwnership)
877888
SwiftDefaultOwnership = RHS.SwiftDefaultOwnership;
878889

879-
if (!SwiftConformance)
880-
SwiftConformance = RHS.SwiftConformance;
881-
882890
if (!HasFlagEnum)
883891
setFlagEnum(RHS.isFlagEnum());
884892

@@ -905,7 +913,6 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
905913
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
906914
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
907915
LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership &&
908-
LHS.SwiftConformance == RHS.SwiftConformance &&
909916
LHS.isFlagEnum() == RHS.isFlagEnum() &&
910917
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
911918
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 = 36; // TO_UPSTREAM(BoundsSafety)
27+
const uint16_t VERSION_MINOR = 37; // 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.
@@ -668,12 +675,6 @@ class TagTableInfo
668675
reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
669676
Data += DefaultOwnershipLength - 1;
670677
}
671-
if (unsigned ConformanceLength =
672-
endian::readNext<uint16_t, llvm::endianness::little>(Data)) {
673-
Info.SwiftConformance = std::string(reinterpret_cast<const char *>(Data),
674-
ConformanceLength - 1);
675-
Data += ConformanceLength - 1;
676-
}
677678

678679
ReadCommonTypeInfo(Data, Info);
679680
return Info;

clang/lib/APINotes/APINotesWriter.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,8 @@ unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) {
543543
// in on-disk hash tables.
544544
unsigned getCommonTypeInfoSize(const CommonTypeInfo &CTI) {
545545
return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
546-
(CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) +
546+
(CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) + 2 +
547+
(CTI.getSwiftConformance() ? CTI.getSwiftConformance()->size() : 0) +
547548
getCommonEntityInfoSize(CTI);
548549
}
549550

@@ -564,6 +565,12 @@ void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
564565
} else {
565566
writer.write<uint16_t>(0);
566567
}
568+
if (auto conformance = CTI.getSwiftConformance()) {
569+
writer.write<uint16_t>(conformance->size() + 1);
570+
OS.write(conformance->c_str(), conformance->size());
571+
} else {
572+
writer.write<uint16_t>(0);
573+
}
567574
}
568575

569576
/// Used to serialize the on-disk Objective-C property table.
@@ -1331,7 +1338,6 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13311338
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
13321339
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
13331340
2 + (TI.SwiftDefaultOwnership ? TI.SwiftDefaultOwnership->size() : 0) +
1334-
2 + (TI.SwiftConformance ? TI.SwiftConformance->size() : 0) +
13351341
3 + getCommonTypeInfoSize(TI);
13361342
// clang-format on
13371343
}
@@ -1385,12 +1391,6 @@ class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
13851391
} else {
13861392
writer.write<uint16_t>(0);
13871393
}
1388-
if (auto Conformance = TI.SwiftConformance) {
1389-
writer.write<uint16_t>(Conformance->size() + 1);
1390-
OS.write(Conformance->c_str(), Conformance->size());
1391-
} else {
1392-
writer.write<uint16_t>(0);
1393-
}
13941394

13951395
emitCommonTypeInfo(OS, TI);
13961396
}

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
}
@@ -693,6 +695,7 @@ struct Typedef {
693695
std::optional<StringRef> SwiftBridge;
694696
std::optional<StringRef> NSErrorDomain;
695697
std::optional<SwiftNewTypeKind> SwiftType;
698+
std::optional<std::string> SwiftConformance;
696699
};
697700

698701
typedef std::vector<Typedef> TypedefsSeq;
@@ -721,6 +724,7 @@ template <> struct MappingTraits<Typedef> {
721724
IO.mapOptional("SwiftBridge", T.SwiftBridge);
722725
IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
723726
IO.mapOptional("SwiftWrapper", T.SwiftType);
727+
IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
724728
}
725729
};
726730
} // namespace yaml
@@ -979,6 +983,8 @@ class YAMLConverter {
979983
if (Common.SwiftBridge)
980984
Info.setSwiftBridge(std::string(*Common.SwiftBridge));
981985
Info.setNSErrorDomain(Common.NSErrorDomain);
986+
if (auto conformance = Common.SwiftConformance)
987+
Info.setSwiftConformance(conformance);
982988
}
983989

984990
// Translate from Method into ObjCMethodInfo and write it out.
@@ -1176,8 +1182,6 @@ class YAMLConverter {
11761182
TI.SwiftRetainOp = T.SwiftRetainOp;
11771183
if (T.SwiftReleaseOp)
11781184
TI.SwiftReleaseOp = T.SwiftReleaseOp;
1179-
if (T.SwiftConformance)
1180-
TI.SwiftConformance = T.SwiftConformance;
11811185
if (T.SwiftDefaultOwnership)
11821186
TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership;
11831187

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
}
@@ -777,10 +781,6 @@ static void ProcessAPINotes(Sema &S, TagDecl *D, const api_notes::TagInfo &Info,
777781
D->addAttr(SwiftAttrAttr::Create(
778782
S.Context, "returned_as_" + DefaultOwnership.value() + "_by_default"));
779783

780-
if (auto ConformsTo = Info.SwiftConformance)
781-
D->addAttr(
782-
SwiftAttrAttr::Create(S.Context, "conforms_to:" + ConformsTo.value()));
783-
784784
if (auto Copyable = Info.isSwiftCopyable()) {
785785
if (!*Copyable)
786786
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
@@ -51,8 +51,8 @@
5151
// CHECK-OPAQUE-REF-COUNTED-NOT: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:
5252
// CHECK-NON-COPYABLE: Dumping NonCopyableType:
5353
// CHECK-NON-COPYABLE-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct NonCopyableType
54-
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"
5554
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "~Copyable"
55+
// CHECK-NON-COPYABLE: SwiftAttrAttr {{.+}} <<invalid sloc>> "conforms_to:MySwiftModule.MySwiftNonCopyableProtocol"
5656

5757
// CHECK-COPYABLE: Dumping CopyableType:
5858
// 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)