On Fri, May 09, 2025 at 10:31:38AM +0800, LIU Hao wrote:
> 在 2025-5-4 22:24, наб 写道:
> > Consider the following program, reduced from Lensfun:
> >    #include <cstring>
> >    extern char *f(const char *first_element, ...) 
> > __attribute__((__sentinel__));
> >    static auto N = f("a", "b", NULL);
> >    static auto n = f("a", "b", nullptr);
> >    static auto z = f("a", "b", 0);
> >    #define NULL 123
> > in C++11 and later, NULL=nullptr so N/n are valid, and z is wrong.
> 
> In C++ it's common to have `NULL` defined as `0`.
This is not the case. I think I was a little overzealous to say that
"C++11 <=> NULL=nullptr" (both C and C++ allow any "null-pointer constant"),
but both GCC and Clang define it as __null.

GCC:
  77395be63213 (Richard Stallman  1992-03-30 02:25:19 +0000 413) #if defined 
(_STDDEF_H) || defined (__need_NULL)
  301264e6e9f7 (Michael Meissner  1991-11-27 20:06:32 +0000 414) #undef NULL    
          /* in case <stdio.h> has defined it. */
  7a389b48df6a (Jason Merrill     1996-08-08 01:45:02 +0000 415) #ifdef __GNUG__
  7a389b48df6a (Jason Merrill     1996-08-08 01:45:02 +0000 416) #define NULL 
__null
  7a389b48df6a (Jason Merrill     1996-08-08 01:45:02 +0000 417) #else   /* G++ 
*/
  be78ffb2267d (Jason Merrill     2000-06-24 18:19:46 -0400 418) #ifndef 
__cplusplus
  301264e6e9f7 (Michael Meissner  1991-11-27 20:06:32 +0000 419) #define NULL 
((void *)0)
  be78ffb2267d (Jason Merrill     2000-06-24 18:19:46 -0400 420) #else   /* C++ 
*/
  be78ffb2267d (Jason Merrill     2000-06-24 18:19:46 -0400 421) #define NULL 0
  be78ffb2267d (Jason Merrill     2000-06-24 18:19:46 -0400 422) #endif  /* C++ 
*/
  7a389b48df6a (Jason Merrill     1996-08-08 01:45:02 +0000 423) #endif  /* G++ 
*/
  77395be63213 (Richard Stallman  1992-03-30 02:25:19 +0000 424) #endif   /* 
NULL not defined and <stddef.h> or need NULL.  */
  77395be63213 (Richard Stallman  1992-03-30 02:25:19 +0000 425) #undef   
__need_NULL

  $ git show 7a389b48df6a
  commit 7a389b48df6a1622eb12ad09d5def385f357734b
  Author: Jason Merrill <merr...@gnu.org>
  Date:   Thu Aug 8 01:45:02 1996 +0000

      (NULL): Use __null for G++.

      From-SVN: r12601

  diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
  index 49c2556e001..0cea45972da 100644
  --- a/gcc/ginclude/stddef.h
  +++ b/gcc/ginclude/stddef.h
  @@ -306,7 +306,11 @@ typedef __WINT_TYPE__ wint_t;

   #if defined (_STDDEF_H) || defined (__need_NULL)
   #undef NULL            /* in case <stdio.h> has defined it. */
  +#ifdef __GNUG__
  +#define NULL __null
  +#else   /* G++ */
   #define NULL ((void *)0)
  +#endif  /* G++ */
   #endif /* NULL not defined and <stddef.h> or need NULL.  */
   #undef __need_NULL

Clang:
  272bcf6768d3c (Nico Weber         2014-04-30 04:35:09 +0000 102) #if 
defined(__need_NULL)
  0a4a8326c1027 (Ted Kremenek       2010-03-08 23:23:45 +0000 103) #undef NULL
  95aa0b77f25c8 (Argyrios Kyrtzidis 2013-03-27 21:22:45 +0000 104) #ifdef 
__cplusplus
  1d725ecf93037 (Nico Weber         2012-04-24 21:27:01 +0000 105) #  if 
!defined(__MINGW32__) && !defined(_MSC_VER)
  1d725ecf93037 (Nico Weber         2012-04-24 21:27:01 +0000 106) #    define 
