|
@@ -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:
|