Skip to content

Commit edb5cd5

Browse files
committed
[clang][Interp] Report erroneous floating point results in _Complex math
Use handleFloatFloatBinOp to properly diagnose NaN results and divisions by zero.
1 parent af5d41e commit edb5cd5

File tree

2 files changed

+65
-35
lines changed

2 files changed

+65
-35
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15209,11 +15209,21 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1520915209
APFloat &ResI = Result.getComplexFloatImag();
1521015210
if (LHSReal) {
1521115211
assert(!RHSReal && "Cannot have two real operands for a complex op!");
15212-
ResR = A * C;
15213-
ResI = A * D;
15212+
ResR = A;
15213+
ResI = A;
15214+
// ResR = A * C;
15215+
// ResI = A * D;
15216+
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, C) ||
15217+
!handleFloatFloatBinOp(Info, E, ResI, BO_Mul, D))
15218+
return false;
1521415219
} else if (RHSReal) {
15215-
ResR = C * A;
15216-
ResI = C * B;
15220+
// ResR = C * A;
15221+
// ResI = C * B;
15222+
ResR = C;
15223+
ResI = C;
15224+
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, A) ||
15225+
!handleFloatFloatBinOp(Info, E, ResI, BO_Mul, B))
15226+
return false;
1521715227
} else {
1521815228
// In the fully general case, we need to handle NaNs and infinities
1521915229
// robustly.
@@ -15289,8 +15299,13 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1528915299
APFloat &ResR = Result.getComplexFloatReal();
1529015300
APFloat &ResI = Result.getComplexFloatImag();
1529115301
if (RHSReal) {
15292-
ResR = A / C;
15293-
ResI = B / C;
15302+
ResR = A;
15303+
ResI = B;
15304+
// ResR = A / C;
15305+
// ResI = B / C;
15306+
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Div, C) ||
15307+
!handleFloatFloatBinOp(Info, E, ResI, BO_Div, C))
15308+
return false;
1529415309
} else {
1529515310
if (LHSReal) {
1529615311
// No real optimizations we can do here, stub out with zero.

clang/test/SemaCXX/complex-folding.cpp

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -57,43 +57,58 @@ static_assert(((1.25 + 0.5j) / (0.25 - 0.75j)) == (-0.1 + 1.7j));
5757
static_assert(((1.25 + 0.5j) / 0.25) == (5.0 + 2.0j));
5858
static_assert((1.25 / (0.25 - 0.75j)) == (0.5 + 1.5j));
5959

60-
// Test that infinities are preserved, don't turn into NaNs, and do form zeros
61-
// when the divisor.
60+
6261
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * 1.0)) == 1);
63-
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * 1.0)) == 1);
62+
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * 1.0)) == 1); // expected-error {{static assertion}} \
63+
// expected-note {{produces a NaN}}
6464
static_assert(__builtin_isinf_sign(__real__(1.0 * (__builtin_inf() + 1.0j))) == 1);
65-
static_assert(__builtin_isinf_sign(__imag__(1.0 * (1.0 + __builtin_inf() * 1.0j))) == 1);
66-
65+
static_assert(__builtin_isinf_sign(__imag__(1.0 * (1.0 + __builtin_inf() * 1.0j))) == 1); // expected-error {{static assertion}} \
66+
// expected-note {{produces a NaN}}
6767
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * (1.0 + 1.0j))) == 1);
6868
static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (__builtin_inf() + 1.0j))) == 1);
6969
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * (__builtin_inf() + 1.0j))) == 1);
70-
71-
static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == -1);
72-
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == 1);
73-
static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1);
74-
static_assert(__builtin_isinf_sign(__imag__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == 1);
75-
76-
static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1);
77-
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + __builtin_inf() * 1.0j) * (__builtin_inf() + __builtin_inf() * 1.0j))) == -1);
78-
70+
static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == -1); // expected-error {{static assertion}} \
71+
// expected-note {{produces a NaN}}
72+
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == 1); // expected-error {{static assertion}} \
73+
// expected-note {{produces a NaN}}
74+
static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1); // expected-error {{static assertion}} \
75+
// expected-note {{produces a NaN}}
76+
static_assert(__builtin_isinf_sign(__imag__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == 1); // expected-error {{static assertion}} \
77+
// expected-note {{produces a NaN}}
78+
static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1); // expected-error {{static assertion}} \
79+
// expected-note {{produces a NaN}}
80+
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + __builtin_inf() * 1.0j) * (__builtin_inf() + __builtin_inf() * 1.0j))) == -1); // expected-error {{static assertion}} \
81+
// expected-note {{produces a NaN}}
7982
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (1.0 + 1.0j))) == 1);
80-
static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1);
81-
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1);
83+
static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1); // expected-error {{static assertion}} \
84+
// expected-note {{produces a NaN}}
85+
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1); // expected-error {{static assertion}} \
86+
// expected-note {{produces a NaN}}
8287
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 1.0)) == 1);
83-
static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / 1.0)) == 1);
84-
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 1.0)) == 1);
85-
88+
static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / 1.0)) == 1); // expected-error {{static assertion}} \
89+
// expected-note {{produces a NaN}}
90+
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 1.0)) == 1); // expected-error {{static assertion}} \
91+
// expected-note {{produces a NaN}}
8692
static_assert(((1.0 + 1.0j) / (__builtin_inf() + 1.0j)) == (0.0 + 0.0j));
87-
static_assert(((1.0 + 1.0j) / (1.0 + __builtin_inf() * 1.0j)) == (0.0 + 0.0j));
88-
static_assert(((1.0 + 1.0j) / (__builtin_inf() + __builtin_inf() * 1.0j)) == (0.0 + 0.0j));
93+
static_assert(((1.0 + 1.0j) / (1.0 + __builtin_inf() * 1.0j)) == (0.0 + 0.0j)); // expected-error {{static assertion}} \
94+
// expected-note {{produces a NaN}}
95+
static_assert(((1.0 + 1.0j) / (__builtin_inf() + __builtin_inf() * 1.0j)) == (0.0 + 0.0j)); // expected-error {{static assertion}} \
96+
// expected-note {{produces a NaN}}
8997
static_assert(((1.0 + 1.0j) / __builtin_inf()) == (0.0 + 0.0j));
90-
98+
static_assert(1.0j / 0.0 == 1); // expected-error {{static assertion}} \
99+
// expected-note {{division by zero}}
91100
static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / (0.0 + 0.0j))) == 1);
92-
static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1);
93-
101+
static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \
102+
// expected-note {{division by zero}}
94103
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (0.0 + 0.0j))) == 1);
95-
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1);
96-
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1);
97-
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 0.0)) == 1);
98-
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / 0.0)) == 1);
99-
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 0.0)) == 1);
104+
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1); // expected-error {{static assertion}} \
105+
// expected-note {{produces a NaN}}
106+
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1); // expected-error {{static assertion}} \
107+
// expected-note {{produces a NaN}}
108+
static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \
109+
// expected-note {{division by zero}}
110+
static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \
111+
// expected-note {{produces a NaN}}
112+
static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \
113+
// expected-note {{produces a NaN}}
114+

0 commit comments

Comments
 (0)