diff options
author | Richard Trieu <rtrieu@google.com> | 2018-07-10 01:40:50 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2018-07-10 01:40:50 +0000 |
commit | 27c1b1a638d2f6300ebc6f64fd97bd6f4d9c9e2d (patch) | |
tree | 3b7724f9d051c9ec64ba4b74476f5d13df9ee69e /clang/lib/Serialization/ASTReader.cpp | |
parent | 2a3036fb1d92747ddaeba88182227c6e726b6d0e (diff) | |
download | bcm5719-llvm-27c1b1a638d2f6300ebc6f64fd97bd6f4d9c9e2d.tar.gz bcm5719-llvm-27c1b1a638d2f6300ebc6f64fd97bd6f4d9c9e2d.zip |
[ODRHash] Merge the two function hashes into one.
Functions that are a sub-Decl of a record were hashed differently than other
functions. This change keeps the AddFunctionDecl function and the hash of
records now calls this function. In addition, AddFunctionDecl has an option
to perform a hash as if the body was absent, which is required for some
checks after loading modules. Additional logic prevents multiple error
message from being printed.
llvm-svn: 336632
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 84286ca3808..32772436678 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9397,7 +9397,15 @@ void ASTReader::finishPendingActions() { if (!FD->isLateTemplateParsed() && !NonConstDefn->isLateTemplateParsed() && FD->getODRHash() != NonConstDefn->getODRHash()) { - PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + if (!isa<CXXMethodDecl>(FD)) { + PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + } else if (FD->getLexicalParent()->isFileContext() && + NonConstDefn->getLexicalParent()->isFileContext()) { + // Only diagnose out-of-line method definitions. If they are + // in class definitions, then an error will be generated when + // processing the class bodies. + PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn); + } } } continue; @@ -10069,6 +10077,7 @@ void ASTReader::diagnoseOdrViolations() { FieldDifferentInitializers, MethodName, MethodDeleted, + MethodDefaulted, MethodVirtual, MethodStatic, MethodVolatile, @@ -10082,6 +10091,8 @@ void ASTReader::diagnoseOdrViolations() { MethodNoTemplateArguments, MethodDifferentNumberTemplateArguments, MethodDifferentTemplateArgument, + MethodSingleBody, + MethodDifferentBody, TypedefName, TypedefType, VarName, @@ -10315,8 +10326,8 @@ void ASTReader::diagnoseOdrViolations() { break; } - const bool FirstDeleted = FirstMethod->isDeleted(); - const bool SecondDeleted = SecondMethod->isDeleted(); + const bool FirstDeleted = FirstMethod->isDeletedAsWritten(); + const bool SecondDeleted = SecondMethod->isDeletedAsWritten(); if (FirstDeleted != SecondDeleted) { ODRDiagError(FirstMethod->getLocation(), FirstMethod->getSourceRange(), MethodDeleted) @@ -10329,6 +10340,20 @@ void ASTReader::diagnoseOdrViolations() { break; } + const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted(); + const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted(); + if (FirstDefaulted != SecondDefaulted) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodDefaulted) + << FirstMethodType << FirstName << FirstDefaulted; + + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodDefaulted) + << SecondMethodType << SecondName << SecondDefaulted; + Diagnosed = true; + break; + } + const bool FirstVirtual = FirstMethod->isVirtualAsWritten(); const bool SecondVirtual = SecondMethod->isVirtualAsWritten(); const bool FirstPure = FirstMethod->isPure(); @@ -10594,6 +10619,44 @@ void ASTReader::diagnoseOdrViolations() { break; } } + + // 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(); + }; + + // Compare the hash generated to the hash stored. A difference means + // that a body was present in the original source. Due to merging, + // the stardard way of detecting a body will not work. + const bool HasFirstBody = + ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash(); + const bool HasSecondBody = + ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash(); + + if (HasFirstBody != HasSecondBody) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodSingleBody) + << FirstMethodType << FirstName << HasFirstBody; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodSingleBody) + << SecondMethodType << SecondName << HasSecondBody; + Diagnosed = true; + break; + } + + if (HasFirstBody && HasSecondBody) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodDifferentBody) + << FirstMethodType << FirstName; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodDifferentBody) + << SecondMethodType << SecondName; + Diagnosed = true; + break; + } + break; } case TypeAlias: |