diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 7f63a5577262ba..af209eb9089d7f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1839,8 +1839,7 @@ def fsystem_module : Flag<["-"], "fsystem-module">, Flags<[CC1Option]>, MarshallingInfoFlag<"FrontendOpts.IsSystemModule">; def fmodule_map_file : Joined<["-"], "fmodule-map-file=">, Group, Flags<[NoXarchOption,CC1Option]>, MetaVarName<"">, - HelpText<"Load this module map file">, - MarshallingInfoStringVector<"FrontendOpts.ModuleMapFiles">; + HelpText<"Load this module map file">; def fmodule_file : Joined<["-"], "fmodule-file=">, Group, Flags<[NoXarchOption,CC1Option]>, MetaVarName<"[=]">, HelpText<"Specify the mapping of module name to precompiled module file, or load a module file if name is omitted.">; @@ -4625,7 +4624,7 @@ def arcmt_action_EQ : Joined<["-"], "arcmt-action=">, Flags<[CC1Option, NoDriver NormalizedValuesScope<"FrontendOptions">, NormalizedValues<["ARCMT_Check", "ARCMT_Modify", "ARCMT_Migrate"]>, MarshallingInfoString<"FrontendOpts.ARCMTAction", "ARCMT_None">, - AutoNormalizeEnum; + AutoNormalizeEnumJoined; def opt_record_file : Separate<["-"], "opt-record-file">, HelpText<"File name to use for YAML optimization record output">; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index a7a5a73eebdd67..06d8d2e27c9b77 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -152,8 +152,8 @@ static Optional normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned, /// argument. static void denormalizeSimpleFlag(SmallVectorImpl &Args, const char *Spelling, - CompilerInvocation::StringAllocator, - Option::OptionClass, unsigned, /*T*/...) { + CompilerInvocation::StringAllocator, unsigned, + /*T*/...) { Args.push_back(Spelling); } @@ -193,41 +193,12 @@ static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue, static auto makeBooleanOptionDenormalizer(bool Value) { return [Value](SmallVectorImpl &Args, const char *Spelling, - CompilerInvocation::StringAllocator, Option::OptionClass, - unsigned, bool KeyPath) { + CompilerInvocation::StringAllocator, unsigned, bool KeyPath) { if (KeyPath == Value) Args.push_back(Spelling); }; } -static void denormalizeStringImpl(SmallVectorImpl &Args, - const char *Spelling, - CompilerInvocation::StringAllocator SA, - Option::OptionClass OptClass, unsigned, - Twine Value) { - switch (OptClass) { - case Option::SeparateClass: - case Option::JoinedOrSeparateClass: - Args.push_back(Spelling); - Args.push_back(SA(Value)); - break; - case Option::JoinedClass: - Args.push_back(SA(Twine(Spelling) + Value)); - break; - default: - llvm_unreachable("Cannot denormalize an option with option class " - "incompatible with string denormalization."); - } -} - -template -static void -denormalizeString(SmallVectorImpl &Args, const char *Spelling, - CompilerInvocation::StringAllocator SA, - Option::OptionClass OptClass, unsigned TableIndex, T Value) { - denormalizeStringImpl(Args, Spelling, SA, OptClass, TableIndex, Twine(Value)); -} - static Optional findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) { for (int I = 0, E = Table.Size; I != E; ++I) @@ -269,13 +240,12 @@ static llvm::Optional normalizeSimpleEnum(OptSpecifier Opt, static void denormalizeSimpleEnumImpl(SmallVectorImpl &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, - Option::OptionClass OptClass, unsigned TableIndex, unsigned Value) { assert(TableIndex < SimpleEnumValueTablesSize); const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) { - denormalizeString(Args, Spelling, SA, OptClass, TableIndex, - MaybeEnumVal->Name); + Args.push_back(Spelling); + Args.push_back(MaybeEnumVal->Name); } else { llvm_unreachable("The simple enum value was not correctly defined in " "the tablegen option description"); @@ -286,12 +256,24 @@ template static void denormalizeSimpleEnum(SmallVectorImpl &Args, const char *Spelling, CompilerInvocation::StringAllocator SA, - Option::OptionClass OptClass, unsigned TableIndex, T Value) { - return denormalizeSimpleEnumImpl(Args, Spelling, SA, OptClass, TableIndex, + return denormalizeSimpleEnumImpl(Args, Spelling, SA, TableIndex, static_cast(Value)); } +static void denormalizeSimpleEnumJoined(SmallVectorImpl &Args, + const char *Spelling, + CompilerInvocation::StringAllocator SA, + unsigned TableIndex, unsigned Value) { + assert(TableIndex < SimpleEnumValueTablesSize); + const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; + if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) + Args.push_back(SA(Twine(Spelling) + MaybeEnumVal->Name)); + else + llvm_unreachable("The simple enum value was not correctly defined in " + "the tablegen option description"); +} + static Optional normalizeString(OptSpecifier Opt, int TableIndex, const ArgList &Args, DiagnosticsEngine &Diags) { @@ -301,6 +283,25 @@ static Optional normalizeString(OptSpecifier Opt, int TableIndex, return std::string(Arg->getValue()); } +static void denormalizeString(SmallVectorImpl &Args, + const char *Spelling, + CompilerInvocation::StringAllocator SA, unsigned, + Twine Value) { + Args.push_back(Spelling); + Args.push_back(SA(Value)); +} + +template ::value && + std::is_constructible::value, + bool> = false> +static void denormalizeString(SmallVectorImpl &Args, + const char *Spelling, + CompilerInvocation::StringAllocator SA, + unsigned TableIndex, T Value) { + denormalizeString(Args, Spelling, SA, TableIndex, Twine(Value)); +} + template static Optional normalizeStringIntegral(OptSpecifier Opt, int, const ArgList &Args, @@ -316,23 +317,6 @@ static Optional normalizeStringIntegral(OptSpecifier Opt, int, return Res; } -static Optional> -normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args, - DiagnosticsEngine &) { - return Args.getAllArgValues(Opt); -} - -static void denormalizeStringVector(SmallVectorImpl &Args, - const char *Spelling, - CompilerInvocation::StringAllocator SA, - Option::OptionClass OptClass, - unsigned TableIndex, - const std::vector &Values) { - for (const std::string &Value : Values) { - denormalizeString(Args, Spelling, SA, OptClass, TableIndex, Value); - } -} - static Optional normalizeTriple(OptSpecifier Opt, int TableIndex, const ArgList &Args, DiagnosticsEngine &Diags) { @@ -2105,6 +2089,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); 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.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file); // Only the -fmodule-file= form. for (const auto *A : Args.filtered(OPT_fmodule_file)) { StringRef Val = A->getValue(); @@ -4001,8 +3986,7 @@ void CompilerInvocation::generateCC1CommandLine( (Extracted != \ static_castKEYPATH)>( \ (IMPLIED_CHECK) ? (IMPLIED_VALUE) : (DEFAULT_VALUE)))) \ - DENORMALIZER(Args, SPELLING, SA, Option::KIND##Class, TABLE_INDEX, \ - Extracted); \ + DENORMALIZER(Args, SPELLING, SA, TABLE_INDEX, Extracted); \ }(EXTRACTOR(this->KEYPATH)); \ } diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp b/clang/unittests/Frontend/CompilerInvocationTest.cpp index 5738f70791718a..51b7ba8c147fe0 100644 --- a/clang/unittests/Frontend/CompilerInvocationTest.cpp +++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp @@ -18,7 +18,6 @@ using namespace llvm; using namespace clang; using ::testing::Contains; -using ::testing::HasSubstr; using ::testing::StrEq; namespace { @@ -343,109 +342,30 @@ TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) { ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str()))); } -TEST_F(CommandLineTest, SeparateEnumNonDefault) { +TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateEnumNonDefault) { const char *Args[] = {"-mrelocation-model", "static"}; CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); ASSERT_FALSE(Diags->hasErrorOccurred()); - ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static); Invocation.generateCC1CommandLine(GeneratedArgs, *this); // Non default relocation model. - ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model"))); ASSERT_THAT(GeneratedArgs, Contains(StrEq("static"))); - ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static")))); } -TEST_F(CommandLineTest, SeparateEnumDefault) { +TEST_F(CommandLineTest, CanGenerateCC1COmmandLineSeparateEnumDefault) { const char *Args[] = {"-mrelocation-model", "pic"}; CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); ASSERT_FALSE(Diags->hasErrorOccurred()); - ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_); Invocation.generateCC1CommandLine(GeneratedArgs, *this); // Default relocation model. - ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model")))); ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic")))); - ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic")))); -} - -TEST_F(CommandLineTest, JoinedEnumNonDefault) { - const char *Args[] = {"-fobjc-dispatch-method=non-legacy"}; - - CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); - - ASSERT_FALSE(Diags->hasErrorOccurred()); - ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(), - CodeGenOptions::NonLegacy); - - Invocation.generateCC1CommandLine(GeneratedArgs, *this); - - ASSERT_THAT(GeneratedArgs, - Contains(StrEq("-fobjc-dispatch-method=non-legacy"))); - ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method=")))); - ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy")))); -} - -TEST_F(CommandLineTest, JoinedEnumDefault) { - const char *Args[] = {"-fobjc-dispatch-method=legacy"}; - - CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); - - ASSERT_FALSE(Diags->hasErrorOccurred()); - ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(), - CodeGenOptions::Legacy); - - Invocation.generateCC1CommandLine(GeneratedArgs, *this); - - ASSERT_THAT(GeneratedArgs, - Not(Contains(StrEq("-fobjc-dispatch-method=legacy")))); - ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method=")))); - ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy")))); -} - -TEST_F(CommandLineTest, StringVectorEmpty) { - const char *Args[] = {""}; - - CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); - - ASSERT_FALSE(Diags->hasErrorOccurred()); - ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles.empty()); - - Invocation.generateCC1CommandLine(GeneratedArgs, *this); - ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-fmodule-map-file=")))); -} - -TEST_F(CommandLineTest, StringVectorSingle) { - const char *Args[] = {"-fmodule-map-file=a"}; - - CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); - - ASSERT_FALSE(Diags->hasErrorOccurred()); - ASSERT_EQ(Invocation.getFrontendOpts().ModuleMapFiles, - std::vector({"a"})); - - Invocation.generateCC1CommandLine(GeneratedArgs, *this); - ASSERT_EQ(count(GeneratedArgs, StringRef("-fmodule-map-file=a")), 1); -} - -TEST_F(CommandLineTest, StringVectorMultiple) { - const char *Args[] = {"-fmodule-map-file=a", "-fmodule-map-file=b"}; - - CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); - - ASSERT_FALSE(Diags->hasErrorOccurred()); - ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles == - std::vector({"a", "b"})); - - Invocation.generateCC1CommandLine(GeneratedArgs, *this); - ASSERT_EQ(count(GeneratedArgs, StringRef("-fmodule-map-file=a")), 1); - ASSERT_EQ(count(GeneratedArgs, StringRef("-fmodule-map-file=b")), 1); } // Tree of boolean options that can be (directly or transitively) implied by diff --git a/llvm/include/llvm/Option/OptParser.td b/llvm/include/llvm/Option/OptParser.td index 943fce82d988a4..e96e541315695f 100644 --- a/llvm/include/llvm/Option/OptParser.td +++ b/llvm/include/llvm/Option/OptParser.td @@ -167,12 +167,6 @@ class MarshallingInfoStringInt - : MarshallingInfo({})"> { - code Normalizer = "normalizeStringVector"; - code Denormalizer = "denormalizeStringVector"; -} - class MarshallingInfoFlag : MarshallingInfo { code Normalizer = "normalizeSimpleFlag"; @@ -208,6 +202,9 @@ class AutoNormalizeEnum { code Normalizer = "normalizeSimpleEnum"; code Denormalizer = "denormalizeSimpleEnum"; } +class AutoNormalizeEnumJoined : AutoNormalizeEnum { + code Denormalizer = "denormalizeSimpleEnumJoined"; +} class ValueMerger { code ValueMerger = merger; } class ValueExtractor { code ValueExtractor = extractor; }