c++: Fix up mangling of __builtin_{bswap,bitreverse}g calls [PR127668]
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
Commit Message
Hi!
The following testcases ICE during mangling, the dependent
__builtin_{bswap,bitreverse}g calls (where those identifiers
we treat as keywords and don't even have such builtins,
given that those are the first type-generic builtins with the
return type dependent on the argument type(s)) are emitted
as internal fn calls (IFN_BSWAP or IFN_BITREVERSE), and
during mangling we just ICE on any calls to internal functions.
The following patch mangles those 2 calls like we mangle e.g.
template <typename T>
auto foo (T t) -> decltype (__builtin_popcountg (t)) { return t; }
template int foo <unsigned> (unsigned);
- _Z3fooIjEDTcl19__builtin_popcountgfp_EET_ . In
that case it is a type-generic builtin with a fixed return
type and we trigger the
/* Mangle a dependent name as the name, not whatever happens to
be the first function in the overload set. */
if (OVL_P (fn)
&& type_dependent_expression_p_push (expr))
fn = OVL_NAME (fn);
case in the CALL_EXPR write_expression handling, so fn is
then an identifier.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2026-10-01 Jakub Jelinek <jakub@redhat.com>
PR c++/127668
* mangle.cc (write_expression): Handle mangling of
calls to IFN_BSWAP and IFN_BITREVERSE.
* g++.dg/ext/builtin-bswapg-1.C: New test.
* g++.dg/ext/builtin-bitreverseg-1.C: New test.
Jakub
Comments
On 10/1/26 8:10 AM, Jakub Jelinek wrote:
> Hi!
>
> The following testcases ICE during mangling, the dependent
> __builtin_{bswap,bitreverse}g calls (where those identifiers
> we treat as keywords and don't even have such builtins,
> given that those are the first type-generic builtins with the
> return type dependent on the argument type(s)) are emitted
> as internal fn calls (IFN_BSWAP or IFN_BITREVERSE), and
> during mangling we just ICE on any calls to internal functions.
>
> The following patch mangles those 2 calls like we mangle e.g.
> template <typename T>
> auto foo (T t) -> decltype (__builtin_popcountg (t)) { return t; }
>
> template int foo <unsigned> (unsigned);
> - _Z3fooIjEDTcl19__builtin_popcountgfp_EET_ . In
> that case it is a type-generic builtin with a fixed return
> type and we trigger the
> /* Mangle a dependent name as the name, not whatever happens to
> be the first function in the overload set. */
> if (OVL_P (fn)
> && type_dependent_expression_p_push (expr))
> fn = OVL_NAME (fn);
> case in the CALL_EXPR write_expression handling, so fn is
> then an identifier.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Hmm, I'm a bit uncomfortable exposing builtins in mangling; relatedly,
we reject mangling TRAIT_TYPE. But OK.
Jason
@@ -4094,20 +4094,35 @@ write_expression (tree expr)
switch (code)
{
case CALL_EXPR:
- {
- tree fn = CALL_EXPR_FN (expr);
+ if (tree fn = CALL_EXPR_FN (expr))
+ {
+ if (TREE_CODE (fn) == ADDR_EXPR)
+ fn = TREE_OPERAND (fn, 0);
- if (TREE_CODE (fn) == ADDR_EXPR)
- fn = TREE_OPERAND (fn, 0);
+ /* Mangle a dependent name as the name, not whatever happens to
+ be the first function in the overload set. */
+ if (OVL_P (fn)
+ && type_dependent_expression_p_push (expr))
+ fn = OVL_NAME (fn);
- /* Mangle a dependent name as the name, not whatever happens to
- be the first function in the overload set. */
- if (OVL_P (fn)
- && type_dependent_expression_p_push (expr))
- fn = OVL_NAME (fn);
-
- write_expression (fn);
- }
+ write_expression (fn);
+ }
+ else
+ switch (CALL_EXPR_IFN (expr))
+ {
+ /* Calls to __builtin_bswapg/__builtin_bitreverseg are parsed
+ as IFN_BSWAP/IFN_BITREVERSE calls because we don't have
+ those builtins but instead keywords. Pretend they are
+ builtin function template. */
+ case IFN_BSWAP:
+ write_source_name (get_identifier ("__builtin_bswapg"));
+ break;
+ case IFN_BITREVERSE:
+ write_source_name (get_identifier ("__builtin_bitreverseg"));
+ break;
+ default:
+ gcc_unreachable ();
+ }
for (i = 0; i < call_expr_nargs (expr); ++i)
write_expression (CALL_EXPR_ARG (expr, i));
@@ -0,0 +1,8 @@
+// PR c++/127668
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_Z3fooIjEDTcl16__builtin_bswapgfp_EET_" } }
+
+template <typename T>
+auto foo (T t) -> decltype (__builtin_bswapg (t)) { return t; }
+
+template unsigned foo <unsigned> (unsigned);
@@ -0,0 +1,8 @@
+// PR c++/127668
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_Z3fooIjEDTcl21__builtin_bitreversegfp_EET_" } }
+
+template <typename T>
+auto foo (T t) -> decltype (__builtin_bitreverseg (t)) { return t; }
+
+template unsigned foo <unsigned> (unsigned);