llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Use handleFloatFloatBinOp to properly diagnose NaN results and divisions by zero. Fixes #<!-- -->84871 --- Full diff: https://github.com/llvm/llvm-project/pull/90588.diff 2 Files Affected: - (modified) clang/lib/AST/ExprConstant.cpp (+21-6) - (modified) clang/test/SemaCXX/complex-folding.cpp (+44-29) ``````````diff diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index f1aa19e4409e15..86fb396fabe2d9 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15209,11 +15209,21 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APFloat &ResI = Result.getComplexFloatImag(); if (LHSReal) { assert(!RHSReal && "Cannot have two real operands for a complex op!"); - ResR = A * C; - ResI = A * D; + ResR = A; + ResI = A; + // ResR = A * C; + // ResI = A * D; + if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, C) || + !handleFloatFloatBinOp(Info, E, ResI, BO_Mul, D)) + return false; } else if (RHSReal) { - ResR = C * A; - ResI = C * B; + // ResR = C * A; + // ResI = C * B; + ResR = C; + ResI = C; + if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, A) || + !handleFloatFloatBinOp(Info, E, ResI, BO_Mul, B)) + return false; } else { // In the fully general case, we need to handle NaNs and infinities // robustly. @@ -15289,8 +15299,13 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { APFloat &ResR = Result.getComplexFloatReal(); APFloat &ResI = Result.getComplexFloatImag(); if (RHSReal) { - ResR = A / C; - ResI = B / C; + ResR = A; + ResI = B; + // ResR = A / C; + // ResI = B / C; + if (!handleFloatFloatBinOp(Info, E, ResR, BO_Div, C) || + !handleFloatFloatBinOp(Info, E, ResI, BO_Div, C)) + return false; } else { if (LHSReal) { // No real optimizations we can do here, stub out with zero. diff --git a/clang/test/SemaCXX/complex-folding.cpp b/clang/test/SemaCXX/complex-folding.cpp index 054f159e9ce0dd..d3e428f2b75cc2 100644 --- a/clang/test/SemaCXX/complex-folding.cpp +++ b/clang/test/SemaCXX/complex-folding.cpp @@ -57,43 +57,58 @@ static_assert(((1.25 + 0.5j) / (0.25 - 0.75j)) == (-0.1 + 1.7j)); static_assert(((1.25 + 0.5j) / 0.25) == (5.0 + 2.0j)); static_assert((1.25 / (0.25 - 0.75j)) == (0.5 + 1.5j)); -// Test that infinities are preserved, don't turn into NaNs, and do form zeros -// when the divisor. + static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * 1.0)) == 1); -static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * 1.0)) == 1); +static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * 1.0)) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} static_assert(__builtin_isinf_sign(__real__(1.0 * (__builtin_inf() + 1.0j))) == 1); -static_assert(__builtin_isinf_sign(__imag__(1.0 * (1.0 + __builtin_inf() * 1.0j))) == 1); - +static_assert(__builtin_isinf_sign(__imag__(1.0 * (1.0 + __builtin_inf() * 1.0j))) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * (1.0 + 1.0j))) == 1); static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (__builtin_inf() + 1.0j))) == 1); static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) * (__builtin_inf() + 1.0j))) == 1); - -static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == -1); -static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == 1); -static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1); -static_assert(__builtin_isinf_sign(__imag__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == 1); - -static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1); -static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + __builtin_inf() * 1.0j) * (__builtin_inf() + __builtin_inf() * 1.0j))) == -1); - +static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == -1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) * (1.0 + 1.0j))) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__imag__((1.0 + 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__real__((1.0 + __builtin_inf() * 1.0j) * (1.0 + __builtin_inf() * 1.0j))) == -1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + __builtin_inf() * 1.0j) * (__builtin_inf() + __builtin_inf() * 1.0j))) == -1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (1.0 + 1.0j))) == 1); -static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1); -static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1); +static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (1.0 + 1.0j))) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 1.0)) == 1); -static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / 1.0)) == 1); -static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 1.0)) == 1); - +static_assert(__builtin_isinf_sign(__imag__(1.0 + (__builtin_inf() * 1.0j) / 1.0)) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 1.0)) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} static_assert(((1.0 + 1.0j) / (__builtin_inf() + 1.0j)) == (0.0 + 0.0j)); -static_assert(((1.0 + 1.0j) / (1.0 + __builtin_inf() * 1.0j)) == (0.0 + 0.0j)); -static_assert(((1.0 + 1.0j) / (__builtin_inf() + __builtin_inf() * 1.0j)) == (0.0 + 0.0j)); +static_assert(((1.0 + 1.0j) / (1.0 + __builtin_inf() * 1.0j)) == (0.0 + 0.0j)); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(((1.0 + 1.0j) / (__builtin_inf() + __builtin_inf() * 1.0j)) == (0.0 + 0.0j)); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} static_assert(((1.0 + 1.0j) / __builtin_inf()) == (0.0 + 0.0j)); - +static_assert(1.0j / 0.0 == 1); // expected-error {{static assertion}} \ + // expected-note {{division by zero}} static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / (0.0 + 0.0j))) == 1); -static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1); - +static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \ + // expected-note {{division by zero}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (0.0 + 0.0j))) == 1); -static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1); -static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1); -static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 0.0)) == 1); -static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / 0.0)) == 1); -static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 0.0)) == 1); +static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / (0.0 + 0.0j))) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \ + // expected-note {{division by zero}} +static_assert(__builtin_isinf_sign(__imag__((1.0 + __builtin_inf() * 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} +static_assert(__builtin_isinf_sign(__imag__((__builtin_inf() + __builtin_inf() * 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \ + // expected-note {{produces a NaN}} + `````````` </details> https://github.com/llvm/llvm-project/pull/90588 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits