Author: Aaron Ballman
Date: 2025-05-21T06:36:21-04:00
New Revision: 7fe387ac35b0b37d2862beaf9c17062b62a221ed

URL: 
https://github.com/llvm/llvm-project/commit/7fe387ac35b0b37d2862beaf9c17062b62a221ed
DIFF: 
https://github.com/llvm/llvm-project/commit/7fe387ac35b0b37d2862beaf9c17062b62a221ed.diff

LOG: [C] Don't diagnose null pointer macros in -Wimplicit-void-ptr-cast 
(#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++.

Added: 
    

Modified: 
    clang/lib/Sema/SemaExpr.cpp
    clang/test/Sema/implicit-void-ptr-cast.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 66dac21bf5818..414a986dd6196 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 
diff erent
+      // 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 
diff erent 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 *'}}
 }


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

Reply via email to