https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115207

            Bug ID: 115207
           Summary: [constexpr] constexpr assignment rejected as non const
                    on self-assignment test
           Product: gcc
           Version: 14.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nov.ondrej at gmail dot com
  Target Milestone: ---

Hello

Following code fails to compile
//------------------------------------------
#include <memory>
#include <initializer_list>

class value {
public:
    int v;
    constexpr value():v(0) {}
    constexpr value(int v):v(v) {}

    constexpr value &operator=(const value &other) {
        if (this != &other) {
            std::destroy_at(this);
            std::construct_at(this, other.v);
        }
        return *this;
    }
};

template<unsigned int N>
class array {
public:

    constexpr array(const std::initializer_list<value> &items) {
        std::copy(items.begin(), items.end(), std::begin(_items));
    }

protected:
    value _items[N] = {};
};

template<unsigned int N>
array(const value (&)[N]) -> array<N>;

constexpr array test ({1,2,3,4});
//------------------------------------------

<source>:37:32:   in 'constexpr' expansion of 'array<4>(const
std::initializer_list<value>{((const value*)(& const value [4]{value{1},
value{2}, value{3}, value{4}})), 4})'
<source>:25:18:   in 'constexpr' expansion of 'std::copy<const value*,
value*>((& items)->std::initializer_list<value>::begin(), (&
items)->std::initializer_list<value>::end(), std::begin<value,
4>(((array<4>*)this)->array<4>::_items))'
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/stl_algobase.h:651:7:
  in 'constexpr' expansion of 'std::__copy_move_a<false, const value*,
value*>(std::__miter_base<const value*>(__first), std::__miter_base<const
value*>(__last), __result)'
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/stl_algobase.h:556:31:
  in 'constexpr' expansion of 'std::__copy_move_a1<false, const value*,
value*>(std::__niter_base<const value*>(__first), std::__niter_base<const
value*>(__last), std::__niter_base<value*>(__result))'
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/stl_algobase.h:548:42:
  in 'constexpr' expansion of 'std::__copy_move_a2<false, const value*,
value*>(__first, __last, __result)'
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/stl_algobase.h:518:12:
  in 'constexpr' expansion of 'std::__copy_move<false, false,
std::random_access_iterator_tag>::__copy_m<const value*, value*>(__first,
__last, __result)'
/opt/compiler-explorer/gcc-14.1.0/include/c++/14.1.0/bits/stl_algobase.h:403:18:
  in 'constexpr' expansion of '__result->value::operator=((* __first))'
<source>:11:18: error: '(((const value*)(&<anonymous>)) != ((const value*)(&
test.array<4>::_items)))' is not a constant expression
   11 |         if (this != &other) {
      |             ~~~~~^~~~~~~~~
Compiler returned: 1

//------------------------------------------


Godbolt link: https://godbolt.org/z/zzKs58qzv

The above code is compiled correctly in both clang and msvc.

Thank you

Reply via email to