NULL __null
  1d725ecf93037 (Nico Weber         2012-04-24 21:27:01 +0000 107) #  else
  1d725ecf93037 (Nico Weber         2012-04-24 21:27:01 +0000 108) #    define 
NULL 0
  1d725ecf93037 (Nico Weber         2012-04-24 21:27:01 +0000 109) #  endif
  6b0dc8511964e (Anders Carlsson    2008-11-04 06:53:14 +0000 110) #else
  1d725ecf93037 (Nico Weber         2012-04-24 21:27:01 +0000 111) #  define 
NULL ((void*)0)
  6b0dc8511964e (Anders Carlsson    2008-11-04 06:53:14 +0000 112) #endif
  72da678d8c84c (Ian Anderson       2023-08-11 14:38:13 -0700 113) #undef 
__need_NULL
  72da678d8c84c (Ian Anderson       2023-08-11 14:38:13 -0700 114) #endif /* 
defined(__need_NULL) */

  commit 1d725ecf93037e8877286f53a7289f39064a9fc5
  Author: Nico Weber <tha...@chromium.org>
  Date:   Tue Apr 24 21:27:01 2012 +0000

      Let NULL and MSVC headers coexist better.

      Fixes the two issues mentioned in PR12146.

      llvm-svn: 155490

  diff --git a/clang/lib/Headers/stddef.h b/clang/lib/Headers/stddef.h
  index 9e87ee89b3b9..d7db826e676e 100644
  --- a/clang/lib/Headers/stddef.h
  +++ b/clang/lib/Headers/stddef.h
  @@ -43,10 +43,13 @@ typedef __WCHAR_TYPE__ wchar_t;

   #undef NULL
   #ifdef __cplusplus
  -#undef __null  // VC++ hack.
  -#define NULL __null
  +#  if !defined(__MINGW32__) && !defined(_MSC_VER)
  +#    define NULL __null
  +#  else
  +#    define NULL 0
  +#  endif
   #else
  -#define NULL ((void*)0)
  +#  define NULL ((void*)0)
   #endif

   #define offsetof(t, d) __builtin_offsetof(t, d)

  0a4a8326c1027 (Ted Kremenek    2010-03-08 23:23:45 +0000 44) #undef NULL
  6b0dc8511964e (Anders Carlsson 2008-11-04 06:53:14 +0000 45) #ifdef 
__cplusplus
  38321174e09cd (Chris Lattner   2010-08-03 22:13:56 +0000 46) #undef __null  
// VC++ hack.
  f7ab50df29066 (Douglas Gregor  2008-12-01 17:20:57 +0000 47) #define NULL 
__null
  6b0dc8511964e (Anders Carlsson 2008-11-04 06:53:14 +0000 48) #else
  9e9b046ac95c9 (Eli Friedman    2008-05-20 13:34:26 +0000 49) #define NULL 
((void*)0)
  6b0dc8511964e (Anders Carlsson 2008-11-04 06:53:14 +0000 50) #endif

  $ git show f7ab50df29066
  commit f7ab50df290663597d02b8a5668866bfb57fc989
  Author: Douglas Gregor <dgre...@apple.com>
  Date:   Mon Dec 1 17:20:57 2008 +0000

      Define NULL to __null in C++, so that it's guaranteed to have the same 
size as a pointer

      llvm-svn: 60355

  diff --git a/clang/lib/Headers/stddef.h b/clang/lib/Headers/stddef.h
  index d5f4eb9c7c29..2c84b4b066c9 100644
  --- a/clang/lib/Headers/stddef.h
  +++ b/clang/lib/Headers/stddef.h
  @@ -33,7 +33,7 @@ typedef __typeof__(*L"") wchar_t;
   #endif

   #ifdef __cplusplus
  -#define NULL (0)
  +#define NULL __null
   #else
   #define NULL ((void*)0)
   #endif

This has been the case since 1996, and since 2012 Clang includes a
work-around the very bug I'm trying to fix in this patch.

> Your code should not
> assume `NULL` is an expression whose size is a pointer.
This is code found in the wild that obeys the convention followed by
every other distribution, and there's no reason mingw-w64 should diverge.

Even /if/ this weren't the case, mingw-w64 /already/ uses the conventional
  #define NULL __null
in /some/ headers, but not others. Even /if/ this is legal,
having inconsistent NULL values is undesirable
and fixing it to be consistent is also a good goal.

Please reconsider.

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to