]> granicus.if.org Git - clang/commitdiff
Fix an edge case in the template differ with default arguments.
authorBenjamin Kramer <benny.kra@googlemail.com>
Tue, 8 Oct 2013 16:58:52 +0000 (16:58 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Tue, 8 Oct 2013 16:58:52 +0000 (16:58 +0000)
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

lib/AST/ASTDiagnostic.cpp
test/Misc/diag-template-diffing.cpp

index eb22632c9374ffe949537b778140626a67328d94..fce8f64b33287def30cf87661b4e9d376bb05a35 100644 (file)
@@ -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<TemplateTypeParmDecl>(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<TemplateTypeParmDecl>(ParamsTo->getParam(ParamIndex)));
         Tree.SetNode(FromType, ToType);
         Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),
                         ToIter.isEnd() && !ToType.isNull());
index 722ce98ecffebb2080e26d2cd2ca9f644aa8c5dd..46807070c7ccdf415390cb7b6805f096c6ad08b0 100644 (file)
@@ -1051,8 +1051,24 @@ namespace DependentInt {
   }
 }
 
+namespace PR17510 {
+class Atom;
+
+template <typename T> class allocator;
+template <typename T, typename A> class vector;
+
+typedef vector<const Atom *, allocator<const Atom *> > AtomVector;
+
+template <typename T, typename A = allocator<const Atom *> > class vector {};
+
+void foo() {
+  vector<Atom *> v;
+  AtomVector v2(v);
+  // CHECK-ELIDE-NOTREE: no known conversion from 'vector<class PR17510::Atom *, [...]>' to 'const vector<const class PR17510::Atom *, [...]>'
+}
+}
+
 // 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.
-