[clang] [C] Don't diagnose null pointer macros in -Wimplicit-void-ptr-cast (PR #140724)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Tue May 20 05:52:09 PDT 2025
https://github.com/AaronBallman created https://github.com/llvm/llvm-project/pull/140724
This silences the diagnostic when the right-hand side is a null pointer constant that comes from a macro expansion, such as NULL. However, we do not limit to just NULL because other custom macros may expand to an implicit void * cast in C while expanding to something else in C++.
>From a5e8f77597ecc8ae56f947de5ef236d88e1581d1 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aaron at aaronballman.com>
Date: Tue, 20 May 2025 08:49:33 -0400
Subject: [PATCH] [C] Don't diagnose null pointer macros in
-Wimplicit-void-ptr-cast
This silences the diagnostic when the right-hand side is a null pointer
constant that comes from a macro expansion, such as NULL. However, we
do not limit to just NULL because other custom macros may expand to an
implicit void * cast in C while expanding to something else in C++.
---
clang/lib/Sema/SemaExpr.cpp | 9 +++++++--
clang/test/Sema/implicit-void-ptr-cast.c | 22 ++++++++++++++++++++++
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b18e83b605e4f..6b04f8150b0a1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9966,8 +9966,13 @@ AssignConvertType Sema::CheckSingleAssignmentConstraints(QualType LHSType,
// If there is a conversion of some kind, check to see what kind of
// pointer conversion happened so we can diagnose a C++ compatibility
// diagnostic if the conversion is invalid. This only matters if the RHS
- // is some kind of void pointer.
- if (Kind != CK_NoOp && !getLangOpts().CPlusPlus) {
+ // is some kind of void pointer. We have a carve-out when the RHS is from
+ // a macro expansion because the use of a macro may indicate different
+ // code between C and C++. Consider: char *s = NULL; where NULL is
+ // defined as (void *)0 in C (which would be invalid in C++), but 0 in
+ // C++, which is valid in C++.
+ if (Kind != CK_NoOp && !getLangOpts().CPlusPlus &&
+ !RHS.get()->getBeginLoc().isMacroID()) {
QualType CanRHS =
RHS.get()->getType().getCanonicalType().getUnqualifiedType();
QualType CanLHS = LHSType.getCanonicalType().getUnqualifiedType();
diff --git a/clang/test/Sema/implicit-void-ptr-cast.c b/clang/test/Sema/implicit-void-ptr-cast.c
index a469c49c36b49..3c3e153d1dbda 100644
--- a/clang/test/Sema/implicit-void-ptr-cast.c
+++ b/clang/test/Sema/implicit-void-ptr-cast.c
@@ -59,4 +59,26 @@ void more(void) {
b3 = (char *)0;
b3 = nullptr;
b3 = 0;
+
+ // Note that we explicitly silence the diagnostic if the RHS is from a macro
+ // expansion. This allows for things like NULL expanding to different token
+ // sequences depending on language mode, but applies to any macro that
+ // expands to a valid null pointer constant.
+#if defined(__cplusplus)
+ #define NULL 0
+#else
+ #define NULL ((void *)0)
+#endif
+ #define SOMETHING_NOT_SPELLED_NULL nullptr
+ #define SOMETHING_THAT_IS_NOT_NULL (void *)12
+
+ char *ptr1 = NULL; // Ok
+ char *ptr2 = SOMETHING_NOT_SPELLED_NULL; // Ok
+ char *ptr3 = SOMETHING_THAT_IS_NOT_NULL; // c-warning {{implicit conversion when initializing 'char *' with an expression of type 'void *' is not permitted in C++}} \
+ cxx-error {{cannot initialize a variable of type 'char *' with an rvalue of type 'void *'}}
+
+ ptr1 = NULL; // Ok
+ ptr2 = SOMETHING_NOT_SPELLED_NULL; // Ok
+ ptr3 = SOMETHING_THAT_IS_NOT_NULL; // c-warning {{implicit conversion when assigning to 'char *' from type 'void *' is not permitted in C++}} \
+ cxx-error {{assigning to 'char *' from incompatible type 'void *'}}
}
More information about the cfe-commits
mailing list