nathanchance created this revision. nathanchance added reviewers: Mordante, rjmccall. Herald added a project: clang.
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 allowst 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 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D75758 Files: clang/include/clang/Basic/DiagnosticGroups.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaCast.cpp clang/test/Sema/cast.c Index: clang/test/Sema/cast.c =================================================================== --- clang/test/Sema/cast.c +++ clang/test/Sema/cast.c @@ -186,3 +186,23 @@ 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 +} Index: clang/lib/Sema/SemaCast.cpp =================================================================== --- clang/lib/Sema/SemaCast.cpp +++ clang/lib/Sema/SemaCast.cpp @@ -2777,11 +2777,18 @@ // 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()) + if (DestType->isEnumeralType()) + Diag = diag::warn_void_pointer_to_enum_cast; + else + Diag = 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; } } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3669,9 +3669,15 @@ def warn_pointer_to_int_cast : Warning< "cast to smaller integer type %1 from %0">, InGroup<PointerToIntCast>; +def warn_pointer_to_enum_cast : Warning< + "cast to smaller integer type %1 from %0">, + 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< + "cast to smaller integer type %1 from %0">, + InGroup<VoidPointerToEnumCast>; def ext_ms_pointer_to_int_cast : ExtWarn< "cast to smaller integer type %1 from %0 is a Microsoft extension">, InGroup<MicrosoftCast>; Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -838,9 +838,13 @@ 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,
Index: clang/test/Sema/cast.c =================================================================== --- clang/test/Sema/cast.c +++ clang/test/Sema/cast.c @@ -186,3 +186,23 @@ 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 +} Index: clang/lib/Sema/SemaCast.cpp =================================================================== --- clang/lib/Sema/SemaCast.cpp +++ clang/lib/Sema/SemaCast.cpp @@ -2777,11 +2777,18 @@ // 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()) + if (DestType->isEnumeralType()) + Diag = diag::warn_void_pointer_to_enum_cast; + else + Diag = 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; } } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3669,9 +3669,15 @@ def warn_pointer_to_int_cast : Warning< "cast to smaller integer type %1 from %0">, InGroup<PointerToIntCast>; +def warn_pointer_to_enum_cast : Warning< + "cast to smaller integer type %1 from %0">, + 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< + "cast to smaller integer type %1 from %0">, + InGroup<VoidPointerToEnumCast>; def ext_ms_pointer_to_int_cast : ExtWarn< "cast to smaller integer type %1 from %0 is a Microsoft extension">, InGroup<MicrosoftCast>; Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -838,9 +838,13 @@ 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,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits