diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1847,6 +1847,16 @@ "Determines whether to lower _Complex operations to LLVM complex " "intrinsics">, NegFlag>; +def fcx_limited_range : Flag<["-"], "fcx-limited-range">, Group; +def fnocx_limited_range : Flag<["-"], "fnocx-limited-range">, Group; +def fcx_fortran_rules : Flag<["-"], "fcx-fortran-rules">, Group; +def fnocx_fortran_rules : Flag<["-"], "fnocx-fortran-rules">, Group; +def cx_rangeEQ : Joined<["-"], "fcx-range=">, Group, Flags<[CC1Option]>, + HelpText<"Specifies the behavior of complex multiplication and division">, + Values<"limited,nonan,full">, + NormalizedValuesScope<"LangOptions">, + NormalizedValues<["CX_Limited", "CX_NoNan", "CX_Full"]>, + MarshallingInfoEnum, "CX_Full">; def ffor_scope : Flag<["-"], "ffor-scope">, Group; def fno_for_scope : Flag<["-"], "fno-for-scope">, Group; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2696,6 +2696,19 @@ // overriden by ffp-exception-behavior? bool RoundingFPMath = false; bool RoundingMathPresent = false; // Is rounding-math in args? + LangOptions::ComplexRangeKind CxRangeArg = + LangOptions::CX_Full; + StringRef RulingRangeArg = ""; + auto setCxRangeArg = [&CxRangeArg, &RulingRangeArg, &D, &Args]( + LangOptions::ComplexRangeKind Kind, StringRef ArgName) { + if (!RulingRangeArg.empty() && Kind != CxRangeArg) { + D.Diag(clang::diag::warn_drv_overriding_flag_option) + << Args.MakeArgString(RulingRangeArg) + << Args.MakeArgString(ArgName); + } + RulingRangeArg = ArgName; + CxRangeArg = Kind; + }; // -ffp-model values: strict, fast, precise StringRef FPModel = ""; // -ffp-exception-behavior options: strict, maytrap, ignore @@ -2942,6 +2955,7 @@ RoundingFPMath = false; // If fast-math is set then set the fp-contract mode to fast. FPContract = "fast"; + CxRangeArg = LangOptions::CX_NoNan; break; case options::OPT_fno_fast_math: HonorINFs = true; @@ -2966,6 +2980,19 @@ << "-ffp-contract=on"; } break; + + case options::OPT_fcx_limited_range: + setCxRangeArg(LangOptions::CX_Limited, "fcx-limited-range"); + break; + case options::OPT_fnocx_limited_range: + setCxRangeArg(LangOptions::CX_Full, "fcx-limited-range"); + break; + case options::OPT_fcx_fortran_rules: + setCxRangeArg(LangOptions::CX_NoNan, "fcx-fortran-rules"); + break; + case options::OPT_fnocx_fortran_rules: + setCxRangeArg(LangOptions::CX_Full, "fcx-fortran-rules"); + break; } if (StrictFPModel) { // If -ffp-model=strict has been specified on command line but @@ -3103,6 +3130,18 @@ DefaultUseComplexIntrinsics)) { CmdArgs.push_back("-fuse-complex-intrinsics"); } + + switch (CxRangeArg) { + case LangOptions::CX_Limited: + CmdArgs.push_back("-fcx-range=limited"); + break; + case LangOptions::CX_NoNan: + CmdArgs.push_back("-fcx-range=nonan"); + break; + case LangOptions::CX_Full: + CmdArgs.push_back("-fcx-range=full"); + break; + } } static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs, diff --git a/clang/test/Driver/complex-range-flags.c b/clang/test/Driver/complex-range-flags.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/complex-range-flags.c @@ -0,0 +1,21 @@ +// Test that the tri-valued complex range argument gets set appropriately. + +// REQUIRES: clang-driver + +// CHECK-FULL-RANGE: "-cc1" +// CHECK-FULL-RANGE: "-fcx-range=full" + +// CHECK-LIMITED-RANGE: "-cc1" +// CHECK-LIMITED-RANGE: "-fcx-range=limited" + +// CHECK-NONAN-RANGE: "-cc1" +// CHECK-NONAN-RANGE: "-fcx-range=nonan" + +// RUN: %clang -### -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FULL-RANGE %s + +// RUN: %clang -### -c -fcx-limited-range %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-LIMITED-RANGE %s + +// RUN: %clang -### -c -fcx-fortran-rules %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NONAN-RANGE %s