c++: Templated lambda mangling
(Explicitly) Templated lambdas have a different signature to implicitly templated lambdas -- '[]<template T> (T) {}' is not the same as '[](auto) {}'. This should be reflected in the mangling. The ABI captures this as https://github.com/itanium-cxx-abi/cxx-abi/issues/31, and clang has implemented such additions. It's relatively straight forwards to write out the non-synthetic template parms, and note if we need to issue an ABI warning. gcc/cp/ * mangle.cc (write_closure_template_head): New. (write_closure_type_name): Call it. gcc/testsuite/ * g++.dg/abi/lambda-ctx1-18.C: Adjust. * g++.dg/abi/lambda-ctx1-18vs17.C: Adjust. * g++.dg/abi/lambda-tpl1-17.C: New. * g++.dg/abi/lambda-tpl1-18.C: New. * g++.dg/abi/lambda-tpl1-18vs17.C: New. * g++.dg/abi/lambda-tpl1.h: New.
This commit is contained in:
parent
f95d3d5de7
commit
f7d1d7777b
7 changed files with 192 additions and 4 deletions
|
@ -1727,6 +1727,66 @@ write_unnamed_type_name (const tree type)
|
|||
write_compact_number (discriminator);
|
||||
}
|
||||
|
||||
// A template head, for templated lambdas.
|
||||
// <template-head> ::= Tp* Ty
|
||||
// Tp* Tn <type>
|
||||
// Tp* Tt <template-head> E
|
||||
// New in ABI=18. Returns true iff we emitted anything -- used for ABI
|
||||
// version warning.
|
||||
|
||||
static bool
|
||||
write_closure_template_head (tree tmpl)
|
||||
{
|
||||
bool any = false;
|
||||
|
||||
// We only need one level of template parms
|
||||
tree inner = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
|
||||
|
||||
for (int ix = 0, len = TREE_VEC_LENGTH (inner); ix != len; ix++)
|
||||
{
|
||||
tree parm = TREE_VEC_ELT (inner, ix);
|
||||
if (parm == error_mark_node)
|
||||
continue;
|
||||
parm = TREE_VALUE (parm);
|
||||
|
||||
if (DECL_VIRTUAL_P (parm))
|
||||
// A synthetic parm, we're done.
|
||||
break;
|
||||
|
||||
any = true;
|
||||
if (abi_version_at_least (18))
|
||||
{
|
||||
if (TREE_CODE (parm) == PARM_DECL
|
||||
? TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
|
||||
: TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
|
||||
write_string ("Tp");
|
||||
|
||||
switch (TREE_CODE (parm))
|
||||
{
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
|
||||
case TYPE_DECL:
|
||||
write_string ("Ty");
|
||||
break;
|
||||
|
||||
case PARM_DECL:
|
||||
write_string ("Tn");
|
||||
write_type (TREE_TYPE (parm));
|
||||
break;
|
||||
|
||||
case TEMPLATE_DECL:
|
||||
write_string ("Tt");
|
||||
write_closure_template_head (parm);
|
||||
write_string ("E");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
|
||||
<lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters */
|
||||
|
||||
|
@ -1740,6 +1800,14 @@ write_closure_type_name (const tree type)
|
|||
MANGLE_TRACE_TREE ("closure-type-name", type);
|
||||
|
||||
write_string ("Ul");
|
||||
|
||||
if (auto ti = maybe_template_info (fn))
|
||||
if (write_closure_template_head (TI_TEMPLATE (ti)))
|
||||
// If there were any explicit template parms, we may need to
|
||||
// issue a mangling diagnostic.
|
||||
if (abi_warn_or_compat_version_crosses (18))
|
||||
G.need_abi_warning = true;
|
||||
|
||||
write_method_parms (parms, /*method_p=*/1, fn);
|
||||
write_char ('E');
|
||||
write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
// These correctly include the lambda's extra context as a
|
||||
// substitution candidate, and thus demangle as expected
|
||||
// { dg-final { scan-assembler {_ZNK1C1fMUlT_E_clIMS_iEEDaS1_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK2L2MUlT_T0_E_clIifEEvS0_S1_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK1B2L3MUlT_T0_E_clIjdEEvS1_S2_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK2L2MUlTyTyT_T0_E_clIifEEvS0_S1_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK1B2L3MUlTyTyT_T0_E_clIjdEEvS1_S2_:} } }
|
||||
// { dg-final { scan-assembler {_Z3fooIN1qMUlvE_ENS0_UlvE0_EEiOT_OT0_:} } }
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "lambda-ctx1.h"
|
||||
|
||||
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK1B2L3MUlT_T0_E_clIjdEEvS0_S1_'\) and '-fabi-version=18' \('_ZNK1B2L3MUlT_T0_E_clIjdEEvS1_S2_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK2L2MUlT_T0_E_clIifEEvS_S0_'\) and '-fabi-version=18' \('_ZNK2L2MUlT_T0_E_clIifEEvS0_S1_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK1B2L3MUlT_T0_E_clIjdEEvS0_S1_'\) and '-fabi-version=18' \('_ZNK1B2L3MUlTyTyT_T0_E_clIjdEEvS1_S2_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK2L2MUlT_T0_E_clIifEEvS_S0_'\) and '-fabi-version=18' \('_ZNK2L2MUlTyTyT_T0_E_clIifEEvS0_S1_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK1C1fMUlT_E_clIMS_iEEDaS0_'\) and '-fabi-version=18' \('_ZNK1C1fMUlT_E_clIMS_iEEDaS1_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-ctx1.h:[:0-9]* warning: the mangled name [^\n]* \('_Z3fooIN1qMUlvE_EN1qMUlvE0_EEiOT_OT0_'\) and '-fabi-version=18' \('_Z3fooIN1qMUlvE_ENS0_UlvE0_EEiOT_OT0_'\) [^\n]*\n} }
|
||||
|
|
20
gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
Normal file
20
gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
Normal file
|
@ -0,0 +1,20 @@
|
|||
// { dg-do compile { target c++20 } }
|
||||
// { dg-options -fabi-version=17 }
|
||||
|
||||
#include "lambda-tpl1.h"
|
||||
|
||||
// { dg-final { scan-assembler {_ZNK6l_autoMUlT_E_clIiEEDaS_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK5l_tplMUlT_E_clIiEEDaS_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK10l_tpl_autoMUlT_T0_E_clIiiEEDaS_S0_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK12l_tpl_nt_aryMUlRAT__iE_clILi2EEEDaS0_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK13l_tpl_nt_autoMUlvE_clILi0EEEDav:} } }
|
||||
// { dg-final { scan-assembler {_ZNK9l_tpl_tplMUlR3TPLIT_EE_clI1UEEDaS2_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK13l_tpl_tpl_tplMUlR6TPLTPLIT_EE_clI3TPLEEDaS2_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK5l_varMUlDpT_E_clIJiiiEEEDaS0_:} } }
|
||||
|
||||
// This mangling might not be correct, it is my best guess:
|
||||
// { FIXMEdg-final { scan-assembler {_ZNK6l_var2MUlDpRAT__iE_clIJLi2ELi2EEEEDaS1_:} } }
|
||||
|
||||
// { dg-final { scan-assembler {_ZNK6l_var3MUlRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS1_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK6l_var4MUlR1YIJDpT_EEE_clIJ1US6_EEEDaS3_:} } }
|
||||
// { dg-final { scan-assembler {_ZZ2FnILi1EEvvENKUlT_E_clIiEEDaS0_:} } }
|
25
gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
Normal file
25
gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
Normal file
|
@ -0,0 +1,25 @@
|
|||
// { dg-do compile { target c++20 } }
|
||||
|
||||
#include "lambda-tpl1.h"
|
||||
|
||||
// { dg-final { scan-assembler {_ZNK6l_autoMUlT_E_clIiEEDaS0_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK5l_tplMUlTyT_E_clIiEEDaS0_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK10l_tpl_autoMUlTyT_T0_E_clIiiEEDaS0_S1_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK12l_tpl_nt_aryMUlTniRAT__iE_clILi2EEEDaS1_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK13l_tpl_nt_autoMUlTnDavE_clILi0EEEDav:} } }
|
||||
// { dg-final { scan-assembler {_ZNK9l_tpl_tplMUlTtTyTnjER3TPLIT_EE_clI1UEEDaS3_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK13l_tpl_tpl_tplMUlTtTtTyTnjEER6TPLTPLIT_EE_clI3TPLEEDaS3_:} } }
|
||||
// { dg-final { scan-assembler {_ZNK5l_varMUlTpTyDpT_E_clIJiiiEEEDaS1_:} } }
|
||||
|
||||
// { FIXMEdg-final { scan-assembler {_ZNK6l_var2MUlTpTniDpRAT__iE_clIJLi2ELi2EEEEDaS2_:} } }
|
||||
|
||||
// { dg-final { scan-assembler {_ZNK6l_var3MUlTtTpTniETpTniRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS2_:} } }
|
||||
|
||||
// { dg-final { scan-assembler {_ZNK6l_var4MUlTpTtTyTnjER1YIJDpT_EEE_clIJ1US7_EEEDaS4_:} } }
|
||||
// This is a different mangling to clang, which gets
|
||||
// _ZNK6l_var4MUlTpTtTyTnjER1YIJDpT_EEE_clIJ1US6_EEEDaS3_
|
||||
// However, I think that is incorrect -- it doesn't demangle as
|
||||
// expected (using the llvm demangler).
|
||||
// https://github.com/llvm/llvm-project/issues/58631
|
||||
|
||||
// { dg-final { scan-assembler {_ZZ2FnILi1EEvvENKUlTyT_E_clIiEEDaS0_:} } }
|
16
gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
Normal file
16
gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
Normal file
|
@ -0,0 +1,16 @@
|
|||
// { dg-do compile { target c++20 } }
|
||||
// { dg-options {-fabi-version=18 -Wabi=17} }
|
||||
|
||||
#include "lambda-tpl1.h"
|
||||
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZ2FnILi1EEvvENKUlT_E_clIiEEDaS0_'\) and '-fabi-version=18' \('_ZZ2FnILi1EEvvENKUlTyT_E_clIiEEDaS0_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK6l_var4MUlR1YIJDpT_EEE_clIJ1US6_EEEDaS3_'\) and '-fabi-version=18' \('_ZNK6l_var4MUlTpTtTyTnjER1YIJDpT_EEE_clIJ1US7_EEEDaS4_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK6l_var3MUlRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS1_'\) and '-fabi-version=18' \('_ZNK6l_var3MUlTtTpTniETpTniRT_IJXspT0_EEEE_clI1XJLi1ELi2ELi3EEEEDaS2_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK5l_varMUlDpT_E_clIJiiiEEEDaS0_'\) and '-fabi-version=18' \('_ZNK5l_varMUlTpTyDpT_E_clIJiiiEEEDaS1_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK13l_tpl_tpl_tplMUlR6TPLTPLIT_EE_clI3TPLEEDaS2_'\) and '-fabi-version=18' \('_ZNK13l_tpl_tpl_tplMUlTtTtTyTnjEER6TPLTPLIT_EE_clI3TPLEEDaS3_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK9l_tpl_tplMUlR3TPLIT_EE_clI1UEEDaS2_'\) and '-fabi-version=18' \('_ZNK9l_tpl_tplMUlTtTyTnjER3TPLIT_EE_clI1UEEDaS3_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK13l_tpl_nt_autoMUlvE_clILi0EEEDav'\) and '-fabi-version=18' \('_ZNK13l_tpl_nt_autoMUlTnDavE_clILi0EEEDav'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK12l_tpl_nt_aryMUlRAT__iE_clILi2EEEDaS0_'\) and '-fabi-version=18' \('_ZNK12l_tpl_nt_aryMUlTniRAT__iE_clILi2EEEDaS1_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK10l_tpl_autoMUlT_T0_E_clIiiEEDaS_S0_'\) and '-fabi-version=18' \('_ZNK10l_tpl_autoMUlTyT_T0_E_clIiiEEDaS0_S1_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK5l_tplMUlT_E_clIiEEDaS_'\) and '-fabi-version=18' \('_ZNK5l_tplMUlTyT_E_clIiEEDaS0_'\) [^\n]*\n} }
|
||||
// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK6l_autoMUlT_E_clIiEEDaS_'\) and '-fabi-version=18' \('_ZNK6l_autoMUlT_E_clIiEEDaS0_'\) [^\n]*\n} }
|
59
gcc/testsuite/g++.dg/abi/lambda-tpl1.h
Normal file
59
gcc/testsuite/g++.dg/abi/lambda-tpl1.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
inline auto l_auto = [] (auto) {};
|
||||
|
||||
inline auto l_tpl = [] <typename T> (T) {};
|
||||
|
||||
inline auto l_tpl_auto = [] <typename T> (T, auto) {};
|
||||
|
||||
inline auto l_tpl_nt_ary = [] <int I> (int (&)[I]) {};
|
||||
|
||||
inline auto l_tpl_nt_auto = [] <auto I = 0> () {};
|
||||
|
||||
template<typename T, unsigned I> class U;
|
||||
|
||||
template<template<typename, unsigned> typename> class TPL {};
|
||||
inline auto l_tpl_tpl = [] <template<typename, unsigned> typename T> (TPL<T> &) {};
|
||||
|
||||
template<template<template<typename, unsigned> typename> typename> class TPLTPL {};
|
||||
inline auto l_tpl_tpl_tpl = []<template<template<typename, unsigned> typename> typename T> (TPLTPL<T> &) {};
|
||||
|
||||
inline auto l_var = []<typename... Args> (Args...) {};
|
||||
|
||||
#if FIXME // we fail to parse (&...) correctly
|
||||
inline auto l_var2 = []<int... I> (int (&...)[I]) {};
|
||||
#endif
|
||||
|
||||
template<int...I> class X {};
|
||||
inline auto l_var3 = []<template<int...> typename T, int...I> (T<I...> &a) {};
|
||||
|
||||
template<template<typename, unsigned> typename...T> class Y{};
|
||||
inline auto l_var4 = []<template<typename, unsigned> typename... T> (Y<T...> &a) {};
|
||||
|
||||
template<int I> inline void Fn ()
|
||||
{
|
||||
auto l = []<typename T> (T) {};
|
||||
l (1);
|
||||
}
|
||||
|
||||
void f ()
|
||||
{
|
||||
l_auto (1);
|
||||
l_tpl (1);
|
||||
l_tpl_auto (1, 1);
|
||||
int ary[2];
|
||||
l_tpl_nt_ary (ary);
|
||||
l_tpl_nt_auto ();
|
||||
TPL<U> v;
|
||||
l_tpl_tpl (v);
|
||||
TPLTPL<TPL> u;
|
||||
l_tpl_tpl_tpl (u);
|
||||
l_var (1, 2, 3);
|
||||
#if FIXME
|
||||
l_var2 (ary, ary);
|
||||
#endif
|
||||
X<1,2,3> x;
|
||||
l_var3 (x);
|
||||
Y<U,U> y;
|
||||
l_var4 (y);
|
||||
|
||||
Fn<1> ();
|
||||
}
|
Loading…
Add table
Reference in a new issue