[clang] [clang][driver] Improve warning message for complex range overrides and GCC incompatibility (PR #149028)

Shunsuke Watanabe via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 16 00:07:55 PDT 2025


https://github.com/s-watanabe314 created https://github.com/llvm/llvm-project/pull/149028

This patch improves the warnings to show which user options overrides the complex range. It also warns when Clang's last-flag-wins rule causes incompatibility with GCC. When both warnings are necessary, a combined warning message is output by default, and the warning message can be changed using the -W option.

See also the discussion in the following discourse post:
https://discourse.llvm.org/t/the-priority-of-fno-fast-math-regarding-complex-number-calculations/84679

>From b11aa02619af8e4e86fc9ad64a42ff4eca327ade Mon Sep 17 00:00:00 2001
From: s-watanabe314 <watanabe.shu-06 at fujitsu.com>
Date: Tue, 8 Jul 2025 15:50:51 +0900
Subject: [PATCH] [clang][driver] Improve warning message for complex range
 overrides and GCC incompatibility

This patch improves the warnings to show which user options overrides
the complex range. It also warns when Clang's last-flag-wins rule causes
incompatibility with GCC. When both warnings are necessary, a combined
warning message is output by default, and the warning message can be
changed using the -W option.

See also the discussion in the following discourse post:
https://discourse.llvm.org/t/the-priority-of-fno-fast-math-regarding-complex-number-calculations/84679
---
 .../clang/Basic/DiagnosticDriverKinds.td      |   7 +
 clang/include/clang/Driver/Options.td         |  14 ++
 clang/lib/Driver/ToolChains/Clang.cpp         | 188 +++++++++---------
 clang/lib/Driver/ToolChains/CommonArgs.cpp    |   3 +
 clang/test/Driver/cl-options.c                |   6 +-
 clang/test/Driver/fp-model.c                  |  11 +-
 clang/test/Driver/range-wanings.c             | 121 +++++++++++
 clang/test/Driver/range.c                     |  63 +-----
 8 files changed, 251 insertions(+), 162 deletions(-)
 create mode 100644 clang/test/Driver/range-wanings.c

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 34b6c0d7a8acd..32264c27f6665 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -484,6 +484,13 @@ def warn_drv_overriding_option : Warning<
 def warn_drv_overriding_deployment_version
     : Warning<"overriding deployment version from '%0' to '%1'">,
       InGroup<DiagGroup<"overriding-deployment-version">>;
+def warn_drv_overriding_complex_range : Warning<
+  "'%1' sets complex range to \"%3\" overriding the setting of \"%2\" that was implied by '%0'">,
+  InGroup<DiagGroup<"overriding-complex-range">>;
+def warn_drv_gcc_incompatible_complex_range_override: Warning<
+  "%select{complex number caluculation|'%2' sets complex range to \"%4\" overriding the setting of \"%3\" that was implied by '%1' and this}0"
+  " is incompatible with GCC; specify '%1' after '%2' for compatibility">,
+  InGroup<GccCompat>;
 def warn_drv_treating_input_as_cxx : Warning<
   "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
   InGroup<Deprecated>;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index d0b54a446309b..5966bda040fdc 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -896,6 +896,20 @@ def Wsystem_headers_in_module_EQ : Joined<["-"], "Wsystem-headers-in-module=">,
 def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>,
   Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">;
+
+def Wgcc_compat : Flag<["-"], "Wgcc-compat">, Group<W_Group>,
+  Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Enable warnings for GCC Incompatible">;
+def Wno_gcc_compat : Flag<["-"], "Wno-gcc-compat">, Group<W_Group>,
+  Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Disable warnings for GCC Incompatible">;
+def Woverriding_complex_range : Flag<["-"], "Woverriding-complex-range">, Group<W_Group>,
+  Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Enable warnings for overriding complex range">;
+def Wno_overriding_complex_range : Flag<["-"], "Wno-overriding-complex-range">, Group<W_Group>,
+  Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Disable warnings for overriding complex range">;
+
 def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>,
   Visibility<[ClangOption, CC1Option]>;
 defm invalid_constexpr : BoolWOption<"invalid-constexpr",
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index fe1865888bdd0..a0e03290ea841 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2750,16 +2750,64 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
   }
 }
 
