使用可选<string>是否揭示了 gcc 中的错误?

问题描述 投票:0回答:1

我已将代码简化为以下示例,该示例在我的 g++ (x64 12.3) 上以及显然 14.1 上的 -O3 C++20 编译失败使用 godbolt 时

再次根据 godbolt 的说法,clang 可以在没有任何警告的情况下工作。 该警告是否有效,还是 GCC 中的错误?

这是我的代码。 对于长度表示歉意;我试图尽量减少,但警告是不可预测的,也不容易触发。


#include <cassert>
#include <cstdlib>
#include <optional>
#include <string>
#include <utility>

using namespace std;

class HS {
   public:
    constexpr HS() = default;

    constexpr explicit HS(string_view view) : _view(view) {}

    constexpr HS(HS const& other) { *this = other; }

    constexpr HS& operator=(HS const& other) {
        _stringOpt = other._stringOpt;
        _view = _stringOpt ? string_view{*_stringOpt} : other._view;
        return *this;
    }

    constexpr HS& operator=(HS&& other) noexcept {
        if (this != &other) {
            _stringOpt =
                std::exchange(/*inout*/ other._stringOpt, std::nullopt);
            _view = _stringOpt ? string_view{*_stringOpt} : other._view;
            other._view = k_empty;
        }
        return *this;
    }

   private:
    static constexpr char const* k_empty = "";

    optional<string> _stringOpt;
    string_view _view = k_empty;
};

inline HS operator""_hs(char const* string, size_t length) noexcept {
    return HS(string_view{string, length});
}

HS bar(HS const& hs) { return rand() < 10000 ? "sdok"_hs : hs; }

int func() {
    HS foo;
    try {
        foo = "1"_hs;
        foo = bar(foo);        
        foo = "2"_hs;  // <--- warning is about this
    } catch (...) {
        return 1;
    }
    return 0;
}

// No warning if body of func() is placed inside main()
int main() { return func(); }

我收到此警告(视为错误):

In file included from /opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/string:54,
                 from <source>:5:
In member function 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size_type std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::size() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]',
    inlined from 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator __sv_type() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/basic_string.h:950:16,
    inlined from 'constexpr HS& HS::operator=(HS&&)' at <source>:28:57,
    inlined from 'constexpr HS& HS::operator=(HS&&)' at <source>:24:19,
    inlined from 'int func()' at <source>:52:15:
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/basic_string.h:1077:16: error: '*(const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)((char*)&foo + offsetof(HS, HS::_stringOpt.std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<unnamed>.std::_Optional_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, false, false>::<unnamed>)).std::__cxx11::basic_string<char>::_M_string_length' may be used uninitialized [-Werror=maybe-uninitialized]
 1077 |       { return _M_string_length; }
      |                ^~~~~~~~~~~~~~~~
<source>: In function 'int func()':
<source>:48:8: note: 'foo' declared here
   48 |     HS foo;
      |        ^~~
In member function 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::pointer std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_M_data() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]',
    inlined from 'constexpr const _CharT* std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::data() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/basic_string.h:2654:23,
    inlined from 'constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator __sv_type() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]' at /opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/basic_string.h:950:16,
    inlined from 'constexpr HS& HS::operator=(HS&&)' at <source>:28:57,
    inlined from 'constexpr HS& HS::operator=(HS&&)' at <source>:24:19,
    inlined from 'int func()' at <source>:52:15:
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/basic_string.h:228:28: error: '*(const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)((char*)&foo + offsetof(HS, HS::_stringOpt.std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::<unnamed>.std::_Optional_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, false, false>::<unnamed>)).std::__cxx11::basic_string<char>::_M_dataplus.std::__cxx11::basic_string<char>::_Alloc_hider::_M_p' may be used uninitialized [-Werror=maybe-uninitialized]
  228 |       { return _M_dataplus._M_p; }
      |                            ^~~~
<source>: In function 'int func()':
<source>:48:8: note: 'foo' declared here
   48 |     HS foo;
      |        ^~~
cc1plus: all warnings being treated as errors
Compiler returned: 1
c++ gcc g++ std c++20
1个回答
0
投票

再次根据 godbolt 的说法,clang 在没有任何警告的情况下工作。是个 警告有效,还是 GCC 中的错误?

是的,这是已报告的 GCC Bug 109561

© www.soinside.com 2019 - 2024. All rights reserved.