https://github.com/jamieschmeiser updated 
https://github.com/llvm/llvm-project/pull/149176

>From e50062b48a09bd6e077b86bdeed65c7c1abb2ebe Mon Sep 17 00:00:00 2001
From: Jamie Schmeiser <schme...@ca.ibm.com>
Date: Wed, 16 Jul 2025 15:40:09 -0400
Subject: [PATCH] Ensure proper NULL macro definition for system include files.

The C standard allows for at least 2 valid definitions of a null pointer
constant and mandates that several standard headers files define the macro
NULL to be a null pointer constant.  Ensure that definitions of NULL are
consistent across the various C  header files.

respond to review: add in locale.h
---
 clang/lib/Headers/CMakeLists.txt    | 38 ++++++++++++++++++++++++++++
 clang/lib/Headers/dbm.h             | 39 +++++++++++++++++++++++++++++
 clang/lib/Headers/locale.h          | 25 ++++++++++++++++++
 clang/lib/Headers/stdio.h           | 25 ++++++++++++++++++
 clang/lib/Headers/stdlib.h          | 25 ++++++++++++++++++
 clang/lib/Headers/string.h          | 25 ++++++++++++++++++
 clang/lib/Headers/sys/dir.h         | 38 ++++++++++++++++++++++++++++
 clang/lib/Headers/sys/param.h       | 38 ++++++++++++++++++++++++++++
 clang/lib/Headers/sys/types.h       | 38 ++++++++++++++++++++++++++++
 clang/lib/Headers/time.h            | 25 ++++++++++++++++++
 clang/lib/Headers/unistd.h          | 35 ++++++++++++++++++++++++++
 clang/lib/Headers/wchar.h           | 25 ++++++++++++++++++
 clang/test/Headers/check-NULL-aix.c | 16 ++++++++++++
 clang/test/Headers/check-NULL.c     | 15 +++++++++++
 14 files changed, 407 insertions(+)
 create mode 100644 clang/lib/Headers/dbm.h
 create mode 100644 clang/lib/Headers/locale.h
 create mode 100644 clang/lib/Headers/stdio.h
 create mode 100644 clang/lib/Headers/stdlib.h
 create mode 100644 clang/lib/Headers/string.h
 create mode 100644 clang/lib/Headers/sys/dir.h
 create mode 100644 clang/lib/Headers/sys/param.h
 create mode 100644 clang/lib/Headers/sys/types.h
 create mode 100644 clang/lib/Headers/time.h
 create mode 100644 clang/lib/Headers/unistd.h
 create mode 100644 clang/lib/Headers/wchar.h
 create mode 100644 clang/test/Headers/check-NULL-aix.c
 create mode 100644 clang/test/Headers/check-NULL.c

diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index dd52498bbef4c..6c238c2e8aee9 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -39,6 +39,26 @@ set(core_files
   varargs.h
   )
 
