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)