//===-- ODRDiagsEmitter.cpp - Diagnostics for ODR mismatches ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ODRDiagsEmitter.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ODRHash.h"
#include "clang/Basic/DiagnosticAST.h"
#include "clang/Basic/Module.h"

using namespace clang;

static unsigned computeODRHash(QualType Ty) {
  ODRHash Hasher;
  Hasher.AddQualType(Ty);
  return Hasher.CalculateHash();
}

static unsigned computeODRHash(const Stmt *S) {
  ODRHash Hasher;
  Hasher.AddStmt(S);
  return Hasher.CalculateHash();
}

static unsigned computeODRHash(const Decl *D) {
  assert(D);
  ODRHash Hasher;
  Hasher.AddSubDecl(D);
  return Hasher.CalculateHash();
}

static unsigned computeODRHash(const TemplateArgument &TA) {
  ODRHash Hasher;
  Hasher.AddTemplateArgument(TA);
  return Hasher.CalculateHash();
}

std::string ODRDiagsEmitter::getOwningModuleNameForDiagnostic(const Decl *D) {
  // If we know the owning module, use it.
  if (Module *M = D->getImportedOwningModule())
    return M->getFullModuleName();

  // Not from a module.
  return {};
}

template <typename MethodT>
static bool diagnoseSubMismatchMethodParameters(DiagnosticsEngine &Diags,
                                                const NamedDecl *FirstContainer,
                                                StringRef FirstModule,
                                                StringRef SecondModule,
                                                const MethodT *FirstMethod,
                                                const MethodT *SecondMethod) {
  enum DiagMethodType {
    DiagMethod,
    DiagConstructor,
    DiagDestructor,
  };
  auto GetDiagMethodType = [](const NamedDecl *D) {
    if (isa<CXXConstructorDecl>(D))
      return DiagConstructor;
    if (isa<CXXDestructorDecl>(D))
      return DiagDestructor;
    return DiagMethod;
  };

  enum ODRMethodParametersDifference {
    NumberParameters,
    ParameterType,
    ParameterName,
  };
  auto DiagError = [&Diags, &GetDiagMethodType, FirstContainer, FirstModule,
                    FirstMethod](ODRMethodParametersDifference DiffType) {
    DeclarationName FirstName = FirstMethod->getDeclName();
    DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod);
    return Diags.Report(FirstMethod->getLocation(),
                        diag::err_module_odr_violation_method_params)
           << FirstContainer << FirstModule.empty() << FirstModule
           << FirstMethod->getSourceRange() << DiffType << FirstMethodType
           << FirstName;
  };
  auto DiagNote = [&Diags, &GetDiagMethodType, SecondModule,
                   SecondMethod](ODRMethodParametersDifference DiffType) {
    DeclarationName SecondName = SecondMethod->getDeclName();
    DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod);
    return Diags.Report(SecondMethod->getLocation(),
                        diag::note_module_odr_violation_method_params)
           << SecondModule.empty() << SecondModule
           << SecondMethod->getSourceRange() << DiffType << SecondMethodType
           << SecondName;
  };

  const unsigned FirstNumParameters = FirstMethod->param_size();
  const unsigned SecondNumParameters = SecondMethod->param_size();
  if (FirstNumParameters != SecondNumParameters) {
    DiagError(NumberParameters) << FirstNumParameters;
    DiagNote(NumberParameters) << SecondNumParameters;
    return true;
  }

  for (unsigned I = 0; I < FirstNumParameters; ++I) {
    const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);
    const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);

    QualType FirstParamType = FirstParam->getType();
    QualType SecondParamType = SecondParam->getType();
    if (FirstParamType != SecondParamType &&
        computeODRHash(FirstParamType) != computeODRHash(SecondParamType)) {
      if (const DecayedType *ParamDecayedType =
              FirstParamType->getAs<DecayedType>()) {
        DiagError(ParameterType) << (I + 1) << FirstParamType << true
                                 << ParamDecayedType->getOriginalType();
      } else {
        DiagError(ParameterType) << (I + 1) << FirstParamType << false;
      }

      if (const DecayedType *ParamDecayedType =
              SecondParamType->getAs<DecayedType>()) {
        DiagNote(ParameterType) << (I + 1) << SecondParamType << true
                                << ParamDecayedType->getOriginalType();
      } else {
        DiagNote(ParameterType) << (I + 1) << SecondParamType << false;
      }
      return true;
    }

    DeclarationName FirstParamName = FirstParam->getDeclName();
    DeclarationName SecondParamName = SecondParam->getDeclName();
    if (FirstParamName != SecondParamName) {
      DiagError(ParameterName) << (I + 1) << FirstParamName;
      DiagNote(ParameterName) << (I + 1) << SecondParamName;
      return true;
    }
  }

  return false;
}

bool ODRDiagsEmitter::diagnoseSubMismatchField(
    const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,
    const FieldDecl *FirstField, const FieldDecl *SecondField) const {
  enum ODRFieldDifference {
    FieldName,
    FieldTypeName,
    FieldSingleBitField,
    FieldDifferentWidthBitField,
    FieldSingleMutable,
    FieldSingleInitializer,
    FieldDifferentInitializers,
  };

  auto DiagError = [FirstRecord, FirstField, FirstModule,
                    this](ODRFieldDifference DiffType) {
    return Diag(FirstField->getLocation(), diag::err_module_odr_violation_field)
           << FirstRecord << FirstModule.empty() << FirstModule
           << FirstField->getSourceRange() << DiffType;
  };
  auto DiagNote = [SecondField, SecondModule,
                   this](ODRFieldDifference DiffType) {
    return Diag(SecondField->getLocation(),
                diag::note_module_odr_violation_field)
           << SecondModule.empty() << SecondModule << SecondField->getSourceRange() << DiffType;
  };

  IdentifierInfo *FirstII = FirstField->getIdentifier();
  IdentifierInfo *SecondII = SecondField->getIdentifier();
  if (FirstII->getName() != SecondII->getName()) {
    DiagError(FieldName) << FirstII;
    DiagNote(FieldName) << SecondII;
    return true;
  }

  QualType FirstType = FirstField->getType();
  QualType SecondType = SecondField->getType();
  if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
    DiagError(FieldTypeName) << FirstII << FirstType;
    DiagNote(FieldTypeName) << SecondII << SecondType;
    return true;
  }

  assert(Context.hasSameType(FirstField->getType(), SecondField->getType()));
  (void)Context;

  const bool IsFirstBitField = FirstField->isBitField();
  const bool IsSecondBitField = SecondField->isBitField();
  if (IsFirstBitField != IsSecondBitField) {
    DiagError(FieldSingleBitField) << FirstII << IsFirstBitField;
    DiagNote(FieldSingleBitField) << SecondII << IsSecondBitField;
    return true;
  }

  if (IsFirstBitField && IsSecondBitField) {
    unsigned FirstBitWidthHash = computeODRHash(FirstField->getBitWidth());
    unsigned SecondBitWidthHash = computeODRHash(SecondField->getBitWidth());
    if (FirstBitWidthHash != SecondBitWidthHash) {
      DiagError(FieldDifferentWidthBitField)
          << FirstII << FirstField->getBitWidth()->getSourceRange();
      DiagNote(FieldDifferentWidthBitField)
          << SecondII << SecondField->getBitWidth()->getSourceRange();
      return true;
    }
  }

  if (!LangOpts.CPlusPlus)
    return false;

  const bool IsFirstMutable = FirstField->isMutable();
  const bool IsSecondMutable = SecondField->isMutable();
  if (IsFirstMutable != IsSecondMutable) {
    DiagError(FieldSingleMutable) << FirstII << IsFirstMutable;
    DiagNote(FieldSingleMutable) << SecondII << IsSecondMutable;
    return true;
  }

  const Expr *FirstInitializer = FirstField->getInClassInitializer();
  const Expr *SecondInitializer = SecondField->getInClassInitializer();
  if ((!FirstInitializer && SecondInitializer) ||
      (FirstInitializer && !SecondInitializer)) {
    DiagError(FieldSingleInitializer)
        << FirstII << (FirstInitializer != nullptr);
    DiagNote(FieldSingleInitializer)
        << SecondII << (SecondInitializer != nullptr);
    return true;
  }

  if (FirstInitializer && SecondInitializer) {
    unsigned FirstInitHash = computeODRHash(FirstInitializer);
    unsigned SecondInitHash = computeODRHash(SecondInitializer);
    if (FirstInitHash != SecondInitHash) {
      DiagError(FieldDifferentInitializers)
          << FirstII << FirstInitializer->getSourceRange();
      DiagNote(FieldDifferentInitializers)
          << SecondII << SecondInitializer->getSourceRange();
      return true;
    }
  }

  return false;
}

bool ODRDiagsEmitter::diagnoseSubMismatchTypedef(
    const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,
    const TypedefNameDecl *FirstTD, const TypedefNameDecl *SecondTD,
    bool IsTypeAlias) const {
  enum ODRTypedefDifference {
    TypedefName,
    TypedefType,
  };

  auto DiagError = [FirstRecord, FirstTD, FirstModule,
                    this](ODRTypedefDifference DiffType) {
    return Diag(FirstTD->getLocation(), diag::err_module_odr_violation_typedef)
           << FirstRecord << FirstModule.empty() << FirstModule
           << FirstTD->getSourceRange() << DiffType;
  };
  auto DiagNote = [SecondTD, SecondModule,
                   this](ODRTypedefDifference DiffType) {
    return Diag(SecondTD->getLocation(),
                diag::note_module_odr_violation_typedef)
           << SecondModule << SecondTD->getSourceRange() << DiffType;
  };

  DeclarationName FirstName = FirstTD->getDeclName();
  DeclarationName SecondName = SecondTD->getDeclName();
  if (FirstName != SecondName) {
    DiagError(TypedefName) << IsTypeAlias << FirstName;
    DiagNote(TypedefName) << IsTypeAlias << SecondName;
    return true;
  }

  QualType FirstType = FirstTD->getUnderlyingType();
  QualType SecondType = SecondTD->getUnderlyingType();
  if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
    DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType;
    DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType;
    return true;
  }
  return false;
}

