forked from OSchip/llvm-project
[ODRHash diagnostics] Preparation to minimize subsequent diffs. NFC.
Specifically, making the following changes: * Turn lambdas calculating ODR hashes into static functions. * Move `ODRCXXRecordDifference` where it is used. * Rename some variables and move some lines of code. * Replace `auto` with explicit type when the deduced type is not mentioned. * Add `const` for unmodified objects, so we can pass them to more functions. Differential Revision: https://reviews.llvm.org/D128690
This commit is contained in:
parent
f84712f0b8
commit
f693874c53
|
@ -9445,6 +9445,31 @@ void ASTReader::finishPendingActions() {
|
|||
PendingMergedDefinitionsToDeduplicate.clear();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void ASTReader::diagnoseOdrViolations() {
|
||||
if (PendingOdrMergeFailures.empty() && PendingOdrMergeChecks.empty() &&
|
||||
PendingFunctionOdrMergeFailures.empty() &&
|
||||
|
@ -9584,42 +9609,6 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
// we're producing our diagnostics.
|
||||
Deserializing RecursionGuard(this);
|
||||
|
||||
// Common code for hashing helpers.
|
||||
ODRHash Hash;
|
||||
auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
|
||||
Hash.clear();
|
||||
Hash.AddQualType(Ty);
|
||||
return Hash.CalculateHash();
|
||||
};
|
||||
|
||||
auto ComputeODRHash = [&Hash](const Stmt *S) {
|
||||
assert(S);
|
||||
Hash.clear();
|
||||
Hash.AddStmt(S);
|
||||
return Hash.CalculateHash();
|
||||
};
|
||||
|
||||
auto ComputeSubDeclODRHash = [&Hash](const Decl *D) {
|
||||
assert(D);
|
||||
Hash.clear();
|
||||
Hash.AddSubDecl(D);
|
||||
return Hash.CalculateHash();
|
||||
};
|
||||
|
||||
auto ComputeTemplateArgumentODRHash = [&Hash](const TemplateArgument &TA) {
|
||||
Hash.clear();
|
||||
Hash.AddTemplateArgument(TA);
|
||||
return Hash.CalculateHash();
|
||||
};
|
||||
|
||||
auto ComputeTemplateParameterListODRHash =
|
||||
[&Hash](const TemplateParameterList *TPL) {
|
||||
assert(TPL);
|
||||
Hash.clear();
|
||||
Hash.AddTemplateParameterList(TPL);
|
||||
return Hash.CalculateHash();
|
||||
};
|
||||
|
||||
// Used with err_module_odr_violation_mismatch_decl and
|
||||
// note_module_odr_violation_mismatch_decl
|
||||
// This list should be the same Decl's as in ODRHash::isDeclToBeProcessed
|
||||
|
@ -9639,49 +9628,13 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
Other
|
||||
};
|
||||
|
||||
// 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,
|
||||
MethodNumberParameters,
|
||||
MethodParameterType,
|
||||
MethodParameterName,
|
||||
MethodParameterSingleDefaultArgument,
|
||||
MethodParameterDifferentDefaultArgument,
|
||||
MethodNoTemplateArguments,
|
||||
MethodDifferentNumberTemplateArguments,
|
||||
MethodDifferentTemplateArgument,
|
||||
MethodSingleBody,
|
||||
MethodDifferentBody,
|
||||
FriendTypeFunction,
|
||||
FriendType,
|
||||
FriendFunction,
|
||||
FunctionTemplateDifferentNumberParameters,
|
||||
FunctionTemplateParameterDifferentKind,
|
||||
FunctionTemplateParameterName,
|
||||
FunctionTemplateParameterSingleDefaultArgument,
|
||||
FunctionTemplateParameterDifferentDefaultArgument,
|
||||
FunctionTemplateParameterDifferentType,
|
||||
FunctionTemplatePackParameter,
|
||||
};
|
||||
|
||||
// These lambdas have the common portions of the ODR diagnostics. This
|
||||
// has the same return as Diag(), so addition parameters can be passed
|
||||
// in with operator<<
|
||||
auto ODRDiagField = [this, &ComputeQualTypeODRHash, &ComputeODRHash](
|
||||
NamedDecl *FirstRecord, StringRef FirstModule,
|
||||
StringRef SecondModule, FieldDecl *FirstField,
|
||||
FieldDecl *SecondField) {
|
||||
auto ODRDiagField = [this](NamedDecl *FirstRecord, StringRef FirstModule,
|
||||
StringRef SecondModule,
|
||||
const FieldDecl *FirstField,
|
||||
const FieldDecl *SecondField) {
|
||||
enum ODRFieldDifference {
|
||||
FieldName,
|
||||
FieldTypeName,
|
||||
|
@ -9719,8 +9672,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
|
||||
QualType FirstType = FirstField->getType();
|
||||
QualType SecondType = SecondField->getType();
|
||||
if (ComputeQualTypeODRHash(FirstType) !=
|
||||
ComputeQualTypeODRHash(SecondType)) {
|
||||
if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
|
||||
DiagError(FieldTypeName) << FirstII << FirstType;
|
||||
DiagNote(FieldTypeName) << SecondII << SecondType;
|
||||
return true;
|
||||
|
@ -9735,10 +9687,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
if (IsFirstBitField && IsSecondBitField) {
|
||||
unsigned FirstBitWidthHash =
|
||||
ComputeODRHash(FirstField->getBitWidth());
|
||||
unsigned SecondBitWidthHash =
|
||||
ComputeODRHash(SecondField->getBitWidth());
|
||||
unsigned FirstBitWidthHash = computeODRHash(FirstField->getBitWidth());
|
||||
unsigned SecondBitWidthHash = computeODRHash(SecondField->getBitWidth());
|
||||
if (FirstBitWidthHash != SecondBitWidthHash) {
|
||||
DiagError(FieldDifferentWidthBitField)
|
||||
<< FirstII << FirstField->getBitWidth()->getSourceRange();
|
||||
|
@ -9771,8 +9721,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
if (FirstInitializer && SecondInitializer) {
|
||||
unsigned FirstInitHash = ComputeODRHash(FirstInitializer);
|
||||
unsigned SecondInitHash = ComputeODRHash(SecondInitializer);
|
||||
unsigned FirstInitHash = computeODRHash(FirstInitializer);
|
||||
unsigned SecondInitHash = computeODRHash(SecondInitializer);
|
||||
if (FirstInitHash != SecondInitHash) {
|
||||
DiagError(FieldDifferentInitializers)
|
||||
<< FirstII << FirstInitializer->getSourceRange();
|
||||
|
@ -9786,10 +9736,9 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
};
|
||||
|
||||
auto ODRDiagTypeDefOrAlias =
|
||||
[this, &ComputeQualTypeODRHash](
|
||||
NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,
|
||||
TypedefNameDecl *FirstTD, TypedefNameDecl *SecondTD,
|
||||
bool IsTypeAlias) {
|
||||
[this](NamedDecl *FirstRecord, StringRef FirstModule,
|
||||
StringRef SecondModule, const TypedefNameDecl *FirstTD,
|
||||
const TypedefNameDecl *SecondTD, bool IsTypeAlias) {
|
||||
enum ODRTypedefDifference {
|
||||
TypedefName,
|
||||
TypedefType,
|
||||
|
@ -9809,8 +9758,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
<< SecondModule << SecondTD->getSourceRange() << DiffType;
|
||||
};
|
||||
|
||||
auto FirstName = FirstTD->getDeclName();
|
||||
auto SecondName = SecondTD->getDeclName();
|
||||
DeclarationName FirstName = FirstTD->getDeclName();
|
||||
DeclarationName SecondName = SecondTD->getDeclName();
|
||||
if (FirstName != SecondName) {
|
||||
DiagError(TypedefName) << IsTypeAlias << FirstName;
|
||||
DiagNote(TypedefName) << IsTypeAlias << SecondName;
|
||||
|
@ -9819,8 +9768,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
|
||||
QualType FirstType = FirstTD->getUnderlyingType();
|
||||
QualType SecondType = SecondTD->getUnderlyingType();
|
||||
if (ComputeQualTypeODRHash(FirstType) !=
|
||||
ComputeQualTypeODRHash(SecondType)) {
|
||||
if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
|
||||
DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType;
|
||||
DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType;
|
||||
return true;
|
||||
|
@ -9829,10 +9777,9 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
return false;
|
||||
};
|
||||
|
||||
auto ODRDiagVar = [&ComputeQualTypeODRHash, &ComputeODRHash,
|
||||
this](NamedDecl *FirstRecord, StringRef FirstModule,
|
||||
StringRef SecondModule, VarDecl *FirstVD,
|
||||
VarDecl *SecondVD) {
|
||||
auto ODRDiagVar = [this](NamedDecl *FirstRecord, StringRef FirstModule,
|
||||
StringRef SecondModule, const VarDecl *FirstVD,
|
||||
const VarDecl *SecondVD) {
|
||||
enum ODRVarDifference {
|
||||
VarName,
|
||||
VarType,
|
||||
|
@ -9854,8 +9801,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
<< SecondModule << SecondVD->getSourceRange() << DiffType;
|
||||
};
|
||||
|
||||
auto FirstName = FirstVD->getDeclName();
|
||||
auto SecondName = SecondVD->getDeclName();
|
||||
DeclarationName FirstName = FirstVD->getDeclName();
|
||||
DeclarationName SecondName = SecondVD->getDeclName();
|
||||
if (FirstName != SecondName) {
|
||||
DiagError(VarName) << FirstName;
|
||||
DiagNote(VarName) << SecondName;
|
||||
|
@ -9864,8 +9811,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
|
||||
QualType FirstType = FirstVD->getType();
|
||||
QualType SecondType = SecondVD->getType();
|
||||
if (ComputeQualTypeODRHash(FirstType) !=
|
||||
ComputeQualTypeODRHash(SecondType)) {
|
||||
if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
|
||||
DiagError(VarType) << FirstName << FirstType;
|
||||
DiagNote(VarType) << SecondName << SecondType;
|
||||
return true;
|
||||
|
@ -9887,7 +9833,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
if (FirstInit && SecondInit &&
|
||||
ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
|
||||
computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
|
||||
DiagError(VarDifferentInitializer)
|
||||
<< FirstName << FirstInit->getSourceRange();
|
||||
DiagNote(VarDifferentInitializer)
|
||||
|
@ -9905,6 +9851,25 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
return false;
|
||||
};
|
||||
|
||||
using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>;
|
||||
auto PopulateHashes = [](DeclHashes &Hashes, RecordDecl *Record,
|
||||
const DeclContext *DC) {
|
||||
for (auto *D : Record->decls()) {
|
||||
if (!ODRHash::isDeclToBeProcessed(D, DC))
|
||||
continue;
|
||||
Hashes.emplace_back(D, computeODRHash(D));
|
||||
}
|
||||
};
|
||||
|
||||
struct DiffResult {
|
||||
Decl *FirstDecl = nullptr, *SecondDecl = nullptr;
|
||||
ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other;
|
||||
};
|
||||
|
||||
// If there is a diagnoseable difference, FirstDiffType and
|
||||
// SecondDiffType will not be Other and FirstDecl and SecondDecl will be
|
||||
// filled in if not EndOfClass.
|
||||
auto FindTypeDiffs = [](DeclHashes &FirstHashes, DeclHashes &SecondHashes) {
|
||||
auto DifferenceSelector = [](Decl *D) {
|
||||
assert(D && "valid Decl required");
|
||||
switch (D->getKind()) {
|
||||
|
@ -9943,27 +9908,6 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
};
|
||||
|
||||
using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>;
|
||||
auto PopulateHashes = [&ComputeSubDeclODRHash](DeclHashes &Hashes,
|
||||
RecordDecl *Record,
|
||||
const DeclContext *DC) {
|
||||
for (auto *D : Record->decls()) {
|
||||
if (!ODRHash::isDeclToBeProcessed(D, DC))
|
||||
continue;
|
||||
Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
|
||||
}
|
||||
};
|
||||
|
||||
struct DiffResult {
|
||||
Decl *FirstDecl = nullptr, *SecondDecl = nullptr;
|
||||
ODRMismatchDecl FirstDiffType = Other, SecondDiffType = Other;
|
||||
};
|
||||
|
||||
// If there is a diagnoseable difference, FirstDiffType and
|
||||
// SecondDiffType will not be Other and FirstDecl and SecondDecl will be
|
||||
// filled in if not EndOfClass.
|
||||
auto FindTypeDiffs = [&DifferenceSelector](DeclHashes &FirstHashes,
|
||||
DeclHashes &SecondHashes) {
|
||||
DiffResult DR;
|
||||
auto FirstIt = FirstHashes.begin();
|
||||
auto SecondIt = SecondHashes.begin();
|
||||
|
@ -10062,19 +10006,6 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
continue;
|
||||
|
||||
std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord);
|
||||
auto ODRDiagDeclError = [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 ODRDiagDeclNote = [&SecondModule,
|
||||
this](SourceLocation Loc, SourceRange Range,
|
||||
ODRCXXRecordDifference DiffType) {
|
||||
return Diag(Loc, diag::note_module_odr_violation_record)
|
||||
<< SecondModule << Range << DiffType;
|
||||
};
|
||||
|
||||
auto *FirstDD = FirstRecord->DefinitionData;
|
||||
auto *SecondDD = RecordPair.second;
|
||||
|
@ -10103,20 +10034,18 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
return Diag(Loc, diag::note_module_odr_violation_definition_data)
|
||||
<< SecondModule << Range << DiffType;
|
||||
};
|
||||
auto GetSourceRange = [](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;
|
||||
|
||||
auto GetSourceRange = [](struct CXXRecordDecl::DefinitionData *DD) {
|
||||
unsigned NumBases = DD->NumBases;
|
||||
if (NumBases == 0) return SourceRange();
|
||||
auto bases = DD->bases();
|
||||
return SourceRange(bases[0].getBeginLoc(),
|
||||
bases[NumBases - 1].getEndLoc());
|
||||
};
|
||||
|
||||
if (FirstNumBases != SecondNumBases) {
|
||||
ODRDiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),
|
||||
NumBases)
|
||||
|
@ -10139,30 +10068,30 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
break;
|
||||
}
|
||||
|
||||
auto FirstBases = FirstDD->bases();
|
||||
auto SecondBases = SecondDD->bases();
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < FirstNumBases; ++i) {
|
||||
auto FirstBase = FirstBases[i];
|
||||
auto SecondBase = SecondBases[i];
|
||||
if (ComputeQualTypeODRHash(FirstBase.getType()) !=
|
||||
ComputeQualTypeODRHash(SecondBase.getType())) {
|
||||
ArrayRef<CXXBaseSpecifier> FirstBases = FirstDD->bases();
|
||||
ArrayRef<CXXBaseSpecifier> SecondBases = SecondDD->bases();
|
||||
unsigned I = 0;
|
||||
for (I = 0; I < FirstNumBases; ++I) {
|
||||
const CXXBaseSpecifier FirstBase = FirstBases[I];
|
||||
const CXXBaseSpecifier SecondBase = SecondBases[I];
|
||||
if (computeODRHash(FirstBase.getType()) !=
|
||||
computeODRHash(SecondBase.getType())) {
|
||||
ODRDiagBaseError(FirstRecord->getLocation(),
|
||||
FirstBase.getSourceRange(), BaseType)
|
||||
<< (i + 1) << FirstBase.getType();
|
||||
<< (I + 1) << FirstBase.getType();
|
||||
ODRDiagBaseNote(SecondRecord->getLocation(),
|
||||
SecondBase.getSourceRange(), BaseType)
|
||||
<< (i + 1) << SecondBase.getType();
|
||||
<< (I + 1) << SecondBase.getType();
|
||||
break;
|
||||
}
|
||||
|
||||
if (FirstBase.isVirtual() != SecondBase.isVirtual()) {
|
||||
ODRDiagBaseError(FirstRecord->getLocation(),
|
||||
FirstBase.getSourceRange(), BaseVirtual)
|
||||
<< (i + 1) << FirstBase.isVirtual() << FirstBase.getType();
|
||||
<< (I + 1) << FirstBase.isVirtual() << FirstBase.getType();
|
||||
ODRDiagBaseNote(SecondRecord->getLocation(),
|
||||
SecondBase.getSourceRange(), BaseVirtual)
|
||||
<< (i + 1) << SecondBase.isVirtual() << SecondBase.getType();
|
||||
<< (I + 1) << SecondBase.isVirtual() << SecondBase.getType();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -10170,17 +10099,17 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
SecondBase.getAccessSpecifierAsWritten()) {
|
||||
ODRDiagBaseError(FirstRecord->getLocation(),
|
||||
FirstBase.getSourceRange(), BaseAccess)
|
||||
<< (i + 1) << FirstBase.getType()
|
||||
<< (I + 1) << FirstBase.getType()
|
||||
<< (int)FirstBase.getAccessSpecifierAsWritten();
|
||||
ODRDiagBaseNote(SecondRecord->getLocation(),
|
||||
SecondBase.getSourceRange(), BaseAccess)
|
||||
<< (i + 1) << SecondBase.getType()
|
||||
<< (I + 1) << SecondBase.getType()
|
||||
<< (int)SecondBase.getAccessSpecifierAsWritten();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != FirstNumBases) {
|
||||
if (I != FirstNumBases) {
|
||||
Diagnosed = true;
|
||||
break;
|
||||
}
|
||||
|
@ -10198,11 +10127,10 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
DeclHashes FirstTemplateHashes;
|
||||
DeclHashes SecondTemplateHashes;
|
||||
|
||||
auto PopulateTemplateParameterHashs =
|
||||
[&ComputeSubDeclODRHash](DeclHashes &Hashes,
|
||||
auto PopulateTemplateParameterHashs = [](DeclHashes &Hashes,
|
||||
const ClassTemplateDecl *TD) {
|
||||
for (auto *D : TD->getTemplateParameters()->asArray()) {
|
||||
Hashes.emplace_back(D, ComputeSubDeclODRHash(D));
|
||||
Hashes.emplace_back(D, computeODRHash(D));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -10288,11 +10216,11 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
PopulateHashes(FirstHashes, FirstRecord, DC);
|
||||
PopulateHashes(SecondHashes, SecondRecord, DC);
|
||||
|
||||
auto DR = FindTypeDiffs(FirstHashes, SecondHashes);
|
||||
DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);
|
||||
ODRMismatchDecl FirstDiffType = DR.FirstDiffType;
|
||||
ODRMismatchDecl SecondDiffType = DR.SecondDiffType;
|
||||
Decl *FirstDecl = DR.FirstDecl;
|
||||
Decl *SecondDecl = DR.SecondDecl;
|
||||
const Decl *FirstDecl = DR.FirstDecl;
|
||||
const Decl *SecondDecl = DR.SecondDecl;
|
||||
|
||||
if (FirstDiffType == Other || SecondDiffType == Other) {
|
||||
DiagnoseODRUnexpected(DR, FirstRecord, FirstModule, SecondRecord,
|
||||
|
@ -10308,8 +10236,56 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
break;
|
||||
}
|
||||
|
||||
assert(FirstDiffType == SecondDiffType);
|
||||
// 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,
|
||||
MethodNumberParameters,
|
||||
MethodParameterType,
|
||||
MethodParameterName,
|
||||
MethodParameterSingleDefaultArgument,
|
||||
MethodParameterDifferentDefaultArgument,
|
||||
MethodNoTemplateArguments,
|
||||
MethodDifferentNumberTemplateArguments,
|
||||
MethodDifferentTemplateArgument,
|
||||
MethodSingleBody,
|
||||
MethodDifferentBody,
|
||||
FriendTypeFunction,
|
||||
FriendType,
|
||||
FriendFunction,
|
||||
FunctionTemplateDifferentNumberParameters,
|
||||
FunctionTemplateParameterDifferentKind,
|
||||
FunctionTemplateParameterName,
|
||||
FunctionTemplateParameterSingleDefaultArgument,
|
||||
FunctionTemplateParameterDifferentDefaultArgument,
|
||||
FunctionTemplateParameterDifferentType,
|
||||
FunctionTemplatePackParameter,
|
||||
};
|
||||
auto ODRDiagDeclError = [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 ODRDiagDeclNote = [&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:
|
||||
|
@ -10319,13 +10295,13 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
llvm_unreachable("Invalid diff type");
|
||||
|
||||
case StaticAssert: {
|
||||
StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl);
|
||||
StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl);
|
||||
const StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl);
|
||||
const StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl);
|
||||
|
||||
Expr *FirstExpr = FirstSA->getAssertExpr();
|
||||
Expr *SecondExpr = SecondSA->getAssertExpr();
|
||||
unsigned FirstODRHash = ComputeODRHash(FirstExpr);
|
||||
unsigned SecondODRHash = ComputeODRHash(SecondExpr);
|
||||
const Expr *FirstExpr = FirstSA->getAssertExpr();
|
||||
const Expr *SecondExpr = SecondSA->getAssertExpr();
|
||||
unsigned FirstODRHash = computeODRHash(FirstExpr);
|
||||
unsigned SecondODRHash = computeODRHash(SecondExpr);
|
||||
if (FirstODRHash != SecondODRHash) {
|
||||
ODRDiagDeclError(FirstExpr->getBeginLoc(),
|
||||
FirstExpr->getSourceRange(), StaticAssertCondition);
|
||||
|
@ -10335,8 +10311,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
break;
|
||||
}
|
||||
|
||||
StringLiteral *FirstStr = FirstSA->getMessage();
|
||||
StringLiteral *SecondStr = SecondSA->getMessage();
|
||||
const StringLiteral *FirstStr = FirstSA->getMessage();
|
||||
const StringLiteral *SecondStr = SecondSA->getMessage();
|
||||
assert((FirstStr || SecondStr) && "Both messages cannot be empty");
|
||||
if ((FirstStr && !SecondStr) || (!FirstStr && SecondStr)) {
|
||||
SourceLocation FirstLoc, SecondLoc;
|
||||
|
@ -10451,8 +10427,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
// 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.
|
||||
const auto FirstStorage = FirstMethod->getStorageClass();
|
||||
const auto SecondStorage = SecondMethod->getStorageClass();
|
||||
StorageClass FirstStorage = FirstMethod->getStorageClass();
|
||||
StorageClass SecondStorage = SecondMethod->getStorageClass();
|
||||
const bool FirstStatic = FirstStorage == SC_Static;
|
||||
const bool SecondStatic = SecondStorage == SC_Static;
|
||||
if (FirstStatic != SecondStatic) {
|
||||
|
@ -10507,8 +10483,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
QualType FirstParamType = FirstParam->getType();
|
||||
QualType SecondParamType = SecondParam->getType();
|
||||
if (FirstParamType != SecondParamType &&
|
||||
ComputeQualTypeODRHash(FirstParamType) !=
|
||||
ComputeQualTypeODRHash(SecondParamType)) {
|
||||
computeODRHash(FirstParamType) !=
|
||||
computeODRHash(SecondParamType)) {
|
||||
if (const DecayedType *ParamDecayedType =
|
||||
FirstParamType->getAs<DecayedType>()) {
|
||||
DiagMethodError(MethodParameterType)
|
||||
|
@ -10555,14 +10531,13 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
if (FirstInit && SecondInit &&
|
||||
ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
|
||||
computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
|
||||
DiagMethodError(MethodParameterDifferentDefaultArgument)
|
||||
<< (I + 1) << FirstInit->getSourceRange();
|
||||
DiagMethodNote(MethodParameterDifferentDefaultArgument)
|
||||
<< (I + 1) << SecondInit->getSourceRange();
|
||||
ParameterMismatch = true;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10571,9 +10546,9 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
break;
|
||||
}
|
||||
|
||||
const auto *FirstTemplateArgs =
|
||||
const TemplateArgumentList *FirstTemplateArgs =
|
||||
FirstMethod->getTemplateSpecializationArgs();
|
||||
const auto *SecondTemplateArgs =
|
||||
const TemplateArgumentList *SecondTemplateArgs =
|
||||
SecondMethod->getTemplateSpecializationArgs();
|
||||
|
||||
if ((FirstTemplateArgs && !SecondTemplateArgs) ||
|
||||
|
@ -10619,8 +10594,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) {
|
||||
const TemplateArgument &FirstTA = *FirstExpandedList[i],
|
||||
&SecondTA = *SecondExpandedList[i];
|
||||
if (ComputeTemplateArgumentODRHash(FirstTA) ==
|
||||
ComputeTemplateArgumentODRHash(SecondTA)) {
|
||||
if (computeODRHash(FirstTA) == computeODRHash(SecondTA)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -10639,10 +10613,10 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
// Compute the hash of the method as if it has no body.
|
||||
auto ComputeCXXMethodODRHash = [&Hash](const CXXMethodDecl *D) {
|
||||
Hash.clear();
|
||||
Hash.AddFunctionDecl(D, true /*SkipBody*/);
|
||||
return Hash.CalculateHash();
|
||||
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
|
||||
|
@ -10684,11 +10658,11 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
break;
|
||||
}
|
||||
case Friend: {
|
||||
FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
|
||||
FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);
|
||||
const FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl);
|
||||
const FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl);
|
||||
|
||||
NamedDecl *FirstND = FirstFriend->getFriendDecl();
|
||||
NamedDecl *SecondND = SecondFriend->getFriendDecl();
|
||||
const NamedDecl *FirstND = FirstFriend->getFriendDecl();
|
||||
const NamedDecl *SecondND = SecondFriend->getFriendDecl();
|
||||
|
||||
TypeSourceInfo *FirstTSI = FirstFriend->getFriendType();
|
||||
TypeSourceInfo *SecondTSI = SecondFriend->getFriendType();
|
||||
|
@ -10707,8 +10681,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
if (FirstTSI && SecondTSI) {
|
||||
QualType FirstFriendType = FirstTSI->getType();
|
||||
QualType SecondFriendType = SecondTSI->getType();
|
||||
assert(ComputeQualTypeODRHash(FirstFriendType) !=
|
||||
ComputeQualTypeODRHash(SecondFriendType));
|
||||
assert(computeODRHash(FirstFriendType) !=
|
||||
computeODRHash(SecondFriendType));
|
||||
ODRDiagDeclError(FirstFriend->getFriendLoc(),
|
||||
FirstFriend->getSourceRange(), FriendType)
|
||||
<< FirstFriendType;
|
||||
|
@ -10729,9 +10703,9 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
break;
|
||||
}
|
||||
case FunctionTemplate: {
|
||||
FunctionTemplateDecl *FirstTemplate =
|
||||
const FunctionTemplateDecl *FirstTemplate =
|
||||
cast<FunctionTemplateDecl>(FirstDecl);
|
||||
FunctionTemplateDecl *SecondTemplate =
|
||||
const FunctionTemplateDecl *SecondTemplate =
|
||||
cast<FunctionTemplateDecl>(SecondDecl);
|
||||
|
||||
TemplateParameterList *FirstTPL =
|
||||
|
@ -10826,8 +10800,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
|
||||
QualType FirstType = FirstTTPD->getDefaultArgument();
|
||||
QualType SecondType = SecondTTPD->getDefaultArgument();
|
||||
if (ComputeQualTypeODRHash(FirstType) !=
|
||||
ComputeQualTypeODRHash(SecondType)) {
|
||||
if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
|
||||
DiagTemplateError(
|
||||
FunctionTemplateParameterDifferentDefaultArgument)
|
||||
<< (i + 1) << FirstType;
|
||||
|
@ -10862,6 +10835,14 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
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)
|
||||
|
@ -10892,8 +10873,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
FirstTTPD->getDefaultArgument().getArgument();
|
||||
TemplateArgument SecondTA =
|
||||
SecondTTPD->getDefaultArgument().getArgument();
|
||||
if (ComputeTemplateArgumentODRHash(FirstTA) !=
|
||||
ComputeTemplateArgumentODRHash(SecondTA)) {
|
||||
if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) {
|
||||
DiagTemplateError(
|
||||
FunctionTemplateParameterDifferentDefaultArgument)
|
||||
<< (i + 1) << FirstTA;
|
||||
|
@ -10925,8 +10905,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
|
||||
QualType FirstType = FirstNTTPD->getType();
|
||||
QualType SecondType = SecondNTTPD->getType();
|
||||
if (ComputeQualTypeODRHash(FirstType) !=
|
||||
ComputeQualTypeODRHash(SecondType)) {
|
||||
if (computeODRHash(FirstType) != computeODRHash(SecondType)) {
|
||||
DiagTemplateError(FunctionTemplateParameterDifferentType)
|
||||
<< (i + 1);
|
||||
DiagTemplateNote(FunctionTemplateParameterDifferentType)
|
||||
|
@ -10953,8 +10932,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
|
||||
Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
|
||||
Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
|
||||
if (ComputeODRHash(FirstDefaultArgument) !=
|
||||
ComputeODRHash(SecondDefaultArgument)) {
|
||||
if (computeODRHash(FirstDefaultArgument) !=
|
||||
computeODRHash(SecondDefaultArgument)) {
|
||||
DiagTemplateError(
|
||||
FunctionTemplateParameterDifferentDefaultArgument)
|
||||
<< (i + 1) << FirstDefaultArgument;
|
||||
|
@ -11050,8 +11029,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
<< SecondModule << Range << DiffType;
|
||||
};
|
||||
|
||||
if (ComputeQualTypeODRHash(FirstFunction->getReturnType()) !=
|
||||
ComputeQualTypeODRHash(SecondFunction->getReturnType())) {
|
||||
if (computeODRHash(FirstFunction->getReturnType()) !=
|
||||
computeODRHash(SecondFunction->getReturnType())) {
|
||||
ODRDiagError(FirstFunction->getReturnTypeSourceRange().getBegin(),
|
||||
FirstFunction->getReturnTypeSourceRange(), ReturnType)
|
||||
<< FirstFunction->getReturnType();
|
||||
|
@ -11065,11 +11044,11 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
assert(FirstFunction->param_size() == SecondFunction->param_size() &&
|
||||
"Merged functions with different number of parameters");
|
||||
|
||||
auto ParamSize = FirstFunction->param_size();
|
||||
size_t ParamSize = FirstFunction->param_size();
|
||||
bool ParameterMismatch = false;
|
||||
for (unsigned I = 0; I < ParamSize; ++I) {
|
||||
auto *FirstParam = FirstFunction->getParamDecl(I);
|
||||
auto *SecondParam = SecondFunction->getParamDecl(I);
|
||||
const ParmVarDecl *FirstParam = FirstFunction->getParamDecl(I);
|
||||
const ParmVarDecl *SecondParam = SecondFunction->getParamDecl(I);
|
||||
|
||||
assert(getContext().hasSameType(FirstParam->getType(),
|
||||
SecondParam->getType()) &&
|
||||
|
@ -11089,8 +11068,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
QualType FirstParamType = FirstParam->getType();
|
||||
QualType SecondParamType = SecondParam->getType();
|
||||
if (FirstParamType != SecondParamType &&
|
||||
ComputeQualTypeODRHash(FirstParamType) !=
|
||||
ComputeQualTypeODRHash(SecondParamType)) {
|
||||
computeODRHash(FirstParamType) != computeODRHash(SecondParamType)) {
|
||||
if (const DecayedType *ParamDecayedType =
|
||||
FirstParamType->getAs<DecayedType>()) {
|
||||
ODRDiagError(FirstParam->getLocation(),
|
||||
|
@ -11134,7 +11112,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
if (FirstInit && SecondInit &&
|
||||
ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
|
||||
computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
|
||||
ODRDiagError(FirstParam->getLocation(), FirstParam->getSourceRange(),
|
||||
ParameterDifferentDefaultArgument)
|
||||
<< (I + 1) << FirstInit->getSourceRange();
|
||||
|
@ -11145,8 +11123,7 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
break;
|
||||
}
|
||||
|
||||
assert(ComputeSubDeclODRHash(FirstParam) ==
|
||||
ComputeSubDeclODRHash(SecondParam) &&
|
||||
assert(computeODRHash(FirstParam) == computeODRHash(SecondParam) &&
|
||||
"Undiagnosed parameter difference.");
|
||||
}
|
||||
|
||||
|
@ -11191,16 +11168,14 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
|
||||
using DeclHashes =
|
||||
llvm::SmallVector<std::pair<EnumConstantDecl *, unsigned>, 4>;
|
||||
auto PopulateHashes = [&ComputeSubDeclODRHash, FirstEnum](
|
||||
DeclHashes &Hashes, EnumDecl *Enum) {
|
||||
auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, EnumDecl *Enum) {
|
||||
for (auto *D : Enum->decls()) {
|
||||
// Due to decl merging, the first EnumDecl is the parent of
|
||||
// Decls in both records.
|
||||
if (!ODRHash::isDeclToBeProcessed(D, FirstEnum))
|
||||
continue;
|
||||
assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind");
|
||||
Hashes.emplace_back(cast<EnumConstantDecl>(D),
|
||||
ComputeSubDeclODRHash(D));
|
||||
Hashes.emplace_back(cast<EnumConstantDecl>(D), computeODRHash(D));
|
||||
}
|
||||
};
|
||||
DeclHashes FirstHashes;
|
||||
|
@ -11266,8 +11241,8 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
}
|
||||
|
||||
if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {
|
||||
if (ComputeQualTypeODRHash(FirstUnderlyingType) !=
|
||||
ComputeQualTypeODRHash(SecondUnderlyingType)) {
|
||||
if (computeODRHash(FirstUnderlyingType) !=
|
||||
computeODRHash(SecondUnderlyingType)) {
|
||||
ODRDiagError(FirstEnum, DifferentSpecifiedTypes)
|
||||
<< FirstUnderlyingType;
|
||||
ODRDiagNote(SecondEnum, DifferentSpecifiedTypes)
|
||||
|
@ -11292,39 +11267,38 @@ void ASTReader::diagnoseOdrViolations() {
|
|||
for (unsigned I = 0; I < FirstHashes.size(); ++I) {
|
||||
if (FirstHashes[I].second == SecondHashes[I].second)
|
||||
continue;
|
||||
const EnumConstantDecl *FirstEnumConstant = FirstHashes[I].first;
|
||||
const EnumConstantDecl *SecondEnumConstant = SecondHashes[I].first;
|
||||
const EnumConstantDecl *FirstConstant = FirstHashes[I].first;
|
||||
const EnumConstantDecl *SecondConstant = SecondHashes[I].first;
|
||||
|
||||
if (FirstEnumConstant->getDeclName() !=
|
||||
SecondEnumConstant->getDeclName()) {
|
||||
if (FirstConstant->getDeclName() != SecondConstant->getDeclName()) {
|
||||
|
||||
ODRDiagError(FirstEnumConstant, EnumConstantName)
|
||||
<< I + 1 << FirstEnumConstant;
|
||||
ODRDiagNote(SecondEnumConstant, EnumConstantName)
|
||||
<< I + 1 << SecondEnumConstant;
|
||||
ODRDiagError(FirstConstant, EnumConstantName)
|
||||
<< I + 1 << FirstConstant;
|
||||
ODRDiagNote(SecondConstant, EnumConstantName)
|
||||
<< I + 1 << SecondConstant;
|
||||
Diagnosed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
const Expr *FirstInit = FirstEnumConstant->getInitExpr();
|
||||
const Expr *SecondInit = SecondEnumConstant->getInitExpr();
|
||||
const Expr *FirstInit = FirstConstant->getInitExpr();
|
||||
const Expr *SecondInit = SecondConstant->getInitExpr();
|
||||
if (!FirstInit && !SecondInit)
|
||||
continue;
|
||||
|
||||
if (!FirstInit || !SecondInit) {
|
||||
ODRDiagError(FirstEnumConstant, EnumConstantSingleInitializer)
|
||||
<< I + 1 << FirstEnumConstant << (FirstInit != nullptr);
|
||||
ODRDiagNote(SecondEnumConstant, EnumConstantSingleInitializer)
|
||||
<< I + 1 << SecondEnumConstant << (SecondInit != nullptr);
|
||||
ODRDiagError(FirstConstant, EnumConstantSingleInitializer)
|
||||
<< I + 1 << FirstConstant << (FirstInit != nullptr);
|
||||
ODRDiagNote(SecondConstant, EnumConstantSingleInitializer)
|
||||
<< I + 1 << SecondConstant << (SecondInit != nullptr);
|
||||
Diagnosed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ComputeODRHash(FirstInit) != ComputeODRHash(SecondInit)) {
|
||||
ODRDiagError(FirstEnumConstant, EnumConstantDifferentInitializer)
|
||||
<< I + 1 << FirstEnumConstant;
|
||||
ODRDiagNote(SecondEnumConstant, EnumConstantDifferentInitializer)
|
||||
<< I + 1 << SecondEnumConstant;
|
||||
if (computeODRHash(FirstInit) != computeODRHash(SecondInit)) {
|
||||
ODRDiagError(FirstConstant, EnumConstantDifferentInitializer)
|
||||
<< I + 1 << FirstConstant;
|
||||
ODRDiagNote(SecondConstant, EnumConstantDifferentInitializer)
|
||||
<< I + 1 << SecondConstant;
|
||||
Diagnosed = true;
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue