Path: blob/main/contrib/llvm-project/clang/lib/Frontend/CompilerInvocation.cpp
35232 views
//===- CompilerInvocation.cpp ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Frontend/CompilerInvocation.h"9#include "TestModuleFileExtension.h"10#include "clang/Basic/Builtins.h"11#include "clang/Basic/CharInfo.h"12#include "clang/Basic/CodeGenOptions.h"13#include "clang/Basic/CommentOptions.h"14#include "clang/Basic/Diagnostic.h"15#include "clang/Basic/DiagnosticDriver.h"16#include "clang/Basic/DiagnosticOptions.h"17#include "clang/Basic/FileSystemOptions.h"18#include "clang/Basic/LLVM.h"19#include "clang/Basic/LangOptions.h"20#include "clang/Basic/LangStandard.h"21#include "clang/Basic/ObjCRuntime.h"22#include "clang/Basic/Sanitizers.h"23#include "clang/Basic/SourceLocation.h"24#include "clang/Basic/TargetOptions.h"25#include "clang/Basic/Version.h"26#include "clang/Basic/Visibility.h"27#include "clang/Basic/XRayInstr.h"28#include "clang/Config/config.h"29#include "clang/Driver/Driver.h"30#include "clang/Driver/DriverDiagnostic.h"31#include "clang/Driver/Options.h"32#include "clang/Frontend/CommandLineSourceLoc.h"33#include "clang/Frontend/DependencyOutputOptions.h"34#include "clang/Frontend/FrontendDiagnostic.h"35#include "clang/Frontend/FrontendOptions.h"36#include "clang/Frontend/FrontendPluginRegistry.h"37#include "clang/Frontend/MigratorOptions.h"38#include "clang/Frontend/PreprocessorOutputOptions.h"39#include "clang/Frontend/TextDiagnosticBuffer.h"40#include "clang/Frontend/Utils.h"41#include "clang/Lex/HeaderSearchOptions.h"42#include "clang/Lex/PreprocessorOptions.h"43#include "clang/Sema/CodeCompleteOptions.h"44#include "clang/Serialization/ASTBitCodes.h"45#include "clang/Serialization/ModuleFileExtension.h"46#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"47#include "llvm/ADT/APInt.h"48#include "llvm/ADT/ArrayRef.h"49#include "llvm/ADT/CachedHashString.h"50#include "llvm/ADT/FloatingPointMode.h"51#include "llvm/ADT/Hashing.h"52#include "llvm/ADT/STLExtras.h"53#include "llvm/ADT/SmallString.h"54#include "llvm/ADT/SmallVector.h"55#include "llvm/ADT/StringRef.h"56#include "llvm/ADT/StringSwitch.h"57#include "llvm/ADT/Twine.h"58#include "llvm/Config/llvm-config.h"59#include "llvm/Frontend/Debug/Options.h"60#include "llvm/IR/DebugInfoMetadata.h"61#include "llvm/Linker/Linker.h"62#include "llvm/MC/MCTargetOptions.h"63#include "llvm/Option/Arg.h"64#include "llvm/Option/ArgList.h"65#include "llvm/Option/OptSpecifier.h"66#include "llvm/Option/OptTable.h"67#include "llvm/Option/Option.h"68#include "llvm/ProfileData/InstrProfReader.h"69#include "llvm/Remarks/HotnessThresholdParser.h"70#include "llvm/Support/CodeGen.h"71#include "llvm/Support/Compiler.h"72#include "llvm/Support/Error.h"73#include "llvm/Support/ErrorHandling.h"74#include "llvm/Support/ErrorOr.h"75#include "llvm/Support/FileSystem.h"76#include "llvm/Support/HashBuilder.h"77#include "llvm/Support/MathExtras.h"78#include "llvm/Support/MemoryBuffer.h"79#include "llvm/Support/Path.h"80#include "llvm/Support/Process.h"81#include "llvm/Support/Regex.h"82#include "llvm/Support/VersionTuple.h"83#include "llvm/Support/VirtualFileSystem.h"84#include "llvm/Support/raw_ostream.h"85#include "llvm/Target/TargetOptions.h"86#include "llvm/TargetParser/Host.h"87#include "llvm/TargetParser/Triple.h"88#include <algorithm>89#include <atomic>90#include <cassert>91#include <cstddef>92#include <cstring>93#include <ctime>94#include <fstream>95#include <limits>96#include <memory>97#include <optional>98#include <string>99#include <tuple>100#include <type_traits>101#include <utility>102#include <vector>103104using namespace clang;105using namespace driver;106using namespace options;107using namespace llvm::opt;108109//===----------------------------------------------------------------------===//110// Helpers.111//===----------------------------------------------------------------------===//112113// Parse misexpect tolerance argument value.114// Valid option values are integers in the range [0, 100)115static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) {116uint32_t Val;117if (Arg.getAsInteger(10, Val))118return llvm::createStringError(llvm::inconvertibleErrorCode(),119"Not an integer: %s", Arg.data());120return Val;121}122123//===----------------------------------------------------------------------===//124// Initialization.125//===----------------------------------------------------------------------===//126127namespace {128template <class T> std::shared_ptr<T> make_shared_copy(const T &X) {129return std::make_shared<T>(X);130}131132template <class T>133llvm::IntrusiveRefCntPtr<T> makeIntrusiveRefCntCopy(const T &X) {134return llvm::makeIntrusiveRefCnt<T>(X);135}136} // namespace137138CompilerInvocationBase::CompilerInvocationBase()139: LangOpts(std::make_shared<LangOptions>()),140TargetOpts(std::make_shared<TargetOptions>()),141DiagnosticOpts(llvm::makeIntrusiveRefCnt<DiagnosticOptions>()),142HSOpts(std::make_shared<HeaderSearchOptions>()),143PPOpts(std::make_shared<PreprocessorOptions>()),144AnalyzerOpts(llvm::makeIntrusiveRefCnt<AnalyzerOptions>()),145MigratorOpts(std::make_shared<MigratorOptions>()),146APINotesOpts(std::make_shared<APINotesOptions>()),147CodeGenOpts(std::make_shared<CodeGenOptions>()),148FSOpts(std::make_shared<FileSystemOptions>()),149FrontendOpts(std::make_shared<FrontendOptions>()),150DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()),151PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {}152153CompilerInvocationBase &154CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) {155if (this != &X) {156LangOpts = make_shared_copy(X.getLangOpts());157TargetOpts = make_shared_copy(X.getTargetOpts());158DiagnosticOpts = makeIntrusiveRefCntCopy(X.getDiagnosticOpts());159HSOpts = make_shared_copy(X.getHeaderSearchOpts());160PPOpts = make_shared_copy(X.getPreprocessorOpts());161AnalyzerOpts = makeIntrusiveRefCntCopy(X.getAnalyzerOpts());162MigratorOpts = make_shared_copy(X.getMigratorOpts());163APINotesOpts = make_shared_copy(X.getAPINotesOpts());164CodeGenOpts = make_shared_copy(X.getCodeGenOpts());165FSOpts = make_shared_copy(X.getFileSystemOpts());166FrontendOpts = make_shared_copy(X.getFrontendOpts());167DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts());168PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts());169}170return *this;171}172173CompilerInvocationBase &174CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) {175if (this != &X) {176LangOpts = X.LangOpts;177TargetOpts = X.TargetOpts;178DiagnosticOpts = X.DiagnosticOpts;179HSOpts = X.HSOpts;180PPOpts = X.PPOpts;181AnalyzerOpts = X.AnalyzerOpts;182MigratorOpts = X.MigratorOpts;183APINotesOpts = X.APINotesOpts;184CodeGenOpts = X.CodeGenOpts;185FSOpts = X.FSOpts;186FrontendOpts = X.FrontendOpts;187DependencyOutputOpts = X.DependencyOutputOpts;188PreprocessorOutputOpts = X.PreprocessorOutputOpts;189}190return *this;191}192193CompilerInvocation::CompilerInvocation(const CowCompilerInvocation &X)194: CompilerInvocationBase(EmptyConstructor{}) {195CompilerInvocationBase::deep_copy_assign(X);196}197198CompilerInvocation &199CompilerInvocation::operator=(const CowCompilerInvocation &X) {200CompilerInvocationBase::deep_copy_assign(X);201return *this;202}203204namespace {205template <typename T>206T &ensureOwned(std::shared_ptr<T> &Storage) {207if (Storage.use_count() > 1)208Storage = std::make_shared<T>(*Storage);209return *Storage;210}211212template <typename T>213T &ensureOwned(llvm::IntrusiveRefCntPtr<T> &Storage) {214if (Storage.useCount() > 1)215Storage = llvm::makeIntrusiveRefCnt<T>(*Storage);216return *Storage;217}218} // namespace219220LangOptions &CowCompilerInvocation::getMutLangOpts() {221return ensureOwned(LangOpts);222}223224TargetOptions &CowCompilerInvocation::getMutTargetOpts() {225return ensureOwned(TargetOpts);226}227228DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() {229return ensureOwned(DiagnosticOpts);230}231232HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() {233return ensureOwned(HSOpts);234}235236PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() {237return ensureOwned(PPOpts);238}239240AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() {241return ensureOwned(AnalyzerOpts);242}243244MigratorOptions &CowCompilerInvocation::getMutMigratorOpts() {245return ensureOwned(MigratorOpts);246}247248APINotesOptions &CowCompilerInvocation::getMutAPINotesOpts() {249return ensureOwned(APINotesOpts);250}251252CodeGenOptions &CowCompilerInvocation::getMutCodeGenOpts() {253return ensureOwned(CodeGenOpts);254}255256FileSystemOptions &CowCompilerInvocation::getMutFileSystemOpts() {257return ensureOwned(FSOpts);258}259260FrontendOptions &CowCompilerInvocation::getMutFrontendOpts() {261return ensureOwned(FrontendOpts);262}263264DependencyOutputOptions &CowCompilerInvocation::getMutDependencyOutputOpts() {265return ensureOwned(DependencyOutputOpts);266}267268PreprocessorOutputOptions &269CowCompilerInvocation::getMutPreprocessorOutputOpts() {270return ensureOwned(PreprocessorOutputOpts);271}272273//===----------------------------------------------------------------------===//274// Normalizers275//===----------------------------------------------------------------------===//276277using ArgumentConsumer = CompilerInvocation::ArgumentConsumer;278279#define SIMPLE_ENUM_VALUE_TABLE280#include "clang/Driver/Options.inc"281#undef SIMPLE_ENUM_VALUE_TABLE282283static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt,284unsigned TableIndex,285const ArgList &Args,286DiagnosticsEngine &Diags) {287if (Args.hasArg(Opt))288return true;289return std::nullopt;290}291292static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt,293unsigned,294const ArgList &Args,295DiagnosticsEngine &) {296if (Args.hasArg(Opt))297return false;298return std::nullopt;299}300301/// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but302/// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with303/// unnecessary template instantiations and just ignore it with a variadic304/// argument.305static void denormalizeSimpleFlag(ArgumentConsumer Consumer,306const Twine &Spelling, Option::OptionClass,307unsigned, /*T*/...) {308Consumer(Spelling);309}310311template <typename T> static constexpr bool is_uint64_t_convertible() {312return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value;313}314315template <typename T,316std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>317static auto makeFlagToValueNormalizer(T Value) {318return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,319DiagnosticsEngine &) -> std::optional<T> {320if (Args.hasArg(Opt))321return Value;322return std::nullopt;323};324}325326template <typename T,327std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false>328static auto makeFlagToValueNormalizer(T Value) {329return makeFlagToValueNormalizer(uint64_t(Value));330}331332static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,333OptSpecifier OtherOpt) {334return [Value, OtherValue,335OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args,336DiagnosticsEngine &) -> std::optional<bool> {337if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {338return A->getOption().matches(Opt) ? Value : OtherValue;339}340return std::nullopt;341};342}343344static auto makeBooleanOptionDenormalizer(bool Value) {345return [Value](ArgumentConsumer Consumer, const Twine &Spelling,346Option::OptionClass, unsigned, bool KeyPath) {347if (KeyPath == Value)348Consumer(Spelling);349};350}351352static void denormalizeStringImpl(ArgumentConsumer Consumer,353const Twine &Spelling,354Option::OptionClass OptClass, unsigned,355const Twine &Value) {356switch (OptClass) {357case Option::SeparateClass:358case Option::JoinedOrSeparateClass:359case Option::JoinedAndSeparateClass:360Consumer(Spelling);361Consumer(Value);362break;363case Option::JoinedClass:364case Option::CommaJoinedClass:365Consumer(Spelling + Value);366break;367default:368llvm_unreachable("Cannot denormalize an option with option class "369"incompatible with string denormalization.");370}371}372373template <typename T>374static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling,375Option::OptionClass OptClass, unsigned TableIndex,376T Value) {377denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value));378}379380static std::optional<SimpleEnumValue>381findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {382for (int I = 0, E = Table.Size; I != E; ++I)383if (Name == Table.Table[I].Name)384return Table.Table[I];385386return std::nullopt;387}388389static std::optional<SimpleEnumValue>390findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) {391for (int I = 0, E = Table.Size; I != E; ++I)392if (Value == Table.Table[I].Value)393return Table.Table[I];394395return std::nullopt;396}397398static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,399unsigned TableIndex,400const ArgList &Args,401DiagnosticsEngine &Diags) {402assert(TableIndex < SimpleEnumValueTablesSize);403const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];404405auto *Arg = Args.getLastArg(Opt);406if (!Arg)407return std::nullopt;408409StringRef ArgValue = Arg->getValue();410if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))411return MaybeEnumVal->Value;412413Diags.Report(diag::err_drv_invalid_value)414<< Arg->getAsString(Args) << ArgValue;415return std::nullopt;416}417418static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer,419const Twine &Spelling,420Option::OptionClass OptClass,421unsigned TableIndex, unsigned Value) {422assert(TableIndex < SimpleEnumValueTablesSize);423const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];424if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {425denormalizeString(Consumer, Spelling, OptClass, TableIndex,426MaybeEnumVal->Name);427} else {428llvm_unreachable("The simple enum value was not correctly defined in "429"the tablegen option description");430}431}432433template <typename T>434static void denormalizeSimpleEnum(ArgumentConsumer Consumer,435const Twine &Spelling,436Option::OptionClass OptClass,437unsigned TableIndex, T Value) {438return denormalizeSimpleEnumImpl(Consumer, Spelling, OptClass, TableIndex,439static_cast<unsigned>(Value));440}441442static std::optional<std::string> normalizeString(OptSpecifier Opt,443int TableIndex,444const ArgList &Args,445DiagnosticsEngine &Diags) {446auto *Arg = Args.getLastArg(Opt);447if (!Arg)448return std::nullopt;449return std::string(Arg->getValue());450}451452template <typename IntTy>453static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,454const ArgList &Args,455DiagnosticsEngine &Diags) {456auto *Arg = Args.getLastArg(Opt);457if (!Arg)458return std::nullopt;459IntTy Res;460if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {461Diags.Report(diag::err_drv_invalid_int_value)462<< Arg->getAsString(Args) << Arg->getValue();463return std::nullopt;464}465return Res;466}467468static std::optional<std::vector<std::string>>469normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,470DiagnosticsEngine &) {471return Args.getAllArgValues(Opt);472}473474static void denormalizeStringVector(ArgumentConsumer Consumer,475const Twine &Spelling,476Option::OptionClass OptClass,477unsigned TableIndex,478const std::vector<std::string> &Values) {479switch (OptClass) {480case Option::CommaJoinedClass: {481std::string CommaJoinedValue;482if (!Values.empty()) {483CommaJoinedValue.append(Values.front());484for (const std::string &Value : llvm::drop_begin(Values, 1)) {485CommaJoinedValue.append(",");486CommaJoinedValue.append(Value);487}488}489denormalizeString(Consumer, Spelling, Option::OptionClass::JoinedClass,490TableIndex, CommaJoinedValue);491break;492}493case Option::JoinedClass:494case Option::SeparateClass:495case Option::JoinedOrSeparateClass:496for (const std::string &Value : Values)497denormalizeString(Consumer, Spelling, OptClass, TableIndex, Value);498break;499default:500llvm_unreachable("Cannot denormalize an option with option class "501"incompatible with string vector denormalization.");502}503}504505static std::optional<std::string> normalizeTriple(OptSpecifier Opt,506int TableIndex,507const ArgList &Args,508DiagnosticsEngine &Diags) {509auto *Arg = Args.getLastArg(Opt);510if (!Arg)511return std::nullopt;512return llvm::Triple::normalize(Arg->getValue());513}514515template <typename T, typename U>516static T mergeForwardValue(T KeyPath, U Value) {517return static_cast<T>(Value);518}519520template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {521return KeyPath | Value;522}523524template <typename T> static T extractForwardValue(T KeyPath) {525return KeyPath;526}527528template <typename T, typename U, U Value>529static T extractMaskValue(T KeyPath) {530return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T();531}532533#define PARSE_OPTION_WITH_MARSHALLING( \534ARGS, DIAGS, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, \535FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \536SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \537IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \538if ((VISIBILITY) & options::CC1Option) { \539KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE); \540if (IMPLIED_CHECK) \541KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE); \542if (SHOULD_PARSE) \543if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS)) \544KEYPATH = \545MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue)); \546}547548// Capture the extracted value as a lambda argument to avoid potential issues549// with lifetime extension of the reference.550#define GENERATE_OPTION_WITH_MARSHALLING( \551CONSUMER, PREFIX_TYPE, SPELLING, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \552VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \553SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, IMPLIED_CHECK, \554IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \555if ((VISIBILITY) & options::CC1Option) { \556[&](const auto &Extracted) { \557if (ALWAYS_EMIT || \558(Extracted != \559static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE) \560: (DEFAULT_VALUE)))) \561DENORMALIZER(CONSUMER, SPELLING, Option::KIND##Class, TABLE_INDEX, \562Extracted); \563}(EXTRACTOR(KEYPATH)); \564}565566static StringRef GetInputKindName(InputKind IK);567568static bool FixupInvocation(CompilerInvocation &Invocation,569DiagnosticsEngine &Diags, const ArgList &Args,570InputKind IK) {571unsigned NumErrorsBefore = Diags.getNumErrors();572573LangOptions &LangOpts = Invocation.getLangOpts();574CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();575TargetOptions &TargetOpts = Invocation.getTargetOpts();576FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();577CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument;578CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents;579CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;580CodeGenOpts.DisableFree = FrontendOpts.DisableFree;581FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;582if (FrontendOpts.ShowStats)583CodeGenOpts.ClearASTBeforeBackend = false;584LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();585LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;586LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;587LangOpts.CurrentModule = LangOpts.ModuleName;588589llvm::Triple T(TargetOpts.Triple);590llvm::Triple::ArchType Arch = T.getArch();591592CodeGenOpts.CodeModel = TargetOpts.CodeModel;593CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold;594595if (LangOpts.getExceptionHandling() !=596LangOptions::ExceptionHandlingKind::None &&597T.isWindowsMSVCEnvironment())598Diags.Report(diag::err_fe_invalid_exception_model)599<< static_cast<unsigned>(LangOpts.getExceptionHandling()) << T.str();600601if (LangOpts.AppleKext && !LangOpts.CPlusPlus)602Diags.Report(diag::warn_c_kext);603604if (LangOpts.NewAlignOverride &&605!llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {606Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);607Diags.Report(diag::err_fe_invalid_alignment)608<< A->getAsString(Args) << A->getValue();609LangOpts.NewAlignOverride = 0;610}611612// The -f[no-]raw-string-literals option is only valid in C and in C++613// standards before C++11.614if (LangOpts.CPlusPlus11) {615if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) {616Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals);617Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11)618<< bool(LangOpts.RawStringLiterals);619}620621// Do not allow disabling raw string literals in C++11 or later.622LangOpts.RawStringLiterals = true;623}624625// Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.626if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)627Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"628<< "-fsycl-is-host";629630if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)631Diags.Report(diag::err_drv_argument_not_allowed_with)632<< "-fgnu89-inline" << GetInputKindName(IK);633634if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL)635Diags.Report(diag::err_drv_argument_not_allowed_with)636<< "-hlsl-entry" << GetInputKindName(IK);637638if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)639Diags.Report(diag::warn_ignored_hip_only_option)640<< Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);641642if (Args.hasArg(OPT_gpu_max_threads_per_block_EQ) && !LangOpts.HIP)643Diags.Report(diag::warn_ignored_hip_only_option)644<< Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args);645646// When these options are used, the compiler is allowed to apply647// optimizations that may affect the final result. For example648// (x+y)+z is transformed to x+(y+z) but may not give the same649// final result; it's not value safe.650// Another example can be to simplify x/x to 1.0 but x could be 0.0, INF651// or NaN. Final result may then differ. An error is issued when the eval652// method is set with one of these options.653if (Args.hasArg(OPT_ffp_eval_method_EQ)) {654if (LangOpts.ApproxFunc)655Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0;656if (LangOpts.AllowFPReassoc)657Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1;658if (LangOpts.AllowRecip)659Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2;660}661662// -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.663// This option should be deprecated for CL > 1.0 because664// this option was added for compatibility with OpenCL 1.0.665if (Args.getLastArg(OPT_cl_strict_aliasing) &&666(LangOpts.getOpenCLCompatibleVersion() > 100))667Diags.Report(diag::warn_option_invalid_ocl_version)668<< LangOpts.getOpenCLVersionString()669<< Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);670671if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {672auto DefaultCC = LangOpts.getDefaultCallingConv();673674bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||675DefaultCC == LangOptions::DCC_StdCall) &&676Arch != llvm::Triple::x86;677emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||678DefaultCC == LangOptions::DCC_RegCall) &&679!T.isX86();680emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k;681if (emitError)682Diags.Report(diag::err_drv_argument_not_allowed_with)683<< A->getSpelling() << T.getTriple();684}685686return Diags.getNumErrors() == NumErrorsBefore;687}688689//===----------------------------------------------------------------------===//690// Deserialization (from args)691//===----------------------------------------------------------------------===//692693static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,694DiagnosticsEngine &Diags) {695unsigned DefaultOpt = 0;696if ((IK.getLanguage() == Language::OpenCL ||697IK.getLanguage() == Language::OpenCLCXX) &&698!Args.hasArg(OPT_cl_opt_disable))699DefaultOpt = 2;700701if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {702if (A->getOption().matches(options::OPT_O0))703return 0;704705if (A->getOption().matches(options::OPT_Ofast))706return 3;707708assert(A->getOption().matches(options::OPT_O));709710StringRef S(A->getValue());711if (S == "s" || S == "z")712return 2;713714if (S == "g")715return 1;716717return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);718}719720return DefaultOpt;721}722723static unsigned getOptimizationLevelSize(ArgList &Args) {724if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {725if (A->getOption().matches(options::OPT_O)) {726switch (A->getValue()[0]) {727default:728return 0;729case 's':730return 1;731case 'z':732return 2;733}734}735}736return 0;737}738739static void GenerateArg(ArgumentConsumer Consumer,740llvm::opt::OptSpecifier OptSpecifier) {741Option Opt = getDriverOptTable().getOption(OptSpecifier);742denormalizeSimpleFlag(Consumer, Opt.getPrefixedName(),743Option::OptionClass::FlagClass, 0);744}745746static void GenerateArg(ArgumentConsumer Consumer,747llvm::opt::OptSpecifier OptSpecifier,748const Twine &Value) {749Option Opt = getDriverOptTable().getOption(OptSpecifier);750denormalizeString(Consumer, Opt.getPrefixedName(), Opt.getKind(), 0, Value);751}752753// Parse command line arguments into CompilerInvocation.754using ParseFn =755llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>,756DiagnosticsEngine &, const char *)>;757758// Generate command line arguments from CompilerInvocation.759using GenerateFn = llvm::function_ref<void(760CompilerInvocation &, SmallVectorImpl<const char *> &,761CompilerInvocation::StringAllocator)>;762763/// May perform round-trip of command line arguments. By default, the round-trip764/// is enabled in assert builds. This can be overwritten at run-time via the765/// "-round-trip-args" and "-no-round-trip-args" command line flags, or via the766/// ForceRoundTrip parameter.767///768/// During round-trip, the command line arguments are parsed into a dummy769/// CompilerInvocation, which is used to generate the command line arguments770/// again. The real CompilerInvocation is then created by parsing the generated771/// arguments, not the original ones. This (in combination with tests covering772/// argument behavior) ensures the generated command line is complete (doesn't773/// drop/mangle any arguments).774///775/// Finally, we check the command line that was used to create the real776/// CompilerInvocation instance. By default, we compare it to the command line777/// the real CompilerInvocation generates. This checks whether the generator is778/// deterministic. If \p CheckAgainstOriginalInvocation is enabled, we instead779/// compare it to the original command line to verify the original command-line780/// was canonical and can round-trip exactly.781static bool RoundTrip(ParseFn Parse, GenerateFn Generate,782CompilerInvocation &RealInvocation,783CompilerInvocation &DummyInvocation,784ArrayRef<const char *> CommandLineArgs,785DiagnosticsEngine &Diags, const char *Argv0,786bool CheckAgainstOriginalInvocation = false,787bool ForceRoundTrip = false) {788#ifndef NDEBUG789bool DoRoundTripDefault = true;790#else791bool DoRoundTripDefault = false;792#endif793794bool DoRoundTrip = DoRoundTripDefault;795if (ForceRoundTrip) {796DoRoundTrip = true;797} else {798for (const auto *Arg : CommandLineArgs) {799if (Arg == StringRef("-round-trip-args"))800DoRoundTrip = true;801if (Arg == StringRef("-no-round-trip-args"))802DoRoundTrip = false;803}804}805806// If round-trip was not requested, simply run the parser with the real807// invocation diagnostics.808if (!DoRoundTrip)809return Parse(RealInvocation, CommandLineArgs, Diags, Argv0);810811// Serializes quoted (and potentially escaped) arguments.812auto SerializeArgs = [](ArrayRef<const char *> Args) {813std::string Buffer;814llvm::raw_string_ostream OS(Buffer);815for (const char *Arg : Args) {816llvm::sys::printArg(OS, Arg, /*Quote=*/true);817OS << ' ';818}819OS.flush();820return Buffer;821};822823// Setup a dummy DiagnosticsEngine.824DiagnosticsEngine DummyDiags(new DiagnosticIDs(), new DiagnosticOptions());825DummyDiags.setClient(new TextDiagnosticBuffer());826827// Run the first parse on the original arguments with the dummy invocation and828// diagnostics.829if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) ||830DummyDiags.getNumWarnings() != 0) {831// If the first parse did not succeed, it must be user mistake (invalid832// command line arguments). We won't be able to generate arguments that833// would reproduce the same result. Let's fail again with the real834// invocation and diagnostics, so all side-effects of parsing are visible.835unsigned NumWarningsBefore = Diags.getNumWarnings();836auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0);837if (!Success || Diags.getNumWarnings() != NumWarningsBefore)838return Success;839840// Parse with original options and diagnostics succeeded even though it841// shouldn't have. Something is off.842Diags.Report(diag::err_cc1_round_trip_fail_then_ok);843Diags.Report(diag::note_cc1_round_trip_original)844<< SerializeArgs(CommandLineArgs);845return false;846}847848// Setup string allocator.849llvm::BumpPtrAllocator Alloc;850llvm::StringSaver StringPool(Alloc);851auto SA = [&StringPool](const Twine &Arg) {852return StringPool.save(Arg).data();853};854855// Generate arguments from the dummy invocation. If Generate is the856// inverse of Parse, the newly generated arguments must have the same857// semantics as the original.858SmallVector<const char *> GeneratedArgs;859Generate(DummyInvocation, GeneratedArgs, SA);860861// Run the second parse, now on the generated arguments, and with the real862// invocation and diagnostics. The result is what we will end up using for the863// rest of compilation, so if Generate is not inverse of Parse, something down864// the line will break.865bool Success2 = Parse(RealInvocation, GeneratedArgs, Diags, Argv0);866867// The first parse on original arguments succeeded, but second parse of868// generated arguments failed. Something must be wrong with the generator.869if (!Success2) {870Diags.Report(diag::err_cc1_round_trip_ok_then_fail);871Diags.Report(diag::note_cc1_round_trip_generated)872<< 1 << SerializeArgs(GeneratedArgs);873return false;874}875876SmallVector<const char *> ComparisonArgs;877if (CheckAgainstOriginalInvocation)878// Compare against original arguments.879ComparisonArgs.assign(CommandLineArgs.begin(), CommandLineArgs.end());880else881// Generate arguments again, this time from the options we will end up using882// for the rest of the compilation.883Generate(RealInvocation, ComparisonArgs, SA);884885// Compares two lists of arguments.886auto Equal = [](const ArrayRef<const char *> A,887const ArrayRef<const char *> B) {888return std::equal(A.begin(), A.end(), B.begin(), B.end(),889[](const char *AElem, const char *BElem) {890return StringRef(AElem) == StringRef(BElem);891});892};893894// If we generated different arguments from what we assume are two895// semantically equivalent CompilerInvocations, the Generate function may896// be non-deterministic.897if (!Equal(GeneratedArgs, ComparisonArgs)) {898Diags.Report(diag::err_cc1_round_trip_mismatch);899Diags.Report(diag::note_cc1_round_trip_generated)900<< 1 << SerializeArgs(GeneratedArgs);901Diags.Report(diag::note_cc1_round_trip_generated)902<< 2 << SerializeArgs(ComparisonArgs);903return false;904}905906Diags.Report(diag::remark_cc1_round_trip_generated)907<< 1 << SerializeArgs(GeneratedArgs);908Diags.Report(diag::remark_cc1_round_trip_generated)909<< 2 << SerializeArgs(ComparisonArgs);910911return Success2;912}913914bool CompilerInvocation::checkCC1RoundTrip(ArrayRef<const char *> Args,915DiagnosticsEngine &Diags,916const char *Argv0) {917CompilerInvocation DummyInvocation1, DummyInvocation2;918return RoundTrip(919[](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,920DiagnosticsEngine &Diags, const char *Argv0) {921return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);922},923[](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,924StringAllocator SA) {925Args.push_back("-cc1");926Invocation.generateCC1CommandLine(Args, SA);927},928DummyInvocation1, DummyInvocation2, Args, Diags, Argv0,929/*CheckAgainstOriginalInvocation=*/true, /*ForceRoundTrip=*/true);930}931932static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,933OptSpecifier GroupWithValue,934std::vector<std::string> &Diagnostics) {935for (auto *A : Args.filtered(Group)) {936if (A->getOption().getKind() == Option::FlagClass) {937// The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add938// its name (minus the "W" or "R" at the beginning) to the diagnostics.939Diagnostics.push_back(940std::string(A->getOption().getName().drop_front(1)));941} else if (A->getOption().matches(GroupWithValue)) {942// This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic943// group. Add only the group name to the diagnostics.944Diagnostics.push_back(945std::string(A->getOption().getName().drop_front(1).rtrim("=-")));946} else {947// Otherwise, add its value (for OPT_W_Joined and similar).948Diagnostics.push_back(A->getValue());949}950}951}952953// Parse the Static Analyzer configuration. If \p Diags is set to nullptr,954// it won't verify the input.955static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,956DiagnosticsEngine *Diags);957958static void getAllNoBuiltinFuncValues(ArgList &Args,959std::vector<std::string> &Funcs) {960std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);961auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc);962Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);963}964965static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts,966ArgumentConsumer Consumer) {967const AnalyzerOptions *AnalyzerOpts = &Opts;968969#define ANALYZER_OPTION_WITH_MARSHALLING(...) \970GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)971#include "clang/Driver/Options.inc"972#undef ANALYZER_OPTION_WITH_MARSHALLING973974if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {975switch (Opts.AnalysisConstraintsOpt) {976#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \977case NAME##Model: \978GenerateArg(Consumer, OPT_analyzer_constraints, CMDFLAG); \979break;980#include "clang/StaticAnalyzer/Core/Analyses.def"981default:982llvm_unreachable("Tried to generate unknown analysis constraint.");983}984}985986if (Opts.AnalysisDiagOpt != PD_HTML) {987switch (Opts.AnalysisDiagOpt) {988#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \989case PD_##NAME: \990GenerateArg(Consumer, OPT_analyzer_output, CMDFLAG); \991break;992#include "clang/StaticAnalyzer/Core/Analyses.def"993default:994llvm_unreachable("Tried to generate unknown analysis diagnostic client.");995}996}997998if (Opts.AnalysisPurgeOpt != PurgeStmt) {999switch (Opts.AnalysisPurgeOpt) {1000#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \1001case NAME: \1002GenerateArg(Consumer, OPT_analyzer_purge, CMDFLAG); \1003break;1004#include "clang/StaticAnalyzer/Core/Analyses.def"1005default:1006llvm_unreachable("Tried to generate unknown analysis purge mode.");1007}1008}10091010if (Opts.InliningMode != NoRedundancy) {1011switch (Opts.InliningMode) {1012#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \1013case NAME: \1014GenerateArg(Consumer, OPT_analyzer_inlining_mode, CMDFLAG); \1015break;1016#include "clang/StaticAnalyzer/Core/Analyses.def"1017default:1018llvm_unreachable("Tried to generate unknown analysis inlining mode.");1019}1020}10211022for (const auto &CP : Opts.CheckersAndPackages) {1023OptSpecifier Opt =1024CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;1025GenerateArg(Consumer, Opt, CP.first);1026}10271028AnalyzerOptions ConfigOpts;1029parseAnalyzerConfigs(ConfigOpts, nullptr);10301031// Sort options by key to avoid relying on StringMap iteration order.1032SmallVector<std::pair<StringRef, StringRef>, 4> SortedConfigOpts;1033for (const auto &C : Opts.Config)1034SortedConfigOpts.emplace_back(C.getKey(), C.getValue());1035llvm::sort(SortedConfigOpts, llvm::less_first());10361037for (const auto &[Key, Value] : SortedConfigOpts) {1038// Don't generate anything that came from parseAnalyzerConfigs. It would be1039// redundant and may not be valid on the command line.1040auto Entry = ConfigOpts.Config.find(Key);1041if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value)1042continue;10431044GenerateArg(Consumer, OPT_analyzer_config, Key + "=" + Value);1045}10461047// Nothing to generate for FullCompilerInvocation.1048}10491050static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,1051DiagnosticsEngine &Diags) {1052unsigned NumErrorsBefore = Diags.getNumErrors();10531054AnalyzerOptions *AnalyzerOpts = &Opts;10551056#define ANALYZER_OPTION_WITH_MARSHALLING(...) \1057PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)1058#include "clang/Driver/Options.inc"1059#undef ANALYZER_OPTION_WITH_MARSHALLING10601061if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {1062StringRef Name = A->getValue();1063AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)1064#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \1065.Case(CMDFLAG, NAME##Model)1066#include "clang/StaticAnalyzer/Core/Analyses.def"1067.Default(NumConstraints);1068if (Value == NumConstraints) {1069Diags.Report(diag::err_drv_invalid_value)1070<< A->getAsString(Args) << Name;1071} else {1072#ifndef LLVM_WITH_Z31073if (Value == AnalysisConstraints::Z3ConstraintsModel) {1074Diags.Report(diag::err_analyzer_not_built_with_z3);1075}1076#endif // LLVM_WITH_Z31077Opts.AnalysisConstraintsOpt = Value;1078}1079}10801081if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {1082StringRef Name = A->getValue();1083AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)1084#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \1085.Case(CMDFLAG, PD_##NAME)1086#include "clang/StaticAnalyzer/Core/Analyses.def"1087.Default(NUM_ANALYSIS_DIAG_CLIENTS);1088if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {1089Diags.Report(diag::err_drv_invalid_value)1090<< A->getAsString(Args) << Name;1091} else {1092Opts.AnalysisDiagOpt = Value;1093}1094}10951096if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {1097StringRef Name = A->getValue();1098AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)1099#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \1100.Case(CMDFLAG, NAME)1101#include "clang/StaticAnalyzer/Core/Analyses.def"1102.Default(NumPurgeModes);1103if (Value == NumPurgeModes) {1104Diags.Report(diag::err_drv_invalid_value)1105<< A->getAsString(Args) << Name;1106} else {1107Opts.AnalysisPurgeOpt = Value;1108}1109}11101111if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {1112StringRef Name = A->getValue();1113AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)1114#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \1115.Case(CMDFLAG, NAME)1116#include "clang/StaticAnalyzer/Core/Analyses.def"1117.Default(NumInliningModes);1118if (Value == NumInliningModes) {1119Diags.Report(diag::err_drv_invalid_value)1120<< A->getAsString(Args) << Name;1121} else {1122Opts.InliningMode = Value;1123}1124}11251126Opts.CheckersAndPackages.clear();1127for (const Arg *A :1128Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {1129A->claim();1130bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;1131// We can have a list of comma separated checker names, e.g:1132// '-analyzer-checker=cocoa,unix'1133StringRef CheckerAndPackageList = A->getValue();1134SmallVector<StringRef, 16> CheckersAndPackages;1135CheckerAndPackageList.split(CheckersAndPackages, ",");1136for (const StringRef &CheckerOrPackage : CheckersAndPackages)1137Opts.CheckersAndPackages.emplace_back(std::string(CheckerOrPackage),1138IsEnabled);1139}11401141// Go through the analyzer configuration options.1142for (const auto *A : Args.filtered(OPT_analyzer_config)) {11431144// We can have a list of comma separated config names, e.g:1145// '-analyzer-config key1=val1,key2=val2'1146StringRef configList = A->getValue();1147SmallVector<StringRef, 4> configVals;1148configList.split(configVals, ",");1149for (const auto &configVal : configVals) {1150StringRef key, val;1151std::tie(key, val) = configVal.split("=");1152if (val.empty()) {1153Diags.Report(SourceLocation(),1154diag::err_analyzer_config_no_value) << configVal;1155break;1156}1157if (val.contains('=')) {1158Diags.Report(SourceLocation(),1159diag::err_analyzer_config_multiple_values)1160<< configVal;1161break;1162}11631164// TODO: Check checker options too, possibly in CheckerRegistry.1165// Leave unknown non-checker configs unclaimed.1166if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {1167if (Opts.ShouldEmitErrorsOnInvalidConfigValue)1168Diags.Report(diag::err_analyzer_config_unknown) << key;1169continue;1170}11711172A->claim();1173Opts.Config[key] = std::string(val);1174}1175}11761177if (Opts.ShouldEmitErrorsOnInvalidConfigValue)1178parseAnalyzerConfigs(Opts, &Diags);1179else1180parseAnalyzerConfigs(Opts, nullptr);11811182llvm::raw_string_ostream os(Opts.FullCompilerInvocation);1183for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {1184if (i != 0)1185os << " ";1186os << Args.getArgString(i);1187}1188os.flush();11891190return Diags.getNumErrors() == NumErrorsBefore;1191}11921193static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,1194StringRef OptionName, StringRef DefaultVal) {1195return Config.insert({OptionName, std::string(DefaultVal)}).first->second;1196}11971198static void initOption(AnalyzerOptions::ConfigTable &Config,1199DiagnosticsEngine *Diags,1200StringRef &OptionField, StringRef Name,1201StringRef DefaultVal) {1202// String options may be known to invalid (e.g. if the expected string is a1203// file name, but the file does not exist), those will have to be checked in1204// parseConfigs.1205OptionField = getStringOption(Config, Name, DefaultVal);1206}12071208static void initOption(AnalyzerOptions::ConfigTable &Config,1209DiagnosticsEngine *Diags,1210bool &OptionField, StringRef Name, bool DefaultVal) {1211auto PossiblyInvalidVal =1212llvm::StringSwitch<std::optional<bool>>(1213getStringOption(Config, Name, (DefaultVal ? "true" : "false")))1214.Case("true", true)1215.Case("false", false)1216.Default(std::nullopt);12171218if (!PossiblyInvalidVal) {1219if (Diags)1220Diags->Report(diag::err_analyzer_config_invalid_input)1221<< Name << "a boolean";1222else1223OptionField = DefaultVal;1224} else1225OptionField = *PossiblyInvalidVal;1226}12271228static void initOption(AnalyzerOptions::ConfigTable &Config,1229DiagnosticsEngine *Diags,1230unsigned &OptionField, StringRef Name,1231unsigned DefaultVal) {12321233OptionField = DefaultVal;1234bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))1235.getAsInteger(0, OptionField);1236if (Diags && HasFailed)1237Diags->Report(diag::err_analyzer_config_invalid_input)1238<< Name << "an unsigned";1239}12401241static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,1242DiagnosticsEngine *Diags) {1243// TODO: There's no need to store the entire configtable, it'd be plenty1244// enough to store checker options.12451246#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \1247initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);1248#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...)1249#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"12501251assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep");1252const bool InShallowMode = AnOpts.UserMode == "shallow";12531254#define ANALYZER_OPTION(...)1255#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \1256SHALLOW_VAL, DEEP_VAL) \1257initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, \1258InShallowMode ? SHALLOW_VAL : DEEP_VAL);1259#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"12601261// At this point, AnalyzerOptions is configured. Let's validate some options.12621263// FIXME: Here we try to validate the silenced checkers or packages are valid.1264// The current approach only validates the registered checkers which does not1265// contain the runtime enabled checkers and optimally we would validate both.1266if (!AnOpts.RawSilencedCheckersAndPackages.empty()) {1267std::vector<StringRef> Checkers =1268AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true);1269std::vector<StringRef> Packages =1270AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true);12711272SmallVector<StringRef, 16> CheckersAndPackages;1273AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";");12741275for (const StringRef &CheckerOrPackage : CheckersAndPackages) {1276if (Diags) {1277bool IsChecker = CheckerOrPackage.contains('.');1278bool IsValidName = IsChecker1279? llvm::is_contained(Checkers, CheckerOrPackage)1280: llvm::is_contained(Packages, CheckerOrPackage);12811282if (!IsValidName)1283Diags->Report(diag::err_unknown_analyzer_checker_or_package)1284<< CheckerOrPackage;1285}12861287AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage);1288}1289}12901291if (!Diags)1292return;12931294if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)1295Diags->Report(diag::err_analyzer_config_invalid_input)1296<< "track-conditions-debug" << "'track-conditions' to also be enabled";12971298if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir))1299Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir"1300<< "a filename";13011302if (!AnOpts.ModelPath.empty() &&1303!llvm::sys::fs::is_directory(AnOpts.ModelPath))1304Diags->Report(diag::err_analyzer_config_invalid_input) << "model-path"1305<< "a filename";1306}13071308/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.1309static void1310GenerateOptimizationRemark(ArgumentConsumer Consumer, OptSpecifier OptEQ,1311StringRef Name,1312const CodeGenOptions::OptRemark &Remark) {1313if (Remark.hasValidPattern()) {1314GenerateArg(Consumer, OptEQ, Remark.Pattern);1315} else if (Remark.Kind == CodeGenOptions::RK_Enabled) {1316GenerateArg(Consumer, OPT_R_Joined, Name);1317} else if (Remark.Kind == CodeGenOptions::RK_Disabled) {1318GenerateArg(Consumer, OPT_R_Joined, StringRef("no-") + Name);1319}1320}13211322/// Parse a remark command line argument. It may be missing, disabled/enabled by1323/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.1324/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.1325static CodeGenOptions::OptRemark1326ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args,1327OptSpecifier OptEQ, StringRef Name) {1328CodeGenOptions::OptRemark Result;13291330auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A,1331StringRef Pattern) {1332Result.Pattern = Pattern.str();13331334std::string RegexError;1335Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);1336if (!Result.Regex->isValid(RegexError)) {1337Diags.Report(diag::err_drv_optimization_remark_pattern)1338<< RegexError << A->getAsString(Args);1339return false;1340}13411342return true;1343};13441345for (Arg *A : Args) {1346if (A->getOption().matches(OPT_R_Joined)) {1347StringRef Value = A->getValue();13481349if (Value == Name)1350Result.Kind = CodeGenOptions::RK_Enabled;1351else if (Value == "everything")1352Result.Kind = CodeGenOptions::RK_EnabledEverything;1353else if (Value.split('-') == std::make_pair(StringRef("no"), Name))1354Result.Kind = CodeGenOptions::RK_Disabled;1355else if (Value == "no-everything")1356Result.Kind = CodeGenOptions::RK_DisabledEverything;1357else1358continue;13591360if (Result.Kind == CodeGenOptions::RK_Disabled ||1361Result.Kind == CodeGenOptions::RK_DisabledEverything) {1362Result.Pattern = "";1363Result.Regex = nullptr;1364} else {1365InitializeResultPattern(A, ".*");1366}1367} else if (A->getOption().matches(OptEQ)) {1368Result.Kind = CodeGenOptions::RK_WithPattern;1369if (!InitializeResultPattern(A, A->getValue()))1370return CodeGenOptions::OptRemark();1371}1372}13731374return Result;1375}13761377static bool parseDiagnosticLevelMask(StringRef FlagName,1378const std::vector<std::string> &Levels,1379DiagnosticsEngine &Diags,1380DiagnosticLevelMask &M) {1381bool Success = true;1382for (const auto &Level : Levels) {1383DiagnosticLevelMask const PM =1384llvm::StringSwitch<DiagnosticLevelMask>(Level)1385.Case("note", DiagnosticLevelMask::Note)1386.Case("remark", DiagnosticLevelMask::Remark)1387.Case("warning", DiagnosticLevelMask::Warning)1388.Case("error", DiagnosticLevelMask::Error)1389.Default(DiagnosticLevelMask::None);1390if (PM == DiagnosticLevelMask::None) {1391Success = false;1392Diags.Report(diag::err_drv_invalid_value) << FlagName << Level;1393}1394M = M | PM;1395}1396return Success;1397}13981399static void parseSanitizerKinds(StringRef FlagName,1400const std::vector<std::string> &Sanitizers,1401DiagnosticsEngine &Diags, SanitizerSet &S) {1402for (const auto &Sanitizer : Sanitizers) {1403SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);1404if (K == SanitizerMask())1405Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;1406else1407S.set(K, true);1408}1409}14101411static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) {1412SmallVector<StringRef, 4> Values;1413serializeSanitizerSet(S, Values);1414return Values;1415}14161417static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,1418ArgList &Args, DiagnosticsEngine &D,1419XRayInstrSet &S) {1420llvm::SmallVector<StringRef, 2> BundleParts;1421llvm::SplitString(Bundle, BundleParts, ",");1422for (const auto &B : BundleParts) {1423auto Mask = parseXRayInstrValue(B);1424if (Mask == XRayInstrKind::None)1425if (B != "none")1426D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;1427else1428S.Mask = Mask;1429else if (Mask == XRayInstrKind::All)1430S.Mask = Mask;1431else1432S.set(Mask, true);1433}1434}14351436static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) {1437llvm::SmallVector<StringRef, 2> BundleParts;1438serializeXRayInstrValue(S, BundleParts);1439std::string Buffer;1440llvm::raw_string_ostream OS(Buffer);1441llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");1442return Buffer;1443}14441445// Set the profile kind using fprofile-instrument-use-path.1446static void setPGOUseInstrumentor(CodeGenOptions &Opts,1447const Twine &ProfileName,1448llvm::vfs::FileSystem &FS,1449DiagnosticsEngine &Diags) {1450auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName, FS);1451if (auto E = ReaderOrErr.takeError()) {1452unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,1453"Error in reading profile %0: %1");1454llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {1455Diags.Report(DiagID) << ProfileName.str() << EI.message();1456});1457return;1458}1459std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader =1460std::move(ReaderOrErr.get());1461// Currently memprof profiles are only added at the IR level. Mark the profile1462// type as IR in that case as well and the subsequent matching needs to detect1463// which is available (might be one or both).1464if (PGOReader->isIRLevelProfile() || PGOReader->hasMemoryProfile()) {1465if (PGOReader->hasCSIRLevelProfile())1466Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr);1467else1468Opts.setProfileUse(CodeGenOptions::ProfileIRInstr);1469} else1470Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);1471}14721473void CompilerInvocation::setDefaultPointerAuthOptions(1474PointerAuthOptions &Opts, const LangOptions &LangOpts,1475const llvm::Triple &Triple) {1476assert(Triple.getArch() == llvm::Triple::aarch64);1477if (LangOpts.PointerAuthCalls) {1478using Key = PointerAuthSchema::ARM8_3Key;1479using Discrimination = PointerAuthSchema::Discrimination;1480// If you change anything here, be sure to update <ptrauth.h>.1481Opts.FunctionPointers = PointerAuthSchema(1482Key::ASIA, false,1483LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type1484: Discrimination::None);14851486Opts.CXXVTablePointers = PointerAuthSchema(1487Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,1488LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type1489: Discrimination::None);14901491if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)1492Opts.CXXTypeInfoVTablePointer =1493PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,1494StdTypeInfoVTablePointerConstantDiscrimination);1495else1496Opts.CXXTypeInfoVTablePointer =1497PointerAuthSchema(Key::ASDA, false, Discrimination::None);14981499Opts.CXXVTTVTablePointers =1500PointerAuthSchema(Key::ASDA, false, Discrimination::None);1501Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers =1502PointerAuthSchema(Key::ASIA, true, Discrimination::Decl);1503Opts.CXXMemberFunctionPointers =1504PointerAuthSchema(Key::ASIA, false, Discrimination::Type);1505}1506Opts.ReturnAddresses = LangOpts.PointerAuthReturns;1507Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;1508Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos;1509}15101511static void parsePointerAuthOptions(PointerAuthOptions &Opts,1512const LangOptions &LangOpts,1513const llvm::Triple &Triple,1514DiagnosticsEngine &Diags) {1515if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns &&1516!LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos)1517return;15181519CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple);1520}15211522void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,1523ArgumentConsumer Consumer,1524const llvm::Triple &T,1525const std::string &OutputFile,1526const LangOptions *LangOpts) {1527const CodeGenOptions &CodeGenOpts = Opts;15281529if (Opts.OptimizationLevel == 0)1530GenerateArg(Consumer, OPT_O0);1531else1532GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel));15331534#define CODEGEN_OPTION_WITH_MARSHALLING(...) \1535GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)1536#include "clang/Driver/Options.inc"1537#undef CODEGEN_OPTION_WITH_MARSHALLING15381539if (Opts.OptimizationLevel > 0) {1540if (Opts.Inlining == CodeGenOptions::NormalInlining)1541GenerateArg(Consumer, OPT_finline_functions);1542else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)1543GenerateArg(Consumer, OPT_finline_hint_functions);1544else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)1545GenerateArg(Consumer, OPT_fno_inline);1546}15471548if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)1549GenerateArg(Consumer, OPT_fdirect_access_external_data);1550else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)1551GenerateArg(Consumer, OPT_fno_direct_access_external_data);15521553std::optional<StringRef> DebugInfoVal;1554switch (Opts.DebugInfo) {1555case llvm::codegenoptions::DebugLineTablesOnly:1556DebugInfoVal = "line-tables-only";1557break;1558case llvm::codegenoptions::DebugDirectivesOnly:1559DebugInfoVal = "line-directives-only";1560break;1561case llvm::codegenoptions::DebugInfoConstructor:1562DebugInfoVal = "constructor";1563break;1564case llvm::codegenoptions::LimitedDebugInfo:1565DebugInfoVal = "limited";1566break;1567case llvm::codegenoptions::FullDebugInfo:1568DebugInfoVal = "standalone";1569break;1570case llvm::codegenoptions::UnusedTypeInfo:1571DebugInfoVal = "unused-types";1572break;1573case llvm::codegenoptions::NoDebugInfo: // default value1574DebugInfoVal = std::nullopt;1575break;1576case llvm::codegenoptions::LocTrackingOnly: // implied value1577DebugInfoVal = std::nullopt;1578break;1579}1580if (DebugInfoVal)1581GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal);15821583for (const auto &Prefix : Opts.DebugPrefixMap)1584GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ,1585Prefix.first + "=" + Prefix.second);15861587for (const auto &Prefix : Opts.CoveragePrefixMap)1588GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ,1589Prefix.first + "=" + Prefix.second);15901591if (Opts.NewStructPathTBAA)1592GenerateArg(Consumer, OPT_new_struct_path_tbaa);15931594if (Opts.OptimizeSize == 1)1595GenerateArg(Consumer, OPT_O, "s");1596else if (Opts.OptimizeSize == 2)1597GenerateArg(Consumer, OPT_O, "z");15981599// SimplifyLibCalls is set only in the absence of -fno-builtin and1600// -ffreestanding. We'll consider that when generating them.16011602// NoBuiltinFuncs are generated by LangOptions.16031604if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)1605GenerateArg(Consumer, OPT_funroll_loops);1606else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)1607GenerateArg(Consumer, OPT_fno_unroll_loops);16081609if (!Opts.BinutilsVersion.empty())1610GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion);16111612if (Opts.DebugNameTable ==1613static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))1614GenerateArg(Consumer, OPT_ggnu_pubnames);1615else if (Opts.DebugNameTable ==1616static_cast<unsigned>(1617llvm::DICompileUnit::DebugNameTableKind::Default))1618GenerateArg(Consumer, OPT_gpubnames);16191620if (Opts.DebugTemplateAlias)1621GenerateArg(Consumer, OPT_gtemplate_alias);16221623auto TNK = Opts.getDebugSimpleTemplateNames();1624if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {1625if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)1626GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple");1627else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled)1628GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled");1629}1630// ProfileInstrumentUsePath is marshalled automatically, no need to generate1631// it or PGOUseInstrumentor.16321633if (Opts.TimePasses) {1634if (Opts.TimePassesPerRun)1635GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run");1636else1637GenerateArg(Consumer, OPT_ftime_report);1638}16391640if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)1641GenerateArg(Consumer, OPT_flto_EQ, "full");16421643if (Opts.PrepareForThinLTO)1644GenerateArg(Consumer, OPT_flto_EQ, "thin");16451646if (!Opts.ThinLTOIndexFile.empty())1647GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile);16481649if (Opts.SaveTempsFilePrefix == OutputFile)1650GenerateArg(Consumer, OPT_save_temps_EQ, "obj");16511652StringRef MemProfileBasename("memprof.profraw");1653if (!Opts.MemoryProfileOutput.empty()) {1654if (Opts.MemoryProfileOutput == MemProfileBasename) {1655GenerateArg(Consumer, OPT_fmemory_profile);1656} else {1657size_t ArgLength =1658Opts.MemoryProfileOutput.size() - MemProfileBasename.size();1659GenerateArg(Consumer, OPT_fmemory_profile_EQ,1660Opts.MemoryProfileOutput.substr(0, ArgLength));1661}1662}16631664if (memcmp(Opts.CoverageVersion, "408*", 4) != 0)1665GenerateArg(Consumer, OPT_coverage_version_EQ,1666StringRef(Opts.CoverageVersion, 4));16671668// TODO: Check if we need to generate arguments stored in CmdArgs. (Namely1669// '-fembed_bitcode', which does not map to any CompilerInvocation field and1670// won't be generated.)16711672if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) {1673std::string InstrBundle =1674serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle);1675if (!InstrBundle.empty())1676GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle);1677}16781679if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)1680GenerateArg(Consumer, OPT_fcf_protection_EQ, "full");1681else if (Opts.CFProtectionReturn)1682GenerateArg(Consumer, OPT_fcf_protection_EQ, "return");1683else if (Opts.CFProtectionBranch)1684GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch");16851686if (Opts.FunctionReturnThunks)1687GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");16881689for (const auto &F : Opts.LinkBitcodeFiles) {1690bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&1691F.PropagateAttrs && F.Internalize;1692GenerateArg(Consumer,1693Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,1694F.Filename);1695}16961697if (Opts.EmulatedTLS)1698GenerateArg(Consumer, OPT_femulated_tls);16991700if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())1701GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str());17021703if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) ||1704(Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()))1705GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ,1706Opts.FP32DenormalMode.str());17071708if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {1709OptSpecifier Opt =1710T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;1711GenerateArg(Consumer, Opt);1712} else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {1713OptSpecifier Opt =1714T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;1715GenerateArg(Consumer, Opt);1716}17171718if (Opts.EnableAIXExtendedAltivecABI)1719GenerateArg(Consumer, OPT_mabi_EQ_vec_extabi);17201721if (Opts.XCOFFReadOnlyPointers)1722GenerateArg(Consumer, OPT_mxcoff_roptr);17231724if (!Opts.OptRecordPasses.empty())1725GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses);17261727if (!Opts.OptRecordFormat.empty())1728GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat);17291730GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass",1731Opts.OptimizationRemark);17321733GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed",1734Opts.OptimizationRemarkMissed);17351736GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis",1737Opts.OptimizationRemarkAnalysis);17381739GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ,1740Opts.DiagnosticsHotnessThreshold1741? Twine(*Opts.DiagnosticsHotnessThreshold)1742: "auto");17431744GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ,1745Twine(*Opts.DiagnosticsMisExpectTolerance));17461747for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))1748GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer);17491750for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))1751GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer);17521753if (!Opts.EmitVersionIdentMetadata)1754GenerateArg(Consumer, OPT_Qn);17551756switch (Opts.FiniteLoops) {1757case CodeGenOptions::FiniteLoopsKind::Language:1758break;1759case CodeGenOptions::FiniteLoopsKind::Always:1760GenerateArg(Consumer, OPT_ffinite_loops);1761break;1762case CodeGenOptions::FiniteLoopsKind::Never:1763GenerateArg(Consumer, OPT_fno_finite_loops);1764break;1765}1766}17671768bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,1769InputKind IK,1770DiagnosticsEngine &Diags,1771const llvm::Triple &T,1772const std::string &OutputFile,1773const LangOptions &LangOptsRef) {1774unsigned NumErrorsBefore = Diags.getNumErrors();17751776unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);1777// TODO: This could be done in Driver1778unsigned MaxOptLevel = 3;1779if (OptimizationLevel > MaxOptLevel) {1780// If the optimization level is not supported, fall back on the default1781// optimization1782Diags.Report(diag::warn_drv_optimization_value)1783<< Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;1784OptimizationLevel = MaxOptLevel;1785}1786Opts.OptimizationLevel = OptimizationLevel;17871788// The key paths of codegen options defined in Options.td start with1789// "CodeGenOpts.". Let's provide the expected variable name and type.1790CodeGenOptions &CodeGenOpts = Opts;1791// Some codegen options depend on language options. Let's provide the expected1792// variable name and type.1793const LangOptions *LangOpts = &LangOptsRef;17941795#define CODEGEN_OPTION_WITH_MARSHALLING(...) \1796PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)1797#include "clang/Driver/Options.inc"1798#undef CODEGEN_OPTION_WITH_MARSHALLING17991800// At O0 we want to fully disable inlining outside of cases marked with1801// 'alwaysinline' that are required for correctness.1802if (Opts.OptimizationLevel == 0) {1803Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);1804} else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions,1805options::OPT_finline_hint_functions,1806options::OPT_fno_inline_functions,1807options::OPT_fno_inline)) {1808// Explicit inlining flags can disable some or all inlining even at1809// optimization levels above zero.1810if (A->getOption().matches(options::OPT_finline_functions))1811Opts.setInlining(CodeGenOptions::NormalInlining);1812else if (A->getOption().matches(options::OPT_finline_hint_functions))1813Opts.setInlining(CodeGenOptions::OnlyHintInlining);1814else1815Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);1816} else {1817Opts.setInlining(CodeGenOptions::NormalInlining);1818}18191820// PIC defaults to -fno-direct-access-external-data while non-PIC defaults to1821// -fdirect-access-external-data.1822Opts.DirectAccessExternalData =1823Args.hasArg(OPT_fdirect_access_external_data) ||1824(!Args.hasArg(OPT_fno_direct_access_external_data) &&1825LangOpts->PICLevel == 0);18261827if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {1828unsigned Val =1829llvm::StringSwitch<unsigned>(A->getValue())1830.Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)1831.Case("line-directives-only",1832llvm::codegenoptions::DebugDirectivesOnly)1833.Case("constructor", llvm::codegenoptions::DebugInfoConstructor)1834.Case("limited", llvm::codegenoptions::LimitedDebugInfo)1835.Case("standalone", llvm::codegenoptions::FullDebugInfo)1836.Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)1837.Default(~0U);1838if (Val == ~0U)1839Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)1840<< A->getValue();1841else1842Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val));1843}18441845// If -fuse-ctor-homing is set and limited debug info is already on, then use1846// constructor homing, and vice versa for -fno-use-ctor-homing.1847if (const Arg *A =1848Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {1849if (A->getOption().matches(OPT_fuse_ctor_homing) &&1850Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo)1851Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor);1852if (A->getOption().matches(OPT_fno_use_ctor_homing) &&1853Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor)1854Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo);1855}18561857for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {1858auto Split = StringRef(Arg).split('=');1859Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);1860}18611862for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {1863auto Split = StringRef(Arg).split('=');1864Opts.CoveragePrefixMap.emplace_back(Split.first, Split.second);1865}18661867const llvm::Triple::ArchType DebugEntryValueArchs[] = {1868llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::aarch64,1869llvm::Triple::arm, llvm::Triple::armeb, llvm::Triple::mips,1870llvm::Triple::mipsel, llvm::Triple::mips64, llvm::Triple::mips64el};18711872if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&1873llvm::is_contained(DebugEntryValueArchs, T.getArch()))1874Opts.EmitCallSiteInfo = true;18751876if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {1877Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)1878<< Opts.DIBugsReportFilePath;1879Opts.DIBugsReportFilePath = "";1880}18811882Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&1883Args.hasArg(OPT_new_struct_path_tbaa);1884Opts.OptimizeSize = getOptimizationLevelSize(Args);1885Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;1886if (Opts.SimplifyLibCalls)1887Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;1888Opts.UnrollLoops =1889Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,1890(Opts.OptimizationLevel > 1));1891Opts.BinutilsVersion =1892std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));18931894Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias);18951896Opts.DebugNameTable = static_cast<unsigned>(1897Args.hasArg(OPT_ggnu_pubnames)1898? llvm::DICompileUnit::DebugNameTableKind::GNU1899: Args.hasArg(OPT_gpubnames)1900? llvm::DICompileUnit::DebugNameTableKind::Default1901: llvm::DICompileUnit::DebugNameTableKind::None);1902if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) {1903StringRef Value = A->getValue();1904if (Value != "simple" && Value != "mangled")1905Diags.Report(diag::err_drv_unsupported_option_argument)1906<< A->getSpelling() << A->getValue();1907Opts.setDebugSimpleTemplateNames(1908StringRef(A->getValue()) == "simple"1909? llvm::codegenoptions::DebugTemplateNamesKind::Simple1910: llvm::codegenoptions::DebugTemplateNamesKind::Mangled);1911}19121913if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ)) {1914Opts.TimePasses = true;19151916// -ftime-report= is only for new pass manager.1917if (A->getOption().getID() == OPT_ftime_report_EQ) {1918StringRef Val = A->getValue();1919if (Val == "per-pass")1920Opts.TimePassesPerRun = false;1921else if (Val == "per-pass-run")1922Opts.TimePassesPerRun = true;1923else1924Diags.Report(diag::err_drv_invalid_value)1925<< A->getAsString(Args) << A->getValue();1926}1927}19281929Opts.PrepareForLTO = false;1930Opts.PrepareForThinLTO = false;1931if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {1932Opts.PrepareForLTO = true;1933StringRef S = A->getValue();1934if (S == "thin")1935Opts.PrepareForThinLTO = true;1936else if (S != "full")1937Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;1938if (Args.hasArg(OPT_funified_lto))1939Opts.PrepareForThinLTO = true;1940}1941if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {1942if (IK.getLanguage() != Language::LLVM_IR)1943Diags.Report(diag::err_drv_argument_only_allowed_with)1944<< A->getAsString(Args) << "-x ir";1945Opts.ThinLTOIndexFile =1946std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ));1947}1948if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))1949Opts.SaveTempsFilePrefix =1950llvm::StringSwitch<std::string>(A->getValue())1951.Case("obj", OutputFile)1952.Default(llvm::sys::path::filename(OutputFile).str());19531954// The memory profile runtime appends the pid to make this name more unique.1955const char *MemProfileBasename = "memprof.profraw";1956if (Args.hasArg(OPT_fmemory_profile_EQ)) {1957SmallString<128> Path(1958std::string(Args.getLastArgValue(OPT_fmemory_profile_EQ)));1959llvm::sys::path::append(Path, MemProfileBasename);1960Opts.MemoryProfileOutput = std::string(Path);1961} else if (Args.hasArg(OPT_fmemory_profile))1962Opts.MemoryProfileOutput = MemProfileBasename;19631964memcpy(Opts.CoverageVersion, "408*", 4);1965if (Opts.CoverageNotesFile.size() || Opts.CoverageDataFile.size()) {1966if (Args.hasArg(OPT_coverage_version_EQ)) {1967StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);1968if (CoverageVersion.size() != 4) {1969Diags.Report(diag::err_drv_invalid_value)1970<< Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)1971<< CoverageVersion;1972} else {1973memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);1974}1975}1976}1977// FIXME: For backend options that are not yet recorded as function1978// attributes in the IR, keep track of them so we can embed them in a1979// separate data section and use them when building the bitcode.1980for (const auto &A : Args) {1981// Do not encode output and input.1982if (A->getOption().getID() == options::OPT_o ||1983A->getOption().getID() == options::OPT_INPUT ||1984A->getOption().getID() == options::OPT_x ||1985A->getOption().getID() == options::OPT_fembed_bitcode ||1986A->getOption().matches(options::OPT_W_Group))1987continue;1988ArgStringList ASL;1989A->render(Args, ASL);1990for (const auto &arg : ASL) {1991StringRef ArgStr(arg);1992Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end());1993// using \00 to separate each commandline options.1994Opts.CmdArgs.push_back('\0');1995}1996}19971998auto XRayInstrBundles =1999Args.getAllArgValues(OPT_fxray_instrumentation_bundle);2000if (XRayInstrBundles.empty())2001Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All;2002else2003for (const auto &A : XRayInstrBundles)2004parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,2005Diags, Opts.XRayInstrumentationBundle);20062007if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {2008StringRef Name = A->getValue();2009if (Name == "full") {2010Opts.CFProtectionReturn = 1;2011Opts.CFProtectionBranch = 1;2012} else if (Name == "return")2013Opts.CFProtectionReturn = 1;2014else if (Name == "branch")2015Opts.CFProtectionBranch = 1;2016else if (Name != "none")2017Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;2018}20192020if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {2021auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())2022.Case("keep", llvm::FunctionReturnThunksKind::Keep)2023.Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)2024.Default(llvm::FunctionReturnThunksKind::Invalid);2025// SystemZ might want to add support for "expolines."2026if (!T.isX86())2027Diags.Report(diag::err_drv_argument_not_allowed_with)2028<< A->getSpelling() << T.getTriple();2029else if (Val == llvm::FunctionReturnThunksKind::Invalid)2030Diags.Report(diag::err_drv_invalid_value)2031<< A->getAsString(Args) << A->getValue();2032else if (Val == llvm::FunctionReturnThunksKind::Extern &&2033Args.getLastArgValue(OPT_mcmodel_EQ) == "large")2034Diags.Report(diag::err_drv_argument_not_allowed_with)2035<< A->getAsString(Args)2036<< Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);2037else2038Opts.FunctionReturnThunks = static_cast<unsigned>(Val);2039}20402041for (auto *A :2042Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {2043CodeGenOptions::BitcodeFileToLink F;2044F.Filename = A->getValue();2045if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {2046F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;2047// When linking CUDA bitcode, propagate function attributes so that2048// e.g. libdevice gets fast-math attrs if we're building with fast-math.2049F.PropagateAttrs = true;2050F.Internalize = true;2051}2052Opts.LinkBitcodeFiles.push_back(F);2053}20542055if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {2056StringRef Val = A->getValue();2057Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);2058Opts.FP32DenormalMode = Opts.FPDenormalMode;2059if (!Opts.FPDenormalMode.isValid())2060Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;2061}20622063if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_f32_EQ)) {2064StringRef Val = A->getValue();2065Opts.FP32DenormalMode = llvm::parseDenormalFPAttribute(Val);2066if (!Opts.FP32DenormalMode.isValid())2067Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;2068}20692070// X86_32 has -fppc-struct-return and -freg-struct-return.2071// PPC32 has -maix-struct-return and -msvr4-struct-return.2072if (Arg *A =2073Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return,2074OPT_maix_struct_return, OPT_msvr4_struct_return)) {2075// TODO: We might want to consider enabling these options on AIX in the2076// future.2077if (T.isOSAIX())2078Diags.Report(diag::err_drv_unsupported_opt_for_target)2079<< A->getSpelling() << T.str();20802081const Option &O = A->getOption();2082if (O.matches(OPT_fpcc_struct_return) ||2083O.matches(OPT_maix_struct_return)) {2084Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);2085} else {2086assert(O.matches(OPT_freg_struct_return) ||2087O.matches(OPT_msvr4_struct_return));2088Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs);2089}2090}20912092if (Arg *A = Args.getLastArg(OPT_mxcoff_roptr)) {2093if (!T.isOSAIX())2094Diags.Report(diag::err_drv_unsupported_opt_for_target)2095<< A->getSpelling() << T.str();20962097// Since the storage mapping class is specified per csect,2098// without using data sections, it is less effective to use read-only2099// pointers. Using read-only pointers may cause other RO variables in the2100// same csect to become RW when the linker acts upon `-bforceimprw`;2101// therefore, we require that separate data sections2102// are used when `-mxcoff-roptr` is in effect. We respect the setting of2103// data-sections since we have not found reasons to do otherwise that2104// overcome the user surprise of not respecting the setting.2105if (!Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false))2106Diags.Report(diag::err_roptr_requires_data_sections);21072108Opts.XCOFFReadOnlyPointers = true;2109}21102111if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) {2112if (!T.isOSAIX() || T.isPPC32())2113Diags.Report(diag::err_drv_unsupported_opt_for_target)2114<< A->getSpelling() << T.str();2115}21162117bool NeedLocTracking = false;21182119if (!Opts.OptRecordFile.empty())2120NeedLocTracking = true;21212122if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) {2123Opts.OptRecordPasses = A->getValue();2124NeedLocTracking = true;2125}21262127if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {2128Opts.OptRecordFormat = A->getValue();2129NeedLocTracking = true;2130}21312132Opts.OptimizationRemark =2133ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");21342135Opts.OptimizationRemarkMissed =2136ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");21372138Opts.OptimizationRemarkAnalysis = ParseOptimizationRemark(2139Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");21402141NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||2142Opts.OptimizationRemarkMissed.hasValidPattern() ||2143Opts.OptimizationRemarkAnalysis.hasValidPattern();21442145bool UsingSampleProfile = !Opts.SampleProfileFile.empty();2146bool UsingProfile =2147UsingSampleProfile || !Opts.ProfileInstrumentUsePath.empty();21482149if (Opts.DiagnosticsWithHotness && !UsingProfile &&2150// An IR file will contain PGO as metadata2151IK.getLanguage() != Language::LLVM_IR)2152Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)2153<< "-fdiagnostics-show-hotness";21542155// Parse remarks hotness threshold. Valid value is either integer or 'auto'.2156if (auto *arg =2157Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {2158auto ResultOrErr =2159llvm::remarks::parseHotnessThresholdOption(arg->getValue());21602161if (!ResultOrErr) {2162Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold)2163<< "-fdiagnostics-hotness-threshold=";2164} else {2165Opts.DiagnosticsHotnessThreshold = *ResultOrErr;2166if ((!Opts.DiagnosticsHotnessThreshold ||2167*Opts.DiagnosticsHotnessThreshold > 0) &&2168!UsingProfile)2169Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)2170<< "-fdiagnostics-hotness-threshold=";2171}2172}21732174if (auto *arg =2175Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) {2176auto ResultOrErr = parseToleranceOption(arg->getValue());21772178if (!ResultOrErr) {2179Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance)2180<< "-fdiagnostics-misexpect-tolerance=";2181} else {2182Opts.DiagnosticsMisExpectTolerance = *ResultOrErr;2183if ((!Opts.DiagnosticsMisExpectTolerance ||2184*Opts.DiagnosticsMisExpectTolerance > 0) &&2185!UsingProfile)2186Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)2187<< "-fdiagnostics-misexpect-tolerance=";2188}2189}21902191// If the user requested to use a sample profile for PGO, then the2192// backend will need to track source location information so the profile2193// can be incorporated into the IR.2194if (UsingSampleProfile)2195NeedLocTracking = true;21962197if (!Opts.StackUsageOutput.empty())2198NeedLocTracking = true;21992200// If the user requested a flag that requires source locations available in2201// the backend, make sure that the backend tracks source location information.2202if (NeedLocTracking &&2203Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)2204Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);22052206// Parse -fsanitize-recover= arguments.2207// FIXME: Report unrecoverable sanitizers incorrectly specified here.2208parseSanitizerKinds("-fsanitize-recover=",2209Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,2210Opts.SanitizeRecover);2211parseSanitizerKinds("-fsanitize-trap=",2212Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,2213Opts.SanitizeTrap);22142215Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);22162217if (!LangOpts->CUDAIsDevice)2218parsePointerAuthOptions(Opts.PointerAuth, *LangOpts, T, Diags);22192220if (Args.hasArg(options::OPT_ffinite_loops))2221Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;2222else if (Args.hasArg(options::OPT_fno_finite_loops))2223Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;22242225Opts.EmitIEEENaNCompliantInsts = Args.hasFlag(2226options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true);2227if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)2228Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);22292230return Diags.getNumErrors() == NumErrorsBefore;2231}22322233static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts,2234ArgumentConsumer Consumer) {2235const DependencyOutputOptions &DependencyOutputOpts = Opts;2236#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \2237GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2238#include "clang/Driver/Options.inc"2239#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING22402241if (Opts.ShowIncludesDest != ShowIncludesDestination::None)2242GenerateArg(Consumer, OPT_show_includes);22432244for (const auto &Dep : Opts.ExtraDeps) {2245switch (Dep.second) {2246case EDK_SanitizeIgnorelist:2247// Sanitizer ignorelist arguments are generated from LanguageOptions.2248continue;2249case EDK_ModuleFile:2250// Module file arguments are generated from FrontendOptions and2251// HeaderSearchOptions.2252continue;2253case EDK_ProfileList:2254// Profile list arguments are generated from LanguageOptions via the2255// marshalling infrastructure.2256continue;2257case EDK_DepFileEntry:2258GenerateArg(Consumer, OPT_fdepfile_entry, Dep.first);2259break;2260}2261}2262}22632264static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts,2265ArgList &Args, DiagnosticsEngine &Diags,2266frontend::ActionKind Action,2267bool ShowLineMarkers) {2268unsigned NumErrorsBefore = Diags.getNumErrors();22692270DependencyOutputOptions &DependencyOutputOpts = Opts;2271#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...) \2272PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)2273#include "clang/Driver/Options.inc"2274#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING22752276if (Args.hasArg(OPT_show_includes)) {2277// Writing both /showIncludes and preprocessor output to stdout2278// would produce interleaved output, so use stderr for /showIncludes.2279// This behaves the same as cl.exe, when /E, /EP or /P are passed.2280if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers)2281Opts.ShowIncludesDest = ShowIncludesDestination::Stderr;2282else2283Opts.ShowIncludesDest = ShowIncludesDestination::Stdout;2284} else {2285Opts.ShowIncludesDest = ShowIncludesDestination::None;2286}22872288// Add sanitizer ignorelists as extra dependencies.2289// They won't be discovered by the regular preprocessor, so2290// we let make / ninja to know about this implicit dependency.2291if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) {2292for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) {2293StringRef Val = A->getValue();2294if (!Val.contains('='))2295Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);2296}2297if (Opts.IncludeSystemHeaders) {2298for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) {2299StringRef Val = A->getValue();2300if (!Val.contains('='))2301Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);2302}2303}2304}23052306// -fprofile-list= dependencies.2307for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ))2308Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList);23092310// Propagate the extra dependencies.2311for (const auto *A : Args.filtered(OPT_fdepfile_entry))2312Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry);23132314// Only the -fmodule-file=<file> form.2315for (const auto *A : Args.filtered(OPT_fmodule_file)) {2316StringRef Val = A->getValue();2317if (!Val.contains('='))2318Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile);2319}23202321// Check for invalid combinations of header-include-format2322// and header-include-filtering.2323if ((Opts.HeaderIncludeFormat == HIFMT_Textual &&2324Opts.HeaderIncludeFiltering != HIFIL_None) ||2325(Opts.HeaderIncludeFormat == HIFMT_JSON &&2326Opts.HeaderIncludeFiltering != HIFIL_Only_Direct_System))2327Diags.Report(diag::err_drv_print_header_env_var_combination_cc1)2328<< Args.getLastArg(OPT_header_include_format_EQ)->getValue()2329<< Args.getLastArg(OPT_header_include_filtering_EQ)->getValue();23302331return Diags.getNumErrors() == NumErrorsBefore;2332}23332334static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {2335// Color diagnostics default to auto ("on" if terminal supports) in the driver2336// but default to off in cc1, needing an explicit OPT_fdiagnostics_color.2337// Support both clang's -f[no-]color-diagnostics and gcc's2338// -f[no-]diagnostics-colors[=never|always|auto].2339enum {2340Colors_On,2341Colors_Off,2342Colors_Auto2343} ShowColors = DefaultColor ? Colors_Auto : Colors_Off;2344for (auto *A : Args) {2345const Option &O = A->getOption();2346if (O.matches(options::OPT_fcolor_diagnostics)) {2347ShowColors = Colors_On;2348} else if (O.matches(options::OPT_fno_color_diagnostics)) {2349ShowColors = Colors_Off;2350} else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {2351StringRef Value(A->getValue());2352if (Value == "always")2353ShowColors = Colors_On;2354else if (Value == "never")2355ShowColors = Colors_Off;2356else if (Value == "auto")2357ShowColors = Colors_Auto;2358}2359}2360return ShowColors == Colors_On ||2361(ShowColors == Colors_Auto &&2362llvm::sys::Process::StandardErrHasColors());2363}23642365static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,2366DiagnosticsEngine &Diags) {2367bool Success = true;2368for (const auto &Prefix : VerifyPrefixes) {2369// Every prefix must start with a letter and contain only alphanumeric2370// characters, hyphens, and underscores.2371auto BadChar = llvm::find_if(Prefix, [](char C) {2372return !isAlphanumeric(C) && C != '-' && C != '_';2373});2374if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {2375Success = false;2376Diags.Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;2377Diags.Report(diag::note_drv_verify_prefix_spelling);2378}2379}2380return Success;2381}23822383static void GenerateFileSystemArgs(const FileSystemOptions &Opts,2384ArgumentConsumer Consumer) {2385const FileSystemOptions &FileSystemOpts = Opts;23862387#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \2388GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2389#include "clang/Driver/Options.inc"2390#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING2391}23922393static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args,2394DiagnosticsEngine &Diags) {2395unsigned NumErrorsBefore = Diags.getNumErrors();23962397FileSystemOptions &FileSystemOpts = Opts;23982399#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...) \2400PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)2401#include "clang/Driver/Options.inc"2402#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING24032404return Diags.getNumErrors() == NumErrorsBefore;2405}24062407static void GenerateMigratorArgs(const MigratorOptions &Opts,2408ArgumentConsumer Consumer) {2409const MigratorOptions &MigratorOpts = Opts;2410#define MIGRATOR_OPTION_WITH_MARSHALLING(...) \2411GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2412#include "clang/Driver/Options.inc"2413#undef MIGRATOR_OPTION_WITH_MARSHALLING2414}24152416static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,2417DiagnosticsEngine &Diags) {2418unsigned NumErrorsBefore = Diags.getNumErrors();24192420MigratorOptions &MigratorOpts = Opts;24212422#define MIGRATOR_OPTION_WITH_MARSHALLING(...) \2423PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)2424#include "clang/Driver/Options.inc"2425#undef MIGRATOR_OPTION_WITH_MARSHALLING24262427return Diags.getNumErrors() == NumErrorsBefore;2428}24292430void CompilerInvocationBase::GenerateDiagnosticArgs(2431const DiagnosticOptions &Opts, ArgumentConsumer Consumer,2432bool DefaultDiagColor) {2433const DiagnosticOptions *DiagnosticOpts = &Opts;2434#define DIAG_OPTION_WITH_MARSHALLING(...) \2435GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2436#include "clang/Driver/Options.inc"2437#undef DIAG_OPTION_WITH_MARSHALLING24382439if (!Opts.DiagnosticSerializationFile.empty())2440GenerateArg(Consumer, OPT_diagnostic_serialized_file,2441Opts.DiagnosticSerializationFile);24422443if (Opts.ShowColors)2444GenerateArg(Consumer, OPT_fcolor_diagnostics);24452446if (Opts.VerifyDiagnostics &&2447llvm::is_contained(Opts.VerifyPrefixes, "expected"))2448GenerateArg(Consumer, OPT_verify);24492450for (const auto &Prefix : Opts.VerifyPrefixes)2451if (Prefix != "expected")2452GenerateArg(Consumer, OPT_verify_EQ, Prefix);24532454DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();2455if (VIU == DiagnosticLevelMask::None) {2456// This is the default, don't generate anything.2457} else if (VIU == DiagnosticLevelMask::All) {2458GenerateArg(Consumer, OPT_verify_ignore_unexpected);2459} else {2460if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)2461GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "note");2462if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)2463GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "remark");2464if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)2465GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "warning");2466if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)2467GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "error");2468}24692470for (const auto &Warning : Opts.Warnings) {2471// This option is automatically generated from UndefPrefixes.2472if (Warning == "undef-prefix")2473continue;2474// This option is automatically generated from CheckConstexprFunctionBodies.2475if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")2476continue;2477Consumer(StringRef("-W") + Warning);2478}24792480for (const auto &Remark : Opts.Remarks) {2481// These arguments are generated from OptimizationRemark fields of2482// CodeGenOptions.2483StringRef IgnoredRemarks[] = {"pass", "no-pass",2484"pass-analysis", "no-pass-analysis",2485"pass-missed", "no-pass-missed"};2486if (llvm::is_contained(IgnoredRemarks, Remark))2487continue;24882489Consumer(StringRef("-R") + Remark);2490}2491}24922493std::unique_ptr<DiagnosticOptions>2494clang::CreateAndPopulateDiagOpts(ArrayRef<const char *> Argv) {2495auto DiagOpts = std::make_unique<DiagnosticOptions>();2496unsigned MissingArgIndex, MissingArgCount;2497InputArgList Args = getDriverOptTable().ParseArgs(2498Argv.slice(1), MissingArgIndex, MissingArgCount);24992500bool ShowColors = true;2501if (std::optional<std::string> NoColor =2502llvm::sys::Process::GetEnv("NO_COLOR");2503NoColor && !NoColor->empty()) {2504// If the user set the NO_COLOR environment variable, we'll honor that2505// unless the command line overrides it.2506ShowColors = false;2507}25082509// We ignore MissingArgCount and the return value of ParseDiagnosticArgs.2510// Any errors that would be diagnosed here will also be diagnosed later,2511// when the DiagnosticsEngine actually exists.2512(void)ParseDiagnosticArgs(*DiagOpts, Args, /*Diags=*/nullptr, ShowColors);2513return DiagOpts;2514}25152516bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,2517DiagnosticsEngine *Diags,2518bool DefaultDiagColor) {2519std::optional<DiagnosticsEngine> IgnoringDiags;2520if (!Diags) {2521IgnoringDiags.emplace(new DiagnosticIDs(), new DiagnosticOptions(),2522new IgnoringDiagConsumer());2523Diags = &*IgnoringDiags;2524}25252526unsigned NumErrorsBefore = Diags->getNumErrors();25272528// The key paths of diagnostic options defined in Options.td start with2529// "DiagnosticOpts->". Let's provide the expected variable name and type.2530DiagnosticOptions *DiagnosticOpts = &Opts;25312532#define DIAG_OPTION_WITH_MARSHALLING(...) \2533PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, __VA_ARGS__)2534#include "clang/Driver/Options.inc"2535#undef DIAG_OPTION_WITH_MARSHALLING25362537llvm::sys::Process::UseANSIEscapeCodes(Opts.UseANSIEscapeCodes);25382539if (Arg *A =2540Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))2541Opts.DiagnosticSerializationFile = A->getValue();2542Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);25432544Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);2545Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);2546if (Args.hasArg(OPT_verify))2547Opts.VerifyPrefixes.push_back("expected");2548// Keep VerifyPrefixes in its original order for the sake of diagnostics, and2549// then sort it to prepare for fast lookup using std::binary_search.2550if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags))2551Opts.VerifyDiagnostics = false;2552else2553llvm::sort(Opts.VerifyPrefixes);2554DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;2555parseDiagnosticLevelMask(2556"-verify-ignore-unexpected=",2557Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask);2558if (Args.hasArg(OPT_verify_ignore_unexpected))2559DiagMask = DiagnosticLevelMask::All;2560Opts.setVerifyIgnoreUnexpected(DiagMask);2561if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {2562Diags->Report(diag::warn_ignoring_ftabstop_value)2563<< Opts.TabStop << DiagnosticOptions::DefaultTabStop;2564Opts.TabStop = DiagnosticOptions::DefaultTabStop;2565}25662567addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);2568addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);25692570return Diags->getNumErrors() == NumErrorsBefore;2571}25722573/// Parse the argument to the -ftest-module-file-extension2574/// command-line argument.2575///2576/// \returns true on error, false on success.2577static bool parseTestModuleFileExtensionArg(StringRef Arg,2578std::string &BlockName,2579unsigned &MajorVersion,2580unsigned &MinorVersion,2581bool &Hashed,2582std::string &UserInfo) {2583SmallVector<StringRef, 5> Args;2584Arg.split(Args, ':', 5);2585if (Args.size() < 5)2586return true;25872588BlockName = std::string(Args[0]);2589if (Args[1].getAsInteger(10, MajorVersion)) return true;2590if (Args[2].getAsInteger(10, MinorVersion)) return true;2591if (Args[3].getAsInteger(2, Hashed)) return true;2592if (Args.size() > 4)2593UserInfo = std::string(Args[4]);2594return false;2595}25962597/// Return a table that associates command line option specifiers with the2598/// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is2599/// intentionally missing, as this case is handled separately from other2600/// frontend options.2601static const auto &getFrontendActionTable() {2602static const std::pair<frontend::ActionKind, unsigned> Table[] = {2603{frontend::ASTDeclList, OPT_ast_list},26042605{frontend::ASTDump, OPT_ast_dump_all_EQ},2606{frontend::ASTDump, OPT_ast_dump_all},2607{frontend::ASTDump, OPT_ast_dump_EQ},2608{frontend::ASTDump, OPT_ast_dump},2609{frontend::ASTDump, OPT_ast_dump_lookups},2610{frontend::ASTDump, OPT_ast_dump_decl_types},26112612{frontend::ASTPrint, OPT_ast_print},2613{frontend::ASTView, OPT_ast_view},2614{frontend::DumpCompilerOptions, OPT_compiler_options_dump},2615{frontend::DumpRawTokens, OPT_dump_raw_tokens},2616{frontend::DumpTokens, OPT_dump_tokens},2617{frontend::EmitAssembly, OPT_S},2618{frontend::EmitBC, OPT_emit_llvm_bc},2619{frontend::EmitCIR, OPT_emit_cir},2620{frontend::EmitHTML, OPT_emit_html},2621{frontend::EmitLLVM, OPT_emit_llvm},2622{frontend::EmitLLVMOnly, OPT_emit_llvm_only},2623{frontend::EmitCodeGenOnly, OPT_emit_codegen_only},2624{frontend::EmitObj, OPT_emit_obj},2625{frontend::ExtractAPI, OPT_extract_api},26262627{frontend::FixIt, OPT_fixit_EQ},2628{frontend::FixIt, OPT_fixit},26292630{frontend::GenerateModule, OPT_emit_module},2631{frontend::GenerateModuleInterface, OPT_emit_module_interface},2632{frontend::GenerateReducedModuleInterface,2633OPT_emit_reduced_module_interface},2634{frontend::GenerateHeaderUnit, OPT_emit_header_unit},2635{frontend::GeneratePCH, OPT_emit_pch},2636{frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},2637{frontend::InitOnly, OPT_init_only},2638{frontend::ParseSyntaxOnly, OPT_fsyntax_only},2639{frontend::ModuleFileInfo, OPT_module_file_info},2640{frontend::VerifyPCH, OPT_verify_pch},2641{frontend::PrintPreamble, OPT_print_preamble},2642{frontend::PrintPreprocessedInput, OPT_E},2643{frontend::TemplightDump, OPT_templight_dump},2644{frontend::RewriteMacros, OPT_rewrite_macros},2645{frontend::RewriteObjC, OPT_rewrite_objc},2646{frontend::RewriteTest, OPT_rewrite_test},2647{frontend::RunAnalysis, OPT_analyze},2648{frontend::MigrateSource, OPT_migrate},2649{frontend::RunPreprocessorOnly, OPT_Eonly},2650{frontend::PrintDependencyDirectivesSourceMinimizerOutput,2651OPT_print_dependency_directives_minimized_source},2652};26532654return Table;2655}26562657/// Maps command line option to frontend action.2658static std::optional<frontend::ActionKind>2659getFrontendAction(OptSpecifier &Opt) {2660for (const auto &ActionOpt : getFrontendActionTable())2661if (ActionOpt.second == Opt.getID())2662return ActionOpt.first;26632664return std::nullopt;2665}26662667/// Maps frontend action to command line option.2668static std::optional<OptSpecifier>2669getProgramActionOpt(frontend::ActionKind ProgramAction) {2670for (const auto &ActionOpt : getFrontendActionTable())2671if (ActionOpt.first == ProgramAction)2672return OptSpecifier(ActionOpt.second);26732674return std::nullopt;2675}26762677static void GenerateFrontendArgs(const FrontendOptions &Opts,2678ArgumentConsumer Consumer, bool IsHeader) {2679const FrontendOptions &FrontendOpts = Opts;2680#define FRONTEND_OPTION_WITH_MARSHALLING(...) \2681GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2682#include "clang/Driver/Options.inc"2683#undef FRONTEND_OPTION_WITH_MARSHALLING26842685std::optional<OptSpecifier> ProgramActionOpt =2686getProgramActionOpt(Opts.ProgramAction);26872688// Generating a simple flag covers most frontend actions.2689std::function<void()> GenerateProgramAction = [&]() {2690GenerateArg(Consumer, *ProgramActionOpt);2691};26922693if (!ProgramActionOpt) {2694// PluginAction is the only program action handled separately.2695assert(Opts.ProgramAction == frontend::PluginAction &&2696"Frontend action without option.");2697GenerateProgramAction = [&]() {2698GenerateArg(Consumer, OPT_plugin, Opts.ActionName);2699};2700}27012702// FIXME: Simplify the complex 'AST dump' command line.2703if (Opts.ProgramAction == frontend::ASTDump) {2704GenerateProgramAction = [&]() {2705// ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via2706// marshalling infrastructure.27072708if (Opts.ASTDumpFormat != ADOF_Default) {2709StringRef Format;2710switch (Opts.ASTDumpFormat) {2711case ADOF_Default:2712llvm_unreachable("Default AST dump format.");2713case ADOF_JSON:2714Format = "json";2715break;2716}27172718if (Opts.ASTDumpAll)2719GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format);2720if (Opts.ASTDumpDecls)2721GenerateArg(Consumer, OPT_ast_dump_EQ, Format);2722} else {2723if (Opts.ASTDumpAll)2724GenerateArg(Consumer, OPT_ast_dump_all);2725if (Opts.ASTDumpDecls)2726GenerateArg(Consumer, OPT_ast_dump);2727}2728};2729}27302731if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {2732GenerateProgramAction = [&]() {2733GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix);2734};2735}27362737GenerateProgramAction();27382739for (const auto &PluginArgs : Opts.PluginArgs) {2740Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);2741for (const auto &PluginArg : PluginArgs.second)2742denormalizeString(Consumer,2743Opt.getPrefix() + Opt.getName() + PluginArgs.first,2744Opt.getKind(), 0, PluginArg);2745}27462747for (const auto &Ext : Opts.ModuleFileExtensions)2748if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))2749GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str());27502751if (!Opts.CodeCompletionAt.FileName.empty())2752GenerateArg(Consumer, OPT_code_completion_at,2753Opts.CodeCompletionAt.ToString());27542755for (const auto &Plugin : Opts.Plugins)2756GenerateArg(Consumer, OPT_load, Plugin);27572758// ASTDumpDecls and ASTDumpAll already handled with ProgramAction.27592760for (const auto &ModuleFile : Opts.ModuleFiles)2761GenerateArg(Consumer, OPT_fmodule_file, ModuleFile);27622763if (Opts.AuxTargetCPU)2764GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU);27652766if (Opts.AuxTargetFeatures)2767for (const auto &Feature : *Opts.AuxTargetFeatures)2768GenerateArg(Consumer, OPT_aux_target_feature, Feature);27692770{2771StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";2772StringRef ModuleMap =2773Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";2774StringRef HeaderUnit = "";2775switch (Opts.DashX.getHeaderUnitKind()) {2776case InputKind::HeaderUnit_None:2777break;2778case InputKind::HeaderUnit_User:2779HeaderUnit = "-user";2780break;2781case InputKind::HeaderUnit_System:2782HeaderUnit = "-system";2783break;2784case InputKind::HeaderUnit_Abs:2785HeaderUnit = "-header-unit";2786break;2787}2788StringRef Header = IsHeader ? "-header" : "";27892790StringRef Lang;2791switch (Opts.DashX.getLanguage()) {2792case Language::C:2793Lang = "c";2794break;2795case Language::OpenCL:2796Lang = "cl";2797break;2798case Language::OpenCLCXX:2799Lang = "clcpp";2800break;2801case Language::CUDA:2802Lang = "cuda";2803break;2804case Language::HIP:2805Lang = "hip";2806break;2807case Language::CXX:2808Lang = "c++";2809break;2810case Language::ObjC:2811Lang = "objective-c";2812break;2813case Language::ObjCXX:2814Lang = "objective-c++";2815break;2816case Language::RenderScript:2817Lang = "renderscript";2818break;2819case Language::Asm:2820Lang = "assembler-with-cpp";2821break;2822case Language::Unknown:2823assert(Opts.DashX.getFormat() == InputKind::Precompiled &&2824"Generating -x argument for unknown language (not precompiled).");2825Lang = "ast";2826break;2827case Language::LLVM_IR:2828Lang = "ir";2829break;2830case Language::HLSL:2831Lang = "hlsl";2832break;2833case Language::CIR:2834Lang = "cir";2835break;2836}28372838GenerateArg(Consumer, OPT_x,2839Lang + HeaderUnit + Header + ModuleMap + Preprocessed);2840}28412842// OPT_INPUT has a unique class, generate it directly.2843for (const auto &Input : Opts.Inputs)2844Consumer(Input.getFile());2845}28462847static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,2848DiagnosticsEngine &Diags, bool &IsHeaderFile) {2849unsigned NumErrorsBefore = Diags.getNumErrors();28502851FrontendOptions &FrontendOpts = Opts;28522853#define FRONTEND_OPTION_WITH_MARSHALLING(...) \2854PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)2855#include "clang/Driver/Options.inc"2856#undef FRONTEND_OPTION_WITH_MARSHALLING28572858Opts.ProgramAction = frontend::ParseSyntaxOnly;2859if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {2860OptSpecifier Opt = OptSpecifier(A->getOption().getID());2861std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);2862assert(ProgramAction && "Option specifier not in Action_Group.");28632864if (ProgramAction == frontend::ASTDump &&2865(Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {2866unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())2867.CaseLower("default", ADOF_Default)2868.CaseLower("json", ADOF_JSON)2869.Default(std::numeric_limits<unsigned>::max());28702871if (Val != std::numeric_limits<unsigned>::max())2872Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);2873else {2874Diags.Report(diag::err_drv_invalid_value)2875<< A->getAsString(Args) << A->getValue();2876Opts.ASTDumpFormat = ADOF_Default;2877}2878}28792880if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)2881Opts.FixItSuffix = A->getValue();28822883if (ProgramAction == frontend::GenerateInterfaceStubs) {2884StringRef ArgStr =2885Args.hasArg(OPT_interface_stub_version_EQ)2886? Args.getLastArgValue(OPT_interface_stub_version_EQ)2887: "ifs-v1";2888if (ArgStr == "experimental-yaml-elf-v1" ||2889ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||2890ArgStr == "experimental-tapi-elf-v1") {2891std::string ErrorMessage =2892"Invalid interface stub format: " + ArgStr.str() +2893" is deprecated.";2894Diags.Report(diag::err_drv_invalid_value)2895<< "Must specify a valid interface stub format type, ie: "2896"-interface-stub-version=ifs-v1"2897<< ErrorMessage;2898ProgramAction = frontend::ParseSyntaxOnly;2899} else if (!ArgStr.starts_with("ifs-")) {2900std::string ErrorMessage =2901"Invalid interface stub format: " + ArgStr.str() + ".";2902Diags.Report(diag::err_drv_invalid_value)2903<< "Must specify a valid interface stub format type, ie: "2904"-interface-stub-version=ifs-v1"2905<< ErrorMessage;2906ProgramAction = frontend::ParseSyntaxOnly;2907}2908}29092910Opts.ProgramAction = *ProgramAction;29112912// Catch common mistakes when multiple actions are specified for cc1 (e.g.2913// -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to2914// support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name2915// X ACTION), we suppress the error when the two actions are separated by2916// -main-file-name.2917//2918// As an exception, accept composable -ast-dump*.2919if (!A->getSpelling().starts_with("-ast-dump")) {2920const Arg *SavedAction = nullptr;2921for (const Arg *AA :2922Args.filtered(OPT_Action_Group, OPT_main_file_name)) {2923if (AA->getOption().matches(OPT_main_file_name)) {2924SavedAction = nullptr;2925} else if (!SavedAction) {2926SavedAction = AA;2927} else {2928if (!A->getOption().matches(OPT_ast_dump_EQ))2929Diags.Report(diag::err_fe_invalid_multiple_actions)2930<< SavedAction->getSpelling() << A->getSpelling();2931break;2932}2933}2934}2935}29362937if (const Arg* A = Args.getLastArg(OPT_plugin)) {2938Opts.Plugins.emplace_back(A->getValue(0));2939Opts.ProgramAction = frontend::PluginAction;2940Opts.ActionName = A->getValue();2941}2942for (const auto *AA : Args.filtered(OPT_plugin_arg))2943Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));29442945for (const std::string &Arg :2946Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {2947std::string BlockName;2948unsigned MajorVersion;2949unsigned MinorVersion;2950bool Hashed;2951std::string UserInfo;2952if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,2953MinorVersion, Hashed, UserInfo)) {2954Diags.Report(diag::err_test_module_file_extension_format) << Arg;29552956continue;2957}29582959// Add the testing module file extension.2960Opts.ModuleFileExtensions.push_back(2961std::make_shared<TestModuleFileExtension>(2962BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));2963}29642965if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {2966Opts.CodeCompletionAt =2967ParsedSourceLocation::FromString(A->getValue());2968if (Opts.CodeCompletionAt.FileName.empty())2969Diags.Report(diag::err_drv_invalid_value)2970<< A->getAsString(Args) << A->getValue();2971}29722973Opts.Plugins = Args.getAllArgValues(OPT_load);2974Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);2975Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);2976// Only the -fmodule-file=<file> form.2977for (const auto *A : Args.filtered(OPT_fmodule_file)) {2978StringRef Val = A->getValue();2979if (!Val.contains('='))2980Opts.ModuleFiles.push_back(std::string(Val));2981}29822983if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule)2984Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"2985<< "-emit-module";2986if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir))2987Opts.UseClangIRPipeline = true;29882989if (Args.hasArg(OPT_aux_target_cpu))2990Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu));2991if (Args.hasArg(OPT_aux_target_feature))2992Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);29932994if (Opts.ARCMTAction != FrontendOptions::ARCMT_None &&2995Opts.ObjCMTAction != FrontendOptions::ObjCMT_None) {2996Diags.Report(diag::err_drv_argument_not_allowed_with)2997<< "ARC migration" << "ObjC migration";2998}29993000InputKind DashX(Language::Unknown);3001if (const Arg *A = Args.getLastArg(OPT_x)) {3002StringRef XValue = A->getValue();30033004// Parse suffixes:3005// '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'.3006// FIXME: Supporting '<lang>-header-cpp-output' would be useful.3007bool Preprocessed = XValue.consume_back("-cpp-output");3008bool ModuleMap = XValue.consume_back("-module-map");3009// Detect and consume the header indicator.3010bool IsHeader =3011XValue != "precompiled-header" && XValue.consume_back("-header");30123013// If we have c++-{user,system}-header, that indicates a header unit input3014// likewise, if the user put -fmodule-header together with a header with an3015// absolute path (header-unit-header).3016InputKind::HeaderUnitKind HUK = InputKind::HeaderUnit_None;3017if (IsHeader || Preprocessed) {3018if (XValue.consume_back("-header-unit"))3019HUK = InputKind::HeaderUnit_Abs;3020else if (XValue.consume_back("-system"))3021HUK = InputKind::HeaderUnit_System;3022else if (XValue.consume_back("-user"))3023HUK = InputKind::HeaderUnit_User;3024}30253026// The value set by this processing is an un-preprocessed source which is3027// not intended to be a module map or header unit.3028IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&3029HUK == InputKind::HeaderUnit_None;30303031// Principal languages.3032DashX = llvm::StringSwitch<InputKind>(XValue)3033.Case("c", Language::C)3034.Case("cl", Language::OpenCL)3035.Case("clcpp", Language::OpenCLCXX)3036.Case("cuda", Language::CUDA)3037.Case("hip", Language::HIP)3038.Case("c++", Language::CXX)3039.Case("objective-c", Language::ObjC)3040.Case("objective-c++", Language::ObjCXX)3041.Case("renderscript", Language::RenderScript)3042.Case("hlsl", Language::HLSL)3043.Default(Language::Unknown);30443045// "objc[++]-cpp-output" is an acceptable synonym for3046// "objective-c[++]-cpp-output".3047if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap &&3048HUK == InputKind::HeaderUnit_None)3049DashX = llvm::StringSwitch<InputKind>(XValue)3050.Case("objc", Language::ObjC)3051.Case("objc++", Language::ObjCXX)3052.Default(Language::Unknown);30533054// Some special cases cannot be combined with suffixes.3055if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap &&3056HUK == InputKind::HeaderUnit_None)3057DashX = llvm::StringSwitch<InputKind>(XValue)3058.Case("cpp-output", InputKind(Language::C).getPreprocessed())3059.Case("assembler-with-cpp", Language::Asm)3060.Cases("ast", "pcm", "precompiled-header",3061InputKind(Language::Unknown, InputKind::Precompiled))3062.Case("ir", Language::LLVM_IR)3063.Case("cir", Language::CIR)3064.Default(Language::Unknown);30653066if (DashX.isUnknown())3067Diags.Report(diag::err_drv_invalid_value)3068<< A->getAsString(Args) << A->getValue();30693070if (Preprocessed)3071DashX = DashX.getPreprocessed();3072// A regular header is considered mutually exclusive with a header unit.3073if (HUK != InputKind::HeaderUnit_None) {3074DashX = DashX.withHeaderUnit(HUK);3075IsHeaderFile = true;3076} else if (IsHeaderFile)3077DashX = DashX.getHeader();3078if (ModuleMap)3079DashX = DashX.withFormat(InputKind::ModuleMap);3080}30813082// '-' is the default input if none is given.3083std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);3084Opts.Inputs.clear();3085if (Inputs.empty())3086Inputs.push_back("-");30873088if (DashX.getHeaderUnitKind() != InputKind::HeaderUnit_None &&3089Inputs.size() > 1)3090Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];30913092for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {3093InputKind IK = DashX;3094if (IK.isUnknown()) {3095IK = FrontendOptions::getInputKindForExtension(3096StringRef(Inputs[i]).rsplit('.').second);3097// FIXME: Warn on this?3098if (IK.isUnknown())3099IK = Language::C;3100// FIXME: Remove this hack.3101if (i == 0)3102DashX = IK;3103}31043105bool IsSystem = false;31063107// The -emit-module action implicitly takes a module map.3108if (Opts.ProgramAction == frontend::GenerateModule &&3109IK.getFormat() == InputKind::Source) {3110IK = IK.withFormat(InputKind::ModuleMap);3111IsSystem = Opts.IsSystemModule;3112}31133114Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);3115}31163117Opts.DashX = DashX;31183119return Diags.getNumErrors() == NumErrorsBefore;3120}31213122std::string CompilerInvocation::GetResourcesPath(const char *Argv0,3123void *MainAddr) {3124std::string ClangExecutable =3125llvm::sys::fs::getMainExecutable(Argv0, MainAddr);3126return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);3127}31283129static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,3130ArgumentConsumer Consumer) {3131const HeaderSearchOptions *HeaderSearchOpts = &Opts;3132#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \3133GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)3134#include "clang/Driver/Options.inc"3135#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING31363137if (Opts.UseLibcxx)3138GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");31393140if (!Opts.ModuleCachePath.empty())3141GenerateArg(Consumer, OPT_fmodules_cache_path, Opts.ModuleCachePath);31423143for (const auto &File : Opts.PrebuiltModuleFiles)3144GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);31453146for (const auto &Path : Opts.PrebuiltModulePaths)3147GenerateArg(Consumer, OPT_fprebuilt_module_path, Path);31483149for (const auto &Macro : Opts.ModulesIgnoreMacros)3150GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val());31513152auto Matches = [](const HeaderSearchOptions::Entry &Entry,3153llvm::ArrayRef<frontend::IncludeDirGroup> Groups,3154std::optional<bool> IsFramework,3155std::optional<bool> IgnoreSysRoot) {3156return llvm::is_contained(Groups, Entry.Group) &&3157(!IsFramework || (Entry.IsFramework == *IsFramework)) &&3158(!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));3159};31603161auto It = Opts.UserEntries.begin();3162auto End = Opts.UserEntries.end();31633164// Add -I..., -F..., and -index-header-map options in order.3165for (; It < End && Matches(*It, {frontend::IndexHeaderMap, frontend::Angled},3166std::nullopt, true);3167++It) {3168OptSpecifier Opt = [It, Matches]() {3169if (Matches(*It, frontend::IndexHeaderMap, true, true))3170return OPT_F;3171if (Matches(*It, frontend::IndexHeaderMap, false, true))3172return OPT_I;3173if (Matches(*It, frontend::Angled, true, true))3174return OPT_F;3175if (Matches(*It, frontend::Angled, false, true))3176return OPT_I;3177llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");3178}();31793180if (It->Group == frontend::IndexHeaderMap)3181GenerateArg(Consumer, OPT_index_header_map);3182GenerateArg(Consumer, Opt, It->Path);3183};31843185// Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may3186// have already been generated as "-I[xx]yy". If that's the case, their3187// position on command line was such that this has no semantic impact on3188// include paths.3189for (; It < End &&3190Matches(*It, {frontend::After, frontend::Angled}, false, true);3191++It) {3192OptSpecifier Opt =3193It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;3194GenerateArg(Consumer, Opt, It->Path);3195}31963197// Note: Some paths that came from "-idirafter=xxyy" may have already been3198// generated as "-iwithprefix=xxyy". If that's the case, their position on3199// command line was such that this has no semantic impact on include paths.3200for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)3201GenerateArg(Consumer, OPT_idirafter, It->Path);3202for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)3203GenerateArg(Consumer, OPT_iquote, It->Path);3204for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt);3205++It)3206GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,3207It->Path);3208for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)3209GenerateArg(Consumer, OPT_iframework, It->Path);3210for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)3211GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path);32123213// Add the paths for the various language specific isystem flags.3214for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)3215GenerateArg(Consumer, OPT_c_isystem, It->Path);3216for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)3217GenerateArg(Consumer, OPT_cxx_isystem, It->Path);3218for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)3219GenerateArg(Consumer, OPT_objc_isystem, It->Path);3220for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)3221GenerateArg(Consumer, OPT_objcxx_isystem, It->Path);32223223// Add the internal paths from a driver that detects standard include paths.3224// Note: Some paths that came from "-internal-isystem" arguments may have3225// already been generated as "-isystem". If that's the case, their position on3226// command line was such that this has no semantic impact on include paths.3227for (; It < End &&3228Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);3229++It) {3230OptSpecifier Opt = It->Group == frontend::System3231? OPT_internal_isystem3232: OPT_internal_externc_isystem;3233GenerateArg(Consumer, Opt, It->Path);3234}32353236assert(It == End && "Unhandled HeaderSearchOption::Entry.");32373238// Add the path prefixes which are implicitly treated as being system headers.3239for (const auto &P : Opts.SystemHeaderPrefixes) {3240OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix3241: OPT_no_system_header_prefix;3242GenerateArg(Consumer, Opt, P.Prefix);3243}32443245for (const std::string &F : Opts.VFSOverlayFiles)3246GenerateArg(Consumer, OPT_ivfsoverlay, F);3247}32483249static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,3250DiagnosticsEngine &Diags,3251const std::string &WorkingDir) {3252unsigned NumErrorsBefore = Diags.getNumErrors();32533254HeaderSearchOptions *HeaderSearchOpts = &Opts;32553256#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...) \3257PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)3258#include "clang/Driver/Options.inc"3259#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING32603261if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))3262Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);32633264// Canonicalize -fmodules-cache-path before storing it.3265SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));3266if (!(P.empty() || llvm::sys::path::is_absolute(P))) {3267if (WorkingDir.empty())3268llvm::sys::fs::make_absolute(P);3269else3270llvm::sys::fs::make_absolute(WorkingDir, P);3271}3272llvm::sys::path::remove_dots(P);3273Opts.ModuleCachePath = std::string(P);32743275// Only the -fmodule-file=<name>=<file> form.3276for (const auto *A : Args.filtered(OPT_fmodule_file)) {3277StringRef Val = A->getValue();3278if (Val.contains('=')) {3279auto Split = Val.split('=');3280Opts.PrebuiltModuleFiles.insert_or_assign(3281std::string(Split.first), std::string(Split.second));3282}3283}3284for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))3285Opts.AddPrebuiltModulePath(A->getValue());32863287for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {3288StringRef MacroDef = A->getValue();3289Opts.ModulesIgnoreMacros.insert(3290llvm::CachedHashString(MacroDef.split('=').first));3291}32923293// Add -I..., -F..., and -index-header-map options in order.3294bool IsIndexHeaderMap = false;3295bool IsSysrootSpecified =3296Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);32973298// Expand a leading `=` to the sysroot if one was passed (and it's not a3299// framework flag).3300auto PrefixHeaderPath = [IsSysrootSpecified,3301&Opts](const llvm::opt::Arg *A,3302bool IsFramework = false) -> std::string {3303assert(A->getNumValues() && "Unexpected empty search path flag!");3304if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {3305SmallString<32> Buffer;3306llvm::sys::path::append(Buffer, Opts.Sysroot,3307llvm::StringRef(A->getValue()).substr(1));3308return std::string(Buffer);3309}3310return A->getValue();3311};33123313for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {3314if (A->getOption().matches(OPT_index_header_map)) {3315// -index-header-map applies to the next -I or -F.3316IsIndexHeaderMap = true;3317continue;3318}33193320frontend::IncludeDirGroup Group =3321IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled;33223323bool IsFramework = A->getOption().matches(OPT_F);3324Opts.AddPath(PrefixHeaderPath(A, IsFramework), Group, IsFramework,3325/*IgnoreSysroot*/ true);3326IsIndexHeaderMap = false;3327}33283329// Add -iprefix/-iwithprefix/-iwithprefixbefore options.3330StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.3331for (const auto *A :3332Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {3333if (A->getOption().matches(OPT_iprefix))3334Prefix = A->getValue();3335else if (A->getOption().matches(OPT_iwithprefix))3336Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);3337else3338Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);3339}33403341for (const auto *A : Args.filtered(OPT_idirafter))3342Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true);3343for (const auto *A : Args.filtered(OPT_iquote))3344Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true);33453346for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) {3347if (A->getOption().matches(OPT_iwithsysroot)) {3348Opts.AddPath(A->getValue(), frontend::System, false,3349/*IgnoreSysRoot=*/false);3350continue;3351}3352Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true);3353}3354for (const auto *A : Args.filtered(OPT_iframework))3355Opts.AddPath(A->getValue(), frontend::System, true, true);3356for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))3357Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,3358/*IgnoreSysRoot=*/false);33593360// Add the paths for the various language specific isystem flags.3361for (const auto *A : Args.filtered(OPT_c_isystem))3362Opts.AddPath(A->getValue(), frontend::CSystem, false, true);3363for (const auto *A : Args.filtered(OPT_cxx_isystem))3364Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);3365for (const auto *A : Args.filtered(OPT_objc_isystem))3366Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);3367for (const auto *A : Args.filtered(OPT_objcxx_isystem))3368Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);33693370// Add the internal paths from a driver that detects standard include paths.3371for (const auto *A :3372Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {3373frontend::IncludeDirGroup Group = frontend::System;3374if (A->getOption().matches(OPT_internal_externc_isystem))3375Group = frontend::ExternCSystem;3376Opts.AddPath(A->getValue(), Group, false, true);3377}33783379// Add the path prefixes which are implicitly treated as being system headers.3380for (const auto *A :3381Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))3382Opts.AddSystemHeaderPrefix(3383A->getValue(), A->getOption().matches(OPT_system_header_prefix));33843385for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))3386Opts.AddVFSOverlayFile(A->getValue());33873388return Diags.getNumErrors() == NumErrorsBefore;3389}33903391static void GenerateAPINotesArgs(const APINotesOptions &Opts,3392ArgumentConsumer Consumer) {3393if (!Opts.SwiftVersion.empty())3394GenerateArg(Consumer, OPT_fapinotes_swift_version,3395Opts.SwiftVersion.getAsString());33963397for (const auto &Path : Opts.ModuleSearchPaths)3398GenerateArg(Consumer, OPT_iapinotes_modules, Path);3399}34003401static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args,3402DiagnosticsEngine &diags) {3403if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) {3404if (Opts.SwiftVersion.tryParse(A->getValue()))3405diags.Report(diag::err_drv_invalid_value)3406<< A->getAsString(Args) << A->getValue();3407}3408for (const Arg *A : Args.filtered(OPT_iapinotes_modules))3409Opts.ModuleSearchPaths.push_back(A->getValue());3410}34113412static void GeneratePointerAuthArgs(const LangOptions &Opts,3413ArgumentConsumer Consumer) {3414if (Opts.PointerAuthIntrinsics)3415GenerateArg(Consumer, OPT_fptrauth_intrinsics);3416if (Opts.PointerAuthCalls)3417GenerateArg(Consumer, OPT_fptrauth_calls);3418if (Opts.PointerAuthReturns)3419GenerateArg(Consumer, OPT_fptrauth_returns);3420if (Opts.PointerAuthIndirectGotos)3421GenerateArg(Consumer, OPT_fptrauth_indirect_gotos);3422if (Opts.PointerAuthAuthTraps)3423GenerateArg(Consumer, OPT_fptrauth_auth_traps);3424if (Opts.PointerAuthVTPtrAddressDiscrimination)3425GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);3426if (Opts.PointerAuthVTPtrTypeDiscrimination)3427GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);3428if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)3429GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);34303431if (Opts.PointerAuthInitFini)3432GenerateArg(Consumer, OPT_fptrauth_init_fini);3433if (Opts.PointerAuthFunctionTypeDiscrimination)3434GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);3435}34363437static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,3438DiagnosticsEngine &Diags) {3439Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);3440Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls);3441Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns);3442Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos);3443Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps);3444Opts.PointerAuthVTPtrAddressDiscrimination =3445Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);3446Opts.PointerAuthVTPtrTypeDiscrimination =3447Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);3448Opts.PointerAuthTypeInfoVTPtrDiscrimination =3449Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);34503451Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);3452Opts.PointerAuthFunctionTypeDiscrimination =3453Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);3454}34553456/// Check if input file kind and language standard are compatible.3457static bool IsInputCompatibleWithStandard(InputKind IK,3458const LangStandard &S) {3459switch (IK.getLanguage()) {3460case Language::Unknown:3461case Language::LLVM_IR:3462case Language::CIR:3463llvm_unreachable("should not parse language flags for this input");34643465case Language::C:3466case Language::ObjC:3467case Language::RenderScript:3468return S.getLanguage() == Language::C;34693470case Language::OpenCL:3471return S.getLanguage() == Language::OpenCL ||3472S.getLanguage() == Language::OpenCLCXX;34733474case Language::OpenCLCXX:3475return S.getLanguage() == Language::OpenCLCXX;34763477case Language::CXX:3478case Language::ObjCXX:3479return S.getLanguage() == Language::CXX;34803481case Language::CUDA:3482// FIXME: What -std= values should be permitted for CUDA compilations?3483return S.getLanguage() == Language::CUDA ||3484S.getLanguage() == Language::CXX;34853486case Language::HIP:3487return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;34883489case Language::Asm:3490// Accept (and ignore) all -std= values.3491// FIXME: The -std= value is not ignored; it affects the tokenization3492// and preprocessing rules if we're preprocessing this asm input.3493return true;34943495case Language::HLSL:3496return S.getLanguage() == Language::HLSL;3497}34983499llvm_unreachable("unexpected input language");3500}35013502/// Get language name for given input kind.3503static StringRef GetInputKindName(InputKind IK) {3504switch (IK.getLanguage()) {3505case Language::C:3506return "C";3507case Language::ObjC:3508return "Objective-C";3509case Language::CXX:3510return "C++";3511case Language::ObjCXX:3512return "Objective-C++";3513case Language::OpenCL:3514return "OpenCL";3515case Language::OpenCLCXX:3516return "C++ for OpenCL";3517case Language::CUDA:3518return "CUDA";3519case Language::RenderScript:3520return "RenderScript";3521case Language::HIP:3522return "HIP";35233524case Language::Asm:3525return "Asm";3526case Language::LLVM_IR:3527return "LLVM IR";3528case Language::CIR:3529return "Clang IR";35303531case Language::HLSL:3532return "HLSL";35333534case Language::Unknown:3535break;3536}3537llvm_unreachable("unknown input language");3538}35393540void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,3541ArgumentConsumer Consumer,3542const llvm::Triple &T,3543InputKind IK) {3544if (IK.getFormat() == InputKind::Precompiled ||3545IK.getLanguage() == Language::LLVM_IR ||3546IK.getLanguage() == Language::CIR) {3547if (Opts.ObjCAutoRefCount)3548GenerateArg(Consumer, OPT_fobjc_arc);3549if (Opts.PICLevel != 0)3550GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel));3551if (Opts.PIE)3552GenerateArg(Consumer, OPT_pic_is_pie);3553for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))3554GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);35553556return;3557}35583559OptSpecifier StdOpt;3560switch (Opts.LangStd) {3561case LangStandard::lang_opencl10:3562case LangStandard::lang_opencl11:3563case LangStandard::lang_opencl12:3564case LangStandard::lang_opencl20:3565case LangStandard::lang_opencl30:3566case LangStandard::lang_openclcpp10:3567case LangStandard::lang_openclcpp2021:3568StdOpt = OPT_cl_std_EQ;3569break;3570default:3571StdOpt = OPT_std_EQ;3572break;3573}35743575auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);3576GenerateArg(Consumer, StdOpt, LangStandard.getName());35773578if (Opts.IncludeDefaultHeader)3579GenerateArg(Consumer, OPT_finclude_default_header);3580if (Opts.DeclareOpenCLBuiltins)3581GenerateArg(Consumer, OPT_fdeclare_opencl_builtins);35823583const LangOptions *LangOpts = &Opts;35843585#define LANG_OPTION_WITH_MARSHALLING(...) \3586GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)3587#include "clang/Driver/Options.inc"3588#undef LANG_OPTION_WITH_MARSHALLING35893590// The '-fcf-protection=' option is generated by CodeGenOpts generator.35913592if (Opts.ObjC) {3593GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString());35943595if (Opts.GC == LangOptions::GCOnly)3596GenerateArg(Consumer, OPT_fobjc_gc_only);3597else if (Opts.GC == LangOptions::HybridGC)3598GenerateArg(Consumer, OPT_fobjc_gc);3599else if (Opts.ObjCAutoRefCount == 1)3600GenerateArg(Consumer, OPT_fobjc_arc);36013602if (Opts.ObjCWeakRuntime)3603GenerateArg(Consumer, OPT_fobjc_runtime_has_weak);36043605if (Opts.ObjCWeak)3606GenerateArg(Consumer, OPT_fobjc_weak);36073608if (Opts.ObjCSubscriptingLegacyRuntime)3609GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime);3610}36113612if (Opts.GNUCVersion != 0) {3613unsigned Major = Opts.GNUCVersion / 100 / 100;3614unsigned Minor = (Opts.GNUCVersion / 100) % 100;3615unsigned Patch = Opts.GNUCVersion % 100;3616GenerateArg(Consumer, OPT_fgnuc_version_EQ,3617Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch));3618}36193620if (Opts.IgnoreXCOFFVisibility)3621GenerateArg(Consumer, OPT_mignore_xcoff_visibility);36223623if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {3624GenerateArg(Consumer, OPT_ftrapv);3625GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler);3626} else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {3627GenerateArg(Consumer, OPT_fwrapv);3628}36293630if (Opts.MSCompatibilityVersion != 0) {3631unsigned Major = Opts.MSCompatibilityVersion / 10000000;3632unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;3633unsigned Subminor = Opts.MSCompatibilityVersion % 100000;3634GenerateArg(Consumer, OPT_fms_compatibility_version,3635Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor));3636}36373638if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||3639T.isOSzOS()) {3640if (!Opts.Trigraphs)3641GenerateArg(Consumer, OPT_fno_trigraphs);3642} else {3643if (Opts.Trigraphs)3644GenerateArg(Consumer, OPT_ftrigraphs);3645}36463647if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))3648GenerateArg(Consumer, OPT_fblocks);36493650if (Opts.ConvergentFunctions &&3651!(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice ||3652Opts.HLSL))3653GenerateArg(Consumer, OPT_fconvergent_functions);36543655if (Opts.NoBuiltin && !Opts.Freestanding)3656GenerateArg(Consumer, OPT_fno_builtin);36573658if (!Opts.NoBuiltin)3659for (const auto &Func : Opts.NoBuiltinFuncs)3660GenerateArg(Consumer, OPT_fno_builtin_, Func);36613662if (Opts.LongDoubleSize == 128)3663GenerateArg(Consumer, OPT_mlong_double_128);3664else if (Opts.LongDoubleSize == 64)3665GenerateArg(Consumer, OPT_mlong_double_64);3666else if (Opts.LongDoubleSize == 80)3667GenerateArg(Consumer, OPT_mlong_double_80);36683669// Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.36703671// OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or3672// '-fopenmp-targets='.3673if (Opts.OpenMP && !Opts.OpenMPSimd) {3674GenerateArg(Consumer, OPT_fopenmp);36753676if (Opts.OpenMP != 51)3677GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));36783679if (!Opts.OpenMPUseTLS)3680GenerateArg(Consumer, OPT_fnoopenmp_use_tls);36813682if (Opts.OpenMPIsTargetDevice)3683GenerateArg(Consumer, OPT_fopenmp_is_target_device);36843685if (Opts.OpenMPIRBuilder)3686GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder);3687}36883689if (Opts.OpenMPSimd) {3690GenerateArg(Consumer, OPT_fopenmp_simd);36913692if (Opts.OpenMP != 51)3693GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));3694}36953696if (Opts.OpenMPThreadSubscription)3697GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription);36983699if (Opts.OpenMPTeamSubscription)3700GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription);37013702if (Opts.OpenMPTargetDebug != 0)3703GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ,3704Twine(Opts.OpenMPTargetDebug));37053706if (Opts.OpenMPCUDANumSMs != 0)3707GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ,3708Twine(Opts.OpenMPCUDANumSMs));37093710if (Opts.OpenMPCUDABlocksPerSM != 0)3711GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ,3712Twine(Opts.OpenMPCUDABlocksPerSM));37133714if (Opts.OpenMPCUDAReductionBufNum != 1024)3715GenerateArg(Consumer, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,3716Twine(Opts.OpenMPCUDAReductionBufNum));37173718if (!Opts.OMPTargetTriples.empty()) {3719std::string Targets;3720llvm::raw_string_ostream OS(Targets);3721llvm::interleave(3722Opts.OMPTargetTriples, OS,3723[&OS](const llvm::Triple &T) { OS << T.str(); }, ",");3724GenerateArg(Consumer, OPT_fopenmp_targets_EQ, OS.str());3725}37263727if (!Opts.OMPHostIRFile.empty())3728GenerateArg(Consumer, OPT_fopenmp_host_ir_file_path, Opts.OMPHostIRFile);37293730if (Opts.OpenMPCUDAMode)3731GenerateArg(Consumer, OPT_fopenmp_cuda_mode);37323733if (Opts.OpenACC) {3734GenerateArg(Consumer, OPT_fopenacc);3735if (!Opts.OpenACCMacroOverride.empty())3736GenerateArg(Consumer, OPT_openacc_macro_override,3737Opts.OpenACCMacroOverride);3738}37393740// The arguments used to set Optimize, OptimizeSize and NoInlineDefine are3741// generated from CodeGenOptions.37423743if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)3744GenerateArg(Consumer, OPT_ffp_contract, "fast");3745else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)3746GenerateArg(Consumer, OPT_ffp_contract, "on");3747else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)3748GenerateArg(Consumer, OPT_ffp_contract, "off");3749else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)3750GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas");37513752for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))3753GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);37543755// Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.3756for (const std::string &F : Opts.NoSanitizeFiles)3757GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F);37583759switch (Opts.getClangABICompat()) {3760case LangOptions::ClangABI::Ver3_8:3761GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "3.8");3762break;3763case LangOptions::ClangABI::Ver4:3764GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "4.0");3765break;3766case LangOptions::ClangABI::Ver6:3767GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "6.0");3768break;3769case LangOptions::ClangABI::Ver7:3770GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "7.0");3771break;3772case LangOptions::ClangABI::Ver9:3773GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "9.0");3774break;3775case LangOptions::ClangABI::Ver11:3776GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "11.0");3777break;3778case LangOptions::ClangABI::Ver12:3779GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "12.0");3780break;3781case LangOptions::ClangABI::Ver14:3782GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "14.0");3783break;3784case LangOptions::ClangABI::Ver15:3785GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "15.0");3786break;3787case LangOptions::ClangABI::Ver17:3788GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");3789break;3790case LangOptions::ClangABI::Ver18:3791GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "18.0");3792break;3793case LangOptions::ClangABI::Latest:3794break;3795}37963797if (Opts.getSignReturnAddressScope() ==3798LangOptions::SignReturnAddressScopeKind::All)3799GenerateArg(Consumer, OPT_msign_return_address_EQ, "all");3800else if (Opts.getSignReturnAddressScope() ==3801LangOptions::SignReturnAddressScopeKind::NonLeaf)3802GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf");38033804if (Opts.getSignReturnAddressKey() ==3805LangOptions::SignReturnAddressKeyKind::BKey)3806GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key");38073808if (Opts.CXXABI)3809GenerateArg(Consumer, OPT_fcxx_abi_EQ,3810TargetCXXABI::getSpelling(*Opts.CXXABI));38113812if (Opts.RelativeCXXABIVTables)3813GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);3814else3815GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables);38163817if (Opts.UseTargetPathSeparator)3818GenerateArg(Consumer, OPT_ffile_reproducible);3819else3820GenerateArg(Consumer, OPT_fno_file_reproducible);38213822for (const auto &MP : Opts.MacroPrefixMap)3823GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second);38243825if (!Opts.RandstructSeed.empty())3826GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed);3827}38283829bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,3830InputKind IK, const llvm::Triple &T,3831std::vector<std::string> &Includes,3832DiagnosticsEngine &Diags) {3833unsigned NumErrorsBefore = Diags.getNumErrors();38343835if (IK.getFormat() == InputKind::Precompiled ||3836IK.getLanguage() == Language::LLVM_IR ||3837IK.getLanguage() == Language::CIR) {3838// ObjCAAutoRefCount and Sanitize LangOpts are used to setup the3839// PassManager in BackendUtil.cpp. They need to be initialized no matter3840// what the input type is.3841if (Args.hasArg(OPT_fobjc_arc))3842Opts.ObjCAutoRefCount = 1;3843// PICLevel and PIELevel are needed during code generation and this should3844// be set regardless of the input type.3845Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);3846Opts.PIE = Args.hasArg(OPT_pic_is_pie);3847parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),3848Diags, Opts.Sanitize);38493850return Diags.getNumErrors() == NumErrorsBefore;3851}38523853// Other LangOpts are only initialized when the input is not AST or LLVM IR.3854// FIXME: Should we really be parsing this for an Language::Asm input?38553856// FIXME: Cleanup per-file based stuff.3857LangStandard::Kind LangStd = LangStandard::lang_unspecified;3858if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {3859LangStd = LangStandard::getLangKind(A->getValue());3860if (LangStd == LangStandard::lang_unspecified) {3861Diags.Report(diag::err_drv_invalid_value)3862<< A->getAsString(Args) << A->getValue();3863// Report supported standards with short description.3864for (unsigned KindValue = 0;3865KindValue != LangStandard::lang_unspecified;3866++KindValue) {3867const LangStandard &Std = LangStandard::getLangStandardForKind(3868static_cast<LangStandard::Kind>(KindValue));3869if (IsInputCompatibleWithStandard(IK, Std)) {3870auto Diag = Diags.Report(diag::note_drv_use_standard);3871Diag << Std.getName() << Std.getDescription();3872unsigned NumAliases = 0;3873#define LANGSTANDARD(id, name, lang, desc, features)3874#define LANGSTANDARD_ALIAS(id, alias) \3875if (KindValue == LangStandard::lang_##id) ++NumAliases;3876#define LANGSTANDARD_ALIAS_DEPR(id, alias)3877#include "clang/Basic/LangStandards.def"3878Diag << NumAliases;3879#define LANGSTANDARD(id, name, lang, desc, features)3880#define LANGSTANDARD_ALIAS(id, alias) \3881if (KindValue == LangStandard::lang_##id) Diag << alias;3882#define LANGSTANDARD_ALIAS_DEPR(id, alias)3883#include "clang/Basic/LangStandards.def"3884}3885}3886} else {3887// Valid standard, check to make sure language and standard are3888// compatible.3889const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);3890if (!IsInputCompatibleWithStandard(IK, Std)) {3891Diags.Report(diag::err_drv_argument_not_allowed_with)3892<< A->getAsString(Args) << GetInputKindName(IK);3893}3894}3895}38963897// -cl-std only applies for OpenCL language standards.3898// Override the -std option in this case.3899if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {3900LangStandard::Kind OpenCLLangStd3901= llvm::StringSwitch<LangStandard::Kind>(A->getValue())3902.Cases("cl", "CL", LangStandard::lang_opencl10)3903.Cases("cl1.0", "CL1.0", LangStandard::lang_opencl10)3904.Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)3905.Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)3906.Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)3907.Cases("cl3.0", "CL3.0", LangStandard::lang_opencl30)3908.Cases("clc++", "CLC++", LangStandard::lang_openclcpp10)3909.Cases("clc++1.0", "CLC++1.0", LangStandard::lang_openclcpp10)3910.Cases("clc++2021", "CLC++2021", LangStandard::lang_openclcpp2021)3911.Default(LangStandard::lang_unspecified);39123913if (OpenCLLangStd == LangStandard::lang_unspecified) {3914Diags.Report(diag::err_drv_invalid_value)3915<< A->getAsString(Args) << A->getValue();3916}3917else3918LangStd = OpenCLLangStd;3919}39203921// These need to be parsed now. They are used to set OpenCL defaults.3922Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);3923Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);39243925LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);39263927// The key paths of codegen options defined in Options.td start with3928// "LangOpts->". Let's provide the expected variable name and type.3929LangOptions *LangOpts = &Opts;39303931#define LANG_OPTION_WITH_MARSHALLING(...) \3932PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)3933#include "clang/Driver/Options.inc"3934#undef LANG_OPTION_WITH_MARSHALLING39353936if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {3937StringRef Name = A->getValue();3938if (Name == "full" || Name == "branch") {3939Opts.CFProtectionBranch = 1;3940}3941}39423943if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&3944!Args.hasArg(OPT_sycl_std_EQ)) {3945// If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to3946// provide -sycl-std=, we want to default it to whatever the default SYCL3947// version is. I could not find a way to express this with the options3948// tablegen because we still want this value to be SYCL_None when the user3949// is not in device or host mode.3950Opts.setSYCLVersion(LangOptions::SYCL_Default);3951}39523953if (Opts.ObjC) {3954if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {3955StringRef value = arg->getValue();3956if (Opts.ObjCRuntime.tryParse(value))3957Diags.Report(diag::err_drv_unknown_objc_runtime) << value;3958}39593960if (Args.hasArg(OPT_fobjc_gc_only))3961Opts.setGC(LangOptions::GCOnly);3962else if (Args.hasArg(OPT_fobjc_gc))3963Opts.setGC(LangOptions::HybridGC);3964else if (Args.hasArg(OPT_fobjc_arc)) {3965Opts.ObjCAutoRefCount = 1;3966if (!Opts.ObjCRuntime.allowsARC())3967Diags.Report(diag::err_arc_unsupported_on_runtime);3968}39693970// ObjCWeakRuntime tracks whether the runtime supports __weak, not3971// whether the feature is actually enabled. This is predominantly3972// determined by -fobjc-runtime, but we allow it to be overridden3973// from the command line for testing purposes.3974if (Args.hasArg(OPT_fobjc_runtime_has_weak))3975Opts.ObjCWeakRuntime = 1;3976else3977Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();39783979// ObjCWeak determines whether __weak is actually enabled.3980// Note that we allow -fno-objc-weak to disable this even in ARC mode.3981if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {3982if (!weakArg->getOption().matches(OPT_fobjc_weak)) {3983assert(!Opts.ObjCWeak);3984} else if (Opts.getGC() != LangOptions::NonGC) {3985Diags.Report(diag::err_objc_weak_with_gc);3986} else if (!Opts.ObjCWeakRuntime) {3987Diags.Report(diag::err_objc_weak_unsupported);3988} else {3989Opts.ObjCWeak = 1;3990}3991} else if (Opts.ObjCAutoRefCount) {3992Opts.ObjCWeak = Opts.ObjCWeakRuntime;3993}39943995if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))3996Opts.ObjCSubscriptingLegacyRuntime =3997(Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);3998}39994000if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {4001// Check that the version has 1 to 3 components and the minor and patch4002// versions fit in two decimal digits.4003VersionTuple GNUCVer;4004bool Invalid = GNUCVer.tryParse(A->getValue());4005unsigned Major = GNUCVer.getMajor();4006unsigned Minor = GNUCVer.getMinor().value_or(0);4007unsigned Patch = GNUCVer.getSubminor().value_or(0);4008if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {4009Diags.Report(diag::err_drv_invalid_value)4010<< A->getAsString(Args) << A->getValue();4011}4012Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;4013}40144015if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility)))4016Opts.IgnoreXCOFFVisibility = 1;40174018if (Args.hasArg(OPT_ftrapv)) {4019Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);4020// Set the handler, if one is specified.4021Opts.OverflowHandler =4022std::string(Args.getLastArgValue(OPT_ftrapv_handler));4023}4024else if (Args.hasArg(OPT_fwrapv))4025Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);40264027Opts.MSCompatibilityVersion = 0;4028if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {4029VersionTuple VT;4030if (VT.tryParse(A->getValue()))4031Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)4032<< A->getValue();4033Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +4034VT.getMinor().value_or(0) * 100000 +4035VT.getSubminor().value_or(0);4036}40374038// Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs4039// is specified, or -std is set to a conforming mode.4040// Trigraphs are disabled by default in C++17 and C23 onwards.4041// For z/OS, trigraphs are enabled by default (without regard to the above).4042Opts.Trigraphs =4043(!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||4044T.isOSzOS();4045Opts.Trigraphs =4046Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);40474048Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL4049&& Opts.OpenCLVersion == 200);40504051Opts.ConvergentFunctions = Args.hasArg(OPT_fconvergent_functions) ||4052Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) ||4053Opts.SYCLIsDevice || Opts.HLSL;40544055Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;4056if (!Opts.NoBuiltin)4057getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);4058if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {4059if (A->getOption().matches(options::OPT_mlong_double_64))4060Opts.LongDoubleSize = 64;4061else if (A->getOption().matches(options::OPT_mlong_double_80))4062Opts.LongDoubleSize = 80;4063else if (A->getOption().matches(options::OPT_mlong_double_128))4064Opts.LongDoubleSize = 128;4065else4066Opts.LongDoubleSize = 0;4067}4068if (Opts.FastRelaxedMath || Opts.CLUnsafeMath)4069Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);40704071llvm::sort(Opts.ModuleFeatures);40724073// -mrtd option4074if (Arg *A = Args.getLastArg(OPT_mrtd)) {4075if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)4076Diags.Report(diag::err_drv_argument_not_allowed_with)4077<< A->getSpelling() << "-fdefault-calling-conv";4078else {4079switch (T.getArch()) {4080case llvm::Triple::x86:4081Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);4082break;4083case llvm::Triple::m68k:4084Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall);4085break;4086default:4087Diags.Report(diag::err_drv_argument_not_allowed_with)4088<< A->getSpelling() << T.getTriple();4089}4090}4091}40924093// Check if -fopenmp is specified and set default version to 5.0.4094Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 51 : 0;4095// Check if -fopenmp-simd is specified.4096bool IsSimdSpecified =4097Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,4098/*Default=*/false);4099Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;4100Opts.OpenMPUseTLS =4101Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);4102Opts.OpenMPIsTargetDevice =4103Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_target_device);4104Opts.OpenMPIRBuilder =4105Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder);4106bool IsTargetSpecified =4107Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ);41084109Opts.ConvergentFunctions =4110Opts.ConvergentFunctions || Opts.OpenMPIsTargetDevice;41114112if (Opts.OpenMP || Opts.OpenMPSimd) {4113if (int Version = getLastArgIntValue(4114Args, OPT_fopenmp_version_EQ,4115(IsSimdSpecified || IsTargetSpecified) ? 51 : Opts.OpenMP, Diags))4116Opts.OpenMP = Version;4117// Provide diagnostic when a given target is not expected to be an OpenMP4118// device or host.4119if (!Opts.OpenMPIsTargetDevice) {4120switch (T.getArch()) {4121default:4122break;4123// Add unsupported host targets here:4124case llvm::Triple::nvptx:4125case llvm::Triple::nvptx64:4126Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str();4127break;4128}4129}4130}41314132// Set the flag to prevent the implementation from emitting device exception4133// handling code for those requiring so.4134if ((Opts.OpenMPIsTargetDevice && (T.isNVPTX() || T.isAMDGCN())) ||4135Opts.OpenCLCPlusPlus) {41364137Opts.Exceptions = 0;4138Opts.CXXExceptions = 0;4139}4140if (Opts.OpenMPIsTargetDevice && T.isNVPTX()) {4141Opts.OpenMPCUDANumSMs =4142getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,4143Opts.OpenMPCUDANumSMs, Diags);4144Opts.OpenMPCUDABlocksPerSM =4145getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,4146Opts.OpenMPCUDABlocksPerSM, Diags);4147Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue(4148Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,4149Opts.OpenMPCUDAReductionBufNum, Diags);4150}41514152// Set the value of the debugging flag used in the new offloading device RTL.4153// Set either by a specific value or to a default if not specified.4154if (Opts.OpenMPIsTargetDevice && (Args.hasArg(OPT_fopenmp_target_debug) ||4155Args.hasArg(OPT_fopenmp_target_debug_EQ))) {4156Opts.OpenMPTargetDebug = getLastArgIntValue(4157Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags);4158if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug))4159Opts.OpenMPTargetDebug = 1;4160}41614162if (Opts.OpenMPIsTargetDevice) {4163if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription))4164Opts.OpenMPTeamSubscription = true;4165if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription))4166Opts.OpenMPThreadSubscription = true;4167}41684169// Get the OpenMP target triples if any.4170if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {4171enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };4172auto getArchPtrSize = [](const llvm::Triple &T) {4173if (T.isArch16Bit())4174return Arch16Bit;4175if (T.isArch32Bit())4176return Arch32Bit;4177assert(T.isArch64Bit() && "Expected 64-bit architecture");4178return Arch64Bit;4179};41804181for (unsigned i = 0; i < A->getNumValues(); ++i) {4182llvm::Triple TT(A->getValue(i));41834184if (TT.getArch() == llvm::Triple::UnknownArch ||4185!(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||4186TT.getArch() == llvm::Triple::systemz ||4187TT.getArch() == llvm::Triple::nvptx ||4188TT.getArch() == llvm::Triple::nvptx64 ||4189TT.getArch() == llvm::Triple::amdgcn ||4190TT.getArch() == llvm::Triple::x86 ||4191TT.getArch() == llvm::Triple::x86_64))4192Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);4193else if (getArchPtrSize(T) != getArchPtrSize(TT))4194Diags.Report(diag::err_drv_incompatible_omp_arch)4195<< A->getValue(i) << T.str();4196else4197Opts.OMPTargetTriples.push_back(TT);4198}4199}42004201// Get OpenMP host file path if any and report if a non existent file is4202// found4203if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {4204Opts.OMPHostIRFile = A->getValue();4205if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))4206Diags.Report(diag::err_drv_omp_host_ir_file_not_found)4207<< Opts.OMPHostIRFile;4208}42094210// Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options4211Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice &&4212(T.isNVPTX() || T.isAMDGCN()) &&4213Args.hasArg(options::OPT_fopenmp_cuda_mode);42144215// OpenACC Configuration.4216if (Args.hasArg(options::OPT_fopenacc)) {4217Opts.OpenACC = true;42184219if (Arg *A = Args.getLastArg(options::OPT_openacc_macro_override))4220Opts.OpenACCMacroOverride = A->getValue();4221}42224223// FIXME: Eliminate this dependency.4224unsigned Opt = getOptimizationLevel(Args, IK, Diags),4225OptSize = getOptimizationLevelSize(Args);4226Opts.Optimize = Opt != 0;4227Opts.OptimizeSize = OptSize != 0;42284229// This is the __NO_INLINE__ define, which just depends on things like the4230// optimization level and -fno-inline, not actually whether the backend has4231// inlining enabled.4232Opts.NoInlineDefine = !Opts.Optimize;4233if (Arg *InlineArg = Args.getLastArg(4234options::OPT_finline_functions, options::OPT_finline_hint_functions,4235options::OPT_fno_inline_functions, options::OPT_fno_inline))4236if (InlineArg->getOption().matches(options::OPT_fno_inline))4237Opts.NoInlineDefine = true;42384239if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {4240StringRef Val = A->getValue();4241if (Val == "fast")4242Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);4243else if (Val == "on")4244Opts.setDefaultFPContractMode(LangOptions::FPM_On);4245else if (Val == "off")4246Opts.setDefaultFPContractMode(LangOptions::FPM_Off);4247else if (Val == "fast-honor-pragmas")4248Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas);4249else4250Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;4251}42524253// Parse -fsanitize= arguments.4254parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),4255Diags, Opts.Sanitize);4256Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);4257std::vector<std::string> systemIgnorelists =4258Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);4259Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),4260systemIgnorelists.begin(),4261systemIgnorelists.end());42624263if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {4264Opts.setClangABICompat(LangOptions::ClangABI::Latest);42654266StringRef Ver = A->getValue();4267std::pair<StringRef, StringRef> VerParts = Ver.split('.');4268unsigned Major, Minor = 0;42694270// Check the version number is valid: either 3.x (0 <= x <= 9) or4271// y or y.0 (4 <= y <= current version).4272if (!VerParts.first.starts_with("0") &&4273!VerParts.first.getAsInteger(10, Major) && 3 <= Major &&4274Major <= CLANG_VERSION_MAJOR &&4275(Major == 34276? VerParts.second.size() == 1 &&4277!VerParts.second.getAsInteger(10, Minor)4278: VerParts.first.size() == Ver.size() || VerParts.second == "0")) {4279// Got a valid version number.4280if (Major == 3 && Minor <= 8)4281Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8);4282else if (Major <= 4)4283Opts.setClangABICompat(LangOptions::ClangABI::Ver4);4284else if (Major <= 6)4285Opts.setClangABICompat(LangOptions::ClangABI::Ver6);4286else if (Major <= 7)4287Opts.setClangABICompat(LangOptions::ClangABI::Ver7);4288else if (Major <= 9)4289Opts.setClangABICompat(LangOptions::ClangABI::Ver9);4290else if (Major <= 11)4291Opts.setClangABICompat(LangOptions::ClangABI::Ver11);4292else if (Major <= 12)4293Opts.setClangABICompat(LangOptions::ClangABI::Ver12);4294else if (Major <= 14)4295Opts.setClangABICompat(LangOptions::ClangABI::Ver14);4296else if (Major <= 15)4297Opts.setClangABICompat(LangOptions::ClangABI::Ver15);4298else if (Major <= 17)4299Opts.setClangABICompat(LangOptions::ClangABI::Ver17);4300else if (Major <= 18)4301Opts.setClangABICompat(LangOptions::ClangABI::Ver18);4302} else if (Ver != "latest") {4303Diags.Report(diag::err_drv_invalid_value)4304<< A->getAsString(Args) << A->getValue();4305}4306}43074308if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {4309StringRef SignScope = A->getValue();43104311if (SignScope.equals_insensitive("none"))4312Opts.setSignReturnAddressScope(4313LangOptions::SignReturnAddressScopeKind::None);4314else if (SignScope.equals_insensitive("all"))4315Opts.setSignReturnAddressScope(4316LangOptions::SignReturnAddressScopeKind::All);4317else if (SignScope.equals_insensitive("non-leaf"))4318Opts.setSignReturnAddressScope(4319LangOptions::SignReturnAddressScopeKind::NonLeaf);4320else4321Diags.Report(diag::err_drv_invalid_value)4322<< A->getAsString(Args) << SignScope;43234324if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {4325StringRef SignKey = A->getValue();4326if (!SignScope.empty() && !SignKey.empty()) {4327if (SignKey == "a_key")4328Opts.setSignReturnAddressKey(4329LangOptions::SignReturnAddressKeyKind::AKey);4330else if (SignKey == "b_key")4331Opts.setSignReturnAddressKey(4332LangOptions::SignReturnAddressKeyKind::BKey);4333else4334Diags.Report(diag::err_drv_invalid_value)4335<< A->getAsString(Args) << SignKey;4336}4337}4338}43394340// The value can be empty, which indicates the system default should be used.4341StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);4342if (!CXXABI.empty()) {4343if (!TargetCXXABI::isABI(CXXABI)) {4344Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;4345} else {4346auto Kind = TargetCXXABI::getKind(CXXABI);4347if (!TargetCXXABI::isSupportedCXXABI(T, Kind))4348Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();4349else4350Opts.CXXABI = Kind;4351}4352}43534354Opts.RelativeCXXABIVTables =4355Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,4356options::OPT_fno_experimental_relative_cxx_abi_vtables,4357TargetCXXABI::usesRelativeVTables(T));43584359// RTTI is on by default.4360bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);4361Opts.OmitVTableRTTI =4362Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti,4363options::OPT_fno_experimental_omit_vtable_rtti, false);4364if (Opts.OmitVTableRTTI && HasRTTI)4365Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti);43664367for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {4368auto Split = StringRef(A).split('=');4369Opts.MacroPrefixMap.insert(4370{std::string(Split.first), std::string(Split.second)});4371}43724373Opts.UseTargetPathSeparator =4374!Args.getLastArg(OPT_fno_file_reproducible) &&4375(Args.getLastArg(OPT_ffile_compilation_dir_EQ) ||4376Args.getLastArg(OPT_fmacro_prefix_map_EQ) ||4377Args.getLastArg(OPT_ffile_reproducible));43784379// Error if -mvscale-min is unbounded.4380if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) {4381unsigned VScaleMin;4382if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)4383Diags.Report(diag::err_cc1_unbounded_vscale_min);4384}43854386if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {4387std::ifstream SeedFile(A->getValue(0));43884389if (!SeedFile.is_open())4390Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file)4391<< A->getValue(0);43924393std::getline(SeedFile, Opts.RandstructSeed);4394}43954396if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ))4397Opts.RandstructSeed = A->getValue(0);43984399// Validate options for HLSL4400if (Opts.HLSL) {4401// TODO: Revisit restricting SPIR-V to logical once we've figured out how to4402// handle PhysicalStorageBuffer64 memory model4403if (T.isDXIL() || T.isSPIRVLogical()) {4404enum { ShaderModel, VulkanEnv, ShaderStage };4405enum { OS, Environment };44064407int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel;44084409if (T.getOSName().empty()) {4410Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)4411<< ExpectedOS << OS << T.str();4412} else if (T.getEnvironmentName().empty()) {4413Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)4414<< ShaderStage << Environment << T.str();4415} else if (!T.isShaderStageEnvironment()) {4416Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)4417<< ShaderStage << T.getEnvironmentName() << T.str();4418}44194420if (T.isDXIL()) {4421if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {4422Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)4423<< ShaderModel << T.getOSName() << T.str();4424}4425// Validate that if fnative-half-type is given, that4426// the language standard is at least hlsl2018, and that4427// the target shader model is at least 6.2.4428if (Args.getLastArg(OPT_fnative_half_type)) {4429const LangStandard &Std =4430LangStandard::getLangStandardForKind(Opts.LangStd);4431if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 &&4432T.getOSVersion() >= VersionTuple(6, 2)))4433Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)4434<< "-enable-16bit-types" << true << Std.getName()4435<< T.getOSVersion().getAsString();4436}4437} else if (T.isSPIRVLogical()) {4438if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) {4439Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)4440<< VulkanEnv << T.getOSName() << T.str();4441}4442if (Args.getLastArg(OPT_fnative_half_type)) {4443const LangStandard &Std =4444LangStandard::getLangStandardForKind(Opts.LangStd);4445if (!(Opts.LangStd >= LangStandard::lang_hlsl2018))4446Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)4447<< "-fnative-half-type" << false << Std.getName();4448}4449} else {4450llvm_unreachable("expected DXIL or SPIR-V target");4451}4452} else4453Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();4454}44554456return Diags.getNumErrors() == NumErrorsBefore;4457}44584459static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {4460switch (Action) {4461case frontend::ASTDeclList:4462case frontend::ASTDump:4463case frontend::ASTPrint:4464case frontend::ASTView:4465case frontend::EmitAssembly:4466case frontend::EmitBC:4467case frontend::EmitCIR:4468case frontend::EmitHTML:4469case frontend::EmitLLVM:4470case frontend::EmitLLVMOnly:4471case frontend::EmitCodeGenOnly:4472case frontend::EmitObj:4473case frontend::ExtractAPI:4474case frontend::FixIt:4475case frontend::GenerateModule:4476case frontend::GenerateModuleInterface:4477case frontend::GenerateReducedModuleInterface:4478case frontend::GenerateHeaderUnit:4479case frontend::GeneratePCH:4480case frontend::GenerateInterfaceStubs:4481case frontend::ParseSyntaxOnly:4482case frontend::ModuleFileInfo:4483case frontend::VerifyPCH:4484case frontend::PluginAction:4485case frontend::RewriteObjC:4486case frontend::RewriteTest:4487case frontend::RunAnalysis:4488case frontend::TemplightDump:4489case frontend::MigrateSource:4490return false;44914492case frontend::DumpCompilerOptions:4493case frontend::DumpRawTokens:4494case frontend::DumpTokens:4495case frontend::InitOnly:4496case frontend::PrintPreamble:4497case frontend::PrintPreprocessedInput:4498case frontend::RewriteMacros:4499case frontend::RunPreprocessorOnly:4500case frontend::PrintDependencyDirectivesSourceMinimizerOutput:4501return true;4502}4503llvm_unreachable("invalid frontend action");4504}45054506static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts,4507ArgumentConsumer Consumer,4508const LangOptions &LangOpts,4509const FrontendOptions &FrontendOpts,4510const CodeGenOptions &CodeGenOpts) {4511const PreprocessorOptions *PreprocessorOpts = &Opts;45124513#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \4514GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)4515#include "clang/Driver/Options.inc"4516#undef PREPROCESSOR_OPTION_WITH_MARSHALLING45174518if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)4519GenerateArg(Consumer, OPT_pch_through_hdrstop_use);45204521for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)4522GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D);45234524if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))4525GenerateArg(Consumer, OPT_preamble_bytes_EQ,4526Twine(Opts.PrecompiledPreambleBytes.first) + "," +4527(Opts.PrecompiledPreambleBytes.second ? "1" : "0"));45284529for (const auto &M : Opts.Macros) {4530// Don't generate __CET__ macro definitions. They are implied by the4531// -fcf-protection option that is generated elsewhere.4532if (M.first == "__CET__=1" && !M.second &&4533!CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)4534continue;4535if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&4536!CodeGenOpts.CFProtectionBranch)4537continue;4538if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&4539CodeGenOpts.CFProtectionBranch)4540continue;45414542GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first);4543}45444545for (const auto &I : Opts.Includes) {4546// Don't generate OpenCL includes. They are implied by other flags that are4547// generated elsewhere.4548if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&4549((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||4550I == "opencl-c.h"))4551continue;4552// Don't generate HLSL includes. They are implied by other flags that are4553// generated elsewhere.4554if (LangOpts.HLSL && I == "hlsl.h")4555continue;45564557GenerateArg(Consumer, OPT_include, I);4558}45594560for (const auto &CI : Opts.ChainedIncludes)4561GenerateArg(Consumer, OPT_chain_include, CI);45624563for (const auto &RF : Opts.RemappedFiles)4564GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second);45654566if (Opts.SourceDateEpoch)4567GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch));45684569if (Opts.DefineTargetOSMacros)4570GenerateArg(Consumer, OPT_fdefine_target_os_macros);45714572for (const auto &EmbedEntry : Opts.EmbedEntries)4573GenerateArg(Consumer, OPT_embed_dir_EQ, EmbedEntry);45744575// Don't handle LexEditorPlaceholders. It is implied by the action that is4576// generated elsewhere.4577}45784579static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,4580DiagnosticsEngine &Diags,4581frontend::ActionKind Action,4582const FrontendOptions &FrontendOpts) {4583unsigned NumErrorsBefore = Diags.getNumErrors();45844585PreprocessorOptions *PreprocessorOpts = &Opts;45864587#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...) \4588PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)4589#include "clang/Driver/Options.inc"4590#undef PREPROCESSOR_OPTION_WITH_MARSHALLING45914592Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||4593Args.hasArg(OPT_pch_through_hdrstop_use);45944595for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))4596Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());45974598if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {4599StringRef Value(A->getValue());4600size_t Comma = Value.find(',');4601unsigned Bytes = 0;4602unsigned EndOfLine = 0;46034604if (Comma == StringRef::npos ||4605Value.substr(0, Comma).getAsInteger(10, Bytes) ||4606Value.substr(Comma + 1).getAsInteger(10, EndOfLine))4607Diags.Report(diag::err_drv_preamble_format);4608else {4609Opts.PrecompiledPreambleBytes.first = Bytes;4610Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);4611}4612}46134614// Add the __CET__ macro if a CFProtection option is set.4615if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {4616StringRef Name = A->getValue();4617if (Name == "branch")4618Opts.addMacroDef("__CET__=1");4619else if (Name == "return")4620Opts.addMacroDef("__CET__=2");4621else if (Name == "full")4622Opts.addMacroDef("__CET__=3");4623}46244625// Add macros from the command line.4626for (const auto *A : Args.filtered(OPT_D, OPT_U)) {4627if (A->getOption().matches(OPT_D))4628Opts.addMacroDef(A->getValue());4629else4630Opts.addMacroUndef(A->getValue());4631}46324633// Add the ordered list of -includes.4634for (const auto *A : Args.filtered(OPT_include))4635Opts.Includes.emplace_back(A->getValue());46364637for (const auto *A : Args.filtered(OPT_chain_include))4638Opts.ChainedIncludes.emplace_back(A->getValue());46394640for (const auto *A : Args.filtered(OPT_remap_file)) {4641std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');46424643if (Split.second.empty()) {4644Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);4645continue;4646}46474648Opts.addRemappedFile(Split.first, Split.second);4649}46504651if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) {4652StringRef Epoch = A->getValue();4653// SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer.4654// On time64 systems, pick 253402300799 (the UNIX timestamp of4655// 9999-12-31T23:59:59Z) as the upper bound.4656const uint64_t MaxTimestamp =4657std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799);4658uint64_t V;4659if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) {4660Diags.Report(diag::err_fe_invalid_source_date_epoch)4661<< Epoch << MaxTimestamp;4662} else {4663Opts.SourceDateEpoch = V;4664}4665}46664667for (const auto *A : Args.filtered(OPT_embed_dir_EQ)) {4668StringRef Val = A->getValue();4669Opts.EmbedEntries.push_back(std::string(Val));4670}46714672// Always avoid lexing editor placeholders when we're just running the4673// preprocessor as we never want to emit the4674// "editor placeholder in source file" error in PP only mode.4675if (isStrictlyPreprocessorAction(Action))4676Opts.LexEditorPlaceholders = false;46774678Opts.DefineTargetOSMacros =4679Args.hasFlag(OPT_fdefine_target_os_macros,4680OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros);46814682return Diags.getNumErrors() == NumErrorsBefore;4683}46844685static void4686GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts,4687ArgumentConsumer Consumer,4688frontend::ActionKind Action) {4689const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;46904691#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \4692GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)4693#include "clang/Driver/Options.inc"4694#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING46954696bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;4697if (Generate_dM)4698GenerateArg(Consumer, OPT_dM);4699if (!Generate_dM && Opts.ShowMacros)4700GenerateArg(Consumer, OPT_dD);4701if (Opts.DirectivesOnly)4702GenerateArg(Consumer, OPT_fdirectives_only);4703}47044705static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,4706ArgList &Args, DiagnosticsEngine &Diags,4707frontend::ActionKind Action) {4708unsigned NumErrorsBefore = Diags.getNumErrors();47094710PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;47114712#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...) \4713PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)4714#include "clang/Driver/Options.inc"4715#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING47164717Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);4718Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);4719Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);47204721return Diags.getNumErrors() == NumErrorsBefore;4722}47234724static void GenerateTargetArgs(const TargetOptions &Opts,4725ArgumentConsumer Consumer) {4726const TargetOptions *TargetOpts = &Opts;4727#define TARGET_OPTION_WITH_MARSHALLING(...) \4728GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)4729#include "clang/Driver/Options.inc"4730#undef TARGET_OPTION_WITH_MARSHALLING47314732if (!Opts.SDKVersion.empty())4733GenerateArg(Consumer, OPT_target_sdk_version_EQ,4734Opts.SDKVersion.getAsString());4735if (!Opts.DarwinTargetVariantSDKVersion.empty())4736GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ,4737Opts.DarwinTargetVariantSDKVersion.getAsString());4738}47394740static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,4741DiagnosticsEngine &Diags) {4742unsigned NumErrorsBefore = Diags.getNumErrors();47434744TargetOptions *TargetOpts = &Opts;47454746#define TARGET_OPTION_WITH_MARSHALLING(...) \4747PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)4748#include "clang/Driver/Options.inc"4749#undef TARGET_OPTION_WITH_MARSHALLING47504751if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {4752llvm::VersionTuple Version;4753if (Version.tryParse(A->getValue()))4754Diags.Report(diag::err_drv_invalid_value)4755<< A->getAsString(Args) << A->getValue();4756else4757Opts.SDKVersion = Version;4758}4759if (Arg *A =4760Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) {4761llvm::VersionTuple Version;4762if (Version.tryParse(A->getValue()))4763Diags.Report(diag::err_drv_invalid_value)4764<< A->getAsString(Args) << A->getValue();4765else4766Opts.DarwinTargetVariantSDKVersion = Version;4767}47684769return Diags.getNumErrors() == NumErrorsBefore;4770}47714772bool CompilerInvocation::CreateFromArgsImpl(4773CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,4774DiagnosticsEngine &Diags, const char *Argv0) {4775unsigned NumErrorsBefore = Diags.getNumErrors();47764777// Parse the arguments.4778const OptTable &Opts = getDriverOptTable();4779llvm::opt::Visibility VisibilityMask(options::CC1Option);4780unsigned MissingArgIndex, MissingArgCount;4781InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,4782MissingArgCount, VisibilityMask);4783LangOptions &LangOpts = Res.getLangOpts();47844785// Check for missing argument error.4786if (MissingArgCount)4787Diags.Report(diag::err_drv_missing_argument)4788<< Args.getArgString(MissingArgIndex) << MissingArgCount;47894790// Issue errors on unknown arguments.4791for (const auto *A : Args.filtered(OPT_UNKNOWN)) {4792auto ArgString = A->getAsString(Args);4793std::string Nearest;4794if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)4795Diags.Report(diag::err_drv_unknown_argument) << ArgString;4796else4797Diags.Report(diag::err_drv_unknown_argument_with_suggestion)4798<< ArgString << Nearest;4799}48004801ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);4802ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);4803ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags);4804ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,4805/*DefaultDiagColor=*/false);4806ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);4807// FIXME: We shouldn't have to pass the DashX option around here4808InputKind DashX = Res.getFrontendOpts().DashX;4809ParseTargetArgs(Res.getTargetOpts(), Args, Diags);4810llvm::Triple T(Res.getTargetOpts().Triple);4811ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags,4812Res.getFileSystemOpts().WorkingDir);4813ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);48144815ParsePointerAuthArgs(LangOpts, Args, Diags);48164817ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,4818Diags);4819if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)4820LangOpts.ObjCExceptions = 1;48214822for (auto Warning : Res.getDiagnosticOpts().Warnings) {4823if (Warning == "misexpect" &&4824!Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {4825Res.getCodeGenOpts().MisExpect = true;4826}4827}48284829if (LangOpts.CUDA) {4830// During CUDA device-side compilation, the aux triple is the4831// triple used for host compilation.4832if (LangOpts.CUDAIsDevice)4833Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;4834}48354836// Set the triple of the host for OpenMP device compile.4837if (LangOpts.OpenMPIsTargetDevice)4838Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;48394840ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,4841Res.getFrontendOpts().OutputFile, LangOpts);48424843// FIXME: Override value name discarding when asan or msan is used because the4844// backend passes depend on the name of the alloca in order to print out4845// names.4846Res.getCodeGenOpts().DiscardValueNames &=4847!LangOpts.Sanitize.has(SanitizerKind::Address) &&4848!LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&4849!LangOpts.Sanitize.has(SanitizerKind::Memory) &&4850!LangOpts.Sanitize.has(SanitizerKind::KernelMemory);48514852ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,4853Res.getFrontendOpts().ProgramAction,4854Res.getFrontendOpts());4855ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Diags,4856Res.getFrontendOpts().ProgramAction);48574858ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args, Diags,4859Res.getFrontendOpts().ProgramAction,4860Res.getPreprocessorOutputOpts().ShowLineMarkers);4861if (!Res.getDependencyOutputOpts().OutputFile.empty() &&4862Res.getDependencyOutputOpts().Targets.empty())4863Diags.Report(diag::err_fe_dependency_file_requires_MT);48644865// If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.4866if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&4867!Res.getLangOpts().Sanitize.empty()) {4868Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;4869Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);4870}48714872// Store the command-line for using in the CodeView backend.4873if (Res.getCodeGenOpts().CodeViewCommandLine) {4874Res.getCodeGenOpts().Argv0 = Argv0;4875append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);4876}48774878// Set PGOOptions. Need to create a temporary VFS to read the profile4879// to determine the PGO type.4880if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty()) {4881auto FS =4882createVFSFromOverlayFiles(Res.getHeaderSearchOpts().VFSOverlayFiles,4883Diags, llvm::vfs::getRealFileSystem());4884setPGOUseInstrumentor(Res.getCodeGenOpts(),4885Res.getCodeGenOpts().ProfileInstrumentUsePath, *FS,4886Diags);4887}48884889FixupInvocation(Res, Diags, Args, DashX);48904891return Diags.getNumErrors() == NumErrorsBefore;4892}48934894bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation,4895ArrayRef<const char *> CommandLineArgs,4896DiagnosticsEngine &Diags,4897const char *Argv0) {4898CompilerInvocation DummyInvocation;48994900return RoundTrip(4901[](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,4902DiagnosticsEngine &Diags, const char *Argv0) {4903return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);4904},4905[](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,4906StringAllocator SA) {4907Args.push_back("-cc1");4908Invocation.generateCC1CommandLine(Args, SA);4909},4910Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);4911}49124913std::string CompilerInvocation::getModuleHash() const {4914// FIXME: Consider using SHA1 instead of MD5.4915llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder;49164917// Note: For QoI reasons, the things we use as a hash here should all be4918// dumped via the -module-info flag.49194920// Start the signature with the compiler version.4921HBuilder.add(getClangFullRepositoryVersion());49224923// Also include the serialization version, in case LLVM_APPEND_VC_REV is off4924// and getClangFullRepositoryVersion() doesn't include git revision.4925HBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);49264927// Extend the signature with the language options4928#define LANGOPT(Name, Bits, Default, Description) HBuilder.add(LangOpts->Name);4929#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \4930HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));4931#define BENIGN_LANGOPT(Name, Bits, Default, Description)4932#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)4933#include "clang/Basic/LangOptions.def"49344935HBuilder.addRange(getLangOpts().ModuleFeatures);49364937HBuilder.add(getLangOpts().ObjCRuntime);4938HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames);49394940// Extend the signature with the target options.4941HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU,4942getTargetOpts().TuneCPU, getTargetOpts().ABI);4943HBuilder.addRange(getTargetOpts().FeaturesAsWritten);49444945// Extend the signature with preprocessor options.4946const PreprocessorOptions &ppOpts = getPreprocessorOpts();4947HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord);49484949const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();4950for (const auto &Macro : getPreprocessorOpts().Macros) {4951// If we're supposed to ignore this macro for the purposes of modules,4952// don't put it into the hash.4953if (!hsOpts.ModulesIgnoreMacros.empty()) {4954// Check whether we're ignoring this macro.4955StringRef MacroDef = Macro.first;4956if (hsOpts.ModulesIgnoreMacros.count(4957llvm::CachedHashString(MacroDef.split('=').first)))4958continue;4959}49604961HBuilder.add(Macro);4962}49634964// Extend the signature with the sysroot and other header search options.4965HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo,4966hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes,4967hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx,4968hsOpts.ModulesValidateDiagnosticOptions);4969HBuilder.add(hsOpts.ResourceDir);49704971if (hsOpts.ModulesStrictContextHash) {4972HBuilder.addRange(hsOpts.SystemHeaderPrefixes);4973HBuilder.addRange(hsOpts.UserEntries);4974HBuilder.addRange(hsOpts.VFSOverlayFiles);49754976const DiagnosticOptions &diagOpts = getDiagnosticOpts();4977#define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name);4978#define ENUM_DIAGOPT(Name, Type, Bits, Default) \4979HBuilder.add(diagOpts.get##Name());4980#include "clang/Basic/DiagnosticOptions.def"4981#undef DIAGOPT4982#undef ENUM_DIAGOPT4983}49844985// Extend the signature with the user build path.4986HBuilder.add(hsOpts.ModuleUserBuildPath);49874988// Extend the signature with the module file extensions.4989for (const auto &ext : getFrontendOpts().ModuleFileExtensions)4990ext->hashExtension(HBuilder);49914992// Extend the signature with the Swift version for API notes.4993const APINotesOptions &APINotesOpts = getAPINotesOpts();4994if (!APINotesOpts.SwiftVersion.empty()) {4995HBuilder.add(APINotesOpts.SwiftVersion.getMajor());4996if (auto Minor = APINotesOpts.SwiftVersion.getMinor())4997HBuilder.add(*Minor);4998if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor())4999HBuilder.add(*Subminor);5000if (auto Build = APINotesOpts.SwiftVersion.getBuild())5001HBuilder.add(*Build);5002}50035004// When compiling with -gmodules, also hash -fdebug-prefix-map as it5005// affects the debug info in the PCM.5006if (getCodeGenOpts().DebugTypeExtRefs)5007HBuilder.addRange(getCodeGenOpts().DebugPrefixMap);50085009// Extend the signature with the affecting debug options.5010if (getHeaderSearchOpts().ModuleFormat == "obj") {5011#define DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name);5012#define VALUE_DEBUGOPT(Name, Bits, Default) HBuilder.add(CodeGenOpts->Name);5013#define ENUM_DEBUGOPT(Name, Type, Bits, Default) \5014HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));5015#define BENIGN_DEBUGOPT(Name, Bits, Default)5016#define BENIGN_VALUE_DEBUGOPT(Name, Bits, Default)5017#define BENIGN_ENUM_DEBUGOPT(Name, Type, Bits, Default)5018#include "clang/Basic/DebugOptions.def"5019}50205021// Extend the signature with the enabled sanitizers, if at least one is5022// enabled. Sanitizers which cannot affect AST generation aren't hashed.5023SanitizerSet SanHash = getLangOpts().Sanitize;5024SanHash.clear(getPPTransparentSanitizers());5025if (!SanHash.empty())5026HBuilder.add(SanHash.Mask);50275028llvm::MD5::MD5Result Result;5029HBuilder.getHasher().final(Result);5030uint64_t Hash = Result.high() ^ Result.low();5031return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);5032}50335034void CompilerInvocationBase::generateCC1CommandLine(5035ArgumentConsumer Consumer) const {5036llvm::Triple T(getTargetOpts().Triple);50375038GenerateFileSystemArgs(getFileSystemOpts(), Consumer);5039GenerateMigratorArgs(getMigratorOpts(), Consumer);5040GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer);5041GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer,5042/*DefaultDiagColor=*/false);5043GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile);5044GenerateTargetArgs(getTargetOpts(), Consumer);5045GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer);5046GenerateAPINotesArgs(getAPINotesOpts(), Consumer);5047GeneratePointerAuthArgs(getLangOpts(), Consumer);5048GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);5049GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,5050getFrontendOpts().OutputFile, &getLangOpts());5051GeneratePreprocessorArgs(getPreprocessorOpts(), Consumer, getLangOpts(),5052getFrontendOpts(), getCodeGenOpts());5053GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer,5054getFrontendOpts().ProgramAction);5055GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer);5056}50575058std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {5059std::vector<std::string> Args{"-cc1"};5060generateCC1CommandLine(5061[&Args](const Twine &Arg) { Args.push_back(Arg.str()); });5062return Args;5063}50645065void CompilerInvocation::resetNonModularOptions() {5066getLangOpts().resetNonModularOptions();5067getPreprocessorOpts().resetNonModularOptions();5068getCodeGenOpts().resetNonModularOptions(getHeaderSearchOpts().ModuleFormat);5069}50705071void CompilerInvocation::clearImplicitModuleBuildOptions() {5072getLangOpts().ImplicitModules = false;5073getHeaderSearchOpts().ImplicitModuleMaps = false;5074getHeaderSearchOpts().ModuleCachePath.clear();5075getHeaderSearchOpts().ModulesValidateOncePerBuildSession = false;5076getHeaderSearchOpts().BuildSessionTimestamp = 0;5077// The specific values we canonicalize to for pruning don't affect behaviour,5078/// so use the default values so they may be dropped from the command-line.5079getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60;5080getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60;5081}50825083IntrusiveRefCntPtr<llvm::vfs::FileSystem>5084clang::createVFSFromCompilerInvocation(const CompilerInvocation &CI,5085DiagnosticsEngine &Diags) {5086return createVFSFromCompilerInvocation(CI, Diags,5087llvm::vfs::getRealFileSystem());5088}50895090IntrusiveRefCntPtr<llvm::vfs::FileSystem>5091clang::createVFSFromCompilerInvocation(5092const CompilerInvocation &CI, DiagnosticsEngine &Diags,5093IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {5094return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles,5095Diags, std::move(BaseFS));5096}50975098IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles(5099ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,5100IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {5101if (VFSOverlayFiles.empty())5102return BaseFS;51035104IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS;5105// earlier vfs files are on the bottom5106for (const auto &File : VFSOverlayFiles) {5107llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =5108Result->getBufferForFile(File);5109if (!Buffer) {5110Diags.Report(diag::err_missing_vfs_overlay_file) << File;5111continue;5112}51135114IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(5115std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,5116/*DiagContext*/ nullptr, Result);5117if (!FS) {5118Diags.Report(diag::err_invalid_vfs_overlay) << File;5119continue;5120}51215122Result = FS;5123}5124return Result;5125}512651275128