[Bug c++/96064] New: Defaulted constexpr spaceship operator triggers internal compiler error after including utility
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96064 Bug ID: 96064 Summary: Defaulted constexpr spaceship operator triggers internal compiler error after including utility Product: gcc Version: 10.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- The following code crashes gcc-10.1 #include class WrappedValue { public: constexpr explicit WrappedValue(double val): m_value{val}{} constexpr bool operator<=>(WrappedValue const&) const = default constexpr double value() const {return m_value; } private: double m_value; }; Any of the following actions prevents the crash: * Remove `#include ` * Make `operator<=>` non-constexpr * Make `operator<=>` non-defaulted Error log: : In member function 'constexpr bool WrappedValue::operator<=>(const WrappedValue&) const': :8:24: internal compiler error: Segmentation fault 8 | constexpr bool operator<=>(WrappedValue const&) const = default; |^~~~ Please submit a full bug report, with preprocessed source if appropriate. See <https://gcc.gnu.org/bugs/> for instructions. Compiler returned: 1 On compiler explorer: https://gcc.godbolt.org/z/mo7HkG
[Bug c++/96419] New: Constant propoagation works on global variable, but not in a function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96419 Bug ID: 96419 Summary: Constant propoagation works on global variable, but not in a function Product: gcc Version: 10.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- I tried to implement a map-like data structure, with compile-time keys: #include #include #include namespace fixed_flatmap_detail { template constexpr auto sort(std::array const& x, Compare const& compare) { auto tmp = x; std::ranges::sort(tmp, compare); return tmp; } } template> class FixedFlatmap { public: using key_type = std::remove_reference_t; using value_type = Value; static constexpr auto size() { return std::size(Keys::items); } static constexpr auto const keys() { return s_keys; } constexpr auto const values() const { return m_vals; } constexpr auto values() { return m_vals; } constexpr auto find(key_type const& key) const { auto i = std::ranges::lower_bound(s_keys, key, Compare{}); if(i != std::end(s_keys) && !Compare{}(key, *i)) [[likely]] { return std::begin(m_vals) + (i - std::begin(s_keys)); } return static_cast(nullptr); } constexpr auto find(key_type const& key) { return const_cast(std::as_const(*this).find(key)); } private: static constexpr auto s_keys = fixed_flatmap_detail::sort(Keys::items, Compare{}); std::array m_vals; }; struct KeyStruct { static constexpr std::array items{"Foo", "Bar", "Kaka"}; }; FixedFlatmap my_vals{}; auto this_value_is_computed_at_compile_time = my_vals.find("Kaka"); int* test_lookup(FixedFlatmap& vals) { return vals.find("Foo"); // == static_cast(static_cast(&vals) + sizeof(int)) } Interestingly gcc succeeds to compute `find` on a global variable, but fails as soon as the same structure is allocated in a function. I am not an expert in compilers, but realize that it could be trickier to compute it on a non-global object (base address is not known at compile-time). However, the binary search does not even use *this. Thus, `std::lower_bound` and outcome validation should be possible to compute. Godbolt: https://gcc.godbolt.org/z/c7E3P9
[Bug libstdc++/96851] New: operator< on std::array does not work in constexpr, for sizeof(T) == 1, and N > 1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96851 Bug ID: 96851 Summary: operator< on std::array does not work in constexpr, for sizeof(T) == 1, and N > 1 Product: gcc Version: 10.1.0 URL: https://gcc.godbolt.org/z/vjvYE5 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- It appears that `operator<` on `std::array` does not work in constexpr context, for `sizeof(T) == 1`, and `N > 1`. I tried different `T`and `N` combinations, and it appears that these work. MWE: #include #include #include template constexpr bool test(std::array const& a, std::array const& b) { return a < b; } using Type = int8_t; constexpr auto Count = 2; // Below does not compile constexpr auto value = test(std::array{}, std::array{}); The problem exists in gcc 10.1 and trunk. /opt/compiler-explorer/gcc-trunk-20200830/include/c++/11.0.0/array:262:32: error: '__builtin_memcmp(((std::array::const_pointer)(&.std::array::_M_elems)), ((std::array::const_pointer)(&.std::array::_M_elems)), 2)' is not a constant expression 262 | return __builtin_memcmp(__a.data(), __b.data(), _Nm) <=> 0; Godbolt url: https://gcc.godbolt.org/z/vjvYE5
[Bug libstdc++/96851] operator< on std::array does not work in constexpr, for sizeof(T) == 1, and N > 1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96851 --- Comment #1 from milasudril at gmail dot com --- Apparently, std::lexicographical_compare works https://gcc.godbolt.org/z/E1ETh1
[Bug libstdc++/96851] operator< on std::array does not work in constexpr, for sizeof(T) == 1, and N > 1
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96851 --- Comment #4 from milasudril at gmail dot com --- Actually, I did not even try without the c++20 flag: template< class T, std::size_t N > bool operator<( const std::array& lhs, const std::array& rhs ); (3) (until C++20) ... template< class T, std::size_t N > constexpr /* see below */ operator<=>( const std::array& lhs, const std::array& rhs ); (7) (since C++20) https://en.cppreference.com/w/cpp/container/array/operator_cmp Thus I wouldn't expect it to work in C++17 or below. If it did, it could be considered a bug.
[Bug c++/92745] New: Initializing array with vec4 results in compile error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92745 Bug ID: 92745 Summary: Initializing array with vec4 results in compile error Product: gcc Version: 8.3.0 URL: https://gcc.godbolt.org/z/sxvR3G Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- Target: Any In GCC 8.3 and later the following code fails to compile: #include template using vec4_t __attribute__((vector_size(4*sizeof(T = float; auto transpose(std::array, 4> col) { std::array, 4> ret{vec4_t{col[0][0], col[1][0], col[2][0], col[3][0]}, vec4_t{col[0][1], col[1][1], col[2][1], col[3][1]}, vec4_t{col[0][2], col[1][2], col[2][2], col[3][2]}, vec4_t{col[0][3], col[1][3], col[2][3], col[3][3]}}; return ret; } x86-64 gcc 8.3 -O3 1 x86-64 gcc 8.3 - 1240ms : In function 'auto transpose(std::array<__vector(4) float, 4>)': :11:102: error: too many initializers for 'std::array<__vector(4) float, 4>' vec4_t{col[0][3], col[1][3], col[2][3], col[3][3]}}; ^ Compiler returned: 1 It compiles with GCC 8.2 and earlier, and also the latest version of clang.
[Bug c++/91217] New: Returning std::array from lambda results in an extra copy step on return
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91217 Bug ID: 91217 Summary: Returning std::array from lambda results in an extra copy step on return Product: gcc Version: 8.1.0 URL: https://godbolt.org/z/3zAhtv Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- Target: ARM, x86-64 It appears that for GCC versions later than or equal to version 8.1, an extra copy procedure when an std::array is being returned from a lambda. The problem does not exist for an immediately created function object. Not affected: GCC 7.4 Affected: GCC 8.1 up to and including trunk.
[Bug c++/91217] Returning std::array from lambda results in an extra copy step on return
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91217 --- Comment #1 from milasudril at gmail dot com --- For reference, here is a MWE: #include #include template struct CreateArray { using value_type = typename TargetArray::value_type; auto operator()() { TargetArray ret; for(int k = 0 ; k < std::size(src) - 1; ++k) {ret[k] = value_type{src[k]};} return ret; } SourceArray const& src; }; class TestA { public: using value_type = char; static constexpr size_t npos = 255; template TestA(SrcType const (&src)[N] , std::enable_if_t<(N>=1 && N x = 0) : m_size{N - 1} , m_data{CreateArray{src}()} {} private: size_t m_size; std::array m_data; }; class TestB { public: using value_type = char; static constexpr size_t npos = 255; template TestB(SrcType const (&src)[N] , std::enable_if_t<(N>=1 && N x = 0) : m_size{N - 1} , m_data { [&src]() { std::array ret; for(int k = 0 ; k < std::size(src) - 1; ++k) {ret[k] = value_type{src[k]};} return ret; }() } {} private: size_t m_size; std::array m_data; }; TestB hello_2() {return TestB{"Hello, World! This is a very long string that the compiler probably will not inline"};} TestA hello_1() {return TestA{"Hello, World! This is a very long string that the compiler probably will not inline"};}
[Bug c++/71566] New: Attribute [[aligned(16)]] on function is ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71566 Bug ID: 71566 Summary: Attribute [[aligned(16)]] on function is ignored Product: gcc Version: 6.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- g++ does not accept [[aligned(16)]] as attribute on a function. However, the non-standard notation works. Example: #include __attribute__((aligned(16))) int test(int x) { printf("Address of test: %p\n",test); return 0; } [[aligned(16)]] int test2(int x) { printf("Address of test2: %p\n",test2); return 0; } int main() { test(0); test2(0); return 0; } g++ --version && g++ -std=c++14 -Wall main.cpp && ./a.out g++ (GCC) 6.1.0 Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. main.cpp:9:32: warning: 'aligned' attribute directive ignored [-Wattributes] [[aligned(16)]] int test2(int x) ^ Address of test: 0x4005a0 Address of test2: 0x4005c6
[Bug c++/59861] Inconsistent error output format
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59861 milasudril at gmail dot com changed: What|Removed |Added Severity|minor |enhancement
[Bug c++/59861] New: Inconsistent error output format
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59861 Bug ID: 59861 Summary: Inconsistent error output format Product: gcc Version: 4.7.2 Status: UNCONFIRMED Severity: minor Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com There are inconsistencies in how gcc reports function names on compile error Note the use and no use of quotation marks: /wand-src/wand.cpp: In member function ‘void Wand::Wand::targetsInstall(const Herbs::Array&, Wand::Invoker&) const’: ./wand-src/wand.cpp:923:22: error: no matching function for call to ‘Wand::TargetAdaptorImpl::TargetAdaptorImpl()’ ... ./wand-src/target_adaptor_impl.h:19:4: note: Wand::TargetAdaptorImpl::TargetAdaptorImpl(const Wand::Target&, const Herbs::Path&) It would be better if a function name always is surrounded by quotation marks since it makes messages easier to parse.
[Bug c++/97601] New: ICE when using type determined by std::tuple_element_t<...>, on tuple generated from type id stored in std::array
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97601 Bug ID: 97601 Summary: ICE when using type determined by std::tuple_element_t<...>, on tuple generated from type id stored in std::array Product: gcc Version: 10.2.1 URL: https://gcc.godbolt.org/z/n13PKr Status: UNCONFIRMED Keywords: ice-on-valid-code Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- Host: any Target: any Code that triggers the bug(s). It uses enum values stored in an std::array, to generate an std::tuple. Using std::tuple_element_t on the generated tuple causes ICE. Compiler options: -Wall -std=c++20 -O3 #include #include #include #include namespace Enum { template using Empty = std::type_identity; template constexpr auto add(T base, std::underlying_type_t offset = 1) { return static_cast(std::underlying_type_t(base) + offset); } namespace detail { template class EnumItemTraits, class T = std::make_integer_sequence> struct make_tuple_from_array; template class EnumItemTraits, size_t index> struct int_to_type_array: public EnumItemTraits { }; template class EnumItemTraits, size_t... indices> struct make_tuple_from_array> { using type = std::tuple::type...>; }; } template class EnumItemTraits> using TupleFromTypeArray = typename detail::make_tuple_from_array::type; } enum class PortType : size_t { RgbaPixels, GrayscaleRealPixels, GrayscaleComplexPixels, }; constexpr PortType begin(Enum::Empty) { return PortType::RgbaPixels; } constexpr PortType end(Enum::Empty) { return Enum::add(PortType::GrayscaleComplexPixels); } using vec4_t __attribute__((vector_size(16))) = float; using RgbaValue= vec4_t; using RealValue= double; using ComplexValue = std::complex; template struct PortTypeToType; template<> struct PortTypeToType { using type = std::unique_ptr; }; template<> struct PortTypeToType { using type = std::unique_ptr; }; template<> struct PortTypeToType { using type = std::unique_ptr; }; template struct InputPortType { using type = std::conditional_t<(sizeof(T) <= 16), T, std::reference_wrapper>; }; template struct InputPortType> { using type = T const*; }; template struct InputPortType> { using type = std::reference_wrapper; }; namespace detail { template struct GenInputPortType { using type = typename InputPortType::type>::type; }; } namespace detail { template constexpr decltype(auto) create_impl(F&& f, std::index_sequence) { return Object{f(std::integral_constant{})...}; } } template constexpr decltype(auto) createTuple(F&& f) { return detail::create_impl(std::forward(f), std::make_index_sequence>{}); } template void doStuffWithTArg(T); template void doStuffWithT(); template class InArgTuple { using storage_type = Enum::TupleFromTypeArray; public: constexpr explicit InArgTuple() : m_data{createTuple([](Tag) { using T = typename detail::GenInputPortType::type; // Trunk gets stuck here // internal compiler error: in cxx_eval_constant_expression, at cp/constexpr.c:6188 using OtherT = std::tuple_element_t; static_assert(std::is_same_v); T foo{}; // This triggers ICE: in finish_expr_stmt, at cp/semantics.c:681 // doStuffWithT(); doStuffWithT(); // Not ICE OtherT bar{}; // This also triggers ICE: in tsubst_copy, at cp/pt.c:16485 //doStuffWithTArg(bar); doStuffWithTArg(foo); // Not ICE // // Also in tsubst_copy, at cp/pt.c:16485 // // return bar; // return foo; })} { } static constexpr auto size() { return types.size(); } template constexpr auto get() const { static_assert(index < types.size()); return std::get(m_data); } private: storage_type m_data; }; void test() { constexpr std::array types{PortType::RgbaPixels}; InArgTuple test{}; }
[Bug c++/107123] New: Size deduction for vector size in template fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107123 Bug ID: 107123 Summary: Size deduction for vector size in template fails Product: gcc Version: 12.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- Host: x86-64_linux_gnu Target: x86-64_linux_gnu I tried to write a generic inner product implementation, accepting vectorized arguments: ```c++ #include #include template concept arithmetic = std::is_arithmetic_v; template using native_vector [[gnu::vector_size(sizeof(T)*N)]] = T; template auto inner_product(native_vector a, native_vector b) { auto const prod = a * b; T ret{}; for(size_t k = 0; k != N; ++k) { ret += prod[k]; } return ret; } auto test(native_vector a, native_vector b) { return inner_product(a, b); } ``` Apparently, it is not possible to deduce N here: ``` : In function 'auto test(native_vector, native_vector)': :23:25: error: no matching function for call to 'inner_product(native_vector&, native_vector&)' 23 | return inner_product(a, b); |~^~ :11:6: note: candidate: 'template auto inner_product(native_vector, native_vector)' 11 | auto inner_product(native_vector a, native_vector b) | ^ :11:6: note: template argument deduction/substitution failed: :23:25: note: couldn't deduce template parameter 'N' 23 | return inner_product(a, b); ``` I would appreciate if size deduction worked like for std::array: ```c++ #include template auto inner_product(std::array a, std::array b) { T ret{}; for(size_t k = 0; k != N; ++k) { ret += a[k]*b[k]; } return ret; } auto test(std::array a, std::array b) { return inner_product(a, b); // N deduced to 4 } ``` The problem is present on gcc 10-trunk.
[Bug c++/107123] Size deduction for vector size in template fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107123 --- Comment #2 from milasudril at gmail dot com --- > It would be nice to standardized the vector attribute. Good features to have: constexpr std::size (and also std::ssize) template inline constexpr std::is_simd_type_v = ...; namespace std { template struct simd_element_type{ using type = ...; }; template simd_element_type_t = typename simd_element_type::type; } I belive the working paper is p2638r0 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2638r0.pdf
[Bug c++/107862] New: Returning an std::vector from a lambda fails to be constexpr, while a custom class with allocated storage works
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107862 Bug ID: 107862 Summary: Returning an std::vector from a lambda fails to be constexpr, while a custom class with allocated storage works Product: gcc Version: 12.2.0 URL: https://godbolt.org/z/dve3Yx8ax Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- Host: x86-64_linux_gnu Target: x86-64_linux_gnu Minimal working example: #include #include #include struct Test { using value_type = int; constexpr Test(){ data = new value_type(0); } constexpr ~Test(){ delete data; } constexpr unsigned size() const { return 1; } constexpr auto begin() const { return data; } constexpr auto end() const { return data + 1; } private: value_type* data; }; consteval auto dynamic_data_to_array(auto generator) { auto test = generator(); using VT = typename decltype(test)::value_type; std::array data; std::copy(test.begin(), test.end(), data.begin()); return data; } constexpr Test get_test() { return Test(); } int main() { // Does not work constexpr auto data0 = dynamic_data_to_array([] { return std::vector{0};}); constexpr auto data1 = dynamic_data_to_array([] { return Test{};}); return data1[0]; } It works to return a Test object here, but not an std::vector. Compiler output: :22:29: in 'constexpr' expansion of 'test.std::vector::size()' :22:33: error: the value of 'test' is not usable in a constant expression 22 | std::array data; | ^~~~ :19:10: note: 'test' was not declared 'constexpr' 19 | auto test = generator(); | ^~~~ :22:29: note: in template argument for type 'long unsigned int' 22 | std::array data; |~^~ :22:29: in 'constexpr' expansion of 'test.std::vector::size()' :22:33: error: the value of 'test' is not usable in a constant expression 22 | std::array data; | ^~~~ :19:10: note: 'test' was not declared 'constexpr' 19 | auto test = generator(); | ^~~~ :22:29: note: in template argument for type 'long unsigned int' 22 | std::array data; I am not sure if this is by the standard, or if this is related to some missing implementation details in the standard library. Note: clang doesn't like it either.
[Bug c++/109287] New: Optimizing sal shr pairs when inlining function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109287 Bug ID: 109287 Summary: Optimizing sal shr pairs when inlining function Product: gcc Version: 12.2.0 URL: https://gcc.godbolt.org/z/aPTsjc1sM Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- Target: x86-64_linux_gnu I was trying to construct a span type to be used for working with a tile-based image ``` #include #include #include template class span_2d_tiled { public: using IndexType = size_t; static constexpr size_t tile_size() { return TileSize; } constexpr explicit span_2d_tiled(): span_2d_tiled{0u, 0u, nullptr} {} constexpr explicit span_2d_tiled(IndexType w, IndexType h, T* ptr): m_tilecount_x{1 + (w - 1)/TileSize}, m_tilecount_y{1 + (h - 1)/TileSize}, m_ptr{ptr} {} constexpr auto tilecount_x() const { return m_tilecount_x; } constexpr auto tilecount_y() const { return m_tilecount_y; } constexpr T& operator()(IndexType x, IndexType y) const { auto const x_tile = x/TileSize; auto const y_tile = y/TileSize; auto const x_offset = x%TileSize; auto const y_offset = y%TileSize; auto const tile_start = y_tile*m_tilecount_x + x_tile; return *(m_ptr + tile_start + y_offset*TileSize + x_offset); } private: IndexType m_tilecount_x; IndexType m_tilecount_y; T* m_ptr; }; template void visit_tiles(size_t x_count, size_t y_count, Func&& f) { for(size_t k = 0; k != y_count; ++k) { for(size_t l = 0; l != x_count; ++l) { for(size_t y = 0; y != TileSize; ++y) { for(size_t x = 0; x != TileSize; ++x) { f(l*TileSize + x, k*TileSize + y); } } } } } void do_stuff(float); void call_do_stuff(span_2d_tiled foo) { visit_tiles(foo.tilecount_x(), foo.tilecount_y(), [foo](size_t x, size_t y){ do_stuff(foo(x, y)); }); } ``` Here, the user of this API wants to access individual pixels. Thus, the coordinates are transformed before calling f. To do so, we multiply by TileSize and adds the appropriate offset. In the callback, the pixel value is looked up. But now we must find out what tile it is, and the offset within that tile, which means that the inverse transformation must be applied. As can be seen in the Godbolt link, GCC does not fully understand what is going on here. However, latest clang appears to do a much better job with the same settings. It also unrolls the inner loop, much better than if I used ``` #pragma GCC unroll 16 ```
[Bug c++/113754] New: GCC complains when using a type that depends on lambda
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113754 Bug ID: 113754 Summary: GCC complains when using a type that depends on lambda Product: gcc Version: 13.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: milasudril at gmail dot com Target Milestone: --- I tried to use template using unique_ptr_deleter = std::unique_ptr; As described by https://andreasfertig.blog/2022/08/cpp-insights-lambdas-in-unevaluated-contexts/ It works well as long as I do not try define it in a header file. If gcc detects a from a header file that uses unique_ptr_deleter, I get the warning lib/array_classes/./memory_block.hpp:12:8: error: 'memory_block' has a field 'unique_ptr_deleter terraformer::memory_block::m_pointer' whose type has internal linkage [-Werror=subobject-linkage] Clang do generate any warnings. Stand-alone snippet to reproduce the issue: #include #include # 7 "lib/array_classes/./memory_block.hpp" template using unique_ptr_deleter = std::unique_ptr; class memory_block { public: private: unique_ptr_deleter m_pointer; }; # 4 "lib/array_classes/memory_block.test.cpp"