-static std::string ComplexArithmeticStr(LangOptions::ComplexRangeKind Range) {
-  return (Range == LangOptions::ComplexRangeKind::CX_None)
-             ? ""
-             : "-fcomplex-arithmetic=" + complexRangeKindToStr(Range);
-}
+static void EmitComplexRangeDiag(const Driver &D, StringRef LastOpt,
+                                 LangOptions::ComplexRangeKind Range,
+                                 StringRef NewOpt,
+                                 LangOptions::ComplexRangeKind NewRange,
+                                 bool EmitGCCWarning, bool EmitOverrideWaning) {
+  //  Do not emit a warning if NewOpt overrides LastOpt in the following cases.
+  //
+  // | LastOpt               | NewOpt                |
+  // |-----------------------|-----------------------|
+  // | -fcx-limited-range    | -fno-cx-limited-range |
+  // | -fno-cx-limited-range | -fcx-limited-range    |
+  // | -fcx-fortran-rules    | -fno-cx-fortran-rules |
+  // | -fno-cx-fortran-rules | -fcx-fortran-rules    |
+  // | -ffast-math           | -fno-fast-math        |
+  // | -ffp-model=           | -fno-fast-math        |
+  // | -ffp-model=           | -ffp-model=           |
+  // | -fcomplex-arithmetic= | -fcomplex-arithmetic= |
+  if ((LastOpt == "-fcx-limited-range" && NewOpt == "-fno-cx-limited-range") ||
+      (LastOpt == "-fno-cx-limited-range" && NewOpt == "-fcx-limited-range") ||
+      (LastOpt == "-fcx-fortran-rules" && NewOpt == "-fno-cx-fortran-rules") ||
+      (LastOpt == "-fno-cx-fortran-rules" && NewOpt == "-fcx-fortran-rules") ||
+      (LastOpt == "-ffast-math" && NewOpt == "-fno-fast-math") ||
+      (LastOpt.starts_with("-ffp-model=") && NewOpt == "-fno-fast-math") ||
+      (LastOpt.starts_with("-ffp-model=") &&
+       NewOpt.starts_with("-ffp-model=")) ||
+      (LastOpt.starts_with("-fcomplex-arithmetic=") &&
+       NewOpt.starts_with("-fcomplex-arithmetic=")))
+    return;
 
-static void EmitComplexRangeDiag(const Driver &D, std::string str1,
-                                 std::string str2) {
-  if (str1 != str2 && !str2.empty() && !str1.empty()) {
-    D.Diag(clang::diag::warn_drv_overriding_option) << str1 << str2;
+  // Emit GCC incompatible warning combined with overriding warning.
+  // In the following cases where NewOpt overrides LastOpt, incompatibility
+  // with GCC occurs.
+  //
+  // | LastOpt               | NewOpt                |
+  // |-----------------------|-----------------------|
+  // | -fcx-limited-range    | -fno-fast-math        |
+  // | -fcx-fortran-rules    | -fcx-limited-range    |
+  // | -fcx-fortran-rules    | -fno-cx-limited-range |
+  // | -fcx-fortran-rules    | -ffast-math           |
+  // | -fcx-fortran-rules    | -fno-fast-math        |
+  // | -fno-cx-fortran-rules | -fcx-limited-range    |
+  // | -fno-cx-fortran-rules | -ffast-math           |
+  if (EmitGCCWarning &&
+      ((LastOpt == "-fcx-limited-range" && NewOpt == "-fno-fast-math") ||
+       (LastOpt == "-fcx-fortran-rules" && NewOpt == "-fcx-limited-range") ||
+       (LastOpt == "-fcx-fortran-rules" && NewOpt == "-fno-cx-limited-range") ||
+       (LastOpt == "-fcx-fortran-rules" && NewOpt == "-ffast-math") ||
+       (LastOpt == "-fcx-fortran-rules" && NewOpt == "-fno-fast-math") ||
+       (LastOpt == "-fno-cx-fortran-rules" && NewOpt == "-fcx-limited-range") ||
+       (LastOpt == "-fno-cx-fortran-rules" && NewOpt == "-ffast-math"))) {
+    D.Diag(clang::diag::warn_drv_gcc_incompatible_complex_range_override)
+        << (EmitOverrideWaning ? 1 : 0) << LastOpt << NewOpt
+        << complexRangeKindToStr(Range) << complexRangeKindToStr(NewRange);
+  } else {
+    // Emit only overriding warning.
+    D.Diag(clang::diag::warn_drv_overriding_complex_range)
+        << LastOpt << NewOpt << complexRangeKindToStr(Range)
+        << complexRangeKindToStr(NewRange);
   }
 }
 
@@ -2817,31 +2865,33 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
   StringRef BFloat16ExcessPrecision = "";
   LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None;
   std::string ComplexRangeStr;
-  std::string GccRangeComplexOption;
-  std::string LastComplexRangeOption;
+  StringRef LastComplexRangeOption;
 
-  auto setComplexRange = [&](LangOptions::ComplexRangeKind NewRange) {
+  auto setComplexRange = [&](StringRef NewOption,
+                             LangOptions::ComplexRangeKind NewRange) {
     // Warn if user expects to perform full implementation of complex
     // multiplication or division in the presence of nnan or ninf flags.
-    if (Range != NewRange)
-      EmitComplexRangeDiag(D,
-                           !GccRangeComplexOption.empty()
-                               ? GccRangeComplexOption
-                               : ComplexArithmeticStr(Range),
-                           ComplexArithmeticStr(NewRange));
+    if (Range != LangOptions::ComplexRangeKind::CX_None && Range != NewRange)
+      EmitComplexRangeDiag(
+          D, LastComplexRangeOption, Range, NewOption, NewRange,
+          Args.hasFlag(options::OPT_Wgcc_compat, options::OPT_Wno_gcc_compat,
+                       true),
+          Args.hasFlag(options::OPT_Woverriding_complex_range,
+                       options::OPT_Wno_overriding_complex_range, true));
+    LastComplexRangeOption = NewOption;
     Range = NewRange;
   };
 
   // Lambda to set fast-math options. This is also used by -ffp-model=fast
-  auto applyFastMath = [&](bool Aggressive) {
+  auto applyFastMath = [&](bool Aggressive, StringRef CallerOption) {
     if (Aggressive) {
       HonorINFs = false;
       HonorNaNs = false;
-      setComplexRange(LangOptions::ComplexRangeKind::CX_Basic);
+      setComplexRange(CallerOption, LangOptions::ComplexRangeKind::CX_Basic);
     } else {
       HonorINFs = true;
       HonorNaNs = true;
-      setComplexRange(LangOptions::ComplexRangeKind::CX_Promoted);
+      setComplexRange(CallerOption, LangOptions::ComplexRangeKind::CX_Promoted);
     }
     MathErrno = false;
     AssociativeMath = true;
@@ -2893,54 +2943,18 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
     default: continue;
 
     case options::OPT_fcx_limited_range:
-      if (GccRangeComplexOption.empty()) {
-        if (Range != LangOptions::ComplexRangeKind::CX_Basic)
-          EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
-                               "-fcx-limited-range");
-      } else {
-        if (GccRangeComplexOption != "-fno-cx-limited-range")
-          EmitComplexRangeDiag(D, GccRangeComplexOption, "-fcx-limited-range");
-      }
-      GccRangeComplexOption = "-fcx-limited-range";
-      LastComplexRangeOption = A->getSpelling();
-      Range = LangOptions::ComplexRangeKind::CX_Basic;
+      setComplexRange(A->getSpelling(),
+                      LangOptions::ComplexRangeKind::CX_Basic);
       break;
     case options::OPT_fno_cx_limited_range:
-      if (GccRangeComplexOption.empty()) {
-        EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
-                             "-fno-cx-limited-range");
-      } else {
-        if (GccRangeComplexOption != "-fcx-limited-range" &&
-            GccRangeComplexOption != "-fno-cx-fortran-rules")
-          EmitComplexRangeDiag(D, GccRangeComplexOption,
-                               "-fno-cx-limited-range");
-      }
-      GccRangeComplexOption = "-fno-cx-limited-range";
-      LastComplexRangeOption = A->getSpelling();
-      Range = LangOptions::ComplexRangeKind::CX_Full;
+      setComplexRange(A->getSpelling(), LangOptions::ComplexRangeKind::CX_Full);
       break;
     case options::OPT_fcx_fortran_rules:
-      if (GccRangeComplexOption.empty())
-        EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
-                             "-fcx-fortran-rules");
-      else
-        EmitComplexRangeDiag(D, GccRangeComplexOption, "-fcx-fortran-rules");
-      GccRangeComplexOption = "-fcx-fortran-rules";
-      LastComplexRangeOption = A->getSpelling();
-      Range = LangOptions::ComplexRangeKind::CX_Improved;
+      setComplexRange(A->getSpelling(),
+                      LangOptions::ComplexRangeKind::CX_Improved);
       break;
     case options::OPT_fno_cx_fortran_rules:
-      if (GccRangeComplexOption.empty()) {
-        EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
-                             "-fno-cx-fortran-rules");
-      } else {
-        if (GccRangeComplexOption != "-fno-cx-limited-range")
-          EmitComplexRangeDiag(D, GccRangeComplexOption,
-                               "-fno-cx-fortran-rules");
-      }
-      GccRangeComplexOption = "-fno-cx-fortran-rules";
-      LastComplexRangeOption = A->getSpelling();
-      Range = LangOptions::ComplexRangeKind::CX_Full;
+      setComplexRange(A->getSpelling(), LangOptions::ComplexRangeKind::CX_Full);
       break;
     case options::OPT_fcomplex_arithmetic_EQ: {
       LangOptions::ComplexRangeKind RangeVal;
@@ -2958,25 +2972,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
             << A->getSpelling() << Val;
         break;
       }
-      if (!GccRangeComplexOption.empty()) {
-        if (GccRangeComplexOption != "-fcx-limited-range") {
-          if (GccRangeComplexOption != "-fcx-fortran-rules") {
-            if (RangeVal != LangOptions::ComplexRangeKind::CX_Improved)
-              EmitComplexRangeDiag(D, GccRangeComplexOption,
-                                   ComplexArithmeticStr(RangeVal));
-          } else {
-            EmitComplexRangeDiag(D, GccRangeComplexOption,
-                                 ComplexArithmeticStr(RangeVal));
-          }
-        } else {
-          if (RangeVal != LangOptions::ComplexRangeKind::CX_Basic)
-            EmitComplexRangeDiag(D, GccRangeComplexOption,
-                                 ComplexArithmeticStr(RangeVal));
-        }
-      }
-      LastComplexRangeOption =
-          Args.MakeArgString(A->getSpelling() + A->getValue());
-      Range = RangeVal;
+      setComplexRange(Args.MakeArgString(A->getSpelling() + Val),
+                      RangeVal);
       break;
     }
     case options::OPT_ffp_model_EQ: {
@@ -3004,19 +3001,20 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
             << Args.MakeArgString("-ffp-model=" + Val);
       if (Val == "fast") {
         FPModel = Val;
-        applyFastMath(false);
+        applyFastMath(false, Args.MakeArgString(A->getSpelling() + Val));
         // applyFastMath sets fp-contract="fast"
         LastFpContractOverrideOption = "-ffp-model=fast";
       } else if (Val == "aggressive") {
         FPModel = Val;
-        applyFastMath(true);
+        applyFastMath(true, Args.MakeArgString(A->getSpelling() + Val));
         // applyFastMath sets fp-contract="fast"
         LastFpContractOverrideOption = "-ffp-model=aggressive";
       } else if (Val == "precise") {
         FPModel = Val;
         FPContract = "on";
         LastFpContractOverrideOption = "-ffp-model=precise";
-        setComplexRange(LangOptions::ComplexRangeKind::CX_Full);
+        setComplexRange(Args.MakeArgString(A->getSpelling() + Val),
+                        LangOptions::ComplexRangeKind::CX_Full);
       } else if (Val == "strict") {
         StrictFPModel = true;
         FPExceptionBehavior = "strict";
@@ -3025,11 +3023,11 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
         LastFpContractOverrideOption = "-ffp-model=strict";
         TrappingMath = true;
         RoundingFPMath = true;
-        setComplexRange(LangOptions::ComplexRangeKind::CX_Full);
+        setComplexRange(Args.MakeArgString(A->getSpelling() + Val),
+                        LangOptions::ComplexRangeKind::CX_Full);
       } else
         D.Diag(diag::err_drv_unsupported_option_argument)
             << A->getSpelling() << Val;
-      LastComplexRangeOption = A->getSpelling();
       break;
     }
 
@@ -3214,8 +3212,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
         continue;
       [[fallthrough]];
     case options::OPT_ffast_math:
-      applyFastMath(true);
-      LastComplexRangeOption = A->getSpelling();
+      applyFastMath(true, A->getSpelling());
       if (A->getOption().getID() == options::OPT_Ofast)
         LastFpContractOverrideOption = "-Ofast";
       else
@@ -3233,15 +3230,12 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
       ApproxFunc = false;
       SignedZeros = true;
       restoreFPContractState();
-      // If the last specified option related to complex range is not
-      // -ffast-math or -ffp-model=, emit warning.
-      if (LastComplexRangeOption != "-ffast-math" &&
-          LastComplexRangeOption != "-ffp-model=" &&
-          Range != LangOptions::ComplexRangeKind::CX_Full)
-        EmitComplexRangeDiag(D, LastComplexRangeOption, "-fno-fast-math");
-      Range = LangOptions::ComplexRangeKind::CX_None;
+      if (Range != LangOptions::ComplexRangeKind::CX_Full)
+        setComplexRange(A->getSpelling(),
+                        LangOptions::ComplexRangeKind::CX_None);
+      else
+        Range = LangOptions::ComplexRangeKind::CX_None;
       LastComplexRangeOption = "";
-      GccRangeComplexOption = "";
       LastFpContractOverrideOption = "";
       break;
     } // End switch (A->getOption().getID())
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 097d186ad8ea4..c0fddd2f6c204 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3435,6 +3435,9 @@ std::string tools::complexRangeKindToStr(LangOptions::ComplexRangeKind Range) {
   case LangOptions::ComplexRangeKind::CX_Promoted:
     return "promoted";
     break;
+  case LangOptions::ComplexRangeKind::CX_None:
+    return "none";
+    break;
   default:
     return "";
   }
diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c
index 57e16e8795a28..627592e808d78 100644
--- a/clang/test/Driver/cl-options.c
+++ b/clang/test/Driver/cl-options.c
@@ -54,11 +54,13 @@
 // fpfast: -funsafe-math-optimizations
 // fpfast: -ffast-math
 
-// RUN: %clang_cl /fp:fast /fp:precise -### -- %s 2>&1 | FileCheck -check-prefix=fpprecise %s
+// RUN: %clang_cl /fp:fast /fp:precise -Wno-overriding-complex-range -### -- %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=fpprecise %s
 // fpprecise-NOT: -funsafe-math-optimizations
 // fpprecise-NOT: -ffast-math
 
-// RUN: %clang_cl /fp:fast /fp:strict -### -- %s 2>&1 | FileCheck -check-prefix=fpstrict %s
+// RUN: %clang_cl /fp:fast /fp:strict -Wno-overriding-complex-range -### -- %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=fpstrict %s
 // fpstrict-NOT: -funsafe-math-optimizations
 // fpstrict-NOT: -ffast-math
 // fpstrict: -ffp-contract=off
diff --git a/clang/test/Driver/fp-model.c b/clang/test/Driver/fp-model.c
index 6f17d4aeb1ef5..9cf5d0c53b24b 100644
--- a/clang/test/Driver/fp-model.c
+++ b/clang/test/Driver/fp-model.c
@@ -81,8 +81,7 @@
 // WARN12: warning: overriding '-ffp-model=strict' option with '-Ofast'
 
 // RUN: %clang -### -ffast-math -ffp-model=strict -c %s 2>&1 | FileCheck \
-// RUN:   --check-prefix=WARN-CX-BASIC-TO-FULL %s
-// WARN-CX-BASIC-TO-FULL: warning: overriding '-fcomplex-arithmetic=basic' option with '-fcomplex-arithmetic=full'
+// RUN:   --check-prefix=CHECK-FASTMATH-FPM-STRICT %s
 
 // RUN: %clang -### -ffp-model=strict -fapprox-func -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=WARN13 %s
@@ -205,7 +204,7 @@
 
 // RUN: %clang -### -nostdinc -ffast-math -ffp-model=fast -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-FASTMATH-FPM-FAST %s
-// CHECK-FASTMATH-FPM-FAST: warning: overriding '-fcomplex-arithmetic=basic' option with '-fcomplex-arithmetic=promoted'
+// CHECK-FASTMATH-FPM-FAST: warning: '-ffp-model=fast' sets complex range to "promoted" overriding the setting of "basic" that was implied by '-ffast-math'
 // CHECK-FASTMATH-FPM-FAST: "-cc1"
 // CHECK-FASTMATH-FPM-FAST-NOT: "-menable-no-infs"
 // CHECK-FASTMATH-FPM-FAST-NOT: "-menable-no-nans"
@@ -221,7 +220,8 @@
 // CHECK-FASTMATH-FPM-FAST-SAME: "-complex-range=promoted"
 
 // RUN: %clang -### -nostdinc -ffast-math -ffp-model=precise -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefixes=CHECK-FASTMATH-FPM-PRECISE,WARN-CX-BASIC-TO-FULL %s
+// RUN:   | FileCheck --check-prefixes=CHECK-FASTMATH-FPM-PRECISE %s
+// CHECK-FASTMATH-FPM-PRECISE: warning: '-ffp-model=precise' sets complex range to "full" overriding the setting of "basic" that was implied by '-ffast-math'
 // CHECK-FASTMATH-FPM-PRECISE:     "-cc1"
 // CHECK-FASTMATH-FPM-PRECISE-NOT: "-menable-no-infs"
 // CHECK-FASTMATH-FPM-PRECISE-NOT: "-menable-no-nans"
@@ -237,7 +237,8 @@
 // CHECK-FASTMATH-FPM-PRECISE-SAME: "-complex-range=full"
 
 // RUN: %clang -### -nostdinc -ffast-math -ffp-model=strict -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefixes=CHECK-FASTMATH-FPM-STRICT,WARN-CX-BASIC-TO-FULL %s
+// RUN:   | FileCheck --check-prefixes=CHECK-FASTMATH-FPM-STRICT %s
+// CHECK-FASTMATH-FPM-STRICT: warning: '-ffp-model=strict' sets complex range to "full" overriding the setting of "basic" that was implied by '-ffast-math'
 // CHECK-FASTMATH-FPM-STRICT:     "-cc1"
 // CHECK-FASTMATH-FPM-STRICT-NOT: "-menable-no-infs"
 // CHECK-FASTMATH-FPM-STRICT-NOT: "-menable-no-nans"
