[Bug c++/96064] New: Defaulted constexpr spaceship operator triggers internal compiler error after including utility

2020-07-05 Thread milasudril at gmail dot com
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

2020-08-02 Thread milasudril at gmail dot com
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

2020-08-30 Thread milasudril at gmail dot com
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

2020-08-30 Thread milasudril at gmail dot com
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

2020-09-02 Thread milasudril at gmail dot com
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

2019-12-01 Thread milasudril at gmail dot com
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

2019-07-20 Thread milasudril at gmail dot com
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

2019-07-20 Thread milasudril at gmail dot com
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

2016-06-17 Thread milasudril at gmail dot com
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

2016-06-17 Thread milasudril at gmail dot com
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

2014-01-17 Thread milasudril at gmail dot com
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

2020-10-27 Thread milasudril at gmail dot com via Gcc-bugs
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

2022-10-02 Thread milasudril at gmail dot com via Gcc-bugs
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

2022-10-03 Thread milasudril at gmail dot com via Gcc-bugs
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

2022-11-24 Thread milasudril at gmail dot com via Gcc-bugs
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

2023-03-26 Thread milasudril at gmail dot com via Gcc-bugs
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

2024-02-04 Thread milasudril at gmail dot com via Gcc-bugs
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"