Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/error_msg.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3679,5 +3679,7 @@ ec_exp_interpolator;;"expected an interpolator (\"\\[\", \"\\[:\", \"\\{\", \"\\
ec_interpolated_id_is_not_identifier;;"%sq does not spell an identifier"
ec_interpolated_operand_is_not_token_sequence;;"the operand of a \"\\{...}\" interpolator is not a token sequence"
ec_tag_redefined_differently;;"this declaration of %n does not declare the same type as the declaration %p"
ec_array_comparison_deprecated;;"comparison between two arrays is deprecated"
ec_array_comparison_not_allowed;;"comparison between two arrays is not allowed"
###############################################################################

45 changes: 45 additions & 0 deletions src/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -32487,6 +32487,49 @@ different enum types (or, in C, have different affiliated enum types).
} /* diagnose_comparison_if_different_enum_types */


static a_boolean is_array_comparison_operand(an_operand *opnd)
/*
Return TRUE if opnd, an operand of a built-in equality or relational operator,
is an array: either it has array type, or it is a class operand that overload
resolution converted to an array and then to a pointer (e.g., through a
conversion function returning a reference to an array).
*/
{
a_boolean is_array = is_array_type(opnd->type);

if (!is_array && is_expression_operand(opnd)) {
an_expr_node_ptr expr = opnd->variant.expression;
is_array = is_operation_node(expr) &&
node_operator_is(expr, eok_array_to_pointer);
} /* if */
return is_array;
} /* is_array_comparison_operand */


static void check_for_array_comparison(an_operand *opnd1,
an_operand *opnd2,
a_source_position *operator_pos)
/*
opnd1 and opnd2 are the operands of a built-in equality or relational
operator at operator_pos, before the array-to-pointer conversion. If both
are arrays, issue a diagnostic: such comparisons are deprecated in C++20 and
not allowed in C++26 (P2865).
*/
{
if (cpp20_mode && is_array_comparison_operand(opnd1) &&
is_array_comparison_operand(opnd2)) {
if (cpp26_mode && !gpp_version_is(<150000) &&
!clangcpp_version_is(<200000)) {
/* GCC 15 and Clang 20 implement P2865. Earlier versions only issue a
deprecation warning. */
expr_pos_error(ec_array_comparison_not_allowed, operator_pos);
} else {
expr_pos_warning(ec_array_comparison_deprecated, operator_pos);
} /* if */
} /* if */
} /* check_for_array_comparison */


