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 @@ -325,10 +325,6 @@ string Spelling = prefix#!cond(flag.Polarity.Value : "", true : "no-")#spelling; - // Does the flag have CC1Option? - bit IsCC1 = !not(!empty(!filter(opt_flag, flag.OptionFlags, - !eq(opt_flag, CC1Option)))); - // Can the flag be implied by another flag? bit CanBeImplied = !not(!empty(flag.ImpliedBy)); @@ -336,18 +332,14 @@ code ValueAsCode = !cond(flag.Value : "true", true: "false"); } -// Creates simple flag record. -class BoolOptionFlag - : Flag<["-"], flag.Spelling>, Flags, HelpText {} - -// Creates marshalled flag record. -class CC1BoolOptionFlag +// Creates record with a marshalled flag. +class BoolOptionFlag : Flag<["-"], flag.Spelling>, Flags, HelpText, MarshallingInfoBooleanFlag, - ImpliedByAnyOf {} + ImpliedByAnyOf {} // Generates TableGen records for two command line flags that control the same // keypath via the marshalling infrastructure. @@ -370,17 +362,10 @@ // TODO: Assert that the flags have different value. // TODO: Assert that only one of the flags can be implied. - if flag1.IsCC1 then { - def flag1.RecordName : CC1BoolOptionFlag; - } else { - def flag1.RecordName : BoolOptionFlag; - } - - if flag2.IsCC1 then { - def flag2.RecordName : CC1BoolOptionFlag; - } else { - def flag2.RecordName : BoolOptionFlag; - } + defvar implied = !cond(flag1.CanBeImplied: flag1, true: flag2); + + def flag1.RecordName : BoolOptionFlag; + def flag2.RecordName : BoolOptionFlag; } //===----------------------------------------------------------------------===// @@ -4322,10 +4307,11 @@ def flto_unit: Flag<["-"], "flto-unit">, HelpText<"Emit IR to support LTO unit features (CFI, whole program vtable opt)">; def fno_lto_unit: Flag<["-"], "fno-lto-unit">; -def fdebug_pass_manager : Flag<["-"], "fdebug-pass-manager">, - HelpText<"Prints debug information for the new pass manager">; -def fno_debug_pass_manager : Flag<["-"], "fno-debug-pass-manager">, - HelpText<"Disables debug printing for the new pass manager">; +defm debug_pass_manager : BoolOption<"debug-pass-manager", + "CodeGenOpts.DebugPassManager", DefaultsToFalse, + ChangedBy, + ResetBy, + BothFlags<[]>, "f">; def fexperimental_debug_variable_locations : Flag<["-"], "fexperimental-debug-variable-locations">, HelpText<"Use experimental new value-tracking variable locations">; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -869,10 +869,6 @@ } } - Opts.DebugPassManager = - Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager, - /* Default */ false); - if (Arg *A = Args.getLastArg(OPT_fveclib)) { StringRef Name = A->getValue(); if (Name == "Accelerate") @@ -3767,7 +3763,7 @@ HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \ IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, \ TABLE_INDEX) \ - { \ + if ((FLAGS)&options::CC1Option) { \ this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE); \ if (IMPLIED_CHECK) \ this->KEYPATH = MERGER(this->KEYPATH, IMPLIED_VALUE); \ diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp b/clang/unittests/Frontend/CompilerInvocationTest.cpp --- a/clang/unittests/Frontend/CompilerInvocationTest.cpp +++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp @@ -238,6 +238,55 @@ ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerChangedByFlag)))); } +// Boolean option that gets the CC1Option flag from a let statement (which +// is applied **after** the record is defined): +// +// let Flags = [CC1Option] in { +// defm option : BoolOption<...>; +// } + +TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) { + const char *Args[] = {""}; + + CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); + + ASSERT_FALSE(Diags->hasErrorOccurred()); + ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager")))); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); +} + +TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) { + const char *Args[] = {"-fdebug-pass-manager"}; + + CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); + + ASSERT_FALSE(Diags->hasErrorOccurred()); + ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + + ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdebug-pass-manager"))); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); +} + +TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) { + const char *Args[] = {"-fno-debug-pass-manager"}; + + CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); + + ASSERT_FALSE(Diags->hasErrorOccurred()); + ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager")))); +} + TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) { const char *Args[] = {"-fmodules-strict-context-hash"};