Skip to content

Commit

Permalink
c++: sizeof... mangling with alias template [PR95298]
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jicama committed Dec 22, 2023
1 parent 2fa122c commit d26f589
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 3 deletions.
14 changes: 14 additions & 0 deletions gcc/cp/mangle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3444,6 +3444,7 @@ write_expression (tree expr)

if (PACK_EXPANSION_P (op))
{
sizeof_pack:
if (abi_check (11))
{
/* sZ rather than szDp. */
Expand All @@ -3464,6 +3465,19 @@ write_expression (tree expr)
int length = TREE_VEC_LENGTH (args);
if (abi_check (10))
{
/* Before v19 we wrongly mangled all single pack expansions with
sZ, but now only for expressions, as types ICEd (95298). */
if (length == 1)
{
tree arg = TREE_VEC_ELT (args, 0);
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION
&& !abi_check (19))
{
op = arg;
goto sizeof_pack;
}
}

/* sP <template-arg>* E # sizeof...(T), size of a captured
template parameter pack from an alias template */
write_string ("sP");
Expand Down
12 changes: 9 additions & 3 deletions gcc/cp/pt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13572,7 +13572,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
/* If the argument pack is a single pack expansion, pull it out. */
if (TREE_VEC_LENGTH (args) == 1
&& pack_expansion_args_count (args))
return TREE_VEC_ELT (args, 0);
{
tree arg = TREE_VEC_ELT (args, 0);
if (PACK_EXPANSION_SIZEOF_P (t)
&& !TEMPLATE_PARM_P (PACK_EXPANSION_PATTERN (arg)))
/* Except if this isn't a simple sizeof...(T) which gets sZ
mangling, keep the TREE_VEC to get sP mangling. */;
else
return TREE_VEC_ELT (args, 0);
}

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

Expand Down
8 changes: 8 additions & 0 deletions gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@ struct A {
template<typename...T> using M = int[sizeof...(T)];
template<typename...A> void g(M<A...> &);
};

template<typename ...T> using N = int[sizeof...(T)];
template<typename ...T> void f(N<T...> &);
// equivalent to template<typename ...T> void f(int(&)[sizeof...(T)])

void g(A a)
{
int arr[3];
// { dg-final { scan-assembler "_ZN1A1fIJLi1ELi2ELi3EEEEvRAsZT__i" } }
a.f<1,2,3>(arr);
// { dg-final { scan-assembler "_ZN1A1gIJiiiEEEvRAsZT__i" } }
a.g<int,int,int>(arr);
// { dg-final { scan-assembler "_Z1fIJiiiEEvRAsZT__i" } }
f<int,int,int>(arr);
}

29 changes: 29 additions & 0 deletions gcc/testsuite/g++.dg/cpp0x/variadic-mangle4.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// PR c++/95298
// { dg-do compile { target c++11 } }
// { dg-additional-options -fabi-compat-version=0 }

template<class...>
struct list{};

template<int n>
struct _func_select
{
using f = void;
};

struct func
{
template<class... seqs>
using f = typename _func_select<sizeof...(seqs)>::f;
};

template<class... T>
func::f<list<T>...> foo(T&&...)
{}

// { dg-final { scan-assembler "_Z3fooIJEEN12_func_selectIXsPDp4listIJT_EEEEE1fEDpOS2_" } }

int main()
{
foo();
}
13 changes: 13 additions & 0 deletions gcc/testsuite/g++.dg/cpp0x/variadic-mangle5.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// { dg-do compile { target c++11 } }
// { dg-additional-options "-fabi-version=0 -fabi-compat-version=0" }

template<int...T> using N = int[sizeof...(T)];
template<int...A> void f(N<(A+1)...> &);

void g()
{
int arr[3];

// { dg-final { scan-assembler "_Z1fIJLi1ELi2ELi3EEEvRAsPXspplT_Li1EEE_i" } }
f<1,2,3>(arr);
}
13 changes: 13 additions & 0 deletions gcc/testsuite/g++.dg/cpp0x/variadic-mangle5a.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// { dg-do compile { target c++11 } }
// { dg-additional-options "-fabi-version=18 -fabi-compat-version=18" }

template<int...T> using N = int[sizeof...(T)];
template<int...A> void f(N<(A+1)...> &);

void g()
{
int arr[3];

// { dg-final { scan-assembler "_Z1fIJLi1ELi2ELi3EEEvRAsZplT_Li1E_i" } }
f<1,2,3>(arr);
}

0 comments on commit d26f589

Please sign in to comment.