bool ODRDiagsEmitter::diagnoseSubMismatchVar(const NamedDecl *FirstRecord,
                                             StringRef FirstModule,
                                             StringRef SecondModule,
                                             const VarDecl *FirstVD,
                                             const VarDecl *SecondVD) const {
  enum ODRVarDifference {
    VarName,
    VarType,
    VarSingleInitializer,
    VarDifferentInitializer,
    VarConstexpr,
  };

  auto DiagError = [FirstRecord, FirstVD, FirstModule,
                    this](ODRVarDifference DiffType) {
    return Diag(FirstVD->getLocation(), diag::err_module_odr_violation_variable)
           << FirstRecord << FirstModule.empty() << FirstModule
           << FirstVD->getSourceRange() << DiffType;
  };
  auto DiagNote = [SecondVD, SecondModule, this](ODRVarDifference DiffType) {
    return Diag(SecondVD->getLocation(),
                diag::note_module_odr_violation_variable)
           << SecondModule << SecondVD->getSourceRange() << DiffType;
  };

  DeclarationName FirstName = FirstVD->getDeclName();
  DeclarationName SecondName = SecondVD->getDeclName();
  if (FirstName != SecondName) {
    DiagError(VarName) << FirstName;
    DiagNote(VarName) << SecondName;
    return true;
  }

  QualType FirstType = FirstVD->getType();
  QualType SecondType = SecondVD->getType();
  if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
    DiagError(VarType) << FirstName << FirstType;
    DiagNote(VarType) << SecondName << SecondType;
    return true;
  }

  if (!LangOpts.CPlusPlus)
    return false;

  const Expr *FirstInit = FirstVD->getInit();
  const Expr *SecondInit = SecondVD->getInit();
  if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
    DiagError(VarSingleInitializer)
        << FirstName << (FirstInit == nullptr)
        << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
    DiagNote(VarSingleInitializer)
        << SecondName << (SecondInit == nullptr)
        << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
    return true;
  }

  if (FirstInit && SecondInit &&
      computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
    DiagError(VarDifferentInitializer)
        << FirstName << FirstInit->getSourceRange();
    DiagNote(VarDifferentInitializer)
        << SecondName << SecondInit->getSourceRange();
    return true;
  }

  const bool FirstIsConstexpr = FirstVD->isConstexpr();
  const bool SecondIsConstexpr = SecondVD->isConstexpr();
  if (FirstIsConstexpr != SecondIsConstexpr) {
    DiagError(VarConstexpr) << FirstName << FirstIsConstexpr;
    DiagNote(VarConstexpr) << SecondName << SecondIsConstexpr;
    return true;
  }
  return false;
}

bool ODRDiagsEmitter::diagnoseSubMismatchProtocols(
    const ObjCProtocolList &FirstProtocols,
    const ObjCContainerDecl *FirstContainer, StringRef FirstModule,
    const ObjCProtocolList &SecondProtocols,
    const ObjCContainerDecl *SecondContainer, StringRef SecondModule) const {
  // Keep in sync with err_module_odr_violation_referenced_protocols.
  enum ODRReferencedProtocolDifference {
    NumProtocols,
    ProtocolType,
  };
  auto DiagRefProtocolError = [FirstContainer, FirstModule,
                               this](SourceLocation Loc, SourceRange Range,
                                     ODRReferencedProtocolDifference DiffType) {
    return Diag(Loc, diag::err_module_odr_violation_referenced_protocols)
           << FirstContainer << FirstModule.empty() << FirstModule << Range
           << DiffType;
  };
  auto DiagRefProtocolNote = [SecondModule,
                              this](SourceLocation Loc, SourceRange Range,
                                    ODRReferencedProtocolDifference DiffType) {
    return Diag(Loc, diag::note_module_odr_violation_referenced_protocols)
           << SecondModule.empty() << SecondModule << Range << DiffType;
  };
  auto GetProtoListSourceRange = [](const ObjCProtocolList &PL) {
    if (PL.empty())
      return SourceRange();
    return SourceRange(*PL.loc_begin(), *std::prev(PL.loc_end()));
  };

  if (FirstProtocols.size() != SecondProtocols.size()) {
    DiagRefProtocolError(FirstContainer->getLocation(),
                         GetProtoListSourceRange(FirstProtocols), NumProtocols)
        << FirstProtocols.size();
    DiagRefProtocolNote(SecondContainer->getLocation(),
                        GetProtoListSourceRange(SecondProtocols), NumProtocols)
        << SecondProtocols.size();
    return true;
  }

  for (unsigned I = 0, E = FirstProtocols.size(); I != E; ++I) {
    const ObjCProtocolDecl *FirstProtocol = FirstProtocols[I];
    const ObjCProtocolDecl *SecondProtocol = SecondProtocols[I];
    DeclarationName FirstProtocolName = FirstProtocol->getDeclName();
    DeclarationName SecondProtocolName = SecondProtocol->getDeclName();
    if (FirstProtocolName != SecondProtocolName) {
      SourceLocation FirstLoc = *(FirstProtocols.loc_begin() + I);
      SourceLocation SecondLoc = *(SecondProtocols.loc_begin() + I);
      SourceRange EmptyRange;
      DiagRefProtocolError(FirstLoc, EmptyRange, ProtocolType)
          << (I + 1) << FirstProtocolName;
      DiagRefProtocolNote(SecondLoc, EmptyRange, ProtocolType)
          << (I + 1) << SecondProtocolName;
      return true;
    }
  }

  return false;
}

bool ODRDiagsEmitter::diagnoseSubMismatchObjCMethod(
    const NamedDecl *FirstObjCContainer, StringRef FirstModule,
    StringRef SecondModule, const ObjCMethodDecl *FirstMethod,
    const ObjCMethodDecl *SecondMethod) const {
  enum ODRMethodDifference {
    ReturnType,
    InstanceOrClass,
    ControlLevel, // optional/required
    DesignatedInitializer,
    Directness,
    Name,
  };

  auto DiagError = [FirstObjCContainer, FirstModule, FirstMethod,
                    this](ODRMethodDifference DiffType) {
    return Diag(FirstMethod->getLocation(),
                diag::err_module_odr_violation_objc_method)
           << FirstObjCContainer << FirstModule.empty() << FirstModule
           << FirstMethod->getSourceRange() << DiffType;
  };
  auto DiagNote = [SecondModule, SecondMethod,
                   this](ODRMethodDifference DiffType) {
    return Diag(SecondMethod->getLocation(),
                diag::note_module_odr_violation_objc_method)
           << SecondModule.empty() << SecondModule
           << SecondMethod->getSourceRange() << DiffType;
  };

  if (computeODRHash(FirstMethod->getReturnType()) !=
      computeODRHash(SecondMethod->getReturnType())) {
    DiagError(ReturnType) << FirstMethod << FirstMethod->getReturnType();
    DiagNote(ReturnType) << SecondMethod << SecondMethod->getReturnType();
    return true;
  }

  if (FirstMethod->isInstanceMethod() != SecondMethod->isInstanceMethod()) {
    DiagError(InstanceOrClass)
        << FirstMethod << FirstMethod->isInstanceMethod();
    DiagNote(InstanceOrClass)
        << SecondMethod << SecondMethod->isInstanceMethod();
    return true;
  }
  if (FirstMethod->getImplementationControl() !=
      SecondMethod->getImplementationControl()) {
    DiagError(ControlLevel) << FirstMethod->getImplementationControl();
    DiagNote(ControlLevel) << SecondMethod->getImplementationControl();
    return true;
  }
  if (FirstMethod->isThisDeclarationADesignatedInitializer() !=
      SecondMethod->isThisDeclarationADesignatedInitializer()) {
    DiagError(DesignatedInitializer)
        << FirstMethod
        << FirstMethod->isThisDeclarationADesignatedInitializer();
    DiagNote(DesignatedInitializer)
        << SecondMethod
        << SecondMethod->isThisDeclarationADesignatedInitializer();
    return true;
  }
  if (FirstMethod->isDirectMethod() != SecondMethod->isDirectMethod()) {
    DiagError(Directness) << FirstMethod << FirstMethod->isDirectMethod();
    DiagNote(Directness) << SecondMethod << SecondMethod->isDirectMethod();
    return true;
  }
  if (diagnoseSubMismatchMethodParameters(Diags, FirstObjCContainer,
                                          FirstModule, SecondModule,
                                          FirstMethod, SecondMethod))
    return true;

  // Check method name *after* looking at the parameters otherwise we get a
  // less ideal diagnostics: a ObjCMethodName mismatch given that selectors
  // for different parameters are likely to be different.
  DeclarationName FirstName = FirstMethod->getDeclName();
  DeclarationName SecondName = SecondMethod->getDeclName();
  if (FirstName != SecondName) {
    DiagError(Name) << FirstName;
    DiagNote(Name) << SecondName;
    return true;
  }

  return false;
}

