erik.pilkington created this revision. erik.pilkington added a reviewer: rsmith. erik.pilkington added a subscriber: cfe-commits.
Clang rejects the following valid code: ``` template <class T> struct Foo {}; template <class... Ts> using FooAlias = Foo<void(Ts...)>; template <class... Ts> int bar(FooAlias<Ts...>); int main() { bar(FooAlias<>()); } ``` The problem is that in the substitution of `FooAlias<Ts...>` during the parsing of bar, the pack expansion in `Foo<void(Ts...)>` is transformed into a parameter with the unexpanded flag set, as opposed to another pack expansion. This leads to deduction failing in `main`, which is incorrect. The fix is to expand the parameter pack when needed. Fixes PR25250 & PR26017. Incidentally, there was an incorrect comment in a very similar function that said that a path wasn't reachable. This isn't the case, although no existing test case exercised it, so I added one that did. Please let me know if it would be cleaner to commit that separately! Thanks! http://reviews.llvm.org/D21030 Files: lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/p5.cpp Index: test/CXX/temp/temp.decls/temp.variadic/p5.cpp =================================================================== --- test/CXX/temp/temp.decls/temp.variadic/p5.cpp +++ test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -437,3 +437,32 @@ template void g<>(); template void g<1, 2, 3>(); } + +template <class... Ts> +int var_expr(Ts... ts); + +template <class... Ts> +auto a_function(Ts... ts) -> decltype(var_expr(ts...)); + +template <class T> +using partial = decltype(a_function<int, T>); + +int use_partial() { partial<char> n; } + +namespace PR26017 { +template <class T> +struct Foo {}; +template <class... Ts> +using FooAlias = Foo<void(Ts...)>; + +template <class... Ts> +void bar(const FooAlias<Ts...> &) {} + +int fn() { + FooAlias<> a; + bar(a); + + FooAlias<int> b; + bar(b); +} +} Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -3311,8 +3311,6 @@ if (Out.isInvalid()) return true; - // FIXME: Can this happen? We should not try to expand the pack - // in this case. if (Out.get()->containsUnexpandedParameterPack()) { Out = getDerived().RebuildPackExpansion( Out.get(), Expansion->getEllipsisLoc(), OrigNumExpansions); @@ -4781,6 +4779,13 @@ if (NewType.isNull()) return true; + if (NewType->containsUnexpandedParameterPack()) { + NewType = getDerived().RebuildPackExpansionType( + NewType, SourceRange(), Loc, NumExpansions); + if (NewType.isNull()) + return true; + } + if (ParamInfos) PInfos.set(OutParamTypes.size(), ParamInfos[i]); OutParamTypes.push_back(NewType);
Index: test/CXX/temp/temp.decls/temp.variadic/p5.cpp =================================================================== --- test/CXX/temp/temp.decls/temp.variadic/p5.cpp +++ test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -437,3 +437,32 @@ template void g<>(); template void g<1, 2, 3>(); } + +template <class... Ts> +int var_expr(Ts... ts); + +template <class... Ts> +auto a_function(Ts... ts) -> decltype(var_expr(ts...)); + +template <class T> +using partial = decltype(a_function<int, T>); + +int use_partial() { partial<char> n; } + +namespace PR26017 { +template <class T> +struct Foo {}; +template <class... Ts> +using FooAlias = Foo<void(Ts...)>; + +template <class... Ts> +void bar(const FooAlias<Ts...> &) {} + +int fn() { + FooAlias<> a; + bar(a); + + FooAlias<int> b; + bar(b); +} +} Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -3311,8 +3311,6 @@ if (Out.isInvalid()) return true; - // FIXME: Can this happen? We should not try to expand the pack - // in this case. if (Out.get()->containsUnexpandedParameterPack()) { Out = getDerived().RebuildPackExpansion( Out.get(), Expansion->getEllipsisLoc(), OrigNumExpansions); @@ -4781,6 +4779,13 @@ if (NewType.isNull()) return true; + if (NewType->containsUnexpandedParameterPack()) { + NewType = getDerived().RebuildPackExpansionType( + NewType, SourceRange(), Loc, NumExpansions); + if (NewType.isNull()) + return true; + } + if (ParamInfos) PInfos.set(OutParamTypes.size(), ParamInfos[i]); OutParamTypes.push_back(NewType);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits