diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h index 1464ce4e1b31b..6b32f7d70a9be 100644 --- a/clang/include/clang/Driver/CommonArgs.h +++ b/clang/include/clang/Driver/CommonArgs.h @@ -294,6 +294,11 @@ std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range); // Render a frontend option corresponding to ComplexRangeKind. std::string renderComplexRangeOption(LangOptions::ComplexRangeKind Range); +// Set the complex range and output a warning as needed. +void setComplexRange(const Driver &D, StringRef NewOpt, + LangOptions::ComplexRangeKind NewRange, StringRef &LastOpt, + LangOptions::ComplexRangeKind &Range); + } // end namespace tools } // end namespace driver } // end namespace clang diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index e7aabee273a34..a4a2b231bd860 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2744,42 +2744,6 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } } -static void EmitComplexRangeDiag(const Driver &D, StringRef LastOpt, - LangOptions::ComplexRangeKind Range, - StringRef NewOpt, - LangOptions::ComplexRangeKind NewRange) { - // 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= | -ffast-math | - // | -ffp-model= | -fno-fast-math | - // | -ffp-model= | -ffp-model= | - // | -fcomplex-arithmetic= | -fcomplex-arithmetic= | - if (LastOpt == NewOpt || NewOpt.empty() || LastOpt.empty() || - (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 == "-ffast-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; - - D.Diag(clang::diag::warn_drv_overriding_complex_range) - << LastOpt << NewOpt << complexRangeKindToStr(Range) - << complexRangeKindToStr(NewRange); -} - static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, bool OFastEnabled, const ArgList &Args, ArgStringList &CmdArgs, @@ -2836,27 +2800,19 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, std::string ComplexRangeStr; StringRef LastComplexRangeOption; - auto setComplexRange = [&](StringRef NewOption, - LangOptions::ComplexRangeKind NewRange) { - // Warn if user overrides the previously set complex number - // multiplication/division option. - if (Range != LangOptions::ComplexRangeKind::CX_None && Range != NewRange) - EmitComplexRangeDiag(D, LastComplexRangeOption, Range, NewOption, - NewRange); - LastComplexRangeOption = NewOption; - Range = NewRange; - }; - // Lambda to set fast-math options. This is also used by -ffp-model=fast auto applyFastMath = [&](bool Aggressive, StringRef CallerOption) { if (Aggressive) { HonorINFs = false; HonorNaNs = false; - setComplexRange(CallerOption, LangOptions::ComplexRangeKind::CX_Basic); + setComplexRange(D, CallerOption, LangOptions::ComplexRangeKind::CX_Basic, + LastComplexRangeOption, Range); } else { HonorINFs = true; HonorNaNs = true; - setComplexRange(CallerOption, LangOptions::ComplexRangeKind::CX_Promoted); + setComplexRange(D, CallerOption, + LangOptions::ComplexRangeKind::CX_Promoted, + LastComplexRangeOption, Range); } MathErrno = false; AssociativeMath = true; @@ -2908,18 +2864,24 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, default: continue; case options::OPT_fcx_limited_range: - setComplexRange(A->getSpelling(), - LangOptions::ComplexRangeKind::CX_Basic); + setComplexRange(D, A->getSpelling(), + LangOptions::ComplexRangeKind::CX_Basic, + LastComplexRangeOption, Range); break; case options::OPT_fno_cx_limited_range: - setComplexRange(A->getSpelling(), LangOptions::ComplexRangeKind::CX_Full); + setComplexRange(D, A->getSpelling(), + LangOptions::ComplexRangeKind::CX_Full, + LastComplexRangeOption, Range); break; case options::OPT_fcx_fortran_rules: - setComplexRange(A->getSpelling(), - LangOptions::ComplexRangeKind::CX_Improved); + setComplexRange(D, A->getSpelling(), + LangOptions::ComplexRangeKind::CX_Improved, + LastComplexRangeOption, Range); break; case options::OPT_fno_cx_fortran_rules: - setComplexRange(A->getSpelling(), LangOptions::ComplexRangeKind::CX_Full); + setComplexRange(D, A->getSpelling(), + LangOptions::ComplexRangeKind::CX_Full, + LastComplexRangeOption, Range); break; case options::OPT_fcomplex_arithmetic_EQ: { LangOptions::ComplexRangeKind RangeVal; @@ -2937,7 +2899,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, << A->getSpelling() << Val; break; } - setComplexRange(Args.MakeArgString(A->getSpelling() + Val), RangeVal); + setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val), RangeVal, + LastComplexRangeOption, Range); break; } case options::OPT_ffp_model_EQ: { @@ -2977,8 +2940,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, FPModel = Val; FPContract = "on"; LastFpContractOverrideOption = "-ffp-model=precise"; - setComplexRange(Args.MakeArgString(A->getSpelling() + Val), - LangOptions::ComplexRangeKind::CX_Full); + setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val), + LangOptions::ComplexRangeKind::CX_Full, + LastComplexRangeOption, Range); } else if (Val == "strict") { StrictFPModel = true; FPExceptionBehavior = "strict"; @@ -2987,8 +2951,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, LastFpContractOverrideOption = "-ffp-model=strict"; TrappingMath = true; RoundingFPMath = true; - setComplexRange(Args.MakeArgString(A->getSpelling() + Val), - LangOptions::ComplexRangeKind::CX_Full); + setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val), + LangOptions::ComplexRangeKind::CX_Full, + LastComplexRangeOption, Range); } else D.Diag(diag::err_drv_unsupported_option_argument) << A->getSpelling() << Val; @@ -3195,8 +3160,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, SignedZeros = true; restoreFPContractState(); if (Range != LangOptions::ComplexRangeKind::CX_Full) - setComplexRange(A->getSpelling(), - LangOptions::ComplexRangeKind::CX_None); + setComplexRange(D, A->getSpelling(), + LangOptions::ComplexRangeKind::CX_None, + LastComplexRangeOption, Range); else Range = LangOptions::ComplexRangeKind::CX_None; LastComplexRangeOption = ""; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 08cd98fd04df0..4f44f6f9110e7 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -3530,3 +3530,51 @@ tools::renderComplexRangeOption(LangOptionsBase::ComplexRangeKind Range) { return "-complex-range=" + ComplexRangeStr; return ComplexRangeStr; } + +static void emitComplexRangeDiag(const Driver &D, StringRef LastOpt, + LangOptions::ComplexRangeKind Range, + StringRef NewOpt, + LangOptions::ComplexRangeKind NewRange) { + // 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= | -ffast-math | + // | -ffp-model= | -fno-fast-math | + // | -ffp-model= | -ffp-model= | + // | -fcomplex-arithmetic= | -fcomplex-arithmetic= | + if (LastOpt == NewOpt || NewOpt.empty() || LastOpt.empty() || + (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 == "-ffast-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; + + D.Diag(clang::diag::warn_drv_overriding_complex_range) + << LastOpt << NewOpt << complexRangeKindToStr(Range) + << complexRangeKindToStr(NewRange); +} + +void tools::setComplexRange(const Driver &D, StringRef NewOpt, + LangOptions::ComplexRangeKind NewRange, + StringRef &LastOpt, + LangOptions::ComplexRangeKind &Range) { + // Warn if user overrides the previously set complex number + // multiplication/division option. + if (Range != LangOptions::ComplexRangeKind::CX_None && Range != NewRange) + emitComplexRangeDiag(D, LastOpt, Range, NewOpt, NewRange); + LastOpt = NewOpt; + Range = NewRange; +} diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 6fc372eb75eb7..e643c1e705609 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -649,6 +649,7 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args, bool AssociativeMath = false; bool ReciprocalMath = false; + StringRef LastComplexRangeOption; LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None; if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) { @@ -676,17 +677,22 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args, continue; case options::OPT_fcomplex_arithmetic_EQ: { + LangOptions::ComplexRangeKind NewRange; StringRef Val = A->getValue(); if (Val == "full") - Range = LangOptions::ComplexRangeKind::CX_Full; + NewRange = LangOptions::ComplexRangeKind::CX_Full; else if (Val == "improved") - Range = LangOptions::ComplexRangeKind::CX_Improved; + NewRange = LangOptions::ComplexRangeKind::CX_Improved; else if (Val == "basic") - Range = LangOptions::ComplexRangeKind::CX_Basic; + NewRange = LangOptions::ComplexRangeKind::CX_Basic; else { D.Diag(diag::err_drv_unsupported_option_argument) << A->getSpelling() << Val; + break; } + + setComplexRange(D, Args.MakeArgString(A->getSpelling() + Val), NewRange, + LastComplexRangeOption, Range); break; } case options::OPT_fhonor_infinities: @@ -735,6 +741,9 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args, ApproxFunc = true; SignedZeros = false; FPContract = "fast"; + setComplexRange(D, A->getSpelling(), + LangOptions::ComplexRangeKind::CX_Basic, + LastComplexRangeOption, Range); break; case options::OPT_fno_fast_math: HonorINFs = true; @@ -748,6 +757,9 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args, // --ffp-contract=off -fno-fast-math --> -ffp-contract=off if (FPContract == "fast") FPContract = ""; + setComplexRange(D, A->getSpelling(), + LangOptions::ComplexRangeKind::CX_None, + LastComplexRangeOption, Range); break; } diff --git a/flang/docs/ComplexOperations.md b/flang/docs/ComplexOperations.md index 3ebeea5e0a540..1b6ec527b446a 100644 --- a/flang/docs/ComplexOperations.md +++ b/flang/docs/ComplexOperations.md @@ -93,7 +93,9 @@ While [the same option in clang][2] allows specifying `promoted`, this is not implemented in Flang. Also, in the case of `improved`, clang does not handle NaN and infinite values, but Flang does. These behavioral differences arise because the transformation of complex division calculations depends on the implementation -of ComplexToStandard, which may change in the future. +of ComplexToStandard, which may change in the future. If you specify +`-ffast-math`, the lowering is the same as specifiying +`-fcomplex-arithmetic=basic`. [1]: https://discourse.llvm.org/t/rfc-change-lowering-of-fortran-math-intrinsics/63971 [2]: https://clang.llvm.org/docs/UsersManual.html#cmdoption-fcomplex-arithmetic diff --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md index 2b7d9d4ae6908..3286171bb1499 100644 --- a/flang/docs/FlangDriver.md +++ b/flang/docs/FlangDriver.md @@ -573,6 +573,9 @@ documentation for more details. These correspond to LLVM IR Fast Math attributes: https://llvm.org/docs/LangRef.html#fast-math-flags +In addition to the above, `-ffast-math` also enables +`-fcomplex-arithmetic=basic`. + When `-ffast-math` is specified, any linker steps generated by the compiler driver will also link to `crtfastmath.o`, which adds a static constructor that sets the FTZ/DAZ bits in MXCSR, affecting not only the current only the diff --git a/flang/test/Driver/complex-range.f90 b/flang/test/Driver/complex-range.f90 index e5a1ba9068ac9..575fa0437fd0d 100644 --- a/flang/test/Driver/complex-range.f90 +++ b/flang/test/Driver/complex-range.f90 @@ -15,6 +15,83 @@ ! RUN: not %flang -### -fcomplex-arithmetic=foo -c %s 2>&1 \ ! RUN: | FileCheck %s --check-prefix=ERR +! RUN: %flang -### -ffast-math -c %s 2>&1 \ +! RUN: | FileCheck %s --check-prefix=BASIC + +! RUN: %flang -### -fno-fast-math -c %s 2>&1 \ +! RUN: | FileCheck %s --check-prefix=RANGE + +! RUN: %flang -### -Werror -ffast-math -fno-fast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=RANGE %s + +! RUN: %flang -### -ffast-math -fcomplex-arithmetic=full -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=FULL,ARITH-FULL-OVERRIDING,FAST-OVERRIDDEN %s + +! RUN: %flang -### -ffast-math -fcomplex-arithmetic=improved -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=IMPRVD,ARITH-IMPROVED-OVERRIDING,FAST-OVERRIDDEN %s + +! RUN: %flang -### -Werror -ffast-math -fcomplex-arithmetic=basic -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC %s + +! RUN: %flang -### -Werror -fno-fast-math -ffast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC %s + +! RUN: %flang -### -Werror -fno-fast-math -fcomplex-arithmetic=full -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=FULL %s + +! RUN: %flang -### -Werror -fno-fast-math -fcomplex-arithmetic=improved -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=IMPRVD %s + +! RUN: %flang -### -Werror -fno-fast-math -fcomplex-arithmetic=basic -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC %s + +! RUN: %flang -### -fcomplex-arithmetic=full -ffast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC,FAST-OVERRIDING,ARITH-FULL-OVERRIDDEN %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=full -fno-fast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=RANGE %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=full -fcomplex-arithmetic=improved -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=IMPRVD %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=full -fcomplex-arithmetic=basic -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC %s + +! RUN: %flang -### -fcomplex-arithmetic=improved -ffast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC,FAST-OVERRIDING,ARITH-IMPROVED-OVERRIDDEN %s + +! RUN: %flang -### -fcomplex-arithmetic=improved -fno-fast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=RANGE,NOFAST-OVERRIDING,ARITH-IMPROVED-OVERRIDDEN %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=improved -fcomplex-arithmetic=full -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=FULL %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=improved -fcomplex-arithmetic=basic -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=basic -ffast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=BASIC %s + +! RUN: %flang -### -fcomplex-arithmetic=basic -fno-fast-math -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=RANGE,NOFAST-OVERRIDING,ARITH-BASIC-OVERRIDDEN %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=basic -fcomplex-arithmetic=full -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=FULL %s + +! RUN: %flang -### -Werror -fcomplex-arithmetic=basic -fcomplex-arithmetic=improved -c %s 2>&1 \ +! RUN: | FileCheck --check-prefixes=IMPRVD %s + + +! FAST-OVERRIDING: warning: '-ffast-math' sets complex range to "basic" +! NOFAST-OVERRIDING: warning: '-fno-fast-math' sets complex range to "none" +! ARITH-FULL-OVERRIDING: warning: '-fcomplex-arithmetic=full' sets complex range to "full" +! ARITH-IMPROVED-OVERRIDING: warning: '-fcomplex-arithmetic=improved' sets complex range to "improved" + +! FAST-OVERRIDDEN: overriding the setting of "basic" that was implied by '-ffast-math' [-Woverriding-complex-range] +! ARITH-FULL-OVERRIDDEN: overriding the setting of "full" that was implied by '-fcomplex-arithmetic=full' [-Woverriding-complex-range] +! ARITH-IMPROVED-OVERRIDDEN: overriding the setting of "improved" that was implied by '-fcomplex-arithmetic=improved' [-Woverriding-complex-range] +! ARITH-BASIC-OVERRIDDEN: overriding the setting of "basic" that was implied by '-fcomplex-arithmetic=basic' [-Woverriding-complex-range] + ! RANGE-NOT: -complex-range= ! FULL: -complex-range=full ! IMPRVD: -complex-range=improved