[clang] [NFC] Move warning from CodeGen to Sema. (PR #107397)

Zahira Ammarguellat via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 16 09:12:16 PDT 2024


https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/107397

>From 621578de568be1e71665254060956ea1971965c9 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 5 Sep 2024 05:42:26 -0700
Subject: [PATCH 1/8] [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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
+  // div-precision-warning at +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 at +2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
+  // div-precision-warning at +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 at +2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
+  // div-precision-warning at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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}} \

>From 80544b7357b7d4eb761308ec8cc2f40ca96094fd Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 6 Sep 2024 07:27:48 -0700
Subject: [PATCH 2/8] Fixed issue with LIT tests.

---
 clang/lib/Sema/SemaExpr.cpp                    |  4 +++-
 clang/test/AST/ByteCode/complex.cpp            | 11 ++++-------
 clang/test/Headers/nvptx_device_math_complex.c | 13 +++++--------
 clang/test/Sema/complex-arithmetic.c           |  7 ++++++-
 clang/test/Sema/complex-int.c                  |  2 +-
 clang/test/SemaCXX/complex-folding.cpp         | 16 +---------------
 6 files changed, 20 insertions(+), 33 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index fcd365a6639e05..8f2699ea66793f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15088,7 +15088,9 @@ static void DiagnosePrecisionLossInComplexDivision(Sema &S,
                                                    Expr *Operand) {
   if (auto *CT = Operand->getType()->getAs<ComplexType>()) {
     QualType ElementType = CT->getElementType();
-    if (ElementType->isFloatingType()) {
+    bool IsComplexRangePromoted = S.getLangOpts().getComplexRange() ==
+                                  LangOptions::ComplexRangeKind::CX_Promoted;
+    if (ElementType->isFloatingType() && IsComplexRangePromoted) {
       ASTContext &Ctx = S.getASTContext();
       QualType HigherElementType = Ctx.GetHigherPrecisionFPType(ElementType);
       const llvm::fltSemantics &ElementTypeSemantics =
diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp
index c2665481570dd3..03e72f429e44ea 100644
--- a/clang/test/AST/ByteCode/complex.cpp
+++ b/clang/test/AST/ByteCode/complex.cpp
@@ -40,17 +40,14 @@ constexpr _Complex int IIMC = IIMA * IIMB;
 static_assert(__real(IIMC) == -30, "");
 static_assert(__imag(IIMC) == 40, "");
 
-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}}	\
+static_assert(1.0j / 0.0 == 1); // both-error {{static assertion}}	\
                                 // both-note {{division by zero}}
-// both-warning at +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-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}} \
+static_assert(__builtin_isinf_sign(__real__((1.0 + 1.0j) / 0.0)) == 1); // both-error {{static assertion}} \
                                                                         // both-note {{division by zero}}
-// both-warning at +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 at +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 9e3df83301c177..354e9a10adf297 100644
--- a/clang/test/Headers/nvptx_device_math_complex.c
+++ b/clang/test/Headers/nvptx_device_math_complex.c
@@ -1,8 +1,9 @@
 // REQUIRES: nvptx-registered-target
-// 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
+// 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
 
 #ifdef __cplusplus
 #include <complex>
@@ -48,10 +49,6 @@ void test_scmplx(float _Complex a) {
 void test_dcmplx(double _Complex a) {
 #pragma omp target
   {
-  // div-precision-nvptx64-warning at +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 at +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 at +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 at +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 bda92fe0a5a884..8c303bd1c055c4 100644
--- a/clang/test/Sema/complex-arithmetic.c
+++ b/clang/test/Sema/complex-arithmetic.c
@@ -1,5 +1,10 @@
-// RUN: %clang_cc1 -verify=div-precision %s
+// RUN: %clang_cc1 -verify=no-diag %s
+// RUN: %clang_cc1 -complex-range=promoted -verify=div-precision %s
+// RUN: %clang_cc1 -complex-range=promoted -triple x86_64-unknown-windows \
+// RUN: -verify=div-precision %s
 
+
+// no-diag-no-diagnostics
 // This tests evaluation of _Complex arithmetic at compile time.
 
 #define APPROX_EQ(a, b) (                             \
diff --git a/clang/test/Sema/complex-int.c b/clang/test/Sema/complex-int.c
index 4819568124419a..e5a9a947d03708 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}} // expected-warning {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
+int f2[(29.0i-11.0)/(5.0+7.0i) == 2.0+3.0i ? 1 : -1]; // expected-warning {{fold}}
 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 0f1dfe1c45da8b..bb54fa92689d9d 100644
--- a/clang/test/SemaCXX/complex-folding.cpp
+++ b/clang/test/SemaCXX/complex-folding.cpp
@@ -54,9 +54,7 @@ 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 at +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 at +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));
 
@@ -82,39 +80,27 @@ 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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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}} \

>From 20f2e9517bba081cf074ab9f2a62d097c4c35871 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 6 Sep 2024 11:10:11 -0700
Subject: [PATCH 3/8] Fixed LIT test.

---
 clang/test/Sema/complex-arithmetic.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/test/Sema/complex-arithmetic.c b/clang/test/Sema/complex-arithmetic.c
index 8c303bd1c055c4..a9ff001d60a8b6 100644
--- a/clang/test/Sema/complex-arithmetic.c
+++ b/clang/test/Sema/complex-arithmetic.c
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -verify=no-diag %s
-// RUN: %clang_cc1 -complex-range=promoted -verify=div-precision %s
+// RUN: %clang_cc1 -complex-range=promoted -triple x86_64-unknown-linux \
+// RUN: -verify=no-diag %s
 // RUN: %clang_cc1 -complex-range=promoted -triple x86_64-unknown-windows \
 // RUN: -verify=div-precision %s
-
-
 // no-diag-no-diagnostics
+
 // This tests evaluation of _Complex arithmetic at compile time.
 
 #define APPROX_EQ(a, b) (                             \

>From 6c039324b9f9858fb57c251ab2128209fd6b0be5 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 12 Sep 2024 06:00:12 -0700
Subject: [PATCH 4/8] Addressed review comments.

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  9 +++++----
 clang/include/clang/Sema/Sema.h                  |  7 +++++++
 clang/lib/Sema/Sema.cpp                          |  1 +
 clang/lib/Sema/SemaAttr.cpp                      | 10 ++++++++++
 clang/lib/Sema/SemaExpr.cpp                      | 16 ++++++++++++++--
 clang/test/AST/ByteCode/complex.cpp              |  4 +---
 clang/test/Sema/complex-arithmetic.c             |  7 +------
 clang/test/SemaCXX/complex-folding.cpp           |  1 -
 8 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2aaf8dc3b7ecc1..909cd22eae1470 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6784,10 +6784,11 @@ 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">>;
+def warn_excess_precision_not_supported : Warning<
+  "excess precision is requested but the target does not support excess "
+  "precision %select{which may result in observable differences in arithmetic "
+  "behavior}0 %select{|,additional use of %1 were found but not diagnosed}2">,
+  InGroup<DiagGroup<"higher-precision">>;
 
 let CategoryName = "ARC Retain Cycle" in {
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0358259945c796..2469b49f56ea74 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -626,6 +626,11 @@ class Sema final : public SemaBase {
   const llvm::MapVector<FieldDecl *, DeleteLocs> &
   getMismatchingDeleteExpressions() const;
 
+  std::vector<std::tuple<SourceLocation, QualType, unsigned>>
+      ExcessPrecisionNotSatisfied;
+  unsigned NumExcessPrecisionNotSatisfied = 0;
+  SourceLocation LocationOfExcessPrecisionNotSatisfied;
+
   /// Cause the active diagnostic on the DiagosticsEngine to be
   /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and
   /// should not be used elsewhere.
@@ -1963,6 +1968,8 @@ class Sema final : public SemaBase {
 
   void DiagnoseUnterminatedPragmaAttribute();
 
+  void DiagnoseExcessPrecision();
+
   /// Called on well formed \#pragma clang optimize.
   void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
 
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 29acd06af603be..be495f0210647d 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1213,6 +1213,7 @@ void Sema::ActOnEndOfTranslationUnit() {
   DiagnoseUnterminatedPragmaAlignPack();
   DiagnoseUnterminatedPragmaAttribute();
   OpenMP().DiagnoseUnterminatedOpenMPDeclareTarget();
+  DiagnoseExcessPrecision();
 
   // All delayed member exception specs should be checked or we end up accepting
   // incompatible declarations.
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index fb594e6f13c0b3..62a63b5a8298ba 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1180,6 +1180,16 @@ void Sema::PrintPragmaAttributeInstantiationPoint() {
                diag::note_pragma_attribute_applied_decl_here);
 }
 
+void Sema::DiagnoseExcessPrecision() {
+  if (NumExcessPrecisionNotSatisfied > 0) {
+    for (auto &[Loc, Type, Num] : ExcessPrecisionNotSatisfied)
+      if (Num > 1)
+        Diag(Loc, diag::warn_excess_precision_not_supported) << 0 << Type << 1;
+      else
+        Diag(Loc, diag::warn_excess_precision_not_supported) << 0 << Type << 0;
+  }
+}
+
 void Sema::DiagnoseUnterminatedPragmaAttribute() {
   if (PragmaAttributeStack.empty())
     return;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8f2699ea66793f..ccd9a878c892fd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15098,8 +15098,20 @@ static void DiagnosePrecisionLossInComplexDivision(Sema &S,
       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);
+          llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
+        // Retain the location of the first use of higher precision type.
+        if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
+          S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
+        S.NumExcessPrecisionNotSatisfied++;
+        for (auto &[Loc, Type, Num] : S.ExcessPrecisionNotSatisfied) {
+          if (Type == HigherElementType) {
+            Num++;
+            return;
+          }
+        }
+        S.ExcessPrecisionNotSatisfied.push_back(std::make_tuple(
+            OpLoc, HigherElementType, S.NumExcessPrecisionNotSatisfied));
+      }
     }
   }
 }
diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp
index 03e72f429e44ea..dc93c786dac7ae 100644
--- a/clang/test/AST/ByteCode/complex.cpp
+++ b/clang/test/AST/ByteCode/complex.cpp
@@ -40,14 +40,12 @@ 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-error {{static assertion}} \
                                 // both-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); // both-error {{static assertion}} \
                                                                         // both-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 + InfC) / (0.0 + 0.0j))) == 1);
 static_assert(__builtin_isinf_sign(__imag__((InfInf) / (0.0 + 0.0j))) == 1);
 
diff --git a/clang/test/Sema/complex-arithmetic.c b/clang/test/Sema/complex-arithmetic.c
index a9ff001d60a8b6..41f7b88949168e 100644
--- a/clang/test/Sema/complex-arithmetic.c
+++ b/clang/test/Sema/complex-arithmetic.c
@@ -25,8 +25,7 @@ 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 at +2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
-  // div-precision-warning at +1 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
+  // div-precision-warning at +1 {{excess precision is requested but the target does not support excess precision which may result in observable differences in arithmetic behavior ,additional use of 'long double' were found but not diagnosed}}
   EVALF((2. + 3i) / (4. + 5i), .5609 + .0487i);
 }
 
