aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2022-10-24 17:39:55 -0400
committerNathan Sidwell <nathan@acm.org>2022-10-27 11:56:11 -0400
commitf7d1d7777bb86ad049f88214109fb561a741aa2c (patch)
tree82ece2eeb0a792f358dd7a0a57be1d4e85c90a57 /gcc/cp
parentf95d3d5de72a1c43e8d529bad3ef59afc3214705 (diff)
downloadgcc-f7d1d7777bb86ad049f88214109fb561a741aa2c.zip
gcc-f7d1d7777bb86ad049f88214109fb561a741aa2c.tar.gz
gcc-f7d1d7777bb86ad049f88214109fb561a741aa2c.tar.bz2
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.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/mangle.cc68
1 files changed, 68 insertions, 0 deletions
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 1215463..e396218 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -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));