Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -717,6 +717,7 @@ def InvalidPPToken : DiagGroup<"invalid-pp-token">; def Trigraphs : DiagGroup<"trigraphs">; +def HiddenReinterpretCast : DiagGroup<"hidden-reinterpret-cast">; def UndefinedReinterpretCast : DiagGroup<"undefined-reinterpret-cast">; def ReinterpretBaseClass : DiagGroup<"reinterpret-base-class">; def Unicode : DiagGroup<"unicode">; Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7402,6 +7402,10 @@ "use 'static_cast' to adjust the pointer correctly while " "%select{upcasting|downcasting}0">; +def warn_cxx_functional_style_cast_hidden_reinterpret_cast: Warning< + "C++ functional style cast may be a hidden reinterpret cast">, + InGroup, DefaultIgnore; + def err_bad_static_cast_overload : Error< "address of overloaded function %0 cannot be static_cast to type %1">; Index: clang/lib/Sema/SemaCast.cpp =================================================================== --- clang/lib/Sema/SemaCast.cpp +++ clang/lib/Sema/SemaCast.cpp @@ -2760,6 +2760,15 @@ // ... and finally a reinterpret_cast, ignoring const and addr space. tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/ true, OpRange, msg, Kind); + + // If this CXX Functional cast is a reinterpret cast then we have a + // potentially hidden reinterpret cast here. + if (isValidCast(tcr)) { + Self.Diag( + OpRange.getBegin(), + diag::warn_cxx_functional_style_cast_hidden_reinterpret_cast); + } + if (SrcExpr.isInvalid()) return; } Index: clang/test/SemaCXX/hidden_reinterpret_test.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/hidden_reinterpret_test.cpp @@ -0,0 +1,64 @@ +// Check that various conversions from integral to pointer to references +// generate an appropriate hidden-reinterpret-cast diagnostic. + +// RUN: %clang_cc1 -verify %s -Whidden-reinterpret-cast + +class castee { +public: + int i; +}; + +class caster { +public: + caster(castee tbc): + i(tbc.i) {} +private: + int i; +}; + +int main() { + using long_def = long long; + using long_ptr = long long*; + using long_ref = long long&; + + // Check pointer to int conversion for reinterpret warning. + long_ptr ptr = 0x0; + long_def new_num = long_def(ptr); // expected-warning {{C++ functional style cast may be a hidden reinterpret cast}} + + // Check int to pointer conversion for reinterpret warning. + long_def strange_address = 0xDEADBEEF; + long_ptr strange_ptr = long_ptr(strange_address); // expected-warning {{C++ functional style cast may be a hidden reinterpret cast}} + + // Check pointer to reference conversion for reinterpret warning. + long_ptr ptr_to_ref = 0x0; + long_ref ref_of_ptr = long_ref(ptr_to_ref); // expected-warning {{C++ functional style cast may be a hidden reinterpret cast}} + + // Check reference to pointer conversion, should not provide a warning + long_def to_ref = 50; + long_ref ref_to_ptr = to_ref; + // "long_ptr(ptr_from_ref)" is synonymous with "long_ptr(&to_ref)" and + // should not generate a warning. + long_ptr ptr_from_ref = long_ptr(ptr_from_ref); + + // implicit conversions and therefore static_casts, should not generate + // warnings. + float f = 1.5f; + int i = int(f); + + unsigned long int uli = 50; + char c = char(uli); + + long long int value = 50; + long long int &iref = value; + long long int iNotRef = long_def(iref); + + int small = 500; + long long int big = long_def(small); + + // class conversion test, this will call the constructor of to_static_cast + // shouldn't generate a warning. + castee c1; + caster c2 = caster(c1); + + return 0; +} Index: clang/test/SemaCXX/hidden_reinterpret_test_template.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/hidden_reinterpret_test_template.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -verify %s -Whidden-reinterpret-cast + +template +T find(T obj[], T key, unsigned long int size) { + using X = decltype(obj[0]); + for (T *ix = 0; ix != obj+size; ++ix) { + if ((*ix) == key) + return X(ix); // expected-warning {{C++ functional style cast may be a hidden reinterpret cast}} + } + return X(key); +} + +int main(const int argc, const char *argv[]) { + int array[] = {0, 1, 2, 3}; + int *array_ptrs[] = {&(array[0]), &(array[1]), &(array[2]), &(array[3])}; + int *key = &(array[2]); + find(array_ptrs, key, sizeof(array_ptrs)); // expected-note {{in instantiation of function template specialization 'find' requested here}} + return *key; +}