CHECK_EQUAL: fix array != array compare under C++26#1886
Open
dale-stewart wants to merge 1 commit into
Open
Conversation
C++26 [over.match.oper]/p10 makes array == array (and array != array)
ill-formed. CHECK_EQUAL_LOCATION expanded its two side-effect-detection
probes literally as (operand) != (operand). As soon as either operand
was an array (most often a string literal in CHECK_EQUAL("text", x)),
the inner self-compare became a forbidden array-vs-array compare. The
same pattern is also a -Wdeprecated-array-compare error under C++20+
when -Werror is on.
Add a CppUTestPrivate::checkEqualSelfNotEqual<T>(T, T) helper that
takes both arguments by value, so any array decays to a pointer
before the comparison runs. The two side-effect probes
((actual) != (actual) and (expected) != (expected)) are routed
through it. Both arguments come from the same operand expression, so
T is identical on both sides; -Wsign-compare cannot fire.
The outer (expected) != (actual) is intentionally left at the macro
call site. Routing it through a function template would lose
-Wsign-compare's constant-fits exception that lets idioms like
CHECK_EQUAL(0, some_unsigned) build clean today.
Behavior is unchanged for every non-array operand. For arrays, the
resulting pointer-address self-compare matches the historical C++03
behavior (always false, since the same array's decayed pointer
equals itself).
Add a regression test exercising the array-operand path. Without the
helper, the test TU is ill-formed under C++26 and emits
-Wdeprecated-array-compare under C++20+; with the helper it compiles
at every standard from C++98 through C++26.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
C++26 [over.match.oper]/p10 makes
array == array(andarray != array) ill-formed.CHECK_EQUAL_LOCATIONexpanded its two side-effect-detection probes literally as(operand) != (operand). As soon as either operand was an array — most commonly a string literal inCHECK_EQUAL("text", x)— the inner self-compare became a forbidden array-vs-array compare.The same pattern is also a
-Wdeprecated-array-compareerror under C++20+ when-Werroris on. CppUTest's existing tests don't exercise the array-operand path, so this never showed up in CI; it surfaces immediately in any consuming project that does.Fix
A small
CppUTestPrivate::checkEqualSelfNotEqual<T>(T, T)helper that takes both arguments by value, so any array decays to a pointer before the comparison runs. The two side-effect probes ((actual) != (actual)and(expected) != (expected)) route through it. Both arguments come from the same operand expression, soTis identical on both sides —-Wsign-comparecannot fire.The outer
(expected) != (actual)is intentionally left at the macro call site. Routing it through a function template would lose-Wsign-compare's constant-fits exception that lets idioms likeCHECK_EQUAL(0, some_unsigned)build clean today.Behavior is unchanged for every non-array operand. For arrays, the resulting pointer-address self-compare matches the historical C++03 behavior (always false, since the same array's decayed pointer equals itself).
Test
Added
CHECK_EQUAL_compilesWithArrayOperandinTestUTestMacro.cpp. Without the fix, the test TU emits-Wdeprecated-array-compareunder C++20+ with-Werror, and is ill-formed at C++26 regardless of warning flags. With the fix it compiles at every standard from C++98 through C++26.CI coverage
Verified by the existing
-Wall -Werrorjobs (Make Defaults, CMake Linux GNU 17/20/23, etc.) —-Wdeprecated-array-compareis on by default at C++20+ and gates the relevant condition. A future PR could add a C++26 job once compiler C++26 support stabilizes; this fix doesn't depend on that addition.Compatibility
Works at C++98 through C++26. No new headers included. The helper is a plain function template — no
<type_traits>, noif constexpr, no forwarding refs.