diff --git a/src/pending_changes/gh-472-c-deep-qualification-conversion.txt b/src/pending_changes/gh-472-c-deep-qualification-conversion.txt new file mode 100644 index 0000000000..6e3057afcd --- /dev/null +++ b/src/pending_changes/gh-472-c-deep-qualification-conversion.txt @@ -0,0 +1,14 @@ +[GH #472] +C: pointer conversions adding qualifiers below the first level + +In C, the front end accepted an implicit conversion between pointer types +that adds type qualifiers below the first level, such as "int **" to +"const int *const *", without a diagnostic. Such a conversion is valid in +C++, but in C the types pointed to are not compatible, so it violates a +constraint and requires a diagnostic (C23 6.5.17.2). A warning is now +issued; the conversion is still accepted. For example: + + void f(int **p) { + const int *const *q; + q = p; // Now a warning. + } diff --git a/src/types.c b/src/types.c index 3e8a3aed1b..7394cb5b80 100644 --- a/src/types.c +++ b/src/types.c @@ -11687,6 +11687,11 @@ operators), 3.3.15 (?: operator), and 3.3.16.1 (simple assignment). std_conv->nontrivial_conversion = FALSE; std_conv->type_qualifiers_added = qualifiers_added; std_conv->warning_suggested = warning_suggested; + if (C_mode() && warning_suggested == ec_no_error) { + /* Even const-safe deep qualification conversions require a + diagnostic in C: the pointed-to types are incompatible. */ + std_conv->warning_suggested = default_warning_code; + } /* if */ qualifiers_checked = TRUE; } else if ((!suppress_extensions || any_cfront_mode()) && same_type_with_added_qualifiers( diff --git a/tests/tests/regressions/.c-deep-pointer-qualification-positive.rto/default.1.1.txt b/tests/tests/regressions/.c-deep-pointer-qualification-positive.rto/default.1.1.txt new file mode 100644 index 0000000000..89c79baec6 --- /dev/null +++ b/tests/tests/regressions/.c-deep-pointer-qualification-positive.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c --c23 --strict Test_name.c diff --git a/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.1.1.txt b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.1.1.txt new file mode 100644 index 0000000000..34bc9123fd --- /dev/null +++ b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.1.1.txt @@ -0,0 +1,5 @@ +fe_only -DTEST_NUMBER=1 --c --c23 --no_strict_gnu --gnu_version=130300 Test_name.c +"Test_name.c", line 11: warning: a value of type "int **" cannot be assigned to an entity of type "const int *const *" + q = p; + ^ + diff --git a/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.1.matches.txt b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.1.matches.txt new file mode 100644 index 0000000000..d494ed67e9 --- /dev/null +++ b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.1.matches.txt @@ -0,0 +1,4 @@ +Matches for "(?is)warning.*cannot be assigned to an entity of type": + <----------------------------------------------------------------------------- + warning: a value of type "int **" cannot be assigned to an entity of type + -----------------------------------------------------------------------------> diff --git a/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.2.1.txt b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.2.1.txt new file mode 100644 index 0000000000..6c9548e03e --- /dev/null +++ b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.2.1.txt @@ -0,0 +1,5 @@ +fe_only -DTEST_NUMBER=2 --c --c23 --strict_warnings Test_name.c +"Test_name.c", line 11: warning: a value of type "int **" cannot be assigned to an entity of type "const int *const *" + q = p; + ^ + diff --git a/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.2.matches.txt b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.2.matches.txt new file mode 100644 index 0000000000..d494ed67e9 --- /dev/null +++ b/tests/tests/regressions/.c-deep-pointer-qualification.rto/default.2.matches.txt @@ -0,0 +1,4 @@ +Matches for "(?is)warning.*cannot be assigned to an entity of type": + <----------------------------------------------------------------------------- + warning: a value of type "int **" cannot be assigned to an entity of type + -----------------------------------------------------------------------------> diff --git a/tests/tests/regressions/.cpp-deep-pointer-qualification.rto/default.1.1.txt b/tests/tests/regressions/.cpp-deep-pointer-qualification.rto/default.1.1.txt new file mode 100644 index 0000000000..8d2436f20d --- /dev/null +++ b/tests/tests/regressions/.cpp-deep-pointer-qualification.rto/default.1.1.txt @@ -0,0 +1,5 @@ +fe_only -DTEST_NUMBER=1 --c++20 --strict Test_name.c +"Test_name.c", line 6: warning: variable "q" was set but never used + const int *const* q = p; + ^ + diff --git a/tests/tests/regressions/c-deep-pointer-qualification-positive.sft.c b/tests/tests/regressions/c-deep-pointer-qualification-positive.sft.c new file mode 100644 index 0000000000..5fb85852b6 --- /dev/null +++ b/tests/tests/regressions/c-deep-pointer-qualification-positive.sft.c @@ -0,0 +1,16 @@ +//type:fp +//options_all:--c --c23 --strict + +void add_first_level_const(int **p) +{ + int *const* q = p; + + (void)q; +} + +void explicit_deep_qualification(int **p) +{ + const int *const* q = (const int *const* )p; + + (void)q; +} diff --git a/tests/tests/regressions/c-deep-pointer-qualification.sft.c b/tests/tests/regressions/c-deep-pointer-qualification.sft.c new file mode 100644 index 0000000000..72b131abbd --- /dev/null +++ b/tests/tests/regressions/c-deep-pointer-qualification.sft.c @@ -0,0 +1,13 @@ +//type:fp +//options_all:--c --c23 +//options:--no_strict_gnu --gnu_version=130300:--strict_warnings +//match_regex:(?is)warning.*cannot be assigned to an entity of type + +void deep_pointer_qualification(int **p) +{ + const int *const* q; + + /* C++ permits this conversion, but C requires a diagnostic. */ + q = p; + (void)q; +} diff --git a/tests/tests/regressions/cpp-deep-pointer-qualification.sft.cpp b/tests/tests/regressions/cpp-deep-pointer-qualification.sft.cpp new file mode 100644 index 0000000000..d5f50c70df --- /dev/null +++ b/tests/tests/regressions/cpp-deep-pointer-qualification.sft.cpp @@ -0,0 +1,9 @@ +//type:fp +//options_all:--c++20 --strict + +void add_deep_const(int **p) +{ + const int *const* q = p; + + (void)q; +}