diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/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, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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; +def warn_pointer_to_enum_cast : Warning< + "cast to smaller integer type %1 from %0">, + InGroup; def warn_void_pointer_to_int_cast : Warning< "cast to smaller integer type %1 from %0">, InGroup; +def warn_void_pointer_to_enum_cast : Warning< + "cast to smaller integer type %1 from %0">, + InGroup; def ext_ms_pointer_to_int_cast : ExtWarn< "cast to smaller integer type %1 from %0 is a Microsoft extension">, InGroup; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/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; } } diff --git a/clang/test/Sema/cast.c b/clang/test/Sema/cast.c --- a/clang/test/Sema/cast.c +++ b/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 +}