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
16using namespace clang;
17
18static unsigned computeODRHash(QualType Ty) {
19 ODRHash Hasher;
20 Hasher.AddQualType(T: Ty);
21 return Hasher.CalculateHash();
22}
23
24static unsigned computeODRHash(const Stmt *S) {
25 ODRHash Hasher;
26 Hasher.AddStmt(S);
27 return Hasher.CalculateHash();
28}
29
30static unsigned computeODRHash(const Decl *D) {
31 assert(D);
32 ODRHash Hasher;
33 Hasher.AddSubDecl(D);
34 return Hasher.CalculateHash();
35}
36
37static unsigned computeODRHash(const TemplateArgument &TA) {
38 ODRHash Hasher;
39 Hasher.AddTemplateArgument(TA);
40 return Hasher.CalculateHash();
41}
42
43std::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
52template <typename MethodT>
53static 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>(Val: D))
66 return DiagConstructor;
67 if (isa<CXXDestructorDecl>(Val: 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(Ty: FirstParamType) != computeODRHash(Ty: 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
144bool 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(Ty: FirstType) != computeODRHash(Ty: 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(TA: FirstField->getBitWidth());
199 unsigned SecondBitWidthHash = computeODRHash(TA: 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
246bool 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(Ty: FirstType) != computeODRHash(Ty: SecondType)) {
279 DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType;
280 DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType;
281 return true;
282 }
283 return false;
284}
285
286bool 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(Ty: FirstType) != computeODRHash(Ty: 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
361bool 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(x: 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
420bool 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(Ty: FirstMethod->getReturnType()) !=
449 computeODRHash(Ty: 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(E: FirstMethod->getImplementationControl());
466 DiagNote(ControlLevel) << llvm::to_underlying(
467 E: 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, FirstContainer: 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
504bool 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(Ty: FirstProp->getType()) !=
536 computeODRHash(Ty: 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
580ODRDiagsEmitter::DiffResult
581ODRDiagsEmitter::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
650void ODRDiagsEmitter::diagnoseSubMismatchUnexpected(
651 DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule,
652 const NamedDecl *SecondRecord, StringRef SecondModule) const {
653 Diag(Loc: FirstRecord->getLocation(),
654 diag::DiagID: err_module_odr_violation_different_definitions)
655 << FirstRecord << FirstModule.empty() << FirstModule;
656
657 if (DR.FirstDecl) {
658 Diag(Loc: DR.FirstDecl->getLocation(), diag::DiagID: note_first_module_difference)
659 << FirstRecord << DR.FirstDecl->getSourceRange();
660 }
661
662 Diag(Loc: SecondRecord->getLocation(),
663 diag::DiagID: 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
672void 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>(Val: Container))
681 Loc = Tag->getBraceRange().getEnd();
682 else if (auto *IF = dyn_cast<ObjCInterfaceDecl>(Val: 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(x&: Loc, y&: 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
706bool 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(Ty: FirstBase.getType()) !=
783 computeODRHash(Ty: 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>(Val: FirstDecl);
985 const StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(Val: 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>(Val: FirstDecl),
1043 cast<FieldDecl>(Val: 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>(Val: D))
1057 return DiagConstructor;
1058 if (isa<CXXDestructorDecl>(Val: D))
1059 return DiagDestructor;
1060 return DiagMethod;
1061 };
1062 const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(Val: FirstDecl);
1063 const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(Val: 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(Elt: &TA);
1203 continue;
1204 }
1205 llvm::append_range(C&: ExpandedList,
1206 R: llvm::make_pointer_range(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(TA: FirstTA) == computeODRHash(TA: 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>(Val: FirstDecl),
1269 cast<TypedefNameDecl>(Val: SecondDecl),
1270 FirstDiffType == TypeAlias))
1271 return true;
1272 break;
1273 }
1274 case Var: {
1275 if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,
1276 cast<VarDecl>(Val: FirstDecl),
1277 cast<VarDecl>(Val: SecondDecl)))
1278 return true;
1279 break;
1280 }
1281 case Friend: {
1282 const FriendDecl *FirstFriend = cast<FriendDecl>(Val: FirstDecl);
1283 const FriendDecl *SecondFriend = cast<FriendDecl>(Val: 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>(Val: FirstDecl);
1326 const FunctionTemplateDecl *SecondTemplate =
1327 cast<FunctionTemplateDecl>(Val: 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(Idx: i);
1355 NamedDecl *SecondParam = SecondTPL->getParam(Idx: 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>(Val: FirstParam) &&
1392 isa<TemplateTypeParmDecl>(Val: SecondParam)) {
1393 TemplateTypeParmDecl *FirstTTPD =
1394 cast<TemplateTypeParmDecl>(Val: FirstParam);
1395 TemplateTypeParmDecl *SecondTTPD =
1396 cast<TemplateTypeParmDecl>(Val: 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 QualType FirstType = FirstTTPD->getDefaultArgument();
1413 QualType SecondType = SecondTTPD->getDefaultArgument();
1414 if (computeODRHash(Ty: FirstType) != computeODRHash(Ty: SecondType)) {
1415 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
1416 << (i + 1) << FirstType;
1417 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
1418 << (i + 1) << SecondType;
1419 return true;
1420 }
1421 }
1422
1423 if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) {
1424 DiagTemplateError(FunctionTemplatePackParameter)
1425 << (i + 1) << FirstTTPD->isParameterPack();
1426 DiagTemplateNote(FunctionTemplatePackParameter)
1427 << (i + 1) << SecondTTPD->isParameterPack();
1428 return true;
1429 }
1430 }
1431
1432 if (isa<TemplateTemplateParmDecl>(Val: FirstParam) &&
1433 isa<TemplateTemplateParmDecl>(Val: SecondParam)) {
1434 TemplateTemplateParmDecl *FirstTTPD =
1435 cast<TemplateTemplateParmDecl>(Val: FirstParam);
1436 TemplateTemplateParmDecl *SecondTTPD =
1437 cast<TemplateTemplateParmDecl>(Val: SecondParam);
1438
1439 TemplateParameterList *FirstTPL = FirstTTPD->getTemplateParameters();
1440 TemplateParameterList *SecondTPL = SecondTTPD->getTemplateParameters();
1441
1442 auto ComputeTemplateParameterListODRHash =
1443 [](const TemplateParameterList *TPL) {
1444 assert(TPL);
1445 ODRHash Hasher;
1446 Hasher.AddTemplateParameterList(TPL);
1447 return Hasher.CalculateHash();
1448 };
1449
1450 if (ComputeTemplateParameterListODRHash(FirstTPL) !=
1451 ComputeTemplateParameterListODRHash(SecondTPL)) {
1452 DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);
1453 DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);
1454 return true;
1455 }
1456
1457 bool HasFirstDefaultArgument =
1458 FirstTTPD->hasDefaultArgument() &&
1459 !FirstTTPD->defaultArgumentWasInherited();
1460 bool HasSecondDefaultArgument =
1461 SecondTTPD->hasDefaultArgument() &&
1462 !SecondTTPD->defaultArgumentWasInherited();
1463 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
1464 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
1465 << (i + 1) << HasFirstDefaultArgument;
1466 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
1467 << (i + 1) << HasSecondDefaultArgument;
1468 return true;
1469 }
1470
1471 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
1472 TemplateArgument FirstTA =
1473 FirstTTPD->getDefaultArgument().getArgument();
1474 TemplateArgument SecondTA =
1475 SecondTTPD->getDefaultArgument().getArgument();
1476 if (computeODRHash(TA: FirstTA) != computeODRHash(TA: SecondTA)) {
1477 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
1478 << (i + 1) << FirstTA;
1479 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
1480 << (i + 1) << SecondTA;
1481 return true;
1482 }
1483 }
1484
1485 if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) {
1486 DiagTemplateError(FunctionTemplatePackParameter)
1487 << (i + 1) << FirstTTPD->isParameterPack();
1488 DiagTemplateNote(FunctionTemplatePackParameter)
1489 << (i + 1) << SecondTTPD->isParameterPack();
1490 return true;
1491 }
1492 }
1493
1494 if (isa<NonTypeTemplateParmDecl>(Val: FirstParam) &&
1495 isa<NonTypeTemplateParmDecl>(Val: SecondParam)) {
1496 NonTypeTemplateParmDecl *FirstNTTPD =
1497 cast<NonTypeTemplateParmDecl>(Val: FirstParam);
1498 NonTypeTemplateParmDecl *SecondNTTPD =
1499 cast<NonTypeTemplateParmDecl>(Val: SecondParam);
1500
1501 QualType FirstType = FirstNTTPD->getType();
1502 QualType SecondType = SecondNTTPD->getType();
1503 if (computeODRHash(Ty: FirstType) != computeODRHash(Ty: SecondType)) {
1504 DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);
1505 DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);
1506 return true;
1507 }
1508
1509 bool HasFirstDefaultArgument =
1510 FirstNTTPD->hasDefaultArgument() &&
1511 !FirstNTTPD->defaultArgumentWasInherited();
1512 bool HasSecondDefaultArgument =
1513 SecondNTTPD->hasDefaultArgument() &&
1514 !SecondNTTPD->defaultArgumentWasInherited();
1515 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
1516 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
1517 << (i + 1) << HasFirstDefaultArgument;
1518 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
1519 << (i + 1) << HasSecondDefaultArgument;
1520 return true;
1521 }
1522
1523 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
1524 Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
1525 Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
1526 if (computeODRHash(TA: FirstDefaultArgument) !=
1527 computeODRHash(TA: SecondDefaultArgument)) {
1528 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
1529 << (i + 1) << FirstDefaultArgument;
1530 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
1531 << (i + 1) << SecondDefaultArgument;
1532 return true;
1533 }
1534 }
1535
1536 if (FirstNTTPD->isParameterPack() != SecondNTTPD->isParameterPack()) {
1537 DiagTemplateError(FunctionTemplatePackParameter)
1538 << (i + 1) << FirstNTTPD->isParameterPack();
1539 DiagTemplateNote(FunctionTemplatePackParameter)
1540 << (i + 1) << SecondNTTPD->isParameterPack();
1541 return true;
1542 }
1543 }
1544 }
1545 break;
1546 }
1547 }
1548
1549 Diag(FirstDecl->getLocation(),
1550 diag::err_module_odr_violation_mismatch_decl_unknown)
1551 << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
1552 << FirstDecl->getSourceRange();
1553 Diag(SecondDecl->getLocation(),
1554 diag::note_module_odr_violation_mismatch_decl_unknown)
1555 << SecondModule.empty() << SecondModule << FirstDiffType
1556 << SecondDecl->getSourceRange();
1557 return true;
1558}
1559
1560bool ODRDiagsEmitter::diagnoseMismatch(const RecordDecl *FirstRecord,
1561 const RecordDecl *SecondRecord) const {
1562 if (FirstRecord == SecondRecord)
1563 return false;
1564
1565 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord);
1566 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);
1567
1568 auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record,
1569 const DeclContext *DC) {
1570 for (const Decl *D : Record->decls()) {
1571 if (!ODRHash::isSubDeclToBeProcessed(D, DC))
1572 continue;
1573 Hashes.emplace_back(D, computeODRHash(D));
1574 }
1575 };
1576
1577 DeclHashes FirstHashes;
1578 DeclHashes SecondHashes;
1579 const DeclContext *DC = FirstRecord;
1580 PopulateHashes(FirstHashes, FirstRecord, DC);
1581 PopulateHashes(SecondHashes, SecondRecord, DC);
1582
1583 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
1584 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
1585 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
1586 const Decl *FirstDecl = DR.FirstDecl;
1587 const Decl *SecondDecl = DR.SecondDecl;
1588
1589 if (FirstDiffType == Other || SecondDiffType == Other) {
1590 diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
1591 SecondModule);
1592 return true;
1593 }
1594
1595 if (FirstDiffType != SecondDiffType) {
1596 diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule,
1597 SecondRecord, SecondModule);
1598 return true;
1599 }
1600
1601 assert(FirstDiffType == SecondDiffType);
1602 switch (FirstDiffType) {
1603 // Already handled.
1604 case EndOfClass:
1605 case Other:
1606 // C++ only, invalid in this context.
1607 case PublicSpecifer:
1608 case PrivateSpecifer:
1609 case ProtectedSpecifer:
1610 case StaticAssert:
1611 case CXXMethod:
1612 case TypeAlias:
1613 case Friend:
1614 case FunctionTemplate:
1615 // Cannot be contained by RecordDecl, invalid in this context.
1616 case ObjCMethod:
1617 case ObjCIvar:
1618 case ObjCProperty:
1619 llvm_unreachable("Invalid diff type");
1620
1621 case Field: {
1622 if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule,
1623 cast<FieldDecl>(Val: FirstDecl),
1624 cast<FieldDecl>(Val: SecondDecl)))
1625 return true;
1626 break;
1627 }
1628 case TypeDef: {
1629 if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule,
1630 cast<TypedefNameDecl>(Val: FirstDecl),
1631 cast<TypedefNameDecl>(Val: SecondDecl),
1632 /*IsTypeAlias=*/false))
1633 return true;
1634 break;
1635 }
1636 case Var: {
1637 if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,
1638 cast<VarDecl>(Val: FirstDecl),
1639 cast<VarDecl>(Val: SecondDecl)))
1640 return true;
1641 break;
1642 }
1643 }
1644
1645 Diag(FirstDecl->getLocation(),
1646 diag::err_module_odr_violation_mismatch_decl_unknown)
1647 << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
1648 << FirstDecl->getSourceRange();
1649 Diag(SecondDecl->getLocation(),
1650 diag::note_module_odr_violation_mismatch_decl_unknown)
1651 << SecondModule.empty() << SecondModule << FirstDiffType
1652 << SecondDecl->getSourceRange();
1653 return true;
1654}
1655
1656bool ODRDiagsEmitter::diagnoseMismatch(
1657 const FunctionDecl *FirstFunction,
1658 const FunctionDecl *SecondFunction) const {
1659 if (FirstFunction == SecondFunction)
1660 return false;
1661
1662 // Keep in sync with select options in err_module_odr_violation_function.
1663 enum ODRFunctionDifference {
1664 ReturnType,
1665 ParameterName,
1666 ParameterType,
1667 ParameterSingleDefaultArgument,
1668 ParameterDifferentDefaultArgument,
1669 FunctionBody,
1670 };
1671
1672 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction);
1673 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondFunction);
1674
1675 auto DiagError = [FirstFunction, &FirstModule,
1676 this](SourceLocation Loc, SourceRange Range,
1677 ODRFunctionDifference DiffType) {
1678 return Diag(Loc, diag::err_module_odr_violation_function)
1679 << FirstFunction << FirstModule.empty() << FirstModule << Range
1680 << DiffType;
1681 };
1682 auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
1683 ODRFunctionDifference DiffType) {
1684 return Diag(Loc, diag::note_module_odr_violation_function)
1685 << SecondModule << Range << DiffType;
1686 };
1687
1688 if (computeODRHash(Ty: FirstFunction->getReturnType()) !=
1689 computeODRHash(Ty: SecondFunction->getReturnType())) {
1690 DiagError(FirstFunction->getReturnTypeSourceRange().getBegin(),
1691 FirstFunction->getReturnTypeSourceRange(), ReturnType)
1692 << FirstFunction->getReturnType();
1693 DiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(),
1694 SecondFunction->getReturnTypeSourceRange(), ReturnType)
1695 << SecondFunction->getReturnType();
1696 return true;
1697 }
1698
1699 assert(FirstFunction->param_size() == SecondFunction->param_size() &&
1700 "Merged functions with different number of parameters");
1701
1702 size_t ParamSize = FirstFunction->param_size();
1703 for (unsigned I = 0; I < ParamSize; ++I) {
1704 const ParmVarDecl *FirstParam = FirstFunction->getParamDecl(i: I);
1705 const ParmVarDecl *SecondParam = SecondFunction->getParamDecl(i: I);
1706
1707 assert(Context.hasSameType(FirstParam->getType(), SecondParam->getType()) &&
1708 "Merged function has different parameter types.");
1709
1710 if (FirstParam->getDeclName() != SecondParam->getDeclName()) {
1711 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1712 ParameterName)
1713 << I + 1 << FirstParam->getDeclName();
1714 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1715 ParameterName)
1716 << I + 1 << SecondParam->getDeclName();
1717 return true;
1718 };
1719
1720 QualType FirstParamType = FirstParam->getType();
1721 QualType SecondParamType = SecondParam->getType();
1722 if (FirstParamType != SecondParamType &&
1723 computeODRHash(Ty: FirstParamType) != computeODRHash(Ty: SecondParamType)) {
1724 if (const DecayedType *ParamDecayedType =
1725 FirstParamType->getAs<DecayedType>()) {
1726 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1727 ParameterType)
1728 << (I + 1) << FirstParamType << true
1729 << ParamDecayedType->getOriginalType();
1730 } else {
1731 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1732 ParameterType)
1733 << (I + 1) << FirstParamType << false;
1734 }
1735
1736 if (const DecayedType *ParamDecayedType =
1737 SecondParamType->getAs<DecayedType>()) {
1738 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1739 ParameterType)
1740 << (I + 1) << SecondParamType << true
1741 << ParamDecayedType->getOriginalType();
1742 } else {
1743 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1744 ParameterType)
1745 << (I + 1) << SecondParamType << false;
1746 }
1747 return true;
1748 }
1749
1750 // Note, these calls can trigger deserialization.
1751 const Expr *FirstInit = FirstParam->getInit();
1752 const Expr *SecondInit = SecondParam->getInit();
1753 if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
1754 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1755 ParameterSingleDefaultArgument)
1756 << (I + 1) << (FirstInit == nullptr)
1757 << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
1758 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1759 ParameterSingleDefaultArgument)
1760 << (I + 1) << (SecondInit == nullptr)
1761 << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
1762 return true;
1763 }
1764
1765 if (FirstInit && SecondInit &&
1766 computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
1767 DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
1768 ParameterDifferentDefaultArgument)
1769 << (I + 1) << FirstInit->getSourceRange();
1770 DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
1771 ParameterDifferentDefaultArgument)
1772 << (I + 1) << SecondInit->getSourceRange();
1773 return true;
1774 }
1775
1776 assert(computeODRHash(FirstParam) == computeODRHash(SecondParam) &&
1777 "Undiagnosed parameter difference.");
1778 }
1779
1780 // If no error has been generated before now, assume the problem is in
1781 // the body and generate a message.
1782 DiagError(FirstFunction->getLocation(), FirstFunction->getSourceRange(),
1783 FunctionBody);
1784 DiagNote(SecondFunction->getLocation(), SecondFunction->getSourceRange(),
1785 FunctionBody);
1786 return true;
1787}
1788
1789bool ODRDiagsEmitter::diagnoseMismatch(const EnumDecl *FirstEnum,
1790 const EnumDecl *SecondEnum) const {
1791 if (FirstEnum == SecondEnum)
1792 return false;
1793
1794 // Keep in sync with select options in err_module_odr_violation_enum.
1795 enum ODREnumDifference {
1796 SingleScopedEnum,
1797 EnumTagKeywordMismatch,
1798 SingleSpecifiedType,
1799 DifferentSpecifiedTypes,
1800 DifferentNumberEnumConstants,
1801 EnumConstantName,
1802 EnumConstantSingleInitializer,
1803 EnumConstantDifferentInitializer,
1804 };
1805
1806 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum);
1807 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondEnum);
1808
1809 auto DiagError = [FirstEnum, &FirstModule, this](const auto *DiagAnchor,
1810 ODREnumDifference DiffType) {
1811 return Diag(DiagAnchor->getLocation(), diag::err_module_odr_violation_enum)
1812 << FirstEnum << FirstModule.empty() << FirstModule
1813 << DiagAnchor->getSourceRange() << DiffType;
1814 };
1815 auto DiagNote = [&SecondModule, this](const auto *DiagAnchor,
1816 ODREnumDifference DiffType) {
1817 return Diag(DiagAnchor->getLocation(), diag::note_module_odr_violation_enum)
1818 << SecondModule << DiagAnchor->getSourceRange() << DiffType;
1819 };
1820
1821 if (FirstEnum->isScoped() != SecondEnum->isScoped()) {
1822 DiagError(FirstEnum, SingleScopedEnum) << FirstEnum->isScoped();
1823 DiagNote(SecondEnum, SingleScopedEnum) << SecondEnum->isScoped();
1824 return true;
1825 }
1826
1827 if (FirstEnum->isScoped() && SecondEnum->isScoped()) {
1828 if (FirstEnum->isScopedUsingClassTag() !=
1829 SecondEnum->isScopedUsingClassTag()) {
1830 DiagError(FirstEnum, EnumTagKeywordMismatch)
1831 << FirstEnum->isScopedUsingClassTag();
1832 DiagNote(SecondEnum, EnumTagKeywordMismatch)
1833 << SecondEnum->isScopedUsingClassTag();
1834 return true;
1835 }
1836 }
1837
1838 QualType FirstUnderlyingType =
1839 FirstEnum->getIntegerTypeSourceInfo()
1840 ? FirstEnum->getIntegerTypeSourceInfo()->getType()
1841 : QualType();
1842 QualType SecondUnderlyingType =
1843 SecondEnum->getIntegerTypeSourceInfo()
1844 ? SecondEnum->getIntegerTypeSourceInfo()->getType()
1845 : QualType();
1846 if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) {
1847 DiagError(FirstEnum, SingleSpecifiedType) << !FirstUnderlyingType.isNull();
1848 DiagNote(SecondEnum, SingleSpecifiedType) << !SecondUnderlyingType.isNull();
1849 return true;
1850 }
1851
1852 if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {
1853 if (computeODRHash(Ty: FirstUnderlyingType) !=
1854 computeODRHash(Ty: SecondUnderlyingType)) {
1855 DiagError(FirstEnum, DifferentSpecifiedTypes) << FirstUnderlyingType;
1856 DiagNote(SecondEnum, DifferentSpecifiedTypes) << SecondUnderlyingType;
1857 return true;
1858 }
1859 }
1860
1861 // Compare enum constants.
1862 using DeclHashes =
1863 llvm::SmallVector<std::pair<const EnumConstantDecl *, unsigned>, 4>;
1864 auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, const EnumDecl *Enum) {
1865 for (const Decl *D : Enum->decls()) {
1866 // Due to decl merging, the first EnumDecl is the parent of
1867 // Decls in both records.
1868 if (!ODRHash::isSubDeclToBeProcessed(D, FirstEnum))
1869 continue;
1870 assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind");
1871 Hashes.emplace_back(cast<EnumConstantDecl>(D), computeODRHash(D));
1872 }
1873 };
1874 DeclHashes FirstHashes;
1875 PopulateHashes(FirstHashes, FirstEnum);
1876 DeclHashes SecondHashes;
1877 PopulateHashes(SecondHashes, SecondEnum);
1878
1879 if (FirstHashes.size() != SecondHashes.size()) {
1880 DiagError(FirstEnum, DifferentNumberEnumConstants)
1881 << (int)FirstHashes.size();
1882 DiagNote(SecondEnum, DifferentNumberEnumConstants)
1883 << (int)SecondHashes.size();
1884 return true;
1885 }
1886
1887 for (unsigned I = 0, N = FirstHashes.size(); I < N; ++I) {
1888 if (FirstHashes[I].second == SecondHashes[I].second)
1889 continue;
1890 const EnumConstantDecl *FirstConstant = FirstHashes[I].first;
1891 const EnumConstantDecl *SecondConstant = SecondHashes[I].first;
1892
1893 if (FirstConstant->getDeclName() != SecondConstant->getDeclName()) {
1894 DiagError(FirstConstant, EnumConstantName) << I + 1 << FirstConstant;
1895 DiagNote(SecondConstant, EnumConstantName) << I + 1 << SecondConstant;
1896 return true;
1897 }
1898
1899 const Expr *FirstInit = FirstConstant->getInitExpr();
1900 const Expr *SecondInit = SecondConstant->getInitExpr();
1901 if (!FirstInit && !SecondInit)
1902 continue;
1903
1904 if (!FirstInit || !SecondInit) {
1905 DiagError(FirstConstant, EnumConstantSingleInitializer)
1906 << I + 1 << FirstConstant << (FirstInit != nullptr);
1907 DiagNote(SecondConstant, EnumConstantSingleInitializer)
1908 << I + 1 << SecondConstant << (SecondInit != nullptr);
1909 return true;
1910 }
1911
1912 if (computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
1913 DiagError(FirstConstant, EnumConstantDifferentInitializer)
1914 << I + 1 << FirstConstant;
1915 DiagNote(SecondConstant, EnumConstantDifferentInitializer)
1916 << I + 1 << SecondConstant;
1917 return true;
1918 }
1919 }
1920 return false;
1921}
1922
1923bool ODRDiagsEmitter::diagnoseMismatch(
1924 const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID,
1925 const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const {
1926 // Multiple different declarations got merged together; tell the user
1927 // where they came from.
1928 if (FirstID == SecondID)
1929 return false;
1930
1931 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstID);
1932 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondID);
1933
1934 // Keep in sync with err_module_odr_violation_objc_interface.
1935 enum ODRInterfaceDifference {
1936 SuperClassType,
1937 IVarAccess,
1938 };
1939
1940 auto DiagError = [FirstID, &FirstModule,
1941 this](SourceLocation Loc, SourceRange Range,
1942 ODRInterfaceDifference DiffType) {
1943 return Diag(Loc, diag::err_module_odr_violation_objc_interface)
1944 << FirstID << FirstModule.empty() << FirstModule << Range
1945 << DiffType;
1946 };
1947 auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
1948 ODRInterfaceDifference DiffType) {
1949 return Diag(Loc, diag::note_module_odr_violation_objc_interface)
1950 << SecondModule.empty() << SecondModule << Range << DiffType;
1951 };
1952
1953 const struct ObjCInterfaceDecl::DefinitionData *FirstDD = &FirstID->data();
1954 assert(FirstDD && SecondDD && "Definitions without DefinitionData");
1955 if (FirstDD != SecondDD) {
1956 // Check for matching super class.
1957 auto GetSuperClassSourceRange = [](const TypeSourceInfo *SuperInfo,
1958 const ObjCInterfaceDecl *ID) {
1959 if (!SuperInfo)
1960 return ID->getSourceRange();
1961 TypeLoc Loc = SuperInfo->getTypeLoc();
1962 return SourceRange(Loc.getBeginLoc(), Loc.getEndLoc());
1963 };
1964
1965 ObjCInterfaceDecl *FirstSuperClass = FirstID->getSuperClass();
1966 ObjCInterfaceDecl *SecondSuperClass = nullptr;
1967 const TypeSourceInfo *FirstSuperInfo = FirstID->getSuperClassTInfo();
1968 const TypeSourceInfo *SecondSuperInfo = SecondDD->SuperClassTInfo;
1969 if (SecondSuperInfo)
1970 SecondSuperClass =
1971 SecondSuperInfo->getType()->castAs<ObjCObjectType>()->getInterface();
1972
1973 if ((FirstSuperClass && SecondSuperClass &&
1974 FirstSuperClass->getODRHash() != SecondSuperClass->getODRHash()) ||
1975 (FirstSuperClass && !SecondSuperClass) ||
1976 (!FirstSuperClass && SecondSuperClass)) {
1977 QualType FirstType;
1978 if (FirstSuperInfo)
1979 FirstType = FirstSuperInfo->getType();
1980
1981 DiagError(FirstID->getLocation(),
1982 GetSuperClassSourceRange(FirstSuperInfo, FirstID),
1983 SuperClassType)
1984 << (bool)FirstSuperInfo << FirstType;
1985
1986 QualType SecondType;
1987 if (SecondSuperInfo)
1988 SecondType = SecondSuperInfo->getType();
1989
1990 DiagNote(SecondID->getLocation(),
1991 GetSuperClassSourceRange(SecondSuperInfo, SecondID),
1992 SuperClassType)
1993 << (bool)SecondSuperInfo << SecondType;
1994 return true;
1995 }
1996
1997 // Check both interfaces reference the same protocols.
1998 auto &FirstProtos = FirstID->getReferencedProtocols();
1999 auto &SecondProtos = SecondDD->ReferencedProtocols;
2000 if (diagnoseSubMismatchProtocols(FirstProtos, FirstID, FirstModule,
2001 SecondProtos, SecondID, SecondModule))
2002 return true;
2003 }
2004
2005 auto PopulateHashes = [](DeclHashes &Hashes, const ObjCInterfaceDecl *ID,
2006 const DeclContext *DC) {
2007 for (auto *D : ID->decls()) {
2008 if (!ODRHash::isSubDeclToBeProcessed(D, DC))
2009 continue;
2010 Hashes.emplace_back(D, computeODRHash(D));
2011 }
2012 };
2013
2014 DeclHashes FirstHashes;
2015 DeclHashes SecondHashes;
2016 // Use definition as DeclContext because definitions are merged when
2017 // DeclContexts are merged and separate when DeclContexts are separate.
2018 PopulateHashes(FirstHashes, FirstID, FirstID->getDefinition());
2019 PopulateHashes(SecondHashes, SecondID, SecondID->getDefinition());
2020
2021 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
2022 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
2023 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
2024 const Decl *FirstDecl = DR.FirstDecl;
2025 const Decl *SecondDecl = DR.SecondDecl;
2026
2027 if (FirstDiffType == Other || SecondDiffType == Other) {
2028 diagnoseSubMismatchUnexpected(DR, FirstID, FirstModule, SecondID,
2029 SecondModule);
2030 return true;
2031 }
2032
2033 if (FirstDiffType != SecondDiffType) {
2034 diagnoseSubMismatchDifferentDeclKinds(DR, FirstID, FirstModule, SecondID,
2035 SecondModule);
2036 return true;
2037 }
2038
2039 assert(FirstDiffType == SecondDiffType);
2040 switch (FirstDiffType) {
2041 // Already handled.
2042 case EndOfClass:
2043 case Other:
2044 // Cannot be contained by ObjCInterfaceDecl, invalid in this context.
2045 case Field:
2046 case TypeDef:
2047 case Var:
2048 // C++ only, invalid in this context.
2049 case PublicSpecifer:
2050 case PrivateSpecifer:
2051 case ProtectedSpecifer:
2052 case StaticAssert:
2053 case CXXMethod:
2054 case TypeAlias:
2055 case Friend:
2056 case FunctionTemplate:
2057 llvm_unreachable("Invalid diff type");
2058
2059 case ObjCMethod: {
2060 if (diagnoseSubMismatchObjCMethod(FirstID, FirstModule, SecondModule,
2061 cast<ObjCMethodDecl>(Val: FirstDecl),
2062 cast<ObjCMethodDecl>(Val: SecondDecl)))
2063 return true;
2064 break;
2065 }
2066 case ObjCIvar: {
2067 if (diagnoseSubMismatchField(FirstID, FirstModule, SecondModule,
2068 cast<FieldDecl>(Val: FirstDecl),
2069 cast<FieldDecl>(Val: SecondDecl)))
2070 return true;
2071
2072 // Check if the access match.
2073 const ObjCIvarDecl *FirstIvar = cast<ObjCIvarDecl>(Val: FirstDecl);
2074 const ObjCIvarDecl *SecondIvar = cast<ObjCIvarDecl>(Val: SecondDecl);
2075 if (FirstIvar->getCanonicalAccessControl() !=
2076 SecondIvar->getCanonicalAccessControl()) {
2077 DiagError(FirstIvar->getLocation(), FirstIvar->getSourceRange(),
2078 IVarAccess)
2079 << FirstIvar->getName()
2080 << (int)FirstIvar->getCanonicalAccessControl();
2081 DiagNote(SecondIvar->getLocation(), SecondIvar->getSourceRange(),
2082 IVarAccess)
2083 << SecondIvar->getName()
2084 << (int)SecondIvar->getCanonicalAccessControl();
2085 return true;
2086 }
2087 break;
2088 }
2089 case ObjCProperty: {
2090 if (diagnoseSubMismatchObjCProperty(FirstID, FirstModule, SecondModule,
2091 cast<ObjCPropertyDecl>(Val: FirstDecl),
2092 cast<ObjCPropertyDecl>(Val: SecondDecl)))
2093 return true;
2094 break;
2095 }
2096 }
2097
2098 Diag(FirstDecl->getLocation(),
2099 diag::err_module_odr_violation_mismatch_decl_unknown)
2100 << FirstID << FirstModule.empty() << FirstModule << FirstDiffType
2101 << FirstDecl->getSourceRange();
2102 Diag(SecondDecl->getLocation(),
2103 diag::note_module_odr_violation_mismatch_decl_unknown)
2104 << SecondModule.empty() << SecondModule << FirstDiffType
2105 << SecondDecl->getSourceRange();
2106 return true;
2107}
2108
2109bool ODRDiagsEmitter::diagnoseMismatch(
2110 const ObjCProtocolDecl *FirstProtocol,
2111 const ObjCProtocolDecl *SecondProtocol,
2112 const struct ObjCProtocolDecl::DefinitionData *SecondDD) const {
2113 if (FirstProtocol == SecondProtocol)
2114 return false;
2115
2116 std::string FirstModule = getOwningModuleNameForDiagnostic(FirstProtocol);
2117 std::string SecondModule = getOwningModuleNameForDiagnostic(SecondProtocol);
2118
2119 const ObjCProtocolDecl::DefinitionData *FirstDD = &FirstProtocol->data();
2120 assert(FirstDD && SecondDD && "Definitions without DefinitionData");
2121 // Diagnostics from ObjCProtocol DefinitionData are emitted here.
2122 if (FirstDD != SecondDD) {
2123 // Check both protocols reference the same protocols.
2124 const ObjCProtocolList &FirstProtocols =
2125 FirstProtocol->getReferencedProtocols();
2126 const ObjCProtocolList &SecondProtocols = SecondDD->ReferencedProtocols;
2127 if (diagnoseSubMismatchProtocols(FirstProtocols, FirstProtocol, FirstModule,
2128 SecondProtocols, SecondProtocol,
2129 SecondModule))
2130 return true;
2131 }
2132
2133 auto PopulateHashes = [](DeclHashes &Hashes, const ObjCProtocolDecl *ID,
2134 const DeclContext *DC) {
2135 for (const Decl *D : ID->decls()) {
2136 if (!ODRHash::isSubDeclToBeProcessed(D, DC))
2137 continue;
2138 Hashes.emplace_back(D, computeODRHash(D));
2139 }
2140 };
2141
2142 DeclHashes FirstHashes;
2143 DeclHashes SecondHashes;
2144 // Use definition as DeclContext because definitions are merged when
2145 // DeclContexts are merged and separate when DeclContexts are separate.
2146 PopulateHashes(FirstHashes, FirstProtocol, FirstProtocol->getDefinition());
2147 PopulateHashes(SecondHashes, SecondProtocol, SecondProtocol->getDefinition());
2148
2149 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
2150 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
2151 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
2152 const Decl *FirstDecl = DR.FirstDecl;
2153 const Decl *SecondDecl = DR.SecondDecl;
2154
2155 if (FirstDiffType == Other || SecondDiffType == Other) {
2156 diagnoseSubMismatchUnexpected(DR, FirstProtocol, FirstModule,
2157 SecondProtocol, SecondModule);
2158 return true;
2159 }
2160
2161 if (FirstDiffType != SecondDiffType) {
2162 diagnoseSubMismatchDifferentDeclKinds(DR, FirstProtocol, FirstModule,
2163 SecondProtocol, SecondModule);
2164 return true;
2165 }
2166
2167 assert(FirstDiffType == SecondDiffType);
2168 switch (FirstDiffType) {
2169 // Already handled.
2170 case EndOfClass:
2171 case Other:
2172 // Cannot be contained by ObjCProtocolDecl, invalid in this context.
2173 case Field:
2174 case TypeDef:
2175 case Var:
2176 case ObjCIvar:
2177 // C++ only, invalid in this context.
2178 case PublicSpecifer:
2179 case PrivateSpecifer:
2180 case ProtectedSpecifer:
2181 case StaticAssert:
2182 case CXXMethod:
2183 case TypeAlias:
2184 case Friend:
2185 case FunctionTemplate:
2186 llvm_unreachable("Invalid diff type");
2187 case ObjCMethod: {
2188 if (diagnoseSubMismatchObjCMethod(FirstProtocol, FirstModule, SecondModule,
2189 cast<ObjCMethodDecl>(Val: FirstDecl),
2190 cast<ObjCMethodDecl>(Val: SecondDecl)))
2191 return true;
2192 break;
2193 }
2194 case ObjCProperty: {
2195 if (diagnoseSubMismatchObjCProperty(FirstProtocol, FirstModule,
2196 SecondModule,
2197 cast<ObjCPropertyDecl>(Val: FirstDecl),
2198 cast<ObjCPropertyDecl>(Val: SecondDecl)))
2199 return true;
2200 break;
2201 }
2202 }
2203
2204 Diag(FirstDecl->getLocation(),
2205 diag::err_module_odr_violation_mismatch_decl_unknown)
2206 << FirstProtocol << FirstModule.empty() << FirstModule << FirstDiffType
2207 << FirstDecl->getSourceRange();
2208 Diag(SecondDecl->getLocation(),
2209 diag::note_module_odr_violation_mismatch_decl_unknown)
2210 << SecondModule.empty() << SecondModule << FirstDiffType
2211 << SecondDecl->getSourceRange();
2212 return true;
2213}
2214

source code of clang/lib/AST/ODRDiagsEmitter.cpp