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