https://gcc.gnu.org/g:41006b6da54d2fd1b8e5fd81018a1ad6f61183d8
commit r17-1726-g41006b6da54d2fd1b8e5fd81018a1ad6f61183d8 Author: Jason Merrill <[email protected]> Date: Sat Jun 20 18:23:09 2026 -0400 c++: typedef in lambda in pack expansion In trying to reduce the testcase for PR125408, I came across an older regression, dating back to r14-9938, though the problem wasn't in that commit. cp_walk_subtrees avoids walking into uses of typedefs because it wants to look at what's actually written. But here we were also skipping over the definition of the typedef, so extract_locals_r never got to see the use of 't', so later substitution failed. Fixed by specifically handling typedef DECL_EXPR. PR c++/125408 gcc/cp/ChangeLog: * tree.cc (cp_walk_subtrees): Walk into the DECL_ORIGINAL_TYPE of a typedef DECL_EXPR. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/lambda-targ33.C: New test. Diff: --- gcc/cp/tree.cc | 4 ++++ gcc/testsuite/g++.dg/cpp2a/lambda-targ33.C | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index c9b299007467..a99f5e19c0d8 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -6407,6 +6407,10 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, WALK_SUBTREE (DECL_SIZE (decl)); WALK_SUBTREE (DECL_SIZE_UNIT (decl)); } + if (is_typedef_decl (TREE_OPERAND (t, 0))) + /* We avoid walking into typedefs above, but we do want to walk + into them if we're looking at the actual declaration. */ + WALK_SUBTREE (DECL_ORIGINAL_TYPE (TREE_OPERAND (t, 0))); break; case LAMBDA_EXPR: diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ33.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ33.C new file mode 100644 index 000000000000..3b42f322c775 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ33.C @@ -0,0 +1,24 @@ +// PR c++/125408 +// { dg-do compile { target c++20 } } + +struct Role { + long id; +}; + +template <typename T> T Obj; +template<int... I> struct A { }; +void sink(...); + +template <auto Ptr, typename Table> +constexpr int find_member_index() { + constexpr auto& t = Obj<Table>; + []<int... Idx>(A<Idx...>) { + sink([]() { + using T1 = decltype(&(t.*Ptr)); + return Idx; + }() ...); + }(A<1,2>{}); + return 42; +} + +auto i = find_member_index<&Role::id, Role>();
