Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
90 changes: 28 additions & 62 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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: {
Expand Down Expand Up @@ -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";
Expand All @@ -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;
Expand Down Expand Up @@ -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 = "";
Expand Down
48 changes: 48 additions & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
18 changes: 15 additions & 3 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down
4 changes: 3 additions & 1 deletion flang/docs/ComplexOperations.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions flang/docs/FlangDriver.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
77 changes: 77 additions & 0 deletions flang/test/Driver/complex-range.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down