+set(aix_wrapper_files
+  dbm.h
+  locale.h
+  stdio.h
+  stdlib.h
+  string.h
+  time.h
+  unistd.h
+  wchar.h
+  )
+set(aix_sys_subdir_wrapper_files
+  sys/dir.h
+  sys/param.h
+  sys/types.h
+  )
+set(aix_files
+  ${aix_wrapper_files}
+  ${aix_sys_subdir_wrapper_files}
+  )
+
 set(arm_common_files
   # Headers shared by Arm and AArch64
   arm_acle.h
@@ -312,6 +332,7 @@ set(utility_files
 
 set(files
   ${core_files}
+  ${aix_files}
   ${arm_common_files}
   ${arm_only_files}
   ${aarch64_only_files}
@@ -529,6 +550,7 @@ set_target_properties("clang-resource-headers" PROPERTIES
   RUNTIME_OUTPUT_DIRECTORY "${output_dir}")
 add_dependencies("clang-resource-headers"
                  "core-resource-headers"
+                "aix-resource-headers"
                  "arm-common-resource-headers"
                  "arm-resource-headers"
                  "aarch64-resource-headers"
@@ -557,6 +579,7 @@ add_header_target("core-resource-headers" ${core_files})
 add_header_target("arm-common-resource-headers" 
"${arm_common_files};${arm_common_generated_files}")
 
 # Architecture/platform specific targets
+add_header_target("aix-resource-headers" "${aix_files}")
 add_header_target("arm-resource-headers" 
"${arm_only_files};${arm_only_generated_files}")
 add_header_target("aarch64-resource-headers" 
"${aarch64_only_files};${aarch64_only_generated_files}")
 add_header_target("cuda-resource-headers" 
"${cuda_files};${cuda_wrapper_files};${cuda_wrapper_bits_files};${cuda_wrapper_utility_files}")
@@ -644,6 +667,18 @@ install(
   EXCLUDE_FROM_ALL
   COMPONENT core-resource-headers)
 
+install(
+  FILES ${aix_wrapper_files}
+  DESTINATION ${header_install_dir}
+  EXCLUDE_FROM_ALL
+  COMPONENT aix-resource-headers)
+
+install(
+  FILES ${aix_sys_subdir_wrapper_files}
+  DESTINATION ${header_install_dir}/sys
+  EXCLUDE_FROM_ALL
+  COMPONENT aix-resource-headers)
+
 install(
   FILES ${arm_common_files} ${arm_common_generated_files}
   DESTINATION ${header_install_dir}
@@ -837,6 +872,9 @@ if (NOT LLVM_ENABLE_IDE)
   add_llvm_install_targets(install-core-resource-headers
                            DEPENDS core-resource-headers
                            COMPONENT core-resource-headers)
+  add_llvm_install_targets(install-aix-resource-headers
+                           DEPENDS aix-resource-headers
+                           COMPONENT aix-resource-headers)
   add_llvm_install_targets(install-arm-common-resource-headers
                            DEPENDS arm-common-resource-headers
                            COMPONENT arm-common-resource-headers)
diff --git a/clang/lib/Headers/dbm.h b/clang/lib/Headers/dbm.h
new file mode 100644
index 0000000000000..8b7e2f51c5664
--- /dev/null
+++ b/clang/lib/Headers/dbm.h
@@ -0,0 +1,39 @@
+/*===---- dbm.h - BSD header for database management 
----------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX)
+
+// Ensure that the definition of NULL (if present) is correct since it might
+// not be redefined if it is already defined.  This ensures any use of NULL is
+// correct while processing the include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
+
+// Always include_next the file so that it will be included when requested.
+// This will trigger an error on platforms where it is not found unless
+// system include paths find it, which is the correct behaviour.
+
+#include_next <dbm.h>
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX) && defined(NULL)
+
+// Ensure that the definition of NULL (if present) is consistent with what
+// is expected, regardless of where it came from.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
diff --git a/clang/lib/Headers/locale.h b/clang/lib/Headers/locale.h
new file mode 100644
index 0000000000000..6cb85738521cb
--- /dev/null
+++ b/clang/lib/Headers/locale.h
@@ -0,0 +1,25 @@
+/*===---- locale.h - Standard header for localization 
---------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// The standard specifies that locale.h defines NULL so ensure that the
+// definition is correct since it might not be redefined if it is already
+// defined.  This ensures any use of NULL is correct while processing the
+// include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#include_next <locale.h>
+
+// Ensure that the definition of NULL is as expected (likely redundant).
+#define __need_NULL
+#include <stddef.h>
diff --git a/clang/lib/Headers/stdio.h b/clang/lib/Headers/stdio.h
new file mode 100644
index 0000000000000..db981f54ec193
--- /dev/null
+++ b/clang/lib/Headers/stdio.h
@@ -0,0 +1,25 @@
+/*===---- stdio.h - Standard header for input and 
output-------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// The standard specifies that stdio.h defines NULL so ensure that the
+// definition is correct since it might not be redefined if it is already
+// defined.  This ensures any use of NULL is correct while processing the
+// include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#include_next <stdio.h>
+
+// Ensure that the definition of NULL is as expected (likely redundant).
+#define __need_NULL
+#include <stddef.h>
diff --git a/clang/lib/Headers/stdlib.h b/clang/lib/Headers/stdlib.h
new file mode 100644
index 0000000000000..2bcf79e9622a5
--- /dev/null
+++ b/clang/lib/Headers/stdlib.h
@@ -0,0 +1,25 @@
+/*===---- stdlib.h - Standard header for general utilities 
----------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// The standard specifies that stdlib.h defines NULL so ensure that the
+// definition is correct since it might not be redefined if it is already
+// defined.  This ensures any use of NULL is correct while processing the
+// include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#include_next <stdlib.h>
+
+// Ensure that the definition of NULL is as expected (likely redundant).
+#define __need_NULL
+#include <stddef.h>
diff --git a/clang/lib/Headers/string.h b/clang/lib/Headers/string.h
new file mode 100644
index 0000000000000..a23d91e25743f
--- /dev/null
+++ b/clang/lib/Headers/string.h
@@ -0,0 +1,25 @@
+/*===---- string.h - Standard header for string handling 
------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// The standard specifies that string.h defines NULL so ensure that the
+// definition is correct since it might not be redefined if it is already
+// defined.  This ensures any use of NULL is correct while processing the
+// include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#include_next <string.h>
+
+// Ensure that the definition of NULL is as expected (likely redundant).
+#define __need_NULL
+#include <stddef.h>
diff --git a/clang/lib/Headers/sys/dir.h b/clang/lib/Headers/sys/dir.h
new file mode 100644
index 0000000000000..8f7e2a40d1bd8
--- /dev/null
+++ b/clang/lib/Headers/sys/dir.h
@@ -0,0 +1,38 @@
+/*===---- sys/dir.h - BSD header for directory handling 
-------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX)
+
+// Ensure that the definition of NULL (if present) is correct since it might
+// not be redefined if it is already defined.  This ensures any use of NULL is
+// correct while processing the include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
+
+// Always include_next the file so that it will be included when requested.
+// This will trigger an error on platforms where it is not found unless
+// system include paths find it, which is the correct behaviour.
+#include_next <sys/dir.h>
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX) && defined(NULL)
+
+// Ensure that the definition of NULL (if present) is consistent with what
+// is expected, regardless of where it came from.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
diff --git a/clang/lib/Headers/sys/param.h b/clang/lib/Headers/sys/param.h
new file mode 100644
index 0000000000000..e1338854ad0b0
--- /dev/null
+++ b/clang/lib/Headers/sys/param.h
@@ -0,0 +1,38 @@
+/*===---- sys/param.h - BSD header 
----------------------------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX)
+
+// Ensure that the definition of NULL (if present) is correct since it might
+// not be redefined if it is already defined.  This ensures any use of NULL is
+// correct while processing the include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
+
+// Always include_next the file so that it will be included when requested.
+// This will trigger an error on platforms where it is not found unless
+// system include paths find it, which is the correct behaviour.
+#include_next <sys/param.h>
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX) && defined(NULL)
+
+// Ensure that the definition of NULL (if present) is consistent with what
+// is expected, regardless of where it came from.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
diff --git a/clang/lib/Headers/sys/types.h b/clang/lib/Headers/sys/types.h
new file mode 100644
index 0000000000000..c4f6d75491d3a
--- /dev/null
+++ b/clang/lib/Headers/sys/types.h
@@ -0,0 +1,38 @@
+/*===---- sys/types.h - BSD header for types 
------------------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX)
+
+// Ensure that the definition of NULL (if present) is correct since it might
+// not be redefined if it is already defined.  This ensures any use of NULL is
+// correct while processing the include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
+
+// Always include_next the file so that it will be included when requested.
+// This will trigger an error on platforms where it is not found unless
+// system include paths find it, which is the correct behaviour.
+#include_next <sys/types.h>
+
+// Limit the effects to those platforms that have this as a system header.
+#if defined(_AIX) && defined(NULL)
+
+// Ensure that the definition of NULL (if present) is consistent with what
+// is expected, regardless of where it came from.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
diff --git a/clang/lib/Headers/time.h b/clang/lib/Headers/time.h
new file mode 100644
index 0000000000000..3702d40caf8c5
--- /dev/null
+++ b/clang/lib/Headers/time.h
@@ -0,0 +1,25 @@
+/*===---- time.h - Standard header for date and time handling 
-------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// The standard specifies that time.h defines NULL so ensure that the
+// definition is correct since it might not be redefined if it is already
+// defined.  This ensures any use of NULL is correct while processing the
+// include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#include_next <time.h>
+
+// Ensure that the definition of NULL is as expected (likely redundant).
+#define __need_NULL
+#include <stddef.h>
diff --git a/clang/lib/Headers/unistd.h b/clang/lib/Headers/unistd.h
new file mode 100644
index 0000000000000..05b8c936ba574
--- /dev/null
+++ b/clang/lib/Headers/unistd.h
@@ -0,0 +1,35 @@
+/*===---- unistd.h - Posix Standard header 
--------------------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// Limit the effects to those platforms that are POSIX compliant.
+#if defined(_AIX)
+
+// POSIX specifies that unistd.h defines NULL so ensure that the
+// definition is correct since it might not be redefined if it is already
+// defined.  This ensures any use of NULL is correct while processing the
+// include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#endif
+
+#include_next <unistd.h>
+
+// Limit the effects to those platforms that are POSIX compliant.
+#if defined(_AIX) && defined(NULL)
+
+// Ensure that the definition of NULL is as expected (likely redundant).
+#define __need_NULL
+#include <stddef.h>
+
+#endif
diff --git a/clang/lib/Headers/wchar.h b/clang/lib/Headers/wchar.h
new file mode 100644
index 0000000000000..ae7a1e779f5b0
--- /dev/null
+++ b/clang/lib/Headers/wchar.h
@@ -0,0 +1,25 @@
+/*===---- wchar.h - Standard header for string handling ------------------===*\
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+\*===----------------------------------------------------------------------===*/
+
+// Although technically correct according to the standard, NULL defined as 0
+// may be problematic since it may result in a different size object than a
+// pointer (eg 64 bit mode on AIX).  Therefore, re-define the macro to
+// ((void*)0) for consistency where needed.
+
+// The standard specifies that wchar.h defines NULL so ensure that the
+// definition is correct since it might not be redefined if it is already
+// defined.  This ensures any use of NULL is correct while processing the
+// include_next.
+#define __need_NULL
+#include <stddef.h>
+
+#include_next <wchar.h>
+
+// Ensure that the definition of NULL is as expected (likely redundant).
+#define __need_NULL
+#include <stddef.h>
diff --git a/clang/test/Headers/check-NULL-aix.c 
b/clang/test/Headers/check-NULL-aix.c
new file mode 100644
index 0000000000000..01bef5efd4ecd
--- /dev/null
+++ b/clang/test/Headers/check-NULL-aix.c
@@ -0,0 +1,16 @@
+// There are at least 2 valid C null-pointer constants as defined
+// by the C language standard.
+// Test that the macro NULL is defined consistently by those system headers
+// on AIX that have a macro definition for NULL.
+
+// REQUIRES: system-aix
+
+// RUN: %clang %s -Dheader="<dbm.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<sys/dir.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<sys/param.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<sys/types.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<unistd.h>" -E | tail -1 | FileCheck %s
+
+#include header
+void *p = NULL;
+// CHECK: ({{ *}}({{ *}}void{{ *}}*{{ *}}){{ *}}0{{ *}})
diff --git a/clang/test/Headers/check-NULL.c b/clang/test/Headers/check-NULL.c
new file mode 100644
index 0000000000000..10d40b941b648
--- /dev/null
+++ b/clang/test/Headers/check-NULL.c
@@ -0,0 +1,15 @@
+// There are at least 2 valid C null-pointer constants as defined
+// by the C language standard.
+// Test that the macro NULL is defined consistently for all platforms by
+// those headers that the C standard mandates a macro definition for NULL.
+
+// RUN: %clang %s -Dheader="<locale.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<stdio.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<stdlib.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<string.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<time.h>" -E | tail -1 | FileCheck %s
+// RUN: %clang %s -Dheader="<wchar.h>" -E | tail -1 | FileCheck %s
+
+#include header
+void *p = NULL;
+// CHECK: ({{ *}}({{ *}}void{{ *}}*{{ *}}){{ *}}0{{ *}})

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

Reply via email to