Search code examples
visual-c++c++17g++language-lawyerclang++

Calling member function of an incomplete type compiles in gcc and does not compile in clang and msvc


Here is an example:

struct TestClass {
  void testFunction() const {}
  static TestClass* ptr_;
  constexpr static auto funcPtr = +[](){ ptr_->testFunction(); };
};

TestClass* TestClass::ptr_ = new TestClass();

int main() {
  TestClass::funcPtr();
  delete TestClass::ptr_;
  return 0;
}

This compiles with gcc and does not compile with clang and msvc. Which compiler is right? Is it a bug of gcc?

Here is clang error message:

<source>:4:46: error: member access into incomplete type 'TestClass'
    4 |   constexpr static auto funcPtr = +[](){ ptr_->testFunction(); };
      |                                              ^
<source>:1:8: note: definition of 'TestClass' is not complete until the closing '}'
    1 | struct TestClass {
      |        ^
1 error generated.
Compiler returned: 1

msvc error message is the following:

example.cpp
<source>(4): error C2027: use of undefined type 'TestClass'
<source>(1): note: see declaration of 'TestClass'
<source>(4): error C2131: expression did not evaluate to a constant
<source>(4): note: failure was caused by call of undefined function or one not declared 'constexpr'
<source>(4): note: see usage of 'TestClass::<lambda_bdad2d00eade3d9eccb85c581305196c>::operator void (__cdecl *)(void)'
Compiler returned: 2

Solution

  • This is CWG 1836 and the program is well-formed as per the current wording as explained below.

    First note that ->(and .) is the member access operator and so we move onto expr.post#expr.ref:

    Otherwise, the object expression shall be of class type. The class type shall be complete unless the class member access appears in the definition of that class.

    And since ptr_->testFinction() is within the definition of the class, there is no need for the class-type to be complete here.


    Here is the confirmed clang bug:

    Clang rejects valid program involving member access operator with incomplete type CWG 1836