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

