From 849d1b8b1f1fc16dc28b07da358515a52b79ea81 Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena Date: Thu, 12 Sep 2024 13:21:26 +0200 Subject: [PATCH] [clang] Do not substitute parameter pack while retaining the pack expansion (#108197) (In reference to https://github.com/llvm/llvm-project/pull/108197/commits/5901d82ea0543074853b963f7dc9106a6fe3bcee) Consider when `Input[I]` is a `VarDecl` with parameter pack. We would have already expanded the pack before the code change in the loop`for (unsigned I = 0; I != *NumExpansions; ++I) {`. Now in `if (RetainExpansion) {`, without this change, we continue to substitute the pack in the pattern even when we do not have meaningful `ArgumentPackSubstitutionIndex` set. This leads to use of an invalid pack substitution index in `TemplateInstantiator::TransformFunctionParmPackRefExpr` in `TransformedDecl = (*Pack)[getSema().ArgumentPackSubstitutionIndex];` This change sets `ArgumentPackSubstitutionIndex` to `-1` while retaining expansion to instruct `TransformFunctionParmPackRefExpr` to build `FunctionParmPackExpr` instead of substituting the param pack. --- There are other instances of `RetainExpansion` and IIUC, they should also unset the `ArgumentPackSubstitutionIndex`. It would be great if someone can verify my understanding. If this is correct then we could instead have a `ArgumentPackSubstitutionIndexRAII` as part of `ForgetPartiallySubstitutedPackRAII`. EDIT: I have moved this to `ForgetPartiallySubstitutedPackRAII`. Fixes https://github.com/llvm/llvm-project/issues/63819 Fixes https://github.com/llvm/llvm-project/issues/107560 --- clang/docs/ReleaseNotes.rst | 3 +++ clang/lib/Sema/TreeTransform.h | 6 +++++- clang/test/SemaTemplate/pack-deduction.cpp | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d4db877a823ea5..c4fa017b982bbd 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -382,6 +382,9 @@ Bug Fixes to C++ Support - Fix a crash when using ``source_location`` in the trailing return type of a lambda expression. (#GH67134) - A follow-up fix was added for (#GH61460), as the previous fix was not entirely correct. (#GH86361) - Fixed a crash in the typo correction of an invalid CTAD guide. (#GH107887) +- Fixed a crash when clang tries to subtitute parameter pack while retaining the parameter + pack. #GH63819, #GH107560 + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 4bbc024587915c..ff745b3385fcd9 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -113,9 +113,13 @@ class TreeTransform { class ForgetPartiallySubstitutedPackRAII { Derived &Self; TemplateArgument Old; + // Set the pack expansion index to -1 to avoid pack substitution and + // indicate that parameter packs should be instantiated as themselves. + Sema::ArgumentPackSubstitutionIndexRAII ResetPackSubstIndex; public: - ForgetPartiallySubstitutedPackRAII(Derived &Self) : Self(Self) { + ForgetPartiallySubstitutedPackRAII(Derived &Self) + : Self(Self), ResetPackSubstIndex(Self.getSema(), -1) { Old = Self.ForgetPartiallySubstitutedPack(); } diff --git a/clang/test/SemaTemplate/pack-deduction.cpp b/clang/test/SemaTemplate/pack-deduction.cpp index e42709820e9cff..28fb127a386441 100644 --- a/clang/test/SemaTemplate/pack-deduction.cpp +++ b/clang/test/SemaTemplate/pack-deduction.cpp @@ -185,3 +185,17 @@ void Run() { Outer::Inner<0>().Test(1,1); } } + +namespace GH107560 { +int bar(...); + +template struct Int {}; + +template +constexpr auto foo(T... x) -> decltype(bar(T(x)...)) { return 10; } + +template +constexpr auto baz(Int(T())>... x) -> int { return 1; } + +static_assert(baz, Int<2>, Int<3>>(Int<10>(), Int<10>(), Int<10>()) == 1, ""); +}