Skip to content

Commit d26f589

Browse files
committed
c++: sizeof... mangling with alias template [PR95298]
We were getting sizeof... mangling wrong when the argument after substitution was a pack expansion that is not a simple T..., such as list<T>... in variadic-mangle4.C or (A+1)... in variadic-mangle5.C. In the former case we ICEd; in the latter case we wrongly mangled it as sZ <expression>. PR c++/95298 gcc/cp/ChangeLog: * mangle.cc (write_expression): Handle v18 sizeof... bug. * pt.cc (tsubst_pack_expansion): Keep TREE_VEC for sizeof... (tsubst_expr): Don't strip TREE_VEC here. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/variadic-mangle2.C: Add non-member. * g++.dg/cpp0x/variadic-mangle4.C: New test. * g++.dg/cpp0x/variadic-mangle5.C: New test. * g++.dg/cpp0x/variadic-mangle5a.C: New test.
1 parent 2fa122c commit d26f589

File tree

6 files changed

+86
-3
lines changed

6 files changed

+86
-3
lines changed

gcc/cp/mangle.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3444,6 +3444,7 @@ write_expression (tree expr)
34443444

34453445
if (PACK_EXPANSION_P (op))
34463446
{
3447+
sizeof_pack:
34473448
if (abi_check (11))
34483449
{
34493450
/* sZ rather than szDp. */
@@ -3464,6 +3465,19 @@ write_expression (tree expr)
34643465
int length = TREE_VEC_LENGTH (args);
34653466
if (abi_check (10))
34663467
{
3468+
/* Before v19 we wrongly mangled all single pack expansions with
3469+
sZ, but now only for expressions, as types ICEd (95298). */
3470+
if (length == 1)
3471+
{
3472+
tree arg = TREE_VEC_ELT (args, 0);
3473+
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION
3474+
&& !abi_check (19))
3475+
{
3476+
op = arg;
3477+
goto sizeof_pack;
3478+
}
3479+
}
3480+
34673481
/* sP <template-arg>* E # sizeof...(T), size of a captured
34683482
template parameter pack from an alias template */
34693483
write_string ("sP");

gcc/cp/pt.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13572,7 +13572,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
1357213572
/* If the argument pack is a single pack expansion, pull it out. */
1357313573
if (TREE_VEC_LENGTH (args) == 1
1357413574
&& pack_expansion_args_count (args))
13575-
return TREE_VEC_ELT (args, 0);
13575+
{
13576+
tree arg = TREE_VEC_ELT (args, 0);
13577+
if (PACK_EXPANSION_SIZEOF_P (t)
13578+
&& !TEMPLATE_PARM_P (PACK_EXPANSION_PATTERN (arg)))
13579+
/* Except if this isn't a simple sizeof...(T) which gets sZ
13580+
mangling, keep the TREE_VEC to get sP mangling. */;
13581+
else
13582+
return TREE_VEC_ELT (args, 0);
13583+
}
1357613584

1357713585
/* Types need no adjustment, nor does sizeof..., and if we still have
1357813586
some pack expansion args we won't do anything yet. */
@@ -20261,8 +20269,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
2026120269
{
2026220270
if (PACK_EXPANSION_P (expanded))
2026320271
/* OK. */;
20264-
else if (TREE_VEC_LENGTH (expanded) == 1)
20265-
expanded = TREE_VEC_ELT (expanded, 0);
2026620272
else
2026720273
expanded = make_argument_pack (expanded);
2026820274

gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@ struct A {
88
template<typename...T> using M = int[sizeof...(T)];
99
template<typename...A> void g(M<A...> &);
1010
};
11+
12+
template<typename ...T> using N = int[sizeof...(T)];
13+
template<typename ...T> void f(N<T...> &);
14+
// equivalent to template<typename ...T> void f(int(&)[sizeof...(T)])
15+
1116
void g(A a)
1217
{
1318
int arr[3];
1419
// { dg-final { scan-assembler "_ZN1A1fIJLi1ELi2ELi3EEEEvRAsZT__i" } }
1520
a.f<1,2,3>(arr);
1621
// { dg-final { scan-assembler "_ZN1A1gIJiiiEEEvRAsZT__i" } }
1722
a.g<int,int,int>(arr);
23+
// { dg-final { scan-assembler "_Z1fIJiiiEEvRAsZT__i" } }
24+
f<int,int,int>(arr);
1825
}
26+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// PR c++/95298
2+
// { dg-do compile { target c++11 } }
3+
// { dg-additional-options -fabi-compat-version=0 }
4+
5+
template<class...>
6+
struct list{};
7+
8+
template<int n>
9+
struct _func_select
10+
{
11+
using f = void;
12+
};
13+
14+
struct func
15+
{
16+
template<class... seqs>
17+
using f = typename _func_select<sizeof...(seqs)>::f;
18+
};
19+
20+
template<class... T>
21+
func::f<list<T>...> foo(T&&...)
22+
{}
23+
24+
// { dg-final { scan-assembler "_Z3fooIJEEN12_func_selectIXsPDp4listIJT_EEEEE1fEDpOS2_" } }
25+
26+
int main()
27+
{
28+
foo();
29+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// { dg-do compile { target c++11 } }
2+
// { dg-additional-options "-fabi-version=0 -fabi-compat-version=0" }
3+
4+
template<int...T> using N = int[sizeof...(T)];
5+
template<int...A> void f(N<(A+1)...> &);
6+
7+
void g()
8+
{
9+
int arr[3];
10+
11+
// { dg-final { scan-assembler "_Z1fIJLi1ELi2ELi3EEEvRAsPXspplT_Li1EEE_i" } }
12+
f<1,2,3>(arr);
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// { dg-do compile { target c++11 } }
2+
// { dg-additional-options "-fabi-version=18 -fabi-compat-version=18" }
3+
4+
template<int...T> using N = int[sizeof...(T)];
5+
template<int...A> void f(N<(A+1)...> &);
6+
7+
void g()
8+
{
9+
int arr[3];
10+
11+
// { dg-final { scan-assembler "_Z1fIJLi1ELi2ELi3EEEvRAsZplT_Li1E_i" } }
12+
f<1,2,3>(arr);
13+
}

0 commit comments

Comments
 (0)