@@ -9270,7 +9270,8 @@ void ASTReader::diagnoseOdrViolations() {
9270
9270
if (PendingOdrMergeFailures.empty () && PendingOdrMergeChecks.empty () &&
9271
9271
PendingFunctionOdrMergeFailures.empty () &&
9272
9272
PendingEnumOdrMergeFailures.empty () &&
9273
- PendingRecordOdrMergeFailures.empty ())
9273
+ PendingRecordOdrMergeFailures.empty () &&
9274
+ PendingObjCInterfaceOdrMergeFailures.empty ())
9274
9275
return ;
9275
9276
9276
9277
// Trigger the import of the full definition of each class that had any
@@ -9301,6 +9302,16 @@ void ASTReader::diagnoseOdrViolations() {
9301
9302
D->decls_begin ();
9302
9303
}
9303
9304
9305
+ // Trigger the import of the full interface definition.
9306
+ auto ObjCInterfaceOdrMergeFailures =
9307
+ std::move (PendingObjCInterfaceOdrMergeFailures);
9308
+ PendingObjCInterfaceOdrMergeFailures.clear ();
9309
+ for (auto &Merge : ObjCInterfaceOdrMergeFailures) {
9310
+ Merge.first ->decls_begin ();
9311
+ for (auto &InterfacePair : Merge.second )
9312
+ InterfacePair.first ->decls_begin ();
9313
+ }
9314
+
9304
9315
// Trigger the import of functions.
9305
9316
auto FunctionOdrMergeFailures = std::move (PendingFunctionOdrMergeFailures);
9306
9317
PendingFunctionOdrMergeFailures.clear ();
@@ -9413,7 +9424,8 @@ void ASTReader::diagnoseOdrViolations() {
9413
9424
}
9414
9425
9415
9426
if (OdrMergeFailures.empty () && FunctionOdrMergeFailures.empty () &&
9416
- EnumOdrMergeFailures.empty () && RecordOdrMergeFailures.empty ())
9427
+ EnumOdrMergeFailures.empty () && RecordOdrMergeFailures.empty () &&
9428
+ ObjCInterfaceOdrMergeFailures.empty ())
9417
9429
return ;
9418
9430
9419
9431
// Ensure we don't accidentally recursively enter deserialization while
@@ -11199,6 +11211,172 @@ void ASTReader::diagnoseOdrViolations() {
11199
11211
}
11200
11212
}
11201
11213
11214
+ for (auto &Merge : ObjCInterfaceOdrMergeFailures) {
11215
+ // If we've already pointed out a specific problem with this interface,
11216
+ // don't bother issuing a general "something's different" diagnostic.
11217
+ if (!DiagnosedOdrMergeFailures.insert (Merge.first ).second )
11218
+ continue ;
11219
+
11220
+ bool Diagnosed = false ;
11221
+ ObjCInterfaceDecl *FirstID = Merge.first ;
11222
+ std::string FirstModule = getOwningModuleNameForDiagnostic (FirstID);
11223
+ for (auto &InterfacePair : Merge.second ) {
11224
+ ObjCInterfaceDecl *SecondID = InterfacePair.first ;
11225
+ // Multiple different declarations got merged together; tell the user
11226
+ // where they came from.
11227
+ if (FirstID == SecondID)
11228
+ continue ;
11229
+
11230
+ std::string SecondModule = getOwningModuleNameForDiagnostic (SecondID);
11231
+
11232
+ auto *FirstDD = &FirstID->data ();
11233
+ auto *SecondDD = InterfacePair.second ;
11234
+ assert (FirstDD && SecondDD && " Definitions without DefinitionData" );
11235
+ // Diagnostics from ObjCInterfaces DefinitionData are emitted here.
11236
+ // FIXME: as part of definition data handling, add support for checking
11237
+ // matching protocols, ivars and categories
11238
+ if (FirstDD != SecondDD) {
11239
+ // Keep this in sync with
11240
+ // err_module_odr_violation_obj_interface_definition_data and
11241
+ // note_module_odr_violation_obj_interface_definition_data.
11242
+ enum ODRDefinitionDataDifference {
11243
+ SuperClassType,
11244
+ ReferencedProtocols
11245
+ };
11246
+ auto ODRDiagBaseError = [FirstID, &FirstModule,
11247
+ this ](SourceLocation Loc, SourceRange Range,
11248
+ ODRDefinitionDataDifference DiffType) {
11249
+ using namespace diag ;
11250
+ return Diag (Loc,
11251
+ err_module_odr_violation_obj_interface_definition_data)
11252
+ << FirstID << FirstModule.empty () << FirstModule << Range
11253
+ << DiffType;
11254
+ };
11255
+ auto ODRDiagBaseNote = [&SecondModule,
11256
+ this ](SourceLocation Loc, SourceRange Range,
11257
+ ODRDefinitionDataDifference DiffType) {
11258
+ using namespace diag ;
11259
+ return Diag (Loc,
11260
+ note_module_odr_violation_obj_interface_definition_data)
11261
+ << SecondModule << Range << DiffType;
11262
+ };
11263
+
11264
+ // Check for matching super class.
11265
+ auto GetSuperClassSourceRange = [](TypeSourceInfo *SuperInfo,
11266
+ ObjCInterfaceDecl *ID) {
11267
+ if (!SuperInfo)
11268
+ return ID->getSourceRange ();
11269
+ TypeLoc Loc = SuperInfo->getTypeLoc ();
11270
+ return SourceRange (Loc.getBeginLoc (), Loc.getEndLoc ());
11271
+ };
11272
+
11273
+ ObjCInterfaceDecl *FirstSuperClass = FirstID->getSuperClass ();
11274
+ ObjCInterfaceDecl *SecondSuperClass = nullptr ;
11275
+ auto *FirstSuperInfo = FirstID->getSuperClassTInfo ();
11276
+ auto *SecondSuperInfo = SecondDD->SuperClassTInfo ;
11277
+ if (SecondSuperInfo)
11278
+ SecondSuperClass = SecondSuperInfo->getType ()
11279
+ ->castAs <ObjCObjectType>()
11280
+ ->getInterface ();
11281
+
11282
+ if ((FirstSuperClass && SecondSuperClass &&
11283
+ FirstSuperClass->getODRHash () != SecondSuperClass->getODRHash ()) ||
11284
+ (FirstSuperClass && !SecondSuperClass) ||
11285
+ (!FirstSuperClass && SecondSuperClass)) {
11286
+ QualType FirstType;
11287
+ if (FirstSuperInfo)
11288
+ FirstType = FirstSuperInfo->getType ();
11289
+
11290
+ ODRDiagBaseError (FirstID->getLocation (),
11291
+ GetSuperClassSourceRange (FirstSuperInfo, FirstID),
11292
+ SuperClassType)
11293
+ << (bool )FirstSuperInfo << FirstType;
11294
+
11295
+ QualType SecondType;
11296
+ if (SecondSuperInfo)
11297
+ SecondType = SecondSuperInfo->getType ();
11298
+
11299
+ ODRDiagBaseNote (SecondID->getLocation (),
11300
+ GetSuperClassSourceRange (SecondSuperInfo, SecondID),
11301
+ SuperClassType)
11302
+ << (bool )SecondSuperInfo << SecondType;
11303
+ Diagnosed = true ;
11304
+ break ;
11305
+ }
11306
+
11307
+ // Check both interfaces reference the same number of protocols.
11308
+ // FIXME: add support for checking the actual protocols once support
11309
+ // for ODR hash in protocols land.
11310
+ auto GetProtoListSourceRange = [](ObjCInterfaceDecl *ID,
11311
+ const ObjCProtocolList &PL) {
11312
+ if (!PL.size ())
11313
+ return ID->getSourceRange ();
11314
+ return SourceRange (*PL.loc_begin (), *std::prev (PL.loc_end ()));
11315
+ };
11316
+ auto &FirstProtos = FirstID->getReferencedProtocols ();
11317
+ auto &SecondProtos = SecondDD->ReferencedProtocols ;
11318
+ if (FirstProtos.size () != SecondProtos.size ()) {
11319
+ ODRDiagBaseError (FirstID->getLocation (),
11320
+ GetProtoListSourceRange (FirstID, FirstProtos),
11321
+ ReferencedProtocols)
11322
+ << FirstProtos.size ();
11323
+ ODRDiagBaseNote (SecondID->getLocation (),
11324
+ GetProtoListSourceRange (SecondID, SecondProtos),
11325
+ ReferencedProtocols)
11326
+ << SecondProtos.size ();
11327
+ Diagnosed = true ;
11328
+ break ;
11329
+ }
11330
+ }
11331
+
11332
+ // FIXME: Improve PopulateHashes above and only have one version.
11333
+ auto PopulateHashes = [&ComputeSubDeclODRHash](DeclHashes &Hashes,
11334
+ ObjCInterfaceDecl *ID,
11335
+ const DeclContext *DC) {
11336
+ for (auto *D : ID->decls ()) {
11337
+ if (!ODRHash::isWhitelistedDecl (D, DC))
11338
+ continue ;
11339
+ Hashes.emplace_back (D, ComputeSubDeclODRHash (D));
11340
+ }
11341
+ };
11342
+
11343
+ DeclHashes FirstHashes;
11344
+ DeclHashes SecondHashes;
11345
+ PopulateHashes (FirstHashes, FirstID, FirstID);
11346
+ PopulateHashes (SecondHashes, SecondID, SecondID);
11347
+
11348
+ auto DR = FindTypeDiffs (FirstHashes, SecondHashes);
11349
+ ODRMismatchDecl FirstDiffType = DR.FirstDiffType ;
11350
+ ODRMismatchDecl SecondDiffType = DR.SecondDiffType ;
11351
+ Decl *FirstDecl = DR.FirstDecl ;
11352
+ Decl *SecondDecl = DR.SecondDecl ;
11353
+
11354
+ if (FirstDiffType == Other || SecondDiffType == Other) {
11355
+ DiagnoseODRUnexpected (DR, FirstID, FirstModule, SecondID, SecondModule);
11356
+ Diagnosed = true ;
11357
+ break ;
11358
+ }
11359
+
11360
+ if (FirstDiffType != SecondDiffType) {
11361
+ DiagnoseODRMismatch (DR, FirstID, FirstModule, SecondID, SecondModule);
11362
+ Diagnosed = true ;
11363
+ break ;
11364
+ }
11365
+
11366
+ if (Diagnosed)
11367
+ continue ;
11368
+
11369
+ Diag (FirstDecl->getLocation (),
11370
+ diag::err_module_odr_violation_mismatch_decl_unknown)
11371
+ << FirstID << FirstModule.empty () << FirstModule << FirstDiffType
11372
+ << FirstDecl->getSourceRange ();
11373
+ Diag (SecondDecl->getLocation (),
11374
+ diag::note_module_odr_violation_mismatch_decl_unknown)
11375
+ << SecondModule << FirstDiffType << SecondDecl->getSourceRange ();
11376
+ Diagnosed = true ;
11377
+ }
11378
+ }
11379
+
11202
11380
// Issue ODR failures diagnostics for functions.
11203
11381
for (auto &Merge : FunctionOdrMergeFailures) {
11204
11382
enum ODRFunctionDifference {
0 commit comments