]> granicus.if.org Git - clang/commitdiff
Fix deduction of pack elements after a braced-init-list.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 4 Jan 2017 02:59:16 +0000 (02:59 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 4 Jan 2017 02:59:16 +0000 (02:59 +0000)
Previously, if the arguments for a parameter pack contained a braced-init-list,
we would abort deduction (keeping the pack deductions from prior arguments) at
the point when we reached the braced-init-list, resulting in wrong deductions
and rejects-valids. We now just leave a "hole" in the pack for such an argument,
which needs to be filled by another deduction of the same pack.

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

lib/Sema/SemaTemplateDeduction.cpp
test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp

index 7923e7d7e698d84aa2049039b6f7a1402fc7e856..6dae37be277617addda8d49a7f9efcf98c0c7579 100644 (file)
@@ -3468,12 +3468,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
       if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
         TemplateDeductionResult Result;
         if (!DeduceFromInitializerList(*this, TemplateParams, ParamType, ILE,
-                                       Info, Deduced, TDF, Result)) {
-          // FIXME: Bailing out here is wrong; we could still need to deduce
-          // from later pack elements.
-          ++ArgIdx;
-          break;
-        }
+                                       Info, Deduced, TDF, Result))
+          continue;
 
         if (Result)
           return Result;
index 060a0f236b4e787a903f52ba6449c3464a8aad6a..c8595d2e3648b727bd6ddce230e5f3973c0be6bd 100644 (file)
@@ -103,6 +103,12 @@ T deduce(std::initializer_list<T>); // expected-note {{conflicting types for par
 template <typename T>
 T deduce_ref(const std::initializer_list<T>&); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
 
+template<typename T, typename U> struct pair { pair(...); };
+template<typename T> void deduce_pairs(std::initializer_list<pair<T, typename T::type>>);
+struct WithIntType { typedef int type; };
+
+template<typename ...T> void deduce_after_init_list_in_pack(void (*)(T...), T...); // expected-note {{<int, int> vs. <(no value), double>}}
+
 void argument_deduction() {
   static_assert(same_type<decltype(deduce({1, 2, 3})), int>::value, "bad deduction");
   static_assert(same_type<decltype(deduce({1.0, 2.0, 3.0})), double>::value, "bad deduction");
@@ -113,6 +119,14 @@ void argument_deduction() {
   static_assert(same_type<decltype(deduce_ref({1.0, 2.0, 3.0})), double>::value, "bad deduction");
 
   deduce_ref({1, 2.0}); // expected-error {{no matching function}}
+
+  pair<WithIntType, int> pi;
+  pair<WithIntType, float> pf;
+  deduce_pairs({pi, pi, pi}); // ok
+  deduce_pairs({pi, pf, pi}); // FIXME: This should be rejected, as we fail to produce a type that exactly matches the argument type.
+
+  deduce_after_init_list_in_pack((void(*)(int,int))0, {}, 0);
+  deduce_after_init_list_in_pack((void(*)(int,int))0, {}, 0.0); // expected-error {{no matching function}}
 }
 
 void auto_deduction() {