Issue 63445
Summary member call on member 'data_' of union with no active member is not allowed in a constant _expression_
Labels new issue
Assignees
Reporter z0nt
    Clang refuses to compile the following code:
```c++
#include <stdlib.h>

template <class T, int N>
class Array {
 public:
  template <typename... Args>
 constexpr Array(Args... args) noexcept {
    static_assert(sizeof...(args) <= N);
    ArrayBuilder(args...);
  }

  constexpr void push_back(const T& value) noexcept {
    if (size_ < N) {
 data_[size_++] = value;
    } else {
      abort();
    }
 }

  constexpr int size() const { return size_; }
  constexpr const T& operator[](int pos) const { return data_[pos]; }

 private:
 constexpr void ArrayBuilder() noexcept { }

  template <typename _T, typename... Args>
  constexpr void ArrayBuilder(_T value, Args... args) noexcept {
    data_[size_++] = value;
    ArrayBuilder(args...);
 }

  int size_ = 0;
  union {
    T data_[N];
 };
};

class Int {
 public:
  Int() = delete;
  constexpr explicit Int(int i) noexcept : i_(i) {}
  constexpr operator int() const { return i_; }

 private:
  //int i_;  // works
  int i_ = 0;  // doesn't compile
};


static constexpr Array<Int, 1> GetInts() {
  Array<Int, 1> ret;
  ret.push_back(Int(0x5a));
  return ret;
}
//static constexpr Array<Int, 1> GetInts() { return {Int(0x5a)}; }
//static constexpr Array<int, 1> GetInts() { return {int(0x5a)}; }

int main() {
  constexpr auto test = GetInts();
 static_assert(test.size() == 1);
  static_assert(test[0] == 0x5a);
}
```

with the following diagnostic:
```
main.cc:59:18: error: constexpr variable 'test' must be initialized by a constant _expression_
  constexpr auto test = GetInts();
                 ^      ~~~~~~~~~
main.cc:14:22: note: member call on member 'data_' of union with no active member is not allowed in a constant _expression_
      data_[size_++] = value;
 ^
main.cc:52:7: note: in call to '&ret->push_back(Int(90))'
 ret.push_back(Int(0x5a));
      ^
main.cc:59:25: note: in call to 'GetInts()'
  constexpr auto test = GetInts();
 ^
```
Compiles just fine with GCC & MSVC -- https://godbolt.org/z/5qdh7cq6a

Eventually I've made code compiling with Clang.  The only change I've made is removed default initialization of member of`class Int` (which should not make any difference at all, because there is explicit constructor and default one is deleted).  There is also different version of `GetInts()` which uses template parameter pack, but it fails to compile as well (though GCC & MSVC compile it as well with no problem).
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to