static void process_rel_operator(an_operand *opnd1,
an_operand *opnd2,
a_token_kind operator_token,
Expand Down Expand Up @@ -32532,6 +32575,7 @@ describe the location of the operator.
} /* if */
if (!processed) {
/* Non-operator-function cases. */
check_for_array_comparison(opnd1, opnd2, operator_pos);
/* The first operand must be an arithmetic or enum type or a pointer. */
do_operand_transformations(opnd1, TOPT_NO_OPTIONS);
opnd1_is_pointer = FALSE;
Expand Down Expand Up @@ -33036,6 +33080,7 @@ operator_tsn describe the location of the operator.
} /* if */
if (!processed) {
/* Non-operator-function cases. */
check_for_array_comparison(opnd1, opnd2, operator_pos);
/* The first operand must be an arithmetic or enum type or a pointer. */
do_operand_transformations(opnd1, TOPT_NO_OPTIONS);
if (is_arithmetic_or_enum_type(opnd1->type)) {
Expand Down
15 changes: 15 additions & 0 deletions src/pending_changes/gh-370-array-comparisons.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[GH #370]
C++26: comparison between two arrays is not allowed

A comparison between two arrays using an equality or relational operator is
deprecated in C++20 and not allowed in C++26 (P2865). The front end did not
diagnose it. It is now a warning in C++20 and C++23, and an error in C++26
(only a warning when emulating GCC versions before 15 or Clang versions before
20, which do the same). This includes class operands that are converted to
arrays by a conversion function. For example, with --c++26:

int a[2], b[2];
bool x = a == b; // Now an error.
bool y = a == &b[0]; // Okay: one operand is a pointer.
struct C { using A = int[2]; operator A &() const; } c;
bool z = c == c; // Now an error.
2 changes: 0 additions & 2 deletions tests/expectations/edg_x86_64/imported.log
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,6 @@ clang/cpp/SemaCXX/vtordisp-mode.sft.cpp:fp:-DTEST_NUMBER=3 --c++11 -DVTORDISP_MO
clang/cpp/SemaCXX/warn-array-comparion.sft.cpp:fn:-DTEST_NUMBER=1 --c++17:FAIL:
clang/cpp/SemaCXX/warn-array-comparion.sft.cpp:fn:-DTEST_NUMBER=2 --c++20:FAIL:
clang/cpp/SemaCXX/warn-array-comparion.sft.cpp:fn:-DTEST_NUMBER=3 --c++20:FAIL:
clang/cpp/SemaCXX/warn-array-comparion.sft.cpp:fn:-DTEST_NUMBER=4 --c++26:FAIL:
clang/cpp/SemaCXX/warn-bool-conversion.sft.cpp:fn:-DTEST_NUMBER=1 --c++03:FAIL:
clang/cpp/SemaCXX/warn-cast-function-type-strict.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
clang/cpp/SemaCXX/warn-cast-function-type.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
Expand All @@ -1453,7 +1452,6 @@ clang/cpp/SemaCXX/warn-memsize-comparison.sft.cpp:fn:-DTEST_NUMBER=1:FAIL:
clang/cpp/SemaCXX/warn-nrvo.sft.cpp:fp:-DTEST_NUMBER=1:FAIL:
clang/cpp/SemaCXX/warn-self-comparisons.sft.cpp:fn:-DTEST_NUMBER=1 --c++17:FAIL:
clang/cpp/SemaCXX/warn-self-comparisons.sft.cpp:fn:-DTEST_NUMBER=2 --c++20:FAIL:
clang/cpp/SemaCXX/warn-self-comparisons.sft.cpp:fn:-DTEST_NUMBER=3 --c++26:FAIL:
clang/cpp/SemaCXX/warn-static-const-float.sft.cpp:fn:-DTEST_NUMBER=1 --c++03 -DEXT --c++03 -DNONE --c++03 -DNONE --c++03 -DNONE:FAIL:
clang/cpp/SemaCXX/warn-static-const-float.sft.cpp:fn:-DTEST_NUMBER=2 --c++11 -DERR:FAIL:
clang/cpp/SemaCXX/warn-static-const-float.sft.cpp:fn:-DTEST_NUMBER=3 --c++11 -DERR:FAIL:
Expand Down
30 changes: 30 additions & 0 deletions tests/tests/changes/.GH370.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
fe_only -DTEST_NUMBER=1 --c++26 Test_name.c
"Test_name.c", line 10: error: comparison between two arrays is not allowed
bool x1 = a == b; // Two arrays: diagnosed.
^

"Test_name.c", line 11: error: comparison between two arrays is not allowed
bool x2 = a != b;
^

"Test_name.c", line 12: error: comparison between two arrays is not allowed
bool x3 = a < b;
^

"Test_name.c", line 13: error: comparison between two arrays is not allowed
bool x4 = a >= b;
^

"Test_name.c", line 22: error: comparison between two arrays is not allowed
bool z1 = c == c; // Two arrays: diagnosed.
^

"Test_name.c", line 23: error: comparison between two arrays is not allowed
bool z2 = c < c;
^

"Test_name.c", line 24: error: comparison between two arrays is not allowed
bool z3 = c == a;
^

7 errors detected in the compilation of "Test_name.c".
30 changes: 30 additions & 0 deletions tests/tests/changes/.GH370.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
fe_only -DTEST_NUMBER=2 --c++26 --gnu_version 150000 Test_name.c
"Test_name.c", line 10: error: comparison between two arrays is not allowed
bool x1 = a == b; // Two arrays: diagnosed.
^

"Test_name.c", line 11: error: comparison between two arrays is not allowed
bool x2 = a != b;
^

"Test_name.c", line 12: error: comparison between two arrays is not allowed
bool x3 = a < b;
^

"Test_name.c", line 13: error: comparison between two arrays is not allowed
bool x4 = a >= b;
^

"Test_name.c", line 22: error: comparison between two arrays is not allowed
bool z1 = c == c; // Two arrays: diagnosed.
^

"Test_name.c", line 23: error: comparison between two arrays is not allowed
bool z2 = c < c;
^

"Test_name.c", line 24: error: comparison between two arrays is not allowed
bool z3 = c == a;
^

7 errors detected in the compilation of "Test_name.c".
30 changes: 30 additions & 0 deletions tests/tests/changes/.GH370.rto/default.3.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
fe_only -DTEST_NUMBER=3 --c++26 --clang_version 200000 Test_name.c
"Test_name.c", line 10: error: comparison between two arrays is not allowed
bool x1 = a == b; // Two arrays: diagnosed.
^

"Test_name.c", line 11: error: comparison between two arrays is not allowed
bool x2 = a != b;
^

"Test_name.c", line 12: error: comparison between two arrays is not allowed
bool x3 = a < b;
^

"Test_name.c", line 13: error: comparison between two arrays is not allowed
bool x4 = a >= b;
^

"Test_name.c", line 22: error: comparison between two arrays is not allowed
bool z1 = c == c; // Two arrays: diagnosed.
^

"Test_name.c", line 23: error: comparison between two arrays is not allowed
bool z2 = c < c;
^

"Test_name.c", line 24: error: comparison between two arrays is not allowed
bool z3 = c == a;
^

7 errors detected in the compilation of "Test_name.c".
29 changes: 29 additions & 0 deletions tests/tests/changes/.GH370_a.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
fe_only -DTEST_NUMBER=1 --c++20 Test_name.c
"Test_name.c", line 12: warning: comparison between two arrays is deprecated
bool x1 = a == b; // Two arrays: diagnosed.
^

"Test_name.c", line 13: warning: comparison between two arrays is deprecated
bool x2 = a != b;
^

"Test_name.c", line 14: warning: comparison between two arrays is deprecated
bool x3 = a < b;
^

"Test_name.c", line 15: warning: comparison between two arrays is deprecated
bool x4 = a >= b;
^

"Test_name.c", line 24: warning: comparison between two arrays is deprecated
bool z1 = c == c; // Two arrays: diagnosed.
^

"Test_name.c", line 25: warning: comparison between two arrays is deprecated
bool z2 = c < c;
^

"Test_name.c", line 26: warning: comparison between two arrays is deprecated
bool z3 = c == a;
^

29 changes: 29 additions & 0 deletions tests/tests/changes/.GH370_a.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
fe_only -DTEST_NUMBER=2 --c++26 --gnu_version 140000 Test_name.c
"Test_name.c", line 12: warning: comparison between two arrays is deprecated
bool x1 = a == b; // Two arrays: diagnosed.
^

"Test_name.c", line 13: warning: comparison between two arrays is deprecated
bool x2 = a != b;
^

"Test_name.c", line 14: warning: comparison between two arrays is deprecated
bool x3 = a < b;
^

"Test_name.c", line 15: warning: comparison between two arrays is deprecated
bool x4 = a >= b;
^

"Test_name.c", line 24: warning: comparison between two arrays is deprecated
bool z1 = c == c; // Two arrays: diagnosed.
^

"Test_name.c", line 25: warning: comparison between two arrays is deprecated
bool z2 = c < c;
^

"Test_name.c", line 26: warning: comparison between two arrays is deprecated
bool z3 = c == a;
^

29 changes: 29 additions & 0 deletions tests/tests/changes/.GH370_a.rto/default.3.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
fe_only -DTEST_NUMBER=3 --c++26 --clang_version 190000 Test_name.c
"Test_name.c", line 12: warning: comparison between two arrays is deprecated
bool x1 = a == b; // Two arrays: diagnosed.
^

"Test_name.c", line 13: warning: comparison between two arrays is deprecated
bool x2 = a != b;
^

"Test_name.c", line 14: warning: comparison between two arrays is deprecated
bool x3 = a < b;
^

"Test_name.c", line 15: warning: comparison between two arrays is deprecated
bool x4 = a >= b;
^

"Test_name.c", line 24: warning: comparison between two arrays is deprecated
bool z1 = c == c; // Two arrays: diagnosed.
^

"Test_name.c", line 25: warning: comparison between two arrays is deprecated
bool z2 = c < c;
^

"Test_name.c", line 26: warning: comparison between two arrays is deprecated
bool z3 = c == a;
^

1 change: 1 addition & 0 deletions tests/tests/changes/.GH370_a.rto/default.4.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=4 --c++17 Test_name.c
28 changes: 28 additions & 0 deletions tests/tests/changes/GH370.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//type:fn
//options:--c++26:--c++26 --gnu_version 150000:--c++26 --clang_version 200000
//remark:[GH #370] C++26: comparison between two arrays is not allowed
//
// P2865 makes a comparison between two arrays ill-formed in C++26.

int a[2], b[2];
int *p = b;

bool x1 = a == b; // Two arrays: diagnosed.
bool x2 = a != b;
bool x3 = a < b;
bool x4 = a >= b;

bool y1 = a == p; // Array and pointer: not diagnosed.
bool y2 = p < a;

// Class operands converted to arrays by conversion functions.
struct C { using arr_t = int[2]; operator arr_t &() const; };
struct P { operator int *() const; };
void g(C c, P q) {
bool z1 = c == c; // Two arrays: diagnosed.
bool z2 = c < c;
bool z3 = c == a;
bool z4 = c == p; // Array and pointer: not diagnosed.
bool z5 = q == q; // Conversions to pointers: not diagnosed.
bool z6 = +c == +c; // Explicit decay: not diagnosed.
}
30 changes: 30 additions & 0 deletions tests/tests/changes/GH370_a.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//type:fp
//options:--c++20:--c++26 --gnu_version 140000:--c++26 --clang_version 190000:--c++17
//remark:[GH #370] Comparison between two arrays is deprecated in C++20
//
// A comparison between two arrays is deprecated in C++20 and C++23. When
// emulating GCC before 15 or Clang before 20, it is also only deprecated in
// C++26. Before C++20 it is not diagnosed.

int a[2], b[2];
int *p = b;

bool x1 = a == b; // Two arrays: diagnosed.
bool x2 = a != b;
bool x3 = a < b;
bool x4 = a >= b;

bool y1 = a == p; // Array and pointer: not diagnosed.
bool y2 = p < a;

// Class operands converted to arrays by conversion functions.
struct C { using arr_t = int[2]; operator arr_t &() const; };
struct P { operator int *() const; };
void g(C c, P q) {
bool z1 = c == c; // Two arrays: diagnosed.
bool z2 = c < c;
bool z3 = c == a;
bool z4 = c == p; // Array and pointer: not diagnosed.
bool z5 = q == q; // Conversions to pointers: not diagnosed.
bool z6 = +c == +c; // Explicit decay: not diagnosed.
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,26 @@ fe_only -DTEST_NUMBER=8 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
void trex(volatile short left_arm, volatile struct amber right_arm);
^

"SemaCXX/deprecated.cpp", line 256: warning: comparison between two arrays is deprecated
bool b1 = arr1 == arr2;
^

"SemaCXX/deprecated.cpp", line 258: warning: comparison between two arrays is deprecated
bool b2 = arr1 < arr2;
^

"SemaCXX/deprecated.cpp", line 261: warning: comparison between two arrays is deprecated
bool b3 = arr1 == arr3;
^

"SemaCXX/deprecated.cpp", line 262: warning: comparison between two arrays is deprecated
bool b4 = arr1 < arr3;
^

"SemaCXX/deprecated.cpp", line 268: warning: comparison between two arrays is deprecated
bool b6 = arr1 == f();
^

"SemaCXX/deprecated.cpp", line 280: warning: parameter "x" was set but never used
[[deprecated]] void f2([[deprecated]] int x) {
^
Expand Down
Loading
Loading