bool ODRDiagsEmitter::diagnoseSubMismatchObjCProperty(
    const NamedDecl *FirstObjCContainer, StringRef FirstModule,
    StringRef SecondModule, const ObjCPropertyDecl *FirstProp,
    const ObjCPropertyDecl *SecondProp) const {
  enum ODRPropertyDifference {
    Name,
    Type,
    ControlLevel, // optional/required
    Attribute,
  };

  auto DiagError = [FirstObjCContainer, FirstModule, FirstProp,
                    this](SourceLocation Loc, ODRPropertyDifference DiffType) {
    return Diag(Loc, diag::err_module_odr_violation_objc_property)
           << FirstObjCContainer << FirstModule.empty() << FirstModule
           << FirstProp->getSourceRange() << DiffType;
  };
  auto DiagNote = [SecondModule, SecondProp,
                   this](SourceLocation Loc, ODRPropertyDifference DiffType) {
    return Diag(Loc, diag::note_module_odr_violation_objc_property)
           << SecondModule.empty() << SecondModule
           << SecondProp->getSourceRange() << DiffType;
  };

  IdentifierInfo *FirstII = FirstProp->getIdentifier();
  IdentifierInfo *SecondII = SecondProp->getIdentifier();
  if (FirstII->getName() != SecondII->getName()) {
    DiagError(FirstProp->getLocation(), Name) << FirstII;
    DiagNote(SecondProp->getLocation(), Name) << SecondII;
    return true;
  }
  if (computeODRHash(FirstProp->getType()) !=
      computeODRHash(SecondProp->getType())) {
    DiagError(FirstProp->getLocation(), Type)
        << FirstII << FirstProp->getType();
    DiagNote(SecondProp->getLocation(), Type)
        << SecondII << SecondProp->getType();
    return true;
  }
  if (FirstProp->getPropertyImplementation() !=
      SecondProp->getPropertyImplementation()) {
    DiagError(FirstProp->getLocation(), ControlLevel)
        << FirstProp->getPropertyImplementation();
    DiagNote(SecondProp->getLocation(), ControlLevel)
        << SecondProp->getPropertyImplementation();
    return true;
  }

  // Go over the property attributes and stop at the first mismatch.
  unsigned FirstAttrs = (unsigned)FirstProp->getPropertyAttributes();
  unsigned SecondAttrs = (unsigned)SecondProp->getPropertyAttributes();
  if (FirstAttrs != SecondAttrs) {
    for (unsigned I = 0; I < NumObjCPropertyAttrsBits; ++I) {
      unsigned CheckedAttr = (1 << I);
      if ((FirstAttrs & CheckedAttr) == (SecondAttrs & CheckedAttr))
        continue;

      bool IsFirstWritten =
          (unsigned)FirstProp->getPropertyAttributesAsWritten() & CheckedAttr;
      bool IsSecondWritten =
          (unsigned)SecondProp->getPropertyAttributesAsWritten() & CheckedAttr;
      DiagError(IsFirstWritten ? FirstProp->getLParenLoc()
                               : FirstProp->getLocation(),
                Attribute)
          << FirstII << (I + 1) << IsFirstWritten;
      DiagNote(IsSecondWritten ? SecondProp->getLParenLoc()
                               : SecondProp->getLocation(),
               Attribute)
          << SecondII << (I + 1);
      return true;
    }
  }

  return false;
}

ODRDiagsEmitter::DiffResult
ODRDiagsEmitter::FindTypeDiffs(DeclHashes &FirstHashes,
                               DeclHashes &SecondHashes) {
  auto DifferenceSelector = [](const Decl *D) {
    assert(D && "valid Decl required");
    switch (D->getKind()) {
    default:
      return Other;
    case Decl::AccessSpec:
      switch (D->getAccess()) {
      case AS_public:
        return PublicSpecifer;
      case AS_private:
        return PrivateSpecifer;
      case AS_protected:
        return ProtectedSpecifer;
      case AS_none:
        break;
      }
      llvm_unreachable("Invalid access specifier");
    case Decl::StaticAssert:
      return StaticAssert;
    case Decl::Field:
      return Field;
    case Decl::CXXMethod:
    case Decl::CXXConstructor:
    case Decl::CXXDestructor:
      return CXXMethod;
    case Decl::TypeAlias:
      return TypeAlias;
    case Decl::Typedef:
      return TypeDef;
    case Decl::Var:
      return Var;
    case Decl::Friend:
      return Friend;
    case Decl::FunctionTemplate:
      return FunctionTemplate;
    case Decl::ObjCMethod:
      return ObjCMethod;
    case Decl::ObjCIvar:
      return ObjCIvar;
    case Decl::ObjCProperty:
      return ObjCProperty;
    }
  };

  DiffResult DR;
  auto FirstIt = FirstHashes.begin();
  auto SecondIt = SecondHashes.begin();
  while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()) {
    if (FirstIt != FirstHashes.end() && SecondIt != SecondHashes.end() &&
        FirstIt->second == SecondIt->second) {
      ++FirstIt;
      ++SecondIt;
      continue;
    }

    DR.FirstDecl = FirstIt == FirstHashes.end() ? nullptr : FirstIt->first;
    DR.SecondDecl = SecondIt == SecondHashes.end() ? nullptr : SecondIt->first;

    DR.FirstDiffType =
        DR.FirstDecl ? DifferenceSelector(DR.FirstDecl) : EndOfClass;
    DR.SecondDiffType =
        DR.SecondDecl ? DifferenceSelector(DR.SecondDecl) : EndOfClass;
    return DR;
  }
  return DR;
}

void ODRDiagsEmitter::diagnoseSubMismatchUnexpected(
    DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule,
    const NamedDecl *SecondRecord, StringRef SecondModule) const {
  Diag(FirstRecord->getLocation(),
       diag::err_module_odr_violation_different_definitions)
      << FirstRecord << FirstModule.empty() << FirstModule;

  if (DR.FirstDecl) {
    Diag(DR.FirstDecl->getLocation(), diag::note_first_module_difference)
        << FirstRecord << DR.FirstDecl->getSourceRange();
  }

  Diag(SecondRecord->getLocation(),
       diag::note_module_odr_violation_different_definitions)
      << SecondModule;

  if (DR.SecondDecl) {
    Diag(DR.SecondDecl->getLocation(), diag::note_second_module_difference)
        << DR.SecondDecl->getSourceRange();
  }
}

void ODRDiagsEmitter::diagnoseSubMismatchDifferentDeclKinds(
    DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule,
    const NamedDecl *SecondRecord, StringRef SecondModule) const {
  auto GetMismatchedDeclLoc = [](const NamedDecl *Container,
                                 ODRMismatchDecl DiffType, const Decl *D) {
    SourceLocation Loc;
    SourceRange Range;
    if (DiffType == EndOfClass) {
      if (auto *Tag = dyn_cast<TagDecl>(Container))
        Loc = Tag->getBraceRange().getEnd();
      else if (auto *IF = dyn_cast<ObjCInterfaceDecl>(Container))
        Loc = IF->getAtEndRange().getBegin();
      else
        Loc = Container->getEndLoc();
    } else {
      Loc = D->getLocation();
      Range = D->getSourceRange();
    }
    return std::make_pair(Loc, Range);
  };

  auto FirstDiagInfo =
      GetMismatchedDeclLoc(FirstRecord, DR.FirstDiffType, DR.FirstDecl);
  Diag(FirstDiagInfo.first, diag::err_module_odr_violation_mismatch_decl)
      << FirstRecord << FirstModule.empty() << FirstModule
      << FirstDiagInfo.second << DR.FirstDiffType;

  auto SecondDiagInfo =
      GetMismatchedDeclLoc(SecondRecord, DR.SecondDiffType, DR.SecondDecl);
  Diag(SecondDiagInfo.first, diag::note_module_odr_violation_mismatch_decl)
      << SecondModule.empty() << SecondModule << SecondDiagInfo.second
      << DR.SecondDiffType;
}

