tambre updated this revision to Diff 265855. tambre marked an inline comment as done. tambre added a comment.
Improve comment Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D79800/new/ https://reviews.llvm.org/D79800 Files: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/CXX/drs/dr22xx.cpp clang/test/CXX/drs/dr7xx.cpp clang/www/cxx_dr_status.html
Index: clang/www/cxx_dr_status.html =================================================================== --- clang/www/cxx_dr_status.html +++ clang/www/cxx_dr_status.html @@ -4681,7 +4681,7 @@ <td><a href="https://wg21.link/cwg777">777</a></td> <td>CD2</td> <td>Default arguments and parameter packs</td> - <td class="full" align="center">Clang 3.7</td> + <td class="full" align="center">Superseded by <a href="#2233">2233</a></td> </tr> <tr id="778"> <td><a href="https://wg21.link/cwg778">778</a></td> @@ -13213,7 +13213,7 @@ <td><a href="https://wg21.link/cwg2233">2233</a></td> <td>DRWP</td> <td>Function parameter packs following default arguments</td> - <td class="none" align="center">Unknown</td> + <td class="full" align="center">Clang 11</td> </tr> <tr id="2234"> <td><a href="https://wg21.link/cwg2234">2234</a></td> Index: clang/test/CXX/drs/dr7xx.cpp =================================================================== --- clang/test/CXX/drs/dr7xx.cpp +++ clang/test/CXX/drs/dr7xx.cpp @@ -219,16 +219,4 @@ Collision<int, int> c; // expected-note {{in instantiation of}} } -namespace dr777 { // dr777: 3.7 -#if __cplusplus >= 201103L -template <typename... T> -void f(int i = 0, T ...args) {} -void ff() { f(); } - -template <typename... T> -void g(int i = 0, T ...args, T ...args2) {} - -template <typename... T> -void h(int i = 0, T ...args, int j = 1) {} -#endif -} +// dr777 superseded by dr2233 Index: clang/test/CXX/drs/dr22xx.cpp =================================================================== --- clang/test/CXX/drs/dr22xx.cpp +++ clang/test/CXX/drs/dr22xx.cpp @@ -35,3 +35,44 @@ } #endif } + +namespace dr2233 { // dr2233: 11 +#if __cplusplus >= 201103L +template <typename... T> +void f(int i = 0, T... args) {} + +template <typename... T> +void g(int i = 0, T... args, T... args2) {} + +template <typename... T> +void h(int i = 0, T... args, int j = 1) {} + +template <typename... T, typename... U> +void i(int i = 0, T... args, int j = 1, U... args2) {} + +template <class... Ts> +void j(int i = 0, Ts... ts) {} + +template <> +void j<int>(int i, int j) {} + +// PR23029 +// Ensure instantiating the templates works. +void use() { + f(); + f(0, 1); + f<int>(1, 2); + g<int>(1, 2, 3); + h(0, 1); + i(); + i(3); + i<int>(3, 2); + i<int>(3, 2, 1); + i<int, int>(1, 2, 3, 4, 5); + j(); + j(1); + j(1, 2); + j<int>(1, 2); +} +#endif +} // namespace dr2233 Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1974,6 +1974,48 @@ TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost), /*InsertPos=*/nullptr); + + // DR777, DR2233. + // Parameter packs are allowed after and inbetween parameters with default + // values. We need to remove default arguments for parameters before the + // first expanded parameter pack to prevent the declaration being diagnosed + // as invalid due to the expanded parameters after parameters with default + // values lacking default values. This is safe to do because if a parameter + // pack is expanded the user must've provided arguments for all parameters + // before it. + FunctionDecl *TemplatedDecl = FunctionTemplate->getTemplatedDecl(); + unsigned FirstPack = Function->getNumParams(); + bool RemoveDefaults = false; + + // Go backwards through the template declaration parameters and find the + // first parameter pack, which has non-zero number of arguments. + for (unsigned p = TemplatedDecl->getNumParams(); p-- > 0;) { + ParmVarDecl *Param = TemplatedDecl->getParamDecl(p); + + if (Param->isParameterPack()) { + llvm::Optional<unsigned> Args = + SemaRef.getNumArgumentsInExpansion(Param->getType(), TemplateArgs); + assert(Args != None && "Unknown number of pack expansion arguments."); + + if (Args.getValue() == 0) + continue; + + FirstPack -= Args.getValue(); + RemoveDefaults = true; + break; + } else { + FirstPack--; + } + } + + // If we found such a parameter pack, then remove default arguments for all + // parameters before it. + if (RemoveDefaults) { + for (unsigned p = 0; p < FirstPack; p++) { + ParmVarDecl *Param = Function->getParamDecl(p); + Param->setDefaultArg(nullptr); + } + } } else if (isFriend && D->isThisDeclarationADefinition()) { // Do not connect the friend to the template unless it's actually a // definition. We don't want non-template functions to be marked as being
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits