Skip to content

Commit 2a41b31

Browse files
nathanchanceMaskRay
authored andcommitted
[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: ClangBuiltLinux/linux#887 Reviewed By: rjmccall Differential Revision: https://reviews.llvm.org/D75758
1 parent d81d451 commit 2a41b31

4 files changed

Lines changed: 42 additions & 7 deletions

File tree

‎clang/include/clang/Basic/DiagnosticGroups.td‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -838,9 +838,13 @@ def IncompatibleExceptionSpec : DiagGroup<"incompatible-exception-spec">;
838838
def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
839839
def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
840840
[IntToVoidPointerCast]>;
841-
def VoidPointerToIntCast : DiagGroup<"void-pointer-to-int-cast">;
841+
def VoidPointerToEnumCast : DiagGroup<"void-pointer-to-enum-cast">;
842+
def VoidPointerToIntCast : DiagGroup<"void-pointer-to-int-cast",
843+
[VoidPointerToEnumCast]>;
844+
def PointerToEnumCast : DiagGroup<"pointer-to-enum-cast",
845+
[VoidPointerToEnumCast]>;
842846
def PointerToIntCast : DiagGroup<"pointer-to-int-cast",
843-
[VoidPointerToIntCast]>;
847+
[PointerToEnumCast, VoidPointerToIntCast]>;
844848

845849
def Move : DiagGroup<"move", [
846850
PessimizingMove,

‎clang/include/clang/Basic/DiagnosticSemaKinds.td‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3668,9 +3668,15 @@ def warn_int_to_void_pointer_cast : Warning<
36683668
def warn_pointer_to_int_cast : Warning<
36693669
"cast to smaller integer type %1 from %0">,
36703670
InGroup<PointerToIntCast>;
3671+
def warn_pointer_to_enum_cast : Warning<
3672+
warn_pointer_to_int_cast.Text>,
3673+
InGroup<PointerToEnumCast>;
36713674
def warn_void_pointer_to_int_cast : Warning<
36723675
"cast to smaller integer type %1 from %0">,
36733676
InGroup<VoidPointerToIntCast>;
3677+
def warn_void_pointer_to_enum_cast : Warning<
3678+
warn_void_pointer_to_int_cast.Text>,
3679+
InGroup<VoidPointerToEnumCast>;
36743680
def ext_ms_pointer_to_int_cast : ExtWarn<
36753681
"cast to smaller integer type %1 from %0 is a Microsoft extension">,
36763682
InGroup<MicrosoftCast>;

‎clang/lib/Sema/SemaCast.cpp‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2777,11 +2777,16 @@ void CastOperation::CheckCStyleCast() {
27772777
// If the result cannot be represented in the integer type, the behavior
27782778
// is undefined. The result need not be in the range of values of any
27792779
// integer type.
2780-
unsigned Diag = Self.getLangOpts().MicrosoftExt
2781-
? diag::ext_ms_pointer_to_int_cast
2782-
: SrcType->isVoidPointerType()
2783-
? diag::warn_void_pointer_to_int_cast
2784-
: diag::warn_pointer_to_int_cast;
2780+
unsigned Diag;
2781+
if (Self.getLangOpts().MicrosoftExt)
2782+
Diag = diag::ext_ms_pointer_to_int_cast;
2783+
else if (SrcType->isVoidPointerType())
2784+
Diag = DestType->isEnumeralType() ? diag::warn_void_pointer_to_enum_cast
2785+
: diag::warn_void_pointer_to_int_cast;
2786+
else if (DestType->isEnumeralType())
2787+
Diag = diag::warn_pointer_to_enum_cast;
2788+
else
2789+
Diag = diag::warn_pointer_to_int_cast;
27852790
Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange;
27862791
}
27872792
}

‎clang/test/Sema/cast.c‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,23 @@ void *intToPointerCast2(X x) {
186186
void *intToPointerCast3() {
187187
return (void*)(1 + 3);
188188
}
189+
190+
void voidPointerToEnumCast(VoidPtr v) {
191+
(void)(X) v; // expected-warning{{cast to smaller integer type 'X' from 'VoidPtr' (aka 'void *')}}
192+
// Test that casts to void* can be controlled separately
193+
// from other -Wpointer-to-enum-cast warnings.
194+
#pragma clang diagnostic push
195+
#pragma clang diagnostic ignored "-Wvoid-pointer-to-enum-cast"
196+
(void)(X) v; // no-warning
197+
#pragma clang diagnostic pop
198+
}
199+
200+
void pointerToEnumCast(CharPtr v) {
201+
(void)(X) v; // expected-warning{{cast to smaller integer type 'X' from 'CharPtr' (aka 'char *')}}
202+
// Test that casts to void* can be controlled separately
203+
// from other -Wpointer-to-enum-cast warnings.
204+
#pragma clang diagnostic push
205+
#pragma clang diagnostic ignored "-Wvoid-pointer-to-enum-cast"
206+
(void)(X) v; // expected-warning{{cast to smaller integer type 'X' from 'CharPtr' (aka 'char *')}}
207+
#pragma clang diagnostic pop
208+
}

0 commit comments

Comments
 (0)