bool ODRDiagsEmitter::diagnoseMismatch(
    const CXXRecordDecl *FirstRecord, const CXXRecordDecl *SecondRecord,
    const struct CXXRecordDecl::DefinitionData *SecondDD) const {
  // Multiple different declarations got merged together; tell the user
  // where they came from.
  if (FirstRecord == SecondRecord)
    return false;

  std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord);
  std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);

  const struct CXXRecordDecl::DefinitionData *FirstDD =
      FirstRecord->DefinitionData;
  assert(FirstDD && SecondDD && "Definitions without DefinitionData");

  // Diagnostics from DefinitionData are emitted here.
  if (FirstDD != SecondDD) {
    // Keep in sync with err_module_odr_violation_definition_data.
    enum ODRDefinitionDataDifference {
      NumBases,
      NumVBases,
      BaseType,
      BaseVirtual,
      BaseAccess,
    };
    auto DiagBaseError = [FirstRecord, &FirstModule,
                          this](SourceLocation Loc, SourceRange Range,
                                ODRDefinitionDataDifference DiffType) {
      return Diag(Loc, diag::err_module_odr_violation_definition_data)
             << FirstRecord << FirstModule.empty() << FirstModule << Range
             << DiffType;
    };
    auto DiagBaseNote = [&SecondModule,
                         this](SourceLocation Loc, SourceRange Range,
                               ODRDefinitionDataDifference DiffType) {
      return Diag(Loc, diag::note_module_odr_violation_definition_data)
             << SecondModule << Range << DiffType;
    };
    auto GetSourceRange = [](const struct CXXRecordDecl::DefinitionData *DD) {
      unsigned NumBases = DD->NumBases;
      if (NumBases == 0)
        return SourceRange();
      ArrayRef<CXXBaseSpecifier> bases = DD->bases();
      return SourceRange(bases[0].getBeginLoc(),
                         bases[NumBases - 1].getEndLoc());
    };

    unsigned FirstNumBases = FirstDD->NumBases;
    unsigned FirstNumVBases = FirstDD->NumVBases;
    unsigned SecondNumBases = SecondDD->NumBases;
    unsigned SecondNumVBases = SecondDD->NumVBases;
    if (FirstNumBases != SecondNumBases) {
      DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
                    NumBases)
          << FirstNumBases;
      DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
                   NumBases)
          << SecondNumBases;
      return true;
    }

    if (FirstNumVBases != SecondNumVBases) {
      DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
                    NumVBases)
          << FirstNumVBases;
      DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),
                   NumVBases)
          << SecondNumVBases;
      return true;
    }

    ArrayRef<CXXBaseSpecifier> FirstBases = FirstDD->bases();
    ArrayRef<CXXBaseSpecifier> SecondBases = SecondDD->bases();
    for (unsigned I = 0; I < FirstNumBases; ++I) {
      const CXXBaseSpecifier FirstBase = FirstBases[I];
      const CXXBaseSpecifier SecondBase = SecondBases[I];
      if (computeODRHash(FirstBase.getType()) !=
          computeODRHash(SecondBase.getType())) {
        DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
                      BaseType)
            << (I + 1) << FirstBase.getType();
        DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(),
                     BaseType)
            << (I + 1) << SecondBase.getType();
        return true;
      }

      if (FirstBase.isVirtual() != SecondBase.isVirtual()) {
        DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
                      BaseVirtual)
            << (I + 1) << FirstBase.isVirtual() << FirstBase.getType();
        DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(),
                     BaseVirtual)
            << (I + 1) << SecondBase.isVirtual() << SecondBase.getType();
        return true;
      }

      if (FirstBase.getAccessSpecifierAsWritten() !=
          SecondBase.getAccessSpecifierAsWritten()) {
        DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(),
                      BaseAccess)
            << (I + 1) << FirstBase.getType()
            << (int)FirstBase.getAccessSpecifierAsWritten();
        DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(),
                     BaseAccess)
            << (I + 1) << SecondBase.getType()
            << (int)SecondBase.getAccessSpecifierAsWritten();
        return true;
      }
    }
  }

  const ClassTemplateDecl *FirstTemplate =
      FirstRecord->getDescribedClassTemplate();
  const ClassTemplateDecl *SecondTemplate =
      SecondRecord->getDescribedClassTemplate();

  assert(!FirstTemplate == !SecondTemplate &&
         "Both pointers should be null or non-null");

  if (FirstTemplate && SecondTemplate) {
    ArrayRef<const NamedDecl *> FirstTemplateParams =
        FirstTemplate->getTemplateParameters()->asArray();
    ArrayRef<const NamedDecl *> SecondTemplateParams =
        SecondTemplate->getTemplateParameters()->asArray();
    assert(FirstTemplateParams.size() == SecondTemplateParams.size() &&
           "Number of template parameters should be equal.");
    for (auto Pair : llvm::zip(FirstTemplateParams, SecondTemplateParams)) {
      const NamedDecl *FirstDecl = std::get<0>(Pair);
      const NamedDecl *SecondDecl = std::get<1>(Pair);
      if (computeODRHash(FirstDecl) == computeODRHash(SecondDecl))
        continue;

      assert(FirstDecl->getKind() == SecondDecl->getKind() &&
             "Parameter Decl's should be the same kind.");

      enum ODRTemplateDifference {
        ParamEmptyName,
        ParamName,
        ParamSingleDefaultArgument,
        ParamDifferentDefaultArgument,
      };

      auto hasDefaultArg = [](const NamedDecl *D) {
        if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(D))
          return TTP->hasDefaultArgument() &&
                 !TTP->defaultArgumentWasInherited();
        if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
          return NTTP->hasDefaultArgument() &&
                 !NTTP->defaultArgumentWasInherited();
        auto *TTP = cast<TemplateTemplateParmDecl>(D);
        return TTP->hasDefaultArgument() && !TTP->defaultArgumentWasInherited();
      };
      bool hasFirstArg = hasDefaultArg(FirstDecl);
      bool hasSecondArg = hasDefaultArg(SecondDecl);

      ODRTemplateDifference ErrDiffType;
      ODRTemplateDifference NoteDiffType;

      DeclarationName FirstName = FirstDecl->getDeclName();
      DeclarationName SecondName = SecondDecl->getDeclName();

      if (FirstName != SecondName) {
        bool FirstNameEmpty =
            FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo();
        bool SecondNameEmpty =
            SecondName.isIdentifier() && !SecondName.getAsIdentifierInfo();
        ErrDiffType = FirstNameEmpty ? ParamEmptyName : ParamName;
        NoteDiffType = SecondNameEmpty ? ParamEmptyName : ParamName;
      } else if (hasFirstArg == hasSecondArg)
        ErrDiffType = NoteDiffType = ParamDifferentDefaultArgument;
      else
        ErrDiffType = NoteDiffType = ParamSingleDefaultArgument;

      Diag(FirstDecl->getLocation(),
           diag::err_module_odr_violation_template_parameter)
          << FirstRecord << FirstModule.empty() << FirstModule
          << FirstDecl->getSourceRange() << ErrDiffType << hasFirstArg
          << FirstName;
      Diag(SecondDecl->getLocation(),
           diag::note_module_odr_violation_template_parameter)
          << SecondModule << SecondDecl->getSourceRange() << NoteDiffType
          << hasSecondArg << SecondName;
      return true;
    }
  }

  auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record,
                           const DeclContext *DC) {
    for (const Decl *D : Record->decls()) {
      if (!ODRHash::isSubDeclToBeProcessed(D, DC))
        continue;
      Hashes.emplace_back(D, computeODRHash(D));
    }
  };

  DeclHashes FirstHashes;
  DeclHashes SecondHashes;
  const DeclContext *DC = FirstRecord;
  PopulateHashes(FirstHashes, FirstRecord, DC);
  PopulateHashes(SecondHashes, SecondRecord, DC);

  DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
  ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
  ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
  const Decl *FirstDecl = DR.FirstDecl;
  const Decl *SecondDecl = DR.SecondDecl;

  if (FirstDiffType == Other || SecondDiffType == Other) {
    diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
                                  SecondModule);
    return true;
  }

  if (FirstDiffType != SecondDiffType) {
    diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule,
                                          SecondRecord, SecondModule);
    return true;
  }

  // Used with err_module_odr_violation_record and
  // note_module_odr_violation_record
  enum ODRCXXRecordDifference {
    StaticAssertCondition,
    StaticAssertMessage,
    StaticAssertOnlyMessage,
    MethodName,
    MethodDeleted,
    MethodDefaulted,
    MethodVirtual,
    MethodStatic,
    MethodVolatile,
    MethodConst,
    MethodInline,
    MethodParameterSingleDefaultArgument,
    MethodParameterDifferentDefaultArgument,
    MethodNoTemplateArguments,
    MethodDifferentNumberTemplateArguments,
    MethodDifferentTemplateArgument,
    MethodSingleBody,
    MethodDifferentBody,
    FriendTypeFunction,
    FriendType,
    FriendFunction,
    FunctionTemplateDifferentNumberParameters,
    FunctionTemplateParameterDifferentKind,
    FunctionTemplateParameterName,
    FunctionTemplateParameterSingleDefaultArgument,
    FunctionTemplateParameterDifferentDefaultArgument,
    FunctionTemplateParameterDifferentType,
    FunctionTemplatePackParameter,
  };
  auto DiagError = [FirstRecord, &FirstModule,
                    this](SourceLocation Loc, SourceRange Range,
                          ODRCXXRecordDifference DiffType) {
    return Diag(Loc, diag::err_module_odr_violation_record)
           << FirstRecord << FirstModule.empty() << FirstModule << Range
           << DiffType;
  };
  auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
                                        ODRCXXRecordDifference DiffType) {
    return Diag(Loc, diag::note_module_odr_violation_record)
           << SecondModule << Range << DiffType;
  };

  assert(FirstDiffType == SecondDiffType);
  switch (FirstDiffType) {
  case Other:
  case EndOfClass:
  case PublicSpecifer:
  case PrivateSpecifer:
  case ProtectedSpecifer:
  case ObjCMethod:
  case ObjCIvar:
  case ObjCProperty:
    llvm_unreachable("Invalid diff type");

  case StaticAssert: {
    const StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl);
    const StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl);

    const Expr *FirstExpr = FirstSA->getAssertExpr();
    const Expr *SecondExpr = SecondSA->getAssertExpr();
    unsigned FirstODRHash = computeODRHash(FirstExpr);
    unsigned SecondODRHash = computeODRHash(SecondExpr);
    if (FirstODRHash != SecondODRHash) {
      DiagError(FirstExpr->getBeginLoc(), FirstExpr->getSourceRange(),
                StaticAssertCondition);
      DiagNote(SecondExpr->getBeginLoc(), SecondExpr->getSourceRange(),
               StaticAssertCondition);
      return true;
    }

    const Expr *FirstMessage = FirstSA->getMessage();
    const Expr *SecondMessage = SecondSA->getMessage();
    assert((FirstMessage || SecondMessage) && "Both messages cannot be empty");
    if ((FirstMessage && !SecondMessage) || (!FirstMessage && SecondMessage)) {
      SourceLocation FirstLoc, SecondLoc;
      SourceRange FirstRange, SecondRange;
      if (FirstMessage) {
        FirstLoc = FirstMessage->getBeginLoc();
        FirstRange = FirstMessage->getSourceRange();
      } else {
        FirstLoc = FirstSA->getBeginLoc();
        FirstRange = FirstSA->getSourceRange();
      }
      if (SecondMessage) {
        SecondLoc = SecondMessage->getBeginLoc();
        SecondRange = SecondMessage->getSourceRange();
      } else {
        SecondLoc = SecondSA->getBeginLoc();
        SecondRange = SecondSA->getSourceRange();
      }
      DiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage)
          << (FirstMessage == nullptr);
      DiagNote(SecondLoc, SecondRange, StaticAssertOnlyMessage)
          << (SecondMessage == nullptr);
      return true;
    }

    if (FirstMessage && SecondMessage) {
      unsigned FirstMessageODRHash = computeODRHash(FirstMessage);
      unsigned SecondMessageODRHash = computeODRHash(SecondMessage);
      if (FirstMessageODRHash != SecondMessageODRHash) {
        DiagError(FirstMessage->getBeginLoc(), FirstMessage->getSourceRange(),
                  StaticAssertMessage);
        DiagNote(SecondMessage->getBeginLoc(), SecondMessage->getSourceRange(),
                 StaticAssertMessage);
        return true;
      }
    }
    break;
  }

  case Field: {
    if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule,
                                 cast<FieldDecl>(FirstDecl),
                                 cast<FieldDecl>(SecondDecl)))
      return true;
    break;
  }

  case CXXMethod: {
    enum {
      DiagMethod,
      DiagConstructor,
      DiagDestructor,
    } FirstMethodType,
        SecondMethodType;
    auto GetMethodTypeForDiagnostics = [](const CXXMethodDecl *D) {
      if (isa<CXXConstructorDecl>(D))
        return DiagConstructor;
      if (isa<CXXDestructorDecl>(D))
        return DiagDestructor;
      return DiagMethod;
    };
    const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl);
    const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl);
    FirstMethodType = GetMethodTypeForDiagnostics(FirstMethod);
    SecondMethodType = GetMethodTypeForDiagnostics(SecondMethod);
    DeclarationName FirstName = FirstMethod->getDeclName();
    DeclarationName SecondName = SecondMethod->getDeclName();
    auto DiagMethodError = [&DiagError, FirstMethod, FirstMethodType,
                            FirstName](ODRCXXRecordDifference DiffType) {
      return DiagError(FirstMethod->getLocation(),
                       FirstMethod->getSourceRange(), DiffType)
             << FirstMethodType << FirstName;
    };
    auto DiagMethodNote = [&DiagNote, SecondMethod, SecondMethodType,
                           SecondName](ODRCXXRecordDifference DiffType) {
      return DiagNote(SecondMethod->getLocation(),
                      SecondMethod->getSourceRange(), DiffType)
             << SecondMethodType << SecondName;
    };

    if (FirstMethodType != SecondMethodType || FirstName != SecondName) {
      DiagMethodError(MethodName);
      DiagMethodNote(MethodName);
      return true;
    }

    const bool FirstDeleted = FirstMethod->isDeletedAsWritten();
    const bool SecondDeleted = SecondMethod->isDeletedAsWritten();
    if (FirstDeleted != SecondDeleted) {
      DiagMethodError(MethodDeleted) << FirstDeleted;
      DiagMethodNote(MethodDeleted) << SecondDeleted;
      return true;
    }

    const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted();
    const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted();
    if (FirstDefaulted != SecondDefaulted) {
      DiagMethodError(MethodDefaulted) << FirstDefaulted;
      DiagMethodNote(MethodDefaulted) << SecondDefaulted;
      return true;
    }

    const bool FirstVirtual = FirstMethod->isVirtualAsWritten();
    const bool SecondVirtual = SecondMethod->isVirtualAsWritten();
    const bool FirstPure = FirstMethod->isPure();
    const bool SecondPure = SecondMethod->isPure();
    if ((FirstVirtual || SecondVirtual) &&
        (FirstVirtual != SecondVirtual || FirstPure != SecondPure)) {
      DiagMethodError(MethodVirtual) << FirstPure << FirstVirtual;
      DiagMethodNote(MethodVirtual) << SecondPure << SecondVirtual;
      return true;
    }

    // CXXMethodDecl::isStatic uses the canonical Decl.  With Decl merging,
    // FirstDecl is the canonical Decl of SecondDecl, so the storage
    // class needs to be checked instead.
    StorageClass FirstStorage = FirstMethod->getStorageClass();
    StorageClass SecondStorage = SecondMethod->getStorageClass();
    const bool FirstStatic = FirstStorage == SC_Static;
    const bool SecondStatic = SecondStorage == SC_Static;
    if (FirstStatic != SecondStatic) {
      DiagMethodError(MethodStatic) << FirstStatic;
      DiagMethodNote(MethodStatic) << SecondStatic;
      return true;
    }

    const bool FirstVolatile = FirstMethod->isVolatile();
    const bool SecondVolatile = SecondMethod->isVolatile();
    if (FirstVolatile != SecondVolatile) {
      DiagMethodError(MethodVolatile) << FirstVolatile;
      DiagMethodNote(MethodVolatile) << SecondVolatile;
      return true;
    }

    const bool FirstConst = FirstMethod->isConst();
    const bool SecondConst = SecondMethod->isConst();
    if (FirstConst != SecondConst) {
      DiagMethodError(MethodConst) << FirstConst;
      DiagMethodNote(MethodConst) << SecondConst;
      return true;
    }

    const bool FirstInline = FirstMethod->isInlineSpecified();
    const bool SecondInline = SecondMethod->isInlineSpecified();
    if (FirstInline != SecondInline) {
      DiagMethodError(MethodInline) << FirstInline;
      DiagMethodNote(MethodInline) << SecondInline;
      return true;
    }

    if (diagnoseSubMismatchMethodParameters(Diags, FirstRecord,
                                            FirstModule, SecondModule,
                                            FirstMethod, SecondMethod))
      return true;

    for (unsigned I = 0, N = FirstMethod->param_size(); I < N; ++I) {
      const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);
      const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);

      const Expr *FirstInit = FirstParam->getInit();
      const Expr *SecondInit = SecondParam->getInit();
      if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
        DiagMethodError(MethodParameterSingleDefaultArgument)
            << (I + 1) << (FirstInit == nullptr)
            << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
        DiagMethodNote(MethodParameterSingleDefaultArgument)
            << (I + 1) << (SecondInit == nullptr)
            << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
        return true;
      }

      if (FirstInit && SecondInit &&
          computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
        DiagMethodError(MethodParameterDifferentDefaultArgument)
            << (I + 1) << FirstInit->getSourceRange();
        DiagMethodNote(MethodParameterDifferentDefaultArgument)
            << (I + 1) << SecondInit->getSourceRange();
        return true;
      }
    }

    const TemplateArgumentList *FirstTemplateArgs =
        FirstMethod->getTemplateSpecializationArgs();
    const TemplateArgumentList *SecondTemplateArgs =
        SecondMethod->getTemplateSpecializationArgs();

    if ((FirstTemplateArgs && !SecondTemplateArgs) ||
        (!FirstTemplateArgs && SecondTemplateArgs)) {
      DiagMethodError(MethodNoTemplateArguments)
          << (FirstTemplateArgs != nullptr);
      DiagMethodNote(MethodNoTemplateArguments)
          << (SecondTemplateArgs != nullptr);
      return true;
    }

    if (FirstTemplateArgs && SecondTemplateArgs) {
      // Remove pack expansions from argument list.
      auto ExpandTemplateArgumentList = [](const TemplateArgumentList *TAL) {
        llvm::SmallVector<const TemplateArgument *, 8> ExpandedList;
        for (const TemplateArgument &TA : TAL->asArray()) {
          if (TA.getKind() != TemplateArgument::Pack) {
            ExpandedList.push_back(&TA);
            continue;
          }
          llvm::append_range(ExpandedList,
                             llvm::make_pointer_range(TA.getPackAsArray()));
        }
        return ExpandedList;
      };
      llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList =
          ExpandTemplateArgumentList(FirstTemplateArgs);
      llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList =
          ExpandTemplateArgumentList(SecondTemplateArgs);

      if (FirstExpandedList.size() != SecondExpandedList.size()) {
        DiagMethodError(MethodDifferentNumberTemplateArguments)
            << (unsigned)FirstExpandedList.size();
        DiagMethodNote(MethodDifferentNumberTemplateArguments)
            << (unsigned)SecondExpandedList.size();
        return true;
      }

      for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) {
        const TemplateArgument &FirstTA = *FirstExpandedList[i],
                               &SecondTA = *SecondExpandedList[i];
        if (computeODRHash(FirstTA) == computeODRHash(SecondTA))
          continue;

        DiagMethodError(MethodDifferentTemplateArgument) << FirstTA << i + 1;
        DiagMethodNote(MethodDifferentTemplateArgument) << SecondTA << i + 1;
        return true;
      }
    }

    // Compute the hash of the method as if it has no body.
    auto ComputeCXXMethodODRHash = [](const CXXMethodDecl *D) {
      ODRHash Hasher;
      Hasher.AddFunctionDecl(D, true /*SkipBody*/);
      return Hasher.CalculateHash();
    };

    // Compare the hash generated to the hash stored.  A difference means
    // that a body was present in the original source.  Due to merging,
    // the standard way of detecting a body will not work.
    const bool HasFirstBody =
        ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash();
    const bool HasSecondBody =
        ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash();

    if (HasFirstBody != HasSecondBody) {
      DiagMethodError(MethodSingleBody) << HasFirstBody;
      DiagMethodNote(MethodSingleBody) << HasSecondBody;
      return true;
    }

    if (HasFirstBody && HasSecondBody) {
      DiagMethodError(MethodDifferentBody);
      DiagMethodNote(MethodDifferentBody);
      return true;
    }

    break;
  }

  case TypeAlias:
  case TypeDef: {
    if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule,
                                   cast<TypedefNameDecl>(FirstDecl),
                                   cast<TypedefNameDecl>(SecondDecl),
                                   FirstDiffType == TypeAlias))
      return true;
    break;
  }
  case Var: {
    if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,
                               cast<VarDecl>(FirstDecl),
                               cast<VarDecl>(SecondDecl)))
      return true;
    break;
  }
  case Friend: {
    const FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
    const FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);

    const NamedDecl *FirstND = FirstFriend->getFriendDecl();
    const NamedDecl *SecondND = SecondFriend->getFriendDecl();

    TypeSourceInfo *FirstTSI = FirstFriend->getFriendType();
    TypeSourceInfo *SecondTSI = SecondFriend->getFriendType();

    if (FirstND && SecondND) {
      DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(),
                FriendFunction)
          << FirstND;
      DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(),
               FriendFunction)
          << SecondND;
      return true;
    }

    if (FirstTSI && SecondTSI) {
      QualType FirstFriendType = FirstTSI->getType();
      QualType SecondFriendType = SecondTSI->getType();
      assert(computeODRHash(FirstFriendType) !=
             computeODRHash(SecondFriendType));
      DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(),
                FriendType)
          << FirstFriendType;
      DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(),
               FriendType)
          << SecondFriendType;
      return true;
    }

    DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(),
              FriendTypeFunction)
        << (FirstTSI == nullptr);
    DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(),
             FriendTypeFunction)
        << (SecondTSI == nullptr);
    return true;
  }
  case FunctionTemplate: {
    const FunctionTemplateDecl *FirstTemplate =
        cast<FunctionTemplateDecl>(FirstDecl);
    const FunctionTemplateDecl *SecondTemplate =
        cast<FunctionTemplateDecl>(SecondDecl);

    TemplateParameterList *FirstTPL = FirstTemplate->getTemplateParameters();
    TemplateParameterList *SecondTPL = SecondTemplate->getTemplateParameters();

    auto DiagTemplateError = [&DiagError,
                              FirstTemplate](ODRCXXRecordDifference DiffType) {
      return DiagError(FirstTemplate->getLocation(),
                       FirstTemplate->getSourceRange(), DiffType)
             << FirstTemplate;
    };
    auto DiagTemplateNote = [&DiagNote,
                             SecondTemplate](ODRCXXRecordDifference DiffType) {
      return DiagNote(SecondTemplate->getLocation(),
                      SecondTemplate->getSourceRange(), DiffType)
             << SecondTemplate;
    };

    if (FirstTPL->size() != SecondTPL->size()) {
      DiagTemplateError(FunctionTemplateDifferentNumberParameters)
          << FirstTPL->size();
      DiagTemplateNote(FunctionTemplateDifferentNumberParameters)
          << SecondTPL->size();
      return true;
    }

    for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) {
      NamedDecl *FirstParam = FirstTPL->getParam(i);
      NamedDecl *SecondParam = SecondTPL->getParam(i);

      if (FirstParam->getKind() != SecondParam->getKind()) {
        enum {
          TemplateTypeParameter,
          NonTypeTemplateParameter,
          TemplateTemplateParameter,
        };
        auto GetParamType = [](NamedDecl *D) {
          switch (D->getKind()) {
          default:
            llvm_unreachable("Unexpected template parameter type");
          case Decl::TemplateTypeParm:
            return TemplateTypeParameter;
          case Decl::NonTypeTemplateParm:
            return NonTypeTemplateParameter;
          case Decl::TemplateTemplateParm:
            return TemplateTemplateParameter;
          }
        };

        DiagTemplateError(FunctionTemplateParameterDifferentKind)
            << (i + 1) << GetParamType(FirstParam);
        DiagTemplateNote(FunctionTemplateParameterDifferentKind)
            << (i + 1) << GetParamType(SecondParam);
        return true;
      }

      if (FirstParam->getName() != SecondParam->getName()) {
        DiagTemplateError(FunctionTemplateParameterName)
            << (i + 1) << (bool)FirstParam->getIdentifier() << FirstParam;
        DiagTemplateNote(FunctionTemplateParameterName)
            << (i + 1) << (bool)SecondParam->getIdentifier() << SecondParam;
        return true;
      }

      if (isa<TemplateTypeParmDecl>(FirstParam) &&
          isa<TemplateTypeParmDecl>(SecondParam)) {
        TemplateTypeParmDecl *FirstTTPD =
            cast<TemplateTypeParmDecl>(FirstParam);
        TemplateTypeParmDecl *SecondTTPD =
            cast<TemplateTypeParmDecl>(SecondParam);
        bool HasFirstDefaultArgument =
            FirstTTPD->hasDefaultArgument() &&
            !FirstTTPD->defaultArgumentWasInherited();
        bool HasSecondDefaultArgument =
            SecondTTPD->hasDefaultArgument() &&
            !SecondTTPD->defaultArgumentWasInherited();
        if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
          DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
              << (i + 1) << HasFirstDefaultArgument;
          DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
              << (i + 1) << HasSecondDefaultArgument;
          return true;
        }

        if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
          QualType FirstType = FirstTTPD->getDefaultArgument();
          QualType SecondType = SecondTTPD->getDefaultArgument();
          if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
            DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
                << (i + 1) << FirstType;
            DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
                << (i + 1) << SecondType;
            return true;
          }
        }

        if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) {
          DiagTemplateError(FunctionTemplatePackParameter)
              << (i + 1) << FirstTTPD->isParameterPack();
          DiagTemplateNote(FunctionTemplatePackParameter)
              << (i + 1) << SecondTTPD->isParameterPack();
          return true;
        }
      }

      if (isa<TemplateTemplateParmDecl>(FirstParam) &&
          isa<TemplateTemplateParmDecl>(SecondParam)) {
        TemplateTemplateParmDecl *FirstTTPD =
            cast<TemplateTemplateParmDecl>(FirstParam);
        TemplateTemplateParmDecl *SecondTTPD =
            cast<TemplateTemplateParmDecl>(SecondParam);

        TemplateParameterList *FirstTPL = FirstTTPD->getTemplateParameters();
        TemplateParameterList *SecondTPL = SecondTTPD->getTemplateParameters();

        auto ComputeTemplateParameterListODRHash =
            [](const TemplateParameterList *TPL) {
              assert(TPL);
              ODRHash Hasher;
              Hasher.AddTemplateParameterList(TPL);
              return Hasher.CalculateHash();
            };

        if (ComputeTemplateParameterListODRHash(FirstTPL) !=
            ComputeTemplateParameterListODRHash(SecondTPL)) {
          DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);
          DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);
          return true;
        }

        bool HasFirstDefaultArgument =
            FirstTTPD->hasDefaultArgument() &&
            !FirstTTPD->defaultArgumentWasInherited();
        bool HasSecondDefaultArgument =
            SecondTTPD->hasDefaultArgument() &&
            !SecondTTPD->defaultArgumentWasInherited();
        if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
          DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
              << (i + 1) << HasFirstDefaultArgument;
          DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
              << (i + 1) << HasSecondDefaultArgument;
          return true;
        }

        if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
          TemplateArgument FirstTA =
              FirstTTPD->getDefaultArgument().getArgument();
          TemplateArgument SecondTA =
              SecondTTPD->getDefaultArgument().getArgument();
          if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) {
            DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
                << (i + 1) << FirstTA;
            DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
                << (i + 1) << SecondTA;
            return true;
          }
        }

        if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) {
          DiagTemplateError(FunctionTemplatePackParameter)
              << (i + 1) << FirstTTPD->isParameterPack();
          DiagTemplateNote(FunctionTemplatePackParameter)
              << (i + 1) << SecondTTPD->isParameterPack();
          return true;
        }
      }

      if (isa<NonTypeTemplateParmDecl>(FirstParam) &&
          isa<NonTypeTemplateParmDecl>(SecondParam)) {
        NonTypeTemplateParmDecl *FirstNTTPD =
            cast<NonTypeTemplateParmDecl>(FirstParam);
        NonTypeTemplateParmDecl *SecondNTTPD =
            cast<NonTypeTemplateParmDecl>(SecondParam);

        QualType FirstType = FirstNTTPD->getType();
        QualType SecondType = SecondNTTPD->getType();
        if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
          DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);
          DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);
          return true;
        }

        bool HasFirstDefaultArgument =
            FirstNTTPD->hasDefaultArgument() &&
            !FirstNTTPD->defaultArgumentWasInherited();
        bool HasSecondDefaultArgument =
            SecondNTTPD->hasDefaultArgument() &&
            !SecondNTTPD->defaultArgumentWasInherited();
        if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
          DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)
              << (i + 1) << HasFirstDefaultArgument;
          DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)
              << (i + 1) << HasSecondDefaultArgument;
          return true;
        }

        if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
          Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
          Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
          if (computeODRHash(FirstDefaultArgument) !=
              computeODRHash(SecondDefaultArgument)) {
            DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)
                << (i + 1) << FirstDefaultArgument;
            DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)
                << (i + 1) << SecondDefaultArgument;
            return true;
          }
        }

        if (FirstNTTPD->isParameterPack() != SecondNTTPD->isParameterPack()) {
          DiagTemplateError(FunctionTemplatePackParameter)
              << (i + 1) << FirstNTTPD->isParameterPack();
          DiagTemplateNote(FunctionTemplatePackParameter)
              << (i + 1) << SecondNTTPD->isParameterPack();
          return true;
        }
      }
    }
    break;
  }
  }

  Diag(FirstDecl->getLocation(),
       diag::err_module_odr_violation_mismatch_decl_unknown)
      << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
      << FirstDecl->getSourceRange();
  Diag(SecondDecl->getLocation(),
       diag::note_module_odr_violation_mismatch_decl_unknown)
      << SecondModule.empty() << SecondModule << FirstDiffType
      << SecondDecl->getSourceRange();
  return true;
}

