ldionne added inline comments.

================
Comment at: clang/lib/Headers/stddef.h:118-122
+#ifdef __cplusplus
+namespace std {
+typedef decltype(nullptr) nullptr_t;
+}
+using ::std::nullptr_t;
----------------
iana wrote:
> aaron.ballman wrote:
> > ldionne wrote:
> > > iana wrote:
> > > > aaron.ballman wrote:
> > > > > iana wrote:
> > > > > > aaron.ballman wrote:
> > > > > > > iana wrote:
> > > > > > > > ldionne wrote:
> > > > > > > > > iana wrote:
> > > > > > > > > > aaron.ballman wrote:
> > > > > > > > > > > Related:
> > > > > > > > > > > 
> > > > > > > > > > > https://github.com/llvm/llvm-project/issues/37564
> > > > > > > > > > > https://cplusplus.github.io/LWG/issue3484
> > > > > > > > > > > 
> > > > > > > > > > > CC @ldionne
> > > > > > > > > > I don't _think_ this change actually changes the way 
> > > > > > > > > > nullptr_t gets defined in C++, does it?
> > > > > > > > > I think we absolutely don't want to touch `std::nullptr_t` 
> > > > > > > > > from this header. It's libc++'s responsibility to define 
> > > > > > > > > that, and in fact we define it in `std::__1`, so this is even 
> > > > > > > > > an ABI break (or I guess it would be a compiler error, not 
> > > > > > > > > sure).
> > > > > > > > I'm really not touching it though. All I did is move it from 
> > > > > > > > `__need_NULL` to `__need_nullptr_t`.
> > > > > > > > 
> > > > > > > > The old behavior is that `std::nullptr_t` would only be touched 
> > > > > > > > if (no `__need_` macros were set or if `__need_NULL` was set), 
> > > > > > > > and (_MSC_EXTENSIONS and _NATIVE_NULLPTR_SUPPORTED are defined).
> > > > > > > > 
> > > > > > > > The new behavior is that `std::nullptr_t` will only be touched 
> > > > > > > > if ((no `__need_` macros are set) and (_MSC_EXTENSIONS and 
> > > > > > > > _NATIVE_NULLPTR_SUPPORTED are defined)) or (the new 
> > > > > > > > `__need_nullptr_t` macro is set)
> > > > > > > > 
> > > > > > > > So the only change is that C++ code that previously set 
> > > > > > > > `__need_NULL` will no longer get `std::nullptr_t`. @efriedma 
> > > > > > > > felt like that was a fine change.
> > > > > > > Does libc++ provide the symbols for a freestanding compilation?
> > > > > > > 
> > > > > > > I was pointing out those links specifically because the C++ 
> > > > > > > standard currently says that stddef.h (the C standard library 
> > > > > > > header) needs to provide a definition of `std::nullptr_t`, but 
> > > > > > > that LWG thinks that's perhaps not the right way to do that and 
> > > > > > > may be removing that requirement.
> > > > > > It is weird the standard puts that in stddef.h and not cstddef. I 
> > > > > > think libc++ could provide that in their stddef.h anyway, but the 
> > > > > > intent in this review is to not rock the boat and only do the 
> > > > > > minimal change discussed above.
> > > > > Yeah, this discussion is to figure out whether we have an existing 
> > > > > bug we need to address and if so, where to address it (libc++, clang, 
> > > > > or the C++ standard). I don't think your changes are exacerbating 
> > > > > anything, more just that they've potentially pointed out something 
> > > > > related.
> > > > 👍 
> > > > Does libc++ provide the symbols for a freestanding compilation?
> > > 
> > > I don't think we do. We basically don't support `-ffreestanding` right 
> > > now (we support embedded and funky platforms via other mechanisms).
> > > 
> > > But regardless, `<stddef.h>` should never define something in namespace 
> > > `std`, that should be libc++'s responsibility IMO. What we could do here 
> > > instead is just
> > > 
> > > ```
> > > #ifdef __cplusplus
> > > typedef decltype(nullptr) nullptr_t;
> > > #else
> > > typedef typeof(nullptr) nullptr_t;
> > > #endif
> > > ```
> > > 
> > > and then let libc++'s `<cstddef>` do
> > > 
> > > ```
> > > _LIBCPP_BEGIN_NAMESPACE_STD
> > > using ::nullptr_t;
> > > _LIBCPP_END_NAMESPACE_STD
> > > ```
> > > 
> > > If Clang's `<stddef.h>` did define `::nullptr_t`, we could likely remove 
> > > libc++'s `<stddef.h>` and that might simplify things.
> > >> Does libc++ provide the symbols for a freestanding compilation?
> > > I don't think we do. We basically don't support -ffreestanding right now 
> > > (we support embedded and funky platforms via other mechanisms).
> > 
> > Okay, that's what I thought as well. Thanks!
> > 
> > > But regardless, <stddef.h> should never define something in namespace 
> > > std, that should be libc++'s responsibility IMO. What we could do here 
> > > instead is just
> > 
> > Ah, so you're thinking stddef.h should provide the global nullptr_t and 
> > cstddef should provide the std::nullptr_t. I was thinking stddef.h should 
> > not define nullptr_t in C++ mode at all; it's a C header, not a C++ header. 
> > That led me to thinking about what the behavior should be in C23 given that 
> > it supports nullptr_t.
> > 
> > Were it not for the current requirement that stddef.h provide nullptr_t, I 
> > think stddef.h should do:
> > ```
> > typedef typeof(nullptr) nullptr_t;
> > ```
> > in C23 mode and not do anything special for C++ at all. C's `nullptr_t` 
> > needs to be ABI compatible with C++'s `nullptr_t`, so a C++ user including 
> > the C header should not get any problems linking against a C++ library. 
> > However, this would mean that C++ users cannot include stddef.h to get 
> > nullptr_t; they'd need to include cstddef to be assured they'd get it. But 
> > because of the ABI compatibility, perhaps the solution is to expose the 
> > above in both C and C++ modes from stddef.h, then libc++ can do the dance 
> > to import it into namespace std?
> Actually I think I did change it after all. If a C header does something like 
> this
> ```
> // It's assumed that only C23 or later is supported, or C++
> #define __need_nullptr_t
> #include <stddef.h>
> ```
> If such a header got included in a C++ program, we wouldn't want to declare 
> `std::nullptr_t`. I think we need to keep the _MSC_EXTENSIONS check in there 
> and never declare it if that isn't set, even if the includer asked for 
> nullptr_t. That matches the behavior of wchar_t in this header, and I think 
> for similar reasons.
> 
> Otherwise clang's stddef.h would step on the `nullptr_t` declared by libc++'s 
> stddef.h (modules would probably complain about a duplicate/conflicting 
> declaration)
@aaron.ballman Ok, I follow your train of thought. So in that case what we 
would do is this:

```
// <stddef.h> from the Clang builtin headers:
#if we-are-in-C23
typedef typeof(nullptr) nullptr_t;
#endif
// never do anything special for C++
```

```
// <cstddef> from libc++:
#include <stddef.h>

#if we-are-in-whatever-C++-standard-synced-with-C23
  _LIBCPP_BEGIN_NAMESPACE_STD
  using ::nullptr_t; // use the C23 ::nullptr_t as defined in <stddef.h>
  _LIBCPP_END_NAMESPACE_STD
#else
  _LIBCPP_BEGIN_NAMESPACE_STD
  typedef decltype(nullptr) nullptr_t; // declare our own nullptr_t from 
scratch since C doesn't have a notion of it
  _LIBCPP_END_NAMESPACE_STD
#endif
```

This way:
1. Libc++ doesn't need to have `<stddef.h>` anymore
2. The Clang builtin headers are pure C
3. `std::nullptr_t` and `::nullptr_t` are always the same thing when both are 
defined

However in this world `::nullptr_t` would not be defined when including 
`<stddef.h>` in C++ prior to whatever version is synced with C23 (that's not a 
problem IMO, but it is a behavior change).

Does this make sense to everyone?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157757/new/

https://reviews.llvm.org/D157757

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to