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 @@ -2204,13 +2204,19 @@ // C++ 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it; except in Microsoft mode, where the // integral type size doesn't matter (except we don't allow bool). - bool MicrosoftException = Self.getLangOpts().MicrosoftExt && - !DestType->isBooleanType(); if ((Self.Context.getTypeSize(SrcType) > - Self.Context.getTypeSize(DestType)) && - !MicrosoftException) { - msg = diag::err_bad_reinterpret_cast_small_int; - return TC_Failed; + Self.Context.getTypeSize(DestType))) { + bool MicrosoftException = + Self.getLangOpts().MicrosoftExt && !DestType->isBooleanType(); + if (MicrosoftException) { + unsigned Diag = SrcType->isVoidPointerType() + ? diag::warn_void_pointer_to_int_cast + : diag::warn_pointer_to_int_cast; + Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange; + } else { + msg = diag::err_bad_reinterpret_cast_small_int; + return TC_Failed; + } } Kind = CK_PointerToIntegral; return TC_Success; diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -200,17 +200,31 @@ static const int static_var = 3; // expected-warning {{redeclaring non-static 'static_var' as static is a Microsoft extension}} void pointer_to_integral_type_conv(char* ptr) { - char ch = (char)ptr; - short sh = (short)ptr; - ch = (char)ptr; - sh = (short)ptr; + char ch = (char)ptr; // expected-warning {{cast to smaller integer type 'char' from 'char *'}} + short sh = (short)ptr; // expected-warning {{cast to smaller integer type 'short' from 'char *'}} + ch = (char)ptr; // expected-warning {{cast to smaller integer type 'char' from 'char *'}} + sh = (short)ptr; // expected-warning {{cast to smaller integer type 'short' from 'char *'}} - // These are valid C++. - bool b = (bool)ptr; - b = static_cast(ptr); + // These are valid C++. + bool b = (bool)ptr; + b = static_cast(ptr); - // This is bad. - b = reinterpret_cast(ptr); // expected-error {{cast from pointer to smaller type 'bool' loses information}} + // This is bad. + b = reinterpret_cast(ptr); // expected-error {{cast from pointer to smaller type 'bool' loses information}} +} + +void void_pointer_to_integral_type_conv(void *ptr) { + char ch = (char)ptr; // expected-warning {{cast to smaller integer type 'char' from 'void *'}} + short sh = (short)ptr; // expected-warning {{cast to smaller integer type 'short' from 'void *'}} + ch = (char)ptr; // expected-warning {{cast to smaller integer type 'char' from 'void *'}} + sh = (short)ptr; // expected-warning {{cast to smaller integer type 'short' from 'void *'}} + + // These are valid C++. + bool b = (bool)ptr; + b = static_cast(ptr); + + // This is bad. + b = reinterpret_cast(ptr); // expected-error {{cast from pointer to smaller type 'bool' loses information}} } struct PR11150 {