diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:11:55 +0000 |
commit | 5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch) | |
tree | 1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp | |
parent | 3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff) | |
parent | 312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp | 1089 |
1 files changed, 648 insertions, 441 deletions
diff --git a/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp b/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp index 1fba91bed041..11f3f2c2d642 100644 --- a/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp +++ b/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp @@ -48,7 +48,6 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/CachedHashString.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" @@ -126,45 +125,147 @@ static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) { // Initialization. //===----------------------------------------------------------------------===// -CompilerInvocationRefBase::CompilerInvocationRefBase() - : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()), - DiagnosticOpts(new DiagnosticOptions()), - HeaderSearchOpts(new HeaderSearchOptions()), - PreprocessorOpts(new PreprocessorOptions()), - AnalyzerOpts(new AnalyzerOptions()) {} - -CompilerInvocationRefBase::CompilerInvocationRefBase( - const CompilerInvocationRefBase &X) - : LangOpts(new LangOptions(*X.getLangOpts())), - TargetOpts(new TargetOptions(X.getTargetOpts())), - DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())), - HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())), - PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())), - AnalyzerOpts(new AnalyzerOptions(*X.getAnalyzerOpts())) {} - -CompilerInvocationRefBase::CompilerInvocationRefBase( - CompilerInvocationRefBase &&X) = default; - -CompilerInvocationRefBase & -CompilerInvocationRefBase::operator=(CompilerInvocationRefBase X) { - LangOpts.swap(X.LangOpts); - TargetOpts.swap(X.TargetOpts); - DiagnosticOpts.swap(X.DiagnosticOpts); - HeaderSearchOpts.swap(X.HeaderSearchOpts); - PreprocessorOpts.swap(X.PreprocessorOpts); - AnalyzerOpts.swap(X.AnalyzerOpts); +namespace { +template <class T> std::shared_ptr<T> make_shared_copy(const T &X) { + return std::make_shared<T>(X); +} + +template <class T> +llvm::IntrusiveRefCntPtr<T> makeIntrusiveRefCntCopy(const T &X) { + return llvm::makeIntrusiveRefCnt<T>(X); +} +} // namespace + +CompilerInvocationBase::CompilerInvocationBase() + : LangOpts(std::make_shared<LangOptions>()), + TargetOpts(std::make_shared<TargetOptions>()), + DiagnosticOpts(llvm::makeIntrusiveRefCnt<DiagnosticOptions>()), + HSOpts(std::make_shared<HeaderSearchOptions>()), + PPOpts(std::make_shared<PreprocessorOptions>()), + AnalyzerOpts(llvm::makeIntrusiveRefCnt<AnalyzerOptions>()), + MigratorOpts(std::make_shared<MigratorOptions>()), + APINotesOpts(std::make_shared<APINotesOptions>()), + CodeGenOpts(std::make_shared<CodeGenOptions>()), + FSOpts(std::make_shared<FileSystemOptions>()), + FrontendOpts(std::make_shared<FrontendOptions>()), + DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()), + PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {} + +CompilerInvocationBase & +CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) { + if (this != &X) { + LangOpts = make_shared_copy(X.getLangOpts()); + TargetOpts = make_shared_copy(X.getTargetOpts()); + DiagnosticOpts = makeIntrusiveRefCntCopy(X.getDiagnosticOpts()); + HSOpts = make_shared_copy(X.getHeaderSearchOpts()); + PPOpts = make_shared_copy(X.getPreprocessorOpts()); + AnalyzerOpts = makeIntrusiveRefCntCopy(X.getAnalyzerOpts()); + MigratorOpts = make_shared_copy(X.getMigratorOpts()); + APINotesOpts = make_shared_copy(X.getAPINotesOpts()); + CodeGenOpts = make_shared_copy(X.getCodeGenOpts()); + FSOpts = make_shared_copy(X.getFileSystemOpts()); + FrontendOpts = make_shared_copy(X.getFrontendOpts()); + DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts()); + PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts()); + } + return *this; +} + +CompilerInvocationBase & +CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) { + if (this != &X) { + LangOpts = X.LangOpts; + TargetOpts = X.TargetOpts; + DiagnosticOpts = X.DiagnosticOpts; + HSOpts = X.HSOpts; + PPOpts = X.PPOpts; + AnalyzerOpts = X.AnalyzerOpts; + MigratorOpts = X.MigratorOpts; + APINotesOpts = X.APINotesOpts; + CodeGenOpts = X.CodeGenOpts; + FSOpts = X.FSOpts; + FrontendOpts = X.FrontendOpts; + DependencyOutputOpts = X.DependencyOutputOpts; + PreprocessorOutputOpts = X.PreprocessorOutputOpts; + } return *this; } -CompilerInvocationRefBase & -CompilerInvocationRefBase::operator=(CompilerInvocationRefBase &&X) = default; +namespace { +template <typename T> +T &ensureOwned(std::shared_ptr<T> &Storage) { + if (Storage.use_count() > 1) + Storage = std::make_shared<T>(*Storage); + return *Storage; +} + +template <typename T> +T &ensureOwned(llvm::IntrusiveRefCntPtr<T> &Storage) { + if (Storage.useCount() > 1) + Storage = llvm::makeIntrusiveRefCnt<T>(*Storage); + return *Storage; +} +} // namespace + +LangOptions &CowCompilerInvocation::getMutLangOpts() { + return ensureOwned(LangOpts); +} + +TargetOptions &CowCompilerInvocation::getMutTargetOpts() { + return ensureOwned(TargetOpts); +} + +DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() { + return ensureOwned(DiagnosticOpts); +} + +HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() { + return ensureOwned(HSOpts); +} + +PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() { + return ensureOwned(PPOpts); +} + +AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() { + return ensureOwned(AnalyzerOpts); +} + +MigratorOptions &CowCompilerInvocation::getMutMigratorOpts() { + return ensureOwned(MigratorOpts); +} + +APINotesOptions &CowCompilerInvocation::getMutAPINotesOpts() { + return ensureOwned(APINotesOpts); +} + +CodeGenOptions &CowCompilerInvocation::getMutCodeGenOpts() { + return ensureOwned(CodeGenOpts); +} + +FileSystemOptions &CowCompilerInvocation::getMutFileSystemOpts() { + return ensureOwned(FSOpts); +} + +FrontendOptions &CowCompilerInvocation::getMutFrontendOpts() { + return ensureOwned(FrontendOpts); +} + +DependencyOutputOptions &CowCompilerInvocation::getMutDependencyOutputOpts() { + return ensureOwned(DependencyOutputOpts); +} -CompilerInvocationRefBase::~CompilerInvocationRefBase() = default; +PreprocessorOutputOptions & +CowCompilerInvocation::getMutPreprocessorOutputOpts() { + return ensureOwned(PreprocessorOutputOpts); +} //===----------------------------------------------------------------------===// // Normalizers //===----------------------------------------------------------------------===// +using ArgumentConsumer = CompilerInvocation::ArgumentConsumer; + #define SIMPLE_ENUM_VALUE_TABLE #include "clang/Driver/Options.inc" #undef SIMPLE_ENUM_VALUE_TABLE @@ -191,11 +292,10 @@ static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt, /// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with /// unnecessary template instantiations and just ignore it with a variadic /// argument. -static void denormalizeSimpleFlag(SmallVectorImpl<const char *> &Args, - const char *Spelling, - CompilerInvocation::StringAllocator, - Option::OptionClass, unsigned, /*T*/...) { - Args.push_back(Spelling); +static void denormalizeSimpleFlag(ArgumentConsumer Consumer, + const Twine &Spelling, Option::OptionClass, + unsigned, /*T*/...) { + Consumer(Spelling); } template <typename T> static constexpr bool is_uint64_t_convertible() { @@ -232,29 +332,27 @@ static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue, } static auto makeBooleanOptionDenormalizer(bool Value) { - return [Value](SmallVectorImpl<const char *> &Args, const char *Spelling, - CompilerInvocation::StringAllocator, Option::OptionClass, - unsigned, bool KeyPath) { + return [Value](ArgumentConsumer Consumer, const Twine &Spelling, + Option::OptionClass, unsigned, bool KeyPath) { if (KeyPath == Value) - Args.push_back(Spelling); + Consumer(Spelling); }; } -static void denormalizeStringImpl(SmallVectorImpl<const char *> &Args, - const char *Spelling, - CompilerInvocation::StringAllocator SA, +static void denormalizeStringImpl(ArgumentConsumer Consumer, + const Twine &Spelling, Option::OptionClass OptClass, unsigned, const Twine &Value) { switch (OptClass) { case Option::SeparateClass: case Option::JoinedOrSeparateClass: case Option::JoinedAndSeparateClass: - Args.push_back(Spelling); - Args.push_back(SA(Value)); + Consumer(Spelling); + Consumer(Value); break; case Option::JoinedClass: case Option::CommaJoinedClass: - Args.push_back(SA(Twine(Spelling) + Value)); + Consumer(Spelling + Value); break; default: llvm_unreachable("Cannot denormalize an option with option class " @@ -263,11 +361,10 @@ static void denormalizeStringImpl(SmallVectorImpl<const char *> &Args, } template <typename T> -static void -denormalizeString(SmallVectorImpl<const char *> &Args, const char *Spelling, - CompilerInvocation::StringAllocator SA, - Option::OptionClass OptClass, unsigned TableIndex, T Value) { - denormalizeStringImpl(Args, Spelling, SA, OptClass, TableIndex, Twine(Value)); +static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling, + Option::OptionClass OptClass, unsigned TableIndex, + T Value) { + denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value)); } static std::optional<SimpleEnumValue> @@ -308,15 +405,14 @@ static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt, return std::nullopt; } -static void denormalizeSimpleEnumImpl(SmallVectorImpl<const char *> &Args, - const char *Spelling, - CompilerInvocation::StringAllocator SA, +static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer, + const Twine &Spelling, 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, + denormalizeString(Consumer, Spelling, OptClass, TableIndex, MaybeEnumVal->Name); } else { llvm_unreachable("The simple enum value was not correctly defined in " @@ -325,12 +421,11 @@ static void denormalizeSimpleEnumImpl(SmallVectorImpl<const char *> &Args, } template <typename T> -static void denormalizeSimpleEnum(SmallVectorImpl<const char *> &Args, - const char *Spelling, - CompilerInvocation::StringAllocator SA, +static void denormalizeSimpleEnum(ArgumentConsumer Consumer, + const Twine &Spelling, Option::OptionClass OptClass, unsigned TableIndex, T Value) { - return denormalizeSimpleEnumImpl(Args, Spelling, SA, OptClass, TableIndex, + return denormalizeSimpleEnumImpl(Consumer, Spelling, OptClass, TableIndex, static_cast<unsigned>(Value)); } @@ -366,9 +461,8 @@ normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args, return Args.getAllArgValues(Opt); } -static void denormalizeStringVector(SmallVectorImpl<const char *> &Args, - const char *Spelling, - CompilerInvocation::StringAllocator SA, +static void denormalizeStringVector(ArgumentConsumer Consumer, + const Twine &Spelling, Option::OptionClass OptClass, unsigned TableIndex, const std::vector<std::string> &Values) { @@ -382,7 +476,7 @@ static void denormalizeStringVector(SmallVectorImpl<const char *> &Args, CommaJoinedValue.append(Value); } } - denormalizeString(Args, Spelling, SA, Option::OptionClass::JoinedClass, + denormalizeString(Consumer, Spelling, Option::OptionClass::JoinedClass, TableIndex, CommaJoinedValue); break; } @@ -390,7 +484,7 @@ static void denormalizeStringVector(SmallVectorImpl<const char *> &Args, case Option::SeparateClass: case Option::JoinedOrSeparateClass: for (const std::string &Value : Values) - denormalizeString(Args, Spelling, SA, OptClass, TableIndex, Value); + denormalizeString(Consumer, Spelling, OptClass, TableIndex, Value); break; default: llvm_unreachable("Cannot denormalize an option with option class " @@ -427,11 +521,11 @@ static T extractMaskValue(T KeyPath) { } #define PARSE_OPTION_WITH_MARSHALLING( \ - ARGS, DIAGS, PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ - PARAM, HELPTEXT, METAVAR, VALUES, SPELLING, SHOULD_PARSE, ALWAYS_EMIT, \ - KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \ - DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ - if ((FLAGS)&options::CC1Option) { \ + ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, \ + FLAGS, VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, \ + ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, \ + NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ + if ((VISIBILITY)&options::CC1Option) { \ KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \ if (IMPLIED_CHECK) \ KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \ @@ -444,18 +538,18 @@ static T extractMaskValue(T KeyPath) { // Capture the extracted value as a lambda argument to avoid potential issues // with lifetime extension of the reference. #define GENERATE_OPTION_WITH_MARSHALLING( \ - ARGS, STRING_ALLOCATOR, PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, \ - ALIASARGS, FLAGS, PARAM, HELPTEXT, METAVAR, VALUES, SPELLING, \ - SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \ - IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ - if ((FLAGS)&options::CC1Option) { \ + CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ + VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES, SHOULD_PARSE, ALWAYS_EMIT, \ + KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, \ + DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \ + if ((VISIBILITY)&options::CC1Option) { \ [&](const auto &Extracted) { \ if (ALWAYS_EMIT || \ (Extracted != \ static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE) \ : (DEFAULT_VALUE)))) \ - DENORMALIZER(ARGS, SPELLING, STRING_ALLOCATOR, Option::KIND##Class, \ - TABLE_INDEX, Extracted); \ + DENORMALIZER(CONSUMER, SPELLING, Option::KIND##Class, TABLE_INDEX, \ + Extracted); \ }(EXTRACTOR(KEYPATH)); \ } @@ -466,7 +560,7 @@ static bool FixupInvocation(CompilerInvocation &Invocation, InputKind IK) { unsigned NumErrorsBefore = Diags.getNumErrors(); - LangOptions &LangOpts = *Invocation.getLangOpts(); + LangOptions &LangOpts = Invocation.getLangOpts(); CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts(); TargetOptions &TargetOpts = Invocation.getTargetOpts(); FrontendOptions &FrontendOpts = Invocation.getFrontendOpts(); @@ -486,6 +580,7 @@ static bool FixupInvocation(CompilerInvocation &Invocation, llvm::Triple::ArchType Arch = T.getArch(); CodeGenOpts.CodeModel = TargetOpts.CodeModel; + CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold; if (LangOpts.getExceptionHandling() != LangOptions::ExceptionHandlingKind::None && @@ -559,6 +654,7 @@ static bool FixupInvocation(CompilerInvocation &Invocation, emitError |= (DefaultCC == LangOptions::DCC_VectorCall || DefaultCC == LangOptions::DCC_RegCall) && !T.isX86(); + emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k; if (emitError) Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple(); @@ -573,27 +669,27 @@ static bool FixupInvocation(CompilerInvocation &Invocation, static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { - unsigned DefaultOpt = llvm::CodeGenOpt::None; + unsigned DefaultOpt = 0; if ((IK.getLanguage() == Language::OpenCL || IK.getLanguage() == Language::OpenCLCXX) && !Args.hasArg(OPT_cl_opt_disable)) - DefaultOpt = llvm::CodeGenOpt::Default; + DefaultOpt = 2; if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { if (A->getOption().matches(options::OPT_O0)) - return llvm::CodeGenOpt::None; + return 0; if (A->getOption().matches(options::OPT_Ofast)) - return llvm::CodeGenOpt::Aggressive; + return 3; assert(A->getOption().matches(options::OPT_O)); StringRef S(A->getValue()); if (S == "s" || S == "z") - return llvm::CodeGenOpt::Default; + return 2; if (S == "g") - return llvm::CodeGenOpt::Less; + return 1; return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags); } @@ -617,21 +713,18 @@ static unsigned getOptimizationLevelSize(ArgList &Args) { return 0; } -static void GenerateArg(SmallVectorImpl<const char *> &Args, - llvm::opt::OptSpecifier OptSpecifier, - CompilerInvocation::StringAllocator SA) { +static void GenerateArg(ArgumentConsumer Consumer, + llvm::opt::OptSpecifier OptSpecifier) { Option Opt = getDriverOptTable().getOption(OptSpecifier); - denormalizeSimpleFlag(Args, SA(Opt.getPrefix() + Opt.getName()), SA, + denormalizeSimpleFlag(Consumer, Opt.getPrefixedName(), Option::OptionClass::FlagClass, 0); } -static void GenerateArg(SmallVectorImpl<const char *> &Args, +static void GenerateArg(ArgumentConsumer Consumer, llvm::opt::OptSpecifier OptSpecifier, - const Twine &Value, - CompilerInvocation::StringAllocator SA) { + const Twine &Value) { Option Opt = getDriverOptTable().getOption(OptSpecifier); - denormalizeString(Args, SA(Opt.getPrefix() + Opt.getName()), SA, - Opt.getKind(), 0, Value); + denormalizeString(Consumer, Opt.getPrefixedName(), Opt.getKind(), 0, Value); } // Parse command line arguments into CompilerInvocation. @@ -846,13 +939,12 @@ static void getAllNoBuiltinFuncValues(ArgList &Args, Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd); } -static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA) { +static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts, + ArgumentConsumer Consumer) { const AnalyzerOptions *AnalyzerOpts = &Opts; #define ANALYZER_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef ANALYZER_OPTION_WITH_MARSHALLING @@ -860,7 +952,7 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, switch (Opts.AnalysisConstraintsOpt) { #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \ case NAME##Model: \ - GenerateArg(Args, OPT_analyzer_constraints, CMDFLAG, SA); \ + GenerateArg(Consumer, OPT_analyzer_constraints, CMDFLAG); \ break; #include "clang/StaticAnalyzer/Core/Analyses.def" default: @@ -872,7 +964,7 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, switch (Opts.AnalysisDiagOpt) { #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \ case PD_##NAME: \ - GenerateArg(Args, OPT_analyzer_output, CMDFLAG, SA); \ + GenerateArg(Consumer, OPT_analyzer_output, CMDFLAG); \ break; #include "clang/StaticAnalyzer/Core/Analyses.def" default: @@ -884,7 +976,7 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, switch (Opts.AnalysisPurgeOpt) { #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \ case NAME: \ - GenerateArg(Args, OPT_analyzer_purge, CMDFLAG, SA); \ + GenerateArg(Consumer, OPT_analyzer_purge, CMDFLAG); \ break; #include "clang/StaticAnalyzer/Core/Analyses.def" default: @@ -896,7 +988,7 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, switch (Opts.InliningMode) { #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \ case NAME: \ - GenerateArg(Args, OPT_analyzer_inlining_mode, CMDFLAG, SA); \ + GenerateArg(Consumer, OPT_analyzer_inlining_mode, CMDFLAG); \ break; #include "clang/StaticAnalyzer/Core/Analyses.def" default: @@ -907,7 +999,7 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, for (const auto &CP : Opts.CheckersAndPackages) { OptSpecifier Opt = CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker; - GenerateArg(Args, Opt, CP.first, SA); + GenerateArg(Consumer, Opt, CP.first); } AnalyzerOptions ConfigOpts; @@ -926,7 +1018,7 @@ static void GenerateAnalyzerArgs(AnalyzerOptions &Opts, if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value) continue; - GenerateArg(Args, OPT_analyzer_config, Key + "=" + Value, SA); + GenerateArg(Consumer, OPT_analyzer_config, Key + "=" + Value); } // Nothing to generate for FullCompilerInvocation. @@ -1192,16 +1284,15 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, /// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`. static void -GenerateOptimizationRemark(SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA, - OptSpecifier OptEQ, StringRef Name, +GenerateOptimizationRemark(ArgumentConsumer Consumer, OptSpecifier OptEQ, + StringRef Name, const CodeGenOptions::OptRemark &Remark) { if (Remark.hasValidPattern()) { - GenerateArg(Args, OptEQ, Remark.Pattern, SA); + GenerateArg(Consumer, OptEQ, Remark.Pattern); } else if (Remark.Kind == CodeGenOptions::RK_Enabled) { - GenerateArg(Args, OPT_R_Joined, Name, SA); + GenerateArg(Consumer, OPT_R_Joined, Name); } else if (Remark.Kind == CodeGenOptions::RK_Disabled) { - GenerateArg(Args, OPT_R_Joined, StringRef("no-") + Name, SA); + GenerateArg(Consumer, OPT_R_Joined, StringRef("no-") + Name); } } @@ -1356,35 +1447,36 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts, Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); } -void CompilerInvocation::GenerateCodeGenArgs( - const CodeGenOptions &Opts, SmallVectorImpl<const char *> &Args, - StringAllocator SA, const llvm::Triple &T, const std::string &OutputFile, - const LangOptions *LangOpts) { +void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, + ArgumentConsumer Consumer, + const llvm::Triple &T, + const std::string &OutputFile, + const LangOptions *LangOpts) { const CodeGenOptions &CodeGenOpts = Opts; if (Opts.OptimizationLevel == 0) - GenerateArg(Args, OPT_O0, SA); + GenerateArg(Consumer, OPT_O0); else - GenerateArg(Args, OPT_O, Twine(Opts.OptimizationLevel), SA); + GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel)); #define CODEGEN_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef CODEGEN_OPTION_WITH_MARSHALLING if (Opts.OptimizationLevel > 0) { if (Opts.Inlining == CodeGenOptions::NormalInlining) - GenerateArg(Args, OPT_finline_functions, SA); + GenerateArg(Consumer, OPT_finline_functions); else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining) - GenerateArg(Args, OPT_finline_hint_functions, SA); + GenerateArg(Consumer, OPT_finline_hint_functions); else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining) - GenerateArg(Args, OPT_fno_inline, SA); + GenerateArg(Consumer, OPT_fno_inline); } if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0) - GenerateArg(Args, OPT_fdirect_access_external_data, SA); + GenerateArg(Consumer, OPT_fdirect_access_external_data); else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0) - GenerateArg(Args, OPT_fno_direct_access_external_data, SA); + GenerateArg(Consumer, OPT_fno_direct_access_external_data); std::optional<StringRef> DebugInfoVal; switch (Opts.DebugInfo) { @@ -1414,23 +1506,23 @@ void CompilerInvocation::GenerateCodeGenArgs( break; } if (DebugInfoVal) - GenerateArg(Args, OPT_debug_info_kind_EQ, *DebugInfoVal, SA); + GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal); for (const auto &Prefix : Opts.DebugPrefixMap) - GenerateArg(Args, OPT_fdebug_prefix_map_EQ, - Prefix.first + "=" + Prefix.second, SA); + GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ, + Prefix.first + "=" + Prefix.second); for (const auto &Prefix : Opts.CoveragePrefixMap) - GenerateArg(Args, OPT_fcoverage_prefix_map_EQ, - Prefix.first + "=" + Prefix.second, SA); + GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ, + Prefix.first + "=" + Prefix.second); if (Opts.NewStructPathTBAA) - GenerateArg(Args, OPT_new_struct_path_tbaa, SA); + GenerateArg(Consumer, OPT_new_struct_path_tbaa); if (Opts.OptimizeSize == 1) - GenerateArg(Args, OPT_O, "s", SA); + GenerateArg(Consumer, OPT_O, "s"); else if (Opts.OptimizeSize == 2) - GenerateArg(Args, OPT_O, "z", SA); + GenerateArg(Consumer, OPT_O, "z"); // SimplifyLibCalls is set only in the absence of -fno-builtin and // -ffreestanding. We'll consider that when generating them. @@ -1438,65 +1530,65 @@ void CompilerInvocation::GenerateCodeGenArgs( // NoBuiltinFuncs are generated by LangOptions. if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1) - GenerateArg(Args, OPT_funroll_loops, SA); + GenerateArg(Consumer, OPT_funroll_loops); else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1) - GenerateArg(Args, OPT_fno_unroll_loops, SA); + GenerateArg(Consumer, OPT_fno_unroll_loops); if (!Opts.BinutilsVersion.empty()) - GenerateArg(Args, OPT_fbinutils_version_EQ, Opts.BinutilsVersion, SA); + GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion); if (Opts.DebugNameTable == static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU)) - GenerateArg(Args, OPT_ggnu_pubnames, SA); + GenerateArg(Consumer, OPT_ggnu_pubnames); else if (Opts.DebugNameTable == static_cast<unsigned>( llvm::DICompileUnit::DebugNameTableKind::Default)) - GenerateArg(Args, OPT_gpubnames, SA); + GenerateArg(Consumer, OPT_gpubnames); auto TNK = Opts.getDebugSimpleTemplateNames(); if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) { if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple) - GenerateArg(Args, OPT_gsimple_template_names_EQ, "simple", SA); + GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple"); else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled) - GenerateArg(Args, OPT_gsimple_template_names_EQ, "mangled", SA); + GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled"); } // ProfileInstrumentUsePath is marshalled automatically, no need to generate // it or PGOUseInstrumentor. if (Opts.TimePasses) { if (Opts.TimePassesPerRun) - GenerateArg(Args, OPT_ftime_report_EQ, "per-pass-run", SA); + GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run"); else - GenerateArg(Args, OPT_ftime_report, SA); + GenerateArg(Consumer, OPT_ftime_report); } if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO) - GenerateArg(Args, OPT_flto_EQ, "full", SA); + GenerateArg(Consumer, OPT_flto_EQ, "full"); if (Opts.PrepareForThinLTO) - GenerateArg(Args, OPT_flto_EQ, "thin", SA); + GenerateArg(Consumer, OPT_flto_EQ, "thin"); if (!Opts.ThinLTOIndexFile.empty()) - GenerateArg(Args, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile, SA); + GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile); if (Opts.SaveTempsFilePrefix == OutputFile) - GenerateArg(Args, OPT_save_temps_EQ, "obj", SA); + GenerateArg(Consumer, OPT_save_temps_EQ, "obj"); StringRef MemProfileBasename("memprof.profraw"); if (!Opts.MemoryProfileOutput.empty()) { if (Opts.MemoryProfileOutput == MemProfileBasename) { - GenerateArg(Args, OPT_fmemory_profile, SA); + GenerateArg(Consumer, OPT_fmemory_profile); } else { size_t ArgLength = Opts.MemoryProfileOutput.size() - MemProfileBasename.size(); - GenerateArg(Args, OPT_fmemory_profile_EQ, - Opts.MemoryProfileOutput.substr(0, ArgLength), SA); + GenerateArg(Consumer, OPT_fmemory_profile_EQ, + Opts.MemoryProfileOutput.substr(0, ArgLength)); } } if (memcmp(Opts.CoverageVersion, "408*", 4) != 0) - GenerateArg(Args, OPT_coverage_version_EQ, - StringRef(Opts.CoverageVersion, 4), SA); + GenerateArg(Consumer, OPT_coverage_version_EQ, + StringRef(Opts.CoverageVersion, 4)); // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely // '-fembed_bitcode', which does not map to any CompilerInvocation field and @@ -1506,95 +1598,94 @@ void CompilerInvocation::GenerateCodeGenArgs( std::string InstrBundle = serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle); if (!InstrBundle.empty()) - GenerateArg(Args, OPT_fxray_instrumentation_bundle, InstrBundle, SA); + GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle); } if (Opts.CFProtectionReturn && Opts.CFProtectionBranch) - GenerateArg(Args, OPT_fcf_protection_EQ, "full", SA); + GenerateArg(Consumer, OPT_fcf_protection_EQ, "full"); else if (Opts.CFProtectionReturn) - GenerateArg(Args, OPT_fcf_protection_EQ, "return", SA); + GenerateArg(Consumer, OPT_fcf_protection_EQ, "return"); else if (Opts.CFProtectionBranch) - GenerateArg(Args, OPT_fcf_protection_EQ, "branch", SA); + GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch"); if (Opts.FunctionReturnThunks) - GenerateArg(Args, OPT_mfunction_return_EQ, "thunk-extern", SA); + GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern"); for (const auto &F : Opts.LinkBitcodeFiles) { bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded && F.PropagateAttrs && F.Internalize; - GenerateArg(Args, + GenerateArg(Consumer, Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file, - F.Filename, SA); + F.Filename); } if (Opts.EmulatedTLS) - GenerateArg(Args, OPT_femulated_tls, SA); + GenerateArg(Consumer, OPT_femulated_tls); if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE()) - GenerateArg(Args, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str(), SA); + GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str()); if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) || (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE())) - GenerateArg(Args, OPT_fdenormal_fp_math_f32_EQ, Opts.FP32DenormalMode.str(), - SA); + GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ, + Opts.FP32DenormalMode.str()); if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) { OptSpecifier Opt = T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return; - GenerateArg(Args, Opt, SA); + GenerateArg(Consumer, Opt); } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) { OptSpecifier Opt = T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return; - GenerateArg(Args, Opt, SA); + GenerateArg(Consumer, Opt); } if (Opts.EnableAIXExtendedAltivecABI) - GenerateArg(Args, OPT_mabi_EQ_vec_extabi, SA); + GenerateArg(Consumer, OPT_mabi_EQ_vec_extabi); if (Opts.XCOFFReadOnlyPointers) - GenerateArg(Args, OPT_mxcoff_roptr, SA); + GenerateArg(Consumer, OPT_mxcoff_roptr); if (!Opts.OptRecordPasses.empty()) - GenerateArg(Args, OPT_opt_record_passes, Opts.OptRecordPasses, SA); + GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses); if (!Opts.OptRecordFormat.empty()) - GenerateArg(Args, OPT_opt_record_format, Opts.OptRecordFormat, SA); + GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat); - GenerateOptimizationRemark(Args, SA, OPT_Rpass_EQ, "pass", + GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass", Opts.OptimizationRemark); - GenerateOptimizationRemark(Args, SA, OPT_Rpass_missed_EQ, "pass-missed", + GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed", Opts.OptimizationRemarkMissed); - GenerateOptimizationRemark(Args, SA, OPT_Rpass_analysis_EQ, "pass-analysis", + GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis", Opts.OptimizationRemarkAnalysis); - GenerateArg(Args, OPT_fdiagnostics_hotness_threshold_EQ, + GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ, Opts.DiagnosticsHotnessThreshold ? Twine(*Opts.DiagnosticsHotnessThreshold) - : "auto", - SA); + : "auto"); - GenerateArg(Args, OPT_fdiagnostics_misexpect_tolerance_EQ, - Twine(*Opts.DiagnosticsMisExpectTolerance), SA); + GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ, + Twine(*Opts.DiagnosticsMisExpectTolerance)); for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover)) - GenerateArg(Args, OPT_fsanitize_recover_EQ, Sanitizer, SA); + GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer); for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap)) - GenerateArg(Args, OPT_fsanitize_trap_EQ, Sanitizer, SA); + GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer); if (!Opts.EmitVersionIdentMetadata) - GenerateArg(Args, OPT_Qn, SA); + GenerateArg(Consumer, OPT_Qn); switch (Opts.FiniteLoops) { case CodeGenOptions::FiniteLoopsKind::Language: break; case CodeGenOptions::FiniteLoopsKind::Always: - GenerateArg(Args, OPT_ffinite_loops, SA); + GenerateArg(Consumer, OPT_ffinite_loops); break; case CodeGenOptions::FiniteLoopsKind::Never: - GenerateArg(Args, OPT_fno_finite_loops, SA); + GenerateArg(Consumer, OPT_fno_finite_loops); break; } } @@ -1770,6 +1861,20 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, if (Args.hasArg(OPT_funified_lto)) Opts.PrepareForThinLTO = true; } + if (Arg *A = Args.getLastArg(options::OPT_ffat_lto_objects, + options::OPT_fno_fat_lto_objects)) { + if (A->getOption().matches(options::OPT_ffat_lto_objects)) { + if (Arg *Uni = Args.getLastArg(options::OPT_funified_lto, + options::OPT_fno_unified_lto)) { + if (Uni->getOption().matches(options::OPT_fno_unified_lto)) + Diags.Report(diag::err_drv_incompatible_options) + << A->getAsString(Args) << "-fno-unified-lto"; + } else + Diags.Report(diag::err_drv_argument_only_allowed_with) + << A->getAsString(Args) << "-funified-lto"; + } + } + if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) { if (IK.getLanguage() != Language::LLVM_IR) Diags.Report(diag::err_drv_argument_only_allowed_with) @@ -1887,7 +1992,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) { if (T.isOSAIX()) { StringRef Name = A->getValue(); - if (Name != "global-dynamic" && Name != "local-exec") + if (Name == "local-dynamic") Diags.Report(diag::err_aix_unsupported_tls_model) << Name; } } @@ -2067,18 +2172,16 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, return Diags.getNumErrors() == NumErrorsBefore; } -static void -GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA) { +static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts, + ArgumentConsumer Consumer) { const DependencyOutputOptions &DependencyOutputOpts = Opts; #define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING if (Opts.ShowIncludesDest != ShowIncludesDestination::None) - GenerateArg(Args, OPT_show_includes, SA); + GenerateArg(Consumer, OPT_show_includes); for (const auto &Dep : Opts.ExtraDeps) { switch (Dep.second) { @@ -2094,7 +2197,7 @@ GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts, // marshalling infrastructure. continue; case EDK_DepFileEntry: - GenerateArg(Args, OPT_fdepfile_entry, Dep.first, SA); + GenerateArg(Consumer, OPT_fdepfile_entry, Dep.first); break; } } @@ -2220,12 +2323,11 @@ static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes, } static void GenerateFileSystemArgs(const FileSystemOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA) { + ArgumentConsumer Consumer) { const FileSystemOptions &FileSystemOpts = Opts; #define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef FILE_SYSTEM_OPTION_WITH_MARSHALLING } @@ -2245,11 +2347,10 @@ static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args, } static void GenerateMigratorArgs(const MigratorOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA) { + ArgumentConsumer Consumer) { const MigratorOptions &MigratorOpts = Opts; #define MIGRATOR_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef MIGRATOR_OPTION_WITH_MARSHALLING } @@ -2268,51 +2369,51 @@ static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args, return Diags.getNumErrors() == NumErrorsBefore; } -void CompilerInvocation::GenerateDiagnosticArgs( - const DiagnosticOptions &Opts, SmallVectorImpl<const char *> &Args, - StringAllocator SA, bool DefaultDiagColor) { +void CompilerInvocationBase::GenerateDiagnosticArgs( + const DiagnosticOptions &Opts, ArgumentConsumer Consumer, + bool DefaultDiagColor) { const DiagnosticOptions *DiagnosticOpts = &Opts; #define DIAG_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef DIAG_OPTION_WITH_MARSHALLING if (!Opts.DiagnosticSerializationFile.empty()) - GenerateArg(Args, OPT_diagnostic_serialized_file, - Opts.DiagnosticSerializationFile, SA); + GenerateArg(Consumer, OPT_diagnostic_serialized_file, + Opts.DiagnosticSerializationFile); if (Opts.ShowColors) - GenerateArg(Args, OPT_fcolor_diagnostics, SA); + GenerateArg(Consumer, OPT_fcolor_diagnostics); if (Opts.VerifyDiagnostics && llvm::is_contained(Opts.VerifyPrefixes, "expected")) - GenerateArg(Args, OPT_verify, SA); + GenerateArg(Consumer, OPT_verify); for (const auto &Prefix : Opts.VerifyPrefixes) if (Prefix != "expected") - GenerateArg(Args, OPT_verify_EQ, Prefix, SA); + GenerateArg(Consumer, OPT_verify_EQ, Prefix); DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected(); if (VIU == DiagnosticLevelMask::None) { // This is the default, don't generate anything. } else if (VIU == DiagnosticLevelMask::All) { - GenerateArg(Args, OPT_verify_ignore_unexpected, SA); + GenerateArg(Consumer, OPT_verify_ignore_unexpected); } else { if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0) - GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "note", SA); + GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "note"); if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0) - GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "remark", SA); + GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "remark"); if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0) - GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "warning", SA); + GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "warning"); if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0) - GenerateArg(Args, OPT_verify_ignore_unexpected_EQ, "error", SA); + GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "error"); } for (const auto &Warning : Opts.Warnings) { // This option is automatically generated from UndefPrefixes. if (Warning == "undef-prefix") continue; - Args.push_back(SA(StringRef("-W") + Warning)); + Consumer(StringRef("-W") + Warning); } for (const auto &Remark : Opts.Remarks) { @@ -2324,7 +2425,7 @@ void CompilerInvocation::GenerateDiagnosticArgs( if (llvm::is_contained(IgnoredRemarks, Remark)) continue; - Args.push_back(SA(StringRef("-R") + Remark)); + Consumer(StringRef("-R") + Remark); } } @@ -2510,12 +2611,10 @@ getProgramActionOpt(frontend::ActionKind ProgramAction) { } static void GenerateFrontendArgs(const FrontendOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA, - bool IsHeader) { + ArgumentConsumer Consumer, bool IsHeader) { const FrontendOptions &FrontendOpts = Opts; #define FRONTEND_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef FRONTEND_OPTION_WITH_MARSHALLING @@ -2524,7 +2623,7 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, // Generating a simple flag covers most frontend actions. std::function<void()> GenerateProgramAction = [&]() { - GenerateArg(Args, *ProgramActionOpt, SA); + GenerateArg(Consumer, *ProgramActionOpt); }; if (!ProgramActionOpt) { @@ -2532,7 +2631,7 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, assert(Opts.ProgramAction == frontend::PluginAction && "Frontend action without option."); GenerateProgramAction = [&]() { - GenerateArg(Args, OPT_plugin, Opts.ActionName, SA); + GenerateArg(Consumer, OPT_plugin, Opts.ActionName); }; } @@ -2553,21 +2652,21 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, } if (Opts.ASTDumpAll) - GenerateArg(Args, OPT_ast_dump_all_EQ, Format, SA); + GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format); if (Opts.ASTDumpDecls) - GenerateArg(Args, OPT_ast_dump_EQ, Format, SA); + GenerateArg(Consumer, OPT_ast_dump_EQ, Format); } else { if (Opts.ASTDumpAll) - GenerateArg(Args, OPT_ast_dump_all, SA); + GenerateArg(Consumer, OPT_ast_dump_all); if (Opts.ASTDumpDecls) - GenerateArg(Args, OPT_ast_dump, SA); + GenerateArg(Consumer, OPT_ast_dump); } }; } if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) { GenerateProgramAction = [&]() { - GenerateArg(Args, OPT_fixit_EQ, Opts.FixItSuffix, SA); + GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix); }; } @@ -2575,34 +2674,34 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, for (const auto &PluginArgs : Opts.PluginArgs) { Option Opt = getDriverOptTable().getOption(OPT_plugin_arg); - const char *Spelling = - SA(Opt.getPrefix() + Opt.getName() + PluginArgs.first); for (const auto &PluginArg : PluginArgs.second) - denormalizeString(Args, Spelling, SA, Opt.getKind(), 0, PluginArg); + denormalizeString(Consumer, + Opt.getPrefix() + Opt.getName() + PluginArgs.first, + Opt.getKind(), 0, PluginArg); } for (const auto &Ext : Opts.ModuleFileExtensions) if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get())) - GenerateArg(Args, OPT_ftest_module_file_extension_EQ, TestExt->str(), SA); + GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str()); if (!Opts.CodeCompletionAt.FileName.empty()) - GenerateArg(Args, OPT_code_completion_at, Opts.CodeCompletionAt.ToString(), - SA); + GenerateArg(Consumer, OPT_code_completion_at, + Opts.CodeCompletionAt.ToString()); for (const auto &Plugin : Opts.Plugins) - GenerateArg(Args, OPT_load, Plugin, SA); + GenerateArg(Consumer, OPT_load, Plugin); // ASTDumpDecls and ASTDumpAll already handled with ProgramAction. for (const auto &ModuleFile : Opts.ModuleFiles) - GenerateArg(Args, OPT_fmodule_file, ModuleFile, SA); + GenerateArg(Consumer, OPT_fmodule_file, ModuleFile); if (Opts.AuxTargetCPU) - GenerateArg(Args, OPT_aux_target_cpu, *Opts.AuxTargetCPU, SA); + GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU); if (Opts.AuxTargetFeatures) for (const auto &Feature : *Opts.AuxTargetFeatures) - GenerateArg(Args, OPT_aux_target_feature, Feature, SA); + GenerateArg(Consumer, OPT_aux_target_feature, Feature); { StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : ""; @@ -2669,13 +2768,13 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, break; } - GenerateArg(Args, OPT_x, - Lang + HeaderUnit + Header + ModuleMap + Preprocessed, SA); + GenerateArg(Consumer, OPT_x, + Lang + HeaderUnit + Header + ModuleMap + Preprocessed); } // OPT_INPUT has a unique class, generate it directly. for (const auto &Input : Opts.Inputs) - Args.push_back(SA(Input.getFile())); + Consumer(Input.getFile()); } static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, @@ -2730,7 +2829,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, "-interface-stub-version=ifs-v1" << ErrorMessage; ProgramAction = frontend::ParseSyntaxOnly; - } else if (!ArgStr.startswith("ifs-")) { + } else if (!ArgStr.starts_with("ifs-")) { std::string ErrorMessage = "Invalid interface stub format: " + ArgStr.str() + "."; Diags.Report(diag::err_drv_invalid_value) @@ -2933,29 +3032,28 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0, return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR); } -static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA) { +static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts, + ArgumentConsumer Consumer) { const HeaderSearchOptions *HeaderSearchOpts = &Opts; #define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef HEADER_SEARCH_OPTION_WITH_MARSHALLING if (Opts.UseLibcxx) - GenerateArg(Args, OPT_stdlib_EQ, "libc++", SA); + GenerateArg(Consumer, OPT_stdlib_EQ, "libc++"); if (!Opts.ModuleCachePath.empty()) - GenerateArg(Args, OPT_fmodules_cache_path, Opts.ModuleCachePath, SA); + GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath); for (const auto &File : Opts.PrebuiltModuleFiles) - GenerateArg(Args, OPT_fmodule_file, File.first + "=" + File.second, SA); + GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second); for (const auto &Path : Opts.PrebuiltModulePaths) - GenerateArg(Args, OPT_fprebuilt_module_path, Path, SA); + GenerateArg(Consumer, OPT_fprebuilt_module_path, Path); for (const auto &Macro : Opts.ModulesIgnoreMacros) - GenerateArg(Args, OPT_fmodules_ignore_macro, Macro.val(), SA); + GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val()); auto Matches = [](const HeaderSearchOptions::Entry &Entry, llvm::ArrayRef<frontend::IncludeDirGroup> Groups, @@ -2986,8 +3084,8 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, }(); if (It->Group == frontend::IndexHeaderMap) - GenerateArg(Args, OPT_index_header_map, SA); - GenerateArg(Args, Opt, It->Path, SA); + GenerateArg(Consumer, OPT_index_header_map); + GenerateArg(Consumer, Opt, It->Path); }; // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may @@ -2999,34 +3097,34 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, ++It) { OptSpecifier Opt = It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore; - GenerateArg(Args, Opt, It->Path, SA); + GenerateArg(Consumer, Opt, It->Path); } // Note: Some paths that came from "-idirafter=xxyy" may have already been // generated as "-iwithprefix=xxyy". If that's the case, their position on // command line was such that this has no semantic impact on include paths. for (; It < End && Matches(*It, {frontend::After}, false, true); ++It) - GenerateArg(Args, OPT_idirafter, It->Path, SA); + GenerateArg(Consumer, OPT_idirafter, It->Path); for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It) - GenerateArg(Args, OPT_iquote, It->Path, SA); + GenerateArg(Consumer, OPT_iquote, It->Path); for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt); ++It) - GenerateArg(Args, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot, - It->Path, SA); + GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot, + It->Path); for (; It < End && Matches(*It, {frontend::System}, true, true); ++It) - GenerateArg(Args, OPT_iframework, It->Path, SA); + GenerateArg(Consumer, OPT_iframework, It->Path); for (; It < End && Matches(*It, {frontend::System}, true, false); ++It) - GenerateArg(Args, OPT_iframeworkwithsysroot, It->Path, SA); + GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path); // Add the paths for the various language specific isystem flags. for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It) - GenerateArg(Args, OPT_c_isystem, It->Path, SA); + GenerateArg(Consumer, OPT_c_isystem, It->Path); for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It) - GenerateArg(Args, OPT_cxx_isystem, It->Path, SA); + GenerateArg(Consumer, OPT_cxx_isystem, It->Path); for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It) - GenerateArg(Args, OPT_objc_isystem, It->Path, SA); + GenerateArg(Consumer, OPT_objc_isystem, It->Path); for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It) - GenerateArg(Args, OPT_objcxx_isystem, It->Path, SA); + GenerateArg(Consumer, OPT_objcxx_isystem, It->Path); // Add the internal paths from a driver that detects standard include paths. // Note: Some paths that came from "-internal-isystem" arguments may have @@ -3038,7 +3136,7 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, OptSpecifier Opt = It->Group == frontend::System ? OPT_internal_isystem : OPT_internal_externc_isystem; - GenerateArg(Args, Opt, It->Path, SA); + GenerateArg(Consumer, Opt, It->Path); } assert(It == End && "Unhandled HeaderSearchOption::Entry."); @@ -3047,11 +3145,11 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, for (const auto &P : Opts.SystemHeaderPrefixes) { OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix : OPT_no_system_header_prefix; - GenerateArg(Args, Opt, P.Prefix, SA); + GenerateArg(Consumer, Opt, P.Prefix); } for (const std::string &F : Opts.VFSOverlayFiles) - GenerateArg(Args, OPT_ivfsoverlay, F, SA); + GenerateArg(Consumer, OPT_ivfsoverlay, F); } static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, @@ -3085,8 +3183,8 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, StringRef Val = A->getValue(); if (Val.contains('=')) { auto Split = Val.split('='); - Opts.PrebuiltModuleFiles.insert( - {std::string(Split.first), std::string(Split.second)}); + Opts.PrebuiltModuleFiles.insert_or_assign( + std::string(Split.first), std::string(Split.second)); } } for (const auto *A : Args.filtered(OPT_fprebuilt_module_path)) @@ -3183,6 +3281,27 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, return Diags.getNumErrors() == NumErrorsBefore; } +static void GenerateAPINotesArgs(const APINotesOptions &Opts, + ArgumentConsumer Consumer) { + if (!Opts.SwiftVersion.empty()) + GenerateArg(Consumer, OPT_fapinotes_swift_version, + Opts.SwiftVersion.getAsString()); + + for (const auto &Path : Opts.ModuleSearchPaths) + GenerateArg(Consumer, OPT_iapinotes_modules, Path); +} + +static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args, + DiagnosticsEngine &diags) { + if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) { + if (Opts.SwiftVersion.tryParse(A->getValue())) + diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + for (const Arg *A : Args.filtered(OPT_iapinotes_modules)) + Opts.ModuleSearchPaths.push_back(A->getValue()); +} + /// Check if input file kind and language standard are compatible. static bool IsInputCompatibleWithStandard(InputKind IK, const LangStandard &S) { @@ -3264,20 +3383,20 @@ static StringRef GetInputKindName(InputKind IK) { llvm_unreachable("unknown input language"); } -void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, - SmallVectorImpl<const char *> &Args, - StringAllocator SA, - const llvm::Triple &T, InputKind IK) { +void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, + ArgumentConsumer Consumer, + const llvm::Triple &T, + InputKind IK) { if (IK.getFormat() == InputKind::Precompiled || IK.getLanguage() == Language::LLVM_IR) { if (Opts.ObjCAutoRefCount) - GenerateArg(Args, OPT_fobjc_arc, SA); + GenerateArg(Consumer, OPT_fobjc_arc); if (Opts.PICLevel != 0) - GenerateArg(Args, OPT_pic_level, Twine(Opts.PICLevel), SA); + GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel)); if (Opts.PIE) - GenerateArg(Args, OPT_pic_is_pie, SA); + GenerateArg(Consumer, OPT_pic_is_pie); for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize)) - GenerateArg(Args, OPT_fsanitize_EQ, Sanitizer, SA); + GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer); return; } @@ -3299,145 +3418,145 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, } auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd); - GenerateArg(Args, StdOpt, LangStandard.getName(), SA); + GenerateArg(Consumer, StdOpt, LangStandard.getName()); if (Opts.IncludeDefaultHeader) - GenerateArg(Args, OPT_finclude_default_header, SA); + GenerateArg(Consumer, OPT_finclude_default_header); if (Opts.DeclareOpenCLBuiltins) - GenerateArg(Args, OPT_fdeclare_opencl_builtins, SA); + GenerateArg(Consumer, OPT_fdeclare_opencl_builtins); const LangOptions *LangOpts = &Opts; #define LANG_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef LANG_OPTION_WITH_MARSHALLING // The '-fcf-protection=' option is generated by CodeGenOpts generator. if (Opts.ObjC) { - GenerateArg(Args, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString(), SA); + GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString()); if (Opts.GC == LangOptions::GCOnly) - GenerateArg(Args, OPT_fobjc_gc_only, SA); + GenerateArg(Consumer, OPT_fobjc_gc_only); else if (Opts.GC == LangOptions::HybridGC) - GenerateArg(Args, OPT_fobjc_gc, SA); + GenerateArg(Consumer, OPT_fobjc_gc); else if (Opts.ObjCAutoRefCount == 1) - GenerateArg(Args, OPT_fobjc_arc, SA); + GenerateArg(Consumer, OPT_fobjc_arc); if (Opts.ObjCWeakRuntime) - GenerateArg(Args, OPT_fobjc_runtime_has_weak, SA); + GenerateArg(Consumer, OPT_fobjc_runtime_has_weak); if (Opts.ObjCWeak) - GenerateArg(Args, OPT_fobjc_weak, SA); + GenerateArg(Consumer, OPT_fobjc_weak); if (Opts.ObjCSubscriptingLegacyRuntime) - GenerateArg(Args, OPT_fobjc_subscripting_legacy_runtime, SA); + GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime); } if (Opts.GNUCVersion != 0) { unsigned Major = Opts.GNUCVersion / 100 / 100; unsigned Minor = (Opts.GNUCVersion / 100) % 100; unsigned Patch = Opts.GNUCVersion % 100; - GenerateArg(Args, OPT_fgnuc_version_EQ, - Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch), SA); + GenerateArg(Consumer, OPT_fgnuc_version_EQ, + Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch)); } if (Opts.IgnoreXCOFFVisibility) - GenerateArg(Args, OPT_mignore_xcoff_visibility, SA); + GenerateArg(Consumer, OPT_mignore_xcoff_visibility); if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) { - GenerateArg(Args, OPT_ftrapv, SA); - GenerateArg(Args, OPT_ftrapv_handler, Opts.OverflowHandler, SA); + GenerateArg(Consumer, OPT_ftrapv); + GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler); } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) { - GenerateArg(Args, OPT_fwrapv, SA); + GenerateArg(Consumer, OPT_fwrapv); } if (Opts.MSCompatibilityVersion != 0) { unsigned Major = Opts.MSCompatibilityVersion / 10000000; unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100; unsigned Subminor = Opts.MSCompatibilityVersion % 100000; - GenerateArg(Args, OPT_fms_compatibility_version, - Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor), SA); + GenerateArg(Consumer, OPT_fms_compatibility_version, + Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor)); } if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17) || T.isOSzOS()) { if (!Opts.Trigraphs) - GenerateArg(Args, OPT_fno_trigraphs, SA); + GenerateArg(Consumer, OPT_fno_trigraphs); } else { if (Opts.Trigraphs) - GenerateArg(Args, OPT_ftrigraphs, SA); + GenerateArg(Consumer, OPT_ftrigraphs); } if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200)) - GenerateArg(Args, OPT_fblocks, SA); + GenerateArg(Consumer, OPT_fblocks); if (Opts.ConvergentFunctions && !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice)) - GenerateArg(Args, OPT_fconvergent_functions, SA); + GenerateArg(Consumer, OPT_fconvergent_functions); if (Opts.NoBuiltin && !Opts.Freestanding) - GenerateArg(Args, OPT_fno_builtin, SA); + GenerateArg(Consumer, OPT_fno_builtin); if (!Opts.NoBuiltin) for (const auto &Func : Opts.NoBuiltinFuncs) - GenerateArg(Args, OPT_fno_builtin_, Func, SA); + GenerateArg(Consumer, OPT_fno_builtin_, Func); if (Opts.LongDoubleSize == 128) - GenerateArg(Args, OPT_mlong_double_128, SA); + GenerateArg(Consumer, OPT_mlong_double_128); else if (Opts.LongDoubleSize == 64) - GenerateArg(Args, OPT_mlong_double_64, SA); + GenerateArg(Consumer, OPT_mlong_double_64); else if (Opts.LongDoubleSize == 80) - GenerateArg(Args, OPT_mlong_double_80, SA); + GenerateArg(Consumer, OPT_mlong_double_80); // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='. // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or // '-fopenmp-targets='. if (Opts.OpenMP && !Opts.OpenMPSimd) { - GenerateArg(Args, OPT_fopenmp, SA); + GenerateArg(Consumer, OPT_fopenmp); if (Opts.OpenMP != 51) - GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA); + GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP)); if (!Opts.OpenMPUseTLS) - GenerateArg(Args, OPT_fnoopenmp_use_tls, SA); + GenerateArg(Consumer, OPT_fnoopenmp_use_tls); if (Opts.OpenMPIsTargetDevice) - GenerateArg(Args, OPT_fopenmp_is_target_device, SA); + GenerateArg(Consumer, OPT_fopenmp_is_target_device); if (Opts.OpenMPIRBuilder) - GenerateArg(Args, OPT_fopenmp_enable_irbuilder, SA); + GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder); } if (Opts.OpenMPSimd) { - GenerateArg(Args, OPT_fopenmp_simd, SA); + GenerateArg(Consumer, OPT_fopenmp_simd); if (Opts.OpenMP != 51) - GenerateArg(Args, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP), SA); + GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP)); } if (Opts.OpenMPThreadSubscription) - GenerateArg(Args, OPT_fopenmp_assume_threads_oversubscription, SA); + GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription); if (Opts.OpenMPTeamSubscription) - GenerateArg(Args, OPT_fopenmp_assume_teams_oversubscription, SA); + GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription); if (Opts.OpenMPTargetDebug != 0) - GenerateArg(Args, OPT_fopenmp_target_debug_EQ, - Twine(Opts.OpenMPTargetDebug), SA); + GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ, + Twine(Opts.OpenMPTargetDebug)); if (Opts.OpenMPCUDANumSMs != 0) - GenerateArg(Args, OPT_fopenmp_cuda_number_of_sm_EQ, - Twine(Opts.OpenMPCUDANumSMs), SA); + GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ, + Twine(Opts.OpenMPCUDANumSMs)); if (Opts.OpenMPCUDABlocksPerSM != 0) - GenerateArg(Args, OPT_fopenmp_cuda_blocks_per_sm_EQ, - Twine(Opts.OpenMPCUDABlocksPerSM), SA); + GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ, + Twine(Opts.OpenMPCUDABlocksPerSM)); if (Opts.OpenMPCUDAReductionBufNum != 1024) - GenerateArg(Args, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ, - Twine(Opts.OpenMPCUDAReductionBufNum), SA); + GenerateArg(Consumer, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ, + Twine(Opts.OpenMPCUDAReductionBufNum)); if (!Opts.OMPTargetTriples.empty()) { std::string Targets; @@ -3445,83 +3564,106 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, llvm::interleave( Opts.OMPTargetTriples, OS, [&OS](const llvm::Triple &T) { OS << T.str(); }, ","); - GenerateArg(Args, OPT_fopenmp_targets_EQ, OS.str(), SA); + GenerateArg(Consumer, OPT_fopenmp_targets_EQ, OS.str()); } if (!Opts.OMPHostIRFile.empty()) - GenerateArg(Args, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile, SA); + GenerateArg(Consumer, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile); if (Opts.OpenMPCUDAMode) - GenerateArg(Args, OPT_fopenmp_cuda_mode, SA); + GenerateArg(Consumer, OPT_fopenmp_cuda_mode); + + if (Opts.OpenACC) { + GenerateArg(Consumer, OPT_fopenacc); + if (!Opts.OpenACCMacroOverride.empty()) + GenerateArg(Consumer, OPT_openacc_macro_override, + Opts.OpenACCMacroOverride); + } // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are // generated from CodeGenOptions. if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast) - GenerateArg(Args, OPT_ffp_contract, "fast", SA); + GenerateArg(Consumer, OPT_ffp_contract, "fast"); else if (Opts.DefaultFPContractMode == LangOptions::FPM_On) - GenerateArg(Args, OPT_ffp_contract, "on", SA); + GenerateArg(Consumer, OPT_ffp_contract, "on"); else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off) - GenerateArg(Args, OPT_ffp_contract, "off", SA); + GenerateArg(Consumer, OPT_ffp_contract, "off"); else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas) - GenerateArg(Args, OPT_ffp_contract, "fast-honor-pragmas", SA); + GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas"); for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize)) - GenerateArg(Args, OPT_fsanitize_EQ, Sanitizer, SA); + GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer); // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'. for (const std::string &F : Opts.NoSanitizeFiles) - GenerateArg(Args, OPT_fsanitize_ignorelist_EQ, F, SA); - - if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver3_8) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "3.8", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver4) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "4.0", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver6) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "6.0", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver7) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "7.0", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver9) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "9.0", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver11) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "11.0", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver12) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "12.0", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver14) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "14.0", SA); - else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver15) - GenerateArg(Args, OPT_fclang_abi_compat_EQ, "15.0", SA); + GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F); + + switch (Opts.getClangABICompat()) { + case LangOptions::ClangABI::Ver3_8: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "3.8"); + break; + case LangOptions::ClangABI::Ver4: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "4.0"); + break; + case LangOptions::ClangABI::Ver6: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "6.0"); + break; + case LangOptions::ClangABI::Ver7: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "7.0"); + break; + case LangOptions::ClangABI::Ver9: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "9.0"); + break; + case LangOptions::ClangABI::Ver11: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "11.0"); + break; + case LangOptions::ClangABI::Ver12: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "12.0"); + break; + case LangOptions::ClangABI::Ver14: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "14.0"); + break; + case LangOptions::ClangABI::Ver15: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "15.0"); + break; + case LangOptions::ClangABI::Ver17: + GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0"); + break; + case LangOptions::ClangABI::Latest: + break; + } if (Opts.getSignReturnAddressScope() == LangOptions::SignReturnAddressScopeKind::All) - GenerateArg(Args, OPT_msign_return_address_EQ, "all", SA); + GenerateArg(Consumer, OPT_msign_return_address_EQ, "all"); else if (Opts.getSignReturnAddressScope() == LangOptions::SignReturnAddressScopeKind::NonLeaf) - GenerateArg(Args, OPT_msign_return_address_EQ, "non-leaf", SA); + GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf"); if (Opts.getSignReturnAddressKey() == LangOptions::SignReturnAddressKeyKind::BKey) - GenerateArg(Args, OPT_msign_return_address_key_EQ, "b_key", SA); + GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key"); if (Opts.CXXABI) - GenerateArg(Args, OPT_fcxx_abi_EQ, TargetCXXABI::getSpelling(*Opts.CXXABI), - SA); + GenerateArg(Consumer, OPT_fcxx_abi_EQ, + TargetCXXABI::getSpelling(*Opts.CXXABI)); if (Opts.RelativeCXXABIVTables) - GenerateArg(Args, OPT_fexperimental_relative_cxx_abi_vtables, SA); + GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables); else - GenerateArg(Args, OPT_fno_experimental_relative_cxx_abi_vtables, SA); + GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables); if (Opts.UseTargetPathSeparator) - GenerateArg(Args, OPT_ffile_reproducible, SA); + GenerateArg(Consumer, OPT_ffile_reproducible); else - GenerateArg(Args, OPT_fno_file_reproducible, SA); + GenerateArg(Consumer, OPT_fno_file_reproducible); for (const auto &MP : Opts.MacroPrefixMap) - GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA); + GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second); if (!Opts.RandstructSeed.empty()) - GenerateArg(Args, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed, SA); + GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed); } bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, @@ -3772,11 +3914,17 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << "-fdefault-calling-conv"; else { - if (T.getArch() != llvm::Triple::x86) + switch (T.getArch()) { + case llvm::Triple::x86: + Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); + break; + case llvm::Triple::m68k: + Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall); + break; + default: Diags.Report(diag::err_drv_argument_not_allowed_with) << A->getSpelling() << T.getTriple(); - else - Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); + } } } @@ -3901,6 +4049,14 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, (T.isNVPTX() || T.isAMDGCN()) && Args.hasArg(options::OPT_fopenmp_cuda_mode); + // OpenACC Configuration. + if (Args.hasArg(options::OPT_fopenacc)) { + Opts.OpenACC = true; + + if (Arg *A = Args.getLastArg(options::OPT_openacc_macro_override)) + Opts.OpenACCMacroOverride = A->getValue(); + } + // FIXME: Eliminate this dependency. unsigned Opt = getOptimizationLevel(Args, IK, Diags), OptSize = getOptimizationLevelSize(Args); @@ -3950,13 +4106,13 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, // Check the version number is valid: either 3.x (0 <= x <= 9) or // y or y.0 (4 <= y <= current version). - if (!VerParts.first.startswith("0") && - !VerParts.first.getAsInteger(10, Major) && - 3 <= Major && Major <= CLANG_VERSION_MAJOR && - (Major == 3 ? VerParts.second.size() == 1 && - !VerParts.second.getAsInteger(10, Minor) - : VerParts.first.size() == Ver.size() || - VerParts.second == "0")) { + if (!VerParts.first.starts_with("0") && + !VerParts.first.getAsInteger(10, Major) && 3 <= Major && + Major <= CLANG_VERSION_MAJOR && + (Major == 3 + ? VerParts.second.size() == 1 && + !VerParts.second.getAsInteger(10, Minor) + : VerParts.first.size() == Ver.size() || VerParts.second == "0")) { // Got a valid version number. if (Major == 3 && Minor <= 8) Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8); @@ -3976,6 +4132,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.setClangABICompat(LangOptions::ClangABI::Ver14); else if (Major <= 15) Opts.setClangABICompat(LangOptions::ClangABI::Ver15); + else if (Major <= 17) + Opts.setClangABICompat(LangOptions::ClangABI::Ver17); } else if (Ver != "latest") { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); @@ -4001,10 +4159,10 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) { StringRef SignKey = A->getValue(); if (!SignScope.empty() && !SignKey.empty()) { - if (SignKey.equals_insensitive("a_key")) + if (SignKey == "a_key") Opts.setSignReturnAddressKey( LangOptions::SignReturnAddressKeyKind::AKey); - else if (SignKey.equals_insensitive("b_key")) + else if (SignKey == "b_key") Opts.setSignReturnAddressKey( LangOptions::SignReturnAddressKeyKind::BKey); else @@ -4033,6 +4191,14 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, options::OPT_fno_experimental_relative_cxx_abi_vtables, TargetCXXABI::usesRelativeVTables(T)); + // RTTI is on by default. + bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti); + Opts.OmitVTableRTTI = + Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti, + options::OPT_fno_experimental_omit_vtable_rtti, false); + if (Opts.OmitVTableRTTI && HasRTTI) + Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti); + for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) { auto Split = StringRef(A).split('='); Opts.MacroPrefixMap.insert( @@ -4067,9 +4233,24 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, // Validate options for HLSL if (Opts.HLSL) { - bool SupportedTarget = T.getArch() == llvm::Triple::dxil && - T.getOS() == llvm::Triple::ShaderModel; - if (!SupportedTarget) + // TODO: Revisit restricting SPIR-V to logical once we've figured out how to + // handle PhysicalStorageBuffer64 memory model + if (T.isDXIL() || T.isSPIRVLogical()) { + enum { ShaderModel, ShaderStage }; + if (T.getOSName().empty()) { + Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target) + << ShaderModel << T.str(); + } else if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) { + Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported) + << ShaderModel << T.getOSName() << T.str(); + } else if (T.getEnvironmentName().empty()) { + Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target) + << ShaderStage << T.str(); + } else if (!T.isShaderStageEnvironment()) { + Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported) + << ShaderStage << T.getEnvironmentName() << T.str(); + } + } else Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str(); } @@ -4121,30 +4302,28 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { llvm_unreachable("invalid frontend action"); } -static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA, +static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts, + ArgumentConsumer Consumer, const LangOptions &LangOpts, const FrontendOptions &FrontendOpts, const CodeGenOptions &CodeGenOpts) { - PreprocessorOptions *PreprocessorOpts = &Opts; + const PreprocessorOptions *PreprocessorOpts = &Opts; #define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef PREPROCESSOR_OPTION_WITH_MARSHALLING if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate) - GenerateArg(Args, OPT_pch_through_hdrstop_use, SA); + GenerateArg(Consumer, OPT_pch_through_hdrstop_use); for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn) - GenerateArg(Args, OPT_error_on_deserialized_pch_decl, D, SA); + GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D); if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false)) - GenerateArg(Args, OPT_preamble_bytes_EQ, + GenerateArg(Consumer, OPT_preamble_bytes_EQ, Twine(Opts.PrecompiledPreambleBytes.first) + "," + - (Opts.PrecompiledPreambleBytes.second ? "1" : "0"), - SA); + (Opts.PrecompiledPreambleBytes.second ? "1" : "0")); for (const auto &M : Opts.Macros) { // Don't generate __CET__ macro definitions. They are implied by the @@ -4159,7 +4338,7 @@ static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, CodeGenOpts.CFProtectionBranch) continue; - GenerateArg(Args, M.second ? OPT_U : OPT_D, M.first, SA); + GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first); } for (const auto &I : Opts.Includes) { @@ -4174,17 +4353,20 @@ static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, if (LangOpts.HLSL && I == "hlsl.h") continue; - GenerateArg(Args, OPT_include, I, SA); + GenerateArg(Consumer, OPT_include, I); } for (const auto &CI : Opts.ChainedIncludes) - GenerateArg(Args, OPT_chain_include, CI, SA); + GenerateArg(Consumer, OPT_chain_include, CI); for (const auto &RF : Opts.RemappedFiles) - GenerateArg(Args, OPT_remap_file, RF.first + ";" + RF.second, SA); + GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second); if (Opts.SourceDateEpoch) - GenerateArg(Args, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch), SA); + GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch)); + + if (Opts.DefineTargetOSMacros) + GenerateArg(Consumer, OPT_fdefine_target_os_macros); // Don't handle LexEditorPlaceholders. It is implied by the action that is // generated elsewhere. @@ -4284,26 +4466,31 @@ static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, if (isStrictlyPreprocessorAction(Action)) Opts.LexEditorPlaceholders = false; + Opts.DefineTargetOSMacros = + Args.hasFlag(OPT_fdefine_target_os_macros, + OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros); + return Diags.getNumErrors() == NumErrorsBefore; } -static void GeneratePreprocessorOutputArgs( - const PreprocessorOutputOptions &Opts, SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA, frontend::ActionKind Action) { +static void +GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts, + ArgumentConsumer Consumer, + frontend::ActionKind Action) { const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts; #define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP; if (Generate_dM) - GenerateArg(Args, OPT_dM, SA); + GenerateArg(Consumer, OPT_dM); if (!Generate_dM && Opts.ShowMacros) - GenerateArg(Args, OPT_dD, SA); + GenerateArg(Consumer, OPT_dD); if (Opts.DirectivesOnly) - GenerateArg(Args, OPT_fdirectives_only, SA); + GenerateArg(Consumer, OPT_fdirectives_only); } static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, @@ -4326,20 +4513,19 @@ static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, } static void GenerateTargetArgs(const TargetOptions &Opts, - SmallVectorImpl<const char *> &Args, - CompilerInvocation::StringAllocator SA) { + ArgumentConsumer Consumer) { const TargetOptions *TargetOpts = &Opts; #define TARGET_OPTION_WITH_MARSHALLING(...) \ - GENERATE_OPTION_WITH_MARSHALLING(Args, SA, __VA_ARGS__) + GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__) #include "clang/Driver/Options.inc" #undef TARGET_OPTION_WITH_MARSHALLING if (!Opts.SDKVersion.empty()) - GenerateArg(Args, OPT_target_sdk_version_EQ, Opts.SDKVersion.getAsString(), - SA); + GenerateArg(Consumer, OPT_target_sdk_version_EQ, + Opts.SDKVersion.getAsString()); if (!Opts.DarwinTargetVariantSDKVersion.empty()) - GenerateArg(Args, OPT_darwin_target_variant_sdk_version_EQ, - Opts.DarwinTargetVariantSDKVersion.getAsString(), SA); + GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ, + Opts.DarwinTargetVariantSDKVersion.getAsString()); } static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args, @@ -4381,11 +4567,11 @@ bool CompilerInvocation::CreateFromArgsImpl( // Parse the arguments. const OptTable &Opts = getDriverOptTable(); - const unsigned IncludedFlagsBitmask = options::CC1Option; + llvm::opt::Visibility VisibilityMask(options::CC1Option); unsigned MissingArgIndex, MissingArgCount; InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex, - MissingArgCount, IncludedFlagsBitmask); - LangOptions &LangOpts = *Res.getLangOpts(); + MissingArgCount, VisibilityMask); + LangOptions &LangOpts = Res.getLangOpts(); // Check for missing argument error. if (MissingArgCount) @@ -4396,7 +4582,7 @@ bool CompilerInvocation::CreateFromArgsImpl( for (const auto *A : Args.filtered(OPT_UNKNOWN)) { auto ArgString = A->getAsString(Args); std::string Nearest; - if (Opts.findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1) + if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1) Diags.Report(diag::err_drv_unknown_argument) << ArgString; else Diags.Report(diag::err_drv_unknown_argument_with_suggestion) @@ -4405,7 +4591,7 @@ bool CompilerInvocation::CreateFromArgsImpl( ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags); ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags); - ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags); + ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags); ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags, /*DefaultDiagColor=*/false); ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile); @@ -4415,6 +4601,7 @@ bool CompilerInvocation::CreateFromArgsImpl( llvm::Triple T(Res.getTargetOpts().Triple); ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags, Res.getFileSystemOpts().WorkingDir); + ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags); ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes, Diags); @@ -4466,7 +4653,7 @@ bool CompilerInvocation::CreateFromArgsImpl( // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && - !Res.getLangOpts()->Sanitize.empty()) { + !Res.getLangOpts().Sanitize.empty()) { Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false; Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored); } @@ -4514,7 +4701,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation, std::string CompilerInvocation::getModuleHash() const { // FIXME: Consider using SHA1 instead of MD5. - llvm::HashBuilder<llvm::MD5, llvm::support::endianness::native> HBuilder; + llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder; // Note: For QoI reasons, the things we use as a hash here should all be // dumped via the -module-info flag. @@ -4534,15 +4721,15 @@ std::string CompilerInvocation::getModuleHash() const { #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" - HBuilder.addRange(LangOpts->ModuleFeatures); + HBuilder.addRange(getLangOpts().ModuleFeatures); - HBuilder.add(LangOpts->ObjCRuntime); - HBuilder.addRange(LangOpts->CommentOpts.BlockCommandNames); + HBuilder.add(getLangOpts().ObjCRuntime); + HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames); // Extend the signature with the target options. - HBuilder.add(TargetOpts->Triple, TargetOpts->CPU, TargetOpts->TuneCPU, - TargetOpts->ABI); - HBuilder.addRange(TargetOpts->FeaturesAsWritten); + HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU, + getTargetOpts().TuneCPU, getTargetOpts().ABI); + HBuilder.addRange(getTargetOpts().FeaturesAsWritten); // Extend the signature with preprocessor options. const PreprocessorOptions &ppOpts = getPreprocessorOpts(); @@ -4590,14 +4777,38 @@ std::string CompilerInvocation::getModuleHash() const { for (const auto &ext : getFrontendOpts().ModuleFileExtensions) ext->hashExtension(HBuilder); + // Extend the signature with the Swift version for API notes. + const APINotesOptions &APINotesOpts = getAPINotesOpts(); + if (!APINotesOpts.SwiftVersion.empty()) { + HBuilder.add(APINotesOpts.SwiftVersion.getMajor()); + if (auto Minor = APINotesOpts.SwiftVersion.getMinor()) + HBuilder.add(*Minor); + if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor()) + HBuilder.add(*Subminor); + if (auto Build = APINotesOpts.SwiftVersion.getBuild()) + HBuilder.add(*Build); + } + // When compiling with -gmodules, also hash -fdebug-prefix-map as it // affects the debug info in the PCM. if (getCodeGenOpts().DebugTypeExtRefs) HBuilder.addRange(getCodeGenOpts().DebugPrefixMap); + // Extend the signature with the affecting debug options. + if (getHeaderSearchOpts().ModuleFormat == "obj") { +#define DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name); +#define VALUE_DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name); +#define ENUM_DEBUGOPT(Name, Type, Bits, Default) \ + HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name())); +#define BENIGN_DEBUGOPT(Name, Bits, Default) +#define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default) +#define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default) +#include "clang/Basic/DebugOptions.def" + } + // Extend the signature with the enabled sanitizers, if at least one is // enabled. Sanitizers which cannot affect AST generation aren't hashed. - SanitizerSet SanHash = LangOpts->Sanitize; + SanitizerSet SanHash = getLangOpts().Sanitize; SanHash.clear(getPPTransparentSanitizers()); if (!SanHash.empty()) HBuilder.add(SanHash.Mask); @@ -4608,48 +4819,44 @@ std::string CompilerInvocation::getModuleHash() const { return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false); } -void CompilerInvocation::generateCC1CommandLine( - SmallVectorImpl<const char *> &Args, StringAllocator SA) const { - llvm::Triple T(TargetOpts->Triple); - - GenerateFileSystemArgs(FileSystemOpts, Args, SA); - GenerateMigratorArgs(MigratorOpts, Args, SA); - GenerateAnalyzerArgs(*AnalyzerOpts, Args, SA); - GenerateDiagnosticArgs(*DiagnosticOpts, Args, SA, false); - GenerateFrontendArgs(FrontendOpts, Args, SA, LangOpts->IsHeaderFile); - GenerateTargetArgs(*TargetOpts, Args, SA); - GenerateHeaderSearchArgs(*HeaderSearchOpts, Args, SA); - GenerateLangArgs(*LangOpts, Args, SA, T, FrontendOpts.DashX); - GenerateCodeGenArgs(CodeGenOpts, Args, SA, T, FrontendOpts.OutputFile, - &*LangOpts); - GeneratePreprocessorArgs(*PreprocessorOpts, Args, SA, *LangOpts, FrontendOpts, - CodeGenOpts); - GeneratePreprocessorOutputArgs(PreprocessorOutputOpts, Args, SA, - FrontendOpts.ProgramAction); - GenerateDependencyOutputArgs(DependencyOutputOpts, Args, SA); +void CompilerInvocationBase::generateCC1CommandLine( + ArgumentConsumer Consumer) const { + llvm::Triple T(getTargetOpts().Triple); + + GenerateFileSystemArgs(getFileSystemOpts(), Consumer); + GenerateMigratorArgs(getMigratorOpts(), Consumer); + GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer); + GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer, + /*DefaultDiagColor=*/false); + GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile); + GenerateTargetArgs(getTargetOpts(), Consumer); + GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer); + GenerateAPINotesArgs(getAPINotesOpts(), Consumer); + GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX); + GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T, + getFrontendOpts().OutputFile, &getLangOpts()); + GeneratePreprocessorArgs(getPreprocessorOpts(), Consumer, getLangOpts(), + getFrontendOpts(), getCodeGenOpts()); + GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer, + getFrontendOpts().ProgramAction); + GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer); } -std::vector<std::string> CompilerInvocation::getCC1CommandLine() const { - // Set up string allocator. - llvm::BumpPtrAllocator Alloc; - llvm::StringSaver Strings(Alloc); - auto SA = [&Strings](const Twine &Arg) { return Strings.save(Arg).data(); }; - - // Synthesize full command line from the CompilerInvocation, including "-cc1". - SmallVector<const char *, 32> Args{"-cc1"}; - generateCC1CommandLine(Args, SA); - - // Convert arguments to the return type. - return std::vector<std::string>{Args.begin(), Args.end()}; +std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const { + std::vector<std::string> Args{"-cc1"}; + generateCC1CommandLine( + [&Args](const Twine &Arg) { Args.push_back(Arg.str()); }); + return Args; } void CompilerInvocation::resetNonModularOptions() { - getLangOpts()->resetNonModularOptions(); + getLangOpts().resetNonModularOptions(); getPreprocessorOpts().resetNonModularOptions(); + getCodeGenOpts().resetNonModularOptions(getHeaderSearchOpts().ModuleFormat); } void CompilerInvocation::clearImplicitModuleBuildOptions() { - getLangOpts()->ImplicitModules = false; + getLangOpts().ImplicitModules = false; getHeaderSearchOpts().ImplicitModuleMaps = false; getHeaderSearchOpts().ModuleCachePath.clear(); getHeaderSearchOpts().ModulesValidateOncePerBuildSession = false; |