bool ODRDiagsEmitter::diagnoseMismatch(const RecordDecl *FirstRecord,
                                       const RecordDecl *SecondRecord) const {
  if (FirstRecord == SecondRecord)
    return false;

  std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord);
  std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);

  auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record,
                           const DeclContext *DC) {
    for (const Decl *D : Record->decls()) {
      if (!ODRHash::isSubDeclToBeProcessed(D, DC))
        continue;
      Hashes.emplace_back(D, computeODRHash(D));
    }
  };

  DeclHashes FirstHashes;
  DeclHashes SecondHashes;
  const DeclContext *DC = FirstRecord;
  PopulateHashes(FirstHashes, FirstRecord, DC);
  PopulateHashes(SecondHashes, SecondRecord, DC);

  DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
  ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
  ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
  const Decl *FirstDecl = DR.FirstDecl;
  const Decl *SecondDecl = DR.SecondDecl;

  if (FirstDiffType == Other || SecondDiffType == Other) {
    diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
                                  SecondModule);
    return true;
  }

  if (FirstDiffType != SecondDiffType) {
    diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule,
                                          SecondRecord, SecondModule);
    return true;
  }

  assert(FirstDiffType == SecondDiffType);
  switch (FirstDiffType) {
  // Already handled.
  case EndOfClass:
  case Other:
  // C++ only, invalid in this context.
  case PublicSpecifer:
  case PrivateSpecifer:
  case ProtectedSpecifer:
  case StaticAssert:
  case CXXMethod:
  case TypeAlias:
  case Friend:
  case FunctionTemplate:
  // Cannot be contained by RecordDecl, invalid in this context.
  case ObjCMethod:
  case ObjCIvar:
  case ObjCProperty:
    llvm_unreachable("Invalid diff type");

  case Field: {
    if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule,
                                 cast<FieldDecl>(FirstDecl),
                                 cast<FieldDecl>(SecondDecl)))
      return true;
    break;
  }
  case TypeDef: {
    if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule,
                                   cast<TypedefNameDecl>(FirstDecl),
                                   cast<TypedefNameDecl>(SecondDecl),
                                   /*IsTypeAlias=*/false))
      return true;
    break;
  }
  case Var: {
    if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,
                               cast<VarDecl>(FirstDecl),
                               cast<VarDecl>(SecondDecl)))
      return true;
    break;
  }
  }

  Diag(FirstDecl->getLocation(),
       diag::err_module_odr_violation_mismatch_decl_unknown)
      << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType
      << FirstDecl->getSourceRange();
  Diag(SecondDecl->getLocation(),
       diag::note_module_odr_violation_mismatch_decl_unknown)
      << SecondModule.empty() << SecondModule << FirstDiffType
      << SecondDecl->getSourceRange();
  return true;
}

