diff options
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 12 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp | 100 |
2 files changed, 111 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 7d9cec141a3..f941a0992cb 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2816,9 +2816,19 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, // 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(); + } + } continue; } - // We have deduced this argument, so it still needs to be // checked and converted. diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp new file mode 100644 index 00000000000..b0b86e38772 --- /dev/null +++ b/clang/test/SemaCXX/cxx1y-generic-lambdas-variadics.cpp @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING + +namespace explicit_argument_variadics { + + +template<class ... Ts> void print(Ts ... ) { } + +struct X { }; +struct Y { }; +struct Z { }; + +int test() { + { + auto L = [](auto ... as) { }; + L.operator()<bool>(true); + } + { + auto L = [](auto a) { }; + L.operator()<bool>(false); + } + { + auto L = [](auto a, auto b) { }; + L.operator()<bool>(false, 'a'); + } + { + auto L = [](auto a, auto b) { }; + L.operator()<bool, char>(false, 'a'); + } + { + auto L = [](auto a, auto b, auto ... cs) { }; + L.operator()<bool, char>(false, 'a'); + L.operator()<bool, char, const char*>(false, 'a', "jim"); + } + + { + auto L = [](auto ... As) { + }; + L.operator()<bool, double>(false, 3.14, "abc"); + } + { + auto L = [](auto A, auto B, auto ... As) { + }; + L.operator()<bool>(false, 3.14, "abc"); + L.operator()<bool, char>(false, 3.14, "abc"); //expected-warning{{implicit conversion}} + L.operator()<X, Y, bool, Z>(X{}, Y{}, 3.14, Z{}, X{}); //expected-warning{{implicit conversion}} + } + { + auto L = [](auto ... As) { + print("\nL::As = ", As ...); + return [](decltype(As) ... as, auto ... Bs) { + print("\nL::Inner::as = ", as ...); + print("\nL::Inner::Bs = ", Bs ...); + return 4; + }; + }; + auto M = L.operator()<bool, double>(false, 3.14, "abc"); + M(false, 6.26, "jim", true); + M.operator()<bool>(true, 6.26, "jim", false, 3.14); + } + { + auto L = [](auto A, auto ... As) { + print("\nL::As = ", As ...); + return [](decltype(As) ... as, decltype(A) a, auto ... Bs) { + print("\nL::Inner::as = ", as ...); + print("\nL::Inner::Bs = ", Bs ...); + return 4; + }; + }; + auto M = L.operator()<bool, double>(false, 3.14, "abc"); + M(6.26, "jim", true); + M.operator()<X>(6.26, "jim", false, X{}, Y{}, Z{}); + } + + return 0; +} + int run = test(); +} // end ns explicit_argument_extension + + + +#ifdef PR18499_FIXED +namespace variadic_expansion { + void f(int &, char &); + + template <typename ... T> void g(T &... t) { + f([&a(t)]()->decltype(auto) { + return a; + }() ...); + f([&a(f([&b(t)]()->decltype(auto) { return b; }()...), t)]()->decltype(auto) { + return a; + }()...); + } + + void h(int i, char c) { g(i, c); } +} +#endif + |