@@ -349,11 +349,15 @@ void objc::checkCategories() {
349
349
namespace {
350
350
351
351
class ObjcCategoryMerger {
352
+ // In which language was a particular construct originally defined
353
+ enum SourceLanguage { SourceObjC, SourceSwift, SourceUnknown };
354
+
352
355
// Information about an input category
353
356
struct InfoInputCategory {
354
357
ConcatInputSection *catListIsec;
355
358
ConcatInputSection *catBodyIsec;
356
359
uint32_t offCatListIsec = 0 ;
360
+ SourceLanguage sourceLanguage = SourceUnknown;
357
361
358
362
bool wasMerged = false ;
359
363
};
@@ -413,7 +417,9 @@ class ObjcCategoryMerger {
413
417
// Merged names of containers. Ex: base|firstCategory|secondCategory|...
414
418
std::string mergedContainerName;
415
419
std::string baseClassName;
416
- Symbol *baseClass = nullptr ;
420
+ const Symbol *baseClass = nullptr ;
421
+ SourceLanguage baseClassSourceLanguage = SourceUnknown;
422
+
417
423
CategoryLayout &catLayout;
418
424
419
425
// In case we generate new data, mark the new data as belonging to this file
@@ -456,10 +462,12 @@ class ObjcCategoryMerger {
456
462
ClassExtensionInfo &extInfo);
457
463
458
464
void parseProtocolListInfo (const ConcatInputSection *isec, uint32_t secOffset,
459
- PointerListInfo &ptrList);
465
+ PointerListInfo &ptrList,
466
+ SourceLanguage sourceLang);
460
467
461
468
PointerListInfo parseProtocolListInfo (const ConcatInputSection *isec,
462
- uint32_t secOffset);
469
+ uint32_t secOffset,
470
+ SourceLanguage sourceLang);
463
471
464
472
void parsePointerListInfo (const ConcatInputSection *isec, uint32_t secOffset,
465
473
PointerListInfo &ptrList);
@@ -653,9 +661,9 @@ void ObjcCategoryMerger::collectCategoryWriterInfoFromCategory(
653
661
// Parse a protocol list that might be linked to ConcatInputSection at a given
654
662
// offset. The format of the protocol list is different than other lists (prop
655
663
// lists, method lists) so we need to parse it differently
656
- void ObjcCategoryMerger::parseProtocolListInfo (const ConcatInputSection *isec,
657
- uint32_t secOffset,
658
- PointerListInfo &ptrList) {
664
+ void ObjcCategoryMerger::parseProtocolListInfo (
665
+ const ConcatInputSection *isec, uint32_t secOffset,
666
+ PointerListInfo &ptrList, [[maybe_unused]] SourceLanguage sourceLang ) {
659
667
assert ((isec && (secOffset + target->wordSize <= isec->data .size ())) &&
660
668
" Tried to read pointer list beyond protocol section end" );
661
669
@@ -684,8 +692,10 @@ void ObjcCategoryMerger::parseProtocolListInfo(const ConcatInputSection *isec,
684
692
[[maybe_unused]] uint32_t expectedListSizeSwift =
685
693
expectedListSize - target->wordSize ;
686
694
687
- assert ((expectedListSize == ptrListSym->isec ()->data .size () ||
688
- expectedListSizeSwift == ptrListSym->isec ()->data .size ()) &&
695
+ assert (((expectedListSize == ptrListSym->isec ()->data .size () &&
696
+ sourceLang == SourceObjC) ||
697
+ (expectedListSizeSwift == ptrListSym->isec ()->data .size () &&
698
+ sourceLang == SourceSwift)) &&
689
699
" Protocol list does not match expected size" );
690
700
691
701
uint32_t off = protocolListHeaderLayout.totalSize ;
@@ -708,9 +718,10 @@ void ObjcCategoryMerger::parseProtocolListInfo(const ConcatInputSection *isec,
708
718
// Parse a protocol list and return the PointerListInfo for it
709
719
ObjcCategoryMerger::PointerListInfo
710
720
ObjcCategoryMerger::parseProtocolListInfo (const ConcatInputSection *isec,
711
- uint32_t secOffset) {
721
+ uint32_t secOffset,
722
+ SourceLanguage sourceLang) {
712
723
PointerListInfo ptrList;
713
- parseProtocolListInfo (isec, secOffset, ptrList);
724
+ parseProtocolListInfo (isec, secOffset, ptrList, sourceLang );
714
725
return ptrList;
715
726
}
716
727
@@ -772,10 +783,11 @@ void ObjcCategoryMerger::parseCatInfoToExtInfo(const InfoInputCategory &catInfo,
772
783
assert (catNameReloc && " Category does not have a reloc at 'nameOffset'" );
773
784
774
785
// is this the first category we are parsing?
775
- if (extInfo.mergedContainerName .empty ())
786
+ if (extInfo.mergedContainerName .empty ()) {
787
+ auto *theFile = catInfo.catBodyIsec ->getFile ();
776
788
extInfo.objFileForMergeData =
777
789
dyn_cast_or_null<ObjFile>(catInfo.catBodyIsec ->getFile ());
778
- else
790
+ } else
779
791
extInfo.mergedContainerName += " |" ;
780
792
781
793
assert (extInfo.objFileForMergeData &&
@@ -809,7 +821,7 @@ void ObjcCategoryMerger::parseCatInfoToExtInfo(const InfoInputCategory &catInfo,
809
821
extInfo.classMethods );
810
822
811
823
parseProtocolListInfo (catInfo.catBodyIsec , catLayout.protocolsOffset ,
812
- extInfo.protocols );
824
+ extInfo.protocols , catInfo. sourceLanguage );
813
825
814
826
parsePointerListInfo (catInfo.catBodyIsec , catLayout.instancePropsOffset ,
815
827
extInfo.instanceProps );
@@ -1151,22 +1163,26 @@ void ObjcCategoryMerger::collectAndValidateCategoriesData() {
1151
1163
if (nlCategories.count (categorySym))
1152
1164
continue ;
1153
1165
1154
- assert (categorySym->getName ().starts_with (objc::symbol_names::category) ||
1155
- categorySym->getName ().starts_with (
1156
- objc::symbol_names::swift_objc_category));
1157
-
1158
1166
auto *catBodyIsec = dyn_cast<ConcatInputSection>(categorySym->isec ());
1159
1167
assert (catBodyIsec &&
1160
1168
" Category data section is not an ConcatInputSection" );
1161
1169
1170
+ InfoInputCategory catInputInfo{catListCisec, catBodyIsec, off};
1171
+ if (categorySym->getName ().starts_with (objc::symbol_names::category))
1172
+ catInputInfo.sourceLanguage = SourceLanguage::SourceObjC;
1173
+ else if (categorySym->getName ().starts_with (
1174
+ objc::symbol_names::swift_objc_category))
1175
+ catInputInfo.sourceLanguage = SourceLanguage::SourceSwift;
1176
+ else
1177
+ llvm_unreachable (" Unexpected category symbol name" );
1178
+
1162
1179
// Check that the category has a reloc at 'klassOffset' (which is
1163
1180
// a pointer to the class symbol)
1164
1181
1165
1182
Symbol *classSym =
1166
1183
tryGetSymbolAtIsecOffset (catBodyIsec, catLayout.klassOffset );
1167
1184
assert (classSym && " Category does not have a valid base class" );
1168
1185
1169
- InfoInputCategory catInputInfo{catListCisec, catBodyIsec, off};
1170
1186
categoryMap[classSym].push_back (catInputInfo);
1171
1187
1172
1188
collectCategoryWriterInfoFromCategory (catInputInfo);
@@ -1366,6 +1382,16 @@ void ObjcCategoryMerger::mergeCategoriesIntoBaseClass(
1366
1382
1367
1383
// Collect all the info from the categories
1368
1384
ClassExtensionInfo extInfo (catLayout);
1385
+ extInfo.baseClass = baseClass;
1386
+
1387
+ if (baseClass->getName ().starts_with (objc::symbol_names::klass))
1388
+ extInfo.baseClassSourceLanguage = SourceLanguage::SourceObjC;
1389
+ else if (baseClass->getName ().starts_with (
1390
+ objc::symbol_names::swift_objc_klass))
1391
+ extInfo.baseClassSourceLanguage = SourceLanguage::SourceSwift;
1392
+ else
1393
+ llvm_unreachable (" Unexpected base class symbol name" );
1394
+
1369
1395
for (auto &catInfo : categories) {
1370
1396
parseCatInfoToExtInfo (catInfo, extInfo);
1371
1397
}
@@ -1382,14 +1408,15 @@ void ObjcCategoryMerger::mergeCategoriesIntoBaseClass(
1382
1408
// Protocol lists are a special case - the same protocol list is in classRo
1383
1409
// and metaRo, so we only need to parse it once
1384
1410
parseProtocolListInfo (classIsec, roClassLayout.baseProtocolsOffset ,
1385
- extInfo.protocols );
1411
+ extInfo.protocols , extInfo. baseClassSourceLanguage );
1386
1412
1387
1413
// Check that the classRo and metaRo protocol lists are identical
1388
- assert (
1389
- parseProtocolListInfo (classIsec, roClassLayout.baseProtocolsOffset ) ==
1390
- parseProtocolListInfo (metaIsec, roClassLayout.baseProtocolsOffset ) &&
1391
- " Category merger expects classRo and metaRo to have the same protocol "
1392
- " list" );
1414
+ assert (parseProtocolListInfo (classIsec, roClassLayout.baseProtocolsOffset ,
1415
+ extInfo.baseClassSourceLanguage ) ==
1416
+ parseProtocolListInfo (metaIsec, roClassLayout.baseProtocolsOffset ,
1417
+ extInfo.baseClassSourceLanguage ) &&
1418
+ " Category merger expects classRo and metaRo to have the same protocol "
1419
+ " list" );
1393
1420
1394
1421
parsePointerListInfo (metaIsec, roClassLayout.baseMethodsOffset ,
1395
1422
extInfo.classMethods );
0 commit comments