bool ODRDiagsEmitter::diagnoseMismatch(
    const FunctionDecl *FirstFunction,
    const FunctionDecl *SecondFunction) const {
  if (FirstFunction == SecondFunction)
    return false;

  // Keep in sync with select options in err_module_odr_violation_function.
  enum ODRFunctionDifference {
    ReturnType,
    ParameterName,
    ParameterType,
    ParameterSingleDefaultArgument,
    ParameterDifferentDefaultArgument,
    FunctionBody,
  };

  std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction);
  std::string SecondModule = getOwningModuleNameForDiagnostic(SecondFunction);

  auto DiagError = [FirstFunction, &FirstModule,
                    this](SourceLocation Loc, SourceRange Range,
                          ODRFunctionDifference DiffType) {
    return Diag(Loc, diag::err_module_odr_violation_function)
           << FirstFunction << FirstModule.empty() << FirstModule << Range
           << DiffType;
  };
  auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
                                        ODRFunctionDifference DiffType) {
    return Diag(Loc, diag::note_module_odr_violation_function)
           << SecondModule << Range << DiffType;
  };

  if (computeODRHash(FirstFunction->getReturnType()) !=
      computeODRHash(SecondFunction->getReturnType())) {
    DiagError(FirstFunction->getReturnTypeSourceRange().getBegin(),
              FirstFunction->getReturnTypeSourceRange(), ReturnType)
        << FirstFunction->getReturnType();
    DiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(),
             SecondFunction->getReturnTypeSourceRange(), ReturnType)
        << SecondFunction->getReturnType();
    return true;
  }

  assert(FirstFunction->param_size() == SecondFunction->param_size() &&
         "Merged functions with different number of parameters");

  size_t ParamSize = FirstFunction->param_size();
  for (unsigned I = 0; I < ParamSize; ++I) {
    const ParmVarDecl *FirstParam = FirstFunction->getParamDecl(I);
    const ParmVarDecl *SecondParam = SecondFunction->getParamDecl(I);

    assert(Context.hasSameType(FirstParam->getType(), SecondParam->getType()) &&
           "Merged function has different parameter types.");

    if (FirstParam->getDeclName() != SecondParam->getDeclName()) {
      DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
                ParameterName)
          << I + 1 << FirstParam->getDeclName();
      DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
               ParameterName)
          << I + 1 << SecondParam->getDeclName();
      return true;
    };

    QualType FirstParamType = FirstParam->getType();
    QualType SecondParamType = SecondParam->getType();
    if (FirstParamType != SecondParamType &&
        computeODRHash(FirstParamType) != computeODRHash(SecondParamType)) {
      if (const DecayedType *ParamDecayedType =
              FirstParamType->getAs<DecayedType>()) {
        DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
                  ParameterType)
            << (I + 1) << FirstParamType << true
            << ParamDecayedType->getOriginalType();
      } else {
        DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
                  ParameterType)
            << (I + 1) << FirstParamType << false;
      }

      if (const DecayedType *ParamDecayedType =
              SecondParamType->getAs<DecayedType>()) {
        DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
                 ParameterType)
            << (I + 1) << SecondParamType << true
            << ParamDecayedType->getOriginalType();
      } else {
        DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
                 ParameterType)
            << (I + 1) << SecondParamType << false;
      }
      return true;
    }

    // Note, these calls can trigger deserialization.
    const Expr *FirstInit = FirstParam->getInit();
    const Expr *SecondInit = SecondParam->getInit();
    if ((FirstInit == nullptr) != (SecondInit == nullptr)) {
      DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
                ParameterSingleDefaultArgument)
          << (I + 1) << (FirstInit == nullptr)
          << (FirstInit ? FirstInit->getSourceRange() : SourceRange());
      DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
               ParameterSingleDefaultArgument)
          << (I + 1) << (SecondInit == nullptr)
          << (SecondInit ? SecondInit->getSourceRange() : SourceRange());
      return true;
    }

    if (FirstInit && SecondInit &&
        computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
      DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
                ParameterDifferentDefaultArgument)
          << (I + 1) << FirstInit->getSourceRange();
      DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(),
               ParameterDifferentDefaultArgument)
          << (I + 1) << SecondInit->getSourceRange();
      return true;
    }

    assert(computeODRHash(FirstParam) == computeODRHash(SecondParam) &&
           "Undiagnosed parameter difference.");
  }

  // If no error has been generated before now, assume the problem is in
  // the body and generate a message.
  DiagError(FirstFunction->getLocation(), FirstFunction->getSourceRange(),
            FunctionBody);
  DiagNote(SecondFunction->getLocation(), SecondFunction->getSourceRange(),
           FunctionBody);
  return true;
}

