Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer to data member of incomplete type

Is the following code well-defined in C++? (*)

I'm having a hard time figuring out where to even look in the standard, and searching the web hasn't turned up anything concrete.

struct S;
struct T {
    constexpr T() = default;
    bool S::* a = nullptr;
    int b       = 42;
};
const T t{};
// Test. Compiled using: cl /W4 /WX /FAs filename.cpp
#include <stdlib.h>
int main() {
    if (t.b != 42) abort();
}

The reason I'm asking is because it works (or seems to) with newer versions of GCC and Clang (x86/x86_64), but fails(**) with Visual Studio 2015 Update 2 and Update 3 RC.

Before reporting a bug I'd like to be sure I'm not relying on undefined behavior or just not searching for the right terms.

I've also tried using /vmg and /vmb as mentioned in this post.

(*): I mostly care about C++14 and later, but I don't see any reason the answer shouldn't apply to C++11.
(**): If the code is well-defined it looks like a codegen bug where it isn't allocation room for the pointer. Changing struct S to struct S{} seems to make the code "work".

like image 866
user786653 Avatar asked Jun 23 '16 19:06

user786653


People also ask

What does pointer to incomplete class type mean?

This error usually means that you are trying to follow a pointer to a class, but the compiler did not find the definition of that class (it found a declaration for the class, so it is not considered an unknown symbol, but it did not find a definition, so it is considered an incomplete class).

What is dereferencing pointer to incomplete type?

The “dereferencing pointer to incomplete type” error commonly occurs in C when one tries to dereference a type (usually a struct) that is: not declared at all. declared, but not defined.

Which is incomplete data type?

The void type is an incomplete type that cannot be completed. To complete an incomplete type, specify the missing information. The following examples show how to create and complete the incomplete types. To create an incomplete structure type, declare a structure type without specifying its members.


1 Answers

Your code is well-defined:

N4594 3.2/5

[...]A class type T must be complete if:

  • (5.1) an object of type T is defined (3.1), or
  • (5.2) a non-static class data member of type T is declared (9.2), or
  • (5.3) T is used as the object type or array element type in a new-expression (5.3.4), or
  • (5.4) an lvalue-to-rvalue conversion is applied to a glvalue referring to an object of type T (4.1), or
  • (5.5) an expression is converted (either implicitly or explicitly) to type T (Clause 4, 5.2.3, 5.2.7, 5.2.9, 5.4), or
  • (5.6) an expression that is not a null pointer constant, and has type other than cv void*, is converted to the type pointer to T or reference to T using a standard conversion (Clause 4), a dynamic_cast (5.2.7) or a static_cast (5.2.9), or
  • (5.7) a class member access operator is applied to an expression of type T (5.2.5), or
  • (5.8) the typeid operator (5.2.8) or the sizeof operator (5.3.3) is applied to an operand of type T, or
  • (5.9) a function with a return type or argument type of type T is defined (3.1) or called (5.2.2), or
  • (5.10) a class with a base class of type T is defined (Clause 10), or
  • (5.11) an lvalue of type T is assigned to (5.18), or
  • (5.12) the type T is the subject of an alignof expression (5.3.6), or
  • (5.13) an exception-declaration has type T, reference to T, or pointer to T (15.3).

None of them says that T needs to be complete in order to declare pointer-to-member of T.

like image 147
PcAF Avatar answered Oct 07 '22 22:10

PcAF