diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/Frontend/CompilerInvocation.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'clang/lib/Frontend/CompilerInvocation.cpp')
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 311 |
1 files changed, 194 insertions, 117 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 2dd96e68bb92..0bb9c8c83c63 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -52,8 +52,6 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -94,8 +92,11 @@ #include <cassert> #include <cstddef> #include <cstring> +#include <ctime> #include <fstream> +#include <limits> #include <memory> +#include <optional> #include <string> #include <tuple> #include <type_traits> @@ -113,8 +114,8 @@ using namespace llvm::opt; // Parse misexpect tolerance argument value. // Valid option values are integers in the range [0, 100) -inline Expected<Optional<uint64_t>> parseToleranceOption(StringRef Arg) { - int64_t Val; +static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) { + uint32_t Val; if (Arg.getAsInteger(10, Val)) return llvm::createStringError(llvm::inconvertibleErrorCode(), "Not an integer: %s", Arg.data()); @@ -168,21 +169,22 @@ CompilerInvocationRefBase::~CompilerInvocationRefBase() = default; #include "clang/Driver/Options.inc" #undef SIMPLE_ENUM_VALUE_TABLE -static llvm::Optional<bool> normalizeSimpleFlag(OptSpecifier Opt, - unsigned TableIndex, - const ArgList &Args, - DiagnosticsEngine &Diags) { +static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt, + unsigned TableIndex, + const ArgList &Args, + DiagnosticsEngine &Diags) { if (Args.hasArg(Opt)) return true; - return None; + return std::nullopt; } -static Optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt, unsigned, - const ArgList &Args, - DiagnosticsEngine &) { +static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt, + unsigned, + const ArgList &Args, + DiagnosticsEngine &) { if (Args.hasArg(Opt)) return false; - return None; + return std::nullopt; } /// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but @@ -197,18 +199,17 @@ static void denormalizeSimpleFlag(SmallVectorImpl<const char *> &Args, } template <typename T> static constexpr bool is_uint64_t_convertible() { - return !std::is_same<T, uint64_t>::value && - llvm::is_integral_or_enum<T>::value; + return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value; } template <typename T, std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false> static auto makeFlagToValueNormalizer(T Value) { return [Value](OptSpecifier Opt, unsigned, const ArgList &Args, - DiagnosticsEngine &) -> Optional<T> { + DiagnosticsEngine &) -> std::optional<T> { if (Args.hasArg(Opt)) return Value; - return None; + return std::nullopt; }; } @@ -220,13 +221,13 @@ static auto makeFlagToValueNormalizer(T Value) { static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue, OptSpecifier OtherOpt) { - return [Value, OtherValue, OtherOpt](OptSpecifier Opt, unsigned, - const ArgList &Args, - DiagnosticsEngine &) -> Optional<bool> { + return [Value, OtherValue, + OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args, + DiagnosticsEngine &) -> std::optional<bool> { if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) { return A->getOption().matches(Opt) ? Value : OtherValue; } - return None; + return std::nullopt; }; } @@ -269,34 +270,34 @@ denormalizeString(SmallVectorImpl<const char *> &Args, const char *Spelling, denormalizeStringImpl(Args, Spelling, SA, OptClass, TableIndex, Twine(Value)); } -static Optional<SimpleEnumValue> +static std::optional<SimpleEnumValue> findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) { for (int I = 0, E = Table.Size; I != E; ++I) if (Name == Table.Table[I].Name) return Table.Table[I]; - return None; + return std::nullopt; } -static Optional<SimpleEnumValue> +static std::optional<SimpleEnumValue> findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) { for (int I = 0, E = Table.Size; I != E; ++I) if (Value == Table.Table[I].Value) return Table.Table[I]; - return None; + return std::nullopt; } -static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt, - unsigned TableIndex, - const ArgList &Args, - DiagnosticsEngine &Diags) { +static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt, + unsigned TableIndex, + const ArgList &Args, + DiagnosticsEngine &Diags) { assert(TableIndex < SimpleEnumValueTablesSize); const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex]; auto *Arg = Args.getLastArg(Opt); if (!Arg) - return None; + return std::nullopt; StringRef ArgValue = Arg->getValue(); if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue)) @@ -304,7 +305,7 @@ static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt, Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << ArgValue; - return None; + return std::nullopt; } static void denormalizeSimpleEnumImpl(SmallVectorImpl<const char *> &Args, @@ -333,32 +334,33 @@ static void denormalizeSimpleEnum(SmallVectorImpl<const char *> &Args, static_cast<unsigned>(Value)); } -static Optional<std::string> normalizeString(OptSpecifier Opt, int TableIndex, - const ArgList &Args, - DiagnosticsEngine &Diags) { +static std::optional<std::string> normalizeString(OptSpecifier Opt, + int TableIndex, + const ArgList &Args, + DiagnosticsEngine &Diags) { auto *Arg = Args.getLastArg(Opt); if (!Arg) - return None; + return std::nullopt; return std::string(Arg->getValue()); } template <typename IntTy> -static Optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int, - const ArgList &Args, - DiagnosticsEngine &Diags) { +static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int, + const ArgList &Args, + DiagnosticsEngine &Diags) { auto *Arg = Args.getLastArg(Opt); if (!Arg) - return None; + return std::nullopt; IntTy Res; if (StringRef(Arg->getValue()).getAsInteger(0, Res)) { Diags.Report(diag::err_drv_invalid_int_value) << Arg->getAsString(Args) << Arg->getValue(); - return None; + return std::nullopt; } return Res; } -static Optional<std::vector<std::string>> +static std::optional<std::vector<std::string>> normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args, DiagnosticsEngine &) { return Args.getAllArgValues(Opt); @@ -396,12 +398,13 @@ static void denormalizeStringVector(SmallVectorImpl<const char *> &Args, } } -static Optional<std::string> normalizeTriple(OptSpecifier Opt, int TableIndex, - const ArgList &Args, - DiagnosticsEngine &Diags) { +static std::optional<std::string> normalizeTriple(OptSpecifier Opt, + int TableIndex, + const ArgList &Args, + DiagnosticsEngine &Diags) { auto *Arg = Args.getLastArg(Opt); if (!Arg) - return None; + return std::nullopt; return llvm::Triple::normalize(Arg->getValue()); } @@ -490,9 +493,6 @@ static bool FixupInvocation(CompilerInvocation &Invocation, if (LangOpts.AppleKext && !LangOpts.CPlusPlus) Diags.Report(diag::warn_c_kext); - if (Args.hasArg(OPT_fconcepts_ts)) - Diags.Report(diag::warn_fe_concepts_ts_flag); - if (LangOpts.NewAlignOverride && !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) { Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ); @@ -510,6 +510,10 @@ static bool FixupInvocation(CompilerInvocation &Invocation, Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline" << GetInputKindName(IK); + if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << "-hlsl-entry" << GetInputKindName(IK); + if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP) Diags.Report(diag::warn_ignored_hip_only_option) << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args); @@ -903,14 +907,6 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, #include "clang/Driver/Options.inc" #undef ANALYZER_OPTION_WITH_MARSHALLING - if (Args.hasArg(OPT_analyzer_store)) - Diags.Report(diag::warn_analyzer_deprecated_option) << "-analyzer-store" - << "clang-16"; - if (Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks)) - Diags.Report(diag::warn_analyzer_deprecated_option) - << "-analyzer-opt-analyze-nested-blocks" - << "clang-16"; - if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) { StringRef Name = A->getValue(); AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name) @@ -1024,6 +1020,15 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, A->claim(); Opts.Config[key] = std::string(val); + + // FIXME: Remove this hunk after clang-17 released. + constexpr auto SingleFAM = + "consider-single-element-arrays-as-flexible-array-members"; + if (key == SingleFAM) { + Diags.Report(diag::warn_analyzer_deprecated_option_with_alternative) + << SingleFAM << "clang-17" + << "-fstrict-flex-arrays=<N>"; + } } } @@ -1061,11 +1066,12 @@ static void initOption(AnalyzerOptions::ConfigTable &Config, static void initOption(AnalyzerOptions::ConfigTable &Config, DiagnosticsEngine *Diags, bool &OptionField, StringRef Name, bool DefaultVal) { - auto PossiblyInvalidVal = llvm::StringSwitch<Optional<bool>>( - getStringOption(Config, Name, (DefaultVal ? "true" : "false"))) - .Case("true", true) - .Case("false", false) - .Default(None); + auto PossiblyInvalidVal = + llvm::StringSwitch<std::optional<bool>>( + getStringOption(Config, Name, (DefaultVal ? "true" : "false"))) + .Case("true", true) + .Case("false", false) + .Default(std::nullopt); if (!PossiblyInvalidVal) { if (Diags) @@ -1297,17 +1303,23 @@ static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) { // Set the profile kind using fprofile-instrument-use-path. static void setPGOUseInstrumentor(CodeGenOptions &Opts, - const Twine &ProfileName) { + const Twine &ProfileName, + DiagnosticsEngine &Diags) { auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName); - // In error, return silently and let Clang PGOUse report the error message. if (auto E = ReaderOrErr.takeError()) { - llvm::consumeError(std::move(E)); - Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "Error in reading profile %0: %1"); + llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) { + Diags.Report(DiagID) << ProfileName.str() << EI.message(); + }); return; } std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader = std::move(ReaderOrErr.get()); - if (PGOReader->isIRLevelProfile()) { + // Currently memprof profiles are only added at the IR level. Mark the profile + // type as IR in that case as well and the subsequent matching needs to detect + // which is available (might be one or both). + if (PGOReader->isIRLevelProfile() || PGOReader->hasMemoryProfile()) { if (PGOReader->hasCSIRLevelProfile()) Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr); else @@ -1352,7 +1364,7 @@ void CompilerInvocation::GenerateCodeGenArgs( else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0) GenerateArg(Args, OPT_fno_direct_access_external_data, SA); - Optional<StringRef> DebugInfoVal; + std::optional<StringRef> DebugInfoVal; switch (Opts.DebugInfo) { case codegenoptions::DebugLineTablesOnly: DebugInfoVal = "line-tables-only"; @@ -1373,10 +1385,10 @@ void CompilerInvocation::GenerateCodeGenArgs( DebugInfoVal = "unused-types"; break; case codegenoptions::NoDebugInfo: // default value - DebugInfoVal = None; + DebugInfoVal = std::nullopt; break; case codegenoptions::LocTrackingOnly: // implied value - DebugInfoVal = None; + DebugInfoVal = std::nullopt; break; } if (DebugInfoVal) @@ -1482,9 +1494,6 @@ void CompilerInvocation::GenerateCodeGenArgs( else if (Opts.CFProtectionBranch) GenerateArg(Args, OPT_fcf_protection_EQ, "branch", SA); - if (Opts.IBTSeal) - GenerateArg(Args, OPT_mibt_seal, SA); - if (Opts.FunctionReturnThunks) GenerateArg(Args, OPT_mfunction_return_EQ, "thunk-extern", SA); @@ -1496,13 +1505,8 @@ void CompilerInvocation::GenerateCodeGenArgs( F.Filename, SA); } - // TODO: Consider removing marshalling annotations from f[no_]emulated_tls. - // That would make it easy to generate the option only **once** if it was - // explicitly set to non-default value. - if (Opts.ExplicitEmulatedTLS) { - GenerateArg( - Args, Opts.EmulatedTLS ? OPT_femulated_tls : OPT_fno_emulated_tls, SA); - } + GenerateArg( + Args, Opts.EmulatedTLS ? OPT_femulated_tls : OPT_fno_emulated_tls, SA); if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE()) GenerateArg(Args, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str(), SA); @@ -1713,7 +1717,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, StringRef Value = A->getValue(); if (Value != "simple" && Value != "mangled") Diags.Report(diag::err_drv_unsupported_option_argument) - << A->getOption().getName() << A->getValue(); + << A->getSpelling() << A->getValue(); Opts.setDebugSimpleTemplateNames( StringRef(A->getValue()) == "simple" ? codegenoptions::DebugTemplateNamesKind::Simple @@ -1721,7 +1725,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, } if (!Opts.ProfileInstrumentUsePath.empty()) - setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath); + setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath, Diags); if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ)) { Opts.TimePasses = true; @@ -1849,9 +1853,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.FunctionReturnThunks = static_cast<unsigned>(Val); } - if (Opts.PrepareForLTO && Args.hasArg(OPT_mibt_seal)) - Opts.IBTSeal = 1; - for (auto *A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) { CodeGenOptions::BitcodeFileToLink F; @@ -1866,9 +1867,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.LinkBitcodeFiles.push_back(F); } - if (Args.getLastArg(OPT_femulated_tls) || - Args.getLastArg(OPT_fno_emulated_tls)) { - Opts.ExplicitEmulatedTLS = true; + if (!Args.getLastArg(OPT_femulated_tls) && + !Args.getLastArg(OPT_fno_emulated_tls)) { + Opts.EmulatedTLS = T.hasDefaultEmulatedTLS(); } if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) { @@ -1982,7 +1983,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, } else { Opts.DiagnosticsHotnessThreshold = *ResultOrErr; if ((!Opts.DiagnosticsHotnessThreshold || - Opts.DiagnosticsHotnessThreshold.value() > 0) && + *Opts.DiagnosticsHotnessThreshold > 0) && !UsingProfile) Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) << "-fdiagnostics-hotness-threshold="; @@ -1999,7 +2000,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, } else { Opts.DiagnosticsMisExpectTolerance = *ResultOrErr; if ((!Opts.DiagnosticsMisExpectTolerance || - Opts.DiagnosticsMisExpectTolerance.value() > 0) && + *Opts.DiagnosticsMisExpectTolerance > 0) && !UsingProfile) Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo) << "-fdiagnostics-misexpect-tolerance="; @@ -2146,6 +2147,16 @@ static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts, Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile); } + // Check for invalid combinations of header-include-format + // and header-include-filtering. + if ((Opts.HeaderIncludeFormat == HIFMT_Textual && + Opts.HeaderIncludeFiltering != HIFIL_None) || + (Opts.HeaderIncludeFormat == HIFMT_JSON && + Opts.HeaderIncludeFiltering != HIFIL_Only_Direct_System)) + Diags.Report(diag::err_drv_print_header_env_var_combination_cc1) + << Args.getLastArg(OPT_header_include_format_EQ)->getValue() + << Args.getLastArg(OPT_header_include_filtering_EQ)->getValue(); + return Diags.getNumErrors() == NumErrorsBefore; } @@ -2353,7 +2364,7 @@ clang::CreateAndPopulateDiagOpts(ArrayRef<const char *> Argv) { bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, DiagnosticsEngine *Diags, bool DefaultDiagColor) { - Optional<DiagnosticsEngine> IgnoringDiags; + std::optional<DiagnosticsEngine> IgnoringDiags; if (!Diags) { IgnoringDiags.emplace(new DiagnosticIDs(), new DiagnosticOptions(), new IgnoringDiagConsumer()); @@ -2471,7 +2482,6 @@ static const auto &getFrontendActionTable() { {frontend::GenerateModule, OPT_emit_module}, {frontend::GenerateModuleInterface, OPT_emit_module_interface}, - {frontend::GenerateHeaderModule, OPT_emit_header_module}, {frontend::GenerateHeaderUnit, OPT_emit_header_unit}, {frontend::GeneratePCH, OPT_emit_pch}, {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs}, @@ -2496,22 +2506,23 @@ static const auto &getFrontendActionTable() { } /// Maps command line option to frontend action. -static Optional<frontend::ActionKind> getFrontendAction(OptSpecifier &Opt) { +static std::optional<frontend::ActionKind> +getFrontendAction(OptSpecifier &Opt) { for (const auto &ActionOpt : getFrontendActionTable()) if (ActionOpt.second == Opt.getID()) return ActionOpt.first; - return None; + return std::nullopt; } /// Maps frontend action to command line option. -static Optional<OptSpecifier> +static std::optional<OptSpecifier> getProgramActionOpt(frontend::ActionKind ProgramAction) { for (const auto &ActionOpt : getFrontendActionTable()) if (ActionOpt.first == ProgramAction) return OptSpecifier(ActionOpt.second); - return None; + return std::nullopt; } static void GenerateFrontendArgs(const FrontendOptions &Opts, @@ -2530,7 +2541,7 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, #include "clang/Driver/Options.inc" #undef FRONTEND_OPTION_WITH_MARSHALLING - Optional<OptSpecifier> ProgramActionOpt = + std::optional<OptSpecifier> ProgramActionOpt = getProgramActionOpt(Opts.ProgramAction); // Generating a simple flag covers most frontend actions. @@ -2709,7 +2720,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::ParseSyntaxOnly; if (const Arg *A = Args.getLastArg(OPT_Action_Group)) { OptSpecifier Opt = OptSpecifier(A->getOption().getID()); - Optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt); + std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt); assert(ProgramAction && "Option specifier not in Action_Group."); if (ProgramAction == frontend::ASTDump && @@ -2982,8 +2993,8 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, auto Matches = [](const HeaderSearchOptions::Entry &Entry, llvm::ArrayRef<frontend::IncludeDirGroup> Groups, - llvm::Optional<bool> IsFramework, - llvm::Optional<bool> IgnoreSysRoot) { + std::optional<bool> IsFramework, + std::optional<bool> IgnoreSysRoot) { return llvm::is_contained(Groups, Entry.Group) && (!IsFramework || (Entry.IsFramework == *IsFramework)) && (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot)); @@ -2993,8 +3004,8 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, auto End = Opts.UserEntries.end(); // Add -I..., -F..., and -index-header-map options in order. - for (; It < End && - Matches(*It, {frontend::IndexHeaderMap, frontend::Angled}, None, true); + for (; It < End && Matches(*It, {frontend::IndexHeaderMap, frontend::Angled}, + std::nullopt, true); ++It) { OptSpecifier Opt = [It, Matches]() { if (Matches(*It, frontend::IndexHeaderMap, true, true)) @@ -3032,7 +3043,8 @@ static void GenerateHeaderSearchArgs(HeaderSearchOptions &Opts, GenerateArg(Args, OPT_idirafter, It->Path, SA); for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It) GenerateArg(Args, OPT_iquote, It->Path, SA); - for (; It < End && Matches(*It, {frontend::System}, false, None); ++It) + for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt); + ++It) GenerateArg(Args, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot, It->Path, SA); for (; It < End && Matches(*It, {frontend::System}, true, true); ++It) @@ -3488,9 +3500,6 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, if (Opts.OpenMPCUDAMode) GenerateArg(Args, OPT_fopenmp_cuda_mode, SA); - if (Opts.OpenMPCUDAForceFullRuntime) - GenerateArg(Args, OPT_fopenmp_cuda_force_full_runtime, SA); - // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are // generated from CodeGenOptions. @@ -3526,6 +3535,8 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, 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); if (Opts.getSignReturnAddressScope() == LangOptions::SignReturnAddressScopeKind::All) @@ -3802,7 +3813,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, else Opts.LongDoubleSize = 0; } - if (Opts.FastRelaxedMath) + if (Opts.FastRelaxedMath || Opts.CLUnsafeMath) Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); llvm::sort(Opts.ModuleFeatures); @@ -3940,11 +3951,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && (T.isNVPTX() || T.isAMDGCN()) && Args.hasArg(options::OPT_fopenmp_cuda_mode); - // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options - Opts.OpenMPCUDAForceFullRuntime = - Opts.OpenMPIsDevice && (T.isNVPTX() || T.isAMDGCN()) && - Args.hasArg(options::OPT_fopenmp_cuda_force_full_runtime); - // FIXME: Eliminate this dependency. unsigned Opt = getOptimizationLevel(Args, IK, Diags), OptSize = getOptimizationLevelSize(Args); @@ -4018,6 +4024,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.setClangABICompat(LangOptions::ClangABI::Ver12); else if (Major <= 14) Opts.setClangABICompat(LangOptions::ClangABI::Ver14); + else if (Major <= 15) + Opts.setClangABICompat(LangOptions::ClangABI::Ver15); } else if (Ver != "latest") { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); @@ -4107,6 +4115,14 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ)) Opts.RandstructSeed = A->getValue(0); + // Validate options for HLSL + if (Opts.HLSL) { + bool SupportedTarget = T.getArch() == llvm::Triple::dxil && + T.getOS() == llvm::Triple::ShaderModel; + if (!SupportedTarget) + Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str(); + } + return Diags.getNumErrors() == NumErrorsBefore; } @@ -4127,7 +4143,6 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::FixIt: case frontend::GenerateModule: case frontend::GenerateModuleInterface: - case frontend::GenerateHeaderModule: case frontend::GenerateHeaderUnit: case frontend::GeneratePCH: case frontend::GenerateInterfaceStubs: @@ -4224,6 +4239,9 @@ static void GeneratePreprocessorArgs(PreprocessorOptions &Opts, for (const auto &RF : Opts.RemappedFiles) GenerateArg(Args, OPT_remap_file, RF.first + ";" + RF.second, SA); + if (Opts.SourceDateEpoch) + GenerateArg(Args, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch), SA); + // Don't handle LexEditorPlaceholders. It is implied by the action that is // generated elsewhere. } @@ -4306,6 +4324,22 @@ static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.addRemappedFile(Split.first, Split.second); } + if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) { + StringRef Epoch = A->getValue(); + // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer. + // On time64 systems, pick 253402300799 (the UNIX timestamp of + // 9999-12-31T23:59:59Z) as the upper bound. + const uint64_t MaxTimestamp = + std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799); + uint64_t V; + if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) { + Diags.Report(diag::err_fe_invalid_source_date_epoch) + << Epoch << MaxTimestamp; + } else { + Opts.SourceDateEpoch = V; + } + } + // Always avoid lexing editor placeholders when we're just running the // preprocessor as we never want to emit the // "editor placeholder in source file" error in PP only mode. @@ -4524,8 +4558,10 @@ bool CompilerInvocation::CreateFromArgsImpl( } // Store the command-line for using in the CodeView backend. - Res.getCodeGenOpts().Argv0 = Argv0; - append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs); + if (Res.getCodeGenOpts().CodeViewCommandLine) { + Res.getCodeGenOpts().Argv0 = Argv0; + append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs); + } FixupInvocation(Res, Diags, Args, DashX); @@ -4544,7 +4580,10 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation, return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0); }, [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args, - StringAllocator SA) { Invocation.generateCC1CommandLine(Args, SA); }, + StringAllocator SA) { + Args.push_back("-cc1"); + Invocation.generateCC1CommandLine(Args, SA); + }, Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0); } @@ -4665,6 +4704,37 @@ void CompilerInvocation::generateCC1CommandLine( GenerateDependencyOutputArgs(DependencyOutputOpts, Args, SA); } +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()}; +} + +void CompilerInvocation::resetNonModularOptions() { + getLangOpts()->resetNonModularOptions(); + getPreprocessorOpts().resetNonModularOptions(); +} + +void CompilerInvocation::clearImplicitModuleBuildOptions() { + getLangOpts()->ImplicitModules = false; + getHeaderSearchOpts().ImplicitModuleMaps = false; + getHeaderSearchOpts().ModuleCachePath.clear(); + getHeaderSearchOpts().ModulesValidateOncePerBuildSession = false; + getHeaderSearchOpts().BuildSessionTimestamp = 0; + // The specific values we canonicalize to for pruning don't affect behaviour, + /// so use the default values so they may be dropped from the command-line. + getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60; + getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60; +} + IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags) { @@ -4676,12 +4746,19 @@ IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromCompilerInvocation( const CompilerInvocation &CI, DiagnosticsEngine &Diags, IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { - if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) + return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles, + Diags, std::move(BaseFS)); +} + +IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles( + ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { + if (VFSOverlayFiles.empty()) return BaseFS; IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS; // earlier vfs files are on the bottom - for (const auto &File : CI.getHeaderSearchOpts().VFSOverlayFiles) { + for (const auto &File : VFSOverlayFiles) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = Result->getBufferForFile(File); if (!Buffer) { |