llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.44k stars 11.76k forks source link

defaulted destructor makes defaulted copy constructor non-constexpr #37491

Open mclow opened 6 years ago

mclow commented 6 years ago
Bugzilla Link 38143
Version trunk
OS All
CC @DougGregor,@marehr,@zygoloid

Extended Description

Consider this code:

class span {
public:
    using pointer                = const int *;

    constexpr span() : __data{nullptr} {}

    constexpr span           (const span&) noexcept = default;
    constexpr span& operator=(const span&) noexcept = default;
    ~span() noexcept = default;

    constexpr pointer data()    const noexcept { return __data; }

private:
    pointer __data;
};

When compiled with a recent clang [clang version 7.0.0 (trunk 336548)], (-std=c++2a) it gives an error:

junk.cpp:8:5: error: defaulted definition of copy assignment operator is not
      constexpr
    constexpr span& operator=(const span&) noexcept = default;
    ^

However, if I switch the order of the two lines to:
    ~span() noexcept = default;
    constexpr span& operator=(const span&) noexcept = default;

then it compiles w/o error.

However, I believe that it should compile w/o error in both cases.

llvmbot commented 2 years ago

Still persists in Clang 13 with constexpr constructors.

This issue doesn't appear in GCC 11.2 and Clang 13 with -std=c++17, but it only appears when the flag -std=c++20 is given.

Below is the sample code:

struct Foo {
  constexpr Foo(const Foo&) noexcept = default;
  constexpr Foo(Foo&&) noexcept = default;

  constexpr auto operator=(const Foo&) noexcept -> Foo& = default;
  constexpr auto operator=(Foo&&) noexcept -> Foo& = default;
};

with the following errors:

<source>:5:3: error: defaulted definition of copy assignment operator is not constexpr
  constexpr auto operator=(const Foo&) noexcept -> Foo& = default;
  ^
<source>:6:3: error: defaulted definition of move assignment operator is not constexpr
  constexpr auto operator=(Foo&&) noexcept -> Foo& = default;
  ^
2 errors generated.
Compiler returned: 1

Live demo: https://godbolt.org/z/6Mz6K3PMf

As shown above, the warning states that both assignment operators are not constexpr even though they are already declared constexpr, which is contradictory.

marehr commented 5 years ago

duplicate of llvm/llvm-project#26063 ?