diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ODRHash.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 92 |
2 files changed, 103 insertions, 0 deletions
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 364fd04b83b..ee6950655cf 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -148,6 +148,8 @@ void ODRHash::AddTemplateArgument(TemplateArgument TA) { AddQualType(TA.getAsType()); break; case TemplateArgument::Declaration: + AddDecl(TA.getAsDecl()); + break; case TemplateArgument::NullPtr: case TemplateArgument::Integral: break; @@ -330,6 +332,15 @@ public: AddQualType(D->getReturnType()); + const auto* SpecializationArgs = D->getTemplateSpecializationArgs(); + Hash.AddBoolean(SpecializationArgs); + if (SpecializationArgs) { + ID.AddInteger(SpecializationArgs->size()); + for (const TemplateArgument &TA : SpecializationArgs->asArray()) { + Hash.AddTemplateArgument(TA); + } + } + Inherited::VisitFunctionDecl(D); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index a8a4f9328d2..9d10b9ebfbb 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9450,6 +9450,12 @@ void ASTReader::diagnoseOdrViolations() { return Hash.CalculateHash(); }; + auto ComputeTemplateArgumentODRHash = [&Hash](const TemplateArgument &TA) { + Hash.clear(); + Hash.AddTemplateArgument(TA); + return Hash.CalculateHash(); + }; + // Issue any pending ODR-failure diagnostics. for (auto &Merge : OdrMergeFailures) { // If we've already pointed out a specific problem with this class, don't @@ -9948,6 +9954,9 @@ void ASTReader::diagnoseOdrViolations() { MethodParameterName, MethodParameterSingleDefaultArgument, MethodParameterDifferentDefaultArgument, + MethodNoTemplateArguments, + MethodDifferentNumberTemplateArguments, + MethodDifferentTemplateArgument, TypedefName, TypedefType, VarName, @@ -10370,6 +10379,89 @@ void ASTReader::diagnoseOdrViolations() { break; } + const auto *FirstTemplateArgs = + FirstMethod->getTemplateSpecializationArgs(); + const auto *SecondTemplateArgs = + SecondMethod->getTemplateSpecializationArgs(); + + if ((FirstTemplateArgs && !SecondTemplateArgs) || + (!FirstTemplateArgs && SecondTemplateArgs)) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), MethodNoTemplateArguments) + << FirstMethodType << FirstName << (FirstTemplateArgs != nullptr); + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), MethodNoTemplateArguments) + << SecondMethodType << SecondName + << (SecondTemplateArgs != nullptr); + + Diagnosed = true; + break; + } + + if (FirstTemplateArgs && SecondTemplateArgs) { + // Remove pack expansions from argument list. + auto ExpandTemplateArgumentList = + [](const TemplateArgumentList *TAL) { + llvm::SmallVector<const TemplateArgument *, 8> ExpandedList; + for (const TemplateArgument &TA : TAL->asArray()) { + if (TA.getKind() != TemplateArgument::Pack) { + ExpandedList.push_back(&TA); + continue; + } + for (const TemplateArgument &PackTA : TA.getPackAsArray()) { + ExpandedList.push_back(&PackTA); + } + } + return ExpandedList; + }; + llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList = + ExpandTemplateArgumentList(FirstTemplateArgs); + llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList = + ExpandTemplateArgumentList(SecondTemplateArgs); + + if (FirstExpandedList.size() != SecondExpandedList.size()) { + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), + MethodDifferentNumberTemplateArguments) + << FirstMethodType << FirstName + << (unsigned)FirstExpandedList.size(); + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), + MethodDifferentNumberTemplateArguments) + << SecondMethodType << SecondName + << (unsigned)SecondExpandedList.size(); + + Diagnosed = true; + break; + } + + bool TemplateArgumentMismatch = false; + for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) { + const TemplateArgument &FirstTA = *FirstExpandedList[i], + &SecondTA = *SecondExpandedList[i]; + if (ComputeTemplateArgumentODRHash(FirstTA) == + ComputeTemplateArgumentODRHash(SecondTA)) { + continue; + } + + ODRDiagError(FirstMethod->getLocation(), + FirstMethod->getSourceRange(), + MethodDifferentTemplateArgument) + << FirstMethodType << FirstName << FirstTA << i + 1; + ODRDiagNote(SecondMethod->getLocation(), + SecondMethod->getSourceRange(), + MethodDifferentTemplateArgument) + << SecondMethodType << SecondName << SecondTA << i + 1; + + TemplateArgumentMismatch = true; + break; + } + + if (TemplateArgumentMismatch) { + Diagnosed = true; + break; + } + } break; } case TypeAlias: |