C: Fix excess precision handling for logical NOT operator
Correctly handles excess precision for the result of the logical NOT operator (!), preventing compiler errors with types like _Float16.
This commit fixes an issue where the C frontend incorrectly re-wrapped the result of the logical NOT operator (!) in an EXCESS_PRECISION_EXPR, even though the result of ! is always an int. This caused problems with types like _Float16 or when x87 excess precision was enabled, leading to incorrect sizeof results, ICEs in build_conditional_expr, or ICEs at the expansion stage. The fix prevents re-wrapping the result of TRUTH_NOT_EXPR while still testing the operand at its excess precision.
In Details
The build_unary_op function in c-typeck.cc previously stripped an EXCESS_PRECISION_EXPR from the operand of TRUTH_NOT_EXPR and then re-wrapped the int result in another EXCESS_PRECISION_EXPR. This behavior caused issues with types that have excess precision (like _Float16 or x87's long double), leading to ICEs in subsequent passes. The fix modifies build_unary_op to not re-wrap the result of TRUTH_NOT_EXPR, ensuring type correctness while still performing the necessary excess precision tests on the operand itself.
- EXCESS_PRECISION_EXPR
- An internal GCC construct used to manage floating-point types that have more precision than the standard types they represent, particularly relevant for x87 floating-point units.
- logical NOT operator (!)
- A C operator that returns a boolean value (true or false, represented as 1 or 0) indicating whether its operand is zero or non-zero.
- _Float16
- A binary floating-point type with 16 bits of precision, part of the C standard's proposed extensions for half-precision floating-point numbers.
- ICE
- Internal Compiler Error; a crash within the compiler itself, usually indicating a bug in the compiler's logic.
- TRUTH_NOT_EXPR
- GCC's internal representation for the logical NOT operation.