]> granicus.if.org Git - clang/commitdiff
[serialization] PR34728: Don't assume that only a suffix of template
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 31 Jul 2018 21:01:53 +0000 (21:01 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 31 Jul 2018 21:01:53 +0000 (21:01 +0000)
parameters can have default arguments.

At least for function templates and class template partial
specializations, it's possible for a template parameter with a default
argument to be followed by a non-pack template parameter with no default
argument, and this case was not properly handled here.

Testcase by Steve O'Brien!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338438 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTReaderDecl.cpp
test/PCH/cxx-templates.cpp
test/PCH/cxx-templates.h

index da30612b4f1c920d7ca251276822d654246f5ba0..ad37a2978df1a23a4cab0c8c37eb07ab98bbaad1 100644 (file)
@@ -3439,22 +3439,16 @@ static void inheritDefaultTemplateArguments(ASTContext &Context,
   assert(FromTP->size() == ToTP->size() && "merged mismatched templates?");
 
   for (unsigned I = 0, N = FromTP->size(); I != N; ++I) {
-    NamedDecl *FromParam = FromTP->getParam(N - I - 1);
-    if (FromParam->isParameterPack())
-      continue;
-    NamedDecl *ToParam = ToTP->getParam(N - I - 1);
+    NamedDecl *FromParam = FromTP->getParam(I);
+    NamedDecl *ToParam = ToTP->getParam(I);
 
-    if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam)) {
-      if (!inheritDefaultTemplateArgument(Context, FTTP, ToParam))
-        break;
-    } else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) {
-      if (!inheritDefaultTemplateArgument(Context, FNTTP, ToParam))
-        break;
-    } else {
-      if (!inheritDefaultTemplateArgument(
-              Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam))
-        break;
-    }
+    if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam))
+      inheritDefaultTemplateArgument(Context, FTTP, ToParam);
+    else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam))
+      inheritDefaultTemplateArgument(Context, FNTTP, ToParam);
+    else
+      inheritDefaultTemplateArgument(
+              Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam);
   }
 }
 
index e241701f50df9c80360150e991d2b772788c27eb..a7f7b1981f563f8e2f5fe0874163cd3f2053c18e 100644 (file)
@@ -116,3 +116,19 @@ namespace MemberSpecializationLocation {
 #endif
   int k = A<int>::n;
 }
+
+// https://bugs.llvm.org/show_bug.cgi?id=34728
+namespace PR34728 {
+int test() {
+  // Verify with several TemplateParmDecl kinds, using PCH (incl. modules).
+  int z1 = func1(/*ignored*/2.718);
+  int z2 = func2(/*ignored*/3.142);
+  int tmp3 = 30;
+  Container<int> c = func3(tmp3);
+  int z3 = c.item;
+
+  // Return value is meaningless.  Just "use" all these values to avoid
+  // warning about unused vars / values.
+  return z1 + z2 + z3;
+}
+} // end namespace PR34728
index 68b252e7974e9d83502a62cc558da585443c6d9e..e812aa68fb817c4680febc4f91c359622fa6a090 100644 (file)
@@ -361,3 +361,38 @@ namespace rdar15468709c {
 namespace MemberSpecializationLocation {
   template<typename T> struct A { static int n; };
 }
+
+// https://bugs.llvm.org/show_bug.cgi?id=34728
+namespace PR34728 {
+
+// case 1: defaulted `NonTypeTemplateParmDecl`, non-defaulted 2nd tpl param
+template <int foo = 10, class T>
+int func1(T const &);
+
+template <int foo, class T>
+int func1(T const &) {
+  return foo;
+}
+
+// case 2: defaulted `TemplateTypeParmDecl`, non-defaulted 2nd tpl param
+template <class A = int, class B>
+A func2(B const &);
+
+template <class A, class B>
+A func2(B const &) {
+  return A(20.0f);
+}
+
+// case 3: defaulted `TemplateTemplateParmDecl`, non-defaulted 2nd tpl param
+template <class T>
+struct Container { T const &item; };
+
+template <template <class> class C = Container, class D>
+C<D> func3(D const &);
+
+template <template <class> class C, class D>
+C<D> func3(D const &d) {
+  return Container<D>{d};
+}
+
+} // end namespace PR34728