Skip to content

Incorrect handling of incomplete types in std::derived_from #121278

@cor3ntin

Description

@cor3ntin

Per https://eel.is/c++draft/meta#lib:is_base_of,

Derived shall be a complete type

This is generally enforced by __is_base_of (the builtin used to implement is_base_of_v)

However, in libc++, derived_from is defined as

concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v<const volatile _Dp*, const volatile _Bp*>;

And because the constraints are only enforced in __is_base_of which is not in the immediate context of the is_base_of_v constraint, substituting an incomplete class in is_base_of_v does not result in a substitution failure in the immediate context (which should just cause derived_from to not be satisfied per https://eel.is/c++draft/temp.constr.atomic#3.sentence-2) but instead makes the program ill-formed, which i believe is non-conforming.

Note that GCC diverges in all cases. MSVC and EDG exposes what I believe to be the correct behavior.

I think there are 2 solutions:

  • Modify derived_from to use __is_base_of directly (which is what libstdc++ and MS STL do)
  • Add a require clause to std::is_base_of_v to check for completeness

https://godbolt.org/z/zGrKEKEao

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.rejects-valid

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions