diff --git a/src/pending_changes/edg-28892-pointer-integer-cast.txt b/src/pending_changes/edg-28892-pointer-integer-cast.txt new file mode 100644 index 0000000000..4fb2edabc2 --- /dev/null +++ b/src/pending_changes/edg-28892-pointer-integer-cast.txt @@ -0,0 +1,5 @@ +[GH #454] +Reject C++ pointer casts to undersized integers + +In GNU C++ mode, pointer-to-integer reinterpret_cast conversions now +require a destination type large enough to hold the pointer value. diff --git a/src/types.c b/src/types.c index 3e8a3aed1b..fd152ff12b 100644 --- a/src/types.c +++ b/src/types.c @@ -14037,14 +14037,14 @@ well as C++ mode. ) || (is_nullptr(source_type) && !source_type->incomplete)) && is_integral(dest_type) && - (C_mode() || ms_extensions || gpp_mode || + (C_mode() || ms_extensions || dest_of_ptr_cast_big_enough(source_type, dest_type))) { /* Pointer or std::nullptr_t (but not the managed nullptr type, identified by being incomplete) --> integral is okay -- In C mode, always (size of destination is not an issue; see 6.3.4 in the ISO C89 standard) -- In C++ mode, if (a) the integer is big enough or (b) it's - not big enough but we're compiling in Microsoft or GNU mode. */ + not big enough but we're compiling in Microsoft mode. */ okay = TRUE; if (!dest_of_ptr_cast_big_enough(source_type, dest_type)) { /* The destination is not large enough to hold all of the bits diff --git a/tests/tests/regressions/edg-28892-positive.sft.cpp b/tests/tests/regressions/edg-28892-positive.sft.cpp new file mode 100644 index 0000000000..70c82267ac --- /dev/null +++ b/tests/tests/regressions/edg-28892-positive.sft.cpp @@ -0,0 +1,6 @@ +//type:fp +//options_all:--c++20 +//options:--g++ --gnu_version=130300:--strict +using size_type = decltype(sizeof(0)); +static_assert(sizeof(size_type) >= sizeof(void*), "pointer width"); +size_type wide(void *p) { return reinterpret_cast(p); } diff --git a/tests/tests/regressions/edg-28892.sft.cpp b/tests/tests/regressions/edg-28892.sft.cpp new file mode 100644 index 0000000000..d022777a7b --- /dev/null +++ b/tests/tests/regressions/edg-28892.sft.cpp @@ -0,0 +1,11 @@ +//type:fn +//options_all:--c++20 +//options:--g++ --gnu_version=130300:--g++ --gnu_version=150200:--strict +// A pointer-to-integer reinterpret_cast requires sufficient destination width. +static_assert(sizeof(void*) > sizeof(unsigned char), "pointer width"); +unsigned char narrow_object(void *p) { + return reinterpret_cast(p); // Must be an error in GNU mode. +} +unsigned char narrow_function(void (*p)()) { + return reinterpret_cast(p); // Must also be an error. +}