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 @@ -335,8 +335,8 @@ def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output">, HelpText<"Output path for the plist report">, Flags<[CC1Option]>; def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">, - HelpText<"Emit ARC errors even if the migrator can fix them">, - Flags<[CC1Option]>; + HelpText<"Emit ARC errors even if the migrator can fix them">, Flags<[CC1Option]>, + MarshallingInfoFlag<"FrontendOpts.ARCMTMigrateEmitARCErrors">; def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt, HelpText<"Auto-generates preprocessed source files and a reproduction script">; def gen_cdb_fragment_path: Separate<["-"], "gen-cdb-fragment-path">, InternalDebugOpt, @@ -1565,7 +1565,8 @@ def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">, Flags<[CC1Option]>, Alias; def fsystem_module : Flag<["-"], "fsystem-module">, Flags<[CC1Option]>, - HelpText<"Build this module as a system module. Only used with -emit-module">; + HelpText<"Build this module as a system module. Only used with -emit-module">, + MarshallingInfoFlag<"FrontendOpts.IsSystemModule">; def fmodule_map_file : Joined<["-"], "fmodule-map-file=">, Group, Flags<[NoXarchOption,CC1Option]>, MetaVarName<"">, HelpText<"Load this module map file">; @@ -1690,7 +1691,8 @@ def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; def fno_temp_file : Flag<["-"], "fno-temp-file">, Group, Flags<[CC1Option, CoreOption]>, HelpText< - "Directly create compilation output files. This may lead to incorrect incremental builds if the compiler crashes">; + "Directly create compilation output files. This may lead to incorrect incremental builds if the compiler crashes">, + MarshallingInfoFlag<"FrontendOpts.UseTemporary", "true">, IsNegative; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">; def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group, Flags<[CC1Option]>, @@ -1978,14 +1980,16 @@ def : Flag<["-"], "fterminated-vtables">, Alias; def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group; -def ftime_report : Flag<["-"], "ftime-report">, Group, Flags<[CC1Option]>; +def ftime_report : Flag<["-"], "ftime-report">, Group, Flags<[CC1Option]>, + MarshallingInfoFlag<"FrontendOpts.ShowTimers">; def ftime_trace : Flag<["-"], "ftime-trace">, Group, HelpText<"Turn on time profiler. Generates JSON file based on output filename.">, DocBrief<[{ Turn on time profiler. Generates JSON file based on output filename. Results can be analyzed with chrome://tracing or `Speedscope App `_ for flamegraph visualization.}]>, - Flags<[CC1Option, CoreOption]>; + Flags<[CC1Option, CoreOption]>, + MarshallingInfoFlag<"FrontendOpts.TimeTrace">; def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Group, HelpText<"Minimum time granularity (in microseconds) traced by time profiler">, Flags<[CC1Option, CoreOption]>; @@ -2198,7 +2202,8 @@ HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption, FC1Option, - FlangOption]>, HelpText<"Display available options">; + FlangOption]>, HelpText<"Display available options">, + MarshallingInfoFlag<"FrontendOpts.ShowHelp">; def ibuiltininc : Flag<["-"], "ibuiltininc">, HelpText<"Enable builtin #include directories even when -nostdinc is used " "before or after -ibuiltininc. " @@ -2222,7 +2227,8 @@ def include_pch : Separate<["-"], "include-pch">, Group, Flags<[CC1Option]>, HelpText<"Include precompiled header file">, MetaVarName<"">; def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>, - HelpText<"Whether to build a relocatable precompiled header">; + HelpText<"Whether to build a relocatable precompiled header">, + MarshallingInfoFlag<"FrontendOpts.RelocatablePCH">; def verify_pch : Flag<["-"], "verify-pch">, Group, Flags<[CC1Option]>, HelpText<"Load and verify that a pre-compiled header file is not stale">; def init : Separate<["-"], "init">; @@ -3015,7 +3021,8 @@ def print_supported_cpus : Flag<["-", "--"], "print-supported-cpus">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Print supported cpu models for the given target (if target is not specified," - " it will print the supported cpus for the default target)">; + " it will print the supported cpus for the default target)">, + MarshallingInfoFlag<"FrontendOpts.PrintSupportedCPUs">; def mcpu_EQ_QUESTION : Flag<["-"], "mcpu=?">, Alias; def mtune_EQ_QUESTION : Flag<["-"], "mtune=?">, Alias; def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>, @@ -4131,19 +4138,26 @@ def code_completion_at_EQ : Joined<["-"], "code-completion-at=">, Alias; def code_completion_macros : Flag<["-"], "code-completion-macros">, - HelpText<"Include macros in code-completion results">; + HelpText<"Include macros in code-completion results">, + MarshallingInfoFlag<"FrontendOpts.CodeCompleteOpts.IncludeMacros">; def code_completion_patterns : Flag<["-"], "code-completion-patterns">, - HelpText<"Include code patterns in code-completion results">; + HelpText<"Include code patterns in code-completion results">, + MarshallingInfoFlag<"FrontendOpts.CodeCompleteOpts.IncludeCodePatterns">; def no_code_completion_globals : Flag<["-"], "no-code-completion-globals">, - HelpText<"Do not include global declarations in code-completion results.">; + HelpText<"Do not include global declarations in code-completion results.">, + MarshallingInfoFlag<"FrontendOpts.CodeCompleteOpts.IncludeGlobals", "true">, IsNegative; def no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level-decls">, - HelpText<"Do not include declarations inside namespaces (incl. global namespace) in the code-completion results.">; + HelpText<"Do not include declarations inside namespaces (incl. global namespace) in the code-completion results.">, + MarshallingInfoFlag<"FrontendOpts.CodeCompleteOpts.IncludeNamespaceLevelDecls", "true">, IsNegative; def code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">, - HelpText<"Include brief documentation comments in code-completion results.">; + HelpText<"Include brief documentation comments in code-completion results.">, + MarshallingInfoFlag<"FrontendOpts.CodeCompleteOpts.IncludeBriefComments">; def code_completion_with_fixits : Flag<["-"], "code-completion-with-fixits">, - HelpText<"Include code completion results which require small fix-its.">; + HelpText<"Include code completion results which require small fix-its.">, + MarshallingInfoFlag<"FrontendOpts.CodeCompleteOpts.IncludeFixIts">; def disable_free : Flag<["-"], "disable-free">, - HelpText<"Disable freeing of memory on exit">; + HelpText<"Disable freeing of memory on exit">, + MarshallingInfoFlag<"FrontendOpts.DisableFree">; def discard_value_names : Flag<["-"], "discard-value-names">, HelpText<"Discard value names in LLVM IR">; def load : Separate<["-"], "load">, MetaVarName<"">, @@ -4161,7 +4175,8 @@ " nodes having a certain substring in a qualified name. Use" " -ast-list to list all filterable declaration node names.">; def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">, - HelpText<"Do not automatically generate or update the global module index">; + HelpText<"Do not automatically generate or update the global module index">, + MarshallingInfoFlag<"FrontendOpts.UseGlobalModuleIndex", "true">, IsNegative; def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">, HelpText<"Do not automatically import modules for error recovery">; def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">, @@ -4176,7 +4191,8 @@ "being compiled.">; def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">, HelpText<"Embed the contents of all files read by this compilation into " - "the produced module file.">; + "the produced module file.">, + MarshallingInfoFlag<"FrontendOpts.ModulesEmbedAllFiles">; def fmodules_local_submodule_visibility : Flag<["-"], "fmodules-local-submodule-visibility">, HelpText<"Enforce name visibility rules across submodules of the same " @@ -4246,11 +4262,13 @@ HelpText<"Build ASTs and then debug dump them in the specified format, " "forcing deserialization. Supported formats include: default, json">; def ast_dump_decl_types : Flag<["-"], "ast-dump-decl-types">, - HelpText<"Include declaration types in AST dumps">; + HelpText<"Include declaration types in AST dumps">, + MarshallingInfoFlag<"FrontendOpts.ASTDumpDeclTypes">; def templight_dump : Flag<["-"], "templight-dump">, HelpText<"Dump templight information to stdout">; def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">, - HelpText<"Build ASTs and then debug dump their name lookup tables">; + HelpText<"Build ASTs and then debug dump their name lookup tables">, + MarshallingInfoFlag<"FrontendOpts.ASTDumpLookups">; def ast_view : Flag<["-"], "ast-view">, HelpText<"Build ASTs and view them with GraphViz">; def emit_module : Flag<["-"], "emit-module">, @@ -4305,7 +4323,8 @@ HelpText<"The format used for serializing remarks (default: YAML)">; def print_stats : Flag<["-"], "print-stats">, - HelpText<"Print performance metrics and statistics">; + HelpText<"Print performance metrics and statistics">, + MarshallingInfoFlag<"FrontendOpts.ShowStats">; def stats_file : Joined<["-"], "stats-file=">, HelpText<"Filename to write statistics to">; def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">, @@ -4313,13 +4332,17 @@ def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">, HelpText<"Dump record layout information in a simple form used for testing">; def fix_what_you_can : Flag<["-"], "fix-what-you-can">, - HelpText<"Apply fix-it advice even in the presence of unfixable errors">; + HelpText<"Apply fix-it advice even in the presence of unfixable errors">, + MarshallingInfoFlag<"FrontendOpts.FixWhatYouCan">; def fix_only_warnings : Flag<["-"], "fix-only-warnings">, - HelpText<"Apply fix-it advice only for warnings, not errors">; + HelpText<"Apply fix-it advice only for warnings, not errors">, + MarshallingInfoFlag<"FrontendOpts.FixOnlyWarnings">; def fixit_recompile : Flag<["-"], "fixit-recompile">, - HelpText<"Apply fix-it changes and recompile">; + HelpText<"Apply fix-it changes and recompile">, + MarshallingInfoFlag<"FrontendOpts.FixAndRecompile">; def fixit_to_temp : Flag<["-"], "fixit-to-temporary">, - HelpText<"Apply fix-it changes to temporary files">; + HelpText<"Apply fix-it changes to temporary files">, + MarshallingInfoFlag<"FrontendOpts.FixToTemporaries">; def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">, HelpText<"Override record layouts with those in the given file">; @@ -4331,7 +4354,8 @@ def pch_through_hdrstop_use : Flag<["-"], "pch-through-hdrstop-use">, HelpText<"When using a PCH, skip tokens until after a #pragma hdrstop.">; def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">, - HelpText<"Disable inclusion of timestamp in precompiled headers">; + HelpText<"Disable inclusion of timestamp in precompiled headers">, + MarshallingInfoFlag<"FrontendOpts.IncludeTimestamps", "true">, IsNegative; def building_pch_with_obj : Flag<["-"], "building-pch-with-obj">, HelpText<"This compilation is part of building a PCH with corresponding object file.">; @@ -4345,7 +4369,8 @@ let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { def version : Flag<["-"], "version">, - HelpText<"Print the compiler version">; + HelpText<"Print the compiler version">, + MarshallingInfoFlag<"FrontendOpts.ShowVersion">; def main_file_name : Separate<["-"], "main-file-name">, HelpText<"Main file name to use for debug info and source if missing">; def split_dwarf_output : Separate<["-"], "split-dwarf-output">, 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 @@ -134,6 +134,14 @@ return None; } +static Optional normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned, + const ArgList &Args, + DiagnosticsEngine &) { + if (Args.hasArg(Opt)) + return false; + return None; +} + void denormalizeSimpleFlag(SmallVectorImpl &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, @@ -276,9 +284,11 @@ LangOptions &LangOpts = *Invocation.getLangOpts(); DiagnosticOptions &DiagOpts = Invocation.getDiagnosticOpts(); CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts(); + FrontendOptions &FrontendOpts = Invocation.getFrontendOpts(); CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument; CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents; CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents; + FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex; llvm::sys::Process::UseANSIEscapeCodes(DiagOpts.UseANSIEscapeCodes); } @@ -1988,32 +1998,16 @@ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); } - Opts.DisableFree = Args.hasArg(OPT_disable_free); Opts.OutputFile = std::string(Args.getLastArgValue(OPT_o)); Opts.Plugins = Args.getAllArgValues(OPT_load); - Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch); - Opts.ShowHelp = Args.hasArg(OPT_help); - Opts.ShowStats = Args.hasArg(OPT_print_stats); - Opts.ShowTimers = Args.hasArg(OPT_ftime_report); - Opts.PrintSupportedCPUs = Args.hasArg(OPT_print_supported_cpus); - Opts.TimeTrace = Args.hasArg(OPT_ftime_trace); Opts.TimeTraceGranularity = getLastArgIntValue( Args, OPT_ftime_trace_granularity_EQ, Opts.TimeTraceGranularity, Diags); - Opts.ShowVersion = Args.hasArg(OPT_version); Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge); Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); - Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can); - Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings); - Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile); - Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp); Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ); Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ); Opts.ASTDumpFilter = std::string(Args.getLastArgValue(OPT_ast_dump_filter)); - Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups); - Opts.ASTDumpDeclTypes = Args.hasArg(OPT_ast_dump_decl_types); - Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); - Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex; Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file); // Only the -fmodule-file= form. for (const auto *A : Args.filtered(OPT_fmodule_file)) { @@ -2022,29 +2016,12 @@ Opts.ModuleFiles.push_back(std::string(Val)); } Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ); - Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files); - Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp); - Opts.UseTemporary = !Args.hasArg(OPT_fno_temp_file); - Opts.IsSystemModule = Args.hasArg(OPT_fsystem_module); Opts.AllowPCMWithCompilerErrors = Args.hasArg(OPT_fallow_pcm_with_errors); if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule) Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module" << "-emit-module"; - Opts.CodeCompleteOpts.IncludeMacros - = Args.hasArg(OPT_code_completion_macros); - Opts.CodeCompleteOpts.IncludeCodePatterns - = Args.hasArg(OPT_code_completion_patterns); - Opts.CodeCompleteOpts.IncludeGlobals - = !Args.hasArg(OPT_no_code_completion_globals); - Opts.CodeCompleteOpts.IncludeNamespaceLevelDecls - = !Args.hasArg(OPT_no_code_completion_ns_level_decls); - Opts.CodeCompleteOpts.IncludeBriefComments - = Args.hasArg(OPT_code_completion_brief_comments); - Opts.CodeCompleteOpts.IncludeFixIts - = Args.hasArg(OPT_code_completion_with_fixits); - Opts.OverrideRecordLayoutsFile = std::string(Args.getLastArgValue(OPT_foverride_record_layout_EQ)); Opts.AuxTriple = std::string(Args.getLastArgValue(OPT_aux_triple)); @@ -2058,8 +2035,6 @@ std::string(Args.getLastArgValue(OPT_mt_migrate_directory)); Opts.ARCMTMigrateReportOut = std::string(Args.getLastArgValue(OPT_arcmt_migrate_report_output)); - Opts.ARCMTMigrateEmitARCErrors - = Args.hasArg(OPT_arcmt_migrate_emit_arc_errors); Opts.ObjCMTWhiteListPath = std::string(Args.getLastArgValue(OPT_objcmt_whitelist_dir_path)); 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 @@ -22,6 +22,13 @@ using ::testing::StrNe; namespace { +struct OptsPopulationTest : public ::testing::Test { + IntrusiveRefCntPtr Diags; + CompilerInvocation CInvok; + + OptsPopulationTest() + : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions())) {} +}; class CC1CommandLineGenerationTest : public ::testing::Test { public: @@ -37,23 +44,36 @@ : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions())) {} }; -TEST(OptsPopulationTest, CanPopulateOptsWithImpliedFlags) { - const char *Args[] = {"clang", "-xc++", "-cl-unsafe-math-optimizations"}; +TEST_F(OptsPopulationTest, OptIsInitializedWithCustomDefaultValue) { + const char *Args[] = {"clang", "-xc++"}; - auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); + CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags); + + ASSERT_TRUE(CInvok.getFrontendOpts().UseTemporary); +} + +TEST_F(OptsPopulationTest, OptOfNegativeFlagIsPopulatedWithFalse) { + const char *Args[] = {"clang", "-xc++", "-fno-temp-file"}; + + CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags); + + ASSERT_FALSE(CInvok.getFrontendOpts().UseTemporary); +} + +TEST_F(OptsPopulationTest, OptsOfImpliedPositiveFlagArePopulatedWithTrue) { + const char *Args[] = {"clang", "-xc++", "-cl-unsafe-math-optimizations"}; - CompilerInvocation CInvok; CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags); // Explicitly provided flag. - ASSERT_EQ(CInvok.getLangOpts()->CLUnsafeMath, true); + ASSERT_TRUE(CInvok.getLangOpts()->CLUnsafeMath); // Flags directly implied by explicitly provided flag. - ASSERT_EQ(CInvok.getCodeGenOpts().LessPreciseFPMAD, true); - ASSERT_EQ(CInvok.getLangOpts()->UnsafeFPMath, true); + ASSERT_TRUE(CInvok.getCodeGenOpts().LessPreciseFPMAD); + ASSERT_TRUE(CInvok.getLangOpts()->UnsafeFPMath); // Flag transitively implied by explicitly provided flag. - ASSERT_EQ(CInvok.getLangOpts()->AllowRecip, true); + ASSERT_TRUE(CInvok.getLangOpts()->AllowRecip); } TEST_F(CC1CommandLineGenerationTest, CanGenerateCC1CommandLineFlag) { @@ -134,6 +154,28 @@ ASSERT_THAT(GeneratedArgs, Each(StrNe(RelocationModelCStr))); } +TEST_F(CC1CommandLineGenerationTest, NotPresentNegativeFlagNotGenerated) { + const char *Args[] = {"clang", "-xc++"}; + + CompilerInvocation CInvok; + CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags); + + CInvok.generateCC1CommandLine(GeneratedArgs, *this); + + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file")))); +} + +TEST_F(CC1CommandLineGenerationTest, PresentNegativeFlagGenerated) { + const char *Args[] = {"clang", "-xc++", "-fno-temp-file"}; + + CompilerInvocation CInvok; + CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags); + + CInvok.generateCC1CommandLine(GeneratedArgs, *this); + + ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file"))); +} + TEST_F(CC1CommandLineGenerationTest, NotPresentAndNotImpliedNotGenerated) { const char *Args[] = {"clang", "-xc++"}; diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td --- a/llvm/include/llvm/Option/OptParser.td +++ b/llvm/include/llvm/Option/OptParser.td @@ -187,7 +187,7 @@ // Mixins for additional marshalling attributes. class IsNegative { - // todo: create & apply a normalizer for negative flags + code Normalizer = "normalizeSimpleNegativeFlag"; } class AlwaysEmit { bit ShouldAlwaysEmit = true; } class Normalizer { code Normalizer = normalizer; }