From 3b05e20031bcd9fbdc4f65ef1ada3e887f9daeaf Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Tue, 8 Oct 2013 16:58:52 +0000 Subject: 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. llvm-svn: 192202 --- clang/lib/AST/ASTDiagnostic.cpp | 15 ++++++++++----- clang/test/Misc/diag-template-diffing.cpp | 18 +++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'clang') diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index eb22632c937..fce8f64b332 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/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/clang/test/Misc/diag-template-diffing.cpp b/clang/test/Misc/diag-template-diffing.cpp index 722ce98ecff..46807070c7c 100644 --- a/clang/test/Misc/diag-template-diffing.cpp +++ b/clang/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. - -- cgit v1.2.3