[clang] 2a41b31 - [Sema] Add -Wpointer-to-enum-cast and -Wvoid-pointer-to-enum-cast

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Sat Mar 7 16:43:55 PST 2020


Author: Nathan Chancellor
Date: 2020-03-07T16:43:39-08:00
New Revision: 2a41b31fcdfcb67ab7038fc2ffb606fd50b83a84

URL: https://github.com/llvm/llvm-project/commit/2a41b31fcdfcb67ab7038fc2ffb606fd50b83a84
DIFF: https://github.com/llvm/llvm-project/commit/2a41b31fcdfcb67ab7038fc2ffb606fd50b83a84.diff

LOG: [Sema] Add -Wpointer-to-enum-cast and -Wvoid-pointer-to-enum-cast

GCC does not warn on casts from pointers to enumerators, while clang
currently does: https://godbolt.org/z/3DFDVG

This causes a bunch of extra warnings in the Linux kernel, where
certain structs contain a void pointer to avoid using a gigantic
union for all of the various types of driver data, such as
versions.

Add a diagnostic that allows certain projects like the kernel to
disable the warning just for enums, which allows those projects to
keep full compatibility with GCC but keeps the intention of treating
casts to integers and enumerators the same by default so that other
projects have the opportunity to catch issues not noticed before (or
follow suite and disable the warning).

Link: https://github.com/ClangBuiltLinux/linux/issues/887

Reviewed By: rjmccall

Differential Revision: https://reviews.llvm.org/D75758

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaCast.cpp
    clang/test/Sema/cast.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 6c79ea591734..ae3f882dd910 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -838,9 +838,13 @@ def IncompatibleExceptionSpec : DiagGroup<"incompatible-exception-spec">;
 def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
 def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
                                  [IntToVoidPointerCast]>;
-def VoidPointerToIntCast : DiagGroup<"void-pointer-to-int-cast">;
+def VoidPointerToEnumCast : DiagGroup<"void-pointer-to-enum-cast">;
+def VoidPointerToIntCast : DiagGroup<"void-pointer-to-int-cast",
+                                     [VoidPointerToEnumCast]>;
+def PointerToEnumCast : DiagGroup<"pointer-to-enum-cast",
+                                  [VoidPointerToEnumCast]>;
 def PointerToIntCast : DiagGroup<"pointer-to-int-cast",
-                                 [VoidPointerToIntCast]>;
+                                 [PointerToEnumCast, VoidPointerToIntCast]>;
 
 def Move : DiagGroup<"move", [
     PessimizingMove,

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 181341fed780..b0338c44cca9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3668,9 +3668,15 @@ def warn_int_to_void_pointer_cast : Warning<
 def warn_pointer_to_int_cast : Warning<
   "cast to smaller integer type %1 from %0">,
   InGroup<PointerToIntCast>;
+def warn_pointer_to_enum_cast : Warning<
+  warn_pointer_to_int_cast.Text>,
+  InGroup<PointerToEnumCast>;
 def warn_void_pointer_to_int_cast : Warning<
   "cast to smaller integer type %1 from %0">,
   InGroup<VoidPointerToIntCast>;
+def warn_void_pointer_to_enum_cast : Warning<
+  warn_void_pointer_to_int_cast.Text>,
+  InGroup<VoidPointerToEnumCast>;
 def ext_ms_pointer_to_int_cast : ExtWarn<
   "cast to smaller integer type %1 from %0 is a Microsoft extension">,
 InGroup<MicrosoftCast>;

diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 17d07c57a412..8edff2439e0d 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -2777,11 +2777,16 @@ void CastOperation::CheckCStyleCast() {
       // If the result cannot be represented in the integer type, the behavior
       // is undefined. The result need not be in the range of values of any
       // integer type.
-      unsigned Diag = Self.getLangOpts().MicrosoftExt
-                          ? diag::ext_ms_pointer_to_int_cast
-                          : SrcType->isVoidPointerType()
-                                ? diag::warn_void_pointer_to_int_cast
-                                : diag::warn_pointer_to_int_cast;
+      unsigned Diag;
+      if (Self.getLangOpts().MicrosoftExt)
+        Diag = diag::ext_ms_pointer_to_int_cast;
+      else if (SrcType->isVoidPointerType())
+        Diag = DestType->isEnumeralType() ? diag::warn_void_pointer_to_enum_cast
+                                          : diag::warn_void_pointer_to_int_cast;
+      else if (DestType->isEnumeralType())
+        Diag = diag::warn_pointer_to_enum_cast;
+      else
+        Diag = diag::warn_pointer_to_int_cast;
       Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange;
     }
   }

diff  --git a/clang/test/Sema/cast.c b/clang/test/Sema/cast.c
index 0c4fc7d129fc..2335f2198071 100644
--- a/clang/test/Sema/cast.c
+++ b/clang/test/Sema/cast.c
@@ -186,3 +186,23 @@ void *intToPointerCast2(X x) {
 void *intToPointerCast3() {
   return (void*)(1 + 3);
 }
+
+void voidPointerToEnumCast(VoidPtr v) {
+  (void)(X) v; // expected-warning{{cast to smaller integer type 'X' from 'VoidPtr' (aka 'void *')}}
+  // Test that casts to void* can be controlled separately
+  // from other -Wpointer-to-enum-cast warnings.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wvoid-pointer-to-enum-cast"
+  (void)(X) v; // no-warning
+#pragma clang diagnostic pop
+}
+
+void pointerToEnumCast(CharPtr v) {
+  (void)(X) v; // expected-warning{{cast to smaller integer type 'X' from 'CharPtr' (aka 'char *')}}
+  // Test that casts to void* can be controlled separately
+  // from other -Wpointer-to-enum-cast warnings.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wvoid-pointer-to-enum-cast"
+  (void)(X) v; // expected-warning{{cast to smaller integer type 'X' from 'CharPtr' (aka 'char *')}}
+#pragma clang diagnostic pop
+}


        


More information about the cfe-commits mailing list