Repository navigation
Generated C drops vector_size from a std::remove_cv<V>::type typedef when V is a vector type deduced by a conversion function #441
Description
Issue Summary
When std::remove_cv<V>::type is used inside a conversion function template
and V is a GNU vector type deduced from the conversion's target type, the
resulting typedef is emitted in the generated C as the element type
(long long) without __attribute__((vector_size(16))). gcc then rejects the
generated C with "incompatible types". g++ accepts the source.
Boost.UUID's simd_vector is this pattern, so every translation unit that
formats UUIDs with SSE2 (<boost/uuid/uuid_io.hpp>) fails to compile. In the
Boost test suite this fails 13 Boost.Unordered tests (the mmap,
interprocess-concurrency and visualization tests).
Reproducing Source Code
namespace std {
template <class T> struct remove_cv { using type = __remove_cv(T); };
}
typedef long long m128 __attribute__((__vector_size__(16)));
struct S {
alignas(16) unsigned char bytes[16];
template <typename V> operator V() const {
using vector_type = typename std::remove_cv<V>::type;
return *reinterpret_cast<const vector_type *>(bytes);
}
};
m128 f(const S &s) { return s; }Command-line Options
EDG_USE_SYSTEM_HEADERS=1 eccp --c++17 -c remove_cv_vector.cpp -o remove_cv_vector
Type of Issue
[Back End] There is a problem with the generated C code.
Additional Details
Expected: compiles (g++ 15.3.1 compiles it).
Actual (linux-gcc-release and linux-gcc-debug):
eccp: diagnostics generated from compilation of remove_cv_vector.int.c:
remove_cv_vector.cpp: In function '_ZNK1ScvT_IDv2_xEEv':
remove_cv_vector.cpp:11:8: error: incompatible types when returning type '_ZZNK1ScvT_IDv2_xEEvE11vector_type' {aka 'long long int'} but '__vector(2) long long int' was expected
eccp: end of diagnostics from compilation of remove_cv_vector.int.c
eccp: gcc compilation of remove_cv_vector.int.c returned an exit status of 1
Generated C:
typedef long long _ZZNK1ScvT_IDv2_xEEvE11vector_type;What it depends on (each variant checked separately):
- The template has to be
std::remove_cvitself. Renaming it (std::rc) or
moving it out ofstd(foo::remove_cv) gives a correct typedef of the
member typedef, which is emitted with__attribute((vector_size(16))). Vhas to be deduced through the conversion function, which gives an
unnamed vector type (mangledDv2_x).std::remove_cv<m128>::typewith the
named typedef works, and so doesusing vector_type = V;.- libstdc++'s own
<type_traits>reproduces it too:
typename std::remove_cv<typename std::remove_reference<V>::type>::type
(libstdc++ 15 defines both with__remove_cv/__remove_reference).
std::remove_cv<T>::type is one of the front end's type-member intrinsics
(NS_templ_type_member_intrinsics, src/sys_predef.h:135; resolved by
subst_std_remove_cv, src/sys_predef.c:153, added in 296c4f4). It
returns the template argument type directly, without instantiating the class.
For a deduced vector type the typedef produced this way loses its vector
attribute somewhere before the C back end emits it. I didn't track down
exactly where. std::remove_reference, std::remove_const,
std::remove_volatile and std::remove_cvref use the same mechanism, so they
are probably affected too.
Boost: boost/uuid/detail/simd_vector.hpp. operator Vector() (line 28)
calls get<Vector>() (lines 36-41), which does
using vector_type = typename std::remove_cv<typename std::remove_reference<Vector>::type>::type;
and boost/uuid/detail/to_chars_x86.hpp:333 converts simd_vector constants
to __m128i. A 4-line TU that includes <boost/uuid/uuid_io.hpp> and calls
to_string(uuid) fails the same way, with or without --no_inlining.
Environment: edgcpp/dev-env Docker image (Fedora 43, GCC 15.3.1) on
x86-64, boost branch at c36e03a67c. EDG_USE_SYSTEM_HEADERS=1 makes eccp
use GCC 15's headers and pass --gnu_version=150301
(bases/docker/dev-env/gcc/edg_eccp_config).
Reproducing (Standard) Configuration(s)
linux-gcc-debug
Reproducing (Non-standard) Configuration
No response
I acknowledge that:
- I have checked open issues and existing discussions before filing this report.
- The reproducing source code that I have provided does not depend on headers that I have not included with my submission.
- I have reduced the reproducing source code to the best of my ability.
- I have selected at least one standard configuration or uploaded a non-standard configuration dump.
- I understand code shared via this form is NOT confidential.
- I have permission to share the reproducing source code and grant permission for the project to use the source code (or derivatives of the source code) to create tests.
- I agree that any tests created using the reproducing source code (or deriatives of it) will be licensed under project license unless I included a
LICENSE.txtfile in my.zipor.tar.gzupload. If I included aLICENSE.txtfile, any tests created using the reproducing source code will be governed by the terms of the license I provided instead.
Activity