From: Benjamin Kramer Date: Tue, 8 Oct 2013 16:58:52 +0000 (+0000) Subject: Fix an edge case in the template differ with default arguments. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5ce45c77fc986d13f8cf566b2c195c7cda8afde3;p=clang Fix an edge case in the template differ with default arguments. In the test case one type is coming from a typedef with no default arg, the other has the default arg. Taking the default arg from the typedef crashes, so always use the real template paramter declaration. PR17510. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192202 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index eb22632c93..fce8f64b33 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -831,8 +831,10 @@ class TemplateDiff { void DiffTemplate(const TemplateSpecializationType *FromTST, const TemplateSpecializationType *ToTST) { // Begin descent into diffing template tree. - TemplateParameterList *Params = + TemplateParameterList *ParamsFrom = FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); + TemplateParameterList *ParamsTo = + ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); unsigned TotalArgs = 0; for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST); !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) { @@ -841,15 +843,18 @@ class TemplateDiff { // Get the parameter at index TotalArgs. If index is larger // than the total number of parameters, then there is an // argument pack, so re-use the last parameter. - NamedDecl *ParamND = Params->getParam( - (TotalArgs < Params->size()) ? TotalArgs - : Params->size() - 1); + unsigned ParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1); + NamedDecl *ParamND = ParamsFrom->getParam(ParamIndex); + // Handle Types if (TemplateTypeParmDecl *DefaultTTPD = dyn_cast(ParamND)) { QualType FromType, ToType; FromType = GetType(FromIter, DefaultTTPD); - ToType = GetType(ToIter, DefaultTTPD); + // A forward declaration can have no default arg but the actual class + // can, don't mix up iterators and get the original parameter. + ToType = GetType( + ToIter, cast(ParamsTo->getParam(ParamIndex))); Tree.SetNode(FromType, ToType); Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), ToIter.isEnd() && !ToType.isNull()); diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp index 722ce98ecf..46807070c7 100644 --- a/test/Misc/diag-template-diffing.cpp +++ b/test/Misc/diag-template-diffing.cpp @@ -1051,8 +1051,24 @@ namespace DependentInt { } } +namespace PR17510 { +class Atom; + +template class allocator; +template class vector; + +typedef vector > AtomVector; + +template > class vector {}; + +void foo() { + vector v; + AtomVector v2(v); + // CHECK-ELIDE-NOTREE: no known conversion from 'vector' to 'const vector' +} +} + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-TREE: {{[0-9]*}} errors generated. -