clang icon indicating copy to clipboard operation
clang copied to clipboard

get_pointer_v fails in c++1z mode

Open hamzasood opened this issue 7 years ago • 2 comments

The following code compiles fine using -std=c++14

#include <reflexpr>

struct TestClass {
    int member;
};

int main() {
    auto ptr = std::meta::get_pointer_v<reflexpr(TestClass::member)>;
    return 0;
}

However when using -std=c++1z, the compilation fails

In file included from ReflTest.cpp:1:
include\reflexpr:524:2: error: non-type template argument is not a constant expression
        __metaobject_get_pointer(__unwrap_id_v<T>)
        ^~~~~~~~~~~~~~~~~~~~~~~~
include\reflexpr:528:38: note: in instantiation of template class 'std::meta::get_pointer<std::__metaobject<8376711039260828486> >'
      requested here
constexpr const auto get_pointer_v = get_pointer<T>::value;
                                     ^
ReflTest.cpp:8:27: note: in instantiation of variable template specialization 'std::meta::get_pointer_v' requested here
    auto ptr = std::meta::get_pointer_v<reflexpr(TestClass::member)>;
                          ^
include\reflexpr:524:2: note: non-literal type 'int TestClass::*' cannot be used in a constant expression
        __metaobject_get_pointer(__unwrap_id_v<T>)
        ^
1 error generated.

hamzasood avatar Mar 01 '17 10:03 hamzasood

Although I haven't tested this on another platform, I think it's Windows specific.

The member pointer type is being flagged as non-literal because it sees it as incomplete. This part of Type::isIncompleteType shows that a member pointer can only be incomplete when compiling for the Microsoft ABI. In that case, it'll be incomplete if it's yet to receive an MSInheritanceAttr. The attribute is set in Sema::RequireCompleteTypeImpl.

When using regular member pointers (i.e. not through reflection): Sema::CreateBuiltinUnaryOp calls Sema::CheckAddressOfOperand, which specifically forces the inheritance attribute to be applied at this point. However this doesn't happen for member pointers produced by the reflection system, which is what causes the error. I suppose the fix would be to force application of the inheritance attribute in the same way (by calling Sema::isCompletetype) wherever the reflection system makes these member pointers (I haven't looked at where that is yet).

It only fails in c++1z mode because it requires the parameter check to happen sooner. It happens to work in earlier std modes because the code below that ends up calling Sema::isCompleteType anyway, which applies the attribute hence making the type complete.

hamzasood avatar Mar 04 '17 16:03 hamzasood

Hi, thanks for the hint! I'll have a look at this ASAP.

matus-chochlik avatar Mar 05 '17 06:03 matus-chochlik