Почему g cc выдает мне, возможно, неинициализированное предупреждение для deque :: insert с отфильтрованным диапазоном - PullRequest
3 голосов
/ 31 января 2020

Почему g cc выдает мне возможно неинициализированное предупреждение для deque::insert с отфильтрованным диапазоном при компиляции с -O2 и -DNDEBUG

#include <deque>
#include <vector>
#include <boost/range/adaptor/filtered.hpp>

auto foo(){
    std::deque<int> d{3,4};
    std::vector<int> v{0,2};
    auto b = 1;
    using boost::adaptors::filtered;
    auto r = v | filtered([&b](auto i){return i>b;});

    d.insert(std::end(d),r.begin(),r.end());
    return d;
}

Компилятор g cc 9.2, флаг -std=c++2a -O2 -Wall -Werror -DNDEBUG

Это предупреждение:

<source>: In member function 'void std::deque<_Tp, <source>: In member function 'void std::deque<_Tp, _Alloc>::_M_insert_aux(std::deque<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::deque<_Tp, _Alloc>::size_type) [with _ForwardIterator = boost::iterators::filter_iterator<boost::range_detail::default_constructible_unary_fn_wrapper<foo()::<lambda(auto:1)>, bool>, __gnu_cxx::__normal_iterator<int*, std::vector<int> > >; _Tp = int; _Alloc = std::allocator<int>]':

<source>:10:48: error: '*((void*)& __mid +16)' may be used uninitialized in this function [-Werror=maybe-uninitialized]

   10 |     auto r = v | filtered([&b](auto i){return i>b;});

      |                                               ~^~

In file included from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/deque:69,

                 from <source>:1:

/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/bits/deque.tcc:793:24: note: '*((void*)& __mid +16)' was declared here

  793 |       _ForwardIterator __mid = __first;

      |                        ^~~~~

<source>:10:48: error: '*((void*)& __mid +16)' may be used uninitialized in this function [-Werror=maybe-uninitialized]

   10 |     auto r = v | filtered([&b](auto i){return i>b;});

      |   

Если b зафиксировано значением, то предупреждение исчезнет.

https://godbolt.org/z/8Tbfgf

1 Ответ

3 голосов
/ 31 января 2020

Вы захватываете константу времени компиляции по ссылке.

filtered([](auto i){return i>b;})

, то есть допустимо , поскольку const auto b = 1 - это константа времени компиляции, которую вы можете использовать без ссылки.

Компилятор запутывается из-за неиспользованной ссылки на постоянную времени компиляции, захваченную по имени. Это, вероятно, оптимизирует указанный захват, потому что ссылка, которая никогда не используется, может быть пропущена. Это оставляет вам неинициализированный перехват b, который другой код путает со значением времени компиляции с тем же именем, и вы получаете предупреждение.

Это, очевидно, ошибка компилятора. Возможно, вместо этого он должен предупредить вас, например:

variable captured but unused

или что-то подобное.

...