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
14 changes: 14 additions & 0 deletions src/pending_changes/gh-472-c-deep-qualification-conversion.txt
Original file line number Diff line number Diff line change
@@ -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.
}
5 changes: 5 additions & 0 deletions src/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 --c --c23 --strict Test_name.c
Original file line number Diff line number Diff line change
@@ -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;
^

Original file line number Diff line number Diff line change
@@ -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
----------------------------------------------------------------------------->
Original file line number Diff line number Diff line change
@@ -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;
^

Original file line number Diff line number Diff line change
@@ -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
----------------------------------------------------------------------------->
Original file line number Diff line number Diff line change
@@ -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;
^

Original file line number Diff line number Diff line change
@@ -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;
}
13 changes: 13 additions & 0 deletions tests/tests/regressions/c-deep-pointer-qualification.sft.c
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//type:fp
//options_all:--c++20 --strict

void add_deep_const(int **p)
{
const int *const* q = p;

(void)q;
}
Loading