Search code examples
c++language-lawyerc++20compiler-bug

Illegal use of undefined type


Considering the code example shown below, is decltype(h{}.t()); a legal expression? Which specific rule in the C++20 standard either allows or forbids this?

struct d;
struct h { static auto t() -> d; };

using a = decltype(h::t());             // all ok
using b = decltype(decltype(h{})::t()); // all ok
using c = decltype(h{}.t());            // clang ok, gcc ok, msvc nope

Live example


The error message produced by MSVC:

<source>(6): error C2027: use of undefined type 'd'
<source>(1): note: see declaration of 'd'

Having stumbled upon yet another bug with MSVC, I've actually discovered a workaround for MSVC's deviating behavior. By simply providing a user-defined defaulted default constructor for type h, MSVC no longer complains about d being undefined.

struct d;
struct h {
    static auto t() -> d;
    h() = default;
};
using c = decltype(h{}.t()); // all ok

However, the problem still seems to persist when skipping use of h's constructor, like with the use of std::declval for example (as in: decltype(std::declval<h>().t());). Also, be aware that by providing a user-defined default constructor, even when defaulted, this will cause h to no longer be considered an aggregate type.


Solution

  • It is explicitly permitted for the type of a prvalue expression operand to decltype to be incomplete. Temporary materialization is exceptionally not applied in this circumstance, so that a destructor of d isn't necessary either (which would require d to be complete to lookup the destructor). So d doesn't need to be complete. For reference to the standard see [dcl.type.decltype]/2.

    The function t may also be undefined, because use in a decltype operand is not use in a potentially-evaluated expression and therefore not an odr-use.

    Constructing a h object with h{} also doesn't demand either t to be defined or d to be complete.

    The standard even includes a very similar example (see link above).

    So MSVC is wrong here.