https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127215

            Bug ID: 127215
           Summary: [modules] [reflection] GCC: inconsistent mangling of
                    `__gnu_cxx::operator<=>` (`__normal_iterator`,
                    `__synth3way` `requires` clause) across a module
                    boundary when the iterator value type is
                    `std::meta::info`
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jasio.lpn at gmail dot com
  Target Milestone: ---

=== Reproducer ===

--- repro_di.cppm ---
module;
#include <vector>
#include <algorithm>
#include <meta>
export module repro_di;

export consteval auto di_build() -> std::meta::info
{
    std::vector<std::meta::info> v{^^int, ^^char, ^^bool, ^^long};

    std::ranges::sort(v, [](auto a, auto b) {
        return a != b;
    });

    return v.front();
}

--- main.cpp ---
#include <vector>
#include <algorithm>
#include <meta>

import repro_di;

consteval auto member_ish() -> std::size_t
{
    std::vector<std::meta::info> v{^^int, ^^char, ^^bool, ^^double};

    std::ranges::sort(v, [](auto a, auto b) {
        return a != b;
    });

    return v.size();
}

int main()
{
    static_assert(member_ish() == 4);

    return 0;
}

=== Commands ===
g++ -std=gnu++26 -fmodules -freflection -c repro_di.cppm -o repro_di.o
g++ -std=gnu++26 -fmodules -freflection -c main.cpp -o main.o

=== Summary ===
With C++ modules and reflection, the same specialization

__gnu_cxx::operator<=> (const __normal_iterator<std::meta::info*,
std::vector<std::meta::info>>&,  __normal_iterator<std::meta::info*,
::vector<std::meta::info>>&)

is mangled two different ways: once while compiling the module interface unit
that first instantiates it (the name is streamed into the BMI), and once in a
TU that imports that module and instantiates the specialization again. The
second mangling differs from the first, so compilation is aborted:

In file included from /opt/gcc-trunk/include/c++/17.0.0/bits/stl_algobase.h:66,
                 from /opt/gcc-trunk/include/c++/17.0.0/vector:64,
                 from repro_di.cppm:2,
of module repro_di, imported at main.cpp:5:
/opt/gcc-trunk/include/c++/17.0.0/bits/stl_iterator.h:1204:9: error: mangling
of ‘constexpr std::__detail::__synth3way_t<_Iterator, _Iter>
__gnu_cxx::operator<=>(const __normal_iterator<_Iterator, _Container>&, const
__normal_iterator<_Iter, _Container>&) requires
requires{std::__detail::__synth3way(__gnu_cxx::operator<=>::__lhs->__gnu_cxx::__normal_iterator<_Iterator,
_Container>::base()(), __gnu_cxx::operator<=>::__rhs->base());} [with _Iter =
std::meta::info*; _Iterator = std::meta::info*; _Container =
std::vector<std::meta::info>]’ as
‘_ZN9__gnu_cxx17__normal_iteratorIPDmSt6vectorIDmSaIDmEEEFssIS1_EEDTclL_ZNSt8__detail11__synth3wayEEclL_ZSt7declvalIRS1_EDTcl9__declvalIT_ELi0EEEvEEcl7declvalIRSA_EEEERKS5_RKNS0_ISA_S4_EEQrqXclL_ZNS7_11__synth3wayEEcldtfL0p_L_ZNKS0_ISA_T0_E4baseEvEEcldtfL0p0_4baseEEE’
conflicts with a previous mangle
 1204 |         operator<=>(const __normal_iterator& __lhs,
      |         ^~~~~~~~
In file included from /opt/gcc-trunk/include/c++/17.0.0/bits/stl_algobase.h:66,
                 from /opt/gcc-trunk/include/c++/17.0.0/vector:64,
                 from main.cpp:1:
/opt/gcc-trunk/include/c++/17.0.0/bits/stl_iterator.h:1204:9: note: previous
mangling ‘constexpr std::__detail::__synth3way_t<_Iterator, _Iter>
__gnu_cxx::operator<=>(const __normal_iterator<_Iterator, _Container>&, const
__normal_iterator<_Iter, _Container>&) requires
requires{std::__detail::__synth3way(__gnu_cxx::operator<=>::__lhs->__gnu_cxx::__normal_iterator<_Iterator,
_Container>::base()(), __gnu_cxx::operator<=>::__rhs->base());} [with _Iter =
std::meta::info*; _Iterator = std::meta::info*; _Container =
std::vector<std::meta::info>]’
 1204 |         operator<=>(const __normal_iterator& __lhs,
      |         ^~~~~~~~
/opt/gcc-trunk/include/c++/17.0.0/bits/stl_iterator.h:1204:9: note: a later
‘-fabi-version=’ (or =0) avoids this error with a change in mangling
 1204 |         operator<=>(const __normal_iterator& __lhs,
      |         ^~~~~~~~

=== Observations ===
ABI sweep (-fabi-version=): 17, 18, 21, 0 -> error; 19, 20 -> OK. 21 is the
current default, so the project fails out of the box.

Delete "import repro_di;" from main.cpp (so the specialization is mangled only
once, in main.cpp itself) compiles. A single TU that instantiates the
specialization twice, with no module involved, also compiles. The module
boundary - a mangled name coming back from a BMI and being recomputed — is
required to trigger it.

Replacing "std::meta::info" with an ordinary struct (keeping -freflection,
-fmodules, everything else) compiles. The builtin "std::meta::info" type
(mangled "Dm") is necessary.

=== GCC Version ===
g++ -v                                                       
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/gcc-trunk/libexec/gcc/x86_64-pc-linux-gnu/17.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../source/configure --prefix=/opt/gcc-trunk
--enable-languages=c,c++ --disable-bootstrap --disable-multilib
--disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 17.0.0 20260829 (experimental) (GCC)

Reply via email to