diff --git a/clang/test/Driver/range-wanings.c b/clang/test/Driver/range-wanings.c
new file mode 100644
index 0000000000000..9eab4c90dad75
--- /dev/null
+++ b/clang/test/Driver/range-wanings.c
@@ -0,0 +1,121 @@
+// Test overriding warnings about complex range.
+// range.c tests the settings of -complex-range=, and this test covers
+// all warnings related to complex range.
+// [draft] The tests for Case A are currently insufficient, but in the
+// formal pull request, tests for all combinations of options will be
+// added.
+
+// Clang options related to complex range are as follows:
+// -f[no-]cx-limited-range
+// -f[no-]cx-fortran-rules
+// -fcomplex-arithmetic=[full|improved|promoted|basic]
+// -ffp-model=[strict|precise|fast|aggressive]
+// -f[no-]fast-math
+
+// Case A: Overriding Warnings
+// Emit warnings about overriding when options implying different
+// complex ranges are specified. However, warnings are not emitted in
+// the following cases:
+// (a) When the positive/negative form or a different value of the same
+//     option is specified. 
+//       Example: -fcx-limited-range -fno-cx-limited-range
+// (b) When -ffp-model= is negated by -fno-fast-math. 
+//       Example: -ffp-model=fast -fno-fast-math
+
+// Case B: GCC Incompatibility Warnings
+// Emit warnings because the following cases result in behavior
+// incompatible with GCC:
+// (a) -fcx-limited-range    -fno-fast-math
+// (b) -fcx-fortran-rules    -fcx-limited-range
+// (c) -fcx-fortran-rules    -fno-cx-limited-range
+// (d) -fcx-fortran-rules    -ffast-math
+// (e) -fcx-fortran-rules    -fno-fast-math
+// (f) -fno-cx-fortran-rules -fcx-limited-range
+// (g) -fno-cx-fortran-rules -ffast-math
+
+// Case C: Combined A and B Warnings
+// Emit combined warnings when both A and B apply. This is the default
+// warning when both apply. The warning message changes to Case A or B
+// if the user specifies -Wno-gcc-compat or -Wno-overriding-complex-range.
+
+
+// Test A
+// RUN: %clang -### -fcx-fortran-rules -fcx-limited-range -c -Woverriding-complex-range -Wno-gcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=OVR_WARN1 %s
+
+// RUN: %clang -### -fcomplex-arithmetic=improved  -ffp-model=aggressive -c -Woverriding-complex-range -Wno-gcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=OVR_WARN2 %s
+
+// RUN: %clang -### -Werror -fcx-limited-range -fno-cx-limited-range -c -Woverriding-complex-range -Wno-gcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=OVR_WARN %s
+
+// RUN: %clang -### -ffp-model=fast -ffp-model=strict -c -Woverriding-complex-range -Wno-gcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=OVR_WARN %s
+
+// RUN: %clang -### -Werror -ffp-model=fast -fno-fast-math -c -Woverriding-complex-range -Wno-gcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=OVR_WARN %s
+
+
+// Test B
+// RUN: %clang -### -fcx-limited-range -fno-fast-math -c -Wno-overriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CMPT_WARN1 %s
+
+// RUN: %clang -### -fcx-fortran-rules -fcx-limited-range -c -Wno-overriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CMPT_WARN2 %s
+
+// RUN: %clang -### -fcx-fortran-rules -fno-cx-limited-range -c -Wno-overriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CMPT_WARN3 %s
+
+// RUN: %clang -### -fcx-fortran-rules -ffast-math -c -Wno-overriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CMPT_WARN4 %s
+
+// RUN: %clang -### -fcx-fortran-rules -fno-fast-math -c -Wno-overriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CMPT_WARN5 %s
+
+// RUN: %clang -### -fno-cx-fortran-rules -fcx-limited-range -c -Wno-overriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CMPT_WARN6 %s
+
+// RUN: %clang -### -fno-cx-fortran-rules -ffast-math -c -Wno-overriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=CMPT_WARN7 %s
+
+
+// Test C
+// RUN: %clang -### -fcx-limited-range -fno-fast-math -c -Woverriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=COMBO_WARN1 %s
+
+// RUN: %clang -### -fcx-fortran-rules -fcx-limited-range -c -Woverriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=COMBO_WARN2 %s
+
+// RUN: %clang -### -fcx-fortran-rules -fno-cx-limited-range -c -Woverriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=COMBO_WARN3 %s
+
+// RUN: %clang -### -fcx-fortran-rules -ffast-math -c -Woverriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=COMBO_WARN4 %s
+
+// RUN: %clang -### -fcx-fortran-rules -fno-fast-math -c -Woverriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=COMBO_WARN5 %s
+
+// RUN: %clang -### -fno-cx-fortran-rules -fcx-limited-range -c -Woverriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=COMBO_WARN6 %s
+
+// RUN: %clang -### -fno-cx-fortran-rules -ffast-math -c -Woverriding-complex-range -Wgcc-compat %s 2>&1 \
+// RUN:   | FileCheck --check-prefixes=COMBO_WARN7 %s
+
+
+// OVR_WARN-NOT: [-Woverriding-complex-range]
+// OVR_WARN1: warning: '-fcx-limited-range' sets complex range to "basic" overriding the setting of "improved" that was implied by '-fcx-fortran-rules' [-Woverriding-complex-range]
+// OVR_WARN2: warning: '-ffp-model=aggressive' sets complex range to "basic" overriding the setting of "improved" that was implied by '-fcomplex-arithmetic=improved' [-Woverriding-complex-range]
+// CMPT_WARN1: warning: complex number caluculation is incompatible with GCC; specify '-fcx-limited-range' after '-fno-fast-math' for compatibility [-Wgcc-compat]
+// CMPT_WARN2: warning: complex number caluculation is incompatible with GCC; specify '-fcx-fortran-rules' after '-fcx-limited-range' for compatibility [-Wgcc-compat]
+// CMPT_WARN3: warning: complex number caluculation is incompatible with GCC; specify '-fcx-fortran-rules' after '-fno-cx-limited-range' for compatibility [-Wgcc-compat]
+// CMPT_WARN4: warning: complex number caluculation is incompatible with GCC; specify '-fcx-fortran-rules' after '-ffast-math' for compatibility [-Wgcc-compat]
+// CMPT_WARN5: warning: complex number caluculation is incompatible with GCC; specify '-fcx-fortran-rules' after '-fno-fast-math' for compatibility [-Wgcc-compat]
+// CMPT_WARN6: warning: complex number caluculation is incompatible with GCC; specify '-fno-cx-fortran-rules' after '-fcx-limited-range' for compatibility [-Wgcc-compat]
+// CMPT_WARN7: warning: complex number caluculation is incompatible with GCC; specify '-fno-cx-fortran-rules' after '-ffast-math' for compatibility [-Wgcc-compat]
+// COMBO_WARN1: warning: '-fno-fast-math' sets complex range to "none" overriding the setting of "basic" that was implied by '-fcx-limited-range' and this is incompatible with GCC; specify '-fcx-limited-range' after '-fno-fast-math' for compatibility [-Wgcc-compat]
+// COMBO_WARN2: warning: '-fcx-limited-range' sets complex range to "basic" overriding the setting of "improved" that was implied by '-fcx-fortran-rules' and this is incompatible with GCC; specify '-fcx-fortran-rules' after '-fcx-limited-range' for compatibility [-Wgcc-compat]
+// COMBO_WARN3: warning: '-fno-cx-limited-range' sets complex range to "full" overriding the setting of "improved" that was implied by '-fcx-fortran-rules' and this is incompatible with GCC; specify '-fcx-fortran-rules' after '-fno-cx-limited-range' for compatibility [-Wgcc-compat]
+// COMBO_WARN4: warning: '-ffast-math' sets complex range to "basic" overriding the setting of "improved" that was implied by '-fcx-fortran-rules' and this is incompatible with GCC; specify '-fcx-fortran-rules' after '-ffast-math' for compatibility [-Wgcc-compat]
+// COMBO_WARN5: warning: '-fno-fast-math' sets complex range to "none" overriding the setting of "improved" that was implied by '-fcx-fortran-rules' and this is incompatible with GCC; specify '-fcx-fortran-rules' after '-fno-fast-math' for compatibility [-Wgcc-compat]
+// COMBO_WARN6: warning: '-fcx-limited-range' sets complex range to "basic" overriding the setting of "full" that was implied by '-fno-cx-fortran-rules' and this is incompatible with GCC; specify '-fno-cx-fortran-rules' after '-fcx-limited-range' for compatibility [-Wgcc-compat]
+// COMBO_WARN7: warning: '-ffast-math' sets complex range to "basic" overriding the setting of "full" that was implied by '-fno-cx-fortran-rules' and this is incompatible with GCC; specify '-fno-cx-fortran-rules' after '-ffast-math' for compatibility [-Wgcc-compat]
diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c
index 30140f3c208e0..bcad88ec6ecb8 100644
--- a/clang/test/Driver/range.c
+++ b/clang/test/Driver/range.c
@@ -6,12 +6,6 @@
 // RUN: %clang -### -target x86_64 -fno-cx-limited-range -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=FULL %s
 
