C++ Logo


Advanced search

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

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Thu, 4 Apr 2024 16:59:01 +0100
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.

> Should use of strdup from <string.h> compile despite not being in C17,
> because it is in POSIX?

The C++ standard takes no position in this. Supporting it is a useful and
conforming extension.

> Should use of __STDC_VERSION_LIMITS_H__ from <limits.h> not compile
> because it wasn't in C17 nor in POSIX?

Why would I even care about using that in C++?

I certainly wouldn't rely on it being available in portable C++.

> I don't see how users are served by anything other than providing the
> interfaces from the header they included. I don't think it's
> defensible from an implementation perspective to say "we will only
> give you some C standard interfaces in C++ mode, based on which C
> standard the C++ library was based on at the time" -- that is just
> inexplicable to anyone but a committee member and seems like a burden
> on implementers because that also means C11 interfaces can't be
> exposed in C++14 or C++11 mode, etc.

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.

N.B. glibc headers are typically quite strict about this, not declaring
non-ISO names unless you ask for it (via a macro like _POSIX_SOURCE or

Due to a longstanding bug, G++ defines _GNU_SOURCE on Linux and so glibc
headers dump everything possible into the global namespace when included by
C++. You are saying that's desirable, but not everybody agrees. Wouldn't it
be better to be able to choose which sets of extensions (such as POSIX APIs
and C23 features) to enable?

> Also, I can't square how that fits with "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."
> If it's for interoperability with valid ISO C... C23 is valid ISO C
> whether WG21 has rebased or not.

But a common header that you expect to be used by both C and C++ code
should generally stick to the common subset of the two languages. So don't
use stdbit.h or assume unreachable is a macro.

> > Why, for heaven's sake, is 'unreachable' a macro in C? That is instant
> > trouble for C++,
> > where every user expects to be able to scope names via namespaces.
> I'm not interested in rehashing decisions that are already too late
> for either committee to change, just trying to figure out how to move
> forward within the world we have.
> ~Aaron
> _______________________________________________
> Liaison mailing list
> Liaison_at_[hidden]
> Subscription: https://lists.isocpp.org/mailman/listinfo.cgi/liaison
> Link to this post: http://lists.isocpp.org/liaison/2024/04/1362.php

Received on 2024-04-04 16:00:25