bool ODRDiagsEmitter::diagnoseMismatch(const EnumDecl *FirstEnum,
                                       const EnumDecl *SecondEnum) const {
  if (FirstEnum == SecondEnum)
    return false;

  // Keep in sync with select options in err_module_odr_violation_enum.
  enum ODREnumDifference {
    SingleScopedEnum,
    EnumTagKeywordMismatch,
    SingleSpecifiedType,
    DifferentSpecifiedTypes,
    DifferentNumberEnumConstants,
    EnumConstantName,
    EnumConstantSingleInitializer,
    EnumConstantDifferentInitializer,
  };

  std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum);
  std::string SecondModule = getOwningModuleNameForDiagnostic(SecondEnum);

  auto DiagError = [FirstEnum, &FirstModule, this](const auto *DiagAnchor,
                                                   ODREnumDifference DiffType) {
    return Diag(DiagAnchor->getLocation(), diag::err_module_odr_violation_enum)
           << FirstEnum << FirstModule.empty() << FirstModule
           << DiagAnchor->getSourceRange() << DiffType;
  };
  auto DiagNote = [&SecondModule, this](const auto *DiagAnchor,
                                        ODREnumDifference DiffType) {
    return Diag(DiagAnchor->getLocation(), diag::note_module_odr_violation_enum)
           << SecondModule << DiagAnchor->getSourceRange() << DiffType;
  };

  if (FirstEnum->isScoped() != SecondEnum->isScoped()) {
    DiagError(FirstEnum, SingleScopedEnum) << FirstEnum->isScoped();
    DiagNote(SecondEnum, SingleScopedEnum) << SecondEnum->isScoped();
    return true;
  }

  if (FirstEnum->isScoped() && SecondEnum->isScoped()) {
    if (FirstEnum->isScopedUsingClassTag() !=
        SecondEnum->isScopedUsingClassTag()) {
      DiagError(FirstEnum, EnumTagKeywordMismatch)
          << FirstEnum->isScopedUsingClassTag();
      DiagNote(SecondEnum, EnumTagKeywordMismatch)
          << SecondEnum->isScopedUsingClassTag();
      return true;
    }
  }

  QualType FirstUnderlyingType =
      FirstEnum->getIntegerTypeSourceInfo()
          ? FirstEnum->getIntegerTypeSourceInfo()->getType()
          : QualType();
  QualType SecondUnderlyingType =
      SecondEnum->getIntegerTypeSourceInfo()
          ? SecondEnum->getIntegerTypeSourceInfo()->getType()
          : QualType();
  if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) {
    DiagError(FirstEnum, SingleSpecifiedType) << !FirstUnderlyingType.isNull();
    DiagNote(SecondEnum, SingleSpecifiedType) << !SecondUnderlyingType.isNull();
    return true;
  }

  if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {
    if (computeODRHash(FirstUnderlyingType) !=
        computeODRHash(SecondUnderlyingType)) {
      DiagError(FirstEnum, DifferentSpecifiedTypes) << FirstUnderlyingType;
      DiagNote(SecondEnum, DifferentSpecifiedTypes) << SecondUnderlyingType;
      return true;
    }
  }

  // Compare enum constants.
  using DeclHashes =
      llvm::SmallVector<std::pair<const EnumConstantDecl *, unsigned>, 4>;
  auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, const EnumDecl *Enum) {
    for (const Decl *D : Enum->decls()) {
      // Due to decl merging, the first EnumDecl is the parent of
      // Decls in both records.
      if (!ODRHash::isSubDeclToBeProcessed(D, FirstEnum))
        continue;
      assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind");
      Hashes.emplace_back(cast<EnumConstantDecl>(D), computeODRHash(D));
    }
  };
  DeclHashes FirstHashes;
  PopulateHashes(FirstHashes, FirstEnum);
  DeclHashes SecondHashes;
  PopulateHashes(SecondHashes, SecondEnum);

  if (FirstHashes.size() != SecondHashes.size()) {
    DiagError(FirstEnum, DifferentNumberEnumConstants)
        << (int)FirstHashes.size();
    DiagNote(SecondEnum, DifferentNumberEnumConstants)
        << (int)SecondHashes.size();
    return true;
  }

  for (unsigned I = 0, N = FirstHashes.size(); I < N; ++I) {
    if (FirstHashes[I].second == SecondHashes[I].second)
      continue;
    const EnumConstantDecl *FirstConstant = FirstHashes[I].first;
    const EnumConstantDecl *SecondConstant = SecondHashes[I].first;

    if (FirstConstant->getDeclName() != SecondConstant->getDeclName()) {
      DiagError(FirstConstant, EnumConstantName) << I + 1 << FirstConstant;
      DiagNote(SecondConstant, EnumConstantName) << I + 1 << SecondConstant;
      return true;
    }

    const Expr *FirstInit = FirstConstant->getInitExpr();
    const Expr *SecondInit = SecondConstant->getInitExpr();
    if (!FirstInit && !SecondInit)
      continue;

    if (!FirstInit || !SecondInit) {
      DiagError(FirstConstant, EnumConstantSingleInitializer)
          << I + 1 << FirstConstant << (FirstInit != nullptr);
      DiagNote(SecondConstant, EnumConstantSingleInitializer)
          << I + 1 << SecondConstant << (SecondInit != nullptr);
      return true;
    }

    if (computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
      DiagError(FirstConstant, EnumConstantDifferentInitializer)
          << I + 1 << FirstConstant;
      DiagNote(SecondConstant, EnumConstantDifferentInitializer)
          << I + 1 << SecondConstant;
      return true;
    }
  }
  return false;
}