-// RUN: %clang -### -target x86_64 -fcx-limited-range -fcx-fortran-rules \
-// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN1 %s
-
-// RUN: %clang -### -target x86_64 -fno-cx-limited-range -fcx-fortran-rules \
-// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN2 %s
-
 // RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-limited-range \
 // RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s
 
@@ -24,9 +18,6 @@
 // RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -fno-cx-limited-range \
 // RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s
 
-// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-fortran-rules \
-// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN4 %s
-
 // RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=IMPRVD %s
 
@@ -36,25 +27,12 @@
 // RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
 // RUN:   -fno-cx-fortran-rules | FileCheck --check-prefix=FULL %s
 
-// RUN: %clang -### -target x86_64 -fcx-fortran-rules -fno-cx-limited-range \
-// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN3 %s
-
 // RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -c %s 2>&1 \
 // RUN:   | FileCheck  %s
 
-// RUN: %clang -### -target x86_64 -fcx-limited-range -fcx-fortran-rules \
-// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN1 %s
-
-// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-fortran-rules \
-// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN4 %s
-
 // RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-limited-range \
 // RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s
 
-// RUN: %clang -### -target x86_64 -fcx-fortran-rules \
-// RUN: -fcx-limited-range  -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=WARN20 %s
-
 // RUN: %clang -### -target x86_64 -ffast-math -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=BASIC %s
 
