]> granicus.if.org Git - clang/commitdiff
If an explicitly-specified pack might have been extended by template argument
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 5 Jan 2017 20:27:28 +0000 (20:27 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 5 Jan 2017 20:27:28 +0000 (20:27 +0000)
deduction, don't forget to check the argument is valid.

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

lib/Sema/SemaTemplateDeduction.cpp
test/SemaTemplate/deduction.cpp

index 6c90b5c2266de77a38d1330dada571fb5cc91ecc..7750b9c0eaef800cfd7f7ecaa013e31418384064 100644 (file)
@@ -2215,25 +2215,26 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
 
     if (!Deduced[I].isNull()) {
       if (I < NumAlreadyConverted) {
-        // We have already fully type-checked and converted this
-        // argument, because it was explicitly-specified. Just record the
-        // presence of this argument.
-        Builder.push_back(Deduced[I]);
         // We may have had explicitly-specified template arguments for a
         // template parameter pack (that may or may not have been extended
         // via additional deduced arguments).
-        if (Param->isParameterPack() && CurrentInstantiationScope) {
-          if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
-              Param) {
-            // Forget the partially-substituted pack; its substitution is now
-            // complete.
-            CurrentInstantiationScope->ResetPartiallySubstitutedPack();
-          }
+        if (Param->isParameterPack() && CurrentInstantiationScope &&
+            CurrentInstantiationScope->getPartiallySubstitutedPack() == Param) {
+          // Forget the partially-substituted pack; its substitution is now
+          // complete.
+          CurrentInstantiationScope->ResetPartiallySubstitutedPack();
+          // We still need to check the argument in case it was extended by
+          // deduction.
+        } else {
+          // We have already fully type-checked and converted this
+          // argument, because it was explicitly-specified. Just record the
+          // presence of this argument.
+          Builder.push_back(Deduced[I]);
+          continue;
         }
-        continue;
       }
 
-      // We have deduced this argument, so it still needs to be
+      // We may have deduced this argument, so it still needs to be
       // checked and converted.
       if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info,
                                          IsDeduced, Builder)) {
index 940f6018f20c0a49ec6a1e6c94d7869c07d02ede..2275a8b3b7ad2d8cc664adfb8b4da036effa8e5e 100644 (file)
@@ -428,3 +428,17 @@ namespace deduction_from_empty_list {
     f<1>({0}, {0, 1}); // expected-error {{no matching}}
   }
 }
+
+namespace check_extended_pack {
+  template<typename T> struct X { typedef int type; };
+  template<typename ...T> void f(typename X<T>::type...);
+  template<typename T> void f(T, int, int);
+  void g() {
+    f<int>(0, 0, 0);
+  }
+
+  template<int, int*> struct Y {};
+  template<int ...N> void g(Y<N...>); // expected-note {{deduced non-type template argument does not have the same type as the corresponding template parameter ('int *' vs 'int')}}
+  int n;
+  void h() { g<0>(Y<0, &n>()); } // expected-error {{no matching function}}
+}