bool ODRDiagsEmitter::diagnoseMismatch(
    const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID,
    const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const {
  // Multiple different declarations got merged together; tell the user
  // where they came from.
  if (FirstID == SecondID)
    return false;

  std::string FirstModule = getOwningModuleNameForDiagnostic(FirstID);
  std::string SecondModule = getOwningModuleNameForDiagnostic(SecondID);

  // Keep in sync with err_module_odr_violation_objc_interface.
  enum ODRInterfaceDifference {
    SuperClassType,
    IVarAccess,
  };

  auto DiagError = [FirstID, &FirstModule,
                    this](SourceLocation Loc, SourceRange Range,
                          ODRInterfaceDifference DiffType) {
    return Diag(Loc, diag::err_module_odr_violation_objc_interface)
           << FirstID << FirstModule.empty() << FirstModule << Range
           << DiffType;
  };
  auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range,
                                        ODRInterfaceDifference DiffType) {
    return Diag(Loc, diag::note_module_odr_violation_objc_interface)
           << SecondModule.empty() << SecondModule << Range << DiffType;
  };

  const struct ObjCInterfaceDecl::DefinitionData *FirstDD = &FirstID->data();
  assert(FirstDD && SecondDD && "Definitions without DefinitionData");
  if (FirstDD != SecondDD) {
    // Check for matching super class.
    auto GetSuperClassSourceRange = [](const TypeSourceInfo *SuperInfo,
                                       const ObjCInterfaceDecl *ID) {
      if (!SuperInfo)
        return ID->getSourceRange();
      TypeLoc Loc = SuperInfo->getTypeLoc();
      return SourceRange(Loc.getBeginLoc(), Loc.getEndLoc());
    };

    ObjCInterfaceDecl *FirstSuperClass = FirstID->getSuperClass();
    ObjCInterfaceDecl *SecondSuperClass = nullptr;
    const TypeSourceInfo *FirstSuperInfo = FirstID->getSuperClassTInfo();
    const TypeSourceInfo *SecondSuperInfo = SecondDD->SuperClassTInfo;
    if (SecondSuperInfo)
      SecondSuperClass =
          SecondSuperInfo->getType()->castAs<ObjCObjectType>()->getInterface();

    if ((FirstSuperClass && SecondSuperClass &&
         FirstSuperClass->getODRHash() != SecondSuperClass->getODRHash()) ||
        (FirstSuperClass && !SecondSuperClass) ||
        (!FirstSuperClass && SecondSuperClass)) {
      QualType FirstType;
      if (FirstSuperInfo)
        FirstType = FirstSuperInfo->getType();

      DiagError(FirstID->getLocation(),
                GetSuperClassSourceRange(FirstSuperInfo, FirstID),
                SuperClassType)
          << (bool)FirstSuperInfo << FirstType;

      QualType SecondType;
      if (SecondSuperInfo)
        SecondType = SecondSuperInfo->getType();

      DiagNote(SecondID->getLocation(),
               GetSuperClassSourceRange(SecondSuperInfo, SecondID),
               SuperClassType)
          << (bool)SecondSuperInfo << SecondType;
      return true;
    }

    // Check both interfaces reference the same protocols.
    auto &FirstProtos = FirstID->getReferencedProtocols();
    auto &SecondProtos = SecondDD->ReferencedProtocols;
    if (diagnoseSubMismatchProtocols(FirstProtos, FirstID, FirstModule,
                                     SecondProtos, SecondID, SecondModule))
      return true;
  }

  auto PopulateHashes = [](DeclHashes &Hashes, const ObjCInterfaceDecl *ID,
                           const DeclContext *DC) {
    for (auto *D : ID->decls()) {
      if (!ODRHash::isSubDeclToBeProcessed(D, DC))
        continue;
      Hashes.emplace_back(D, computeODRHash(D));
    }
  };

  DeclHashes FirstHashes;
  DeclHashes SecondHashes;
  // Use definition as DeclContext because definitions are merged when
  // DeclContexts are merged and separate when DeclContexts are separate.
  PopulateHashes(FirstHashes, FirstID, FirstID->getDefinition());
  PopulateHashes(SecondHashes, SecondID, SecondID->getDefinition());

  DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
  ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
  ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
  const Decl *FirstDecl = DR.FirstDecl;
  const Decl *SecondDecl = DR.SecondDecl;

  if (FirstDiffType == Other || SecondDiffType == Other) {
    diagnoseSubMismatchUnexpected(DR, FirstID, FirstModule, SecondID,
                                  SecondModule);
    return true;
  }

  if (FirstDiffType != SecondDiffType) {
    diagnoseSubMismatchDifferentDeclKinds(DR, FirstID, FirstModule, SecondID,
                                          SecondModule);
    return true;
  }

  assert(FirstDiffType == SecondDiffType);
  switch (FirstDiffType) {
  // Already handled.
  case EndOfClass:
  case Other:
  // Cannot be contained by ObjCInterfaceDecl, invalid in this context.
  case Field:
  case TypeDef:
  case Var:
  // C++ only, invalid in this context.
  case PublicSpecifer:
  case PrivateSpecifer:
  case ProtectedSpecifer:
  case StaticAssert:
  case CXXMethod:
  case TypeAlias:
  case Friend:
  case FunctionTemplate:
    llvm_unreachable("Invalid diff type");

  case ObjCMethod: {
    if (diagnoseSubMismatchObjCMethod(FirstID, FirstModule, SecondModule,
                                      cast<ObjCMethodDecl>(FirstDecl),
                                      cast<ObjCMethodDecl>(SecondDecl)))
      return true;
    break;
  }
  case ObjCIvar: {
    if (diagnoseSubMismatchField(FirstID, FirstModule, SecondModule,
                                 cast<FieldDecl>(FirstDecl),
                                 cast<FieldDecl>(SecondDecl)))
      return true;

    // Check if the access match.
    const ObjCIvarDecl *FirstIvar = cast<ObjCIvarDecl>(FirstDecl);
    const ObjCIvarDecl *SecondIvar = cast<ObjCIvarDecl>(SecondDecl);
    if (FirstIvar->getCanonicalAccessControl() !=
        SecondIvar->getCanonicalAccessControl()) {
      DiagError(FirstIvar->getLocation(), FirstIvar->getSourceRange(),
                IVarAccess)
          << FirstIvar->getName()
          << (int)FirstIvar->getCanonicalAccessControl();
      DiagNote(SecondIvar->getLocation(), SecondIvar->getSourceRange(),
               IVarAccess)
          << SecondIvar->getName()
          << (int)SecondIvar->getCanonicalAccessControl();
      return true;
    }
    break;
  }
  case ObjCProperty: {
    if (diagnoseSubMismatchObjCProperty(FirstID, FirstModule, SecondModule,
                                        cast<ObjCPropertyDecl>(FirstDecl),
                                        cast<ObjCPropertyDecl>(SecondDecl)))
      return true;
    break;
  }
  }

  Diag(FirstDecl->getLocation(),
       diag::err_module_odr_violation_mismatch_decl_unknown)
      << FirstID << FirstModule.empty() << FirstModule << FirstDiffType
      << FirstDecl->getSourceRange();
  Diag(SecondDecl->getLocation(),
       diag::note_module_odr_violation_mismatch_decl_unknown)
      << SecondModule.empty() << SecondModule << FirstDiffType
      << SecondDecl->getSourceRange();
  return true;
}

bool ODRDiagsEmitter::diagnoseMismatch(
    const ObjCProtocolDecl *FirstProtocol,
    const ObjCProtocolDecl *SecondProtocol,
    const struct ObjCProtocolDecl::DefinitionData *SecondDD) const {
  if (FirstProtocol == SecondProtocol)
    return false;

  std::string FirstModule = getOwningModuleNameForDiagnostic(FirstProtocol);
  std::string SecondModule = getOwningModuleNameForDiagnostic(SecondProtocol);

  const ObjCProtocolDecl::DefinitionData *FirstDD = &FirstProtocol->data();
  assert(FirstDD && SecondDD && "Definitions without DefinitionData");
  // Diagnostics from ObjCProtocol DefinitionData are emitted here.
  if (FirstDD != SecondDD) {
    // Check both protocols reference the same protocols.
    const ObjCProtocolList &FirstProtocols =
        FirstProtocol->getReferencedProtocols();
    const ObjCProtocolList &SecondProtocols = SecondDD->ReferencedProtocols;
    if (diagnoseSubMismatchProtocols(FirstProtocols, FirstProtocol, FirstModule,
                                     SecondProtocols, SecondProtocol,
                                     SecondModule))
      return true;
  }

  auto PopulateHashes = [](DeclHashes &Hashes, const ObjCProtocolDecl *ID,
                           const DeclContext *DC) {
    for (const Decl *D : ID->decls()) {
      if (!ODRHash::isSubDeclToBeProcessed(D, DC))
        continue;
      Hashes.emplace_back(D, computeODRHash(D));
    }
  };

  DeclHashes FirstHashes;
  DeclHashes SecondHashes;
  // Use definition as DeclContext because definitions are merged when
  // DeclContexts are merged and separate when DeclContexts are separate.
  PopulateHashes(FirstHashes, FirstProtocol, FirstProtocol->getDefinition());
  PopulateHashes(SecondHashes, SecondProtocol, SecondProtocol->getDefinition());

  DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
  ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
  ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
  const Decl *FirstDecl = DR.FirstDecl;
  const Decl *SecondDecl = DR.SecondDecl;

  if (FirstDiffType == Other || SecondDiffType == Other) {
    diagnoseSubMismatchUnexpected(DR, FirstProtocol, FirstModule,
                                  SecondProtocol, SecondModule);
    return true;
  }

  if (FirstDiffType != SecondDiffType) {
    diagnoseSubMismatchDifferentDeclKinds(DR, FirstProtocol, FirstModule,
                                          SecondProtocol, SecondModule);
    return true;
  }

  assert(FirstDiffType == SecondDiffType);
  switch (FirstDiffType) {
  // Already handled.
  case EndOfClass:
  case Other:
  // Cannot be contained by ObjCProtocolDecl, invalid in this context.
  case Field:
  case TypeDef:
  case Var:
  case ObjCIvar:
  // C++ only, invalid in this context.
  case PublicSpecifer:
  case PrivateSpecifer:
  case ProtectedSpecifer:
  case StaticAssert:
  case CXXMethod:
  case TypeAlias:
  case Friend:
  case FunctionTemplate:
    llvm_unreachable("Invalid diff type");
  case ObjCMethod: {
    if (diagnoseSubMismatchObjCMethod(FirstProtocol, FirstModule, SecondModule,
                                      cast<ObjCMethodDecl>(FirstDecl),
                                      cast<ObjCMethodDecl>(SecondDecl)))
      return true;
    break;
  }
  case ObjCProperty: {
    if (diagnoseSubMismatchObjCProperty(FirstProtocol, FirstModule,
                                        SecondModule,
                                        cast<ObjCPropertyDecl>(FirstDecl),
                                        cast<ObjCPropertyDecl>(SecondDecl)))
      return true;
    break;
  }
  }

  Diag(FirstDecl->getLocation(),
       diag::err_module_odr_violation_mismatch_decl_unknown)
      << FirstProtocol << FirstModule.empty() << FirstModule << FirstDiffType
      << FirstDecl->getSourceRange();
  Diag(SecondDecl->getLocation(),
       diag::note_module_odr_violation_mismatch_decl_unknown)
      << SecondModule.empty() << SecondModule << FirstDiffType
      << SecondDecl->getSourceRange();
  return true;
}
