diff options
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 319 |
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) |