It looks to me that assuming resolution of core issue #778 is accepted, the following is valid code template<typename ...T> struct A { template<template<T> class ...> struct B { }; }; template<int> struct C { }; template<long> struct D { }; int main() { A<int, long>::B<C, D> e; } Clang errors out (only showing the first relevant error message): main1.cpp:3:22: error: non-type template parameter type contains unexpanded parameter pack 'T' template<template<T> class ...>
We need to look at the levels of the parameter pack. Core issue 778 also made this ill-formed: template<typename ... T, T... V> struct X { };
I have been thinking about how to properly address this, but it's a rather radical departure from how we behave now. The idea is to model 'contains unexpanded parameter pack' as a purely lexical property: In the parser: * Add an RAII object around each context where we might have a pack expansion (the contexts listed in [temp.variadic]p4). These objects form a stack. * Every time we see a reference to a parameter pack, add it to the top object on the stack. If there's no such object, diagnose an unexpanded parameter pack. * When we get to the end of a pack expansion context: - if the context is expanded, hand the list of expanded packs off to Sema (or diagnose if it's empty) to be stored in the corresponding pack expansion node. - if the context is not expanded, hand the list off to the parent object (or diagnose if there is none). * When parsing a decltype type, inform Sema if it contains any unexpanded parameter packs so it can be treated as dependent. In Sema: * When performing pack expansion, pull the list of expanded packs out of the pack expansion node. * Delete SemaTemplateVariadic.cpp and all calls to DiagnoseUnexpandedParameterPack. * Remove the special-case handling for lambdas. In AST: * Remove the ContainsUnexpandedParameterPack bit from Expr and Type.
The problem in comment#0 is fixed in r163369. It turns out that most of this work was independent of the change I proposed in comment#2. We don't implement the check mentioned in comment#1 yet. Leaving this open for the comment#1 check and comment#2 work. We still get some cases wrong, for instance: * statement-expressions inside pack expansions * default template arguments inside template template parameters which are pack expansions * Objective-C blocks inside pack expansions