(constexpr) function template instantiation and incomplete types

With the recent libstdc++ change https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=2fbdcf5e58c83a671b4d00f72b7ef91c462b6fc8 “libstdc++: Implement constexpr std::unique_ptr for C++23 (P2273R3)”, I started to experience lots of compilation failures in the wild with Clang in -std=c++2b mode.

What this boils down to is

$ cat test.cc
template<typename T> struct W {
  constexpr W() { static_assert(sizeof (T), ""); }
};
struct S;
W<S> v;
struct S {};
$ clang++ -fsyntax-only test.cc
test.cc:2:33: error: invalid application of 'sizeof' to an incomplete type 'S'
  constexpr W() { static_assert(sizeof (T), ""); }
                                ^~~~~~~~~~
test.cc:5:6: note: in instantiation of member function 'W<S>::W' requested here
W<S> v;
     ^
test.cc:4:8: note: forward declaration of 'S'
struct S;
       ^
1 error generated.

while without constexpr,

$ cat test.cc
template<typename T> struct W {
  W() { static_assert(sizeof (T), ""); }
};
struct S;
W<S> v;
struct S {};
$ clang++ -fsyntax-only test.cc

succeeds.

Is the failure related to the “needed for constant evaluation” rule mentioned at Default parameter of unique_ptr instantiates causing failure with incomplete type:?

But then, why does the non-constexpr case work, isn’t the point of instantiation for the definition of W<S>::W the same in both cases?

1 Like