@@ -90,14 +68,6 @@
 // RUN: -fcomplex-arithmetic=improved -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=IMPRVD %s
 
-// RUN: %clang -### -target x86_64 -fcx-limited-range \
-// RUN: -fcomplex-arithmetic=improved -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=WARN6 %s
-
-// RUN: %clang -### -target x86_64 -fcx-fortran-rules \
-// RUN: -fcomplex-arithmetic=basic -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=WARN7 %s
-
 // RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \
 // RUN: -fcomplex-arithmetic=full -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=FULL %s
@@ -123,10 +93,6 @@
 // RUN: -fcomplex-arithmetic=basic  -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=BASIC %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \
-// RUN: -fcx-limited-range  -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=WARN14 %s
-
 // RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \
 // RUN: -fcomplex-arithmetic=improved  -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=IMPRVD %s
@@ -139,9 +105,6 @@
 // RUN: -fcomplex-arithmetic=basic  -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=BASIC %s
 
-// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \
-// RUN: -ffast-math  -c %s 2>&1 | FileCheck --check-prefix=WARN17 %s
-
 // RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \
 // RUN: -fcomplex-arithmetic=improved  -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=IMPRVD %s
@@ -178,13 +141,13 @@
 // RUN:   | FileCheck --check-prefix=BASIC %s
 
 // RUN: %clang -### --target=x86_64 -fcx-limited-range -fno-fast-math \
-// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE,WARN21 %s
+// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
 
 // RUN: %clang -### -Werror --target=x86_64 -fno-cx-limited-range -fno-fast-math \
 // RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
 
 // RUN: %clang -### --target=x86_64 -fcx-fortran-rules -fno-fast-math \
-// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE,WARN22 %s
+// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
 
 // RUN: %clang -### -Werror --target=x86_64 -fno-cx-fortran-rules -fno-fast-math \
 // RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
@@ -193,13 +156,13 @@
 // RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
 
 // RUN: %clang -### --target=x86_64 -fcomplex-arithmetic=basic -fno-fast-math \
-// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE,WARN23 %s
+// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
 
 // RUN: %clang -### --target=x86_64 -fcomplex-arithmetic=promoted -fno-fast-math \
-// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE,WARN24 %s
+// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
 
 // RUN: %clang -### --target=x86_64 -fcomplex-arithmetic=improved -fno-fast-math \
-// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE,WARN25 %s
+// RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
 
 // RUN: %clang -### -Werror --target=x86_64 -fcomplex-arithmetic=full -fno-fast-math \
 // RUN:   -c %s 2>&1 | FileCheck --check-prefixes=RANGE %s
@@ -255,22 +218,6 @@
 // RUN: %clang -### -Werror --target=x86_64 -fno-fast-math -ffp-model=strict \
 // RUN:   -c %s 2>&1 | FileCheck --check-prefixes=FULL %s
 
-// WARN1: warning: overriding '-fcx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option]
-// WARN2: warning: overriding '-fno-cx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option]
-// WARN3: warning: overriding '-fcx-fortran-rules' option with '-fno-cx-limited-range' [-Woverriding-option]
-// WARN4: warning: overriding '-fcx-limited-range' option with '-fno-cx-fortran-rules' [-Woverriding-option]
-// WARN5: warning: overriding '-fcomplex-arithmetic=basic' option with '-fcomplex-arithmetic=improved' [-Woverriding-option]
-// WARN6: warning: overriding '-fcx-limited-range' option with '-fcomplex-arithmetic=improved' [-Woverriding-option]
-// WARN7: warning: overriding '-fcx-fortran-rules' option with '-fcomplex-arithmetic=basic' [-Woverriding-option]
-// WARN14: overriding '-complex-range=promoted' option with '-fcx-limited-range' [-Woverriding-option]
-// WARN17: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=basic' [-Woverriding-option]
-// WARN20: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option]
-// WARN21: warning: overriding '-fcx-limited-range' option with '-fno-fast-math' [-Woverriding-option]
-// WARN22: warning: overriding '-fcx-fortran-rules' option with '-fno-fast-math' [-Woverriding-option]
-// WARN23: warning: overriding '-fcomplex-arithmetic=basic' option with '-fno-fast-math' [-Woverriding-option]
-// WARN24: warning: overriding '-fcomplex-arithmetic=promoted' option with '-fno-fast-math' [-Woverriding-option]
-// WARN25: warning: overriding '-fcomplex-arithmetic=improved' option with '-fno-fast-math' [-Woverriding-option]
-
 // BASIC: -complex-range=basic
 // FULL: -complex-range=full
 // PRMTD: -complex-range=promoted



More information about the cfe-commits mailing list