@@ -53,8 +52,6 @@ void c() {
   EVALF((2. + 4i) + 3., 5. + 4i);
   EVALF((2. + 4i) - 3., -1. + 4i);
   EVALF((2. + 4i) * 3., 6. + 12i);
-  // div-precision-warning at +2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
-  // div-precision-warning at +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);
@@ -91,8 +88,6 @@ void e() {
   EVALF((2. + 4i) + 3, 5. + 4i);
   EVALF((2. + 4i) - 3, -1. + 4i);
   EVALF((2. + 4i) * 3, 6. + 12i);
-  // div-precision-warning at +2 {{higher precision floating-point type requested by user size has the same sizethan floating-point type size; overflow may occur}}
-  // div-precision-warning at +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/SemaCXX/complex-folding.cpp b/clang/test/SemaCXX/complex-folding.cpp
index bb54fa92689d9d..f2fa93ad4795b9 100644
--- a/clang/test/SemaCXX/complex-folding.cpp
+++ b/clang/test/SemaCXX/complex-folding.cpp
@@ -90,7 +90,6 @@ static_assert(((1.0 + 1.0j) / (__builtin_inf() + 1.0j)) == (0.0 + 0.0j));
 static_assert(((1.0 + 1.0j) / (1.0 + InfC)) == (0.0 + 0.0j));
 static_assert(((1.0 + 1.0j) / (InfInf)) == (0.0 + 0.0j));
 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);

>From 51acb49fa02ce4306e251649d7d7d23c65477d07 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 12 Sep 2024 09:02:57 -0700
Subject: [PATCH 5/8] Addressed review comments.

---
 clang/include/clang/Sema/Sema.h | 13 ++++++-------
 clang/lib/Sema/SemaAttr.cpp     |  6 ++----
 2 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2469b49f56ea74..075a2b79c33054 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -626,11 +626,6 @@ class Sema final : public SemaBase {
   const llvm::MapVector<FieldDecl *, DeleteLocs> &
   getMismatchingDeleteExpressions() const;
 
-  std::vector<std::tuple<SourceLocation, QualType, unsigned>>
-      ExcessPrecisionNotSatisfied;
-  unsigned NumExcessPrecisionNotSatisfied = 0;
-  SourceLocation LocationOfExcessPrecisionNotSatisfied;
-
   /// Cause the active diagnostic on the DiagosticsEngine to be
   /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and
   /// should not be used elsewhere.
@@ -1968,8 +1963,6 @@ class Sema final : public SemaBase {
 
   void DiagnoseUnterminatedPragmaAttribute();
 
-  void DiagnoseExcessPrecision();
-
   /// Called on well formed \#pragma clang optimize.
   void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
 
@@ -7971,6 +7964,12 @@ class Sema final : public SemaBase {
   /// Do an explicit extend of the given block pointer if we're in ARC.
   void maybeExtendBlockObject(ExprResult &E);
 
+   std::vector<std::tuple<SourceLocation, QualType, unsigned>>
+      ExcessPrecisionNotSatisfied;
+  unsigned NumExcessPrecisionNotSatisfied = 0;
+  SourceLocation LocationOfExcessPrecisionNotSatisfied;
+  void DiagnoseExcessPrecision();
+
 private:
   static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
 
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 62a63b5a8298ba..4c78c744da4355 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1183,10 +1183,8 @@ void Sema::PrintPragmaAttributeInstantiationPoint() {
 void Sema::DiagnoseExcessPrecision() {
   if (NumExcessPrecisionNotSatisfied > 0) {
     for (auto &[Loc, Type, Num] : ExcessPrecisionNotSatisfied)
-      if (Num > 1)
-        Diag(Loc, diag::warn_excess_precision_not_supported) << 0 << Type << 1;
-      else
-        Diag(Loc, diag::warn_excess_precision_not_supported) << 0 << Type << 0;
+      Diag(Loc, diag::warn_excess_precision_not_supported)
+          << 0 << Type << static_cast<bool>(Num);
   }
 }
 

>From 4799efd48baaa1c2d9c2d502483453b22df80f09 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Thu, 12 Sep 2024 10:17:36 -0700
Subject: [PATCH 6/8] Fix format.

---
 clang/include/clang/Sema/Sema.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 075a2b79c33054..09e83a309b555f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7964,7 +7964,7 @@ class Sema final : public SemaBase {
   /// Do an explicit extend of the given block pointer if we're in ARC.
   void maybeExtendBlockObject(ExprResult &E);
 
-   std::vector<std::tuple<SourceLocation, QualType, unsigned>>
+  std::vector<std::tuple<SourceLocation, QualType, unsigned>>
       ExcessPrecisionNotSatisfied;
   unsigned NumExcessPrecisionNotSatisfied = 0;
   SourceLocation LocationOfExcessPrecisionNotSatisfied;

>From ddab83283e0aa5cddc660334696e994448848da5 Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Fri, 13 Sep 2024 07:38:07 -0700
Subject: [PATCH 7/8] Addressed review comments.

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  7 ++++---
 clang/include/clang/Sema/Sema.h                  |  5 ++---
 clang/lib/Sema/Sema.cpp                          |  2 +-
 clang/lib/Sema/SemaAttr.cpp                      | 12 +++++++-----
 clang/lib/Sema/SemaExpr.cpp                      | 13 ++++++-------
 clang/test/Sema/complex-arithmetic.c             |  2 +-
 6 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 909cd22eae1470..524262c473a799 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6786,9 +6786,10 @@ def warn_arc_lifetime_result_type : Warning<
   InGroup<IgnoredQualifiers>;
 def warn_excess_precision_not_supported : Warning<
   "excess precision is requested but the target does not support excess "
-  "precision %select{which may result in observable differences in arithmetic "
-  "behavior}0 %select{|,additional use of %1 were found but not diagnosed}2">,
-  InGroup<DiagGroup<"higher-precision">>;
+  "precision which may result in observable differences in complex division "
+  "behavior%select{|,additional uses where the requested higher precision "
+  "cannot be honored were found but not diagnosed}0">,
+  InGroup<DiagGroup<"higher-precision-for-complex-division">>;
 
 let CategoryName = "ARC Retain Cycle" in {
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 09e83a309b555f..f41e1969d2a0df 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7964,11 +7964,10 @@ class Sema final : public SemaBase {
   /// Do an explicit extend of the given block pointer if we're in ARC.
   void maybeExtendBlockObject(ExprResult &E);
 
-  std::vector<std::tuple<SourceLocation, QualType, unsigned>>
-      ExcessPrecisionNotSatisfied;
+  std::vector<std::pair<QualType, unsigned>> ExcessPrecisionNotSatisfied;
   unsigned NumExcessPrecisionNotSatisfied = 0;
   SourceLocation LocationOfExcessPrecisionNotSatisfied;
-  void DiagnoseExcessPrecision();
+  void DiagnosePrecisionLossInComplexDivision();
 
 private:
   static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index be495f0210647d..ce8308cf7ae73d 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1213,7 +1213,7 @@ void Sema::ActOnEndOfTranslationUnit() {
   DiagnoseUnterminatedPragmaAlignPack();
   DiagnoseUnterminatedPragmaAttribute();
   OpenMP().DiagnoseUnterminatedOpenMPDeclareTarget();
-  DiagnoseExcessPrecision();
+  DiagnosePrecisionLossInComplexDivision();
 
   // All delayed member exception specs should be checked or we end up accepting
   // incompatible declarations.
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 4c78c744da4355..cf2a5a622a3a4d 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1180,11 +1180,13 @@ void Sema::PrintPragmaAttributeInstantiationPoint() {
                diag::note_pragma_attribute_applied_decl_here);
 }
 
-void Sema::DiagnoseExcessPrecision() {
-  if (NumExcessPrecisionNotSatisfied > 0) {
-    for (auto &[Loc, Type, Num] : ExcessPrecisionNotSatisfied)
-      Diag(Loc, diag::warn_excess_precision_not_supported)
-          << 0 << Type << static_cast<bool>(Num);
+void Sema::DiagnosePrecisionLossInComplexDivision() {
+  for (auto &[Type, Num] : ExcessPrecisionNotSatisfied) {
+    assert(LocationOfExcessPrecisionNotSatisfied.isValid() &&
+           "expected a valid source location");
+    Diag(LocationOfExcessPrecisionNotSatisfied,
+         diag::warn_excess_precision_not_supported)
+        << static_cast<bool>(Num);
   }
 }
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ccd9a878c892fd..1fbdeb428e31f2 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15083,9 +15083,8 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
     DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr);
 }
 
-static void DiagnosePrecisionLossInComplexDivision(Sema &S,
-                                                   SourceLocation OpLoc,
-                                                   Expr *Operand) {
+static void DetectPrecisionLossInComplexDivision(Sema &S, SourceLocation OpLoc,
+                                                 Expr *Operand) {
   if (auto *CT = Operand->getType()->getAs<ComplexType>()) {
     QualType ElementType = CT->getElementType();
     bool IsComplexRangePromoted = S.getLangOpts().getComplexRange() ==
@@ -15103,14 +15102,14 @@ static void DiagnosePrecisionLossInComplexDivision(Sema &S,
         if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
           S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
         S.NumExcessPrecisionNotSatisfied++;
-        for (auto &[Loc, Type, Num] : S.ExcessPrecisionNotSatisfied) {
+        for (auto &[Type, Num] : S.ExcessPrecisionNotSatisfied) {
           if (Type == HigherElementType) {
             Num++;
             return;
           }
         }
-        S.ExcessPrecisionNotSatisfied.push_back(std::make_tuple(
-            OpLoc, HigherElementType, S.NumExcessPrecisionNotSatisfied));
+        S.ExcessPrecisionNotSatisfied.push_back(std::make_pair(
+            HigherElementType, S.NumExcessPrecisionNotSatisfied));
       }
     }
   }
@@ -15129,7 +15128,7 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
   // Emit warnings if the requested higher precision type equal to the current
   // type precision.
   if (Kind == tok::TokenKind::slash)
-    DiagnosePrecisionLossInComplexDivision(*this, TokLoc, LHSExpr);
+    DetectPrecisionLossInComplexDivision(*this, TokLoc, LHSExpr);
 
   return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
 }
diff --git a/clang/test/Sema/complex-arithmetic.c b/clang/test/Sema/complex-arithmetic.c
index 41f7b88949168e..8c327e6d64383d 100644
--- a/clang/test/Sema/complex-arithmetic.c
+++ b/clang/test/Sema/complex-arithmetic.c
@@ -25,7 +25,7 @@ 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 at +1 {{excess precision is requested but the target does not support excess precision which may result in observable differences in arithmetic behavior ,additional use of 'long double' were found but not diagnosed}}
+  // div-precision-warning at +1 {{excess precision is requested but the target does not support excess precision which may result in observable differences in complex division behavior,additional uses where the requested higher precision cannot be honored were found but not diagnosed}}
   EVALF((2. + 3i) / (4. + 5i), .5609 + .0487i);
 }
 

>From 02516a7a9bd6007ff878162cd6ec47119acbbf7b Mon Sep 17 00:00:00 2001
From: Zahira Ammarguellat <zahira.ammarguellat at intel.com>
Date: Mon, 16 Sep 2024 09:11:50 -0700
Subject: [PATCH 8/8] Addressed review comments.

---
 clang/include/clang/AST/ASTContext.h | 3 +++
 clang/include/clang/Sema/Sema.h      | 1 -
 clang/lib/Sema/SemaExpr.cpp          | 3 +--
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index e203568230e491..fd8186d1bba5c2 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -783,11 +783,14 @@ class ASTContext : public RefCountedBase<ASTContext> {
   const QualType GetHigherPrecisionFPType(QualType ElementType) const {
     const auto *CurrentBT = cast<BuiltinType>(ElementType);
     switch (CurrentBT->getKind()) {
+    case BuiltinType::Kind::Half:
     case BuiltinType::Kind::Float16:
       return FloatTy;
     case BuiltinType::Kind::Float:
     case BuiltinType::Kind::BFloat16:
       return DoubleTy;
+    case BuiltinType::Kind::Float128:
+    case BuiltinType::Kind::Ibm128:
     case BuiltinType::Kind::Double:
       return LongDoubleTy;
     default:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f41e1969d2a0df..1a6a77b920c78c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7965,7 +7965,6 @@ class Sema final : public SemaBase {
   void maybeExtendBlockObject(ExprResult &E);
 
   std::vector<std::pair<QualType, unsigned>> ExcessPrecisionNotSatisfied;
-  unsigned NumExcessPrecisionNotSatisfied = 0;
   SourceLocation LocationOfExcessPrecisionNotSatisfied;
   void DiagnosePrecisionLossInComplexDivision();
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 1fbdeb428e31f2..b41874e299774d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -15101,7 +15101,6 @@ static void DetectPrecisionLossInComplexDivision(Sema &S, SourceLocation OpLoc,
         // Retain the location of the first use of higher precision type.
         if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
           S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
-        S.NumExcessPrecisionNotSatisfied++;
         for (auto &[Type, Num] : S.ExcessPrecisionNotSatisfied) {
           if (Type == HigherElementType) {
             Num++;
@@ -15109,7 +15108,7 @@ static void DetectPrecisionLossInComplexDivision(Sema &S, SourceLocation OpLoc,
           }
         }
         S.ExcessPrecisionNotSatisfied.push_back(std::make_pair(
-            HigherElementType, S.NumExcessPrecisionNotSatisfied));
+            HigherElementType, S.ExcessPrecisionNotSatisfied.size()));
       }
     }
   }



More information about the cfe-commits mailing list