https://github.com/ChenMiaoi created
https://github.com/llvm/llvm-project/pull/229612
The macro exemption checks the start location of the entire expression, so
parentheses written at the use site cause null pointer macros such as `NULL` to
be diagnosed. Ignore parentheses when checking the macro origin.
For example:
```c
int *a = (NULL);
```
With `-Wimplicit-void-ptr-cast`, this previously produced:
```txt
test.c:1:6: warning: implicit conversion when initializing 'int *' with an
expression of type 'void *' is not permitted in C++ [-Wimplicit-void-ptr-cast]
1 | int *a = (NULL);
| ^ ~~~~~~
1 warning generated.
```
After the fix, no warning is emitted.
Fixes #171874
>From 29c840793da85433a0274be20b8b75c03ba6d24b Mon Sep 17 00:00:00 2001
From: Chen Miao <[email protected]>
Date: Wed, 7 Oct 2026 07:40:52 +0800
Subject: [PATCH] [clang][Sema] Fix -Wimplicit-void-ptr-cast for parenthesized
null macros
The macro exemption checks the start location of the entire expression,
so parentheses written at the use site cause null pointer macros such as
`NULL` to be diagnosed. Ignore parentheses when checking the macro origin.
For example:
```c
int *a = (NULL);
```
With `-Wimplicit-void-ptr-cast`, this previously produced:
```txt
test.c:1:6: warning: implicit conversion when initializing 'int *' with an
expression of type 'void *' is not permitted in C++ [-Wimplicit-void-ptr-cast]
1 | int *a = (NULL);
| ^ ~~~~~~
1 warning generated.
```
After the fix, no warning is emitted.
Fixes #171874
---
clang/lib/Sema/SemaExpr.cpp | 5 +++--
clang/test/Sema/implicit-void-ptr-cast.c | 18 ++++++++++++++++++
2 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9b3384cdbdac8c..a51889ed9b3aae 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10427,9 +10427,10 @@ AssignConvertType
Sema::CheckSingleAssignmentConstraints(QualType LHSType,
// 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++.
+ // C++, which is valid in C++. Ignore parentheses around the macro when
+ // checking where the expression originates.
if (Kind != CK_NoOp && !getLangOpts().CPlusPlus &&
- !RHS.get()->getBeginLoc().isMacroID()) {
+ !RHS.get()->IgnoreParens()->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 037feaa137289a..23faf2c7b7e6df 100644
--- a/clang/test/Sema/implicit-void-ptr-cast.c
+++ b/clang/test/Sema/implicit-void-ptr-cast.c
@@ -83,6 +83,24 @@ void more(void) {
cxx-error {{assigning to 'char *' from
incompatible type 'void *'}}
}
+int *gh171874(void) {
+ // Parentheses around a null pointer macro must not defeat the macro
+ // expansion exemption, regardless of the assignment action.
+ int *ptr1 = (NULL);
+ ptr1 = ((NULL));
+ func((NULL));
+
+ // Keep diagnosing explicit void pointer casts and non-null pointer macros.
+ #define ZERO 0
+ int *ptr2 = ((void *)ZERO); // c-warning {{implicit conversion when
initializing 'int *' with an expression of type 'void *' is not permitted in
C++}} \
+ cxx-error {{cannot initialize a variable of
type 'int *' with an rvalue of type 'void *'}}
+ #undef ZERO
+ int *ptr3 = (SOMETHING_THAT_IS_NOT_NULL); // c-warning {{implicit conversion
when initializing 'int *' with an expression of type 'void *' is not permitted
in C++}} \
+ cxx-error {{cannot initialize a
variable of type 'int *' with an rvalue of type 'void *'}}
+
+ return (NULL);
+}
+
void gh154157(void) {
#define ATOMIC_VAR_INIT(value) (value)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits