[clang] Ensure proper NULL macro definition for system include files. (PR #149176)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 16 13:17:53 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Jamie Schmeiser (jamieschmeiser)
<details>
<summary>Changes</summary>
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.
---
Patch is 20.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/149176.diff
14 Files Affected:
- (modified) clang/lib/Headers/CMakeLists.txt (+37)
- (added) clang/lib/Headers/dbm.h (+39)
- (added) clang/lib/Headers/locale.h (+25)
- (added) clang/lib/Headers/stdio.h (+25)
- (added) clang/lib/Headers/stdlib.h (+25)
- (added) clang/lib/Headers/string.h (+25)
- (added) clang/lib/Headers/sys/dir.h (+38)
- (added) clang/lib/Headers/sys/param.h (+38)
- (added) clang/lib/Headers/sys/types.h (+38)
- (added) clang/lib/Headers/time.h (+25)
- (added) clang/lib/Headers/unistd.h (+35)
- (added) clang/lib/Headers/wchar.h (+25)
- (added) clang/test/Headers/check-NULL-aix.c (+16)
- (added) clang/test/Headers/check-NULL.c (+15)
``````````diff
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index dd52498bbef4c..f1c10595ea38e 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -39,6 +39,25 @@ set(core_files
varargs.h
)
+set(aix_wrapper_files
+ dbm.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 +331,7 @@ set(utility_files
set(files
${core_files}
+ ${aix_files}
${arm_common_files}
${arm_only_files}
${aarch64_only_files}
@@ -529,6 +549,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 +578,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 +666,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 +871,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
+// R...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/149176
More information about the cfe-commits
mailing list