C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] How to handle conflicting 'unreachable' definitions

From: Aaron Ballman <aaron_at_[hidden]>
Date: Thu, 4 Apr 2024 12:11:52 -0400
On Thu, Apr 4, 2024 at 11:59 AM Jonathan Wakely <cxx_at_[hidden]> wrote:
> On Thu, 4 Apr 2024, 16:39 Aaron Ballman via Liaison, <liaison_at_[hidden]> wrote:
>>
>> On Thu, Apr 4, 2024 at 10:30 AM Ville Voutilainen
>> <ville.voutilainen_at_[hidden]> wrote:
>> >
>> > On Thu, 4 Apr 2024 at 16:15, Aaron Ballman via Liaison
>> > <liaison_at_[hidden]> wrote:
>> > >
>> > > C23 adds a macro named `unreachable` to <stddef.h>. C++23 adds a
>> > > function named `std::unreachable` to <utility>. What should the
>> > > behavior of this code be when compiled in C++23?
>> > >
>> > > #include <stddef.h>
>> > >
>> > > #ifndef unreachable
>> > > #error "oh no, my macro!"
>> > > #endif
>> > >
>> > > [support.c.headers.general]p1
>> > > (https://eel.is/c++draft/support.c.headers#general-1) says:
>> > >
>> > > For compatibility with the C standard library, the C++ standard
>> > > library provides the C headers shown in Table 40. The intended use of
>> > > these headers is for interoperability only. It is possible that C++
>> > > source files need to include one of these headers in order to be valid
>> > > ISO C. Source files that are not intended to also be valid ISO C
>> > > should not use any of the C headers.
>> > >
>> > > I read this as saying that including a C header in a C++
>> > > implementation should provide all the interfaces from the C header
>> > > unless the C++ standard says something else. Since C++23 isn't based
>> > > on top of C23 and thus says nothing about the `unreachable` macro in
>> > > stddef.h, I think this implies that the code should compile.
>> > > (Similarly, including stdbit.h should be fine if the header exists, or
>> > > including string.h and using strdup or memccpy should work, and so on
>> > > for all the newly introduced C23 library functionality.) I think this
>> > > matches user expectations and the intent of the standard, but the
>> > > situation with unreachable is a bit odd and the question came up
>> > > during a code review for Clang which removes the macro from stddef.h
>> > > in C++ mode because of the potential for conflict with the function
>> > > declared in <utility>.
>> > >
>> > > I have two concrete questions:
>> > >
>> > > 1) Before WG21 has rebased on top of the latest C, are C++
>> > > implementations expected to strip out all interfaces from C standard
>> > > library headers that are not in the version of C which C++ has based
>> > > the library on?
>> > >
>> > > 2) If the answer to #1 is "no, C++ implementations are expected to
>> > > provide the C interfaces present unless otherwise stated", is
>> > > unreachable likely to be special when C++ rebases on top of C23?
>> >
>> > My spec-squinting suggests that the answer to (1) is yes. The
>> > normative reference to C
>> > comes with a date, it refers to C18. I therefore would not expect
>> > C++23 to bring in C23 entities.
>> >
>> > That is also my technical preference; it's ostensibly so that that
>> > particular version of C
>> > has been figured out how to make it work with that particular version
>> > of C++, and newer
>> > versions of C simply might not work.
>>
>> Okay, that leaves some really interesting situations then.
>>
>> Should #include <stdbit.h> compile because it's not mentioned at all
>> by the C++ standard and so it's basically a user-provided header?
>
>
> The C++ standard has no position on that. The implementation can decide what to do. I know at least one implementation where it won't work because _BitInt is not supported but the C++ compiler, only the C compiler.
>
> But the C++ standard certainly has a position on std::unreachable and a macro by that name is non-conforming. Implementations cannot define it as a macro as a conforming extension.

Thank you! Does this also mean that a C standard library which
provides a standard interface via a function-like macro cannot be
included in any C++ TU because it would be defining macros that are
not conforming extensions? IOW: #define atoi(str)
(some_impl_for_atoi)((str)) would be conforming for the C standard
library to do in C, but nonconforming if included in C++?

> Some users want a header to include what they ask for, and no more. E.g. if they define _XOPEN_VERSION=500 they don't want features from newer POSIX standards. And since that affects the set of reserved names, that seems very reasonable.
>
> If they use -std=c99 they don't expect static_assert to be reserved as a macro for the impl. If they use -std=c++14 they don't expect optional to be reserved as a name by any standard library headers (so they can define a macro with that name).
>
> If they include a C++ header, it's reasonable to not want it to provide extra stuff not mentioned in the standard. Other users might want everything it provides. Both desires are reasonable.

This makes sense to me, thank you!

~Aaron

Received on 2024-04-04 16:12:09