summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r--clang/lib/Serialization/ASTReader.cpp319
1 files changed, 318 insertions, 1 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 8224236f610..391e3504459 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9462,6 +9462,14 @@ void ASTReader::diagnoseOdrViolations() {
return Hash.CalculateHash();
};
+ auto ComputeTemplateParameterListODRHash =
+ [&Hash](const TemplateParameterList *TPL) {
+ assert(TPL);
+ Hash.clear();
+ Hash.AddTemplateParameterList(TPL);
+ 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
@@ -9814,6 +9822,7 @@ void ASTReader::diagnoseOdrViolations() {
TypeDef,
Var,
Friend,
+ FunctionTemplate,
Other
} FirstDiffType = Other,
SecondDiffType = Other;
@@ -9851,6 +9860,8 @@ void ASTReader::diagnoseOdrViolations() {
return Var;
case Decl::Friend:
return Friend;
+ case Decl::FunctionTemplate:
+ return FunctionTemplate;
}
};
@@ -9937,7 +9948,7 @@ void ASTReader::diagnoseOdrViolations() {
// Used with err_module_odr_violation_mismatch_decl_diff and
// note_module_odr_violation_mismatch_decl_diff
- enum ODRDeclDifference{
+ enum ODRDeclDifference {
StaticAssertCondition,
StaticAssertMessage,
StaticAssertOnlyMessage,
@@ -9973,6 +9984,13 @@ void ASTReader::diagnoseOdrViolations() {
FriendTypeFunction,
FriendType,
FriendFunction,
+ FunctionTemplateDifferentNumberParameters,
+ FunctionTemplateParameterDifferentKind,
+ FunctionTemplateParameterName,
+ FunctionTemplateParameterSingleDefaultArgument,
+ FunctionTemplateParameterDifferentDefaultArgument,
+ FunctionTemplateParameterDifferentType,
+ FunctionTemplatePackParameter,
};
// These lambdas have the common portions of the ODR diagnostics. This
@@ -10620,6 +10638,305 @@ void ASTReader::diagnoseOdrViolations() {
Diagnosed = true;
break;
}
+ case FunctionTemplate: {
+ FunctionTemplateDecl *FirstTemplate =
+ cast<FunctionTemplateDecl>(FirstDecl);
+ FunctionTemplateDecl *SecondTemplate =
+ cast<FunctionTemplateDecl>(SecondDecl);
+
+ TemplateParameterList *FirstTPL =
+ FirstTemplate->getTemplateParameters();
+ TemplateParameterList *SecondTPL =
+ SecondTemplate->getTemplateParameters();
+
+ if (FirstTPL->size() != SecondTPL->size()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateDifferentNumberParameters)
+ << FirstTemplate << FirstTPL->size();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateDifferentNumberParameters)
+ << SecondTemplate << SecondTPL->size();
+
+ Diagnosed = true;
+ break;
+ }
+
+ bool ParameterMismatch = false;
+ for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) {
+ NamedDecl *FirstParam = FirstTPL->getParam(i);
+ NamedDecl *SecondParam = SecondTPL->getParam(i);
+
+ if (FirstParam->getKind() != SecondParam->getKind()) {
+ enum {
+ TemplateTypeParameter,
+ NonTypeTemplateParameter,
+ TemplateTemplateParameter,
+ };
+ auto GetParamType = [](NamedDecl *D) {
+ switch (D->getKind()) {
+ default:
+ llvm_unreachable("Unexpected template parameter type");
+ case Decl::TemplateTypeParm:
+ return TemplateTypeParameter;
+ case Decl::NonTypeTemplateParm:
+ return NonTypeTemplateParameter;
+ case Decl::TemplateTemplateParm:
+ return TemplateTemplateParameter;
+ }
+ };
+
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentKind)
+ << FirstTemplate << (i + 1) << GetParamType(FirstParam);
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentKind)
+ << SecondTemplate << (i + 1) << GetParamType(SecondParam);
+
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (FirstParam->getName() != SecondParam->getName()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterName)
+ << FirstTemplate << (i + 1) << (bool)FirstParam->getIdentifier()
+ << FirstParam;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterName)
+ << SecondTemplate << (i + 1)
+ << (bool)SecondParam->getIdentifier() << SecondParam;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (isa<TemplateTypeParmDecl>(FirstParam) &&
+ isa<TemplateTypeParmDecl>(SecondParam)) {
+ TemplateTypeParmDecl *FirstTTPD =
+ cast<TemplateTypeParmDecl>(FirstParam);
+ TemplateTypeParmDecl *SecondTTPD =
+ cast<TemplateTypeParmDecl>(SecondParam);
+ bool HasFirstDefaultArgument =
+ FirstTTPD->hasDefaultArgument() &&
+ !FirstTTPD->defaultArgumentWasInherited();
+ bool HasSecondDefaultArgument =
+ SecondTTPD->hasDefaultArgument() &&
+ !SecondTTPD->defaultArgumentWasInherited();
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+ QualType FirstType = FirstTTPD->getDefaultArgument();
+ QualType SecondType = SecondTTPD->getDefaultArgument();
+ if (ComputeQualTypeODRHash(FirstType) !=
+ ComputeQualTypeODRHash(SecondType)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << FirstTemplate << (i + 1) << FirstType;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << SecondTemplate << (i + 1) << SecondType;
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (FirstTTPD->isParameterPack() !=
+ SecondTTPD->isParameterPack()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (isa<TemplateTemplateParmDecl>(FirstParam) &&
+ isa<TemplateTemplateParmDecl>(SecondParam)) {
+ TemplateTemplateParmDecl *FirstTTPD =
+ cast<TemplateTemplateParmDecl>(FirstParam);
+ TemplateTemplateParmDecl *SecondTTPD =
+ cast<TemplateTemplateParmDecl>(SecondParam);
+
+ TemplateParameterList *FirstTPL =
+ FirstTTPD->getTemplateParameters();
+ TemplateParameterList *SecondTPL =
+ SecondTTPD->getTemplateParameters();
+
+ if (ComputeTemplateParameterListODRHash(FirstTPL) !=
+ ComputeTemplateParameterListODRHash(SecondTPL)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << FirstTemplate << (i + 1);
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << SecondTemplate << (i + 1);
+ ParameterMismatch = true;
+ break;
+ }
+
+ bool HasFirstDefaultArgument =
+ FirstTTPD->hasDefaultArgument() &&
+ !FirstTTPD->defaultArgumentWasInherited();
+ bool HasSecondDefaultArgument =
+ SecondTTPD->hasDefaultArgument() &&
+ !SecondTTPD->defaultArgumentWasInherited();
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+ TemplateArgument FirstTA =
+ FirstTTPD->getDefaultArgument().getArgument();
+ TemplateArgument SecondTA =
+ SecondTTPD->getDefaultArgument().getArgument();
+ if (ComputeTemplateArgumentODRHash(FirstTA) !=
+ ComputeTemplateArgumentODRHash(SecondTA)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << FirstTemplate << (i + 1) << FirstTA;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << SecondTemplate << (i + 1) << SecondTA;
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (FirstTTPD->isParameterPack() !=
+ SecondTTPD->isParameterPack()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << FirstTemplate << (i + 1) << FirstTTPD->isParameterPack();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << SecondTemplate << (i + 1) << SecondTTPD->isParameterPack();
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (isa<NonTypeTemplateParmDecl>(FirstParam) &&
+ isa<NonTypeTemplateParmDecl>(SecondParam)) {
+ NonTypeTemplateParmDecl *FirstNTTPD =
+ cast<NonTypeTemplateParmDecl>(FirstParam);
+ NonTypeTemplateParmDecl *SecondNTTPD =
+ cast<NonTypeTemplateParmDecl>(SecondParam);
+
+ QualType FirstType = FirstNTTPD->getType();
+ QualType SecondType = SecondNTTPD->getType();
+ if (ComputeQualTypeODRHash(FirstType) !=
+ ComputeQualTypeODRHash(SecondType)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << FirstTemplate << (i + 1);
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentType)
+ << SecondTemplate << (i + 1);
+ ParameterMismatch = true;
+ break;
+ }
+
+ bool HasFirstDefaultArgument =
+ FirstNTTPD->hasDefaultArgument() &&
+ !FirstNTTPD->defaultArgumentWasInherited();
+ bool HasSecondDefaultArgument =
+ SecondNTTPD->hasDefaultArgument() &&
+ !SecondNTTPD->defaultArgumentWasInherited();
+ if (HasFirstDefaultArgument != HasSecondDefaultArgument) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << FirstTemplate << (i + 1) << HasFirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterSingleDefaultArgument)
+ << SecondTemplate << (i + 1) << HasSecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+
+ if (HasFirstDefaultArgument && HasSecondDefaultArgument) {
+ Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument();
+ Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument();
+ if (ComputeODRHash(FirstDefaultArgument) !=
+ ComputeODRHash(SecondDefaultArgument)) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << FirstTemplate << (i + 1) << FirstDefaultArgument;
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplateParameterDifferentDefaultArgument)
+ << SecondTemplate << (i + 1) << SecondDefaultArgument;
+ ParameterMismatch = true;
+ break;
+ }
+ }
+
+ if (FirstNTTPD->isParameterPack() !=
+ SecondNTTPD->isParameterPack()) {
+ ODRDiagError(FirstTemplate->getLocation(),
+ FirstTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << FirstTemplate << (i + 1) << FirstNTTPD->isParameterPack();
+ ODRDiagNote(SecondTemplate->getLocation(),
+ SecondTemplate->getSourceRange(),
+ FunctionTemplatePackParameter)
+ << SecondTemplate << (i + 1)
+ << SecondNTTPD->isParameterPack();
+ ParameterMismatch = true;
+ break;
+ }
+ }
+ }
+
+ if (ParameterMismatch) {
+ Diagnosed = true;
+ break;
+ }
+
+ break;
+ }
}
if (Diagnosed)
OpenPOWER on IntegriCloud