1 //===-- ODRDiagsEmitter.cpp - Diagnostics for ODR mismatches ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "clang/AST/ODRDiagsEmitter.h"
10 #include "clang/AST/DeclFriend.h"
11 #include "clang/AST/DeclTemplate.h"
12 #include "clang/AST/ODRHash.h"
13 #include "clang/Basic/DiagnosticAST.h"
14 #include "clang/Basic/Module.h"
15
16 using namespace clang;
17
computeODRHash(QualType Ty)18 static unsigned computeODRHash(QualType Ty) {
19 ODRHash Hasher;
20 Hasher.AddQualType(Ty);
21 return Hasher.CalculateHash();
22 }
23
computeODRHash(const Stmt * S)24 static unsigned computeODRHash(const Stmt *S) {
25 ODRHash Hasher;
26 Hasher.AddStmt(S);
27 return Hasher.CalculateHash();
28 }
29
computeODRHash(const Decl * D)30 static unsigned computeODRHash(const Decl *D) {
31 assert(D);
32 ODRHash Hasher;
33 Hasher.AddSubDecl(D);
34 return Hasher.CalculateHash();
35 }
36
computeODRHash(const TemplateArgument & TA)37 static unsigned computeODRHash(const TemplateArgument &TA) {
38 ODRHash Hasher;
39 Hasher.AddTemplateArgument(TA);
40 return Hasher.CalculateHash();
41 }
42
getOwningModuleNameForDiagnostic(const Decl * D)43 std::string ODRDiagsEmitter::getOwningModuleNameForDiagnostic(const Decl *D) {
44 // If we know the owning module, use it.
45 if (Module *M = D->getImportedOwningModule())
46 return M->getFullModuleName();
47
48 // Not from a module.
49 return {};
50 }
51
52 template <typename MethodT>
diagnoseSubMismatchMethodParameters(DiagnosticsEngine & Diags,const NamedDecl * FirstContainer,StringRef FirstModule,StringRef SecondModule,const MethodT * FirstMethod,const MethodT * SecondMethod)53 static bool diagnoseSubMismatchMethodParameters(DiagnosticsEngine &Diags,
54 const NamedDecl *FirstContainer,
55 StringRef FirstModule,
56 StringRef SecondModule,
57 const MethodT *FirstMethod,
58 const MethodT *SecondMethod) {
59 enum DiagMethodType {
60 DiagMethod,
61 DiagConstructor,
62 DiagDestructor,
63 };
64 auto GetDiagMethodType = [](const NamedDecl *D) {
65 if (isa<CXXConstructorDecl>(D))
66 return DiagConstructor;
67 if (isa<CXXDestructorDecl>(D))
68 return DiagDestructor;
69 return DiagMethod;
70 };
71
72 enum ODRMethodParametersDifference {
73 NumberParameters,
74 ParameterType,
75 ParameterName,
76 };
77 auto DiagError = [&Diags, &GetDiagMethodType, FirstContainer, FirstModule,
78 FirstMethod](ODRMethodParametersDifference DiffType) {
79 DeclarationName FirstName = FirstMethod->getDeclName();
80 DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod);
81 return Diags.Report(FirstMethod->getLocation(),
82 diag::err_module_odr_violation_method_params)
83 << FirstContainer << FirstModule.empty() << FirstModule
84 << FirstMethod->getSourceRange() << DiffType << FirstMethodType
85 << FirstName;
86 };
87 auto DiagNote = [&Diags, &GetDiagMethodType, SecondModule,
88 SecondMethod](ODRMethodParametersDifference DiffType) {
89 DeclarationName SecondName = SecondMethod->getDeclName();
90 DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod);
91 return Diags.Report(SecondMethod->getLocation(),
92 diag::note_module_odr_violation_method_params)
93 << SecondModule.empty() << SecondModule
94 << SecondMethod->getSourceRange() << DiffType << SecondMethodType
95 << SecondName;
96 };
97
98 const unsigned FirstNumParameters = FirstMethod->param_size();
99 const unsigned SecondNumParameters = SecondMethod->param_size();
100 if (FirstNumParameters != SecondNumParameters) {
101 DiagError(NumberParameters) << FirstNumParameters;
102 DiagNote(NumberParameters) << SecondNumParameters;
103 return true;
104 }
105
106 for (unsigned I = 0; I < FirstNumParameters; ++I) {
107 const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);
108 const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);
109
110 QualType FirstParamType = FirstParam->getType();
111 QualType SecondParamType = SecondParam->getType();
112 if (FirstParamType != SecondParamType &&
113 computeODRHash(FirstParamType) != computeODRHash(SecondParamType)) {
114 if (const DecayedType *ParamDecayedType =
115 FirstParamType->getAs<DecayedType>()) {
116 DiagError(ParameterType) << (I + 1) << FirstParamType << true
117 << ParamDecayedType->getOriginalType();
118 } else {
119 DiagError(ParameterType) << (I + 1) << FirstParamType << false;
120 }
121
122 if (const DecayedType *ParamDecayedType =
123 SecondParamType->getAs<DecayedType>()) {
124 DiagNote(ParameterType) << (I + 1) << SecondParamType << true
125 << ParamDecayedType->getOriginalType();
126 } else {
127 DiagNote(ParameterType) << (I + 1) << SecondParamType << false;
128 }
129 return true;
130 }
131
132 DeclarationName FirstParamName = FirstParam->getDeclName();
133 DeclarationName SecondParamName = SecondParam->getDeclName();
134 if (FirstParamName != SecondParamName) {
135 DiagError(ParameterName) << (I + 1) << FirstParamName;
136 DiagNote(ParameterName) << (I + 1) << SecondParamName;
137 return true;
138 }
139 }
140
141 return false;
142 }
143
diagnoseSubMismatchField(const NamedDecl * FirstRecord,StringRef FirstModule,StringRef SecondModule,const FieldDecl * FirstField,const FieldDecl * SecondField) const144 bool ODRDiagsEmitter::diagnoseSubMismatchField(
145 const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,
146 const FieldDecl *FirstField, const FieldDecl *SecondField) const {
147 enum ODRFieldDifference {
148 FieldName,
149 FieldTypeName,
150 FieldSingleBitField,
151 FieldDifferentWidthBitField,
152 FieldSingleMutable,
153 FieldSingleInitializer,
154 FieldDifferentInitializers,
155 };
156
157 auto DiagError = [FirstRecord, FirstField, FirstModule,
158 this](ODRFieldDifference DiffType) {
159 return Diag(FirstField->getLocation(), diag::err_module_odr_violation_field)
160 << FirstRecord << FirstModule.empty() << FirstModule
161 << FirstField->getSourceRange() << DiffType;
162 };
163 auto DiagNote = [SecondField, SecondModule,
164 this](ODRFieldDifference DiffType) {
165 return Diag(SecondField->getLocation(),
166 diag::note_module_odr_violation_field)
167 << SecondModule.empty() << SecondModule << SecondField->getSourceRange() << DiffType;
168 };
169
170 IdentifierInfo *FirstII = FirstField->getIdentifier();
171 IdentifierInfo *SecondII = SecondField->getIdentifier();
172 if (FirstII->getName() != SecondII->getName()) {
173 DiagError(FieldName) << FirstII;
174 DiagNote(FieldName) << SecondII;
175 return true;
176 }
177
178 QualType FirstType = FirstField->getType();
179 QualType SecondType = SecondField->getType();
180 if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
181 DiagError(FieldTypeName) << FirstII << FirstType;
182 DiagNote(FieldTypeName) << SecondII << SecondType;
183 return true;
184 }
185
186 assert(Context.hasSameType(FirstField->getType(), SecondField->getType()));
187 (void)Context;
188
189 const bool IsFirstBitField = FirstField->isBitField();
190 const bool IsSecondBitField = SecondField->isBitField();
191 if (IsFirstBitField != IsSecondBitField) {
192 DiagError(FieldSingleBitField) << FirstII << IsFirstBitField;
193 DiagNote(FieldSingleBitField) << SecondII << IsSecondBitField;
194 return true;
195 }
196
197 if (IsFirstBitField && IsSecondBitField) {
198 unsigned FirstBitWidthHash = computeODRHash(FirstField->getBitWidth());
199 unsigned SecondBitWidthHash = computeODRHash(SecondField->getBitWidth());
200 if (FirstBitWidthHash != SecondBitWidthHash) {
201 DiagError(FieldDifferentWidthBitField)
202 << FirstII << FirstField->getBitWidth()->getSourceRange();
203 DiagNote(FieldDifferentWidthBitField)
204 << SecondII << SecondField->getBitWidth()->getSourceRange();
205 return true;
206 }
207 }
208
209 if (!LangOpts.CPlusPlus)
210 return false;
211
212 const bool IsFirstMutable = FirstField->isMutable();
213 const bool IsSecondMutable = SecondField->isMutable();
214 if (IsFirstMutable != IsSecondMutable) {
215 DiagError(FieldSingleMutable) << FirstII << IsFirstMutable;
216 DiagNote(FieldSingleMutable) << SecondII << IsSecondMutable;
217 return true;
218 }
219
220 const Expr *FirstInitializer = FirstField->getInClassInitializer();
221 const Expr *SecondInitializer = SecondField->getInClassInitializer();
222 if ((!FirstInitializer && SecondInitializer) ||
223 (FirstInitializer && !SecondInitializer)) {
224 DiagError(FieldSingleInitializer)
225 << FirstII << (FirstInitializer != nullptr);
226 DiagNote(FieldSingleInitializer)
227 << SecondII << (SecondInitializer != nullptr);
228 return true;
229 }
230
231 if (FirstInitializer && SecondInitializer) {
232 unsigned FirstInitHash = computeODRHash(FirstInitializer);
233 unsigned SecondInitHash = computeODRHash(SecondInitializer);
234 if (FirstInitHash != SecondInitHash) {
235 DiagError(FieldDifferentInitializers)
236 << FirstII << FirstInitializer->getSourceRange();
237 DiagNote(FieldDifferentInitializers)
238 << SecondII << SecondInitializer->getSourceRange();
239 return true;
240 }
241 }
242
243 return false;
244 }
245
diagnoseSubMismatchTypedef(const NamedDecl * FirstRecord,StringRef FirstModule,StringRef SecondModule,const TypedefNameDecl * FirstTD,const TypedefNameDecl * SecondTD,bool IsTypeAlias) const246 bool ODRDiagsEmitter::diagnoseSubMismatchTypedef(
247 const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,
248 const TypedefNameDecl *FirstTD, const TypedefNameDecl *SecondTD,
249 bool IsTypeAlias) const {
250 enum ODRTypedefDifference {
251 TypedefName,
252 TypedefType,
253 };
254
255 auto DiagError = [FirstRecord, FirstTD, FirstModule,
256 this](ODRTypedefDifference DiffType) {
257 return Diag(FirstTD->getLocation(), diag::err_module_odr_violation_typedef)
258 << FirstRecord << FirstModule.empty() << FirstModule
259 << FirstTD->getSourceRange() << DiffType;
260 };
261 auto DiagNote = [SecondTD, SecondModule,
262 this](ODRTypedefDifference DiffType) {
263 return Diag(SecondTD->getLocation(),
264 diag::note_module_odr_violation_typedef)
265 << SecondModule << SecondTD->getSourceRange() << DiffType;
266 };
267
268 DeclarationName FirstName = FirstTD->getDeclName();
269 DeclarationName SecondName = SecondTD->getDeclName();
270 if (FirstName != SecondName) {
271 DiagError(TypedefName) << IsTypeAlias << FirstName;
272 DiagNote(TypedefName) << IsTypeAlias << SecondName;
273 return true;
274 }
275
276 QualType FirstType = FirstTD->getUnderlyingType();
277 QualType SecondType = SecondTD->getUnderlyingType();
278 if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
279 DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType;
280 DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType;
281 return true;
282 }
283 return false;
284 }
285
diagnoseSubMismatchVar(const NamedDecl * FirstRecord,StringRef FirstModule,StringRef SecondModule,const VarDecl * FirstVD,const VarDecl * SecondVD) const286 bool ODRDiagsEmitter::diagnoseSubMismatchVar(const NamedDecl *FirstRecord,
287 StringRef FirstModule,
288 StringRef SecondModule,
289 const VarDecl *FirstVD,
290 const VarDecl *SecondVD) const {
291 enum ODRVarDifference {
292 VarName,
293 VarType,
294 VarSingleInitializer,
295 VarDifferentInitializer,
296 VarConstexpr,
297 };
298
299 auto DiagError = [FirstRecord, FirstVD, FirstModule,
300 this](ODRVarDifference DiffType) {
301 return Diag(FirstVD->getLocation(), diag::err_module_odr_violation_variable)
302 << FirstRecord << FirstModule.empty() << FirstModule
303 << FirstVD->getSourceRange() << DiffType;
304 };
305 auto DiagNote = [SecondVD, SecondModule, this](ODRVarDifference DiffType) {
306 return Diag(SecondVD->getLocation(),
307 diag::note_module_odr_violation_variable)
308 << SecondModule << SecondVD->getSourceRange() << DiffType;
309 };
310
311 DeclarationName FirstName = FirstVD->getDeclName();
312 DeclarationName SecondName = SecondVD->getDeclName();
313 if (FirstName != SecondName) {
314 DiagError(VarName) << FirstName;
315 DiagNote(VarName) << SecondName;
316 return true;
317 }
318
319 QualType FirstType = FirstVD->getType();
320 QualType SecondType = SecondVD->getType();
321 if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
322 DiagError(VarType) << FirstName << FirstType;
323 DiagNote(VarType) << SecondName << SecondType;
324 return true;
325 }
326
327 if (!LangOpts.CPlusPlus)
328 return false;
329
330 const Expr *FirstInit = FirstVD->getInit();
331 const Expr *SecondInit = SecondVD->getInit();
332 if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
333 DiagError(VarSingleInitializer)
334 << FirstName << (FirstInit == nullptr)
335 << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
336 DiagNote(VarSingleInitializer)
337 << SecondName << (SecondInit == nullptr)
338 << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
339 return true;
340 }
341
342 if (FirstInit && SecondInit &&
343 computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
344 DiagError(VarDifferentInitializer)
345 << FirstName << FirstInit->getSourceRange();
346 DiagNote(VarDifferentInitializer)
347 << SecondName << SecondInit->getSourceRange();
348 return true;
349 }
350
351 const bool FirstIsConstexpr = FirstVD->isConstexpr();
352 const bool SecondIsConstexpr = SecondVD->isConstexpr();
353 if (FirstIsConstexpr != SecondIsConstexpr) {
354 DiagError(VarConstexpr) << FirstName << FirstIsConstexpr;
355 DiagNote(VarConstexpr) << SecondName << SecondIsConstexpr;
356 return true;
357 }
358 return false;
359 }
360
diagnoseSubMismatchProtocols(const ObjCProtocolList & FirstProtocols,const ObjCContainerDecl * FirstContainer,StringRef FirstModule,const ObjCProtocolList & SecondProtocols,const ObjCContainerDecl * SecondContainer,StringRef SecondModule) const361 bool ODRDiagsEmitter::diagnoseSubMismatchProtocols(
362 const ObjCProtocolList &FirstProtocols,
363 const ObjCContainerDecl *FirstContainer, StringRef FirstModule,
364 const ObjCProtocolList &SecondProtocols,
365 const ObjCContainerDecl *SecondContainer, StringRef SecondModule) const {
366 // Keep in sync with err_module_odr_violation_referenced_protocols.
367 enum ODRReferencedProtocolDifference {
368 NumProtocols,
369 ProtocolType,
370 };
371 auto DiagRefProtocolError = [FirstContainer, FirstModule,
372 this](SourceLocation Loc, SourceRange Range,
373 ODRReferencedProtocolDifference DiffType) {
374 return Diag(Loc, diag::err_module_odr_violation_referenced_protocols)
375 << FirstContainer << FirstModule.empty() << FirstModule << Range
376 << DiffType;
377 };
378 auto DiagRefProtocolNote = [SecondModule,
379 this](SourceLocation Loc, SourceRange Range,
380 ODRReferencedProtocolDifference DiffType) {
381 return Diag(Loc, diag::note_module_odr_violation_referenced_protocols)
382 << SecondModule.empty() << SecondModule << Range << DiffType;
383 };
384 auto GetProtoListSourceRange = [](const ObjCProtocolList &PL) {
385 if (PL.empty())
386 return SourceRange();
387 return SourceRange(*PL.loc_begin(), *std::prev(PL.loc_end()));
388 };
389
390 if (FirstProtocols.size() != SecondProtocols.size()) {
391 DiagRefProtocolError(FirstContainer->getLocation(),
392 GetProtoListSourceRange(FirstProtocols), NumProtocols)
393 << FirstProtocols.size();
394 DiagRefProtocolNote(SecondContainer->getLocation(),
395 GetProtoListSourceRange(SecondProtocols), NumProtocols)
396 << SecondProtocols.size();
397 return true;
398 }
399
400 for (unsigned I = 0, E = FirstProtocols.size(); I != E; ++I) {
401 const ObjCProtocolDecl *FirstProtocol = FirstProtocols[I];
402 const ObjCProtocolDecl *SecondProtocol = SecondProtocols[I];
403 DeclarationName FirstProtocolName = FirstProtocol->getDeclName();
404 DeclarationName SecondProtocolName = SecondProtocol->getDeclName();
405 if (FirstProtocolName != SecondProtocolName) {
406 SourceLocation FirstLoc = *(FirstProtocols.loc_begin() + I);
407 SourceLocation SecondLoc = *(SecondProtocols.loc_begin() + I);
408 SourceRange EmptyRange;
409 DiagRefProtocolError(FirstLoc, EmptyRange, ProtocolType)
410 << (I + 1) << FirstProtocolName;
411 DiagRefProtocolNote(SecondLoc, EmptyRange, ProtocolType)
412 << (I + 1) << SecondProtocolName;
413 return true;
414 }
415 }
416
417 return false;
418 }
419
diagnoseSubMismatchObjCMethod(const NamedDecl * FirstObjCContainer,StringRef FirstModule,StringRef SecondModule,const ObjCMethodDecl * FirstMethod,const ObjCMethodDecl * SecondMethod) const420 bool ODRDiagsEmitter::diagnoseSubMismatchObjCMethod(
421 const NamedDecl *FirstObjCContainer, StringRef FirstModule,
422 StringRef SecondModule, const ObjCMethodDecl *FirstMethod,
423 const ObjCMethodDecl *SecondMethod) const {
424 enum ODRMethodDifference {
425 ReturnType,
426 InstanceOrClass,
427 ControlLevel, // optional/required
428 DesignatedInitializer,
429 Directness,
430 Name,
431 };
432
433 auto DiagError = [FirstObjCContainer, FirstModule, FirstMethod,
434 this](ODRMethodDifference DiffType) {
435 return Diag(FirstMethod->getLocation(),
436 diag::err_module_odr_violation_objc_method)
437 << FirstObjCContainer << FirstModule.empty() << FirstModule
438 << FirstMethod->getSourceRange() << DiffType;
439 };
440 auto DiagNote = [SecondModule, SecondMethod,
441 this](ODRMethodDifference DiffType) {
442 return Diag(SecondMethod->getLocation(),
443 diag::note_module_odr_violation_objc_method)
444 << SecondModule.empty() << SecondModule
445 << SecondMethod->getSourceRange() << DiffType;
446 };
447
448 if (computeODRHash(FirstMethod->getReturnType()) !=
449 computeODRHash(SecondMethod->getReturnType())) {
450 DiagError(ReturnType) << FirstMethod << FirstMethod->getReturnType();
451 DiagNote(ReturnType) << SecondMethod << SecondMethod->getReturnType();
452 return true;
453 }
454
455 if (FirstMethod->isInstanceMethod() != SecondMethod->isInstanceMethod()) {
456 DiagError(InstanceOrClass)
457 << FirstMethod << FirstMethod->isInstanceMethod();
458 DiagNote(InstanceOrClass)
459 << SecondMethod << SecondMethod->isInstanceMethod();
460 return true;
461 }
462 if (FirstMethod->getImplementationControl() !=
463 SecondMethod->getImplementationControl()) {
464 DiagError(ControlLevel)
465 << llvm::to_underlying(FirstMethod->getImplementationControl());
466 DiagNote(ControlLevel) << llvm::to_underlying(
467 SecondMethod->getImplementationControl());
468 return true;
469 }
470 if (FirstMethod->isThisDeclarationADesignatedInitializer() !=
471 SecondMethod->isThisDeclarationADesignatedInitializer()) {
472 DiagError(DesignatedInitializer)
473 << FirstMethod
474 << FirstMethod->isThisDeclarationADesignatedInitializer();
475 DiagNote(DesignatedInitializer)
476 << SecondMethod
477 << SecondMethod->isThisDeclarationADesignatedInitializer();
478 return true;
479 }
480 if (FirstMethod->isDirectMethod() != SecondMethod->isDirectMethod()) {
481 DiagError(Directness) << FirstMethod << FirstMethod->isDirectMethod();
482 DiagNote(Directness) << SecondMethod << SecondMethod->isDirectMethod();
483 return true;
484 }
485 if (diagnoseSubMismatchMethodParameters(Diags, FirstObjCContainer,
486 FirstModule, SecondModule,
487 FirstMethod, SecondMethod))
488 return true;
489
490 // Check method name *after* looking at the parameters otherwise we get a
491 // less ideal diagnostics: a ObjCMethodName mismatch given that selectors
492 // for different parameters are likely to be different.
493 DeclarationName FirstName = FirstMethod->getDeclName();
494 DeclarationName SecondName = SecondMethod->getDeclName();
495 if (FirstName != SecondName) {
496 DiagError(Name) << FirstName;
497 DiagNote(Name) << SecondName;
498 return true;
499 }
500
501 return false;
502 }
503
diagnoseSubMismatchObjCProperty(const NamedDecl * FirstObjCContainer,StringRef FirstModule,StringRef SecondModule,const ObjCPropertyDecl * FirstProp,const ObjCPropertyDecl * SecondProp) const504 bool ODRDiagsEmitter::diagnoseSubMismatchObjCProperty(
505 const NamedDecl *FirstObjCContainer, StringRef FirstModule,
506 StringRef SecondModule, const ObjCPropertyDecl *FirstProp,
507 const ObjCPropertyDecl *SecondProp) const {
508 enum ODRPropertyDifference {
509 Name,
510 Type,
511 ControlLevel, // optional/required
512 Attribute,
513 };
514
515 auto DiagError = [FirstObjCContainer, FirstModule, FirstProp,
516 this](SourceLocation Loc, ODRPropertyDifference DiffType) {
517 return Diag(Loc, diag::err_module_odr_violation_objc_property)
518 << FirstObjCContainer << FirstModule.empty() << FirstModule
519 << FirstProp->getSourceRange() << DiffType;
520 };
521 auto DiagNote = [SecondModule, SecondProp,
522 this](SourceLocation Loc, ODRPropertyDifference DiffType) {
523 return Diag(Loc, diag::note_module_odr_violation_objc_property)
524 << SecondModule.empty() << SecondModule
525 << SecondProp->getSourceRange() << DiffType;
526 };
527
528 IdentifierInfo *FirstII = FirstProp->getIdentifier();
529 IdentifierInfo *SecondII = SecondProp->getIdentifier();
530 if (FirstII->getName() != SecondII->getName()) {
531 DiagError(FirstProp->getLocation(), Name) << FirstII;
532 DiagNote(SecondProp->getLocation(), Name) << SecondII;
533 return true;
534 }
535 if (computeODRHash(FirstProp->getType()) !=
536 computeODRHash(SecondProp->getType())) {
537 DiagError(FirstProp->getLocation(), Type)
538 << FirstII << FirstProp->getType();
539 DiagNote(SecondProp->getLocation(), Type)
540 << SecondII << SecondProp->getType();
541 return true;
542 }
543 if (FirstProp->getPropertyImplementation() !=
544 SecondProp->getPropertyImplementation()) {
545 DiagError(FirstProp->getLocation(), ControlLevel)
546 << FirstProp->getPropertyImplementation();
547 DiagNote(SecondProp->getLocation(), ControlLevel)
548 << SecondProp->getPropertyImplementation();
549 return true;
550 }
551
552 // Go over the property attributes and stop at the first mismatch.
553 unsigned FirstAttrs = (unsigned)FirstProp->getPropertyAttributes();
554 unsigned SecondAttrs = (unsigned)SecondProp->getPropertyAttributes();
555 if (FirstAttrs != SecondAttrs) {
556 for (unsigned I = 0; I < NumObjCPropertyAttrsBits; ++I) {
557 unsigned CheckedAttr = (1 << I);
558 if ((FirstAttrs & CheckedAttr) == (SecondAttrs & CheckedAttr))
559 continue;
560
561 bool IsFirstWritten =
562 (unsigned)FirstProp->getPropertyAttributesAsWritten() & CheckedAttr;
563 bool IsSecondWritten =
564 (unsigned)SecondProp->getPropertyAttributesAsWritten() & CheckedAttr;
565 DiagError(IsFirstWritten ? FirstProp->getLParenLoc()
566 : FirstProp->getLocation(),
567 Attribute)
568 << FirstII << (I + 1) << IsFirstWritten;
569 DiagNote(IsSecondWritten ? SecondProp->getLParenLoc()
570 : SecondProp->getLocation(),
571 Attribute)
572 << SecondII << (I + 1);
573 return true;
574 }
575 }
576
577 return false;
578 }
579
580 ODRDiagsEmitter::DiffResult
FindTypeDiffs(DeclHashes & FirstHashes,DeclHashes & SecondHashes)581 ODRDiagsEmitter::FindTypeDiffs(DeclHashes &FirstHashes,
582 DeclHashes &SecondHashes) {
583 auto DifferenceSelector = [](const Decl *D) {
584 assert(D && "valid Decl required");
585 switch (D->getKind()) {
586 default:
587 return Other;
588 case Decl::AccessSpec:
589 switch (D->getAccess()) {
590 case AS_public:
591 return PublicSpecifer;
592 case AS_private:
593 return PrivateSpecifer;
594 case AS_protected:
595 return ProtectedSpecifer;
596 case AS_none:
597 break;
598 }
599 llvm_unreachable("Invalid access specifier");
600 case Decl::StaticAssert:
601 return StaticAssert;
602 case Decl::Field:
603 return Field;
604 case Decl::CXXMethod:
605 case Decl::CXXConstructor:
606 case Decl::CXXDestructor:
607 return CXXMethod;
608 case Decl::TypeAlias:
609 return TypeAlias;
610 case Decl::Typedef:
611 return TypeDef;
612 case Decl::Var:
613 return Var;
614 case Decl::Friend:
615 return Friend;
616 case Decl::FunctionTemplate:
617 return FunctionTemplate;
618 case Decl::ObjCMethod:
619 return ObjCMethod;
620 case Decl::ObjCIvar:
621 return ObjCIvar;
622 case Decl::ObjCProperty:
623 return ObjCProperty;
624 }
625 };
626
627 DiffResult DR;
628 auto FirstIt = FirstHashes.begin();
629 auto SecondIt = SecondHashes.begin();
630 while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()) {
631 if (FirstIt != FirstHashes.end() && SecondIt != SecondHashes.end() &&
632 FirstIt->second == SecondIt->second) {
633 ++FirstIt;
634 ++SecondIt;
635 continue;
636 }
637
638 DR.FirstDecl = FirstIt == FirstHashes.end() ? nullptr : FirstIt->first;
639 DR.SecondDecl = SecondIt == SecondHashes.end() ? nullptr : SecondIt->first;
640
641 DR.FirstDiffType =
642 DR.FirstDecl ? DifferenceSelector(DR.FirstDecl) : EndOfClass;
643 DR.SecondDiffType =
644 DR.SecondDecl ? DifferenceSelector(DR.SecondDecl) : EndOfClass;
645 return DR;
646 }
647 return DR;
648 }
649
diagnoseSubMismatchUnexpected(DiffResult & DR,const NamedDecl * FirstRecord,StringRef FirstModule,const NamedDecl * SecondRecord,StringRef SecondModule) const650 void ODRDiagsEmitter::diagnoseSubMismatchUnexpected(
651 DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule,
652 const NamedDecl *SecondRecord, StringRef SecondModule) const {
653 Diag(FirstRecord->getLocation(),
654 diag::err_module_odr_violation_different_definitions)
655 << FirstRecord << FirstModule.empty() << FirstModule;
656
657 if (DR.FirstDecl) {
658 Diag(DR.FirstDecl->getLocation(), diag::note_first_module_difference)
659 << FirstRecord << DR.FirstDecl->getSourceRange();
660 }
661
662 Diag(SecondRecord->getLocation(),
663 diag::note_module_odr_violation_different_definitions)
664 << SecondModule;
665
666 if (DR.SecondDecl) {
667 Diag(DR.SecondDecl->getLocation(), diag::note_second_module_difference)
668 << DR.SecondDecl->getSourceRange();
669 }
670 }
671
diagnoseSubMismatchDifferentDeclKinds(DiffResult & DR,const NamedDecl * FirstRecord,StringRef FirstModule,const NamedDecl * SecondRecord,StringRef SecondModule) const672 void ODRDiagsEmitter::diagnoseSubMismatchDifferentDeclKinds(
673 DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule,
674 const NamedDecl *SecondRecord, StringRef SecondModule) const {
675 auto GetMismatchedDeclLoc = [](const NamedDecl *Container,
676 ODRMismatchDecl DiffType, const Decl *D) {
677 SourceLocation Loc;
678 SourceRange Range;
679 if (DiffType == EndOfClass) {
680 if (auto *Tag = dyn_cast<TagDecl>(Container))
681 Loc = Tag->getBraceRange().getEnd();
682 else if (auto *IF = dyn_cast<ObjCInterfaceDecl>(Container))
683 Loc = IF->getAtEndRange().getBegin();
684 else
685 Loc = Container->getEndLoc();
686 } else {
687 Loc = D->getLocation();
688 Range = D->getSourceRange();
689 }
690 return std::make_pair(Loc, Range);
691 };
692
693 auto FirstDiagInfo =
694 GetMismatchedDeclLoc(FirstRecord, DR.FirstDiffType, DR.FirstDecl);
695 Diag(FirstDiagInfo.first, diag::err_module_odr_violation_mismatch_decl)
696 << FirstRecord << FirstModule.empty() << FirstModule
697 << FirstDiagInfo.second << DR.FirstDiffType;
698
699 auto SecondDiagInfo =
700 GetMismatchedDeclLoc(SecondRecord, DR.SecondDiffType, DR.SecondDecl);
701 Diag(SecondDiagInfo.first, diag::note_module_odr_violation_mismatch_decl)
702 << SecondModule.empty() << SecondModule << SecondDiagInfo.second
703 << DR.SecondDiffType;
704 }
705
diagnoseMismatch(const CXXRecordDecl * FirstRecord,const CXXRecordDecl * SecondRecord,const struct CXXRecordDecl::DefinitionData * SecondDD) const706 bool ODRDiagsEmitter::diagnoseMismatch(
707 const CXXRecordDecl *FirstRecord, const CXXRecordDecl *SecondRecord,
708 const struct CXXRecordDecl::DefinitionData *SecondDD) const {
709 // Multiple different declarations got merged together; tell the user
710 // where they came from.
711 if (FirstRecord == SecondRecord)
712 return false;
713
714 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord);
715 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);
716
717 const struct CXXRecordDecl::DefinitionData *FirstDD =
718 FirstRecord->DefinitionData;
719 assert(FirstDD && SecondDD && "Definitions without DefinitionData");
720
721 // Diagnostics from DefinitionData are emitted here.
722 if (FirstDD != SecondDD) {
723 // Keep in sync with err_module_odr_violation_definition_data.
724 enum ODRDefinitionDataDifference {
725 NumBases,
726 NumVBases,
727 BaseType,
728 BaseVirtual,
729 BaseAccess,
730 };
731 auto DiagBaseError = [FirstRecord, &FirstModule,
732 this](SourceLocation Loc, SourceRange Range,
733 ODRDefinitionDataDifference DiffType) {
734 return Diag(Loc, diag::err_module_odr_violation_definition_data)
735 << FirstRecord << FirstModule.empty() << FirstModule << Range
736 << DiffType;
737 };
738 auto DiagBaseNote = [&SecondModule,
739 this](SourceLocation Loc, SourceRange Range,
740 ODRDefinitionDataDifference DiffType) {
741 return Diag(Loc, diag::note_module_odr_violation_definition_data)
742 << SecondModule << Range << DiffType;
743 };
744 auto GetSourceRange = [](const struct CXXRecordDecl::DefinitionData *DD) {
745 unsigned NumBases = DD->NumBases;
746 if (NumBases == 0)
747 return SourceRange();
748 ArrayRef<CXXBaseSpecifier> bases = DD->bases();
749 return SourceRange(bases[0].getBeginLoc(),
750 bases[NumBases - 1].getEndLoc());
751 };
752
753 unsigned FirstNumBases = FirstDD->NumBases;
754 unsigned FirstNumVBases = FirstDD->NumVBases;
755 unsigned SecondNumBases = SecondDD->NumBases;
756 unsigned SecondNumVBases = SecondDD->NumVBases;
757 if (FirstNumBases != SecondNumBases) {
758 DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
759 NumBases)
760 << FirstNumBases;
761 DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
762 NumBases)
763 << SecondNumBases;
764 return true;
765 }
766
767 if (FirstNumVBases != SecondNumVBases) {
768 DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
769 NumVBases)
770 << FirstNumVBases;
771 DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
772 NumVBases)
773 << SecondNumVBases;
774 return true;
775 }
776
777 ArrayRef<CXXBaseSpecifier> FirstBases = FirstDD->bases();
778 ArrayRef<CXXBaseSpecifier> SecondBases = SecondDD->bases();
779 for (unsigned I = 0; I < FirstNumBases; ++I) {
780 const CXXBaseSpecifier FirstBase = FirstBases[I];
781 const CXXBaseSpecifier SecondBase = SecondBases[I];
782 if (computeODRHash(FirstBase.getType()) !=
783 computeODRHash(SecondBase.getType())) {
784 DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
785 BaseType)
786 << (I + 1) << FirstBase.getType();
787 DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(),
788 BaseType)
789 << (I + 1) << SecondBase.getType();
790 return true;
791 }
792
793 if (FirstBase.isVirtual() != SecondBase.isVirtual()) {
794 DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
795 BaseVirtual)
796 << (I + 1) << FirstBase.isVirtual() << FirstBase.getType();
797 DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(),
798 BaseVirtual)
799 << (I + 1) << SecondBase.isVirtual() << SecondBase.getType();
800 return true;
801 }
802
803 if (FirstBase.getAccessSpecifierAsWritten() !=
804 SecondBase.getAccessSpecifierAsWritten()) {
805 DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
806 BaseAccess)
807 << (I + 1) << FirstBase.getType()
808 << (int)FirstBase.getAccessSpecifierAsWritten();
809 DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(),
810 BaseAccess)
811 << (I + 1) << SecondBase.getType()
812 << (int)SecondBase.getAccessSpecifierAsWritten();
813 return true;
814 }
815 }
816 }
817
818 const ClassTemplateDecl *FirstTemplate =
819 FirstRecord->getDescribedClassTemplate();
820 const ClassTemplateDecl *SecondTemplate =
821 SecondRecord->getDescribedClassTemplate();
822
823 assert(!FirstTemplate == !SecondTemplate &&
824 "Both pointers should be null or non-null");
825
826 if (FirstTemplate && SecondTemplate) {
827 ArrayRef<const NamedDecl *> FirstTemplateParams =
828 FirstTemplate->getTemplateParameters()->asArray();
829 ArrayRef<const NamedDecl *> SecondTemplateParams =
830 SecondTemplate->getTemplateParameters()->asArray();
831 assert(FirstTemplateParams.size() == SecondTemplateParams.size() &&
832 "Number of template parameters should be equal.");
833 for (auto Pair : llvm::zip(FirstTemplateParams, SecondTemplateParams)) {
834 const NamedDecl *FirstDecl = std::get<0>(Pair);
835 const NamedDecl *SecondDecl = std::get<1>(Pair);
836 if (computeODRHash(FirstDecl) == computeODRHash(SecondDecl))
837 continue;
838
839 assert(FirstDecl->getKind() == SecondDecl->getKind() &&
840 "Parameter Decl's should be the same kind.");
841
842 enum ODRTemplateDifference {
843 ParamEmptyName,
844 ParamName,
845 ParamSingleDefaultArgument,
846 ParamDifferentDefaultArgument,
847 };
848
849 auto hasDefaultArg = [](const NamedDecl *D) {
850 if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(D))
851 return TTP->hasDefaultArgument() &&
852 !TTP->defaultArgumentWasInherited();
853 if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
854 return NTTP->hasDefaultArgument() &&
855 !NTTP->defaultArgumentWasInherited();
856 auto *TTP = cast<TemplateTemplateParmDecl>(D);
857 return TTP->hasDefaultArgument() && !TTP->defaultArgumentWasInherited();
858 };
859 bool hasFirstArg = hasDefaultArg(FirstDecl);
860 bool hasSecondArg = hasDefaultArg(SecondDecl);
861
862 ODRTemplateDifference ErrDiffType;
863 ODRTemplateDifference NoteDiffType;
864
865 DeclarationName FirstName = FirstDecl->getDeclName();
866 DeclarationName SecondName = SecondDecl->getDeclName();
867
868 if (FirstName != SecondName) {
869 bool FirstNameEmpty =
870 FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo();
871 bool SecondNameEmpty =
872 SecondName.isIdentifier() && !SecondName.getAsIdentifierInfo();
873 ErrDiffType = FirstNameEmpty ? ParamEmptyName : ParamName;
874 NoteDiffType = SecondNameEmpty ? ParamEmptyName : ParamName;
875 } else if (hasFirstArg == hasSecondArg)
876 ErrDiffType = NoteDiffType = ParamDifferentDefaultArgument;
877 else
878 ErrDiffType = NoteDiffType = ParamSingleDefaultArgument;
879
880 Diag(FirstDecl->getLocation(),
881 diag::err_module_odr_violation_template_parameter)
882 << FirstRecord << FirstModule.empty() << FirstModule
883 << FirstDecl->getSourceRange() << ErrDiffType << hasFirstArg
884 << FirstName;
885 Diag(SecondDecl->getLocation(),
886 diag::note_module_odr_violation_template_parameter)
887 << SecondModule << SecondDecl->getSourceRange() << NoteDiffType
888 << hasSecondArg << SecondName;
889 return true;
890 }
891 }
892
893 auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record,
894 const DeclContext *DC) {
895 for (const Decl *D : Record->decls()) {
896 if (!ODRHash::isSubDeclToBeProcessed(D, DC))
897 continue;
898 Hashes.emplace_back(D, computeODRHash(D));
899 }
900 };
901
902 DeclHashes FirstHashes;
903 DeclHashes SecondHashes;
904 const DeclContext *DC = FirstRecord;
905 PopulateHashes(FirstHashes, FirstRecord, DC);
906 PopulateHashes(SecondHashes, SecondRecord, DC);
907
908 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
909 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
910 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
911 const Decl *FirstDecl = DR.FirstDecl;
912 const Decl *SecondDecl = DR.SecondDecl;
913
914 if (FirstDiffType == Other || SecondDiffType == Other) {
915 diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
916 SecondModule);
917 return true;
918 }
919
920 if (FirstDiffType != SecondDiffType) {
921 diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule,
922 SecondRecord, SecondModule);
923 return true;
924 }
925
926 // Used with err_module_odr_violation_record and
927 // note_module_odr_violation_record
928 enum ODRCXXRecordDifference {
929 StaticAssertCondition,
930 StaticAssertMessage,
931 StaticAssertOnlyMessage,
932 MethodName,
933 MethodDeleted,
934 MethodDefaulted,
935 MethodVirtual,
936 MethodStatic,
937 MethodVolatile,
938 MethodConst,
939 MethodInline,
940 MethodParameterSingleDefaultArgument,
941 MethodParameterDifferentDefaultArgument,
942 MethodNoTemplateArguments,
943 MethodDifferentNumberTemplateArguments,
944 MethodDifferentTemplateArgument,
945 MethodSingleBody,
946 MethodDifferentBody,
947 FriendTypeFunction,
948 FriendType,
949 FriendFunction,
950 FunctionTemplateDifferentNumberParameters,
951 FunctionTemplateParameterDifferentKind,
952 FunctionTemplateParameterName,
953 FunctionTemplateParameterSingleDefaultArgument,
954 FunctionTemplateParameterDifferentDefaultArgument,
955 FunctionTemplateParameterDifferentType,
956 FunctionTemplatePackParameter,
957 };
958 auto DiagError = [FirstRecord, &FirstModule,
959 this](SourceLocation Loc, SourceRange Range,
960 ODRCXXRecordDifference DiffType) {
961 return Diag(Loc, diag::err_module_odr_violation_record)
962 << FirstRecord << FirstModule.empty() << FirstModule << Range
963 << DiffType;
964 };
965 auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
966 ODRCXXRecordDifference DiffType) {
967 return Diag(Loc, diag::note_module_odr_violation_record)
968 << SecondModule << Range << DiffType;
969 };
970
971 assert(FirstDiffType == SecondDiffType);
972 switch (FirstDiffType) {
973 case Other:
974 case EndOfClass:
975 case PublicSpecifer:
976 case PrivateSpecifer:
977 case ProtectedSpecifer:
978 case ObjCMethod:
979 case ObjCIvar:
980 case ObjCProperty:
981 llvm_unreachable("Invalid diff type");
982
983 case StaticAssert: {
984 const StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl);
985 const StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl);
986
987 const Expr *FirstExpr = FirstSA->getAssertExpr();
988 const Expr *SecondExpr = SecondSA->getAssertExpr();
989 unsigned FirstODRHash = computeODRHash(FirstExpr);
990 unsigned SecondODRHash = computeODRHash(SecondExpr);
991 if (FirstODRHash != SecondODRHash) {
992 DiagError(FirstExpr->getBeginLoc(), FirstExpr->getSourceRange(),
993 StaticAssertCondition);
994 DiagNote(SecondExpr->getBeginLoc(), SecondExpr->getSourceRange(),
995 StaticAssertCondition);
996 return true;
997 }
998
999 const Expr *FirstMessage = FirstSA->getMessage();
1000 const Expr *SecondMessage = SecondSA->getMessage();
1001 assert((FirstMessage || SecondMessage) && "Both messages cannot be empty");
1002 if ((FirstMessage && !SecondMessage) || (!FirstMessage && SecondMessage)) {
1003 SourceLocation FirstLoc, SecondLoc;
1004 SourceRange FirstRange, SecondRange;
1005 if (FirstMessage) {
1006 FirstLoc = FirstMessage->getBeginLoc();
1007 FirstRange = FirstMessage->getSourceRange();
1008 } else {
1009 FirstLoc = FirstSA->getBeginLoc();
1010 FirstRange = FirstSA->getSourceRange();
1011 }
1012 if (SecondMessage) {
1013 SecondLoc = SecondMessage->getBeginLoc();
1014 SecondRange = SecondMessage->getSourceRange();
1015 } else {
1016 SecondLoc = SecondSA->getBeginLoc();
1017 SecondRange = SecondSA->getSourceRange();
1018 }
1019 DiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage)
1020 << (FirstMessage == nullptr);
1021 DiagNote(SecondLoc, SecondRange, StaticAssertOnlyMessage)
1022 << (SecondMessage == nullptr);
1023 return true;
1024 }
1025
1026 if (FirstMessage && SecondMessage) {
1027 unsigned FirstMessageODRHash = computeODRHash(FirstMessage);
1028 unsigned SecondMessageODRHash = computeODRHash(SecondMessage);
1029 if (FirstMessageODRHash != SecondMessageODRHash) {
1030 DiagError(FirstMessage->getBeginLoc(), FirstMessage->getSourceRange(),
1031 StaticAssertMessage);
1032 DiagNote(SecondMessage->getBeginLoc(), SecondMessage->getSourceRange(),
1033 StaticAssertMessage);
1034 return true;
1035 }
1036 }
1037 break;
1038 }
1039
1040 case Field: {
1041 if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule,
1042 cast<FieldDecl>(FirstDecl),
1043 cast<FieldDecl>(SecondDecl)))
1044 return true;
1045 break;
1046 }
1047
1048 case CXXMethod: {
1049 enum {
1050 DiagMethod,
1051 DiagConstructor,
1052 DiagDestructor,
1053 } FirstMethodType,
1054 SecondMethodType;
1055 auto GetMethodTypeForDiagnostics = [](const CXXMethodDecl *D) {
1056 if (isa<CXXConstructorDecl>(D))
1057 return DiagConstructor;
1058 if (isa<CXXDestructorDecl>(D))
1059 return DiagDestructor;
1060 return DiagMethod;
1061 };
1062 const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl);
1063 const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl);
1064 FirstMethodType = GetMethodTypeForDiagnostics(FirstMethod);
1065 SecondMethodType = GetMethodTypeForDiagnostics(SecondMethod);
1066 DeclarationName FirstName = FirstMethod->getDeclName();
1067 DeclarationName SecondName = SecondMethod->getDeclName();
1068 auto DiagMethodError = [&DiagError, FirstMethod, FirstMethodType,
1069 FirstName](ODRCXXRecordDifference DiffType) {
1070 return DiagError(FirstMethod->getLocation(),
1071 FirstMethod->getSourceRange(), DiffType)
1072 << FirstMethodType << FirstName;
1073 };
1074 auto DiagMethodNote = [&DiagNote, SecondMethod, SecondMethodType,
1075 SecondName](ODRCXXRecordDifference DiffType) {
1076 return DiagNote(SecondMethod->getLocation(),
1077 SecondMethod->getSourceRange(), DiffType)
1078 << SecondMethodType << SecondName;
1079 };
1080
1081 if (FirstMethodType != SecondMethodType || FirstName != SecondName) {
1082 DiagMethodError(MethodName);
1083 DiagMethodNote(MethodName);
1084 return true;
1085 }
1086
1087 const bool FirstDeleted = FirstMethod->isDeletedAsWritten();
1088 const bool SecondDeleted = SecondMethod->isDeletedAsWritten();
1089 if (FirstDeleted != SecondDeleted) {
1090 DiagMethodError(MethodDeleted) << FirstDeleted;
1091 DiagMethodNote(MethodDeleted) << SecondDeleted;
1092 return true;
1093 }
1094
1095 const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted();
1096 const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted();
1097 if (FirstDefaulted != SecondDefaulted) {
1098 DiagMethodError(MethodDefaulted) << FirstDefaulted;
1099 DiagMethodNote(MethodDefaulted) << SecondDefaulted;
1100 return true;
1101 }
1102
1103 const bool FirstVirtual = FirstMethod->isVirtualAsWritten();
1104 const bool SecondVirtual = SecondMethod->isVirtualAsWritten();
1105 const bool FirstPure = FirstMethod->isPureVirtual();
1106 const bool SecondPure = SecondMethod->isPureVirtual();
1107 if ((FirstVirtual || SecondVirtual) &&
1108 (FirstVirtual != SecondVirtual || FirstPure != SecondPure)) {
1109 DiagMethodError(MethodVirtual) << FirstPure << FirstVirtual;
1110 DiagMethodNote(MethodVirtual) << SecondPure << SecondVirtual;
1111 return true;
1112 }
1113
1114 // CXXMethodDecl::isStatic uses the canonical Decl. With Decl merging,
1115 // FirstDecl is the canonical Decl of SecondDecl, so the storage
1116 // class needs to be checked instead.
1117 StorageClass FirstStorage = FirstMethod->getStorageClass();
1118 StorageClass SecondStorage = SecondMethod->getStorageClass();
1119 const bool FirstStatic = FirstStorage == SC_Static;
1120 const bool SecondStatic = SecondStorage == SC_Static;
1121 if (FirstStatic != SecondStatic) {
1122 DiagMethodError(MethodStatic) << FirstStatic;
1123 DiagMethodNote(MethodStatic) << SecondStatic;
1124 return true;
1125 }
1126
1127 const bool FirstVolatile = FirstMethod->isVolatile();
1128 const bool SecondVolatile = SecondMethod->isVolatile();
1129 if (FirstVolatile != SecondVolatile) {
1130 DiagMethodError(MethodVolatile) << FirstVolatile;
1131 DiagMethodNote(MethodVolatile) << SecondVolatile;
1132 return true;
1133 }
1134
1135 const bool FirstConst = FirstMethod->isConst();
1136 const bool SecondConst = SecondMethod->isConst();
1137 if (FirstConst != SecondConst) {
1138 DiagMethodError(MethodConst) << FirstConst;
1139 DiagMethodNote(MethodConst) << SecondConst;
1140 return true;
1141 }
1142
1143 const bool FirstInline = FirstMethod->isInlineSpecified();
1144 const bool SecondInline = SecondMethod->isInlineSpecified();
1145 if (FirstInline != SecondInline) {
1146 DiagMethodError(MethodInline) << FirstInline;
1147 DiagMethodNote(MethodInline) << SecondInline;
1148 return true;
1149 }
1150
1151 if (diagnoseSubMismatchMethodParameters(Diags, FirstRecord,
1152 FirstModule, SecondModule,
1153 FirstMethod, SecondMethod))
1154 return true;
1155
1156 for (unsigned I = 0, N = FirstMethod->param_size(); I < N; ++I) {
1157 const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);
1158 const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);
1159
1160 const Expr *FirstInit = FirstParam->getInit();
1161 const Expr *SecondInit = SecondParam->getInit();
1162 if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
1163 DiagMethodError(MethodParameterSingleDefaultArgument)
1164 << (I + 1) << (FirstInit == nullptr)
1165 << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
1166 DiagMethodNote(MethodParameterSingleDefaultArgument)
1167 << (I + 1) << (SecondInit == nullptr)
1168 << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
1169 return true;
1170 }
1171
1172 if (FirstInit && SecondInit &&
1173 computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
1174 DiagMethodError(MethodParameterDifferentDefaultArgument)
1175 << (I + 1) << FirstInit->getSourceRange();
1176 DiagMethodNote(MethodParameterDifferentDefaultArgument)
1177 << (I + 1) << SecondInit->getSourceRange();
1178 return true;
1179 }
1180 }
1181
1182 const TemplateArgumentList *FirstTemplateArgs =
1183 FirstMethod->getTemplateSpecializationArgs();
1184 const TemplateArgumentList *SecondTemplateArgs =
1185 SecondMethod->getTemplateSpecializationArgs();
1186
1187 if ((FirstTemplateArgs && !SecondTemplateArgs) ||
1188 (!FirstTemplateArgs && SecondTemplateArgs)) {
1189 DiagMethodError(MethodNoTemplateArguments)
1190 << (FirstTemplateArgs != nullptr);
1191 DiagMethodNote(MethodNoTemplateArguments)
1192 << (SecondTemplateArgs != nullptr);
1193 return true;
1194 }
1195
1196 if (FirstTemplateArgs && SecondTemplateArgs) {
1197 // Remove pack expansions from argument list.
1198 auto ExpandTemplateArgumentList = [](const TemplateArgumentList *TAL) {
1199 llvm::SmallVector<const TemplateArgument *, 8> ExpandedList;
1200 for (const TemplateArgument &TA : TAL->asArray()) {
1201 if (TA.getKind() != TemplateArgument::Pack) {
1202 ExpandedList.push_back(&TA);
1203 continue;
1204 }
1205 llvm::append_range(ExpandedList,
1206 llvm::make_pointer_range(TA.getPackAsArray()));
1207 }
1208 return ExpandedList;
1209 };
1210 llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList =
1211 ExpandTemplateArgumentList(FirstTemplateArgs);
1212 llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList =
1213 ExpandTemplateArgumentList(SecondTemplateArgs);
1214
1215 if (FirstExpandedList.size() != SecondExpandedList.size()) {
1216 DiagMethodError(MethodDifferentNumberTemplateArguments)
1217 << (unsigned)FirstExpandedList.size();
1218 DiagMethodNote(MethodDifferentNumberTemplateArguments)
1219 << (unsigned)SecondExpandedList.size();
1220 return true;
1221 }
1222
1223 for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) {
1224 const TemplateArgument &FirstTA = *FirstExpandedList[i],
1225 &SecondTA = *SecondExpandedList[i];
1226 if (computeODRHash(FirstTA) == computeODRHash(SecondTA))
1227 continue;
1228
1229 DiagMethodError(MethodDifferentTemplateArgument) << FirstTA << i + 1;
1230 DiagMethodNote(MethodDifferentTemplateArgument) << SecondTA << i + 1;
1231 return true;
1232 }
1233 }
1234
1235 // Compute the hash of the method as if it has no body.
1236 auto ComputeCXXMethodODRHash = [](const CXXMethodDecl *D) {
1237 ODRHash Hasher;
1238 Hasher.AddFunctionDecl(D, true /*SkipBody*/);
1239 return Hasher.CalculateHash();
1240 };
1241
1242 // Compare the hash generated to the hash stored. A difference means
1243 // that a body was present in the original source. Due to merging,
1244 // the standard way of detecting a body will not work.
1245 const bool HasFirstBody =
1246 ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash();
1247 const bool HasSecondBody =
1248 ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash();
1249
1250 if (HasFirstBody != HasSecondBody) {
1251 DiagMethodError(MethodSingleBody) << HasFirstBody;
1252 DiagMethodNote(MethodSingleBody) << HasSecondBody;
1253 return true;
1254 }
1255
1256 if (HasFirstBody && HasSecondBody) {
1257 DiagMethodError(MethodDifferentBody);
1258 DiagMethodNote(MethodDifferentBody);
1259 return true;
1260 }
1261
1262 break;
1263 }
1264
1265 case TypeAlias:
1266 case TypeDef: {
1267 if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule,
1268 cast<TypedefNameDecl>(FirstDecl),
1269 cast<TypedefNameDecl>(SecondDecl),
1270 FirstDiffType == TypeAlias))
1271 return true;
1272 break;
1273 }
1274 case Var: {
1275 if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,
1276 cast<VarDecl>(FirstDecl),
1277 cast<VarDecl>(SecondDecl)))
1278 return true;
1279 break;
1280 }
1281 case Friend: {
1282 const FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
1283 const FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);
1284
1285 const NamedDecl *FirstND = FirstFriend->getFriendDecl();
1286 const NamedDecl *SecondND = SecondFriend->getFriendDecl();
1287
1288 TypeSourceInfo *FirstTSI = FirstFriend->getFriendType();
1289 TypeSourceInfo *SecondTSI = SecondFriend->getFriendType();
1290
1291 if (FirstND && SecondND) {
1292 DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(),
1293 FriendFunction)
1294 << FirstND;
1295 DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(),
1296 FriendFunction)
1297 << SecondND;
1298 return true;
1299 }
1300
1301 if (FirstTSI && SecondTSI) {
1302 QualType FirstFriendType = FirstTSI->getType();
1303 QualType SecondFriendType = SecondTSI->getType();
1304 assert(computeODRHash(FirstFriendType) !=
1305 computeODRHash(SecondFriendType));
1306 DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(),
1307 FriendType)
1308 << FirstFriendType;
1309 DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(),
1310 FriendType)
1311 << SecondFriendType;
1312 return true;
1313 }
1314
1315 DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(),
1316 FriendTypeFunction)
1317 << (FirstTSI == nullptr);
1318 DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(),
1319 FriendTypeFunction)
1320 << (SecondTSI == nullptr);
1321 return true;
1322 }
1323 case FunctionTemplate: {
1324 const FunctionTemplateDecl *FirstTemplate =
1325 cast<FunctionTemplateDecl>(FirstDecl);
1326 const FunctionTemplateDecl *SecondTemplate =
1327 cast<FunctionTemplateDecl>(SecondDecl);
1328
1329 TemplateParameterList *FirstTPL = FirstTemplate->getTemplateParameters();
1330 TemplateParameterList *SecondTPL = SecondTemplate->getTemplateParameters();
1331
1332 auto DiagTemplateError = [&DiagError,
1333 FirstTemplate](ODRCXXRecordDifference DiffType) {
1334 return DiagError(FirstTemplate->getLocation(),
1335 FirstTemplate->getSourceRange(), DiffType)
1336 << FirstTemplate;
1337 };
1338 auto DiagTemplateNote = [&DiagNote,
1339 SecondTemplate](ODRCXXRecordDifference DiffType) {
1340 return DiagNote(SecondTemplate->getLocation(),
1341 SecondTemplate->getSourceRange(), DiffType)
1342 << SecondTemplate;
1343 };
1344
1345 if (FirstTPL->size() != SecondTPL->size()) {
1346 DiagTemplateError(FunctionTemplateDifferentNumberParameters)
1347 << FirstTPL->size();
1348 DiagTemplateNote(FunctionTemplateDifferentNumberParameters)
1349 << SecondTPL->size();
1350 return true;
1351 }
1352
1353 for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) {
1354 NamedDecl *FirstParam = FirstTPL->getParam(i);
1355 NamedDecl *SecondParam = SecondTPL->getParam(i);
1356
1357 if (FirstParam->getKind() != SecondParam->getKind()) {
1358 enum {
1359 TemplateTypeParameter,
1360 NonTypeTemplateParameter,
1361 TemplateTemplateParameter,
1362 };
1363 auto GetParamType = [](NamedDecl *D) {
1364 switch (D->getKind()) {
1365 default:
1366 llvm_unreachable("Unexpected template parameter type");
1367 case Decl::TemplateTypeParm:
1368 return TemplateTypeParameter;
1369 case Decl::NonTypeTemplateParm:
1370 return NonTypeTemplateParameter;
1371 case Decl::TemplateTemplateParm:
1372 return TemplateTemplateParameter;
1373 }
1374 };
1375
1376 DiagTemplateError(FunctionTemplateParameterDifferentKind)
1377 << (i + 1) << GetParamType(FirstParam);
1378 DiagTemplateNote(FunctionTemplateParameterDifferentKind)
1379 << (i + 1) << GetParamType(SecondParam);
1380 return true;
1381 }
1382
1383 if (FirstParam->getName() != SecondParam->getName()) {
1384 DiagTemplateError(FunctionTemplateParameterName)
1385 << (i + 1) << (bool)FirstParam->getIdentifier() << FirstParam;
1386 DiagTemplateNote(FunctionTemplateParameterName)
1387 << (i + 1) << (bool)SecondParam->getIdentifier() << SecondParam;
1388 return true;
1389 }
1390
1391 if (isa<TemplateTypeParmDecl>(FirstParam) &&
1392 isa<TemplateTypeParmDecl>(SecondParam)) {
1393 TemplateTypeParmDecl *FirstTTPD =
1394 cast<TemplateTypeParmDecl>(FirstParam);
1395 TemplateTypeParmDecl *SecondTTPD =
1396 cast<TemplateTypeParmDecl>(SecondParam);
1397 bool HasFirstDefaultArgument =
1398 FirstTTPD->hasDefaultArgument() &&
1399 !FirstTTPD->defaultArgumentWasInherited();
1400 bool HasSecondDefaultArgument =
1401 SecondTTPD->hasDefaultArgument() &&
1402 !SecondTTPD->defaultArgumentWasInherited();
1403 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
1404 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
1405 << (i + 1) << HasFirstDefaultArgument;
1406 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
1407 << (i + 1) << HasSecondDefaultArgument;
1408 return true;
1409 }
1410
1411 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
1412 TemplateArgument FirstTA =
1413 FirstTTPD->getDefaultArgument().getArgument();
1414 TemplateArgument SecondTA =
1415 SecondTTPD->getDefaultArgument().getArgument();
1416 if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) {
1417 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
1418 << (i + 1) << FirstTA;
1419 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
1420 << (i + 1) << SecondTA;
1421 return true;
1422 }
1423 }
1424
1425 if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) {
1426 DiagTemplateError(FunctionTemplatePackParameter)
1427 << (i + 1) << FirstTTPD->isParameterPack();
1428 DiagTemplateNote(FunctionTemplatePackParameter)
1429 << (i + 1) << SecondTTPD->isParameterPack();
1430 return true;
1431 }
1432 }
1433
1434 if (isa<TemplateTemplateParmDecl>(FirstParam) &&
1435 isa<TemplateTemplateParmDecl>(SecondParam)) {
1436 TemplateTemplateParmDecl *FirstTTPD =
1437 cast<TemplateTemplateParmDecl>(FirstParam);
1438 TemplateTemplateParmDecl *SecondTTPD =
1439 cast<TemplateTemplateParmDecl>(SecondParam);
1440
1441 TemplateParameterList *FirstTPL = FirstTTPD->getTemplateParameters();
1442 TemplateParameterList *SecondTPL = SecondTTPD->getTemplateParameters();
1443
1444 auto ComputeTemplateParameterListODRHash =
1445 [](const TemplateParameterList *TPL) {
1446 assert(TPL);
1447 ODRHash Hasher;
1448 Hasher.AddTemplateParameterList(TPL);
1449 return Hasher.CalculateHash();
1450 };
1451
1452 if (ComputeTemplateParameterListODRHash(FirstTPL) !=
1453 ComputeTemplateParameterListODRHash(SecondTPL)) {
1454 DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);
1455 DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);
1456 return true;
1457 }
1458
1459 bool HasFirstDefaultArgument =
1460 FirstTTPD->hasDefaultArgument() &&
1461 !FirstTTPD->defaultArgumentWasInherited();
1462 bool HasSecondDefaultArgument =
1463 SecondTTPD->hasDefaultArgument() &&
1464 !SecondTTPD->defaultArgumentWasInherited();
1465 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
1466 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
1467 << (i + 1) << HasFirstDefaultArgument;
1468 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
1469 << (i + 1) << HasSecondDefaultArgument;
1470 return true;
1471 }
1472
1473 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
1474 TemplateArgument FirstTA =
1475 FirstTTPD->getDefaultArgument().getArgument();
1476 TemplateArgument SecondTA =
1477 SecondTTPD->getDefaultArgument().getArgument();
1478 if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) {
1479 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
1480 << (i + 1) << FirstTA;
1481 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
1482 << (i + 1) << SecondTA;
1483 return true;
1484 }
1485 }
1486
1487 if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) {
1488 DiagTemplateError(FunctionTemplatePackParameter)
1489 << (i + 1) << FirstTTPD->isParameterPack();
1490 DiagTemplateNote(FunctionTemplatePackParameter)
1491 << (i + 1) << SecondTTPD->isParameterPack();
1492 return true;
1493 }
1494 }
1495
1496 if (isa<NonTypeTemplateParmDecl>(FirstParam) &&
1497 isa<NonTypeTemplateParmDecl>(SecondParam)) {
1498 NonTypeTemplateParmDecl *FirstNTTPD =
1499 cast<NonTypeTemplateParmDecl>(FirstParam);
1500 NonTypeTemplateParmDecl *SecondNTTPD =
1501 cast<NonTypeTemplateParmDecl>(SecondParam);
1502
1503 QualType FirstType = FirstNTTPD->getType();
1504 QualType SecondType = SecondNTTPD->getType();
1505 if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
1506 DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);
1507 DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);
1508 return true;
1509 }
1510
1511 bool HasFirstDefaultArgument =
1512 FirstNTTPD->hasDefaultArgument() &&
1513 !FirstNTTPD->defaultArgumentWasInherited();
1514 bool HasSecondDefaultArgument =
1515 SecondNTTPD->hasDefaultArgument() &&
1516 !SecondNTTPD->defaultArgumentWasInherited();
1517 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
1518 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
1519 << (i + 1) << HasFirstDefaultArgument;
1520 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
1521 << (i + 1) << HasSecondDefaultArgument;
1522 return true;
1523 }
1524
1525 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
1526 TemplateArgument FirstDefaultArgument =
1527 FirstNTTPD->getDefaultArgument().getArgument();
1528 TemplateArgument SecondDefaultArgument =
1529 SecondNTTPD->getDefaultArgument().getArgument();
1530
1531 if (computeODRHash(FirstDefaultArgument) !=
1532 computeODRHash(SecondDefaultArgument)) {
1533 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
1534 << (i + 1) << FirstDefaultArgument;
1535 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
1536 << (i + 1) << SecondDefaultArgument;
1537 return true;
1538 }
1539 }
1540
1541 if (FirstNTTPD->isParameterPack() != SecondNTTPD->isParameterPack()) {
1542 DiagTemplateError(FunctionTemplatePackParameter)
1543 << (i + 1) << FirstNTTPD->isParameterPack();
1544 DiagTemplateNote(FunctionTemplatePackParameter)
1545 << (i + 1) << SecondNTTPD->isParameterPack();
1546 return true;
1547 }
1548 }
1549 }
1550 break;
1551 }
1552 }
1553
1554 Diag(FirstDecl->getLocation(),
1555 diag::err_module_odr_violation_mismatch_decl_unknown)
1556 << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
1557 << FirstDecl->getSourceRange();
1558 Diag(SecondDecl->getLocation(),
1559 diag::note_module_odr_violation_mismatch_decl_unknown)
1560 << SecondModule.empty() << SecondModule << FirstDiffType
1561 << SecondDecl->getSourceRange();
1562 return true;
1563 }
1564
diagnoseMismatch(const RecordDecl * FirstRecord,const RecordDecl * SecondRecord) const1565 bool ODRDiagsEmitter::diagnoseMismatch(const RecordDecl *FirstRecord,
1566 const RecordDecl *SecondRecord) const {
1567 if (FirstRecord == SecondRecord)
1568 return false;
1569
1570 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord);
1571 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);
1572
1573 auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record,
1574 const DeclContext *DC) {
1575 for (const Decl *D : Record->decls()) {
1576 if (!ODRHash::isSubDeclToBeProcessed(D, DC))
1577 continue;
1578 Hashes.emplace_back(D, computeODRHash(D));
1579 }
1580 };
1581
1582 DeclHashes FirstHashes;
1583 DeclHashes SecondHashes;
1584 const DeclContext *DC = FirstRecord;
1585 PopulateHashes(FirstHashes, FirstRecord, DC);
1586 PopulateHashes(SecondHashes, SecondRecord, DC);
1587
1588 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
1589 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
1590 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
1591 const Decl *FirstDecl = DR.FirstDecl;
1592 const Decl *SecondDecl = DR.SecondDecl;
1593
1594 if (FirstDiffType == Other || SecondDiffType == Other) {
1595 diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
1596 SecondModule);
1597 return true;
1598 }
1599
1600 if (FirstDiffType != SecondDiffType) {
1601 diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule,
1602 SecondRecord, SecondModule);
1603 return true;
1604 }
1605
1606 assert(FirstDiffType == SecondDiffType);
1607 switch (FirstDiffType) {
1608 // Already handled.
1609 case EndOfClass:
1610 case Other:
1611 // C++ only, invalid in this context.
1612 case PublicSpecifer:
1613 case PrivateSpecifer:
1614 case ProtectedSpecifer:
1615 case StaticAssert:
1616 case CXXMethod:
1617 case TypeAlias:
1618 case Friend:
1619 case FunctionTemplate:
1620 // Cannot be contained by RecordDecl, invalid in this context.
1621 case ObjCMethod:
1622 case ObjCIvar:
1623 case ObjCProperty:
1624 llvm_unreachable("Invalid diff type");
1625
1626 case Field: {
1627 if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule,
1628 cast<FieldDecl>(FirstDecl),
1629 cast<FieldDecl>(SecondDecl)))
1630 return true;
1631 break;
1632 }
1633 case TypeDef: {
1634 if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule,
1635 cast<TypedefNameDecl>(FirstDecl),
1636 cast<TypedefNameDecl>(SecondDecl),
1637 /*IsTypeAlias=*/false))
1638 return true;
1639 break;
1640 }
1641 case Var: {
1642 if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,
1643 cast<VarDecl>(FirstDecl),
1644 cast<VarDecl>(SecondDecl)))
1645 return true;
1646 break;
1647 }
1648 }
1649
1650 Diag(FirstDecl->getLocation(),
1651 diag::err_module_odr_violation_mismatch_decl_unknown)
1652 << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
1653 << FirstDecl->getSourceRange();
1654 Diag(SecondDecl->getLocation(),
1655 diag::note_module_odr_violation_mismatch_decl_unknown)
1656 << SecondModule.empty() << SecondModule << FirstDiffType
1657 << SecondDecl->getSourceRange();
1658 return true;
1659 }
1660
diagnoseMismatch(const FunctionDecl * FirstFunction,const FunctionDecl * SecondFunction) const1661 bool ODRDiagsEmitter::diagnoseMismatch(
1662 const FunctionDecl *FirstFunction,
1663 const FunctionDecl *SecondFunction) const {
1664 if (FirstFunction == SecondFunction)
1665 return false;
1666
1667 // Keep in sync with select options in err_module_odr_violation_function.
1668 enum ODRFunctionDifference {
1669 ReturnType,
1670 ParameterName,
1671 ParameterType,
1672 ParameterSingleDefaultArgument,
1673 ParameterDifferentDefaultArgument,
1674 FunctionBody,
1675 };
1676
1677 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction);
1678 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondFunction);
1679
1680 auto DiagError = [FirstFunction, &FirstModule,
1681 this](SourceLocation Loc, SourceRange Range,
1682 ODRFunctionDifference DiffType) {
1683 return Diag(Loc, diag::err_module_odr_violation_function)
1684 << FirstFunction << FirstModule.empty() << FirstModule << Range
1685 << DiffType;
1686 };
1687 auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
1688 ODRFunctionDifference DiffType) {
1689 return Diag(Loc, diag::note_module_odr_violation_function)
1690 << SecondModule << Range << DiffType;
1691 };
1692
1693 if (computeODRHash(FirstFunction->getReturnType()) !=
1694 computeODRHash(SecondFunction->getReturnType())) {
1695 DiagError(FirstFunction->getReturnTypeSourceRange().getBegin(),
1696 FirstFunction->getReturnTypeSourceRange(), ReturnType)
1697 << FirstFunction->getReturnType();
1698 DiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(),
1699 SecondFunction->getReturnTypeSourceRange(), ReturnType)
1700 << SecondFunction->getReturnType();
1701 return true;
1702 }
1703
1704 assert(FirstFunction->param_size() == SecondFunction->param_size() &&
1705 "Merged functions with different number of parameters");
1706
1707 size_t ParamSize = FirstFunction->param_size();
1708 for (unsigned I = 0; I < ParamSize; ++I) {
1709 const ParmVarDecl *FirstParam = FirstFunction->getParamDecl(I);
1710 const ParmVarDecl *SecondParam = SecondFunction->getParamDecl(I);
1711
1712 assert(Context.hasSameType(FirstParam->getType(), SecondParam->getType()) &&
1713 "Merged function has different parameter types.");
1714
1715 if (FirstParam->getDeclName() != SecondParam->getDeclName()) {
1716 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1717 ParameterName)
1718 << I + 1 << FirstParam->getDeclName();
1719 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1720 ParameterName)
1721 << I + 1 << SecondParam->getDeclName();
1722 return true;
1723 };
1724
1725 QualType FirstParamType = FirstParam->getType();
1726 QualType SecondParamType = SecondParam->getType();
1727 if (FirstParamType != SecondParamType &&
1728 computeODRHash(FirstParamType) != computeODRHash(SecondParamType)) {
1729 if (const DecayedType *ParamDecayedType =
1730 FirstParamType->getAs<DecayedType>()) {
1731 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1732 ParameterType)
1733 << (I + 1) << FirstParamType << true
1734 << ParamDecayedType->getOriginalType();
1735 } else {
1736 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1737 ParameterType)
1738 << (I + 1) << FirstParamType << false;
1739 }
1740
1741 if (const DecayedType *ParamDecayedType =
1742 SecondParamType->getAs<DecayedType>()) {
1743 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1744 ParameterType)
1745 << (I + 1) << SecondParamType << true
1746 << ParamDecayedType->getOriginalType();
1747 } else {
1748 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1749 ParameterType)
1750 << (I + 1) << SecondParamType << false;
1751 }
1752 return true;
1753 }
1754
1755 // Note, these calls can trigger deserialization.
1756 const Expr *FirstInit = FirstParam->getInit();
1757 const Expr *SecondInit = SecondParam->getInit();
1758 if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
1759 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1760 ParameterSingleDefaultArgument)
1761 << (I + 1) << (FirstInit == nullptr)
1762 << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
1763 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1764 ParameterSingleDefaultArgument)
1765 << (I + 1) << (SecondInit == nullptr)
1766 << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
1767 return true;
1768 }
1769
1770 if (FirstInit && SecondInit &&
1771 computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
1772 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1773 ParameterDifferentDefaultArgument)
1774 << (I + 1) << FirstInit->getSourceRange();
1775 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1776 ParameterDifferentDefaultArgument)
1777 << (I + 1) << SecondInit->getSourceRange();
1778 return true;
1779 }
1780
1781 assert(computeODRHash(FirstParam) == computeODRHash(SecondParam) &&
1782 "Undiagnosed parameter difference.");
1783 }
1784
1785 // If no error has been generated before now, assume the problem is in
1786 // the body and generate a message.
1787 DiagError(FirstFunction->getLocation(), FirstFunction->getSourceRange(),
1788 FunctionBody);
1789 DiagNote(SecondFunction->getLocation(), SecondFunction->getSourceRange(),
1790 FunctionBody);
1791 return true;
1792 }
1793
diagnoseMismatch(const EnumDecl * FirstEnum,const EnumDecl * SecondEnum) const1794 bool ODRDiagsEmitter::diagnoseMismatch(const EnumDecl *FirstEnum,
1795 const EnumDecl *SecondEnum) const {
1796 if (FirstEnum == SecondEnum)
1797 return false;
1798
1799 // Keep in sync with select options in err_module_odr_violation_enum.
1800 enum ODREnumDifference {
1801 SingleScopedEnum,
1802 EnumTagKeywordMismatch,
1803 SingleSpecifiedType,
1804 DifferentSpecifiedTypes,
1805 DifferentNumberEnumConstants,
1806 EnumConstantName,
1807 EnumConstantSingleInitializer,
1808 EnumConstantDifferentInitializer,
1809 };
1810
1811 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum);
1812 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondEnum);
1813
1814 auto DiagError = [FirstEnum, &FirstModule, this](const auto *DiagAnchor,
1815 ODREnumDifference DiffType) {
1816 return Diag(DiagAnchor->getLocation(), diag::err_module_odr_violation_enum)
1817 << FirstEnum << FirstModule.empty() << FirstModule
1818 << DiagAnchor->getSourceRange() << DiffType;
1819 };
1820 auto DiagNote = [&SecondModule, this](const auto *DiagAnchor,
1821 ODREnumDifference DiffType) {
1822 return Diag(DiagAnchor->getLocation(), diag::note_module_odr_violation_enum)
1823 << SecondModule << DiagAnchor->getSourceRange() << DiffType;
1824 };
1825
1826 if (FirstEnum->isScoped() != SecondEnum->isScoped()) {
1827 DiagError(FirstEnum, SingleScopedEnum) << FirstEnum->isScoped();
1828 DiagNote(SecondEnum, SingleScopedEnum) << SecondEnum->isScoped();
1829 return true;
1830 }
1831
1832 if (FirstEnum->isScoped() && SecondEnum->isScoped()) {
1833 if (FirstEnum->isScopedUsingClassTag() !=
1834 SecondEnum->isScopedUsingClassTag()) {
1835 DiagError(FirstEnum, EnumTagKeywordMismatch)
1836 << FirstEnum->isScopedUsingClassTag();
1837 DiagNote(SecondEnum, EnumTagKeywordMismatch)
1838 << SecondEnum->isScopedUsingClassTag();
1839 return true;
1840 }
1841 }
1842
1843 QualType FirstUnderlyingType =
1844 FirstEnum->getIntegerTypeSourceInfo()
1845 ? FirstEnum->getIntegerTypeSourceInfo()->getType()
1846 : QualType();
1847 QualType SecondUnderlyingType =
1848 SecondEnum->getIntegerTypeSourceInfo()
1849 ? SecondEnum->getIntegerTypeSourceInfo()->getType()
1850 : QualType();
1851 if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) {
1852 DiagError(FirstEnum, SingleSpecifiedType) << !FirstUnderlyingType.isNull();
1853 DiagNote(SecondEnum, SingleSpecifiedType) << !SecondUnderlyingType.isNull();
1854 return true;
1855 }
1856
1857 if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {
1858 if (computeODRHash(FirstUnderlyingType) !=
1859 computeODRHash(SecondUnderlyingType)) {
1860 DiagError(FirstEnum, DifferentSpecifiedTypes) << FirstUnderlyingType;
1861 DiagNote(SecondEnum, DifferentSpecifiedTypes) << SecondUnderlyingType;
1862 return true;
1863 }
1864 }
1865
1866 // Compare enum constants.
1867 using DeclHashes =
1868 llvm::SmallVector<std::pair<const EnumConstantDecl *, unsigned>, 4>;
1869 auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, const EnumDecl *Enum) {
1870 for (const Decl *D : Enum->decls()) {
1871 // Due to decl merging, the first EnumDecl is the parent of
1872 // Decls in both records.
1873 if (!ODRHash::isSubDeclToBeProcessed(D, FirstEnum))
1874 continue;
1875 assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind");
1876 Hashes.emplace_back(cast<EnumConstantDecl>(D), computeODRHash(D));
1877 }
1878 };
1879 DeclHashes FirstHashes;
1880 PopulateHashes(FirstHashes, FirstEnum);
1881 DeclHashes SecondHashes;
1882 PopulateHashes(SecondHashes, SecondEnum);
1883
1884 if (FirstHashes.size() != SecondHashes.size()) {
1885 DiagError(FirstEnum, DifferentNumberEnumConstants)
1886 << (int)FirstHashes.size();
1887 DiagNote(SecondEnum, DifferentNumberEnumConstants)
1888 << (int)SecondHashes.size();
1889 return true;
1890 }
1891
1892 for (unsigned I = 0, N = FirstHashes.size(); I < N; ++I) {
1893 if (FirstHashes[I].second == SecondHashes[I].second)
1894 continue;
1895 const EnumConstantDecl *FirstConstant = FirstHashes[I].first;
1896 const EnumConstantDecl *SecondConstant = SecondHashes[I].first;
1897
1898 if (FirstConstant->getDeclName() != SecondConstant->getDeclName()) {
1899 DiagError(FirstConstant, EnumConstantName) << I + 1 << FirstConstant;
1900 DiagNote(SecondConstant, EnumConstantName) << I + 1 << SecondConstant;
1901 return true;
1902 }
1903
1904 const Expr *FirstInit = FirstConstant->getInitExpr();
1905 const Expr *SecondInit = SecondConstant->getInitExpr();
1906 if (!FirstInit && !SecondInit)
1907 continue;
1908
1909 if (!FirstInit || !SecondInit) {
1910 DiagError(FirstConstant, EnumConstantSingleInitializer)
1911 << I + 1 << FirstConstant << (FirstInit != nullptr);
1912 DiagNote(SecondConstant, EnumConstantSingleInitializer)
1913 << I + 1 << SecondConstant << (SecondInit != nullptr);
1914 return true;
1915 }
1916
1917 if (computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
1918 DiagError(FirstConstant, EnumConstantDifferentInitializer)
1919 << I + 1 << FirstConstant;
1920 DiagNote(SecondConstant, EnumConstantDifferentInitializer)
1921 << I + 1 << SecondConstant;
1922 return true;
1923 }
1924 }
1925 return false;
1926 }
1927
diagnoseMismatch(const ObjCInterfaceDecl * FirstID,const ObjCInterfaceDecl * SecondID,const struct ObjCInterfaceDecl::DefinitionData * SecondDD) const1928 bool ODRDiagsEmitter::diagnoseMismatch(
1929 const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID,
1930 const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const {
1931 // Multiple different declarations got merged together; tell the user
1932 // where they came from.
1933 if (FirstID == SecondID)
1934 return false;
1935
1936 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstID);
1937 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondID);
1938
1939 // Keep in sync with err_module_odr_violation_objc_interface.
1940 enum ODRInterfaceDifference {
1941 SuperClassType,
1942 IVarAccess,
1943 };
1944
1945 auto DiagError = [FirstID, &FirstModule,
1946 this](SourceLocation Loc, SourceRange Range,
1947 ODRInterfaceDifference DiffType) {
1948 return Diag(Loc, diag::err_module_odr_violation_objc_interface)
1949 << FirstID << FirstModule.empty() << FirstModule << Range
1950 << DiffType;
1951 };
1952 auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
1953 ODRInterfaceDifference DiffType) {
1954 return Diag(Loc, diag::note_module_odr_violation_objc_interface)
1955 << SecondModule.empty() << SecondModule << Range << DiffType;
1956 };
1957
1958 const struct ObjCInterfaceDecl::DefinitionData *FirstDD = &FirstID->data();
1959 assert(FirstDD && SecondDD && "Definitions without DefinitionData");
1960 if (FirstDD != SecondDD) {
1961 // Check for matching super class.
1962 auto GetSuperClassSourceRange = [](const TypeSourceInfo *SuperInfo,
1963 const ObjCInterfaceDecl *ID) {
1964 if (!SuperInfo)
1965 return ID->getSourceRange();
1966 TypeLoc Loc = SuperInfo->getTypeLoc();
1967 return SourceRange(Loc.getBeginLoc(), Loc.getEndLoc());
1968 };
1969
1970 ObjCInterfaceDecl *FirstSuperClass = FirstID->getSuperClass();
1971 ObjCInterfaceDecl *SecondSuperClass = nullptr;
1972 const TypeSourceInfo *FirstSuperInfo = FirstID->getSuperClassTInfo();
1973 const TypeSourceInfo *SecondSuperInfo = SecondDD->SuperClassTInfo;
1974 if (SecondSuperInfo)
1975 SecondSuperClass =
1976 SecondSuperInfo->getType()->castAs<ObjCObjectType>()->getInterface();
1977
1978 if ((FirstSuperClass && SecondSuperClass &&
1979 FirstSuperClass->getODRHash() != SecondSuperClass->getODRHash()) ||
1980 (FirstSuperClass && !SecondSuperClass) ||
1981 (!FirstSuperClass && SecondSuperClass)) {
1982 QualType FirstType;
1983 if (FirstSuperInfo)
1984 FirstType = FirstSuperInfo->getType();
1985
1986 DiagError(FirstID->getLocation(),
1987 GetSuperClassSourceRange(FirstSuperInfo, FirstID),
1988 SuperClassType)
1989 << (bool)FirstSuperInfo << FirstType;
1990
1991 QualType SecondType;
1992 if (SecondSuperInfo)
1993 SecondType = SecondSuperInfo->getType();
1994
1995 DiagNote(SecondID->getLocation(),
1996 GetSuperClassSourceRange(SecondSuperInfo, SecondID),
1997 SuperClassType)
1998 << (bool)SecondSuperInfo << SecondType;
1999 return true;
2000 }
2001
2002 // Check both interfaces reference the same protocols.
2003 auto &FirstProtos = FirstID->getReferencedProtocols();
2004 auto &SecondProtos = SecondDD->ReferencedProtocols;
2005 if (diagnoseSubMismatchProtocols(FirstProtos, FirstID, FirstModule,
2006 SecondProtos, SecondID, SecondModule))
2007 return true;
2008 }
2009
2010 auto PopulateHashes = [](DeclHashes &Hashes, const ObjCInterfaceDecl *ID,
2011 const DeclContext *DC) {
2012 for (auto *D : ID->decls()) {
2013 if (!ODRHash::isSubDeclToBeProcessed(D, DC))
2014 continue;
2015 Hashes.emplace_back(D, computeODRHash(D));
2016 }
2017 };
2018
2019 DeclHashes FirstHashes;
2020 DeclHashes SecondHashes;
2021 // Use definition as DeclContext because definitions are merged when
2022 // DeclContexts are merged and separate when DeclContexts are separate.
2023 PopulateHashes(FirstHashes, FirstID, FirstID->getDefinition());
2024 PopulateHashes(SecondHashes, SecondID, SecondID->getDefinition());
2025
2026 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
2027 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
2028 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
2029 const Decl *FirstDecl = DR.FirstDecl;
2030 const Decl *SecondDecl = DR.SecondDecl;
2031
2032 if (FirstDiffType == Other || SecondDiffType == Other) {
2033 diagnoseSubMismatchUnexpected(DR, FirstID, FirstModule, SecondID,
2034 SecondModule);
2035 return true;
2036 }
2037
2038 if (FirstDiffType != SecondDiffType) {
2039 diagnoseSubMismatchDifferentDeclKinds(DR, FirstID, FirstModule, SecondID,
2040 SecondModule);
2041 return true;
2042 }
2043
2044 assert(FirstDiffType == SecondDiffType);
2045 switch (FirstDiffType) {
2046 // Already handled.
2047 case EndOfClass:
2048 case Other:
2049 // Cannot be contained by ObjCInterfaceDecl, invalid in this context.
2050 case Field:
2051 case TypeDef:
2052 case Var:
2053 // C++ only, invalid in this context.
2054 case PublicSpecifer:
2055 case PrivateSpecifer:
2056 case ProtectedSpecifer:
2057 case StaticAssert:
2058 case CXXMethod:
2059 case TypeAlias:
2060 case Friend:
2061 case FunctionTemplate:
2062 llvm_unreachable("Invalid diff type");
2063
2064 case ObjCMethod: {
2065 if (diagnoseSubMismatchObjCMethod(FirstID, FirstModule, SecondModule,
2066 cast<ObjCMethodDecl>(FirstDecl),
2067 cast<ObjCMethodDecl>(SecondDecl)))
2068 return true;
2069 break;
2070 }
2071 case ObjCIvar: {
2072 if (diagnoseSubMismatchField(FirstID, FirstModule, SecondModule,
2073 cast<FieldDecl>(FirstDecl),
2074 cast<FieldDecl>(SecondDecl)))
2075 return true;
2076
2077 // Check if the access match.
2078 const ObjCIvarDecl *FirstIvar = cast<ObjCIvarDecl>(FirstDecl);
2079 const ObjCIvarDecl *SecondIvar = cast<ObjCIvarDecl>(SecondDecl);
2080 if (FirstIvar->getCanonicalAccessControl() !=
2081 SecondIvar->getCanonicalAccessControl()) {
2082 DiagError(FirstIvar->getLocation(), FirstIvar->getSourceRange(),
2083 IVarAccess)
2084 << FirstIvar->getName()
2085 << (int)FirstIvar->getCanonicalAccessControl();
2086 DiagNote(SecondIvar->getLocation(), SecondIvar->getSourceRange(),
2087 IVarAccess)
2088 << SecondIvar->getName()
2089 << (int)SecondIvar->getCanonicalAccessControl();
2090 return true;
2091 }
2092 break;
2093 }
2094 case ObjCProperty: {
2095 if (diagnoseSubMismatchObjCProperty(FirstID, FirstModule, SecondModule,
2096 cast<ObjCPropertyDecl>(FirstDecl),
2097 cast<ObjCPropertyDecl>(SecondDecl)))
2098 return true;
2099 break;
2100 }
2101 }
2102
2103 Diag(FirstDecl->getLocation(),
2104 diag::err_module_odr_violation_mismatch_decl_unknown)
2105 << FirstID << FirstModule.empty() << FirstModule << FirstDiffType
2106 << FirstDecl->getSourceRange();
2107 Diag(SecondDecl->getLocation(),
2108 diag::note_module_odr_violation_mismatch_decl_unknown)
2109 << SecondModule.empty() << SecondModule << FirstDiffType
2110 << SecondDecl->getSourceRange();
2111 return true;
2112 }
2113
diagnoseMismatch(const ObjCProtocolDecl * FirstProtocol,const ObjCProtocolDecl * SecondProtocol,const struct ObjCProtocolDecl::DefinitionData * SecondDD) const2114 bool ODRDiagsEmitter::diagnoseMismatch(
2115 const ObjCProtocolDecl *FirstProtocol,
2116 const ObjCProtocolDecl *SecondProtocol,
2117 const struct ObjCProtocolDecl::DefinitionData *SecondDD) const {
2118 if (FirstProtocol == SecondProtocol)
2119 return false;
2120
2121 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstProtocol);
2122 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondProtocol);
2123
2124 const ObjCProtocolDecl::DefinitionData *FirstDD = &FirstProtocol->data();
2125 assert(FirstDD && SecondDD && "Definitions without DefinitionData");
2126 // Diagnostics from ObjCProtocol DefinitionData are emitted here.
2127 if (FirstDD != SecondDD) {
2128 // Check both protocols reference the same protocols.
2129 const ObjCProtocolList &FirstProtocols =
2130 FirstProtocol->getReferencedProtocols();
2131 const ObjCProtocolList &SecondProtocols = SecondDD->ReferencedProtocols;
2132 if (diagnoseSubMismatchProtocols(FirstProtocols, FirstProtocol, FirstModule,
2133 SecondProtocols, SecondProtocol,
2134 SecondModule))
2135 return true;
2136 }
2137
2138 auto PopulateHashes = [](DeclHashes &Hashes, const ObjCProtocolDecl *ID,
2139 const DeclContext *DC) {
2140 for (const Decl *D : ID->decls()) {
2141 if (!ODRHash::isSubDeclToBeProcessed(D, DC))
2142 continue;
2143 Hashes.emplace_back(D, computeODRHash(D));
2144 }
2145 };
2146
2147 DeclHashes FirstHashes;
2148 DeclHashes SecondHashes;
2149 // Use definition as DeclContext because definitions are merged when
2150 // DeclContexts are merged and separate when DeclContexts are separate.
2151 PopulateHashes(FirstHashes, FirstProtocol, FirstProtocol->getDefinition());
2152 PopulateHashes(SecondHashes, SecondProtocol, SecondProtocol->getDefinition());
2153
2154 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
2155 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
2156 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
2157 const Decl *FirstDecl = DR.FirstDecl;
2158 const Decl *SecondDecl = DR.SecondDecl;
2159
2160 if (FirstDiffType == Other || SecondDiffType == Other) {
2161 diagnoseSubMismatchUnexpected(DR, FirstProtocol, FirstModule,
2162 SecondProtocol, SecondModule);
2163 return true;
2164 }
2165
2166 if (FirstDiffType != SecondDiffType) {
2167 diagnoseSubMismatchDifferentDeclKinds(DR, FirstProtocol, FirstModule,
2168 SecondProtocol, SecondModule);
2169 return true;
2170 }
2171
2172 assert(FirstDiffType == SecondDiffType);
2173 switch (FirstDiffType) {
2174 // Already handled.
2175 case EndOfClass:
2176 case Other:
2177 // Cannot be contained by ObjCProtocolDecl, invalid in this context.
2178 case Field:
2179 case TypeDef:
2180 case Var:
2181 case ObjCIvar:
2182 // C++ only, invalid in this context.
2183 case PublicSpecifer:
2184 case PrivateSpecifer:
2185 case ProtectedSpecifer:
2186 case StaticAssert:
2187 case CXXMethod:
2188 case TypeAlias:
2189 case Friend:
2190 case FunctionTemplate:
2191 llvm_unreachable("Invalid diff type");
2192 case ObjCMethod: {
2193 if (diagnoseSubMismatchObjCMethod(FirstProtocol, FirstModule, SecondModule,
2194 cast<ObjCMethodDecl>(FirstDecl),
2195 cast<ObjCMethodDecl>(SecondDecl)))
2196 return true;
2197 break;
2198 }
2199 case ObjCProperty: {
2200 if (diagnoseSubMismatchObjCProperty(FirstProtocol, FirstModule,
2201 SecondModule,
2202 cast<ObjCPropertyDecl>(FirstDecl),
2203 cast<ObjCPropertyDecl>(SecondDecl)))
2204 return true;
2205 break;
2206 }
2207 }
2208
2209 Diag(FirstDecl->getLocation(),
2210 diag::err_module_odr_violation_mismatch_decl_unknown)
2211 << FirstProtocol << FirstModule.empty() << FirstModule << FirstDiffType
2212 << FirstDecl->getSourceRange();
2213 Diag(SecondDecl->getLocation(),
2214 diag::note_module_odr_violation_mismatch_decl_unknown)
2215 << SecondModule.empty() << SecondModule << FirstDiffType
2216 << SecondDecl->getSourceRange();
2217 return true;
2218 }
2219