https://github.com/zahiraam created https://github.com/llvm/llvm-project/pull/107397
None >From 621578de568be1e71665254060956ea1971965c9 Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Thu, 5 Sep 2024 05:42:26 -0700 Subject: [PATCH] [NFC] Move warning from COdeGen to Sema. --- clang/include/clang/AST/ASTContext.h | 16 ++++++++++ .../clang/Basic/DiagnosticCommonKinds.td | 5 ---- .../clang/Basic/DiagnosticSemaKinds.td | 4 +++ clang/lib/CodeGen/CGExprComplex.cpp | 29 +++++-------------- clang/lib/Sema/SemaExpr.cpp | 24 +++++++++++++++ clang/test/AST/ByteCode/complex.cpp | 9 ++++-- .../test/Headers/nvptx_device_math_complex.c | 13 +++++---- clang/test/Sema/complex-arithmetic.c | 9 ++++-- clang/test/Sema/complex-int.c | 2 +- clang/test/SemaCXX/complex-folding.cpp | 15 ++++++++++ 10 files changed, 90 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 89bb5768dbd40d..e203568230e491 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -780,6 +780,22 @@ class ASTContext : public RefCountedBase<ASTContext> { const TargetInfo &getTargetInfo() const { return *Target; } const TargetInfo *getAuxTargetInfo() const { return AuxTarget; } + const QualType GetHigherPrecisionFPType(QualType ElementType) const { + const auto *CurrentBT = cast<BuiltinType>(ElementType); + switch (CurrentBT->getKind()) { + case BuiltinType::Kind::Float16: + return FloatTy; + case BuiltinType::Kind::Float: + case BuiltinType::Kind::BFloat16: + return DoubleTy; + case BuiltinType::Kind::Double: + return LongDoubleTy; + default: + return ElementType; + } + return ElementType; + } + /// getIntTypeForBitwidth - /// sets integer QualTy according to specified details: /// bitwidth, signed/unsigned. diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 33b1d58bb5b099..ae709e45a700a1 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -45,11 +45,6 @@ def note_using : Note<"using">; def note_possibility : Note<"one possibility">; def note_also_found : Note<"also found">; -def warn_next_larger_fp_type_same_size_than_fp : Warning< - "higher precision floating-point type size has the same size than " - "floating-point type size">, - InGroup<DiagGroup<"higher-precision-fp">>; - // Parse && Lex let CategoryName = "Lexical or Preprocessor Issue" in { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index dcb49d8a67604a..2aaf8dc3b7ecc1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6784,6 +6784,10 @@ def warn_arc_lifetime_result_type : Warning< "ARC %select{unused|__unsafe_unretained|__strong|__weak|__autoreleasing}0 " "lifetime qualifier on return type is ignored">, InGroup<IgnoredQualifiers>; +def warn_next_larger_fp_type_same_size_than_fp : Warning< + "higher precision floating-point type requested by user size has the same size" + "than floating-point type size; overflow may occur">, + InGroup<DiagGroup<"higher-precision-fp">>; let CategoryName = "ARC Retain Cycle" in { diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 828a09856099ac..fef26e7b4ccdbd 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -288,28 +288,15 @@ class ComplexExprEmitter ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName, const BinOpInfo &Op); - QualType GetHigherPrecisionFPType(QualType ElementType) { - const auto *CurrentBT = cast<BuiltinType>(ElementType); - switch (CurrentBT->getKind()) { - case BuiltinType::Kind::Float16: - return CGF.getContext().FloatTy; - case BuiltinType::Kind::Float: - case BuiltinType::Kind::BFloat16: - return CGF.getContext().DoubleTy; - case BuiltinType::Kind::Double: - return CGF.getContext().LongDoubleTy; - default: - return ElementType; - } - } - QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType, bool IsDivOpCode) { - QualType HigherElementType = GetHigherPrecisionFPType(ElementType); + ASTContext &Ctx = CGF.getContext(); + const QualType HigherElementType = + Ctx.GetHigherPrecisionFPType(ElementType); const llvm::fltSemantics &ElementTypeSemantics = - CGF.getContext().getFloatTypeSemantics(ElementType); + Ctx.getFloatTypeSemantics(ElementType); const llvm::fltSemantics &HigherElementTypeSemantics = - CGF.getContext().getFloatTypeSemantics(HigherElementType); + Ctx.getFloatTypeSemantics(HigherElementType); // Check that the promoted type can handle the intermediate values without // overflowing. This can be interpreted as: // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal) * 2 <= @@ -320,10 +307,10 @@ class ComplexExprEmitter if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <= llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) { FPHasBeenPromoted = true; - return CGF.getContext().getComplexType(HigherElementType); + return Ctx.getComplexType(HigherElementType); } else { - DiagnosticsEngine &Diags = CGF.CGM.getDiags(); - Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp); + // The intermediate values can't be represented in the promoted type + // without overflowing. return QualType(); } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 94bb938b53b441..fcd365a6639e05 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -15083,6 +15083,25 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr); } +static void DiagnosePrecisionLossInComplexDivision(Sema &S, + SourceLocation OpLoc, + Expr *Operand) { + if (auto *CT = Operand->getType()->getAs<ComplexType>()) { + QualType ElementType = CT->getElementType(); + if (ElementType->isFloatingType()) { + ASTContext &Ctx = S.getASTContext(); + QualType HigherElementType = Ctx.GetHigherPrecisionFPType(ElementType); + const llvm::fltSemantics &ElementTypeSemantics = + Ctx.getFloatTypeSemantics(ElementType); + const llvm::fltSemantics &HigherElementTypeSemantics = + Ctx.getFloatTypeSemantics(HigherElementType); + if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 > + llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) + S.Diag(OpLoc, diag::warn_next_larger_fp_type_same_size_than_fp); + } + } +} + ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr) { @@ -15093,6 +15112,11 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0" DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr); + // Emit warnings if the requested higher precision type equal to the current + // type precision. + if (Kind == tok::TokenKind::slash) + DiagnosePrecisionLossInComplexDivision(*this, TokLoc, LHSExpr); + return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr); } diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp index dc93c786dac7ae..c2665481570dd3 100644 --- a/clang/test/AST/ByteCode/complex.cpp +++ b/clang/test/AST/ByteCode/complex.cpp @@ -40,12 +40,17 @@ constexpr _Complex int IIMC = IIMA * IIMB; static_assert(__real(IIMC) == -30, ""); static_assert(__imag(IIMC) == 40, ""); -static_assert(1.0j / 0.0 == 1); // both-error {{static assertion}} \ +static_assert(1.0j / 0.0 == 1); //both-warning {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} \ + // both-error {{static assertion}} \ // both-note {{division by zero}} +// both-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} 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); // both-error {{static assertion}} \ +static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1); //both-warning {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} \ + // both-error {{static assertion}} \ // both-note {{division by zero}} +// both-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (0.0 + 0.0j))) == 1); +// both-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__imag__((1.0 + InfC) / (0.0 + 0.0j))) == 1); static_assert(__builtin_isinf_sign(__imag__((InfInf) / (0.0 + 0.0j))) == 1); diff --git a/clang/test/Headers/nvptx_device_math_complex.c b/clang/test/Headers/nvptx_device_math_complex.c index 354e9a10adf297..9e3df83301c177 100644 --- a/clang/test/Headers/nvptx_device_math_complex.c +++ b/clang/test/Headers/nvptx_device_math_complex.c @@ -1,9 +1,8 @@ // REQUIRES: nvptx-registered-target -// RUN: %clang_cc1 -verify -internal-isystem %S/Inputs/include -fopenmp -x c -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -x c -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -aux-triple powerpc64le-unknown-unknown -o - | FileCheck %s -// RUN: %clang_cc1 -verify -internal-isystem %S/Inputs/include -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -aux-triple powerpc64le-unknown-unknown -o - | FileCheck %s -// expected-no-diagnostics +// RUN: %clang_cc1 -verify=div-precision-ppc -internal-isystem %S/Inputs/include -fopenmp -x c -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify=div-precision-nvptx -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -x c -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -aux-triple powerpc64le-unknown-unknown -o - | FileCheck %s +// RUN: %clang_cc1 -verify=div-precision-ppc64le -internal-isystem %S/Inputs/include -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-ppc-host.bc +// RUN: %clang_cc1 -verify=div-precision-nvptx64 -internal-isystem %S/../../lib/Headers/openmp_wrappers -include __clang_openmp_device_functions.h -internal-isystem %S/Inputs/include -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-ppc-host.bc -aux-triple powerpc64le-unknown-unknown -o - | FileCheck %s #ifdef __cplusplus #include <complex> @@ -49,6 +48,10 @@ void test_scmplx(float _Complex a) { void test_dcmplx(double _Complex a) { #pragma omp target { + // div-precision-nvptx64-warning@+4 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} + // div-precision-ppc64le-warning@+3 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} + // div-precision-nvptx-warning@+2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} + // div-precision-ppc-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} (void)(a * (a / a)); } } diff --git a/clang/test/Sema/complex-arithmetic.c b/clang/test/Sema/complex-arithmetic.c index c9e84da6daa9dc..bda92fe0a5a884 100644 --- a/clang/test/Sema/complex-arithmetic.c +++ b/clang/test/Sema/complex-arithmetic.c @@ -1,5 +1,4 @@ -// RUN: %clang_cc1 -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -verify=div-precision %s // This tests evaluation of _Complex arithmetic at compile time. @@ -21,6 +20,8 @@ void a() { EVALF((2. + 3i) + (4. + 5i), 6. + 8i); EVALF((2. + 3i) - (4. + 5i), -2. - 2i); EVALF((2. + 3i) * (4. + 5i), -7. + 22i); + // div-precision-warning@+2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} + // div-precision-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} EVALF((2. + 3i) / (4. + 5i), .5609 + .0487i); } @@ -47,6 +48,8 @@ void c() { EVALF((2. + 4i) + 3., 5. + 4i); EVALF((2. + 4i) - 3., -1. + 4i); EVALF((2. + 4i) * 3., 6. + 12i); + // div-precision-warning@+2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} + // div-precision-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} EVALF((2. + 4i) / 2., 1. + 2i); EVALF(3. + (2. + 4i), 5. + 4i); @@ -83,6 +86,8 @@ void e() { EVALF((2. + 4i) + 3, 5. + 4i); EVALF((2. + 4i) - 3, -1. + 4i); EVALF((2. + 4i) * 3, 6. + 12i); + // div-precision-warning@+2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} + // div-precision-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} EVALF((2. + 4i) / 2, 1. + 2i); EVALF(3 + (2. + 4i), 5. + 4i); diff --git a/clang/test/Sema/complex-int.c b/clang/test/Sema/complex-int.c index e5a9a947d03708..4819568124419a 100644 --- a/clang/test/Sema/complex-int.c +++ b/clang/test/Sema/complex-int.c @@ -71,7 +71,7 @@ int i4[~(2+3i) == 2-3i ? 1 : -1]; // expected-warning {{fold}} int i5[(3i == -(-3i) ? ((void)3, 1i - 1) : 0) == 1i - 1 ? 1 : -1]; // expected-warning {{fold}} int f1[(2.0+3.0i)*(5.0+7.0i) == 29.0i-11.0 ? 1 : -1]; // expected-warning {{fold}} -int f2[(29.0i-11.0)/(5.0+7.0i) == 2.0+3.0i ? 1 : -1]; // expected-warning {{fold}} +int f2[(29.0i-11.0)/(5.0+7.0i) == 2.0+3.0i ? 1 : -1]; // expected-warning {{fold}} // expected-warning {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} int f3[-(2.0+3.0i) == +(-3.0i-2.0) ? 1 : -1]; // expected-warning {{fold}} int f4[~(2.0+3.0i) == 2.0-3.0i ? 1 : -1]; // expected-warning {{fold}} int f5[(3.0i == -(-3.0i) ? ((void)3.0, __extension__ (1.0i - 1.0)) : 0) == 1.0i - 1.0 ? 1 : -1]; // expected-warning {{fold}} diff --git a/clang/test/SemaCXX/complex-folding.cpp b/clang/test/SemaCXX/complex-folding.cpp index f2fa93ad4795b9..0f1dfe1c45da8b 100644 --- a/clang/test/SemaCXX/complex-folding.cpp +++ b/clang/test/SemaCXX/complex-folding.cpp @@ -54,7 +54,9 @@ static_assert(((1.25 + 0.5j) * (0.25 - 0.75j)) == (0.6875 - 0.8125j)); static_assert(((1.25 + 0.5j) * 0.25) == (0.3125 + 0.125j)); static_assert((1.25 * (0.25 - 0.75j)) == (0.3125 - 0.9375j)); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(((1.25 + 0.5j) / (0.25 - 0.75j)) == (-0.1 + 1.7j)); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(((1.25 + 0.5j) / 0.25) == (5.0 + 2.0j)); static_assert((1.25 / (0.25 - 0.75j)) == (0.5 + 1.5j)); @@ -80,26 +82,39 @@ static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) * (1.0 + InfC))) == -1) static_assert(__builtin_isinf_sign(__imag__((1.0 + 1.0j) * (1.0 + InfC))) == 1); static_assert(__builtin_isinf_sign(__real__((1.0 + InfC) * (1.0 + InfC))) == -1); static_assert(__builtin_isinf_sign(__real__(InfInf * InfInf)) == 0); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (1.0 + 1.0j))) == 1); static_assert(__builtin_isinf_sign(__imag__(1.0 + (InfC) / (1.0 + 1.0j))) == 1); static_assert(__builtin_isinf_sign(__imag__((InfInf) / (1.0 + 1.0j))) == 0); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 1.0)) == 1); static_assert(__builtin_isinf_sign(__imag__(1.0 + (InfC) / 1.0)) == 1); static_assert(__builtin_isinf_sign(__imag__((InfInf) / 1.0)) == 1); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(((1.0 + 1.0j) / (__builtin_inf() + 1.0j)) == (0.0 + 0.0j)); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(((1.0 + 1.0j) / (1.0 + InfC)) == (0.0 + 0.0j)); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(((1.0 + 1.0j) / (InfInf)) == (0.0 + 0.0j)); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(((1.0 + 1.0j) / __builtin_inf()) == (0.0 + 0.0j)); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(1.0j / 0.0 == 1); // expected-error {{static assertion}} \ // expected-note {{division by zero}} + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / (0.0 + 0.0j))) == 1); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \ // expected-note {{division by zero}} + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / (0.0 + 0.0j))) == 1); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__imag__((1.0 + InfC) / (0.0 + 0.0j))) == 1); static_assert(__builtin_isinf_sign(__imag__((InfInf) / (0.0 + 0.0j))) == 1); + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__real__((__builtin_inf() + 1.0j) / 0.0)) == 1); // expected-error {{static assertion}} \ // expected-note {{division by zero}} + // expected-warning@+1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}} static_assert(__builtin_isinf_sign(__imag__((1.0 + InfC) / 0.0)) == 1); // expected-error {{static assertion}} \ // expected-note {{division by zero}} static_assert(__builtin_isinf_sign(__imag__((InfInf) / 0.0)) == 1); // expected-error {{static assertion}} \ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits