[clang] 849d1b8 - [clang] Do not substitute parameter pack while retaining the pack expansion (#108197)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 12 04:21:30 PDT 2024
Author: Utkarsh Saxena
Date: 2024-09-12T13:21:26+02:00
New Revision: 849d1b8b1f1fc16dc28b07da358515a52b79ea81
URL: https://github.com/llvm/llvm-project/commit/849d1b8b1f1fc16dc28b07da358515a52b79ea81
DIFF: https://github.com/llvm/llvm-project/commit/849d1b8b1f1fc16dc28b07da358515a52b79ea81.diff
LOG: [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
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/TreeTransform.h
clang/test/SemaTemplate/pack-deduction.cpp
Removed:
################################################################################
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<void>::Inner<0>().Test(1,1);
}
}
+
+namespace GH107560 {
+int bar(...);
+
+template <int> struct Int {};
+
+template <class ...T>
+constexpr auto foo(T... x) -> decltype(bar(T(x)...)) { return 10; }
+
+template <class ...T>
+constexpr auto baz(Int<foo<T>(T())>... x) -> int { return 1; }
+
+static_assert(baz<Int<1>, Int<2>, Int<3>>(Int<10>(), Int<10>(), Int<10>()) == 1, "");
+}
More information about the cfe-commits
mailing list