-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[C] Don't diagnose null pointer macros in -Wimplicit-void-ptr-cast #140724
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[C] Don't diagnose null pointer macros in -Wimplicit-void-ptr-cast #140724
Conversation
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++.
|
@llvm/pr-subscribers-clang Author: Aaron Ballman (AaronBallman) ChangesThis 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++. Full diff: https://github.com/llvm/llvm-project/pull/140724.diff 2 Files Affected:
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 *'}}
}
|
alexfh
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the prompt fix! Looks good!
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++.