diff options
| author | Richard Trieu <rtrieu@google.com> | 2017-09-30 02:19:17 +0000 |
|---|---|---|
| committer | Richard Trieu <rtrieu@google.com> | 2017-09-30 02:19:17 +0000 |
| commit | e13eabe7d33956d1d9d72314e4044db904d56728 (patch) | |
| tree | 22e2bcd053aad84898481c053012eadf3f6a3b77 /clang/lib | |
| parent | 305ee8e5f852e2658ea24bafc7f78fe569de7956 (diff) | |
| download | bcm5719-llvm-e13eabe7d33956d1d9d72314e4044db904d56728.tar.gz bcm5719-llvm-e13eabe7d33956d1d9d72314e4044db904d56728.zip | |
[ODRHash] Add base classes to hashing CXXRecordDecl.
llvm-svn: 314581
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/ODRHash.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 124 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 3 |
3 files changed, 132 insertions, 3 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index fb8eade3c08..17c95f2a0af 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -456,6 +456,14 @@ void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) { if (TD) { AddTemplateParameterList(TD->getTemplateParameters()); } + + ID.AddInteger(Record->getNumBases()); + auto Bases = Record->bases(); + for (auto Base : Bases) { + AddQualType(Base.getType()); + ID.AddInteger(Base.isVirtual()); + ID.AddInteger(Base.getAccessSpecifierAsWritten()); + } } void ODRHash::AddDecl(const Decl *D) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 46823030d30..7d745447a81 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9190,7 +9190,8 @@ void ASTReader::diagnoseOdrViolations() { Merge.first->decls_begin(); Merge.first->bases_begin(); Merge.first->vbases_begin(); - for (auto *RD : Merge.second) { + for (auto &RecordPair : Merge.second) { + auto *RD = RecordPair.first; RD->decls_begin(); RD->bases_begin(); RD->vbases_begin(); @@ -9296,13 +9297,132 @@ void ASTReader::diagnoseOdrViolations() { bool Diagnosed = false; CXXRecordDecl *FirstRecord = Merge.first; std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord); - for (CXXRecordDecl *SecondRecord : Merge.second) { + for (auto &RecordPair : Merge.second) { + CXXRecordDecl *SecondRecord = RecordPair.first; // Multiple different declarations got merged together; tell the user // where they came from. if (FirstRecord == SecondRecord) continue; std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord); + + auto *FirstDD = FirstRecord->DefinitionData; + auto *SecondDD = RecordPair.second; + + assert(FirstDD && SecondDD && "Definitions without DefinitionData"); + + // Diagnostics from DefinitionData are emitted here. + if (FirstDD != SecondDD) { + enum ODRDefinitionDataDifference { + NumBases, + NumVBases, + BaseType, + BaseVirtual, + BaseAccess, + }; + auto ODRDiagError = [FirstRecord, &FirstModule, + this](SourceLocation Loc, SourceRange Range, + ODRDefinitionDataDifference DiffType) { + return Diag(Loc, diag::err_module_odr_violation_definition_data) + << FirstRecord << FirstModule.empty() << FirstModule << Range + << DiffType; + }; + auto ODRDiagNote = [&SecondModule, + this](SourceLocation Loc, SourceRange Range, + ODRDefinitionDataDifference DiffType) { + return Diag(Loc, diag::note_module_odr_violation_definition_data) + << SecondModule << Range << DiffType; + }; + + ODRHash Hash; + auto ComputeQualTypeODRHash = [&Hash](QualType Ty) { + Hash.clear(); + Hash.AddQualType(Ty); + return Hash.CalculateHash(); + }; + + 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].getLocStart(), + bases[NumBases - 1].getLocEnd()); + }; + + if (FirstNumBases != SecondNumBases) { + ODRDiagError(FirstRecord->getLocation(), GetSourceRange(FirstDD), + NumBases) + << FirstNumBases; + ODRDiagNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), + NumBases) + << SecondNumBases; + Diagnosed = true; + break; + } + + if (FirstNumVBases != SecondNumVBases) { + ODRDiagError(FirstRecord->getLocation(), GetSourceRange(FirstDD), + NumVBases) + << FirstNumVBases; + ODRDiagNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), + NumVBases) + << SecondNumVBases; + Diagnosed = true; + 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())) { + ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(), + BaseType) + << (i + 1) << FirstBase.getType(); + ODRDiagNote(SecondRecord->getLocation(), + SecondBase.getSourceRange(), BaseType) + << (i + 1) << SecondBase.getType(); + break; + } + + if (FirstBase.isVirtual() != SecondBase.isVirtual()) { + ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(), + BaseVirtual) + << (i + 1) << FirstBase.isVirtual() << FirstBase.getType(); + ODRDiagNote(SecondRecord->getLocation(), + SecondBase.getSourceRange(), BaseVirtual) + << (i + 1) << SecondBase.isVirtual() << SecondBase.getType(); + break; + } + + if (FirstBase.getAccessSpecifierAsWritten() != + SecondBase.getAccessSpecifierAsWritten()) { + ODRDiagError(FirstRecord->getLocation(), FirstBase.getSourceRange(), + BaseAccess) + << (i + 1) << FirstBase.getType() + << (int)FirstBase.getAccessSpecifierAsWritten(); + ODRDiagNote(SecondRecord->getLocation(), + SecondBase.getSourceRange(), BaseAccess) + << (i + 1) << SecondBase.getType() + << (int)SecondBase.getAccessSpecifierAsWritten(); + break; + } + } + + if (i != FirstNumBases) { + Diagnosed = true; + break; + } + } + using DeclHashes = llvm::SmallVector<std::pair<Decl *, unsigned>, 4>; const ClassTemplateDecl *FirstTemplate = diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 46164a06c34..1283b006dfb 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1755,7 +1755,8 @@ void ASTDeclReader::MergeDefinitionData( } if (DetectedOdrViolation) - Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition); + Reader.PendingOdrMergeFailures[DD.Definition].push_back( + {MergeDD.Definition, &MergeDD}); } void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { |

