Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/pending_changes/edg-28892-pointer-integer-cast.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[GH #454]
GNU C++ mode: casts of pointers to integer types that are too small

In GNU C++ mode (including Clang mode), a cast of a pointer to an integer type
too small to hold all of its bits was accepted with a warning. GCC 4.0 and
later, and Clang, reject such casts, and the standard requires a diagnostic.
They are now errors, except when emulating GCC versions before 4.0, which
accepted them with a warning. For example, with --g++ on a target with 64-bit
pointers:

unsigned char narrow(void *p) {
return reinterpret_cast<unsigned char>(p); // Now an error.
}
6 changes: 4 additions & 2 deletions src/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -14037,14 +14037,16 @@ 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 || gpp_version_is(<40000) ||
dest_of_ptr_cast_big_enough(source_type, dest_type))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tracked down why that gpp_mode is there. It's for this test case:

int main()
{
        int *ptr;
        int x;

        x = (int)ptr;
        x = (short)ptr;  // warning in gcc 3.4.6

        return 0;
}

Prior to GCC 4, this was accepted with a warning (https://godbolt.org/z/fG4YcKKr9).
Note that your test case was not accepted even then.
Rather than emulating this 100% accurately, I'd just replace the gpp_mode by gpp_version_is(<40000). That way any pre-GCC-4 code out there that relies on the leniency will continue to work (which should not be a whole lot), and modern code will track GCC 4+.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tracking that down. I replaced gpp_mode with gpp_version_is(<40000), so Clang mode and GNU C++ 4.0 and later now give the error. regressions/edg-28892-legacy is your example with --gnu_version=30406: (int)ptr and (short)ptr are accepted with a warning.

/* 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 or
emulating a GNU C++ version before 4.0 (which accepted such
casts with a warning). */
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
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/edg_x86_32/imported.log
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,7 @@ gnu/cpp/other/pr49133.sft.cpp:rp:-DTEST_NUMBER=1:FAIL(COMPILE):
gnu/cpp/other/profile1.sft.cpp:rp:-DTEST_NUMBER=1:CATASTROPHE(COMPILE):
gnu/cpp/other/ucnid-1-utf8.sft.cpp:rp:-DTEST_NUMBER=1:FAIL(COMPILE):
gnu/cpp/other/ucnid-1.sft.cpp:rp:-DTEST_NUMBER=1:FAIL(COMPILE):
gnu/cpp/parse/cast1.sft.cpp:fp:-DTEST_NUMBER=1 -w:PASS:
gnu/cpp/parse/lookup1.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/parse/offsetof2.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/parse/offsetof3.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/edg_x86_32_cp/imported.log
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,7 @@ gnu/cpp/other/ucnid-1-utf8.sft.cpp:rp:-DTEST_NUMBER=1:FAIL(COMPILE):
gnu/cpp/other/ucnid-1.sft.cpp:rp:-DTEST_NUMBER=1:FAIL(COMPILE):
gnu/cpp/overload/defarg5.sft.cpp:fn:-DTEST_NUMBER=1:ABORT:
gnu/cpp/overload/volatile2.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/parse/cast1.sft.cpp:fp:-DTEST_NUMBER=1 -w:PASS:
gnu/cpp/parse/crash30.sft.cpp:fn:-DTEST_NUMBER=1:PASS:
gnu/cpp/parse/crash75.sft.cpp:fn:-DTEST_NUMBER=1:PASS:
gnu/cpp/parse/defarg5.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/edg_x86_64/imported.log
Original file line number Diff line number Diff line change
Expand Up @@ -8658,6 +8658,7 @@ gnu/cpp/parse/ambig14.sft.cpp:fp:-DTEST_NUMBER=1 --c++11:FAIL:
gnu/cpp/parse/array-size2.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/parse/attr3.sft.cpp:fn:-DTEST_NUMBER=1 --c++23 --c++20:FAIL:
gnu/cpp/parse/bitfield5.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/parse/cast1.sft.cpp:fp:-DTEST_NUMBER=1 -w:FAIL:
gnu/cpp/parse/concat1.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/parse/constructor2.sft.cpp:fn:-DTEST_NUMBER=1 --c++20:FAIL:
gnu/cpp/parse/constructor3.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
Expand Down Expand Up @@ -8885,7 +8886,6 @@ gnu/cpp/template/redecl2.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/template/repo3.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/template/sfinae-dr657.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/template/sfinae11.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/template/sfinae13.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
gnu/cpp/template/sfinae3.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/template/shadow2.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
gnu/cpp/template/sizeof11.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
enum E : T::type {}; // expected-error{{missing 'typename'}}
^

"Test_name.c", line 184: warning: conversion from pointer to smaller integer
"Test_name.c", line 184: error: invalid type conversion
friend X::X(T::type = (int)(void(*)(typename T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}}
^

"Test_name.c", line 185: error: nontype "T::type" is not a type name
friend X::X(T::type = (int)(void(*)(T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} \
^

"Test_name.c", line 185: warning: conversion from pointer to smaller integer
"Test_name.c", line 185: error: invalid type conversion
friend X::X(T::type = (int)(void(*)(T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} \
^

Expand Down Expand Up @@ -105,4 +105,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
const auto *ConstCast = const_cast<const T::type *>(Ptr);
^

20 errors detected in the compilation of "Test_name.c".
22 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
enum E : T::type {}; // expected-error{{missing 'typename'}}
^

"Test_name.c", line 184: warning: conversion from pointer to smaller integer
"Test_name.c", line 184: error: invalid type conversion
friend X::X(T::type = (int)(void(*)(typename T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}}
^

"Test_name.c", line 185: error: nontype "T::type" is not a type name
friend X::X(T::type = (int)(void(*)(T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} \
^

"Test_name.c", line 185: warning: conversion from pointer to smaller integer
"Test_name.c", line 185: error: invalid type conversion
friend X::X(T::type = (int)(void(*)(T::type))(nullptr)); // expected-error {{friend declaration specifying a default argument must be a definition}} \
^

Expand All @@ -105,4 +105,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
^
detected during instantiation of class "GH113324::S2<T> [with T=void]" at line 207

20 errors detected in the compilation of "Test_name.c".
22 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
(void)(int A::*)((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}}
^

"Test_name.c", line 181: warning: conversion from pointer to smaller integer
"Test_name.c", line 181: error: invalid type conversion
(void)(char)(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}}
^

"Test_name.c", line 186: warning: conversion from pointer to smaller integer
"Test_name.c", line 186: error: invalid type conversion
(void)(char)((void*)0); // expected-error {{cast from pointer to smaller type 'char' loses information}}
^

"Test_name.c", line 187: warning: conversion from pointer to smaller integer
"Test_name.c", line 187: error: invalid type conversion
(void)(char)((int*)0); // expected-error {{cast from pointer to smaller type 'char' loses information}}
^

Expand All @@ -75,4 +75,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
(void)(int structure::*)(psf); // expected-error-re {{C-style cast from 'void (structure::*)(){{( __attribute__\(\(thiscall\)\))?}}' to 'int structure::*' is not allowed}}
^

12 errors detected in the compilation of "Test_name.c".
15 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
(void)Amp((int F::*)0); // expected-error {{conversion from pointer to member of class 'F' to pointer to member of class 'A' via virtual base 'B' is not allowed}}
^

"Test_name.c", line 245: warning: conversion from pointer to smaller integer
"Test_name.c", line 245: error: invalid type conversion
(void)char(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}}
^

Expand All @@ -114,4 +114,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
(void)int_ref(); // expected-error {{reference to type 'int' requires an initializer}}
^

19 errors detected in the compilation of "Test_name.c".
20 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
(void)&nullptr;
^

"SemaCXX/nullptr.cpp", line 68: warning: conversion from pointer to smaller integer
"SemaCXX/nullptr.cpp", line 68: error: invalid type conversion
(void)reinterpret_cast<char>(nullptr);
^

Expand Down Expand Up @@ -78,4 +78,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
void *q = null();
^

11 errors detected in the compilation of "Test_name.c".
12 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
const int ci = 0;
^

"SemaCXX/reinterpret-cast.cpp", line 45: warning: conversion from pointer to smaller integer
"SemaCXX/reinterpret-cast.cpp", line 45: error: invalid type conversion
(void)reinterpret_cast<char>(fnp);
^

Expand Down Expand Up @@ -123,4 +123,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
(void)*reinterpret_cast<const TARGETTYPE*>(data);
^

15 errors detected in the compilation of "Test_name.c".
16 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
const int ci = 0;
^

"SemaCXX/reinterpret-cast.cpp", line 45: warning: conversion from pointer to smaller integer
"SemaCXX/reinterpret-cast.cpp", line 45: error: invalid type conversion
(void)reinterpret_cast<char>(fnp);
^

Expand Down Expand Up @@ -147,4 +147,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
const int data[size];
^

15 errors detected in the compilation of "Test_name.c".
16 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
const int ci = 0;
^

"SemaCXX/reinterpret-cast.cpp", line 45: warning: conversion from pointer to smaller integer
"SemaCXX/reinterpret-cast.cpp", line 45: error: invalid type conversion
(void)reinterpret_cast<char>(fnp);
^

Expand Down Expand Up @@ -147,4 +147,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
const int data[size];
^

15 errors detected in the compilation of "Test_name.c".
16 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
extern __unknown_anytype test1(...);
^

"Test_name.c", line 46: warning: conversion from pointer to smaller integer
"Test_name.c", line 46: error: invalid type conversion
int x = (int) test1; // expected-error {{function 'test1' with unknown type must be given a function type}}
^

Expand All @@ -55,4 +55,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
extern __unknown_anytype var;
^

13 errors detected in the compilation of "Test_name.c".
14 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_d
const int n4 = static_cast<const int>(nullptr); // { dg-error "16:invalid 'static_cast' " }
^

"Test_name.c", line 10: warning: conversion from pointer to smaller integer
"Test_name.c", line 10: error: invalid type conversion
const short int n5 = reinterpret_cast<short int>(nullptr); // { dg-error "22:cast from .std::nullptr_t. to .short int. loses precision" "" { target { ! ptr_eq_short } } }
^

Expand All @@ -19,7 +19,7 @@ fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_d
const int n8 = static_cast<const int>(mynull); // { dg-error "16:invalid 'static_cast' " }
^

"Test_name.c", line 16: warning: conversion from pointer to smaller integer
"Test_name.c", line 16: error: invalid type conversion
const short int n9 = reinterpret_cast<short int>(mynull); // { dg-error "22:cast from .std::nullptr_t. to .short int. loses precision" "" { target { ! ptr_eq_short } } }
^

Expand Down Expand Up @@ -55,4 +55,4 @@ fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_d
const intptr_t n11 = (intptr_t)mynull;
^

2 errors detected in the compilation of "Test_name.c".
4 errors detected in the compilation of "Test_name.c".
13 changes: 13 additions & 0 deletions tests/tests/imported/gnu/cpp/parse/.cast1.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_diagnostics -w Test_name.c
"./parse/cast1.C", line 8: error: invalid type conversion
(int((char*)0));
^

"./parse/cast1.C", line 9: error: invalid type conversion
sizeof ((int((char*)0)));
^

"./parse/cast1.C", line 10: error: invalid type conversion
typeid ((int((char*)0)));
^

3 errors detected in the compilation of "Test_name.c".
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_diagnostics -w Test_name.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_diagnostics -w Test_name.c
Original file line number Diff line number Diff line change
@@ -1,24 +1 @@
fe_only -DTEST_NUMBER=1 --gnu_version=999999 -tused -e 200 --no_wrap --no_wrap_diagnostics Test_name.c
"Test_name.c", line 59: warning: conversion from pointer to smaller integer
CHECK_CAST(reinterpret);
^
detected during:
instantiation of "check_reinterpret_cast" based on template arguments <void *, char> at line 59
instantiation of class "has_reinterpret_cast<T, U> [with T=void *, U=char]" at line 83

"Test_name.c", line 83: error: static assertion failed with "!(has_reinterpret_cast<void*, char>::value)"
STATIC_ASSERT(!(has_reinterpret_cast<void*, char>::value));
^

"Test_name.c", line 38: warning: conversion from pointer to smaller integer
typename enable_if<(sizeof(((U)create_a<T>()), 0) > 0), yes_type>::type
^
detected during:
instantiation of "check_c_cast" based on template arguments <void *, char> at line 47
instantiation of class "has_c_cast<T, U> [with T=void *, U=char]" at line 88

"Test_name.c", line 88: error: static assertion failed with "!(has_c_cast<void*, char>::value)"
STATIC_ASSERT(!(has_c_cast<void*, char>::value));
^

2 errors detected in the compilation of "Test_name.c".

This file was deleted.

This file was deleted.

9 changes: 9 additions & 0 deletions tests/tests/regressions/.edg-28892-legacy.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fe_only -DTEST_NUMBER=1 --g++ --gnu_version=30406 Test_name.c
"Test_name.c", line 11: warning: conversion from pointer to smaller integer
x = (int)ptr;
^

"Test_name.c", line 12: warning: conversion from pointer to smaller integer
x = (short)ptr;
^

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fe_only -DTEST_NUMBER=1 --g++ --gnu_version=30406 Test_name.c
"Test_name.c", line 12: warning: conversion from pointer to smaller integer
x = (short)ptr;
^

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fe_only -DTEST_NUMBER=1 --g++ --gnu_version=30406 Test_name.c
"Test_name.c", line 12: warning: conversion from pointer to smaller integer
x = (short)ptr;
^

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 --c++20 --g++ --gnu_version=130300 Test_name.c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=2 --c++20 --strict Test_name.c
10 changes: 10 additions & 0 deletions tests/tests/regressions/.edg-28892.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fe_only -DTEST_NUMBER=1 --c++20 --g++ --gnu_version=130300 Test_name.c
"Test_name.c", line 7: error: invalid type conversion
return reinterpret_cast<unsigned char>(p); // Must be an error in GNU mode.
^

"Test_name.c", line 10: error: invalid type conversion
return reinterpret_cast<unsigned char>(p); // Must also be an error.
^

2 errors detected in the compilation of "Test_name.c".
10 changes: 10 additions & 0 deletions tests/tests/regressions/.edg-28892.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fe_only -DTEST_NUMBER=2 --c++20 --g++ --gnu_version=150200 Test_name.c
"Test_name.c", line 7: error: invalid type conversion
return reinterpret_cast<unsigned char>(p); // Must be an error in GNU mode.
^

"Test_name.c", line 10: error: invalid type conversion
return reinterpret_cast<unsigned char>(p); // Must also be an error.
^

2 errors detected in the compilation of "Test_name.c".
Loading
Loading