@@ -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 { Unknown, ObjC, Swift };
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 = SourceLanguage::Unknown;
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 = SourceLanguage::Unknown;
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 == SourceLanguage::ObjC) ||
697
+ (expectedListSizeSwift == ptrListSym->isec ()->data .size () &&
698
+ sourceLang == SourceLanguage::Swift)) &&
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
@@ -809,7 +820,7 @@ void ObjcCategoryMerger::parseCatInfoToExtInfo(const InfoInputCategory &catInfo,
809
820
extInfo.classMethods );
810
821
811
822
parseProtocolListInfo (catInfo.catBodyIsec , catLayout.protocolsOffset ,
812
- extInfo.protocols );
823
+ extInfo.protocols , catInfo. sourceLanguage );
813
824
814
825
parsePointerListInfo (catInfo.catBodyIsec , catLayout.instancePropsOffset ,
815
826
extInfo.instanceProps );
@@ -1151,22 +1162,28 @@ void ObjcCategoryMerger::collectAndValidateCategoriesData() {
1151
1162
if (nlCategories.count (categorySym))
1152
1163
continue ;
1153
1164
1154
- assert (categorySym->getName ().starts_with (objc::symbol_names::category) ||
1155
- categorySym->getName ().starts_with (
1156
- objc::symbol_names::swift_objc_category));
1157
-
1158
1165
auto *catBodyIsec = dyn_cast<ConcatInputSection>(categorySym->isec ());
1159
1166
assert (catBodyIsec &&
1160
1167
" Category data section is not an ConcatInputSection" );
1161
1168
1169
+ SourceLanguage eLang = SourceLanguage::Unknown;
1170
+ if (categorySym->getName ().starts_with (objc::symbol_names::category))
1171
+ eLang = SourceLanguage::ObjC;
1172
+ else if (categorySym->getName ().starts_with (
1173
+ objc::symbol_names::swift_objc_category))
1174
+ eLang = SourceLanguage::Swift;
1175
+ else
1176
+ llvm_unreachable (" Unexpected category symbol name" );
1177
+
1178
+ InfoInputCategory catInputInfo{catListCisec, catBodyIsec, off, eLang};
1179
+
1162
1180
// Check that the category has a reloc at 'klassOffset' (which is
1163
1181
// a pointer to the class symbol)
1164
1182
1165
1183
Symbol *classSym =
1166
1184
tryGetSymbolAtIsecOffset (catBodyIsec, catLayout.klassOffset );
1167
1185
assert (classSym && " Category does not have a valid base class" );
1168
1186
1169
- InfoInputCategory catInputInfo{catListCisec, catBodyIsec, off};
1170
1187
categoryMap[classSym].push_back (catInputInfo);
1171
1188
1172
1189
collectCategoryWriterInfoFromCategory (catInputInfo);
@@ -1366,6 +1383,16 @@ void ObjcCategoryMerger::mergeCategoriesIntoBaseClass(
1366
1383
1367
1384
// Collect all the info from the categories
1368
1385
ClassExtensionInfo extInfo (catLayout);
1386
+ extInfo.baseClass = baseClass;
1387
+
1388
+ if (baseClass->getName ().starts_with (objc::symbol_names::klass))
1389
+ extInfo.baseClassSourceLanguage = SourceLanguage::ObjC;
1390
+ else if (baseClass->getName ().starts_with (
1391
+ objc::symbol_names::swift_objc_klass))
1392
+ extInfo.baseClassSourceLanguage = SourceLanguage::Swift;
1393
+ else
1394
+ llvm_unreachable (" Unexpected base class symbol name" );
1395
+
1369
1396
for (auto &catInfo : categories) {
1370
1397
parseCatInfoToExtInfo (catInfo, extInfo);
1371
1398
}
@@ -1382,14 +1409,15 @@ void ObjcCategoryMerger::mergeCategoriesIntoBaseClass(
1382
1409
// Protocol lists are a special case - the same protocol list is in classRo
1383
1410
// and metaRo, so we only need to parse it once
1384
1411
parseProtocolListInfo (classIsec, roClassLayout.baseProtocolsOffset ,
1385
- extInfo.protocols );
1412
+ extInfo.protocols , extInfo. baseClassSourceLanguage );
1386
1413
1387
1414
// 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" );
1415
+ assert (parseProtocolListInfo (classIsec, roClassLayout.baseProtocolsOffset ,
1416
+ extInfo.baseClassSourceLanguage ) ==
1417
+ parseProtocolListInfo (metaIsec, roClassLayout.baseProtocolsOffset ,
1418
+ extInfo.baseClassSourceLanguage ) &&
1419
+ " Category merger expects classRo and metaRo to have the same protocol "
1420
+ " list" );
1393
1421
1394
1422
parsePointerListInfo (metaIsec, roClassLayout.baseMethodsOffset ,
1395
1423
extInfo.classMethods );
0 commit comments