boostorg / boostorg/ublas

Broken interaction between std::vector and ublas::c_vector

Open
#195 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
122
Forks
151
PR merge metrics
No merged PRs in 30d

Description

Full interactive example: https://gcc.godbolt.org/z/xe4xh7Wcn

Under certain conditions, when copying a 1-dimensional `c_vector`, for example when resizing or filling a `std::vector`, GCC emits a warning to do with `__builtin_memcpy`; specifically `[-Werror=array-bounds=]`.

This appears to only be a problem under the following circumstances:

- GCC >= 13
- Optimizations enabled that include inlining
- The c_vector is 1-dimensional

Full code to reproduce:

```cpp
#include

#include
#include

using boost::numeric::ublas::c_vector;

template
int do_something()
{
c_vector x;
for(unsigned i = 0; i < DIM; ++i) {
x[i] = static_cast(std::rand());
}

std::vector> vec_of_cvecs;
vec_of_cvecs.resize(3, x);

return vec_of_cvecs.front()[0];
}

int main() {

return do_something<1>(); // produces __builtin_memcpy warning
// return do_something<2>(); // works fine
// return do_something<2>(); // works fine
}
```

The warning:

```
In file included from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/algorithm:60,
from /opt/compiler-explorer/libs/boost_1_83_0/boost/numeric/ublas/storage.hpp:16,
from /opt/compiler-explorer/libs/boost_1_83_0/boost/numeric/ublas/vector.hpp:21,
from :1:
In static member function 'static _Up* std::__copy_move<_IsMove, true, std::random_access_iterator_tag>::__copy_m(_Tp*, _Tp*, _Up*) [with _Tp = const double; _Up = double; bool _IsMove = false]',
inlined from '_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const double*; _OI = double*]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:506:30,
inlined from '_OI std::__copy_move_a1(_II, _II, _OI) [with bool _IsMove = false; _II = const double*; _OI = double*]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:533:42,
inlined from '_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const double*; _OI = double*]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:540:31,
inlined from '_OI std::copy(_II, _II, _OI) [with _II = const double*; _OI = double*]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:633:7,
inlined from 'boost::numeric::ublas::c_vector& boost::numeric::ublas::c_vector::operator=(const boost::numeric::ublas::c_vector&) [with T = double; long unsigned int N = 1]' at /opt/compiler-explorer/libs/boost_1_83_0/boost/numeric/ublas/vector.hpp:2556:21,
inlined from 'typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), void>::__type std::__fill_a1(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = boost::numeric::ublas::c_vector*; _Tp = boost::numeric::ublas::c_vector]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:919:11,
inlined from 'void std::__fill_a(_FIte, _FIte, const _Tp&) [with _FIte = boost::numeric::ublas::c_vector*; _Tp = boost::numeric::ublas::c_vector]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:977:21,
inlined from 'void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = boost::numeric::ublas::c_vector*; _Tp = boost::numeric::ublas::c_vector]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:1007:20,
inlined from 'void std::vector<_Tp, _Alloc>::_M_fill_insert(iterator, size_type, const value_type&) [with _Tp = boost::numeric::ublas::c_vector; _Alloc = std::allocator >]' at /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/vector.tcc:556:14:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:437:30: error: 'void* __builtin_memcpy(void*, const void*, long unsigned int)' forming offset 24 is out of the bounds [0, 24] of object '__tmp' with type 'std::vector, std::allocator > >::_Temporary_value' [-Werror=array-bounds=]
437 | __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
| ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/vector:72,
from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/functional:64,
from /opt/compiler-explorer/libs/boost_1_83_0/boost/numeric/ublas/functional.hpp:16,
from /opt/compiler-explorer/libs/boost_1_83_0/boost/numeric/ublas/expression_types.hpp:16,
from /opt/compiler-explorer/libs/boost_1_83_0/boost/numeric/ublas/vector_expression.hpp:16,
from /opt/compiler-explorer/libs/boost_1_83_0/boost/numeric/ublas/vector.hpp:22:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_fill_insert(iterator, size_type, const value_type&) [with _Tp = boost::numeric::ublas::c_vector; _Alloc = std::allocator >]':
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/vector.tcc:540:32: note: '__tmp' declared here
540 | _Temporary_value __tmp(this, __x);
| ^~~~~
```

Is this likely a problem with ublas? With GCC? Something it's safe for me to ignore? Thank you.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with boost/numeric/ublas/vector.hpp, especially the c_vector assignment near line 2556, and reproduce the warning with GCC 13 or newer using the provided DIM=1 example and optimizations enabled. Compare it with DIM=2 and determine whether the diagnostic originates in uBLAS or GCC; done should establish whether the warning is safe to ignore or requires a project change.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.