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