summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2017-09-30 02:19:17 +0000
committerRichard Trieu <rtrieu@google.com>2017-09-30 02:19:17 +0000
commite13eabe7d33956d1d9d72314e4044db904d56728 (patch)
tree22e2bcd053aad84898481c053012eadf3f6a3b77 /clang/lib
parent305ee8e5f852e2658ea24bafc7f78fe569de7956 (diff)
downloadbcm5719-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.cpp8
-rw-r--r--clang/lib/Serialization/ASTReader.cpp124
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp3
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) {
OpenPOWER on IntegriCloud