brintos

brintos / llvm-project-archived public Read only

0
0
Text · 210.8 KiB · d2a5ed6 Raw
5430 lines · cpp
1//===- CompilerInvocation.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Frontend/CompilerInvocation.h"10#include "TestModuleFileExtension.h"11#include "clang/Basic/Builtins.h"12#include "clang/Basic/CharInfo.h"13#include "clang/Basic/CodeGenOptions.h"14#include "clang/Basic/CommentOptions.h"15#include "clang/Basic/Diagnostic.h"16#include "clang/Basic/DiagnosticDriver.h"17#include "clang/Basic/DiagnosticFrontend.h"18#include "clang/Basic/DiagnosticOptions.h"19#include "clang/Basic/FileSystemOptions.h"20#include "clang/Basic/LLVM.h"21#include "clang/Basic/LangOptions.h"22#include "clang/Basic/LangStandard.h"23#include "clang/Basic/ObjCRuntime.h"24#include "clang/Basic/Sanitizers.h"25#include "clang/Basic/SourceLocation.h"26#include "clang/Basic/TargetOptions.h"27#include "clang/Basic/Version.h"28#include "clang/Basic/XRayInstr.h"29#include "clang/Config/config.h"30#include "clang/Frontend/CommandLineSourceLoc.h"31#include "clang/Frontend/DependencyOutputOptions.h"32#include "clang/Frontend/FrontendOptions.h"33#include "clang/Frontend/MigratorOptions.h"34#include "clang/Frontend/PreprocessorOutputOptions.h"35#include "clang/Frontend/TextDiagnosticBuffer.h"36#include "clang/Frontend/Utils.h"37#include "clang/Lex/HeaderSearchOptions.h"38#include "clang/Lex/PreprocessorOptions.h"39#include "clang/Options/Options.h"40#include "clang/Serialization/ASTBitCodes.h"41#include "clang/Serialization/ModuleFileExtension.h"42#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"43#include "llvm/ADT/APInt.h"44#include "llvm/ADT/ArrayRef.h"45#include "llvm/ADT/CachedHashString.h"46#include "llvm/ADT/FloatingPointMode.h"47#include "llvm/ADT/STLExtras.h"48#include "llvm/ADT/SmallVector.h"49#include "llvm/ADT/StringRef.h"50#include "llvm/ADT/StringSwitch.h"51#include "llvm/ADT/Twine.h"52#include "llvm/Config/llvm-config.h"53#include "llvm/Frontend/Debug/Options.h"54#include "llvm/IR/DebugInfoMetadata.h"55#include "llvm/Linker/Linker.h"56#include "llvm/MC/MCTargetOptions.h"57#include "llvm/Option/Arg.h"58#include "llvm/Option/ArgList.h"59#include "llvm/Option/OptSpecifier.h"60#include "llvm/Option/OptTable.h"61#include "llvm/Option/Option.h"62#include "llvm/ProfileData/InstrProfReader.h"63#include "llvm/Remarks/HotnessThresholdParser.h"64#include "llvm/Support/CodeGen.h"65#include "llvm/Support/Compiler.h"66#include "llvm/Support/Error.h"67#include "llvm/Support/ErrorHandling.h"68#include "llvm/Support/ErrorOr.h"69#include "llvm/Support/FileSystem.h"70#include "llvm/Support/HashBuilder.h"71#include "llvm/Support/MathExtras.h"72#include "llvm/Support/MemoryBuffer.h"73#include "llvm/Support/Path.h"74#include "llvm/Support/Process.h"75#include "llvm/Support/Regex.h"76#include "llvm/Support/VersionTuple.h"77#include "llvm/Support/VirtualFileSystem.h"78#include "llvm/Support/raw_ostream.h"79#include "llvm/Target/TargetOptions.h"80#include "llvm/TargetParser/Host.h"81#include "llvm/TargetParser/Triple.h"82#include <algorithm>83#include <cassert>84#include <cstddef>85#include <cstring>86#include <ctime>87#include <fstream>88#include <limits>89#include <memory>90#include <optional>91#include <string>92#include <tuple>93#include <type_traits>94#include <utility>95#include <vector>96 97using namespace clang;98using namespace options;99using namespace llvm::opt;100 101//===----------------------------------------------------------------------===//102// Helpers.103//===----------------------------------------------------------------------===//104 105// Parse misexpect tolerance argument value.106// Valid option values are integers in the range [0, 100)107static Expected<std::optional<uint32_t>> parseToleranceOption(StringRef Arg) {108  uint32_t Val;109  if (Arg.getAsInteger(10, Val))110    return llvm::createStringError(llvm::inconvertibleErrorCode(),111                                   "Not an integer: %s", Arg.data());112  return Val;113}114 115//===----------------------------------------------------------------------===//116// Initialization.117//===----------------------------------------------------------------------===//118 119template <class T> std::shared_ptr<T> make_shared_copy(const T &X) {120  return std::make_shared<T>(X);121}122 123CompilerInvocationBase::CompilerInvocationBase()124    : LangOpts(std::make_shared<LangOptions>()),125      TargetOpts(std::make_shared<TargetOptions>()),126      DiagnosticOpts(std::make_shared<DiagnosticOptions>()),127      HSOpts(std::make_shared<HeaderSearchOptions>()),128      PPOpts(std::make_shared<PreprocessorOptions>()),129      AnalyzerOpts(std::make_shared<AnalyzerOptions>()),130      MigratorOpts(std::make_shared<MigratorOptions>()),131      APINotesOpts(std::make_shared<APINotesOptions>()),132      CodeGenOpts(std::make_shared<CodeGenOptions>()),133      FSOpts(std::make_shared<FileSystemOptions>()),134      FrontendOpts(std::make_shared<FrontendOptions>()),135      DependencyOutputOpts(std::make_shared<DependencyOutputOptions>()),136      PreprocessorOutputOpts(std::make_shared<PreprocessorOutputOptions>()) {}137 138CompilerInvocationBase &139CompilerInvocationBase::deep_copy_assign(const CompilerInvocationBase &X) {140  if (this != &X) {141    LangOpts = make_shared_copy(X.getLangOpts());142    TargetOpts = make_shared_copy(X.getTargetOpts());143    DiagnosticOpts = make_shared_copy(X.getDiagnosticOpts());144    HSOpts = make_shared_copy(X.getHeaderSearchOpts());145    PPOpts = make_shared_copy(X.getPreprocessorOpts());146    AnalyzerOpts = make_shared_copy(X.getAnalyzerOpts());147    MigratorOpts = make_shared_copy(X.getMigratorOpts());148    APINotesOpts = make_shared_copy(X.getAPINotesOpts());149    CodeGenOpts = make_shared_copy(X.getCodeGenOpts());150    FSOpts = make_shared_copy(X.getFileSystemOpts());151    FrontendOpts = make_shared_copy(X.getFrontendOpts());152    DependencyOutputOpts = make_shared_copy(X.getDependencyOutputOpts());153    PreprocessorOutputOpts = make_shared_copy(X.getPreprocessorOutputOpts());154  }155  return *this;156}157 158CompilerInvocationBase &159CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) {160  if (this != &X) {161    LangOpts = X.LangOpts;162    TargetOpts = X.TargetOpts;163    DiagnosticOpts = X.DiagnosticOpts;164    HSOpts = X.HSOpts;165    PPOpts = X.PPOpts;166    AnalyzerOpts = X.AnalyzerOpts;167    MigratorOpts = X.MigratorOpts;168    APINotesOpts = X.APINotesOpts;169    CodeGenOpts = X.CodeGenOpts;170    FSOpts = X.FSOpts;171    FrontendOpts = X.FrontendOpts;172    DependencyOutputOpts = X.DependencyOutputOpts;173    PreprocessorOutputOpts = X.PreprocessorOutputOpts;174  }175  return *this;176}177 178CompilerInvocation::CompilerInvocation(const CowCompilerInvocation &X)179    : CompilerInvocationBase(EmptyConstructor{}) {180  CompilerInvocationBase::deep_copy_assign(X);181}182 183CompilerInvocation &184CompilerInvocation::operator=(const CowCompilerInvocation &X) {185  CompilerInvocationBase::deep_copy_assign(X);186  return *this;187}188 189template <typename T>190T &ensureOwned(std::shared_ptr<T> &Storage) {191  if (Storage.use_count() > 1)192    Storage = std::make_shared<T>(*Storage);193  return *Storage;194}195 196LangOptions &CowCompilerInvocation::getMutLangOpts() {197  return ensureOwned(LangOpts);198}199 200TargetOptions &CowCompilerInvocation::getMutTargetOpts() {201  return ensureOwned(TargetOpts);202}203 204DiagnosticOptions &CowCompilerInvocation::getMutDiagnosticOpts() {205  return ensureOwned(DiagnosticOpts);206}207 208HeaderSearchOptions &CowCompilerInvocation::getMutHeaderSearchOpts() {209  return ensureOwned(HSOpts);210}211 212PreprocessorOptions &CowCompilerInvocation::getMutPreprocessorOpts() {213  return ensureOwned(PPOpts);214}215 216AnalyzerOptions &CowCompilerInvocation::getMutAnalyzerOpts() {217  return ensureOwned(AnalyzerOpts);218}219 220MigratorOptions &CowCompilerInvocation::getMutMigratorOpts() {221  return ensureOwned(MigratorOpts);222}223 224APINotesOptions &CowCompilerInvocation::getMutAPINotesOpts() {225  return ensureOwned(APINotesOpts);226}227 228CodeGenOptions &CowCompilerInvocation::getMutCodeGenOpts() {229  return ensureOwned(CodeGenOpts);230}231 232FileSystemOptions &CowCompilerInvocation::getMutFileSystemOpts() {233  return ensureOwned(FSOpts);234}235 236FrontendOptions &CowCompilerInvocation::getMutFrontendOpts() {237  return ensureOwned(FrontendOpts);238}239 240DependencyOutputOptions &CowCompilerInvocation::getMutDependencyOutputOpts() {241  return ensureOwned(DependencyOutputOpts);242}243 244PreprocessorOutputOptions &245CowCompilerInvocation::getMutPreprocessorOutputOpts() {246  return ensureOwned(PreprocessorOutputOpts);247}248 249//===----------------------------------------------------------------------===//250// Normalizers251//===----------------------------------------------------------------------===//252 253using ArgumentConsumer = CompilerInvocation::ArgumentConsumer;254 255#define OPTTABLE_STR_TABLE_CODE256#include "clang/Options/Options.inc"257#undef OPTTABLE_STR_TABLE_CODE258 259static llvm::StringRef lookupStrInTable(unsigned Offset) {260  return OptionStrTable[Offset];261}262 263#define SIMPLE_ENUM_VALUE_TABLE264#include "clang/Options/Options.inc"265#undef SIMPLE_ENUM_VALUE_TABLE266 267static std::optional<bool> normalizeSimpleFlag(OptSpecifier Opt,268                                               unsigned TableIndex,269                                               const ArgList &Args,270                                               DiagnosticsEngine &Diags) {271  if (Args.hasArg(Opt))272    return true;273  return std::nullopt;274}275 276static std::optional<bool> normalizeSimpleNegativeFlag(OptSpecifier Opt,277                                                       unsigned,278                                                       const ArgList &Args,279                                                       DiagnosticsEngine &) {280  if (Args.hasArg(Opt))281    return false;282  return std::nullopt;283}284 285/// The tblgen-erated code passes in a fifth parameter of an arbitrary type, but286/// denormalizeSimpleFlags never looks at it. Avoid bloating compile-time with287/// unnecessary template instantiations and just ignore it with a variadic288/// argument.289static void denormalizeSimpleFlag(ArgumentConsumer Consumer,290                                  unsigned SpellingOffset, Option::OptionClass,291                                  unsigned, /*T*/...) {292  Consumer(lookupStrInTable(SpellingOffset));293}294static void denormalizeSimpleFlag(ArgumentConsumer Consumer,295                                  const Twine &Spelling, Option::OptionClass,296                                  unsigned, /*T*/...) {297  Consumer(Spelling);298}299 300template <typename T> static constexpr bool is_uint64_t_convertible() {301  return !std::is_same_v<T, uint64_t> && llvm::is_integral_or_enum<T>::value;302}303 304template <typename T,305          std::enable_if_t<!is_uint64_t_convertible<T>(), bool> = false>306static auto makeFlagToValueNormalizer(T Value) {307  return [Value](OptSpecifier Opt, unsigned, const ArgList &Args,308                 DiagnosticsEngine &) -> std::optional<T> {309    if (Args.hasArg(Opt))310      return Value;311    return std::nullopt;312  };313}314 315template <typename T,316          std::enable_if_t<is_uint64_t_convertible<T>(), bool> = false>317static auto makeFlagToValueNormalizer(T Value) {318  return makeFlagToValueNormalizer(uint64_t(Value));319}320 321static auto makeBooleanOptionNormalizer(bool Value, bool OtherValue,322                                        OptSpecifier OtherOpt) {323  return [Value, OtherValue,324          OtherOpt](OptSpecifier Opt, unsigned, const ArgList &Args,325                    DiagnosticsEngine &) -> std::optional<bool> {326    if (const Arg *A = Args.getLastArg(Opt, OtherOpt)) {327      return A->getOption().matches(Opt) ? Value : OtherValue;328    }329    return std::nullopt;330  };331}332 333static auto makeBooleanOptionDenormalizer(bool Value) {334  return [Value](ArgumentConsumer Consumer, unsigned SpellingOffset,335                 Option::OptionClass, unsigned, bool KeyPath) {336    if (KeyPath == Value)337      Consumer(lookupStrInTable(SpellingOffset));338  };339}340 341static void denormalizeStringImpl(ArgumentConsumer Consumer,342                                  const Twine &Spelling,343                                  Option::OptionClass OptClass, unsigned,344                                  const Twine &Value) {345  switch (OptClass) {346  case Option::SeparateClass:347  case Option::JoinedOrSeparateClass:348  case Option::JoinedAndSeparateClass:349    Consumer(Spelling);350    Consumer(Value);351    break;352  case Option::JoinedClass:353  case Option::CommaJoinedClass:354    Consumer(Spelling + Value);355    break;356  default:357    llvm_unreachable("Cannot denormalize an option with option class "358                     "incompatible with string denormalization.");359  }360}361 362template <typename T>363static void364denormalizeString(ArgumentConsumer Consumer, unsigned SpellingOffset,365                  Option::OptionClass OptClass, unsigned TableIndex, T Value) {366  denormalizeStringImpl(Consumer, lookupStrInTable(SpellingOffset), OptClass,367                        TableIndex, Twine(Value));368}369 370template <typename T>371static void denormalizeString(ArgumentConsumer Consumer, const Twine &Spelling,372                              Option::OptionClass OptClass, unsigned TableIndex,373                              T Value) {374  denormalizeStringImpl(Consumer, Spelling, OptClass, TableIndex, Twine(Value));375}376 377static std::optional<SimpleEnumValue>378findValueTableByName(const SimpleEnumValueTable &Table, StringRef Name) {379  for (int I = 0, E = Table.Size; I != E; ++I)380    if (Name == Table.Table[I].Name)381      return Table.Table[I];382 383  return std::nullopt;384}385 386static std::optional<SimpleEnumValue>387findValueTableByValue(const SimpleEnumValueTable &Table, unsigned Value) {388  for (int I = 0, E = Table.Size; I != E; ++I)389    if (Value == Table.Table[I].Value)390      return Table.Table[I];391 392  return std::nullopt;393}394 395static std::optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,396                                                   unsigned TableIndex,397                                                   const ArgList &Args,398                                                   DiagnosticsEngine &Diags) {399  assert(TableIndex < SimpleEnumValueTablesSize);400  const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];401 402  auto *Arg = Args.getLastArg(Opt);403  if (!Arg)404    return std::nullopt;405 406  StringRef ArgValue = Arg->getValue();407  if (auto MaybeEnumVal = findValueTableByName(Table, ArgValue))408    return MaybeEnumVal->Value;409 410  Diags.Report(diag::err_drv_invalid_value)411      << Arg->getAsString(Args) << ArgValue;412  return std::nullopt;413}414 415static void denormalizeSimpleEnumImpl(ArgumentConsumer Consumer,416                                      unsigned SpellingOffset,417                                      Option::OptionClass OptClass,418                                      unsigned TableIndex, unsigned Value) {419  assert(TableIndex < SimpleEnumValueTablesSize);420  const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];421  if (auto MaybeEnumVal = findValueTableByValue(Table, Value)) {422    denormalizeString(Consumer, lookupStrInTable(SpellingOffset), OptClass,423                      TableIndex, MaybeEnumVal->Name);424  } else {425    llvm_unreachable("The simple enum value was not correctly defined in "426                     "the tablegen option description");427  }428}429 430template <typename T>431static void denormalizeSimpleEnum(ArgumentConsumer Consumer,432                                  unsigned SpellingOffset,433                                  Option::OptionClass OptClass,434                                  unsigned TableIndex, T Value) {435  return denormalizeSimpleEnumImpl(Consumer, SpellingOffset, OptClass,436                                   TableIndex, static_cast<unsigned>(Value));437}438 439static std::optional<std::string> normalizeString(OptSpecifier Opt,440                                                  int TableIndex,441                                                  const ArgList &Args,442                                                  DiagnosticsEngine &Diags) {443  auto *Arg = Args.getLastArg(Opt);444  if (!Arg)445    return std::nullopt;446  return std::string(Arg->getValue());447}448 449template <typename IntTy>450static std::optional<IntTy> normalizeStringIntegral(OptSpecifier Opt, int,451                                                    const ArgList &Args,452                                                    DiagnosticsEngine &Diags) {453  auto *Arg = Args.getLastArg(Opt);454  if (!Arg)455    return std::nullopt;456  IntTy Res;457  if (StringRef(Arg->getValue()).getAsInteger(0, Res)) {458    Diags.Report(diag::err_drv_invalid_int_value)459        << Arg->getAsString(Args) << Arg->getValue();460    return std::nullopt;461  }462  return Res;463}464 465static std::optional<std::vector<std::string>>466normalizeStringVector(OptSpecifier Opt, int, const ArgList &Args,467                      DiagnosticsEngine &) {468  return Args.getAllArgValues(Opt);469}470 471static void denormalizeStringVector(ArgumentConsumer Consumer,472                                    unsigned SpellingOffset,473                                    Option::OptionClass OptClass,474                                    unsigned TableIndex,475                                    const std::vector<std::string> &Values) {476  switch (OptClass) {477  case Option::CommaJoinedClass: {478    std::string CommaJoinedValue;479    if (!Values.empty()) {480      CommaJoinedValue.append(Values.front());481      for (const std::string &Value : llvm::drop_begin(Values, 1)) {482        CommaJoinedValue.append(",");483        CommaJoinedValue.append(Value);484      }485    }486    denormalizeString(Consumer, SpellingOffset,487                      Option::OptionClass::JoinedClass, TableIndex,488                      CommaJoinedValue);489    break;490  }491  case Option::JoinedClass:492  case Option::SeparateClass:493  case Option::JoinedOrSeparateClass:494    for (const std::string &Value : Values)495      denormalizeString(Consumer, SpellingOffset, OptClass, TableIndex, Value);496    break;497  default:498    llvm_unreachable("Cannot denormalize an option with option class "499                     "incompatible with string vector denormalization.");500  }501}502 503static std::optional<std::string> normalizeTriple(OptSpecifier Opt,504                                                  int TableIndex,505                                                  const ArgList &Args,506                                                  DiagnosticsEngine &Diags) {507  auto *Arg = Args.getLastArg(Opt);508  if (!Arg)509    return std::nullopt;510  return llvm::Triple::normalize(Arg->getValue());511}512 513template <typename T, typename U>514static T mergeForwardValue(T KeyPath, U Value) {515  return static_cast<T>(Value);516}517 518template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {519  return KeyPath | Value;520}521 522template <typename T> static T extractForwardValue(T KeyPath) {523  return KeyPath;524}525 526template <typename T, typename U, U Value>527static T extractMaskValue(T KeyPath) {528  return ((KeyPath & Value) == Value) ? static_cast<T>(Value) : T();529}530 531#define PARSE_OPTION_WITH_MARSHALLING(                                         \532    ARGS, DIAGS, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS,         \533    ALIASARGS, FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS,       \534    METAVAR, VALUES, SUBCOMMANDIDS_OFFSET, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, \535    DEFAULT_VALUE, IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER,     \536    MERGER, EXTRACTOR, TABLE_INDEX)                                            \537  if ((VISIBILITY) & options::CC1Option) {                                     \538    KEYPATH = MERGER(KEYPATH, DEFAULT_VALUE);                                  \539    if (IMPLIED_CHECK)                                                         \540      KEYPATH = MERGER(KEYPATH, IMPLIED_VALUE);                                \541    if (SHOULD_PARSE)                                                          \542      if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, ARGS, DIAGS))    \543        KEYPATH =                                                              \544            MERGER(KEYPATH, static_cast<decltype(KEYPATH)>(*MaybeValue));      \545  }546 547// Capture the extracted value as a lambda argument to avoid potential issues548// with lifetime extension of the reference.549#define GENERATE_OPTION_WITH_MARSHALLING(                                      \550    CONSUMER, PREFIX_TYPE, SPELLING_OFFSET, ID, KIND, GROUP, ALIAS, ALIASARGS, \551    FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR, VALUES, \552    SUBCOMMANDIDS_OFFSET, SHOULD_PARSE, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,   \553    IMPLIED_CHECK, IMPLIED_VALUE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, \554    TABLE_INDEX)                                                               \555  if ((VISIBILITY) & options::CC1Option) {                                     \556    [&](const auto &Extracted) {                                               \557      if (ALWAYS_EMIT ||                                                       \558          (Extracted !=                                                        \559           static_cast<decltype(KEYPATH)>((IMPLIED_CHECK) ? (IMPLIED_VALUE)    \560                                                          : (DEFAULT_VALUE)))) \561        DENORMALIZER(CONSUMER, SPELLING_OFFSET, Option::KIND##Class,           \562                     TABLE_INDEX, Extracted);                                  \563    }(EXTRACTOR(KEYPATH));                                                     \564  }565 566static StringRef GetInputKindName(InputKind IK);567 568static bool FixupInvocation(CompilerInvocation &Invocation,569                            DiagnosticsEngine &Diags, const ArgList &Args,570                            InputKind IK) {571  unsigned NumErrorsBefore = Diags.getNumErrors();572 573  LangOptions &LangOpts = Invocation.getLangOpts();574  CodeGenOptions &CodeGenOpts = Invocation.getCodeGenOpts();575  TargetOptions &TargetOpts = Invocation.getTargetOpts();576  FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();577  CodeGenOpts.XRayInstrumentFunctions = LangOpts.XRayInstrument;578  CodeGenOpts.XRayAlwaysEmitCustomEvents = LangOpts.XRayAlwaysEmitCustomEvents;579  CodeGenOpts.XRayAlwaysEmitTypedEvents = LangOpts.XRayAlwaysEmitTypedEvents;580  CodeGenOpts.DisableFree = FrontendOpts.DisableFree;581  FrontendOpts.GenerateGlobalModuleIndex = FrontendOpts.UseGlobalModuleIndex;582  if (FrontendOpts.ShowStats)583    CodeGenOpts.ClearASTBeforeBackend = false;584  LangOpts.SanitizeCoverage = CodeGenOpts.hasSanitizeCoverage();585  LangOpts.ForceEmitVTables = CodeGenOpts.ForceEmitVTables;586  LangOpts.SpeculativeLoadHardening = CodeGenOpts.SpeculativeLoadHardening;587  LangOpts.CurrentModule = LangOpts.ModuleName;588 589  llvm::Triple T(TargetOpts.Triple);590  llvm::Triple::ArchType Arch = T.getArch();591 592  CodeGenOpts.CodeModel = TargetOpts.CodeModel;593  CodeGenOpts.LargeDataThreshold = TargetOpts.LargeDataThreshold;594 595  if (CodeGenOpts.getExceptionHandling() !=596          CodeGenOptions::ExceptionHandlingKind::None &&597      T.isWindowsMSVCEnvironment())598    Diags.Report(diag::err_fe_invalid_exception_model)599        << static_cast<unsigned>(CodeGenOpts.getExceptionHandling()) << T.str();600 601  if (LangOpts.AppleKext && !LangOpts.CPlusPlus)602    Diags.Report(diag::warn_c_kext);603 604  if (LangOpts.NewAlignOverride &&605      !llvm::isPowerOf2_32(LangOpts.NewAlignOverride)) {606    Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);607    Diags.Report(diag::err_fe_invalid_alignment)608        << A->getAsString(Args) << A->getValue();609    LangOpts.NewAlignOverride = 0;610  }611 612  // The -f[no-]raw-string-literals option is only valid in C and in C++613  // standards before C++11.614  if (LangOpts.CPlusPlus11) {615    if (Args.hasArg(OPT_fraw_string_literals, OPT_fno_raw_string_literals)) {616      Args.claimAllArgs(OPT_fraw_string_literals, OPT_fno_raw_string_literals);617      Diags.Report(diag::warn_drv_fraw_string_literals_in_cxx11)618          << bool(LangOpts.RawStringLiterals);619    }620 621    // Do not allow disabling raw string literals in C++11 or later.622    LangOpts.RawStringLiterals = true;623  }624 625  LangOpts.NamedLoops =626      Args.hasFlag(OPT_fnamed_loops, OPT_fno_named_loops, LangOpts.C2y);627 628  // Prevent the user from specifying both -fsycl-is-device and -fsycl-is-host.629  if (LangOpts.SYCLIsDevice && LangOpts.SYCLIsHost)630    Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fsycl-is-device"631                                                          << "-fsycl-is-host";632 633  if (Args.hasArg(OPT_fgnu89_inline) && LangOpts.CPlusPlus)634    Diags.Report(diag::err_drv_argument_not_allowed_with)635        << "-fgnu89-inline" << GetInputKindName(IK);636 637  if (Args.hasArg(OPT_hlsl_entrypoint) && !LangOpts.HLSL)638    Diags.Report(diag::err_drv_argument_not_allowed_with)639        << "-hlsl-entry" << GetInputKindName(IK);640 641  if (Args.hasArg(OPT_fdx_rootsignature_version) && !LangOpts.HLSL)642    Diags.Report(diag::err_drv_argument_not_allowed_with)643        << "-fdx-rootsignature-version" << GetInputKindName(IK);644 645  if (Args.hasArg(OPT_fdx_rootsignature_define) && !LangOpts.HLSL)646    Diags.Report(diag::err_drv_argument_not_allowed_with)647        << "-fdx-rootsignature-define" << GetInputKindName(IK);648 649  if (Args.hasArg(OPT_fgpu_allow_device_init) && !LangOpts.HIP)650    Diags.Report(diag::warn_ignored_hip_only_option)651        << Args.getLastArg(OPT_fgpu_allow_device_init)->getAsString(Args);652 653  if (Args.hasArg(OPT_gpu_max_threads_per_block_EQ) && !LangOpts.HIP)654    Diags.Report(diag::warn_ignored_hip_only_option)655        << Args.getLastArg(OPT_gpu_max_threads_per_block_EQ)->getAsString(Args);656 657  // When these options are used, the compiler is allowed to apply658  // optimizations that may affect the final result. For example659  // (x+y)+z is transformed to x+(y+z) but may not give the same660  // final result; it's not value safe.661  // Another example can be to simplify x/x to 1.0 but x could be 0.0, INF662  // or NaN. Final result may then differ. An error is issued when the eval663  // method is set with one of these options.664  if (Args.hasArg(OPT_ffp_eval_method_EQ)) {665    if (LangOpts.ApproxFunc)666      Diags.Report(diag::err_incompatible_fp_eval_method_options) << 0;667    if (LangOpts.AllowFPReassoc)668      Diags.Report(diag::err_incompatible_fp_eval_method_options) << 1;669    if (LangOpts.AllowRecip)670      Diags.Report(diag::err_incompatible_fp_eval_method_options) << 2;671  }672 673  // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.674  // This option should be deprecated for CL > 1.0 because675  // this option was added for compatibility with OpenCL 1.0.676  if (Args.getLastArg(OPT_cl_strict_aliasing) &&677      (LangOpts.getOpenCLCompatibleVersion() > 100))678    Diags.Report(diag::warn_option_invalid_ocl_version)679        << LangOpts.getOpenCLVersionString()680        << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);681 682  if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {683    auto DefaultCC = LangOpts.getDefaultCallingConv();684 685    bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||686                      DefaultCC == LangOptions::DCC_StdCall) &&687                     Arch != llvm::Triple::x86;688    emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||689                  DefaultCC == LangOptions::DCC_RegCall) &&690                 !T.isX86();691    emitError |= DefaultCC == LangOptions::DCC_RtdCall && Arch != llvm::Triple::m68k;692    if (emitError)693      Diags.Report(diag::err_drv_argument_not_allowed_with)694          << A->getSpelling() << T.getTriple();695  }696 697  return Diags.getNumErrors() == NumErrorsBefore;698}699 700//===----------------------------------------------------------------------===//701// Deserialization (from args)702//===----------------------------------------------------------------------===//703 704static void GenerateArg(ArgumentConsumer Consumer,705                        llvm::opt::OptSpecifier OptSpecifier) {706  Option Opt = getDriverOptTable().getOption(OptSpecifier);707  denormalizeSimpleFlag(Consumer, Opt.getPrefixedName(),708                        Option::OptionClass::FlagClass, 0);709}710 711static void GenerateArg(ArgumentConsumer Consumer,712                        llvm::opt::OptSpecifier OptSpecifier,713                        const Twine &Value) {714  Option Opt = getDriverOptTable().getOption(OptSpecifier);715  denormalizeString(Consumer, Opt.getPrefixedName(), Opt.getKind(), 0, Value);716}717 718// Parse command line arguments into CompilerInvocation.719using ParseFn =720    llvm::function_ref<bool(CompilerInvocation &, ArrayRef<const char *>,721                            DiagnosticsEngine &, const char *)>;722 723// Generate command line arguments from CompilerInvocation.724using GenerateFn = llvm::function_ref<void(725    CompilerInvocation &, SmallVectorImpl<const char *> &,726    CompilerInvocation::StringAllocator)>;727 728/// May perform round-trip of command line arguments. By default, the round-trip729/// is enabled in assert builds. This can be overwritten at run-time via the730/// "-round-trip-args" and "-no-round-trip-args" command line flags, or via the731/// ForceRoundTrip parameter.732///733/// During round-trip, the command line arguments are parsed into a dummy734/// CompilerInvocation, which is used to generate the command line arguments735/// again. The real CompilerInvocation is then created by parsing the generated736/// arguments, not the original ones. This (in combination with tests covering737/// argument behavior) ensures the generated command line is complete (doesn't738/// drop/mangle any arguments).739///740/// Finally, we check the command line that was used to create the real741/// CompilerInvocation instance. By default, we compare it to the command line742/// the real CompilerInvocation generates. This checks whether the generator is743/// deterministic. If \p CheckAgainstOriginalInvocation is enabled, we instead744/// compare it to the original command line to verify the original command-line745/// was canonical and can round-trip exactly.746static bool RoundTrip(ParseFn Parse, GenerateFn Generate,747                      CompilerInvocation &RealInvocation,748                      CompilerInvocation &DummyInvocation,749                      ArrayRef<const char *> CommandLineArgs,750                      DiagnosticsEngine &Diags, const char *Argv0,751                      bool CheckAgainstOriginalInvocation = false,752                      bool ForceRoundTrip = false) {753#ifndef NDEBUG754  bool DoRoundTripDefault = true;755#else756  bool DoRoundTripDefault = false;757#endif758 759  bool DoRoundTrip = DoRoundTripDefault;760  if (ForceRoundTrip) {761    DoRoundTrip = true;762  } else {763    for (const auto *Arg : CommandLineArgs) {764      if (Arg == StringRef("-round-trip-args"))765        DoRoundTrip = true;766      if (Arg == StringRef("-no-round-trip-args"))767        DoRoundTrip = false;768    }769  }770 771  // If round-trip was not requested, simply run the parser with the real772  // invocation diagnostics.773  if (!DoRoundTrip)774    return Parse(RealInvocation, CommandLineArgs, Diags, Argv0);775 776  // Serializes quoted (and potentially escaped) arguments.777  auto SerializeArgs = [](ArrayRef<const char *> Args) {778    std::string Buffer;779    llvm::raw_string_ostream OS(Buffer);780    for (const char *Arg : Args) {781      llvm::sys::printArg(OS, Arg, /*Quote=*/true);782      OS << ' ';783    }784    return Buffer;785  };786 787  // Setup a dummy DiagnosticsEngine.788  DiagnosticOptions DummyDiagOpts;789  DiagnosticsEngine DummyDiags(DiagnosticIDs::create(), DummyDiagOpts);790  DummyDiags.setClient(new TextDiagnosticBuffer());791 792  // Run the first parse on the original arguments with the dummy invocation and793  // diagnostics.794  if (!Parse(DummyInvocation, CommandLineArgs, DummyDiags, Argv0) ||795      DummyDiags.getNumWarnings() != 0) {796    // If the first parse did not succeed, it must be user mistake (invalid797    // command line arguments). We won't be able to generate arguments that798    // would reproduce the same result. Let's fail again with the real799    // invocation and diagnostics, so all side-effects of parsing are visible.800    unsigned NumWarningsBefore = Diags.getNumWarnings();801    auto Success = Parse(RealInvocation, CommandLineArgs, Diags, Argv0);802    if (!Success || Diags.getNumWarnings() != NumWarningsBefore)803      return Success;804 805    // Parse with original options and diagnostics succeeded even though it806    // shouldn't have. Something is off.807    Diags.Report(diag::err_cc1_round_trip_fail_then_ok);808    Diags.Report(diag::note_cc1_round_trip_original)809        << SerializeArgs(CommandLineArgs);810    return false;811  }812 813  // Setup string allocator.814  llvm::BumpPtrAllocator Alloc;815  llvm::StringSaver StringPool(Alloc);816  auto SA = [&StringPool](const Twine &Arg) {817    return StringPool.save(Arg).data();818  };819 820  // Generate arguments from the dummy invocation. If Generate is the821  // inverse of Parse, the newly generated arguments must have the same822  // semantics as the original.823  SmallVector<const char *> GeneratedArgs;824  Generate(DummyInvocation, GeneratedArgs, SA);825 826  // Run the second parse, now on the generated arguments, and with the real827  // invocation and diagnostics. The result is what we will end up using for the828  // rest of compilation, so if Generate is not inverse of Parse, something down829  // the line will break.830  bool Success2 = Parse(RealInvocation, GeneratedArgs, Diags, Argv0);831 832  // The first parse on original arguments succeeded, but second parse of833  // generated arguments failed. Something must be wrong with the generator.834  if (!Success2) {835    Diags.Report(diag::err_cc1_round_trip_ok_then_fail);836    Diags.Report(diag::note_cc1_round_trip_generated)837        << 1 << SerializeArgs(GeneratedArgs);838    return false;839  }840 841  SmallVector<const char *> ComparisonArgs;842  if (CheckAgainstOriginalInvocation)843    // Compare against original arguments.844    ComparisonArgs.assign(CommandLineArgs.begin(), CommandLineArgs.end());845  else846    // Generate arguments again, this time from the options we will end up using847    // for the rest of the compilation.848    Generate(RealInvocation, ComparisonArgs, SA);849 850  // Compares two lists of arguments.851  auto Equal = [](const ArrayRef<const char *> A,852                  const ArrayRef<const char *> B) {853    return llvm::equal(A, B, [](const char *AElem, const char *BElem) {854      return StringRef(AElem) == StringRef(BElem);855    });856  };857 858  // If we generated different arguments from what we assume are two859  // semantically equivalent CompilerInvocations, the Generate function may860  // be non-deterministic.861  if (!Equal(GeneratedArgs, ComparisonArgs)) {862    Diags.Report(diag::err_cc1_round_trip_mismatch);863    Diags.Report(diag::note_cc1_round_trip_generated)864        << 1 << SerializeArgs(GeneratedArgs);865    Diags.Report(diag::note_cc1_round_trip_generated)866        << 2 << SerializeArgs(ComparisonArgs);867    return false;868  }869 870  Diags.Report(diag::remark_cc1_round_trip_generated)871      << 1 << SerializeArgs(GeneratedArgs);872  Diags.Report(diag::remark_cc1_round_trip_generated)873      << 2 << SerializeArgs(ComparisonArgs);874 875  return Success2;876}877 878bool CompilerInvocation::checkCC1RoundTrip(ArrayRef<const char *> Args,879                                           DiagnosticsEngine &Diags,880                                           const char *Argv0) {881  CompilerInvocation DummyInvocation1, DummyInvocation2;882  return RoundTrip(883      [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,884         DiagnosticsEngine &Diags, const char *Argv0) {885        return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);886      },887      [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,888         StringAllocator SA) {889        Args.push_back("-cc1");890        Invocation.generateCC1CommandLine(Args, SA);891      },892      DummyInvocation1, DummyInvocation2, Args, Diags, Argv0,893      /*CheckAgainstOriginalInvocation=*/true, /*ForceRoundTrip=*/true);894}895 896static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,897                              OptSpecifier GroupWithValue,898                              std::vector<std::string> &Diagnostics) {899  for (auto *A : Args.filtered(Group)) {900    if (A->getOption().getKind() == Option::FlagClass) {901      // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add902      // its name (minus the "W" or "R" at the beginning) to the diagnostics.903      Diagnostics.push_back(904          std::string(A->getOption().getName().drop_front(1)));905    } else if (A->getOption().matches(GroupWithValue)) {906      // This is -Wfoo= or -Rfoo=, where foo is the name of the diagnostic907      // group. Add only the group name to the diagnostics.908      Diagnostics.push_back(909          std::string(A->getOption().getName().drop_front(1).rtrim("=-")));910    } else {911      // Otherwise, add its value (for OPT_W_Joined and similar).912      Diagnostics.push_back(A->getValue());913    }914  }915}916 917// Parse the Static Analyzer configuration. If \p Diags is set to nullptr,918// it won't verify the input.919static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,920                                 DiagnosticsEngine *Diags);921 922static void getAllNoBuiltinFuncValues(ArgList &Args,923                                      std::vector<std::string> &Funcs) {924  std::vector<std::string> Values = Args.getAllArgValues(OPT_fno_builtin_);925  auto BuiltinEnd = llvm::partition(Values, Builtin::Context::isBuiltinFunc);926  Funcs.insert(Funcs.end(), Values.begin(), BuiltinEnd);927}928 929static void GenerateAnalyzerArgs(const AnalyzerOptions &Opts,930                                 ArgumentConsumer Consumer) {931  const AnalyzerOptions *AnalyzerOpts = &Opts;932 933#define ANALYZER_OPTION_WITH_MARSHALLING(...)                                  \934  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)935#include "clang/Options/Options.inc"936#undef ANALYZER_OPTION_WITH_MARSHALLING937 938  if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {939    switch (Opts.AnalysisConstraintsOpt) {940#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)                     \941  case NAME##Model:                                                            \942    GenerateArg(Consumer, OPT_analyzer_constraints, CMDFLAG);                  \943    break;944#include "clang/StaticAnalyzer/Core/Analyses.def"945    default:946      llvm_unreachable("Tried to generate unknown analysis constraint.");947    }948  }949 950  if (Opts.AnalysisDiagOpt != PD_HTML) {951    switch (Opts.AnalysisDiagOpt) {952#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN)                     \953  case PD_##NAME:                                                              \954    GenerateArg(Consumer, OPT_analyzer_output, CMDFLAG);                       \955    break;956#include "clang/StaticAnalyzer/Core/Analyses.def"957    default:958      llvm_unreachable("Tried to generate unknown analysis diagnostic client.");959    }960  }961 962  if (Opts.AnalysisPurgeOpt != PurgeStmt) {963    switch (Opts.AnalysisPurgeOpt) {964#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)                                    \965  case NAME:                                                                   \966    GenerateArg(Consumer, OPT_analyzer_purge, CMDFLAG);                        \967    break;968#include "clang/StaticAnalyzer/Core/Analyses.def"969    default:970      llvm_unreachable("Tried to generate unknown analysis purge mode.");971    }972  }973 974  if (Opts.InliningMode != NoRedundancy) {975    switch (Opts.InliningMode) {976#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC)                            \977  case NAME:                                                                   \978    GenerateArg(Consumer, OPT_analyzer_inlining_mode, CMDFLAG);                \979    break;980#include "clang/StaticAnalyzer/Core/Analyses.def"981    default:982      llvm_unreachable("Tried to generate unknown analysis inlining mode.");983    }984  }985 986  for (const auto &CP : Opts.CheckersAndPackages) {987    OptSpecifier Opt =988        CP.second ? OPT_analyzer_checker : OPT_analyzer_disable_checker;989    GenerateArg(Consumer, Opt, CP.first);990  }991 992  AnalyzerOptions ConfigOpts;993  parseAnalyzerConfigs(ConfigOpts, nullptr);994 995  // Sort options by key to avoid relying on StringMap iteration order.996  SmallVector<std::pair<StringRef, StringRef>, 4> SortedConfigOpts;997  for (const auto &C : Opts.Config)998    SortedConfigOpts.emplace_back(C.getKey(), C.getValue());999  llvm::sort(SortedConfigOpts, llvm::less_first());1000 1001  for (const auto &[Key, Value] : SortedConfigOpts) {1002    // Don't generate anything that came from parseAnalyzerConfigs. It would be1003    // redundant and may not be valid on the command line.1004    auto Entry = ConfigOpts.Config.find(Key);1005    if (Entry != ConfigOpts.Config.end() && Entry->getValue() == Value)1006      continue;1007 1008    GenerateArg(Consumer, OPT_analyzer_config, Key + "=" + Value);1009  }1010 1011  // Nothing to generate for FullCompilerInvocation.1012}1013 1014static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,1015                              DiagnosticsEngine &Diags) {1016  unsigned NumErrorsBefore = Diags.getNumErrors();1017 1018  AnalyzerOptions *AnalyzerOpts = &Opts;1019 1020#define ANALYZER_OPTION_WITH_MARSHALLING(...)                                  \1021  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)1022#include "clang/Options/Options.inc"1023#undef ANALYZER_OPTION_WITH_MARSHALLING1024 1025  if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {1026    StringRef Name = A->getValue();1027    AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)1028#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \1029      .Case(CMDFLAG, NAME##Model)1030#include "clang/StaticAnalyzer/Core/Analyses.def"1031      .Default(NumConstraints);1032    if (Value == NumConstraints) {1033      Diags.Report(diag::err_drv_invalid_value)1034        << A->getAsString(Args) << Name;1035    } else {1036#ifndef LLVM_WITH_Z31037      if (Value == AnalysisConstraints::Z3ConstraintsModel) {1038        Diags.Report(diag::err_analyzer_not_built_with_z3);1039      }1040#endif // LLVM_WITH_Z31041      Opts.AnalysisConstraintsOpt = Value;1042    }1043  }1044 1045  if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {1046    StringRef Name = A->getValue();1047    AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)1048#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \1049      .Case(CMDFLAG, PD_##NAME)1050#include "clang/StaticAnalyzer/Core/Analyses.def"1051      .Default(NUM_ANALYSIS_DIAG_CLIENTS);1052    if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {1053      Diags.Report(diag::err_drv_invalid_value)1054        << A->getAsString(Args) << Name;1055    } else {1056      Opts.AnalysisDiagOpt = Value;1057    }1058  }1059 1060  if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {1061    StringRef Name = A->getValue();1062    AnalysisPurgeMode Value = llvm::StringSwitch<AnalysisPurgeMode>(Name)1063#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \1064      .Case(CMDFLAG, NAME)1065#include "clang/StaticAnalyzer/Core/Analyses.def"1066      .Default(NumPurgeModes);1067    if (Value == NumPurgeModes) {1068      Diags.Report(diag::err_drv_invalid_value)1069        << A->getAsString(Args) << Name;1070    } else {1071      Opts.AnalysisPurgeOpt = Value;1072    }1073  }1074 1075  if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) {1076    StringRef Name = A->getValue();1077    AnalysisInliningMode Value = llvm::StringSwitch<AnalysisInliningMode>(Name)1078#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \1079      .Case(CMDFLAG, NAME)1080#include "clang/StaticAnalyzer/Core/Analyses.def"1081      .Default(NumInliningModes);1082    if (Value == NumInliningModes) {1083      Diags.Report(diag::err_drv_invalid_value)1084        << A->getAsString(Args) << Name;1085    } else {1086      Opts.InliningMode = Value;1087    }1088  }1089 1090  Opts.CheckersAndPackages.clear();1091  for (const Arg *A :1092       Args.filtered(OPT_analyzer_checker, OPT_analyzer_disable_checker)) {1093    A->claim();1094    bool IsEnabled = A->getOption().getID() == OPT_analyzer_checker;1095    // We can have a list of comma separated checker names, e.g:1096    // '-analyzer-checker=cocoa,unix'1097    StringRef CheckerAndPackageList = A->getValue();1098    SmallVector<StringRef, 16> CheckersAndPackages;1099    CheckerAndPackageList.split(CheckersAndPackages, ",");1100    for (const StringRef &CheckerOrPackage : CheckersAndPackages)1101      Opts.CheckersAndPackages.emplace_back(std::string(CheckerOrPackage),1102                                            IsEnabled);1103  }1104 1105  // Go through the analyzer configuration options.1106  for (const auto *A : Args.filtered(OPT_analyzer_config)) {1107 1108    // We can have a list of comma separated config names, e.g:1109    // '-analyzer-config key1=val1,key2=val2'1110    StringRef configList = A->getValue();1111    SmallVector<StringRef, 4> configVals;1112    configList.split(configVals, ",");1113    for (const auto &configVal : configVals) {1114      StringRef key, val;1115      std::tie(key, val) = configVal.split("=");1116      if (val.empty()) {1117        Diags.Report(SourceLocation(),1118                     diag::err_analyzer_config_no_value) << configVal;1119        break;1120      }1121      if (val.contains('=')) {1122        Diags.Report(SourceLocation(),1123                     diag::err_analyzer_config_multiple_values)1124          << configVal;1125        break;1126      }1127 1128      // TODO: Check checker options too, possibly in CheckerRegistry.1129      // Leave unknown non-checker configs unclaimed.1130      if (!key.contains(":") && Opts.isUnknownAnalyzerConfig(key)) {1131        if (Opts.ShouldEmitErrorsOnInvalidConfigValue)1132          Diags.Report(diag::err_analyzer_config_unknown) << key;1133        continue;1134      }1135 1136      A->claim();1137      Opts.Config[key] = std::string(val);1138    }1139  }1140 1141  if (Opts.ShouldEmitErrorsOnInvalidConfigValue)1142    parseAnalyzerConfigs(Opts, &Diags);1143  else1144    parseAnalyzerConfigs(Opts, nullptr);1145 1146  llvm::raw_string_ostream os(Opts.FullCompilerInvocation);1147  for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {1148    if (i != 0)1149      os << " ";1150    os << Args.getArgString(i);1151  }1152 1153  return Diags.getNumErrors() == NumErrorsBefore;1154}1155 1156static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,1157                                 StringRef OptionName, StringRef DefaultVal) {1158  return Config.insert({OptionName, std::string(DefaultVal)}).first->second;1159}1160 1161static void initOption(AnalyzerOptions::ConfigTable &Config,1162                       DiagnosticsEngine *Diags,1163                       StringRef &OptionField, StringRef Name,1164                       StringRef DefaultVal) {1165  // String options may be known to invalid (e.g. if the expected string is a1166  // file name, but the file does not exist), those will have to be checked in1167  // parseConfigs.1168  OptionField = getStringOption(Config, Name, DefaultVal);1169}1170 1171static void initOption(AnalyzerOptions::ConfigTable &Config,1172                       DiagnosticsEngine *Diags,1173                       bool &OptionField, StringRef Name, bool DefaultVal) {1174  auto PossiblyInvalidVal =1175      llvm::StringSwitch<std::optional<bool>>(1176          getStringOption(Config, Name, (DefaultVal ? "true" : "false")))1177          .Case("true", true)1178          .Case("false", false)1179          .Default(std::nullopt);1180 1181  if (!PossiblyInvalidVal) {1182    if (Diags)1183      Diags->Report(diag::err_analyzer_config_invalid_input)1184        << Name << "a boolean";1185    else1186      OptionField = DefaultVal;1187  } else1188    OptionField = *PossiblyInvalidVal;1189}1190 1191static void initOption(AnalyzerOptions::ConfigTable &Config,1192                       DiagnosticsEngine *Diags,1193                       unsigned &OptionField, StringRef Name,1194                       unsigned DefaultVal) {1195 1196  OptionField = DefaultVal;1197  bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))1198                     .getAsInteger(0, OptionField);1199  if (Diags && HasFailed)1200    Diags->Report(diag::err_analyzer_config_invalid_input)1201      << Name << "an unsigned";1202}1203 1204static void initOption(AnalyzerOptions::ConfigTable &Config,1205                       DiagnosticsEngine *Diags,1206                       PositiveAnalyzerOption &OptionField, StringRef Name,1207                       unsigned DefaultVal) {1208  auto Parsed = PositiveAnalyzerOption::create(1209      getStringOption(Config, Name, std::to_string(DefaultVal)));1210  if (Parsed.has_value()) {1211    OptionField = Parsed.value();1212    return;1213  }1214  if (Diags && !Parsed.has_value())1215    Diags->Report(diag::err_analyzer_config_invalid_input)1216        << Name << "a positive";1217 1218  OptionField = DefaultVal;1219}1220 1221static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,1222                                 DiagnosticsEngine *Diags) {1223  // TODO: There's no need to store the entire configtable, it'd be plenty1224  // enough to store checker options.1225 1226#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \1227  initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);1228#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(...)1229#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"1230 1231  assert(AnOpts.UserMode == "shallow" || AnOpts.UserMode == "deep");1232  const bool InShallowMode = AnOpts.UserMode == "shallow";1233 1234#define ANALYZER_OPTION(...)1235#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \1236                                             SHALLOW_VAL, DEEP_VAL)            \1237  initOption(AnOpts.Config, Diags, AnOpts.NAME, CMDFLAG,                       \1238             InShallowMode ? SHALLOW_VAL : DEEP_VAL);1239#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"1240 1241  // At this point, AnalyzerOptions is configured. Let's validate some options.1242 1243  // FIXME: Here we try to validate the silenced checkers or packages are valid.1244  // The current approach only validates the registered checkers which does not1245  // contain the runtime enabled checkers and optimally we would validate both.1246  if (!AnOpts.RawSilencedCheckersAndPackages.empty()) {1247    std::vector<StringRef> Checkers =1248        AnOpts.getRegisteredCheckers(/*IncludeExperimental=*/true);1249    std::vector<StringRef> Packages =1250        AnOpts.getRegisteredPackages(/*IncludeExperimental=*/true);1251 1252    SmallVector<StringRef, 16> CheckersAndPackages;1253    AnOpts.RawSilencedCheckersAndPackages.split(CheckersAndPackages, ";");1254 1255    for (const StringRef &CheckerOrPackage : CheckersAndPackages) {1256      if (Diags) {1257        bool IsChecker = CheckerOrPackage.contains('.');1258        bool IsValidName = IsChecker1259                               ? llvm::is_contained(Checkers, CheckerOrPackage)1260                               : llvm::is_contained(Packages, CheckerOrPackage);1261 1262        if (!IsValidName)1263          Diags->Report(diag::err_unknown_analyzer_checker_or_package)1264              << CheckerOrPackage;1265      }1266 1267      AnOpts.SilencedCheckersAndPackages.emplace_back(CheckerOrPackage);1268    }1269  }1270 1271  if (!Diags)1272    return;1273 1274  if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions)1275    Diags->Report(diag::err_analyzer_config_invalid_input)1276        << "track-conditions-debug" << "'track-conditions' to also be enabled";1277}1278 1279/// Generate a remark argument. This is an inverse of `ParseOptimizationRemark`.1280static void1281GenerateOptimizationRemark(ArgumentConsumer Consumer, OptSpecifier OptEQ,1282                           StringRef Name,1283                           const CodeGenOptions::OptRemark &Remark) {1284  if (Remark.hasValidPattern()) {1285    GenerateArg(Consumer, OptEQ, Remark.Pattern);1286  } else if (Remark.Kind == CodeGenOptions::RK_Enabled) {1287    GenerateArg(Consumer, OPT_R_Joined, Name);1288  } else if (Remark.Kind == CodeGenOptions::RK_Disabled) {1289    GenerateArg(Consumer, OPT_R_Joined, StringRef("no-") + Name);1290  }1291}1292 1293/// Parse a remark command line argument. It may be missing, disabled/enabled by1294/// '-R[no-]group' or specified with a regular expression by '-Rgroup=regexp'.1295/// On top of that, it can be disabled/enabled globally by '-R[no-]everything'.1296static CodeGenOptions::OptRemark1297ParseOptimizationRemark(DiagnosticsEngine &Diags, ArgList &Args,1298                        OptSpecifier OptEQ, StringRef Name) {1299  CodeGenOptions::OptRemark Result;1300 1301  auto InitializeResultPattern = [&Diags, &Args, &Result](const Arg *A,1302                                                          StringRef Pattern) {1303    Result.Pattern = Pattern.str();1304 1305    std::string RegexError;1306    Result.Regex = std::make_shared<llvm::Regex>(Result.Pattern);1307    if (!Result.Regex->isValid(RegexError)) {1308      Diags.Report(diag::err_drv_optimization_remark_pattern)1309          << RegexError << A->getAsString(Args);1310      return false;1311    }1312 1313    return true;1314  };1315 1316  for (Arg *A : Args) {1317    if (A->getOption().matches(OPT_R_Joined)) {1318      StringRef Value = A->getValue();1319 1320      if (Value == Name)1321        Result.Kind = CodeGenOptions::RK_Enabled;1322      else if (Value == "everything")1323        Result.Kind = CodeGenOptions::RK_EnabledEverything;1324      else if (Value.split('-') == std::make_pair(StringRef("no"), Name))1325        Result.Kind = CodeGenOptions::RK_Disabled;1326      else if (Value == "no-everything")1327        Result.Kind = CodeGenOptions::RK_DisabledEverything;1328      else1329        continue;1330 1331      if (Result.Kind == CodeGenOptions::RK_Disabled ||1332          Result.Kind == CodeGenOptions::RK_DisabledEverything) {1333        Result.Pattern = "";1334        Result.Regex = nullptr;1335      } else {1336        InitializeResultPattern(A, ".*");1337      }1338    } else if (A->getOption().matches(OptEQ)) {1339      Result.Kind = CodeGenOptions::RK_WithPattern;1340      if (!InitializeResultPattern(A, A->getValue()))1341        return CodeGenOptions::OptRemark();1342    }1343  }1344 1345  return Result;1346}1347 1348static bool parseDiagnosticLevelMask(StringRef FlagName,1349                                     const std::vector<std::string> &Levels,1350                                     DiagnosticsEngine &Diags,1351                                     DiagnosticLevelMask &M) {1352  bool Success = true;1353  for (const auto &Level : Levels) {1354    DiagnosticLevelMask const PM =1355      llvm::StringSwitch<DiagnosticLevelMask>(Level)1356        .Case("note",    DiagnosticLevelMask::Note)1357        .Case("remark",  DiagnosticLevelMask::Remark)1358        .Case("warning", DiagnosticLevelMask::Warning)1359        .Case("error",   DiagnosticLevelMask::Error)1360        .Default(DiagnosticLevelMask::None);1361    if (PM == DiagnosticLevelMask::None) {1362      Success = false;1363      Diags.Report(diag::err_drv_invalid_value) << FlagName << Level;1364    }1365    M = M | PM;1366  }1367  return Success;1368}1369 1370static void parseSanitizerKinds(StringRef FlagName,1371                                const std::vector<std::string> &Sanitizers,1372                                DiagnosticsEngine &Diags, SanitizerSet &S) {1373  for (const auto &Sanitizer : Sanitizers) {1374    SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false);1375    if (K == SanitizerMask())1376      Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;1377    else1378      S.set(K, true);1379  }1380}1381 1382static SmallVector<StringRef, 4> serializeSanitizerKinds(SanitizerSet S) {1383  SmallVector<StringRef, 4> Values;1384  serializeSanitizerSet(S, Values);1385  return Values;1386}1387 1388static SanitizerMaskCutoffs1389parseSanitizerWeightedKinds(StringRef FlagName,1390                            const std::vector<std::string> &Sanitizers,1391                            DiagnosticsEngine &Diags) {1392  SanitizerMaskCutoffs Cutoffs;1393  for (const auto &Sanitizer : Sanitizers) {1394    if (!parseSanitizerWeightedValue(Sanitizer, /*AllowGroups=*/false, Cutoffs))1395      Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;1396  }1397  return Cutoffs;1398}1399 1400static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle,1401                                           ArgList &Args, DiagnosticsEngine &D,1402                                           XRayInstrSet &S) {1403  llvm::SmallVector<StringRef, 2> BundleParts;1404  llvm::SplitString(Bundle, BundleParts, ",");1405  for (const auto &B : BundleParts) {1406    auto Mask = parseXRayInstrValue(B);1407    if (Mask == XRayInstrKind::None)1408      if (B != "none")1409        D.Report(diag::err_drv_invalid_value) << FlagName << Bundle;1410      else1411        S.Mask = Mask;1412    else if (Mask == XRayInstrKind::All)1413      S.Mask = Mask;1414    else1415      S.set(Mask, true);1416  }1417}1418 1419static std::string serializeXRayInstrumentationBundle(const XRayInstrSet &S) {1420  llvm::SmallVector<StringRef, 2> BundleParts;1421  serializeXRayInstrValue(S, BundleParts);1422  std::string Buffer;1423  llvm::raw_string_ostream OS(Buffer);1424  llvm::interleave(BundleParts, OS, [&OS](StringRef Part) { OS << Part; }, ",");1425  return Buffer;1426}1427 1428void CompilerInvocation::setDefaultPointerAuthOptions(1429    PointerAuthOptions &Opts, const LangOptions &LangOpts,1430    const llvm::Triple &Triple) {1431  assert(Triple.getArch() == llvm::Triple::aarch64);1432  if (LangOpts.PointerAuthCalls) {1433    using Key = PointerAuthSchema::ARM8_3Key;1434    using Discrimination = PointerAuthSchema::Discrimination;1435    // If you change anything here, be sure to update <ptrauth.h>.1436    Opts.FunctionPointers = PointerAuthSchema(1437        Key::ASIA, false,1438        LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type1439                                                       : Discrimination::None);1440 1441    Opts.CXXVTablePointers = PointerAuthSchema(1442        Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination,1443        LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type1444                                                    : Discrimination::None);1445 1446    if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)1447      Opts.CXXTypeInfoVTablePointer =1448          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,1449                            StdTypeInfoVTablePointerConstantDiscrimination);1450    else1451      Opts.CXXTypeInfoVTablePointer =1452          PointerAuthSchema(Key::ASDA, false, Discrimination::None);1453 1454    Opts.CXXVTTVTablePointers =1455        PointerAuthSchema(Key::ASDA, false, Discrimination::None);1456    Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers =1457        PointerAuthSchema(Key::ASIA, true, Discrimination::Decl);1458    Opts.CXXMemberFunctionPointers =1459        PointerAuthSchema(Key::ASIA, false, Discrimination::Type);1460 1461    if (LangOpts.PointerAuthInitFini) {1462      Opts.InitFiniPointers = PointerAuthSchema(1463          Key::ASIA, LangOpts.PointerAuthInitFiniAddressDiscrimination,1464          Discrimination::Constant, InitFiniPointerConstantDiscriminator);1465    }1466 1467    Opts.BlockInvocationFunctionPointers =1468        PointerAuthSchema(Key::ASIA, true, Discrimination::None);1469    Opts.BlockHelperFunctionPointers =1470        PointerAuthSchema(Key::ASIA, true, Discrimination::None);1471    Opts.BlockByrefHelperFunctionPointers =1472        PointerAuthSchema(Key::ASIA, true, Discrimination::None);1473    if (LangOpts.PointerAuthBlockDescriptorPointers)1474      Opts.BlockDescriptorPointers =1475          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,1476                            BlockDescriptorConstantDiscriminator);1477 1478    Opts.ObjCMethodListFunctionPointers =1479        PointerAuthSchema(Key::ASIA, true, Discrimination::None);1480    Opts.ObjCMethodListPointer =1481        PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,1482                          MethodListPointerConstantDiscriminator);1483    if (LangOpts.PointerAuthObjcIsa) {1484      Opts.ObjCIsaPointers =1485          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,1486                            IsaPointerConstantDiscriminator);1487      Opts.ObjCSuperPointers =1488          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,1489                            SuperPointerConstantDiscriminator);1490    }1491 1492    if (LangOpts.PointerAuthObjcClassROPointers)1493      Opts.ObjCClassROPointers =1494          PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,1495                            ClassROConstantDiscriminator);1496  }1497  Opts.ReturnAddresses = LangOpts.PointerAuthReturns;1498  Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;1499  Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos;1500  Opts.AArch64JumpTableHardening = LangOpts.AArch64JumpTableHardening;1501}1502 1503static void parsePointerAuthOptions(PointerAuthOptions &Opts,1504                                    const LangOptions &LangOpts,1505                                    const llvm::Triple &Triple,1506                                    DiagnosticsEngine &Diags) {1507  if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns &&1508      !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos &&1509      !LangOpts.AArch64JumpTableHardening)1510    return;1511 1512  CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple);1513}1514 1515void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,1516                                                 ArgumentConsumer Consumer,1517                                                 const llvm::Triple &T,1518                                                 const std::string &OutputFile,1519                                                 const LangOptions *LangOpts) {1520  const CodeGenOptions &CodeGenOpts = Opts;1521 1522  if (Opts.OptimizationLevel == 0)1523    GenerateArg(Consumer, OPT_O0);1524  else1525    GenerateArg(Consumer, OPT_O, Twine(Opts.OptimizationLevel));1526 1527#define CODEGEN_OPTION_WITH_MARSHALLING(...)                                   \1528  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)1529#include "clang/Options/Options.inc"1530#undef CODEGEN_OPTION_WITH_MARSHALLING1531 1532  if (Opts.OptimizationLevel > 0) {1533    if (Opts.Inlining == CodeGenOptions::NormalInlining)1534      GenerateArg(Consumer, OPT_finline_functions);1535    else if (Opts.Inlining == CodeGenOptions::OnlyHintInlining)1536      GenerateArg(Consumer, OPT_finline_hint_functions);1537    else if (Opts.Inlining == CodeGenOptions::OnlyAlwaysInlining)1538      GenerateArg(Consumer, OPT_fno_inline);1539  }1540 1541  if (Opts.DirectAccessExternalData && LangOpts->PICLevel != 0)1542    GenerateArg(Consumer, OPT_fdirect_access_external_data);1543  else if (!Opts.DirectAccessExternalData && LangOpts->PICLevel == 0)1544    GenerateArg(Consumer, OPT_fno_direct_access_external_data);1545 1546  std::optional<StringRef> DebugInfoVal;1547  switch (Opts.DebugInfo) {1548  case llvm::codegenoptions::DebugLineTablesOnly:1549    DebugInfoVal = "line-tables-only";1550    break;1551  case llvm::codegenoptions::DebugDirectivesOnly:1552    DebugInfoVal = "line-directives-only";1553    break;1554  case llvm::codegenoptions::DebugInfoConstructor:1555    DebugInfoVal = "constructor";1556    break;1557  case llvm::codegenoptions::LimitedDebugInfo:1558    DebugInfoVal = "limited";1559    break;1560  case llvm::codegenoptions::FullDebugInfo:1561    DebugInfoVal = "standalone";1562    break;1563  case llvm::codegenoptions::UnusedTypeInfo:1564    DebugInfoVal = "unused-types";1565    break;1566  case llvm::codegenoptions::NoDebugInfo: // default value1567    DebugInfoVal = std::nullopt;1568    break;1569  case llvm::codegenoptions::LocTrackingOnly: // implied value1570    DebugInfoVal = std::nullopt;1571    break;1572  }1573  if (DebugInfoVal)1574    GenerateArg(Consumer, OPT_debug_info_kind_EQ, *DebugInfoVal);1575 1576  for (const auto &Prefix : Opts.DebugPrefixMap)1577    GenerateArg(Consumer, OPT_fdebug_prefix_map_EQ,1578                Prefix.first + "=" + Prefix.second);1579 1580  for (const auto &Prefix : Opts.CoveragePrefixMap)1581    GenerateArg(Consumer, OPT_fcoverage_prefix_map_EQ,1582                Prefix.first + "=" + Prefix.second);1583 1584  if (Opts.NewStructPathTBAA)1585    GenerateArg(Consumer, OPT_new_struct_path_tbaa);1586 1587  if (Opts.OptimizeSize == 1)1588    GenerateArg(Consumer, OPT_O, "s");1589  else if (Opts.OptimizeSize == 2)1590    GenerateArg(Consumer, OPT_O, "z");1591 1592  // SimplifyLibCalls is set only in the absence of -fno-builtin and1593  // -ffreestanding. We'll consider that when generating them.1594 1595  // NoBuiltinFuncs are generated by LangOptions.1596 1597  if (Opts.UnrollLoops && Opts.OptimizationLevel <= 1)1598    GenerateArg(Consumer, OPT_funroll_loops);1599  else if (!Opts.UnrollLoops && Opts.OptimizationLevel > 1)1600    GenerateArg(Consumer, OPT_fno_unroll_loops);1601 1602  if (Opts.InterchangeLoops)1603    GenerateArg(Consumer, OPT_floop_interchange);1604  else1605    GenerateArg(Consumer, OPT_fno_loop_interchange);1606 1607  if (Opts.FuseLoops)1608    GenerateArg(Consumer, OPT_fexperimental_loop_fusion);1609 1610  if (!Opts.BinutilsVersion.empty())1611    GenerateArg(Consumer, OPT_fbinutils_version_EQ, Opts.BinutilsVersion);1612 1613  if (Opts.DebugNameTable ==1614      static_cast<unsigned>(llvm::DICompileUnit::DebugNameTableKind::GNU))1615    GenerateArg(Consumer, OPT_ggnu_pubnames);1616  else if (Opts.DebugNameTable ==1617           static_cast<unsigned>(1618               llvm::DICompileUnit::DebugNameTableKind::Default))1619    GenerateArg(Consumer, OPT_gpubnames);1620 1621  if (Opts.DebugTemplateAlias)1622    GenerateArg(Consumer, OPT_gtemplate_alias);1623 1624  auto TNK = Opts.getDebugSimpleTemplateNames();1625  if (TNK != llvm::codegenoptions::DebugTemplateNamesKind::Full) {1626    if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Simple)1627      GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "simple");1628    else if (TNK == llvm::codegenoptions::DebugTemplateNamesKind::Mangled)1629      GenerateArg(Consumer, OPT_gsimple_template_names_EQ, "mangled");1630  }1631  // ProfileInstrumentUsePath is marshalled automatically, no need to generate1632  // it or PGOUseInstrumentor.1633 1634  if (Opts.TimePasses) {1635    if (Opts.TimePassesPerRun)1636      GenerateArg(Consumer, OPT_ftime_report_EQ, "per-pass-run");1637    else1638      GenerateArg(Consumer, OPT_ftime_report);1639 1640    if (Opts.TimePassesJson)1641      GenerateArg(Consumer, OPT_ftime_report_json);1642  }1643 1644  if (Opts.PrepareForLTO && !Opts.PrepareForThinLTO)1645    GenerateArg(Consumer, OPT_flto_EQ, "full");1646 1647  if (Opts.PrepareForThinLTO)1648    GenerateArg(Consumer, OPT_flto_EQ, "thin");1649 1650  if (!Opts.ThinLTOIndexFile.empty())1651    GenerateArg(Consumer, OPT_fthinlto_index_EQ, Opts.ThinLTOIndexFile);1652 1653  if (Opts.SaveTempsFilePrefix == OutputFile)1654    GenerateArg(Consumer, OPT_save_temps_EQ, "obj");1655 1656  StringRef MemProfileBasename("memprof.profraw");1657  if (!Opts.MemoryProfileOutput.empty()) {1658    if (Opts.MemoryProfileOutput == MemProfileBasename) {1659      GenerateArg(Consumer, OPT_fmemory_profile);1660    } else {1661      size_t ArgLength =1662          Opts.MemoryProfileOutput.size() - MemProfileBasename.size();1663      GenerateArg(Consumer, OPT_fmemory_profile_EQ,1664                  Opts.MemoryProfileOutput.substr(0, ArgLength));1665    }1666  }1667 1668  if (memcmp(Opts.CoverageVersion, "0000", 4))1669    GenerateArg(Consumer, OPT_coverage_version_EQ,1670                StringRef(Opts.CoverageVersion, 4));1671 1672  // TODO: Check if we need to generate arguments stored in CmdArgs. (Namely1673  //  '-fembed_bitcode', which does not map to any CompilerInvocation field and1674  //  won't be generated.)1675 1676  if (Opts.XRayInstrumentationBundle.Mask != XRayInstrKind::All) {1677    std::string InstrBundle =1678        serializeXRayInstrumentationBundle(Opts.XRayInstrumentationBundle);1679    if (!InstrBundle.empty())1680      GenerateArg(Consumer, OPT_fxray_instrumentation_bundle, InstrBundle);1681  }1682 1683  if (Opts.CFProtectionReturn && Opts.CFProtectionBranch)1684    GenerateArg(Consumer, OPT_fcf_protection_EQ, "full");1685  else if (Opts.CFProtectionReturn)1686    GenerateArg(Consumer, OPT_fcf_protection_EQ, "return");1687  else if (Opts.CFProtectionBranch)1688    GenerateArg(Consumer, OPT_fcf_protection_EQ, "branch");1689 1690  if (Opts.CFProtectionBranch) {1691    switch (Opts.getCFBranchLabelScheme()) {1692    case CFBranchLabelSchemeKind::Default:1693      break;1694#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal)                                  \1695  case CFBranchLabelSchemeKind::Kind:                                          \1696    GenerateArg(Consumer, OPT_mcf_branch_label_scheme_EQ, #FlagVal);           \1697    break;1698#include "clang/Basic/CFProtectionOptions.def"1699    }1700  }1701 1702  if (Opts.FunctionReturnThunks)1703    GenerateArg(Consumer, OPT_mfunction_return_EQ, "thunk-extern");1704 1705  for (const auto &F : Opts.LinkBitcodeFiles) {1706    bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&1707                    F.PropagateAttrs && F.Internalize;1708    GenerateArg(Consumer,1709                Builtint ? OPT_mlink_builtin_bitcode : OPT_mlink_bitcode_file,1710                F.Filename);1711  }1712 1713  if (Opts.EmulatedTLS)1714    GenerateArg(Consumer, OPT_femulated_tls);1715 1716  if (Opts.FPDenormalMode != llvm::DenormalMode::getIEEE())1717    GenerateArg(Consumer, OPT_fdenormal_fp_math_EQ, Opts.FPDenormalMode.str());1718 1719  if ((Opts.FPDenormalMode != Opts.FP32DenormalMode) ||1720      (Opts.FP32DenormalMode != llvm::DenormalMode::getIEEE()))1721    GenerateArg(Consumer, OPT_fdenormal_fp_math_f32_EQ,1722                Opts.FP32DenormalMode.str());1723 1724  if (Opts.StructReturnConvention == CodeGenOptions::SRCK_OnStack) {1725    OptSpecifier Opt =1726        T.isPPC32() ? OPT_maix_struct_return : OPT_fpcc_struct_return;1727    GenerateArg(Consumer, Opt);1728  } else if (Opts.StructReturnConvention == CodeGenOptions::SRCK_InRegs) {1729    OptSpecifier Opt =1730        T.isPPC32() ? OPT_msvr4_struct_return : OPT_freg_struct_return;1731    GenerateArg(Consumer, Opt);1732  }1733 1734  if (Opts.EnableAIXExtendedAltivecABI)1735    GenerateArg(Consumer, OPT_mabi_EQ_vec_extabi);1736 1737  if (Opts.XCOFFReadOnlyPointers)1738    GenerateArg(Consumer, OPT_mxcoff_roptr);1739 1740  if (!Opts.OptRecordPasses.empty())1741    GenerateArg(Consumer, OPT_opt_record_passes, Opts.OptRecordPasses);1742 1743  if (!Opts.OptRecordFormat.empty())1744    GenerateArg(Consumer, OPT_opt_record_format, Opts.OptRecordFormat);1745 1746  GenerateOptimizationRemark(Consumer, OPT_Rpass_EQ, "pass",1747                             Opts.OptimizationRemark);1748 1749  GenerateOptimizationRemark(Consumer, OPT_Rpass_missed_EQ, "pass-missed",1750                             Opts.OptimizationRemarkMissed);1751 1752  GenerateOptimizationRemark(Consumer, OPT_Rpass_analysis_EQ, "pass-analysis",1753                             Opts.OptimizationRemarkAnalysis);1754 1755  GenerateArg(Consumer, OPT_fdiagnostics_hotness_threshold_EQ,1756              Opts.DiagnosticsHotnessThreshold1757                  ? Twine(*Opts.DiagnosticsHotnessThreshold)1758                  : "auto");1759 1760  GenerateArg(Consumer, OPT_fdiagnostics_misexpect_tolerance_EQ,1761              Twine(*Opts.DiagnosticsMisExpectTolerance));1762 1763  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeRecover))1764    GenerateArg(Consumer, OPT_fsanitize_recover_EQ, Sanitizer);1765 1766  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.SanitizeTrap))1767    GenerateArg(Consumer, OPT_fsanitize_trap_EQ, Sanitizer);1768 1769  for (StringRef Sanitizer :1770       serializeSanitizerKinds(Opts.SanitizeMergeHandlers))1771    GenerateArg(Consumer, OPT_fsanitize_merge_handlers_EQ, Sanitizer);1772 1773  SmallVector<std::string, 4> Values;1774  serializeSanitizerMaskCutoffs(Opts.SanitizeSkipHotCutoffs, Values);1775  for (std::string Sanitizer : Values)1776    GenerateArg(Consumer, OPT_fsanitize_skip_hot_cutoff_EQ, Sanitizer);1777 1778  if (Opts.AllowRuntimeCheckSkipHotCutoff) {1779    GenerateArg(Consumer, OPT_fallow_runtime_check_skip_hot_cutoff_EQ,1780                std::to_string(*Opts.AllowRuntimeCheckSkipHotCutoff));1781  }1782 1783  for (StringRef Sanitizer :1784       serializeSanitizerKinds(Opts.SanitizeAnnotateDebugInfo))1785    GenerateArg(Consumer, OPT_fsanitize_annotate_debug_info_EQ, Sanitizer);1786 1787  if (!Opts.EmitVersionIdentMetadata)1788    GenerateArg(Consumer, OPT_Qn);1789 1790  switch (Opts.FiniteLoops) {1791  case CodeGenOptions::FiniteLoopsKind::Language:1792    break;1793  case CodeGenOptions::FiniteLoopsKind::Always:1794    GenerateArg(Consumer, OPT_ffinite_loops);1795    break;1796  case CodeGenOptions::FiniteLoopsKind::Never:1797    GenerateArg(Consumer, OPT_fno_finite_loops);1798    break;1799  }1800 1801  if (Opts.StaticClosure)1802    GenerateArg(Consumer, OPT_static_libclosure);1803}1804 1805bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,1806                                          InputKind IK,1807                                          DiagnosticsEngine &Diags,1808                                          const llvm::Triple &T,1809                                          const std::string &OutputFile,1810                                          const LangOptions &LangOptsRef) {1811  unsigned NumErrorsBefore = Diags.getNumErrors();1812 1813  Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);1814 1815  // The key paths of codegen options defined in Options.td start with1816  // "CodeGenOpts.". Let's provide the expected variable name and type.1817  CodeGenOptions &CodeGenOpts = Opts;1818  // Some codegen options depend on language options. Let's provide the expected1819  // variable name and type.1820  const LangOptions *LangOpts = &LangOptsRef;1821 1822#define CODEGEN_OPTION_WITH_MARSHALLING(...)                                   \1823  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)1824#include "clang/Options/Options.inc"1825#undef CODEGEN_OPTION_WITH_MARSHALLING1826 1827  // At O0 we want to fully disable inlining outside of cases marked with1828  // 'alwaysinline' that are required for correctness.1829  if (Opts.OptimizationLevel == 0) {1830    Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);1831  } else if (const Arg *A = Args.getLastArg(options::OPT_finline_functions,1832                                            options::OPT_finline_hint_functions,1833                                            options::OPT_fno_inline_functions,1834                                            options::OPT_fno_inline)) {1835    // Explicit inlining flags can disable some or all inlining even at1836    // optimization levels above zero.1837    if (A->getOption().matches(options::OPT_finline_functions))1838      Opts.setInlining(CodeGenOptions::NormalInlining);1839    else if (A->getOption().matches(options::OPT_finline_hint_functions))1840      Opts.setInlining(CodeGenOptions::OnlyHintInlining);1841    else1842      Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);1843  } else {1844    Opts.setInlining(CodeGenOptions::NormalInlining);1845  }1846 1847  // PIC defaults to -fno-direct-access-external-data while non-PIC defaults to1848  // -fdirect-access-external-data.1849  Opts.DirectAccessExternalData =1850      Args.hasArg(OPT_fdirect_access_external_data) ||1851      (!Args.hasArg(OPT_fno_direct_access_external_data) &&1852       LangOpts->PICLevel == 0);1853 1854  if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {1855    unsigned Val =1856        llvm::StringSwitch<unsigned>(A->getValue())1857            .Case("line-tables-only", llvm::codegenoptions::DebugLineTablesOnly)1858            .Case("line-directives-only",1859                  llvm::codegenoptions::DebugDirectivesOnly)1860            .Case("constructor", llvm::codegenoptions::DebugInfoConstructor)1861            .Case("limited", llvm::codegenoptions::LimitedDebugInfo)1862            .Case("standalone", llvm::codegenoptions::FullDebugInfo)1863            .Case("unused-types", llvm::codegenoptions::UnusedTypeInfo)1864            .Default(~0U);1865    if (Val == ~0U)1866      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)1867                                                << A->getValue();1868    else1869      Opts.setDebugInfo(static_cast<llvm::codegenoptions::DebugInfoKind>(Val));1870  }1871 1872  // If -fuse-ctor-homing is set and limited debug info is already on, then use1873  // constructor homing, and vice versa for -fno-use-ctor-homing.1874  if (const Arg *A =1875          Args.getLastArg(OPT_fuse_ctor_homing, OPT_fno_use_ctor_homing)) {1876    if (A->getOption().matches(OPT_fuse_ctor_homing) &&1877        Opts.getDebugInfo() == llvm::codegenoptions::LimitedDebugInfo)1878      Opts.setDebugInfo(llvm::codegenoptions::DebugInfoConstructor);1879    if (A->getOption().matches(OPT_fno_use_ctor_homing) &&1880        Opts.getDebugInfo() == llvm::codegenoptions::DebugInfoConstructor)1881      Opts.setDebugInfo(llvm::codegenoptions::LimitedDebugInfo);1882  }1883 1884  for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) {1885    auto Split = StringRef(Arg).split('=');1886    Opts.DebugPrefixMap.emplace_back(Split.first, Split.second);1887  }1888 1889  for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {1890    auto Split = StringRef(Arg).split('=');1891    Opts.CoveragePrefixMap.emplace_back(Split.first, Split.second);1892  }1893 1894  const llvm::Triple::ArchType DebugEntryValueArchs[] = {1895      llvm::Triple::x86,     llvm::Triple::x86_64, llvm::Triple::aarch64,1896      llvm::Triple::arm,     llvm::Triple::armeb,  llvm::Triple::mips,1897      llvm::Triple::mipsel,  llvm::Triple::mips64, llvm::Triple::mips64el,1898      llvm::Triple::riscv32, llvm::Triple::riscv64};1899 1900  if (Opts.OptimizationLevel > 0 && Opts.hasReducedDebugInfo() &&1901      llvm::is_contained(DebugEntryValueArchs, T.getArch()))1902    Opts.EmitCallSiteInfo = true;1903 1904  if (!Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) {1905    Diags.Report(diag::warn_ignoring_verify_debuginfo_preserve_export)1906        << Opts.DIBugsReportFilePath;1907    Opts.DIBugsReportFilePath = "";1908  }1909 1910  Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&1911                           Args.hasArg(OPT_new_struct_path_tbaa);1912  Opts.OptimizeSize = getOptimizationLevelSize(Args);1913  Opts.SimplifyLibCalls = !LangOpts->NoBuiltin;1914  if (Opts.SimplifyLibCalls)1915    Opts.NoBuiltinFuncs = LangOpts->NoBuiltinFuncs;1916  Opts.UnrollLoops =1917      Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,1918                   (Opts.OptimizationLevel > 1));1919  Opts.InterchangeLoops =1920      Args.hasFlag(OPT_floop_interchange, OPT_fno_loop_interchange, false);1921  Opts.FuseLoops = Args.hasFlag(OPT_fexperimental_loop_fusion,1922                                OPT_fno_experimental_loop_fusion, false);1923  Opts.BinutilsVersion =1924      std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));1925 1926  Opts.DebugTemplateAlias = Args.hasArg(OPT_gtemplate_alias);1927 1928  Opts.DebugNameTable = static_cast<unsigned>(1929      Args.hasArg(OPT_ggnu_pubnames)1930          ? llvm::DICompileUnit::DebugNameTableKind::GNU1931          : Args.hasArg(OPT_gpubnames)1932                ? llvm::DICompileUnit::DebugNameTableKind::Default1933                : llvm::DICompileUnit::DebugNameTableKind::None);1934  if (const Arg *A = Args.getLastArg(OPT_gsimple_template_names_EQ)) {1935    StringRef Value = A->getValue();1936    if (Value != "simple" && Value != "mangled")1937      Diags.Report(diag::err_drv_unsupported_option_argument)1938          << A->getSpelling() << A->getValue();1939    Opts.setDebugSimpleTemplateNames(1940        StringRef(A->getValue()) == "simple"1941            ? llvm::codegenoptions::DebugTemplateNamesKind::Simple1942            : llvm::codegenoptions::DebugTemplateNamesKind::Mangled);1943  }1944 1945  if (Args.hasArg(OPT_ftime_report, OPT_ftime_report_EQ, OPT_ftime_report_json,1946                  OPT_stats_file_timers)) {1947    Opts.TimePasses = true;1948 1949    // -ftime-report= is only for new pass manager.1950    if (const Arg *EQ = Args.getLastArg(OPT_ftime_report_EQ)) {1951      StringRef Val = EQ->getValue();1952      if (Val == "per-pass")1953        Opts.TimePassesPerRun = false;1954      else if (Val == "per-pass-run")1955        Opts.TimePassesPerRun = true;1956      else1957        Diags.Report(diag::err_drv_invalid_value)1958            << EQ->getAsString(Args) << EQ->getValue();1959    }1960 1961    if (Args.getLastArg(OPT_ftime_report_json))1962      Opts.TimePassesJson = true;1963  }1964 1965  Opts.PrepareForLTO = false;1966  Opts.PrepareForThinLTO = false;1967  if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {1968    Opts.PrepareForLTO = true;1969    StringRef S = A->getValue();1970    if (S == "thin")1971      Opts.PrepareForThinLTO = true;1972    else if (S != "full")1973      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;1974    if (Args.hasArg(OPT_funified_lto))1975      Opts.PrepareForThinLTO = true;1976  }1977  if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {1978    if (IK.getLanguage() != Language::LLVM_IR)1979      Diags.Report(diag::err_drv_argument_only_allowed_with)1980          << A->getAsString(Args) << "-x ir";1981    Opts.ThinLTOIndexFile =1982        std::string(Args.getLastArgValue(OPT_fthinlto_index_EQ));1983  }1984  if (Arg *A = Args.getLastArg(OPT_save_temps_EQ))1985    Opts.SaveTempsFilePrefix =1986        llvm::StringSwitch<std::string>(A->getValue())1987            .Case("obj", OutputFile)1988            .Default(llvm::sys::path::filename(OutputFile).str());1989 1990  // The memory profile runtime appends the pid to make this name more unique.1991  const char *MemProfileBasename = "memprof.profraw";1992  if (Args.hasArg(OPT_fmemory_profile_EQ)) {1993    SmallString<128> Path(Args.getLastArgValue(OPT_fmemory_profile_EQ));1994    llvm::sys::path::append(Path, MemProfileBasename);1995    Opts.MemoryProfileOutput = std::string(Path);1996  } else if (Args.hasArg(OPT_fmemory_profile))1997    Opts.MemoryProfileOutput = MemProfileBasename;1998 1999  if (Opts.CoverageNotesFile.size() || Opts.CoverageDataFile.size()) {2000    if (Args.hasArg(OPT_coverage_version_EQ)) {2001      StringRef CoverageVersion = Args.getLastArgValue(OPT_coverage_version_EQ);2002      if (CoverageVersion.size() != 4) {2003        Diags.Report(diag::err_drv_invalid_value)2004            << Args.getLastArg(OPT_coverage_version_EQ)->getAsString(Args)2005            << CoverageVersion;2006      } else {2007        memcpy(Opts.CoverageVersion, CoverageVersion.data(), 4);2008      }2009    }2010  }2011  // FIXME: For backend options that are not yet recorded as function2012  // attributes in the IR, keep track of them so we can embed them in a2013  // separate data section and use them when building the bitcode.2014  for (const auto &A : Args) {2015    // Do not encode output and input.2016    if (A->getOption().getID() == options::OPT_o ||2017        A->getOption().getID() == options::OPT_INPUT ||2018        A->getOption().getID() == options::OPT_x ||2019        A->getOption().getID() == options::OPT_fembed_bitcode ||2020        A->getOption().matches(options::OPT_W_Group))2021      continue;2022    ArgStringList ASL;2023    A->render(Args, ASL);2024    for (const auto &arg : ASL) {2025      StringRef ArgStr(arg);2026      llvm::append_range(Opts.CmdArgs, ArgStr);2027      // using \00 to separate each commandline options.2028      Opts.CmdArgs.push_back('\0');2029    }2030  }2031 2032  auto XRayInstrBundles =2033      Args.getAllArgValues(OPT_fxray_instrumentation_bundle);2034  if (XRayInstrBundles.empty())2035    Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All;2036  else2037    for (const auto &A : XRayInstrBundles)2038      parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args,2039                                     Diags, Opts.XRayInstrumentationBundle);2040 2041  if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {2042    StringRef Name = A->getValue();2043    if (Name == "full") {2044      Opts.CFProtectionReturn = 1;2045      Opts.CFProtectionBranch = 1;2046    } else if (Name == "return")2047      Opts.CFProtectionReturn = 1;2048    else if (Name == "branch")2049      Opts.CFProtectionBranch = 1;2050    else if (Name != "none")2051      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;2052  }2053 2054  if (Opts.CFProtectionBranch && T.isRISCV()) {2055    if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {2056      const auto Scheme =2057          llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())2058#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal)                                  \2059  .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)2060#include "clang/Basic/CFProtectionOptions.def"2061              .Default(CFBranchLabelSchemeKind::Default);2062      if (Scheme != CFBranchLabelSchemeKind::Default)2063        Opts.setCFBranchLabelScheme(Scheme);2064      else2065        Diags.Report(diag::err_drv_invalid_value)2066            << A->getAsString(Args) << A->getValue();2067    }2068  }2069 2070  if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {2071    auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())2072                   .Case("keep", llvm::FunctionReturnThunksKind::Keep)2073                   .Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)2074                   .Default(llvm::FunctionReturnThunksKind::Invalid);2075    // SystemZ might want to add support for "expolines."2076    if (!T.isX86())2077      Diags.Report(diag::err_drv_argument_not_allowed_with)2078          << A->getSpelling() << T.getTriple();2079    else if (Val == llvm::FunctionReturnThunksKind::Invalid)2080      Diags.Report(diag::err_drv_invalid_value)2081          << A->getAsString(Args) << A->getValue();2082    else if (Val == llvm::FunctionReturnThunksKind::Extern &&2083             Args.getLastArgValue(OPT_mcmodel_EQ) == "large")2084      Diags.Report(diag::err_drv_argument_not_allowed_with)2085          << A->getAsString(Args)2086          << Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);2087    else2088      Opts.FunctionReturnThunks = static_cast<unsigned>(Val);2089  }2090 2091  for (auto *A :2092       Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_builtin_bitcode)) {2093    CodeGenOptions::BitcodeFileToLink F;2094    F.Filename = A->getValue();2095    if (A->getOption().matches(OPT_mlink_builtin_bitcode)) {2096      F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;2097      // When linking CUDA bitcode, propagate function attributes so that2098      // e.g. libdevice gets fast-math attrs if we're building with fast-math.2099      F.PropagateAttrs = true;2100      F.Internalize = true;2101    }2102    Opts.LinkBitcodeFiles.push_back(F);2103  }2104 2105  if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {2106    StringRef Val = A->getValue();2107    Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);2108    Opts.FP32DenormalMode = Opts.FPDenormalMode;2109    if (!Opts.FPDenormalMode.isValid())2110      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;2111  }2112 2113  if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_f32_EQ)) {2114    StringRef Val = A->getValue();2115    Opts.FP32DenormalMode = llvm::parseDenormalFPAttribute(Val);2116    if (!Opts.FP32DenormalMode.isValid())2117      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;2118  }2119 2120  // X86_32 has -fppc-struct-return and -freg-struct-return.2121  // PPC32 has -maix-struct-return and -msvr4-struct-return.2122  if (Arg *A =2123          Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return,2124                          OPT_maix_struct_return, OPT_msvr4_struct_return)) {2125    // TODO: We might want to consider enabling these options on AIX in the2126    // future.2127    if (T.isOSAIX())2128      Diags.Report(diag::err_drv_unsupported_opt_for_target)2129          << A->getSpelling() << T.str();2130 2131    const Option &O = A->getOption();2132    if (O.matches(OPT_fpcc_struct_return) ||2133        O.matches(OPT_maix_struct_return)) {2134      Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack);2135    } else {2136      assert(O.matches(OPT_freg_struct_return) ||2137             O.matches(OPT_msvr4_struct_return));2138      Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs);2139    }2140  }2141 2142  if (Arg *A = Args.getLastArg(OPT_mxcoff_roptr)) {2143    if (!T.isOSAIX())2144      Diags.Report(diag::err_drv_unsupported_opt_for_target)2145          << A->getSpelling() << T.str();2146 2147    // Since the storage mapping class is specified per csect,2148    // without using data sections, it is less effective to use read-only2149    // pointers. Using read-only pointers may cause other RO variables in the2150    // same csect to become RW when the linker acts upon `-bforceimprw`;2151    // therefore, we require that separate data sections2152    // are used when `-mxcoff-roptr` is in effect. We respect the setting of2153    // data-sections since we have not found reasons to do otherwise that2154    // overcome the user surprise of not respecting the setting.2155    if (!Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false))2156      Diags.Report(diag::err_roptr_requires_data_sections);2157 2158    Opts.XCOFFReadOnlyPointers = true;2159  }2160 2161  if (Arg *A = Args.getLastArg(OPT_mabi_EQ_quadword_atomics)) {2162    if (!T.isOSAIX() || T.isPPC32())2163      Diags.Report(diag::err_drv_unsupported_opt_for_target)2164        << A->getSpelling() << T.str();2165  }2166 2167  bool NeedLocTracking = false;2168 2169  if (!Opts.OptRecordFile.empty())2170    NeedLocTracking = true;2171 2172  if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) {2173    Opts.OptRecordPasses = A->getValue();2174    NeedLocTracking = true;2175  }2176 2177  if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {2178    Opts.OptRecordFormat = A->getValue();2179    NeedLocTracking = true;2180  }2181 2182  Opts.OptimizationRemark =2183      ParseOptimizationRemark(Diags, Args, OPT_Rpass_EQ, "pass");2184 2185  Opts.OptimizationRemarkMissed =2186      ParseOptimizationRemark(Diags, Args, OPT_Rpass_missed_EQ, "pass-missed");2187 2188  Opts.OptimizationRemarkAnalysis = ParseOptimizationRemark(2189      Diags, Args, OPT_Rpass_analysis_EQ, "pass-analysis");2190 2191  NeedLocTracking |= Opts.OptimizationRemark.hasValidPattern() ||2192                     Opts.OptimizationRemarkMissed.hasValidPattern() ||2193                     Opts.OptimizationRemarkAnalysis.hasValidPattern();2194 2195  bool UsingSampleProfile = !Opts.SampleProfileFile.empty();2196  bool UsingProfile =2197      UsingSampleProfile || !Opts.ProfileInstrumentUsePath.empty();2198 2199  if (Opts.DiagnosticsWithHotness && !UsingProfile &&2200      // An IR file will contain PGO as metadata2201      IK.getLanguage() != Language::LLVM_IR)2202    Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)2203        << "-fdiagnostics-show-hotness";2204 2205  // Parse remarks hotness threshold. Valid value is either integer or 'auto'.2206  if (auto *arg =2207          Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {2208    auto ResultOrErr =2209        llvm::remarks::parseHotnessThresholdOption(arg->getValue());2210 2211    if (!ResultOrErr) {2212      Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold)2213          << "-fdiagnostics-hotness-threshold=";2214    } else {2215      Opts.DiagnosticsHotnessThreshold = *ResultOrErr;2216      if ((!Opts.DiagnosticsHotnessThreshold ||2217           *Opts.DiagnosticsHotnessThreshold > 0) &&2218          !UsingProfile)2219        Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)2220            << "-fdiagnostics-hotness-threshold=";2221    }2222  }2223 2224  if (auto *arg =2225          Args.getLastArg(options::OPT_fdiagnostics_misexpect_tolerance_EQ)) {2226    auto ResultOrErr = parseToleranceOption(arg->getValue());2227 2228    if (!ResultOrErr) {2229      Diags.Report(diag::err_drv_invalid_diagnotics_misexpect_tolerance)2230          << "-fdiagnostics-misexpect-tolerance=";2231    } else {2232      Opts.DiagnosticsMisExpectTolerance = *ResultOrErr;2233      if ((!Opts.DiagnosticsMisExpectTolerance ||2234           *Opts.DiagnosticsMisExpectTolerance > 0) &&2235          !UsingProfile)2236        Diags.Report(diag::warn_drv_diagnostics_misexpect_requires_pgo)2237            << "-fdiagnostics-misexpect-tolerance=";2238    }2239  }2240 2241  // If the user requested to use a sample profile for PGO, then the2242  // backend will need to track source location information so the profile2243  // can be incorporated into the IR.2244  if (UsingSampleProfile)2245    NeedLocTracking = true;2246 2247  if (!Opts.StackUsageOutput.empty())2248    NeedLocTracking = true;2249 2250  // If the user requested a flag that requires source locations available in2251  // the backend, make sure that the backend tracks source location information.2252  if (NeedLocTracking &&2253      Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)2254    Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);2255 2256  // Parse -fsanitize-recover= arguments.2257  // FIXME: Report unrecoverable sanitizers incorrectly specified here.2258  parseSanitizerKinds("-fsanitize-recover=",2259                      Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,2260                      Opts.SanitizeRecover);2261  parseSanitizerKinds("-fsanitize-trap=",2262                      Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags,2263                      Opts.SanitizeTrap);2264  parseSanitizerKinds("-fsanitize-merge=",2265                      Args.getAllArgValues(OPT_fsanitize_merge_handlers_EQ),2266                      Diags, Opts.SanitizeMergeHandlers);2267 2268  // Parse -fsanitize-skip-hot-cutoff= arguments.2269  Opts.SanitizeSkipHotCutoffs = parseSanitizerWeightedKinds(2270      "-fsanitize-skip-hot-cutoff=",2271      Args.getAllArgValues(OPT_fsanitize_skip_hot_cutoff_EQ), Diags);2272 2273  parseSanitizerKinds(2274      "-fsanitize-annotate-debug-info=",2275      Args.getAllArgValues(OPT_fsanitize_annotate_debug_info_EQ), Diags,2276      Opts.SanitizeAnnotateDebugInfo);2277 2278  if (StringRef V =2279          Args.getLastArgValue(OPT_fallow_runtime_check_skip_hot_cutoff_EQ);2280      !V.empty()) {2281    double A;2282    if (V.getAsDouble(A) || A < 0.0 || A > 1.0) {2283      Diags.Report(diag::err_drv_invalid_value)2284          << "-fallow-runtime-check-skip-hot-cutoff=" << V;2285    } else {2286      Opts.AllowRuntimeCheckSkipHotCutoff = A;2287    }2288  }2289 2290  Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);2291 2292  if (!LangOpts->CUDAIsDevice)2293    parsePointerAuthOptions(Opts.PointerAuth, *LangOpts, T, Diags);2294 2295  if (Args.hasArg(options::OPT_ffinite_loops))2296    Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;2297  else if (Args.hasArg(options::OPT_fno_finite_loops))2298    Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;2299 2300  Opts.EmitIEEENaNCompliantInsts = Args.hasFlag(2301      options::OPT_mamdgpu_ieee, options::OPT_mno_amdgpu_ieee, true);2302  if (!Opts.EmitIEEENaNCompliantInsts && !LangOptsRef.NoHonorNaNs)2303    Diags.Report(diag::err_drv_amdgpu_ieee_without_no_honor_nans);2304 2305  Opts.StaticClosure = Args.hasArg(options::OPT_static_libclosure);2306 2307  return Diags.getNumErrors() == NumErrorsBefore;2308}2309 2310static void GenerateDependencyOutputArgs(const DependencyOutputOptions &Opts,2311                                         ArgumentConsumer Consumer) {2312  const DependencyOutputOptions &DependencyOutputOpts = Opts;2313#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...)                         \2314  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2315#include "clang/Options/Options.inc"2316#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING2317 2318  if (Opts.ShowIncludesDest != ShowIncludesDestination::None)2319    GenerateArg(Consumer, OPT_show_includes);2320 2321  for (const auto &Dep : Opts.ExtraDeps) {2322    switch (Dep.second) {2323    case EDK_SanitizeIgnorelist:2324      // Sanitizer ignorelist arguments are generated from LanguageOptions.2325      continue;2326    case EDK_ModuleFile:2327      // Module file arguments are generated from FrontendOptions and2328      // HeaderSearchOptions.2329      continue;2330    case EDK_ProfileList:2331      // Profile list arguments are generated from LanguageOptions via the2332      // marshalling infrastructure.2333      continue;2334    case EDK_DepFileEntry:2335      GenerateArg(Consumer, OPT_fdepfile_entry, Dep.first);2336      break;2337    }2338  }2339}2340 2341static bool ParseDependencyOutputArgs(DependencyOutputOptions &Opts,2342                                      ArgList &Args, DiagnosticsEngine &Diags,2343                                      frontend::ActionKind Action,2344                                      bool ShowLineMarkers) {2345  unsigned NumErrorsBefore = Diags.getNumErrors();2346 2347  DependencyOutputOptions &DependencyOutputOpts = Opts;2348#define DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING(...)                         \2349  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)2350#include "clang/Options/Options.inc"2351#undef DEPENDENCY_OUTPUT_OPTION_WITH_MARSHALLING2352 2353  if (Args.hasArg(OPT_show_includes)) {2354    // Writing both /showIncludes and preprocessor output to stdout2355    // would produce interleaved output, so use stderr for /showIncludes.2356    // This behaves the same as cl.exe, when /E, /EP or /P are passed.2357    if (Action == frontend::PrintPreprocessedInput || !ShowLineMarkers)2358      Opts.ShowIncludesDest = ShowIncludesDestination::Stderr;2359    else2360      Opts.ShowIncludesDest = ShowIncludesDestination::Stdout;2361  } else {2362    Opts.ShowIncludesDest = ShowIncludesDestination::None;2363  }2364 2365  // Add sanitizer ignorelists as extra dependencies.2366  // They won't be discovered by the regular preprocessor, so2367  // we let make / ninja to know about this implicit dependency.2368  if (!Args.hasArg(OPT_fno_sanitize_ignorelist)) {2369    for (const auto *A : Args.filtered(OPT_fsanitize_ignorelist_EQ)) {2370      StringRef Val = A->getValue();2371      if (!Val.contains('='))2372        Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);2373    }2374    if (Opts.IncludeSystemHeaders) {2375      for (const auto *A : Args.filtered(OPT_fsanitize_system_ignorelist_EQ)) {2376        StringRef Val = A->getValue();2377        if (!Val.contains('='))2378          Opts.ExtraDeps.emplace_back(std::string(Val), EDK_SanitizeIgnorelist);2379      }2380    }2381  }2382 2383  // -fprofile-list= dependencies.2384  for (const auto &Filename : Args.getAllArgValues(OPT_fprofile_list_EQ))2385    Opts.ExtraDeps.emplace_back(Filename, EDK_ProfileList);2386 2387  // Propagate the extra dependencies.2388  for (const auto *A : Args.filtered(OPT_fdepfile_entry))2389    Opts.ExtraDeps.emplace_back(A->getValue(), EDK_DepFileEntry);2390 2391  // Only the -fmodule-file=<file> form.2392  for (const auto *A : Args.filtered(OPT_fmodule_file)) {2393    StringRef Val = A->getValue();2394    if (!Val.contains('='))2395      Opts.ExtraDeps.emplace_back(std::string(Val), EDK_ModuleFile);2396  }2397 2398  // Check for invalid combinations of header-include-format2399  // and header-include-filtering.2400  if (Opts.HeaderIncludeFormat == HIFMT_Textual &&2401      Opts.HeaderIncludeFiltering != HIFIL_None) {2402    if (Args.hasArg(OPT_header_include_format_EQ))2403      Diags.Report(diag::err_drv_print_header_cc1_invalid_combination)2404          << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat)2405          << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering);2406    else2407      Diags.Report(diag::err_drv_print_header_cc1_invalid_filtering)2408          << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering);2409  } else if (Opts.HeaderIncludeFormat == HIFMT_JSON &&2410             Opts.HeaderIncludeFiltering == HIFIL_None) {2411    if (Args.hasArg(OPT_header_include_filtering_EQ))2412      Diags.Report(diag::err_drv_print_header_cc1_invalid_combination)2413          << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat)2414          << headerIncludeFilteringKindToString(Opts.HeaderIncludeFiltering);2415    else2416      Diags.Report(diag::err_drv_print_header_cc1_invalid_format)2417          << headerIncludeFormatKindToString(Opts.HeaderIncludeFormat);2418  }2419 2420  return Diags.getNumErrors() == NumErrorsBefore;2421}2422 2423static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {2424  // Color diagnostics default to auto ("on" if terminal supports) in the driver2425  // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.2426  // Support both clang's -f[no-]color-diagnostics and gcc's2427  // -f[no-]diagnostics-colors[=never|always|auto].2428  enum {2429    Colors_On,2430    Colors_Off,2431    Colors_Auto2432  } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;2433  for (auto *A : Args) {2434    const Option &O = A->getOption();2435    if (O.matches(options::OPT_fcolor_diagnostics)) {2436      ShowColors = Colors_On;2437    } else if (O.matches(options::OPT_fno_color_diagnostics)) {2438      ShowColors = Colors_Off;2439    } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {2440      StringRef Value(A->getValue());2441      if (Value == "always")2442        ShowColors = Colors_On;2443      else if (Value == "never")2444        ShowColors = Colors_Off;2445      else if (Value == "auto")2446        ShowColors = Colors_Auto;2447    }2448  }2449  return ShowColors == Colors_On ||2450         (ShowColors == Colors_Auto &&2451          llvm::sys::Process::StandardErrHasColors());2452}2453 2454static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,2455                                DiagnosticsEngine &Diags) {2456  bool Success = true;2457  for (const auto &Prefix : VerifyPrefixes) {2458    // Every prefix must start with a letter and contain only alphanumeric2459    // characters, hyphens, and underscores.2460    auto BadChar = llvm::find_if(Prefix, [](char C) {2461      return !isAlphanumeric(C) && C != '-' && C != '_';2462    });2463    if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {2464      Success = false;2465      Diags.Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;2466      Diags.Report(diag::note_drv_verify_prefix_spelling);2467    }2468  }2469  return Success;2470}2471 2472static void GenerateFileSystemArgs(const FileSystemOptions &Opts,2473                                   ArgumentConsumer Consumer) {2474  const FileSystemOptions &FileSystemOpts = Opts;2475 2476#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...)                               \2477  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2478#include "clang/Options/Options.inc"2479#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING2480}2481 2482static bool ParseFileSystemArgs(FileSystemOptions &Opts, const ArgList &Args,2483                                DiagnosticsEngine &Diags) {2484  unsigned NumErrorsBefore = Diags.getNumErrors();2485 2486  FileSystemOptions &FileSystemOpts = Opts;2487 2488#define FILE_SYSTEM_OPTION_WITH_MARSHALLING(...)                               \2489  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)2490#include "clang/Options/Options.inc"2491#undef FILE_SYSTEM_OPTION_WITH_MARSHALLING2492 2493  return Diags.getNumErrors() == NumErrorsBefore;2494}2495 2496static void GenerateMigratorArgs(const MigratorOptions &Opts,2497                                 ArgumentConsumer Consumer) {2498  const MigratorOptions &MigratorOpts = Opts;2499#define MIGRATOR_OPTION_WITH_MARSHALLING(...)                                  \2500  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2501#include "clang/Options/Options.inc"2502#undef MIGRATOR_OPTION_WITH_MARSHALLING2503}2504 2505static bool ParseMigratorArgs(MigratorOptions &Opts, const ArgList &Args,2506                              DiagnosticsEngine &Diags) {2507  unsigned NumErrorsBefore = Diags.getNumErrors();2508 2509  MigratorOptions &MigratorOpts = Opts;2510 2511#define MIGRATOR_OPTION_WITH_MARSHALLING(...)                                  \2512  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)2513#include "clang/Options/Options.inc"2514#undef MIGRATOR_OPTION_WITH_MARSHALLING2515 2516  return Diags.getNumErrors() == NumErrorsBefore;2517}2518 2519void CompilerInvocationBase::GenerateDiagnosticArgs(2520    const DiagnosticOptions &Opts, ArgumentConsumer Consumer,2521    bool DefaultDiagColor) {2522  const DiagnosticOptions *DiagnosticOpts = &Opts;2523#define DIAG_OPTION_WITH_MARSHALLING(...)                                      \2524  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2525#include "clang/Options/Options.inc"2526#undef DIAG_OPTION_WITH_MARSHALLING2527 2528  if (!Opts.DiagnosticSerializationFile.empty())2529    GenerateArg(Consumer, OPT_diagnostic_serialized_file,2530                Opts.DiagnosticSerializationFile);2531 2532  if (Opts.ShowColors)2533    GenerateArg(Consumer, OPT_fcolor_diagnostics);2534 2535  if (Opts.VerifyDiagnostics &&2536      llvm::is_contained(Opts.VerifyPrefixes, "expected"))2537    GenerateArg(Consumer, OPT_verify);2538 2539  for (const auto &Prefix : Opts.VerifyPrefixes)2540    if (Prefix != "expected")2541      GenerateArg(Consumer, OPT_verify_EQ, Prefix);2542 2543  DiagnosticLevelMask VIU = Opts.getVerifyIgnoreUnexpected();2544  if (VIU == DiagnosticLevelMask::None) {2545    // This is the default, don't generate anything.2546  } else if (VIU == DiagnosticLevelMask::All) {2547    GenerateArg(Consumer, OPT_verify_ignore_unexpected);2548  } else {2549    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Note) != 0)2550      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "note");2551    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Remark) != 0)2552      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "remark");2553    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Warning) != 0)2554      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "warning");2555    if (static_cast<unsigned>(VIU & DiagnosticLevelMask::Error) != 0)2556      GenerateArg(Consumer, OPT_verify_ignore_unexpected_EQ, "error");2557  }2558 2559  for (const auto &Warning : Opts.Warnings) {2560    // This option is automatically generated from UndefPrefixes.2561    if (Warning == "undef-prefix")2562      continue;2563    // This option is automatically generated from CheckConstexprFunctionBodies.2564    if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")2565      continue;2566    Consumer(StringRef("-W") + Warning);2567  }2568 2569  for (const auto &Remark : Opts.Remarks) {2570    // These arguments are generated from OptimizationRemark fields of2571    // CodeGenOptions.2572    StringRef IgnoredRemarks[] = {"pass",          "no-pass",2573                                  "pass-analysis", "no-pass-analysis",2574                                  "pass-missed",   "no-pass-missed"};2575    if (llvm::is_contained(IgnoredRemarks, Remark))2576      continue;2577 2578    Consumer(StringRef("-R") + Remark);2579  }2580 2581  if (!Opts.DiagnosticSuppressionMappingsFile.empty()) {2582    GenerateArg(Consumer, OPT_warning_suppression_mappings_EQ,2583                Opts.DiagnosticSuppressionMappingsFile);2584  }2585}2586 2587std::unique_ptr<DiagnosticOptions>2588clang::CreateAndPopulateDiagOpts(ArrayRef<const char *> Argv) {2589  auto DiagOpts = std::make_unique<DiagnosticOptions>();2590  unsigned MissingArgIndex, MissingArgCount;2591  InputArgList Args = getDriverOptTable().ParseArgs(2592      Argv.slice(1), MissingArgIndex, MissingArgCount);2593 2594  bool ShowColors = true;2595  if (std::optional<std::string> NoColor =2596          llvm::sys::Process::GetEnv("NO_COLOR");2597      NoColor && !NoColor->empty()) {2598    // If the user set the NO_COLOR environment variable, we'll honor that2599    // unless the command line overrides it.2600    ShowColors = false;2601  }2602 2603  // We ignore MissingArgCount and the return value of ParseDiagnosticArgs.2604  // Any errors that would be diagnosed here will also be diagnosed later,2605  // when the DiagnosticsEngine actually exists.2606  (void)ParseDiagnosticArgs(*DiagOpts, Args, /*Diags=*/nullptr, ShowColors);2607  return DiagOpts;2608}2609 2610bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,2611                                DiagnosticsEngine *Diags,2612                                bool DefaultDiagColor) {2613  std::optional<DiagnosticOptions> IgnoringDiagOpts;2614  std::optional<DiagnosticsEngine> IgnoringDiags;2615  if (!Diags) {2616    IgnoringDiagOpts.emplace();2617    IgnoringDiags.emplace(DiagnosticIDs::create(), *IgnoringDiagOpts,2618                          new IgnoringDiagConsumer());2619    Diags = &*IgnoringDiags;2620  }2621 2622  unsigned NumErrorsBefore = Diags->getNumErrors();2623 2624  // The key paths of diagnostic options defined in Options.td start with2625  // "DiagnosticOpts->". Let's provide the expected variable name and type.2626  DiagnosticOptions *DiagnosticOpts = &Opts;2627 2628#define DIAG_OPTION_WITH_MARSHALLING(...)                                      \2629  PARSE_OPTION_WITH_MARSHALLING(Args, *Diags, __VA_ARGS__)2630#include "clang/Options/Options.inc"2631#undef DIAG_OPTION_WITH_MARSHALLING2632 2633  llvm::sys::Process::UseANSIEscapeCodes(Opts.UseANSIEscapeCodes);2634 2635  if (Arg *A =2636          Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))2637    Opts.DiagnosticSerializationFile = A->getValue();2638  Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);2639 2640  Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);2641  Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);2642  if (Args.hasArg(OPT_verify))2643    Opts.VerifyPrefixes.push_back("expected");2644  // Keep VerifyPrefixes in its original order for the sake of diagnostics, and2645  // then sort it to prepare for fast lookup using std::binary_search.2646  if (!checkVerifyPrefixes(Opts.VerifyPrefixes, *Diags))2647    Opts.VerifyDiagnostics = false;2648  else2649    llvm::sort(Opts.VerifyPrefixes);2650  DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;2651  parseDiagnosticLevelMask(2652      "-verify-ignore-unexpected=",2653      Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), *Diags, DiagMask);2654  if (Args.hasArg(OPT_verify_ignore_unexpected))2655    DiagMask = DiagnosticLevelMask::All;2656  Opts.setVerifyIgnoreUnexpected(DiagMask);2657  if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {2658    Diags->Report(diag::warn_ignoring_ftabstop_value)2659        << Opts.TabStop << DiagnosticOptions::DefaultTabStop;2660    Opts.TabStop = DiagnosticOptions::DefaultTabStop;2661  }2662 2663  if (const Arg *A = Args.getLastArg(OPT_warning_suppression_mappings_EQ))2664    Opts.DiagnosticSuppressionMappingsFile = A->getValue();2665 2666  addDiagnosticArgs(Args, OPT_W_Group, OPT_W_value_Group, Opts.Warnings);2667  addDiagnosticArgs(Args, OPT_R_Group, OPT_R_value_Group, Opts.Remarks);2668 2669  return Diags->getNumErrors() == NumErrorsBefore;2670}2671 2672unsigned clang::getOptimizationLevel(ArgList &Args, InputKind IK,2673                                     DiagnosticsEngine &Diags) {2674  unsigned DefaultOpt = 0;2675  if ((IK.getLanguage() == Language::OpenCL ||2676       IK.getLanguage() == Language::OpenCLCXX) &&2677      !Args.hasArg(OPT_cl_opt_disable))2678    DefaultOpt = 2;2679 2680  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {2681    if (A->getOption().matches(options::OPT_O0))2682      return 0;2683 2684    if (A->getOption().matches(options::OPT_Ofast))2685      return 3;2686 2687    assert(A->getOption().matches(options::OPT_O));2688 2689    StringRef S(A->getValue());2690    if (S == "s" || S == "z")2691      return 2;2692 2693    if (S == "g")2694      return 1;2695 2696    DefaultOpt = getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);2697  }2698 2699  unsigned MaxOptLevel = 3;2700  if (DefaultOpt > MaxOptLevel) {2701    // If the optimization level is not supported, fall back on the default2702    // optimization2703    Diags.Report(diag::warn_drv_optimization_value)2704        << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;2705    DefaultOpt = MaxOptLevel;2706  }2707 2708  return DefaultOpt;2709}2710 2711unsigned clang::getOptimizationLevelSize(ArgList &Args) {2712  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {2713    if (A->getOption().matches(options::OPT_O)) {2714      switch (A->getValue()[0]) {2715      default:2716        return 0;2717      case 's':2718        return 1;2719      case 'z':2720        return 2;2721      }2722    }2723  }2724  return 0;2725}2726 2727/// Parse the argument to the -ftest-module-file-extension2728/// command-line argument.2729///2730/// \returns true on error, false on success.2731static bool parseTestModuleFileExtensionArg(StringRef Arg,2732                                            std::string &BlockName,2733                                            unsigned &MajorVersion,2734                                            unsigned &MinorVersion,2735                                            bool &Hashed,2736                                            std::string &UserInfo) {2737  SmallVector<StringRef, 5> Args;2738  Arg.split(Args, ':', 5);2739  if (Args.size() < 5)2740    return true;2741 2742  BlockName = std::string(Args[0]);2743  if (Args[1].getAsInteger(10, MajorVersion)) return true;2744  if (Args[2].getAsInteger(10, MinorVersion)) return true;2745  if (Args[3].getAsInteger(2, Hashed)) return true;2746  if (Args.size() > 4)2747    UserInfo = std::string(Args[4]);2748  return false;2749}2750 2751/// Return a table that associates command line option specifiers with the2752/// frontend action. Note: The pair {frontend::PluginAction, OPT_plugin} is2753/// intentionally missing, as this case is handled separately from other2754/// frontend options.2755static const auto &getFrontendActionTable() {2756  static const std::pair<frontend::ActionKind, unsigned> Table[] = {2757      {frontend::ASTDeclList, OPT_ast_list},2758 2759      {frontend::ASTDump, OPT_ast_dump_all_EQ},2760      {frontend::ASTDump, OPT_ast_dump_all},2761      {frontend::ASTDump, OPT_ast_dump_EQ},2762      {frontend::ASTDump, OPT_ast_dump},2763      {frontend::ASTDump, OPT_ast_dump_lookups},2764      {frontend::ASTDump, OPT_ast_dump_decl_types},2765 2766      {frontend::ASTPrint, OPT_ast_print},2767      {frontend::ASTView, OPT_ast_view},2768      {frontend::DumpCompilerOptions, OPT_compiler_options_dump},2769      {frontend::DumpRawTokens, OPT_dump_raw_tokens},2770      {frontend::DumpTokens, OPT_dump_tokens},2771      {frontend::EmitAssembly, OPT_S},2772      {frontend::EmitBC, OPT_emit_llvm_bc},2773      {frontend::EmitCIR, OPT_emit_cir},2774      {frontend::EmitHTML, OPT_emit_html},2775      {frontend::EmitLLVM, OPT_emit_llvm},2776      {frontend::EmitLLVMOnly, OPT_emit_llvm_only},2777      {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},2778      {frontend::EmitObj, OPT_emit_obj},2779      {frontend::ExtractAPI, OPT_extract_api},2780 2781      {frontend::FixIt, OPT_fixit_EQ},2782      {frontend::FixIt, OPT_fixit},2783 2784      {frontend::GenerateModule, OPT_emit_module},2785      {frontend::GenerateModuleInterface, OPT_emit_module_interface},2786      {frontend::GenerateReducedModuleInterface,2787       OPT_emit_reduced_module_interface},2788      {frontend::GenerateHeaderUnit, OPT_emit_header_unit},2789      {frontend::GeneratePCH, OPT_emit_pch},2790      {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},2791      {frontend::InitOnly, OPT_init_only},2792      {frontend::ParseSyntaxOnly, OPT_fsyntax_only},2793      {frontend::ModuleFileInfo, OPT_module_file_info},2794      {frontend::VerifyPCH, OPT_verify_pch},2795      {frontend::PrintPreamble, OPT_print_preamble},2796      {frontend::PrintPreprocessedInput, OPT_E},2797      {frontend::TemplightDump, OPT_templight_dump},2798      {frontend::RewriteMacros, OPT_rewrite_macros},2799      {frontend::RewriteObjC, OPT_rewrite_objc},2800      {frontend::RewriteTest, OPT_rewrite_test},2801      {frontend::RunAnalysis, OPT_analyze},2802      {frontend::RunPreprocessorOnly, OPT_Eonly},2803      {frontend::PrintDependencyDirectivesSourceMinimizerOutput,2804       OPT_print_dependency_directives_minimized_source},2805  };2806 2807  return Table;2808}2809 2810/// Maps command line option to frontend action.2811static std::optional<frontend::ActionKind>2812getFrontendAction(OptSpecifier &Opt) {2813  for (const auto &ActionOpt : getFrontendActionTable())2814    if (ActionOpt.second == Opt.getID())2815      return ActionOpt.first;2816 2817  return std::nullopt;2818}2819 2820/// Maps frontend action to command line option.2821static std::optional<OptSpecifier>2822getProgramActionOpt(frontend::ActionKind ProgramAction) {2823  for (const auto &ActionOpt : getFrontendActionTable())2824    if (ActionOpt.first == ProgramAction)2825      return OptSpecifier(ActionOpt.second);2826 2827  return std::nullopt;2828}2829 2830static void GenerateFrontendArgs(const FrontendOptions &Opts,2831                                 ArgumentConsumer Consumer, bool IsHeader) {2832  const FrontendOptions &FrontendOpts = Opts;2833#define FRONTEND_OPTION_WITH_MARSHALLING(...)                                  \2834  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)2835#include "clang/Options/Options.inc"2836#undef FRONTEND_OPTION_WITH_MARSHALLING2837 2838  std::optional<OptSpecifier> ProgramActionOpt =2839      getProgramActionOpt(Opts.ProgramAction);2840 2841  // Generating a simple flag covers most frontend actions.2842  std::function<void()> GenerateProgramAction = [&]() {2843    GenerateArg(Consumer, *ProgramActionOpt);2844  };2845 2846  if (!ProgramActionOpt) {2847    // PluginAction is the only program action handled separately.2848    assert(Opts.ProgramAction == frontend::PluginAction &&2849           "Frontend action without option.");2850    GenerateProgramAction = [&]() {2851      GenerateArg(Consumer, OPT_plugin, Opts.ActionName);2852    };2853  }2854 2855  // FIXME: Simplify the complex 'AST dump' command line.2856  if (Opts.ProgramAction == frontend::ASTDump) {2857    GenerateProgramAction = [&]() {2858      // ASTDumpLookups, ASTDumpDeclTypes and ASTDumpFilter are generated via2859      // marshalling infrastructure.2860 2861      if (Opts.ASTDumpFormat != ADOF_Default) {2862        StringRef Format;2863        switch (Opts.ASTDumpFormat) {2864        case ADOF_Default:2865          llvm_unreachable("Default AST dump format.");2866        case ADOF_JSON:2867          Format = "json";2868          break;2869        }2870 2871        if (Opts.ASTDumpAll)2872          GenerateArg(Consumer, OPT_ast_dump_all_EQ, Format);2873        if (Opts.ASTDumpDecls)2874          GenerateArg(Consumer, OPT_ast_dump_EQ, Format);2875      } else {2876        if (Opts.ASTDumpAll)2877          GenerateArg(Consumer, OPT_ast_dump_all);2878        if (Opts.ASTDumpDecls)2879          GenerateArg(Consumer, OPT_ast_dump);2880      }2881    };2882  }2883 2884  if (Opts.ProgramAction == frontend::FixIt && !Opts.FixItSuffix.empty()) {2885    GenerateProgramAction = [&]() {2886      GenerateArg(Consumer, OPT_fixit_EQ, Opts.FixItSuffix);2887    };2888  }2889 2890  GenerateProgramAction();2891 2892  for (const auto &PluginArgs : Opts.PluginArgs) {2893    Option Opt = getDriverOptTable().getOption(OPT_plugin_arg);2894    for (const auto &PluginArg : PluginArgs.second)2895      denormalizeString(Consumer,2896                        Opt.getPrefix() + Opt.getName() + PluginArgs.first,2897                        Opt.getKind(), 0, PluginArg);2898  }2899 2900  for (const auto &Ext : Opts.ModuleFileExtensions)2901    if (auto *TestExt = dyn_cast_or_null<TestModuleFileExtension>(Ext.get()))2902      GenerateArg(Consumer, OPT_ftest_module_file_extension_EQ, TestExt->str());2903 2904  if (!Opts.CodeCompletionAt.FileName.empty())2905    GenerateArg(Consumer, OPT_code_completion_at,2906                Opts.CodeCompletionAt.ToString());2907 2908  for (const auto &Plugin : Opts.Plugins)2909    GenerateArg(Consumer, OPT_load, Plugin);2910 2911  // ASTDumpDecls and ASTDumpAll already handled with ProgramAction.2912 2913  for (const auto &ModuleFile : Opts.ModuleFiles)2914    GenerateArg(Consumer, OPT_fmodule_file, ModuleFile);2915 2916  if (Opts.AuxTargetCPU)2917    GenerateArg(Consumer, OPT_aux_target_cpu, *Opts.AuxTargetCPU);2918 2919  if (Opts.AuxTargetFeatures)2920    for (const auto &Feature : *Opts.AuxTargetFeatures)2921      GenerateArg(Consumer, OPT_aux_target_feature, Feature);2922 2923  {2924    StringRef Preprocessed = Opts.DashX.isPreprocessed() ? "-cpp-output" : "";2925    StringRef ModuleMap =2926        Opts.DashX.getFormat() == InputKind::ModuleMap ? "-module-map" : "";2927    StringRef HeaderUnit = "";2928    switch (Opts.DashX.getHeaderUnitKind()) {2929    case InputKind::HeaderUnit_None:2930      break;2931    case InputKind::HeaderUnit_User:2932      HeaderUnit = "-user";2933      break;2934    case InputKind::HeaderUnit_System:2935      HeaderUnit = "-system";2936      break;2937    case InputKind::HeaderUnit_Abs:2938      HeaderUnit = "-header-unit";2939      break;2940    }2941    StringRef Header = IsHeader ? "-header" : "";2942 2943    StringRef Lang;2944    switch (Opts.DashX.getLanguage()) {2945    case Language::C:2946      Lang = "c";2947      break;2948    case Language::OpenCL:2949      Lang = "cl";2950      break;2951    case Language::OpenCLCXX:2952      Lang = "clcpp";2953      break;2954    case Language::CUDA:2955      Lang = "cuda";2956      break;2957    case Language::HIP:2958      Lang = "hip";2959      break;2960    case Language::CXX:2961      Lang = "c++";2962      break;2963    case Language::ObjC:2964      Lang = "objective-c";2965      break;2966    case Language::ObjCXX:2967      Lang = "objective-c++";2968      break;2969    case Language::Asm:2970      Lang = "assembler-with-cpp";2971      break;2972    case Language::Unknown:2973      assert(Opts.DashX.getFormat() == InputKind::Precompiled &&2974             "Generating -x argument for unknown language (not precompiled).");2975      Lang = "ast";2976      break;2977    case Language::LLVM_IR:2978      Lang = "ir";2979      break;2980    case Language::HLSL:2981      Lang = "hlsl";2982      break;2983    case Language::CIR:2984      Lang = "cir";2985      break;2986    }2987 2988    GenerateArg(Consumer, OPT_x,2989                Lang + HeaderUnit + Header + ModuleMap + Preprocessed);2990  }2991 2992  // OPT_INPUT has a unique class, generate it directly.2993  for (const auto &Input : Opts.Inputs)2994    Consumer(Input.getFile());2995}2996 2997static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,2998                              DiagnosticsEngine &Diags, bool &IsHeaderFile) {2999  unsigned NumErrorsBefore = Diags.getNumErrors();3000 3001  FrontendOptions &FrontendOpts = Opts;3002 3003#define FRONTEND_OPTION_WITH_MARSHALLING(...)                                  \3004  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)3005#include "clang/Options/Options.inc"3006#undef FRONTEND_OPTION_WITH_MARSHALLING3007 3008  Opts.ProgramAction = frontend::ParseSyntaxOnly;3009  if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {3010    OptSpecifier Opt = OptSpecifier(A->getOption().getID());3011    std::optional<frontend::ActionKind> ProgramAction = getFrontendAction(Opt);3012    assert(ProgramAction && "Option specifier not in Action_Group.");3013 3014    if (ProgramAction == frontend::ASTDump &&3015        (Opt == OPT_ast_dump_all_EQ || Opt == OPT_ast_dump_EQ)) {3016      unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())3017                         .CaseLower("default", ADOF_Default)3018                         .CaseLower("json", ADOF_JSON)3019                         .Default(std::numeric_limits<unsigned>::max());3020 3021      if (Val != std::numeric_limits<unsigned>::max())3022        Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val);3023      else {3024        Diags.Report(diag::err_drv_invalid_value)3025            << A->getAsString(Args) << A->getValue();3026        Opts.ASTDumpFormat = ADOF_Default;3027      }3028    }3029 3030    if (ProgramAction == frontend::FixIt && Opt == OPT_fixit_EQ)3031      Opts.FixItSuffix = A->getValue();3032 3033    if (ProgramAction == frontend::GenerateInterfaceStubs) {3034      StringRef ArgStr =3035          Args.hasArg(OPT_interface_stub_version_EQ)3036              ? Args.getLastArgValue(OPT_interface_stub_version_EQ)3037              : "ifs-v1";3038      if (ArgStr == "experimental-yaml-elf-v1" ||3039          ArgStr == "experimental-ifs-v1" || ArgStr == "experimental-ifs-v2" ||3040          ArgStr == "experimental-tapi-elf-v1") {3041        std::string ErrorMessage =3042            "Invalid interface stub format: " + ArgStr.str() +3043            " is deprecated.";3044        Diags.Report(diag::err_drv_invalid_value)3045            << "Must specify a valid interface stub format type, ie: "3046               "-interface-stub-version=ifs-v1"3047            << ErrorMessage;3048        ProgramAction = frontend::ParseSyntaxOnly;3049      } else if (!ArgStr.starts_with("ifs-")) {3050        std::string ErrorMessage =3051            "Invalid interface stub format: " + ArgStr.str() + ".";3052        Diags.Report(diag::err_drv_invalid_value)3053            << "Must specify a valid interface stub format type, ie: "3054               "-interface-stub-version=ifs-v1"3055            << ErrorMessage;3056        ProgramAction = frontend::ParseSyntaxOnly;3057      }3058    }3059 3060    Opts.ProgramAction = *ProgramAction;3061 3062    // Catch common mistakes when multiple actions are specified for cc1 (e.g.3063    // -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to3064    // support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name3065    // X ACTION), we suppress the error when the two actions are separated by3066    // -main-file-name.3067    //3068    // As an exception, accept composable -ast-dump*.3069    if (!A->getSpelling().starts_with("-ast-dump")) {3070      const Arg *SavedAction = nullptr;3071      for (const Arg *AA :3072           Args.filtered(OPT_Action_Group, OPT_main_file_name)) {3073        if (AA->getOption().matches(OPT_main_file_name)) {3074          SavedAction = nullptr;3075        } else if (!SavedAction) {3076          SavedAction = AA;3077        } else {3078          if (!A->getOption().matches(OPT_ast_dump_EQ))3079            Diags.Report(diag::err_fe_invalid_multiple_actions)3080                << SavedAction->getSpelling() << A->getSpelling();3081          break;3082        }3083      }3084    }3085  }3086 3087  if (const Arg* A = Args.getLastArg(OPT_plugin)) {3088    Opts.Plugins.emplace_back(A->getValue(0));3089    Opts.ProgramAction = frontend::PluginAction;3090    Opts.ActionName = A->getValue();3091  }3092  for (const auto *AA : Args.filtered(OPT_plugin_arg))3093    Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));3094 3095  for (const std::string &Arg :3096         Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {3097    std::string BlockName;3098    unsigned MajorVersion;3099    unsigned MinorVersion;3100    bool Hashed;3101    std::string UserInfo;3102    if (parseTestModuleFileExtensionArg(Arg, BlockName, MajorVersion,3103                                        MinorVersion, Hashed, UserInfo)) {3104      Diags.Report(diag::err_test_module_file_extension_format) << Arg;3105 3106      continue;3107    }3108 3109    // Add the testing module file extension.3110    Opts.ModuleFileExtensions.push_back(3111        std::make_shared<TestModuleFileExtension>(3112            BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));3113  }3114 3115  if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {3116    Opts.CodeCompletionAt =3117      ParsedSourceLocation::FromString(A->getValue());3118    if (Opts.CodeCompletionAt.FileName.empty()) {3119      Diags.Report(diag::err_drv_invalid_value)3120          << A->getAsString(Args) << A->getValue();3121      Diags.Report(diag::note_command_line_code_loc_requirement);3122    }3123  }3124 3125  Opts.Plugins = Args.getAllArgValues(OPT_load);3126  Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ);3127  Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ);3128  // Only the -fmodule-file=<file> form.3129  for (const auto *A : Args.filtered(OPT_fmodule_file)) {3130    StringRef Val = A->getValue();3131    if (!Val.contains('='))3132      Opts.ModuleFiles.push_back(std::string(Val));3133  }3134 3135  if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule)3136    Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"3137                                                           << "-emit-module";3138  if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir))3139    Opts.UseClangIRPipeline = true;3140 3141#if CLANG_ENABLE_CIR3142  if (Args.hasArg(OPT_clangir_disable_passes))3143    Opts.ClangIRDisablePasses = true;3144 3145  if (Args.hasArg(OPT_clangir_disable_verifier))3146    Opts.ClangIRDisableCIRVerifier = true;3147#endif // CLANG_ENABLE_CIR3148 3149  if (Args.hasArg(OPT_aux_target_cpu))3150    Opts.AuxTargetCPU = std::string(Args.getLastArgValue(OPT_aux_target_cpu));3151  if (Args.hasArg(OPT_aux_target_feature))3152    Opts.AuxTargetFeatures = Args.getAllArgValues(OPT_aux_target_feature);3153 3154  InputKind DashX(Language::Unknown);3155  if (const Arg *A = Args.getLastArg(OPT_x)) {3156    StringRef XValue = A->getValue();3157 3158    // Parse suffixes:3159    // '<lang>(-[{header-unit,user,system}-]header|[-module-map][-cpp-output])'.3160    // FIXME: Supporting '<lang>-header-cpp-output' would be useful.3161    bool Preprocessed = XValue.consume_back("-cpp-output");3162    bool ModuleMap = XValue.consume_back("-module-map");3163    // Detect and consume the header indicator.3164    bool IsHeader =3165        XValue != "precompiled-header" && XValue.consume_back("-header");3166 3167    // If we have c++-{user,system}-header, that indicates a header unit input3168    // likewise, if the user put -fmodule-header together with a header with an3169    // absolute path (header-unit-header).3170    InputKind::HeaderUnitKind HUK = InputKind::HeaderUnit_None;3171    if (IsHeader || Preprocessed) {3172      if (XValue.consume_back("-header-unit"))3173        HUK = InputKind::HeaderUnit_Abs;3174      else if (XValue.consume_back("-system"))3175        HUK = InputKind::HeaderUnit_System;3176      else if (XValue.consume_back("-user"))3177        HUK = InputKind::HeaderUnit_User;3178    }3179 3180    // The value set by this processing is an un-preprocessed source which is3181    // not intended to be a module map or header unit.3182    IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&3183                   HUK == InputKind::HeaderUnit_None;3184 3185    // Principal languages.3186    DashX = llvm::StringSwitch<InputKind>(XValue)3187                .Case("c", Language::C)3188                .Case("cl", Language::OpenCL)3189                .Case("clcpp", Language::OpenCLCXX)3190                .Case("cuda", Language::CUDA)3191                .Case("hip", Language::HIP)3192                .Case("c++", Language::CXX)3193                .Case("objective-c", Language::ObjC)3194                .Case("objective-c++", Language::ObjCXX)3195                .Case("hlsl", Language::HLSL)3196                .Default(Language::Unknown);3197 3198    // "objc[++]-cpp-output" is an acceptable synonym for3199    // "objective-c[++]-cpp-output".3200    if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap &&3201        HUK == InputKind::HeaderUnit_None)3202      DashX = llvm::StringSwitch<InputKind>(XValue)3203                  .Case("objc", Language::ObjC)3204                  .Case("objc++", Language::ObjCXX)3205                  .Default(Language::Unknown);3206 3207    // Some special cases cannot be combined with suffixes.3208    if (DashX.isUnknown() && !Preprocessed && !IsHeaderFile && !ModuleMap &&3209        HUK == InputKind::HeaderUnit_None)3210      DashX = llvm::StringSwitch<InputKind>(XValue)3211                  .Case("cpp-output", InputKind(Language::C).getPreprocessed())3212                  .Case("assembler-with-cpp", Language::Asm)3213                  .Cases({"ast", "pcm", "precompiled-header"},3214                         InputKind(Language::Unknown, InputKind::Precompiled))3215                  .Case("ir", Language::LLVM_IR)3216                  .Case("cir", Language::CIR)3217                  .Default(Language::Unknown);3218 3219    if (DashX.isUnknown())3220      Diags.Report(diag::err_drv_invalid_value)3221        << A->getAsString(Args) << A->getValue();3222 3223    if (Preprocessed)3224      DashX = DashX.getPreprocessed();3225    // A regular header is considered mutually exclusive with a header unit.3226    if (HUK != InputKind::HeaderUnit_None) {3227      DashX = DashX.withHeaderUnit(HUK);3228      IsHeaderFile = true;3229    } else if (IsHeaderFile)3230      DashX = DashX.getHeader();3231    if (ModuleMap)3232      DashX = DashX.withFormat(InputKind::ModuleMap);3233  }3234 3235  // '-' is the default input if none is given.3236  std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);3237  Opts.Inputs.clear();3238  if (Inputs.empty())3239    Inputs.push_back("-");3240 3241  if (DashX.getHeaderUnitKind() != InputKind::HeaderUnit_None &&3242      Inputs.size() > 1)3243    Diags.Report(diag::err_drv_header_unit_extra_inputs) << Inputs[1];3244 3245  for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {3246    InputKind IK = DashX;3247    if (IK.isUnknown()) {3248      IK = FrontendOptions::getInputKindForExtension(3249        StringRef(Inputs[i]).rsplit('.').second);3250      // FIXME: Warn on this?3251      if (IK.isUnknown())3252        IK = Language::C;3253      // FIXME: Remove this hack.3254      if (i == 0)3255        DashX = IK;3256    }3257 3258    bool IsSystem = false;3259 3260    // The -emit-module action implicitly takes a module map.3261    if (Opts.ProgramAction == frontend::GenerateModule &&3262        IK.getFormat() == InputKind::Source) {3263      IK = IK.withFormat(InputKind::ModuleMap);3264      IsSystem = Opts.IsSystemModule;3265    }3266 3267    Opts.Inputs.emplace_back(std::move(Inputs[i]), IK, IsSystem);3268  }3269 3270  Opts.DashX = DashX;3271 3272  return Diags.getNumErrors() == NumErrorsBefore;3273}3274 3275static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,3276                                     ArgumentConsumer Consumer) {3277  const HeaderSearchOptions *HeaderSearchOpts = &Opts;3278#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...)                             \3279  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)3280#include "clang/Options/Options.inc"3281#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING3282 3283  if (Opts.UseLibcxx)3284    GenerateArg(Consumer, OPT_stdlib_EQ, "libc++");3285 3286  for (const auto &File : Opts.PrebuiltModuleFiles)3287    GenerateArg(Consumer, OPT_fmodule_file, File.first + "=" + File.second);3288 3289  for (const auto &Path : Opts.PrebuiltModulePaths)3290    GenerateArg(Consumer, OPT_fprebuilt_module_path, Path);3291 3292  for (const auto &Macro : Opts.ModulesIgnoreMacros)3293    GenerateArg(Consumer, OPT_fmodules_ignore_macro, Macro.val());3294 3295  auto Matches = [](const HeaderSearchOptions::Entry &Entry,3296                    llvm::ArrayRef<frontend::IncludeDirGroup> Groups,3297                    std::optional<bool> IsFramework,3298                    std::optional<bool> IgnoreSysRoot) {3299    return llvm::is_contained(Groups, Entry.Group) &&3300           (!IsFramework || (Entry.IsFramework == *IsFramework)) &&3301           (!IgnoreSysRoot || (Entry.IgnoreSysRoot == *IgnoreSysRoot));3302  };3303 3304  auto It = Opts.UserEntries.begin();3305  auto End = Opts.UserEntries.end();3306 3307  // Add -I... and -F... options in order.3308  for (; It < End && Matches(*It, {frontend::Angled}, std::nullopt, true);3309       ++It) {3310    OptSpecifier Opt = [It, Matches]() {3311      if (Matches(*It, frontend::Angled, true, true))3312        return OPT_F;3313      if (Matches(*It, frontend::Angled, false, true))3314        return OPT_I;3315      llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");3316    }();3317 3318    GenerateArg(Consumer, Opt, It->Path);3319  }3320 3321  // Note: some paths that came from "[-iprefix=xx] -iwithprefixbefore=yy" may3322  // have already been generated as "-I[xx]yy". If that's the case, their3323  // position on command line was such that this has no semantic impact on3324  // include paths.3325  for (; It < End &&3326         Matches(*It, {frontend::After, frontend::Angled}, false, true);3327       ++It) {3328    OptSpecifier Opt =3329        It->Group == frontend::After ? OPT_iwithprefix : OPT_iwithprefixbefore;3330    GenerateArg(Consumer, Opt, It->Path);3331  }3332 3333  // Note: Some paths that came from "-idirafter=xxyy" may have already been3334  // generated as "-iwithprefix=xxyy". If that's the case, their position on3335  // command line was such that this has no semantic impact on include paths.3336  for (; It < End && Matches(*It, {frontend::After}, false, true); ++It)3337    GenerateArg(Consumer, OPT_idirafter, It->Path);3338  for (; It < End && Matches(*It, {frontend::Quoted}, false, true); ++It)3339    GenerateArg(Consumer, OPT_iquote, It->Path);3340  for (; It < End && Matches(*It, {frontend::System}, false, std::nullopt);3341       ++It)3342    GenerateArg(Consumer, It->IgnoreSysRoot ? OPT_isystem : OPT_iwithsysroot,3343                It->Path);3344  for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)3345    GenerateArg(Consumer, OPT_iframework, It->Path);3346  for (; It < End && Matches(*It, {frontend::System}, true, false); ++It)3347    GenerateArg(Consumer, OPT_iframeworkwithsysroot, It->Path);3348 3349  // Add the paths for the various language specific isystem flags.3350  for (; It < End && Matches(*It, {frontend::CSystem}, false, true); ++It)3351    GenerateArg(Consumer, OPT_c_isystem, It->Path);3352  for (; It < End && Matches(*It, {frontend::CXXSystem}, false, true); ++It)3353    GenerateArg(Consumer, OPT_cxx_isystem, It->Path);3354  for (; It < End && Matches(*It, {frontend::ObjCSystem}, false, true); ++It)3355    GenerateArg(Consumer, OPT_objc_isystem, It->Path);3356  for (; It < End && Matches(*It, {frontend::ObjCXXSystem}, false, true); ++It)3357    GenerateArg(Consumer, OPT_objcxx_isystem, It->Path);3358 3359  // Add the internal paths from a driver that detects standard include paths.3360  // Note: Some paths that came from "-internal-isystem" arguments may have3361  // already been generated as "-isystem". If that's the case, their position on3362  // command line was such that this has no semantic impact on include paths.3363  for (; It < End &&3364         Matches(*It, {frontend::System, frontend::ExternCSystem}, false, true);3365       ++It) {3366    OptSpecifier Opt = It->Group == frontend::System3367                           ? OPT_internal_isystem3368                           : OPT_internal_externc_isystem;3369    GenerateArg(Consumer, Opt, It->Path);3370  }3371  for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)3372    GenerateArg(Consumer, OPT_internal_iframework, It->Path);3373 3374  assert(It == End && "Unhandled HeaderSearchOption::Entry.");3375 3376  // Add the path prefixes which are implicitly treated as being system headers.3377  for (const auto &P : Opts.SystemHeaderPrefixes) {3378    OptSpecifier Opt = P.IsSystemHeader ? OPT_system_header_prefix3379                                        : OPT_no_system_header_prefix;3380    GenerateArg(Consumer, Opt, P.Prefix);3381  }3382 3383  for (const std::string &F : Opts.VFSOverlayFiles)3384    GenerateArg(Consumer, OPT_ivfsoverlay, F);3385}3386 3387static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,3388                                  DiagnosticsEngine &Diags) {3389  unsigned NumErrorsBefore = Diags.getNumErrors();3390 3391  HeaderSearchOptions *HeaderSearchOpts = &Opts;3392 3393#define HEADER_SEARCH_OPTION_WITH_MARSHALLING(...)                             \3394  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)3395#include "clang/Options/Options.inc"3396#undef HEADER_SEARCH_OPTION_WITH_MARSHALLING3397 3398  if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))3399    Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);3400 3401  // Only the -fmodule-file=<name>=<file> form.3402  for (const auto *A : Args.filtered(OPT_fmodule_file)) {3403    StringRef Val = A->getValue();3404    if (Val.contains('=')) {3405      auto Split = Val.split('=');3406      Opts.PrebuiltModuleFiles.insert_or_assign(3407          std::string(Split.first), std::string(Split.second));3408    }3409  }3410  for (const auto *A : Args.filtered(OPT_fprebuilt_module_path))3411    Opts.AddPrebuiltModulePath(A->getValue());3412 3413  for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) {3414    StringRef MacroDef = A->getValue();3415    Opts.ModulesIgnoreMacros.insert(3416        llvm::CachedHashString(MacroDef.split('=').first));3417  }3418 3419  // Add -I... and -F... options in order.3420  bool IsSysrootSpecified =3421      Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);3422 3423  // Expand a leading `=` to the sysroot if one was passed (and it's not a3424  // framework flag).3425  auto PrefixHeaderPath = [IsSysrootSpecified,3426                           &Opts](const llvm::opt::Arg *A,3427                                  bool IsFramework = false) -> std::string {3428    assert(A->getNumValues() && "Unexpected empty search path flag!");3429    if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {3430      SmallString<32> Buffer;3431      llvm::sys::path::append(Buffer, Opts.Sysroot,3432                              llvm::StringRef(A->getValue()).substr(1));3433      return std::string(Buffer);3434    }3435    return A->getValue();3436  };3437 3438  for (const auto *A : Args.filtered(OPT_I, OPT_F)) {3439    bool IsFramework = A->getOption().matches(OPT_F);3440    Opts.AddPath(PrefixHeaderPath(A, IsFramework), frontend::Angled,3441                 IsFramework, /*IgnoreSysroot=*/true);3442  }3443 3444  // Add -iprefix/-iwithprefix/-iwithprefixbefore options.3445  StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.3446  for (const auto *A :3447       Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) {3448    if (A->getOption().matches(OPT_iprefix))3449      Prefix = A->getValue();3450    else if (A->getOption().matches(OPT_iwithprefix))3451      Opts.AddPath(Prefix.str() + A->getValue(), frontend::After, false, true);3452    else3453      Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true);3454  }3455 3456  for (const auto *A : Args.filtered(OPT_idirafter))3457    Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true);3458  for (const auto *A : Args.filtered(OPT_iquote))3459    Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true);3460 3461  for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) {3462    if (A->getOption().matches(OPT_iwithsysroot)) {3463      Opts.AddPath(A->getValue(), frontend::System, false,3464                   /*IgnoreSysRoot=*/false);3465      continue;3466    }3467    Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true);3468  }3469  for (const auto *A : Args.filtered(OPT_iframework))3470    Opts.AddPath(A->getValue(), frontend::System, true, true);3471  for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot))3472    Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,3473                 /*IgnoreSysRoot=*/false);3474 3475  // Add the paths for the various language specific isystem flags.3476  for (const auto *A : Args.filtered(OPT_c_isystem))3477    Opts.AddPath(A->getValue(), frontend::CSystem, false, true);3478  for (const auto *A : Args.filtered(OPT_cxx_isystem))3479    Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true);3480  for (const auto *A : Args.filtered(OPT_objc_isystem))3481    Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true);3482  for (const auto *A : Args.filtered(OPT_objcxx_isystem))3483    Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true);3484 3485  // Add the internal paths from a driver that detects standard include paths.3486  for (const auto *A :3487       Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) {3488    frontend::IncludeDirGroup Group = frontend::System;3489    if (A->getOption().matches(OPT_internal_externc_isystem))3490      Group = frontend::ExternCSystem;3491    Opts.AddPath(A->getValue(), Group, false, true);3492  }3493  for (const auto *A : Args.filtered(OPT_internal_iframework))3494    Opts.AddPath(A->getValue(), frontend::System, true, true);3495 3496  // Add the path prefixes which are implicitly treated as being system headers.3497  for (const auto *A :3498       Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix))3499    Opts.AddSystemHeaderPrefix(3500        A->getValue(), A->getOption().matches(OPT_system_header_prefix));3501 3502  for (const auto *A : Args.filtered(OPT_ivfsoverlay, OPT_vfsoverlay))3503    Opts.AddVFSOverlayFile(A->getValue());3504 3505  return Diags.getNumErrors() == NumErrorsBefore;3506}3507 3508static void GenerateAPINotesArgs(const APINotesOptions &Opts,3509                                 ArgumentConsumer Consumer) {3510  if (!Opts.SwiftVersion.empty())3511    GenerateArg(Consumer, OPT_fapinotes_swift_version,3512                Opts.SwiftVersion.getAsString());3513 3514  for (const auto &Path : Opts.ModuleSearchPaths)3515    GenerateArg(Consumer, OPT_iapinotes_modules, Path);3516}3517 3518static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args,3519                              DiagnosticsEngine &diags) {3520  if (const Arg *A = Args.getLastArg(OPT_fapinotes_swift_version)) {3521    if (Opts.SwiftVersion.tryParse(A->getValue()))3522      diags.Report(diag::err_drv_invalid_value)3523          << A->getAsString(Args) << A->getValue();3524  }3525  for (const Arg *A : Args.filtered(OPT_iapinotes_modules))3526    Opts.ModuleSearchPaths.push_back(A->getValue());3527}3528 3529static void GeneratePointerAuthArgs(const LangOptions &Opts,3530                                    ArgumentConsumer Consumer) {3531  if (Opts.PointerAuthIntrinsics)3532    GenerateArg(Consumer, OPT_fptrauth_intrinsics);3533  if (Opts.PointerAuthCalls)3534    GenerateArg(Consumer, OPT_fptrauth_calls);3535  if (Opts.PointerAuthReturns)3536    GenerateArg(Consumer, OPT_fptrauth_returns);3537  if (Opts.PointerAuthIndirectGotos)3538    GenerateArg(Consumer, OPT_fptrauth_indirect_gotos);3539  if (Opts.PointerAuthAuthTraps)3540    GenerateArg(Consumer, OPT_fptrauth_auth_traps);3541  if (Opts.PointerAuthVTPtrAddressDiscrimination)3542    GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination);3543  if (Opts.PointerAuthVTPtrTypeDiscrimination)3544    GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);3545  if (Opts.PointerAuthTypeInfoVTPtrDiscrimination)3546    GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);3547  if (Opts.PointerAuthFunctionTypeDiscrimination)3548    GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);3549  if (Opts.PointerAuthInitFini)3550    GenerateArg(Consumer, OPT_fptrauth_init_fini);3551  if (Opts.PointerAuthInitFiniAddressDiscrimination)3552    GenerateArg(Consumer, OPT_fptrauth_init_fini_address_discrimination);3553  if (Opts.PointerAuthELFGOT)3554    GenerateArg(Consumer, OPT_fptrauth_elf_got);3555  if (Opts.AArch64JumpTableHardening)3556    GenerateArg(Consumer, OPT_faarch64_jump_table_hardening);3557  if (Opts.PointerAuthObjcIsa)3558    GenerateArg(Consumer, OPT_fptrauth_objc_isa);3559  if (Opts.PointerAuthObjcInterfaceSel)3560    GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);3561  if (Opts.PointerAuthObjcClassROPointers)3562    GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);3563  if (Opts.PointerAuthBlockDescriptorPointers)3564    GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);3565}3566 3567static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,3568                                 DiagnosticsEngine &Diags) {3569  Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics);3570  Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls);3571  Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns);3572  Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos);3573  Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps);3574  Opts.PointerAuthVTPtrAddressDiscrimination =3575      Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);3576  Opts.PointerAuthVTPtrTypeDiscrimination =3577      Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);3578  Opts.PointerAuthTypeInfoVTPtrDiscrimination =3579      Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination);3580  Opts.PointerAuthFunctionTypeDiscrimination =3581      Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination);3582  Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);3583  Opts.PointerAuthInitFiniAddressDiscrimination =3584      Args.hasArg(OPT_fptrauth_init_fini_address_discrimination);3585  Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);3586  Opts.AArch64JumpTableHardening =3587      Args.hasArg(OPT_faarch64_jump_table_hardening);3588  Opts.PointerAuthBlockDescriptorPointers =3589      Args.hasArg(OPT_fptrauth_block_descriptor_pointers);3590  Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);3591  Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);3592  Opts.PointerAuthObjcInterfaceSel =3593      Args.hasArg(OPT_fptrauth_objc_interface_sel);3594 3595  if (Opts.PointerAuthObjcInterfaceSel)3596    Opts.PointerAuthObjcInterfaceSelKey =3597        static_cast<unsigned>(PointerAuthSchema::ARM8_3Key::ASDB);3598}3599 3600/// Check if input file kind and language standard are compatible.3601static bool IsInputCompatibleWithStandard(InputKind IK,3602                                          const LangStandard &S) {3603  switch (IK.getLanguage()) {3604  case Language::Unknown:3605  case Language::LLVM_IR:3606  case Language::CIR:3607    llvm_unreachable("should not parse language flags for this input");3608 3609  case Language::C:3610  case Language::ObjC:3611    return S.getLanguage() == Language::C;3612 3613  case Language::OpenCL:3614    return S.getLanguage() == Language::OpenCL ||3615           S.getLanguage() == Language::OpenCLCXX;3616 3617  case Language::OpenCLCXX:3618    return S.getLanguage() == Language::OpenCLCXX;3619 3620  case Language::CXX:3621  case Language::ObjCXX:3622    return S.getLanguage() == Language::CXX;3623 3624  case Language::CUDA:3625    // FIXME: What -std= values should be permitted for CUDA compilations?3626    return S.getLanguage() == Language::CUDA ||3627           S.getLanguage() == Language::CXX;3628 3629  case Language::HIP:3630    return S.getLanguage() == Language::CXX || S.getLanguage() == Language::HIP;3631 3632  case Language::Asm:3633    // Accept (and ignore) all -std= values.3634    // FIXME: The -std= value is not ignored; it affects the tokenization3635    // and preprocessing rules if we're preprocessing this asm input.3636    return true;3637 3638  case Language::HLSL:3639    return S.getLanguage() == Language::HLSL;3640  }3641 3642  llvm_unreachable("unexpected input language");3643}3644 3645/// Get language name for given input kind.3646static StringRef GetInputKindName(InputKind IK) {3647  switch (IK.getLanguage()) {3648  case Language::C:3649    return "C";3650  case Language::ObjC:3651    return "Objective-C";3652  case Language::CXX:3653    return "C++";3654  case Language::ObjCXX:3655    return "Objective-C++";3656  case Language::OpenCL:3657    return "OpenCL";3658  case Language::OpenCLCXX:3659    return "C++ for OpenCL";3660  case Language::CUDA:3661    return "CUDA";3662  case Language::HIP:3663    return "HIP";3664 3665  case Language::Asm:3666    return "Asm";3667  case Language::LLVM_IR:3668    return "LLVM IR";3669  case Language::CIR:3670    return "Clang IR";3671 3672  case Language::HLSL:3673    return "HLSL";3674 3675  case Language::Unknown:3676    break;3677  }3678  llvm_unreachable("unknown input language");3679}3680 3681void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,3682                                              ArgumentConsumer Consumer,3683                                              const llvm::Triple &T,3684                                              InputKind IK) {3685  if (IK.getFormat() == InputKind::Precompiled ||3686      IK.getLanguage() == Language::LLVM_IR ||3687      IK.getLanguage() == Language::CIR) {3688    if (Opts.ObjCAutoRefCount)3689      GenerateArg(Consumer, OPT_fobjc_arc);3690    if (Opts.PICLevel != 0)3691      GenerateArg(Consumer, OPT_pic_level, Twine(Opts.PICLevel));3692    if (Opts.PIE)3693      GenerateArg(Consumer, OPT_pic_is_pie);3694    for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))3695      GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);3696 3697    return;3698  }3699 3700  OptSpecifier StdOpt;3701  switch (Opts.LangStd) {3702  case LangStandard::lang_opencl10:3703  case LangStandard::lang_opencl11:3704  case LangStandard::lang_opencl12:3705  case LangStandard::lang_opencl20:3706  case LangStandard::lang_opencl30:3707  case LangStandard::lang_openclcpp10:3708  case LangStandard::lang_openclcpp2021:3709    StdOpt = OPT_cl_std_EQ;3710    break;3711  default:3712    StdOpt = OPT_std_EQ;3713    break;3714  }3715 3716  auto LangStandard = LangStandard::getLangStandardForKind(Opts.LangStd);3717  GenerateArg(Consumer, StdOpt, LangStandard.getName());3718 3719  if (Opts.IncludeDefaultHeader)3720    GenerateArg(Consumer, OPT_finclude_default_header);3721  if (Opts.DeclareOpenCLBuiltins)3722    GenerateArg(Consumer, OPT_fdeclare_opencl_builtins);3723 3724  const LangOptions *LangOpts = &Opts;3725 3726#define LANG_OPTION_WITH_MARSHALLING(...)                                      \3727  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)3728#include "clang/Options/Options.inc"3729#undef LANG_OPTION_WITH_MARSHALLING3730 3731  // The '-fcf-protection=' option is generated by CodeGenOpts generator.3732 3733  if (Opts.ObjC) {3734    GenerateArg(Consumer, OPT_fobjc_runtime_EQ, Opts.ObjCRuntime.getAsString());3735 3736    if (Opts.GC == LangOptions::GCOnly)3737      GenerateArg(Consumer, OPT_fobjc_gc_only);3738    else if (Opts.GC == LangOptions::HybridGC)3739      GenerateArg(Consumer, OPT_fobjc_gc);3740    else if (Opts.ObjCAutoRefCount == 1)3741      GenerateArg(Consumer, OPT_fobjc_arc);3742 3743    if (Opts.ObjCWeakRuntime)3744      GenerateArg(Consumer, OPT_fobjc_runtime_has_weak);3745 3746    if (Opts.ObjCWeak)3747      GenerateArg(Consumer, OPT_fobjc_weak);3748 3749    if (Opts.ObjCSubscriptingLegacyRuntime)3750      GenerateArg(Consumer, OPT_fobjc_subscripting_legacy_runtime);3751  }3752 3753  if (Opts.GNUCVersion != 0) {3754    unsigned Major = Opts.GNUCVersion / 100 / 100;3755    unsigned Minor = (Opts.GNUCVersion / 100) % 100;3756    unsigned Patch = Opts.GNUCVersion % 100;3757    GenerateArg(Consumer, OPT_fgnuc_version_EQ,3758                Twine(Major) + "." + Twine(Minor) + "." + Twine(Patch));3759  }3760 3761  if (Opts.IgnoreXCOFFVisibility)3762    GenerateArg(Consumer, OPT_mignore_xcoff_visibility);3763 3764  if (Opts.SignedOverflowBehavior == LangOptions::SOB_Trapping) {3765    GenerateArg(Consumer, OPT_ftrapv);3766    GenerateArg(Consumer, OPT_ftrapv_handler, Opts.OverflowHandler);3767  } else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {3768    GenerateArg(Consumer, OPT_fwrapv);3769  }3770  if (Opts.PointerOverflowDefined)3771    GenerateArg(Consumer, OPT_fwrapv_pointer);3772 3773  if (Opts.MSCompatibilityVersion != 0) {3774    unsigned Major = Opts.MSCompatibilityVersion / 10000000;3775    unsigned Minor = (Opts.MSCompatibilityVersion / 100000) % 100;3776    unsigned Subminor = Opts.MSCompatibilityVersion % 100000;3777    GenerateArg(Consumer, OPT_fms_compatibility_version,3778                Twine(Major) + "." + Twine(Minor) + "." + Twine(Subminor));3779  }3780 3781  if ((!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||3782      T.isOSzOS()) {3783    if (!Opts.Trigraphs)3784      GenerateArg(Consumer, OPT_fno_trigraphs);3785  } else {3786    if (Opts.Trigraphs)3787      GenerateArg(Consumer, OPT_ftrigraphs);3788  }3789 3790  if (T.isOSzOS() && !Opts.ZOSExt)3791    GenerateArg(Consumer, OPT_fno_zos_extensions);3792  else if (Opts.ZOSExt)3793    GenerateArg(Consumer, OPT_fzos_extensions);3794 3795  if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))3796    GenerateArg(Consumer, OPT_fblocks);3797 3798  if (Opts.ConvergentFunctions)3799    GenerateArg(Consumer, OPT_fconvergent_functions);3800  else3801    GenerateArg(Consumer, OPT_fno_convergent_functions);3802 3803  if (Opts.NoBuiltin && !Opts.Freestanding)3804    GenerateArg(Consumer, OPT_fno_builtin);3805 3806  if (!Opts.NoBuiltin)3807    for (const auto &Func : Opts.NoBuiltinFuncs)3808      GenerateArg(Consumer, OPT_fno_builtin_, Func);3809 3810  if (Opts.LongDoubleSize == 128)3811    GenerateArg(Consumer, OPT_mlong_double_128);3812  else if (Opts.LongDoubleSize == 64)3813    GenerateArg(Consumer, OPT_mlong_double_64);3814  else if (Opts.LongDoubleSize == 80)3815    GenerateArg(Consumer, OPT_mlong_double_80);3816 3817  // Not generating '-mrtd', it's just an alias for '-fdefault-calling-conv='.3818 3819  // OpenMP was requested via '-fopenmp', not implied by '-fopenmp-simd' or3820  // '-fopenmp-targets='.3821  if (Opts.OpenMP && !Opts.OpenMPSimd) {3822    GenerateArg(Consumer, OPT_fopenmp);3823 3824    if (Opts.OpenMP != 51)3825      GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));3826 3827    if (!Opts.OpenMPUseTLS)3828      GenerateArg(Consumer, OPT_fnoopenmp_use_tls);3829 3830    if (Opts.OpenMPIsTargetDevice)3831      GenerateArg(Consumer, OPT_fopenmp_is_target_device);3832 3833    if (Opts.OpenMPIRBuilder)3834      GenerateArg(Consumer, OPT_fopenmp_enable_irbuilder);3835  }3836 3837  if (Opts.OpenMPSimd) {3838    GenerateArg(Consumer, OPT_fopenmp_simd);3839 3840    if (Opts.OpenMP != 51)3841      GenerateArg(Consumer, OPT_fopenmp_version_EQ, Twine(Opts.OpenMP));3842  }3843 3844  if (Opts.OpenMPThreadSubscription)3845    GenerateArg(Consumer, OPT_fopenmp_assume_threads_oversubscription);3846 3847  if (Opts.OpenMPTeamSubscription)3848    GenerateArg(Consumer, OPT_fopenmp_assume_teams_oversubscription);3849 3850  if (Opts.OpenMPTargetDebug != 0)3851    GenerateArg(Consumer, OPT_fopenmp_target_debug_EQ,3852                Twine(Opts.OpenMPTargetDebug));3853 3854  if (Opts.OpenMPCUDANumSMs != 0)3855    GenerateArg(Consumer, OPT_fopenmp_cuda_number_of_sm_EQ,3856                Twine(Opts.OpenMPCUDANumSMs));3857 3858  if (Opts.OpenMPCUDABlocksPerSM != 0)3859    GenerateArg(Consumer, OPT_fopenmp_cuda_blocks_per_sm_EQ,3860                Twine(Opts.OpenMPCUDABlocksPerSM));3861 3862  if (Opts.OpenMPCUDAReductionBufNum != 1024)3863    GenerateArg(Consumer, OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,3864                Twine(Opts.OpenMPCUDAReductionBufNum));3865 3866  if (!Opts.OMPTargetTriples.empty()) {3867    std::string Targets;3868    llvm::raw_string_ostream OS(Targets);3869    llvm::interleave(3870        Opts.OMPTargetTriples, OS,3871        [&OS](const llvm::Triple &T) { OS << T.str(); }, ",");3872    GenerateArg(Consumer, OPT_offload_targets_EQ, Targets);3873  }3874 3875  if (Opts.OpenMPCUDAMode)3876    GenerateArg(Consumer, OPT_fopenmp_cuda_mode);3877 3878  if (Opts.OpenACC)3879    GenerateArg(Consumer, OPT_fopenacc);3880 3881  // The arguments used to set Optimize, OptimizeSize and NoInlineDefine are3882  // generated from CodeGenOptions.3883 3884  if (Opts.DefaultFPContractMode == LangOptions::FPM_Fast)3885    GenerateArg(Consumer, OPT_ffp_contract, "fast");3886  else if (Opts.DefaultFPContractMode == LangOptions::FPM_On)3887    GenerateArg(Consumer, OPT_ffp_contract, "on");3888  else if (Opts.DefaultFPContractMode == LangOptions::FPM_Off)3889    GenerateArg(Consumer, OPT_ffp_contract, "off");3890  else if (Opts.DefaultFPContractMode == LangOptions::FPM_FastHonorPragmas)3891    GenerateArg(Consumer, OPT_ffp_contract, "fast-honor-pragmas");3892 3893  for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize))3894    GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer);3895 3896  // Conflating '-fsanitize-system-ignorelist' and '-fsanitize-ignorelist'.3897  for (const std::string &F : Opts.NoSanitizeFiles)3898    GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F);3899 3900  switch (Opts.getClangABICompat()) {3901#define ABI_VER_MAJOR_MINOR(Major, Minor)                                      \3902  case LangOptions::ClangABI::Ver##Major##_##Minor:                            \3903    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major "." #Minor);        \3904    break;3905#define ABI_VER_MAJOR(Major)                                                   \3906  case LangOptions::ClangABI::Ver##Major:                                      \3907    GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, #Major ".0");              \3908    break;3909#define ABI_VER_LATEST(Latest)                                                 \3910  case LangOptions::ClangABI::Latest:                                          \3911    break;3912#include "clang/Basic/ABIVersions.def"3913  }3914 3915  if (Opts.getSignReturnAddressScope() ==3916      LangOptions::SignReturnAddressScopeKind::All)3917    GenerateArg(Consumer, OPT_msign_return_address_EQ, "all");3918  else if (Opts.getSignReturnAddressScope() ==3919           LangOptions::SignReturnAddressScopeKind::NonLeaf)3920    GenerateArg(Consumer, OPT_msign_return_address_EQ, "non-leaf");3921 3922  if (Opts.getSignReturnAddressKey() ==3923      LangOptions::SignReturnAddressKeyKind::BKey)3924    GenerateArg(Consumer, OPT_msign_return_address_key_EQ, "b_key");3925 3926  if (Opts.CXXABI)3927    GenerateArg(Consumer, OPT_fcxx_abi_EQ,3928                TargetCXXABI::getSpelling(*Opts.CXXABI));3929 3930  if (Opts.RelativeCXXABIVTables)3931    GenerateArg(Consumer, OPT_fexperimental_relative_cxx_abi_vtables);3932  else3933    GenerateArg(Consumer, OPT_fno_experimental_relative_cxx_abi_vtables);3934 3935  if (Opts.UseTargetPathSeparator)3936    GenerateArg(Consumer, OPT_ffile_reproducible);3937  else3938    GenerateArg(Consumer, OPT_fno_file_reproducible);3939 3940  for (const auto &MP : Opts.MacroPrefixMap)3941    GenerateArg(Consumer, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second);3942 3943  if (!Opts.RandstructSeed.empty())3944    GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed);3945 3946  if (Opts.AllocTokenMax)3947    GenerateArg(Consumer, OPT_falloc_token_max_EQ,3948                std::to_string(*Opts.AllocTokenMax));3949 3950  if (Opts.AllocTokenMode) {3951    StringRef S = llvm::getAllocTokenModeAsString(*Opts.AllocTokenMode);3952    GenerateArg(Consumer, OPT_falloc_token_mode_EQ, S);3953  }3954}3955 3956bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,3957                                       InputKind IK, const llvm::Triple &T,3958                                       std::vector<std::string> &Includes,3959                                       DiagnosticsEngine &Diags) {3960  unsigned NumErrorsBefore = Diags.getNumErrors();3961 3962  if (IK.getFormat() == InputKind::Precompiled ||3963      IK.getLanguage() == Language::LLVM_IR ||3964      IK.getLanguage() == Language::CIR) {3965    // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the3966    // PassManager in BackendUtil.cpp. They need to be initialized no matter3967    // what the input type is.3968    if (Args.hasArg(OPT_fobjc_arc))3969      Opts.ObjCAutoRefCount = 1;3970    // PICLevel and PIELevel are needed during code generation and this should3971    // be set regardless of the input type.3972    Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);3973    Opts.PIE = Args.hasArg(OPT_pic_is_pie);3974    parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),3975                        Diags, Opts.Sanitize);3976 3977    return Diags.getNumErrors() == NumErrorsBefore;3978  }3979 3980  // Other LangOpts are only initialized when the input is not AST or LLVM IR.3981  // FIXME: Should we really be parsing this for an Language::Asm input?3982 3983  // FIXME: Cleanup per-file based stuff.3984  LangStandard::Kind LangStd = LangStandard::lang_unspecified;3985  if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {3986    LangStd = LangStandard::getLangKind(A->getValue());3987    if (LangStd == LangStandard::lang_unspecified) {3988      Diags.Report(diag::err_drv_invalid_value)3989        << A->getAsString(Args) << A->getValue();3990      // Report supported standards with short description.3991      for (unsigned KindValue = 0;3992           KindValue != LangStandard::lang_unspecified;3993           ++KindValue) {3994        const LangStandard &Std = LangStandard::getLangStandardForKind(3995          static_cast<LangStandard::Kind>(KindValue));3996        if (IsInputCompatibleWithStandard(IK, Std)) {3997          auto Diag = Diags.Report(diag::note_drv_use_standard);3998          Diag << Std.getName() << Std.getDescription();3999          unsigned NumAliases = 0;4000#define LANGSTANDARD(id, name, lang, desc, features, version)4001#define LANGSTANDARD_ALIAS(id, alias) \4002          if (KindValue == LangStandard::lang_##id) ++NumAliases;4003#define LANGSTANDARD_ALIAS_DEPR(id, alias)4004#include "clang/Basic/LangStandards.def"4005          Diag << NumAliases;4006#define LANGSTANDARD(id, name, lang, desc, features, version)4007#define LANGSTANDARD_ALIAS(id, alias) \4008          if (KindValue == LangStandard::lang_##id) Diag << alias;4009#define LANGSTANDARD_ALIAS_DEPR(id, alias)4010#include "clang/Basic/LangStandards.def"4011        }4012      }4013    } else {4014      // Valid standard, check to make sure language and standard are4015      // compatible.4016      const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);4017      if (!IsInputCompatibleWithStandard(IK, Std)) {4018        Diags.Report(diag::err_drv_argument_not_allowed_with)4019          << A->getAsString(Args) << GetInputKindName(IK);4020      }4021    }4022  }4023 4024  // -cl-std only applies for OpenCL language standards.4025  // Override the -std option in this case.4026  if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {4027    LangStandard::Kind OpenCLLangStd =4028        llvm::StringSwitch<LangStandard::Kind>(A->getValue())4029            .Cases({"cl", "CL"}, LangStandard::lang_opencl10)4030            .Cases({"cl1.0", "CL1.0"}, LangStandard::lang_opencl10)4031            .Cases({"cl1.1", "CL1.1"}, LangStandard::lang_opencl11)4032            .Cases({"cl1.2", "CL1.2"}, LangStandard::lang_opencl12)4033            .Cases({"cl2.0", "CL2.0"}, LangStandard::lang_opencl20)4034            .Cases({"cl3.0", "CL3.0"}, LangStandard::lang_opencl30)4035            .Cases({"clc++", "CLC++"}, LangStandard::lang_openclcpp10)4036            .Cases({"clc++1.0", "CLC++1.0"}, LangStandard::lang_openclcpp10)4037            .Cases({"clc++2021", "CLC++2021"}, LangStandard::lang_openclcpp2021)4038            .Default(LangStandard::lang_unspecified);4039 4040    if (OpenCLLangStd == LangStandard::lang_unspecified) {4041      Diags.Report(diag::err_drv_invalid_value)4042        << A->getAsString(Args) << A->getValue();4043    }4044    else4045      LangStd = OpenCLLangStd;4046  }4047 4048  // These need to be parsed now. They are used to set OpenCL defaults.4049  Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);4050  Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins);4051 4052  LangOptions::setLangDefaults(Opts, IK.getLanguage(), T, Includes, LangStd);4053 4054  // The key paths of codegen options defined in Options.td start with4055  // "LangOpts->". Let's provide the expected variable name and type.4056  LangOptions *LangOpts = &Opts;4057 4058#define LANG_OPTION_WITH_MARSHALLING(...)                                      \4059  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)4060#include "clang/Options/Options.inc"4061#undef LANG_OPTION_WITH_MARSHALLING4062 4063  if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {4064    StringRef Name = A->getValue();4065    if (Name == "full") {4066      Opts.CFProtectionBranch = 1;4067      Opts.CFProtectionReturn = 1;4068    } else if (Name == "branch") {4069      Opts.CFProtectionBranch = 1;4070    } else if (Name == "return") {4071      Opts.CFProtectionReturn = 1;4072    }4073  }4074 4075  if (Opts.CFProtectionBranch) {4076    if (const Arg *A = Args.getLastArg(OPT_mcf_branch_label_scheme_EQ)) {4077      const auto Scheme =4078          llvm::StringSwitch<CFBranchLabelSchemeKind>(A->getValue())4079#define CF_BRANCH_LABEL_SCHEME(Kind, FlagVal)                                  \4080  .Case(#FlagVal, CFBranchLabelSchemeKind::Kind)4081#include "clang/Basic/CFProtectionOptions.def"4082              .Default(CFBranchLabelSchemeKind::Default);4083      Opts.setCFBranchLabelScheme(Scheme);4084    }4085  }4086 4087  if ((Args.hasArg(OPT_fsycl_is_device) || Args.hasArg(OPT_fsycl_is_host)) &&4088      !Args.hasArg(OPT_sycl_std_EQ)) {4089    // If the user supplied -fsycl-is-device or -fsycl-is-host, but failed to4090    // provide -sycl-std=, we want to default it to whatever the default SYCL4091    // version is. I could not find a way to express this with the options4092    // tablegen because we still want this value to be SYCL_None when the user4093    // is not in device or host mode.4094    Opts.setSYCLVersion(LangOptions::SYCL_Default);4095  }4096 4097  if (Opts.ObjC) {4098    if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {4099      StringRef value = arg->getValue();4100      if (Opts.ObjCRuntime.tryParse(value))4101        Diags.Report(diag::err_drv_unknown_objc_runtime) << value;4102    }4103 4104    if (Args.hasArg(OPT_fobjc_gc_only))4105      Opts.setGC(LangOptions::GCOnly);4106    else if (Args.hasArg(OPT_fobjc_gc))4107      Opts.setGC(LangOptions::HybridGC);4108    else if (Args.hasArg(OPT_fobjc_arc)) {4109      Opts.ObjCAutoRefCount = 1;4110      if (!Opts.ObjCRuntime.allowsARC())4111        Diags.Report(diag::err_arc_unsupported_on_runtime);4112    }4113 4114    // ObjCWeakRuntime tracks whether the runtime supports __weak, not4115    // whether the feature is actually enabled.  This is predominantly4116    // determined by -fobjc-runtime, but we allow it to be overridden4117    // from the command line for testing purposes.4118    if (Args.hasArg(OPT_fobjc_runtime_has_weak))4119      Opts.ObjCWeakRuntime = 1;4120    else4121      Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();4122 4123    // ObjCWeak determines whether __weak is actually enabled.4124    // Note that we allow -fno-objc-weak to disable this even in ARC mode.4125    if (auto weakArg = Args.getLastArg(OPT_fobjc_weak, OPT_fno_objc_weak)) {4126      if (!weakArg->getOption().matches(OPT_fobjc_weak)) {4127        assert(!Opts.ObjCWeak);4128      } else if (Opts.getGC() != LangOptions::NonGC) {4129        Diags.Report(diag::err_objc_weak_with_gc);4130      } else if (!Opts.ObjCWeakRuntime) {4131        Diags.Report(diag::err_objc_weak_unsupported);4132      } else {4133        Opts.ObjCWeak = 1;4134      }4135    } else if (Opts.ObjCAutoRefCount) {4136      Opts.ObjCWeak = Opts.ObjCWeakRuntime;4137    }4138 4139    if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime))4140      Opts.ObjCSubscriptingLegacyRuntime =4141        (Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX);4142  }4143 4144  if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {4145    // Check that the version has 1 to 3 components and the minor and patch4146    // versions fit in two decimal digits.4147    VersionTuple GNUCVer;4148    bool Invalid = GNUCVer.tryParse(A->getValue());4149    unsigned Major = GNUCVer.getMajor();4150    unsigned Minor = GNUCVer.getMinor().value_or(0);4151    unsigned Patch = GNUCVer.getSubminor().value_or(0);4152    if (Invalid || GNUCVer.getBuild() || Minor >= 100 || Patch >= 100) {4153      Diags.Report(diag::err_drv_invalid_value)4154          << A->getAsString(Args) << A->getValue();4155    }4156    Opts.GNUCVersion = Major * 100 * 100 + Minor * 100 + Patch;4157  }4158 4159  if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility)))4160    Opts.IgnoreXCOFFVisibility = 1;4161 4162  if (Args.hasArg(OPT_ftrapv)) {4163    Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);4164    // Set the handler, if one is specified.4165    Opts.OverflowHandler =4166        std::string(Args.getLastArgValue(OPT_ftrapv_handler));4167  }4168  else if (Args.hasArg(OPT_fwrapv))4169    Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);4170  if (Args.hasArg(OPT_fwrapv_pointer))4171    Opts.PointerOverflowDefined = true;4172 4173  Opts.MSCompatibilityVersion = 0;4174  if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {4175    VersionTuple VT;4176    if (VT.tryParse(A->getValue()))4177      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)4178                                                << A->getValue();4179    Opts.MSCompatibilityVersion = VT.getMajor() * 10000000 +4180                                  VT.getMinor().value_or(0) * 100000 +4181                                  VT.getSubminor().value_or(0);4182  }4183 4184  // Mimicking gcc's behavior, trigraphs are only enabled if -trigraphs4185  // is specified, or -std is set to a conforming mode.4186  // Trigraphs are disabled by default in C++17 and C23 onwards.4187  // For z/OS, trigraphs are enabled by default (without regard to the above).4188  Opts.Trigraphs =4189      (!Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17 && !Opts.C23) ||4190      T.isOSzOS();4191  Opts.Trigraphs =4192      Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);4193 4194  Opts.ZOSExt =4195      Args.hasFlag(OPT_fzos_extensions, OPT_fno_zos_extensions, T.isOSzOS());4196 4197  Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL4198    && Opts.OpenCLVersion == 200);4199 4200  bool HasConvergentOperations = Opts.isTargetDevice() || Opts.OpenCL ||4201                                 Opts.HLSL || T.isAMDGPU() || T.isNVPTX();4202  Opts.ConvergentFunctions =4203      Args.hasFlag(OPT_fconvergent_functions, OPT_fno_convergent_functions,4204                   HasConvergentOperations);4205 4206  Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;4207  if (!Opts.NoBuiltin)4208    getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);4209  if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {4210    if (A->getOption().matches(options::OPT_mlong_double_64))4211      Opts.LongDoubleSize = 64;4212    else if (A->getOption().matches(options::OPT_mlong_double_80))4213      Opts.LongDoubleSize = 80;4214    else if (A->getOption().matches(options::OPT_mlong_double_128))4215      Opts.LongDoubleSize = 128;4216    else4217      Opts.LongDoubleSize = 0;4218  }4219  if (Opts.FastRelaxedMath || Opts.CLUnsafeMath)4220    Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);4221 4222  llvm::sort(Opts.ModuleFeatures);4223 4224  // -mrtd option4225  if (Arg *A = Args.getLastArg(OPT_mrtd)) {4226    if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)4227      Diags.Report(diag::err_drv_argument_not_allowed_with)4228          << A->getSpelling() << "-fdefault-calling-conv";4229    else {4230      switch (T.getArch()) {4231      case llvm::Triple::x86:4232        Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);4233        break;4234      case llvm::Triple::m68k:4235        Opts.setDefaultCallingConv(LangOptions::DCC_RtdCall);4236        break;4237      default:4238        Diags.Report(diag::err_drv_argument_not_allowed_with)4239            << A->getSpelling() << T.getTriple();4240      }4241    }4242  }4243 4244  // Check if -fopenmp is specified and set default version to 5.1.4245  Opts.OpenMP = Args.hasArg(OPT_fopenmp) ? 51 : 0;4246  // Check if -fopenmp-simd is specified.4247  bool IsSimdSpecified =4248      Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd,4249                   /*Default=*/false);4250  Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified;4251  Opts.OpenMPUseTLS =4252      Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);4253  Opts.OpenMPIsTargetDevice =4254      Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_target_device);4255  Opts.OpenMPIRBuilder =4256      Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_enable_irbuilder);4257  bool IsTargetSpecified =4258      Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_offload_targets_EQ);4259 4260  if (Opts.OpenMP || Opts.OpenMPSimd) {4261    if (int Version = getLastArgIntValue(4262            Args, OPT_fopenmp_version_EQ,4263            (IsSimdSpecified || IsTargetSpecified) ? 51 : Opts.OpenMP, Diags))4264      Opts.OpenMP = Version;4265    // Provide diagnostic when a given target is not expected to be an OpenMP4266    // device or host.4267    if (!Opts.OpenMPIsTargetDevice) {4268      switch (T.getArch()) {4269      default:4270        break;4271      // Add unsupported host targets here:4272      case llvm::Triple::nvptx:4273      case llvm::Triple::nvptx64:4274        Diags.Report(diag::err_drv_omp_host_target_not_supported) << T.str();4275        break;4276      }4277    }4278  }4279 4280  // Set the flag to prevent the implementation from emitting device exception4281  // handling code for those requiring so.4282  if ((Opts.OpenMPIsTargetDevice && T.isGPU()) || Opts.OpenCLCPlusPlus) {4283 4284    Opts.Exceptions = 0;4285    Opts.CXXExceptions = 0;4286  }4287  if (Opts.OpenMPIsTargetDevice && T.isNVPTX()) {4288    Opts.OpenMPCUDANumSMs =4289        getLastArgIntValue(Args, options::OPT_fopenmp_cuda_number_of_sm_EQ,4290                           Opts.OpenMPCUDANumSMs, Diags);4291    Opts.OpenMPCUDABlocksPerSM =4292        getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ,4293                           Opts.OpenMPCUDABlocksPerSM, Diags);4294    Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue(4295        Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ,4296        Opts.OpenMPCUDAReductionBufNum, Diags);4297  }4298 4299  // Set the value of the debugging flag used in the new offloading device RTL.4300  // Set either by a specific value or to a default if not specified.4301  if (Opts.OpenMPIsTargetDevice && (Args.hasArg(OPT_fopenmp_target_debug) ||4302                                    Args.hasArg(OPT_fopenmp_target_debug_EQ))) {4303    Opts.OpenMPTargetDebug = getLastArgIntValue(4304        Args, OPT_fopenmp_target_debug_EQ, Opts.OpenMPTargetDebug, Diags);4305    if (!Opts.OpenMPTargetDebug && Args.hasArg(OPT_fopenmp_target_debug))4306      Opts.OpenMPTargetDebug = 1;4307  }4308 4309  if (Opts.OpenMPIsTargetDevice) {4310    if (Args.hasArg(OPT_fopenmp_assume_teams_oversubscription))4311      Opts.OpenMPTeamSubscription = true;4312    if (Args.hasArg(OPT_fopenmp_assume_threads_oversubscription))4313      Opts.OpenMPThreadSubscription = true;4314  }4315 4316  // Get the OpenMP target triples if any.4317  if (Arg *A = Args.getLastArg(options::OPT_offload_targets_EQ)) {4318    enum ArchPtrSize { Arch16Bit, Arch32Bit, Arch64Bit };4319    auto getArchPtrSize = [](const llvm::Triple &T) {4320      if (T.isArch16Bit())4321        return Arch16Bit;4322      if (T.isArch32Bit())4323        return Arch32Bit;4324      assert(T.isArch64Bit() && "Expected 64-bit architecture");4325      return Arch64Bit;4326    };4327 4328    for (unsigned i = 0; i < A->getNumValues(); ++i) {4329      llvm::Triple TT(A->getValue(i));4330 4331      if (TT.getArch() == llvm::Triple::UnknownArch ||4332          !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||4333            TT.getArch() == llvm::Triple::spirv64 ||4334            TT.getArch() == llvm::Triple::systemz ||4335            TT.getArch() == llvm::Triple::loongarch64 ||4336            TT.getArch() == llvm::Triple::nvptx ||4337            TT.getArch() == llvm::Triple::nvptx64 || TT.isAMDGCN() ||4338            TT.getArch() == llvm::Triple::x86 ||4339            TT.getArch() == llvm::Triple::x86_64))4340        Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i);4341      else if (getArchPtrSize(T) != getArchPtrSize(TT))4342        Diags.Report(diag::err_drv_incompatible_omp_arch)4343            << A->getValue(i) << T.str();4344      else4345        Opts.OMPTargetTriples.push_back(TT);4346    }4347  }4348 4349  // Set CUDA mode for OpenMP target NVPTX/AMDGCN if specified in options4350  Opts.OpenMPCUDAMode = Opts.OpenMPIsTargetDevice &&4351                        (T.isNVPTX() || T.isAMDGCN()) &&4352                        Args.hasArg(options::OPT_fopenmp_cuda_mode);4353 4354  // OpenACC Configuration.4355  if (Args.hasArg(options::OPT_fopenacc))4356    Opts.OpenACC = true;4357 4358  if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {4359    StringRef Val = A->getValue();4360    if (Val == "fast")4361      Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);4362    else if (Val == "on")4363      Opts.setDefaultFPContractMode(LangOptions::FPM_On);4364    else if (Val == "off")4365      Opts.setDefaultFPContractMode(LangOptions::FPM_Off);4366    else if (Val == "fast-honor-pragmas")4367      Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas);4368    else4369      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;4370  }4371 4372  if (auto *A =4373          Args.getLastArg(OPT_fsanitize_undefined_ignore_overflow_pattern_EQ)) {4374    for (int i = 0, n = A->getNumValues(); i != n; ++i) {4375      Opts.OverflowPatternExclusionMask |=4376          llvm::StringSwitch<unsigned>(A->getValue(i))4377              .Case("none", LangOptionsBase::None)4378              .Case("all", LangOptionsBase::All)4379              .Case("add-unsigned-overflow-test",4380                    LangOptionsBase::AddUnsignedOverflowTest)4381              .Case("add-signed-overflow-test",4382                    LangOptionsBase::AddSignedOverflowTest)4383              .Case("negated-unsigned-const", LangOptionsBase::NegUnsignedConst)4384              .Case("unsigned-post-decr-while",4385                    LangOptionsBase::PostDecrInWhile)4386              .Default(0);4387    }4388  }4389 4390  // Parse -fsanitize= arguments.4391  parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),4392                      Diags, Opts.Sanitize);4393  Opts.NoSanitizeFiles = Args.getAllArgValues(OPT_fsanitize_ignorelist_EQ);4394  std::vector<std::string> systemIgnorelists =4395      Args.getAllArgValues(OPT_fsanitize_system_ignorelist_EQ);4396  Opts.NoSanitizeFiles.insert(Opts.NoSanitizeFiles.end(),4397                              systemIgnorelists.begin(),4398                              systemIgnorelists.end());4399 4400  if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {4401    Opts.setClangABICompat(LangOptions::ClangABI::Latest);4402 4403    StringRef Ver = A->getValue();4404    std::pair<StringRef, StringRef> VerParts = Ver.split('.');4405    int Major, Minor = 0;4406 4407    // Check the version number is valid: either 3.x (0 <= x <= 9) or4408    // y or y.0 (4 <= y <= current version).4409    if (!VerParts.first.starts_with("0") &&4410        !VerParts.first.getAsInteger(10, Major) && 3 <= Major &&4411        Major <= MAX_CLANG_ABI_COMPAT_VERSION &&4412        (Major == 34413             ? VerParts.second.size() == 1 &&4414                   !VerParts.second.getAsInteger(10, Minor)4415             : VerParts.first.size() == Ver.size() || VerParts.second == "0")) {4416      // Got a valid version number.4417#define ABI_VER_MAJOR_MINOR(Major_, Minor_)                                    \4418  if (std::tuple(Major, Minor) <= std::tuple(Major_, Minor_))                  \4419    Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_##_##Minor_);     \4420  else4421#define ABI_VER_MAJOR(Major_)                                                  \4422  if (Major <= Major_)                                                         \4423    Opts.setClangABICompat(LangOptions::ClangABI::Ver##Major_);                \4424  else4425#define ABI_VER_LATEST(Latest)                                                 \4426  { /* Equivalent to latest version - do nothing */                            \4427  }4428#include "clang/Basic/ABIVersions.def"4429    } else if (Ver != "latest") {4430      Diags.Report(diag::err_drv_invalid_value)4431          << A->getAsString(Args) << A->getValue();4432    }4433  }4434 4435  if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) {4436    StringRef SignScope = A->getValue();4437 4438    if (SignScope.equals_insensitive("none"))4439      Opts.setSignReturnAddressScope(4440          LangOptions::SignReturnAddressScopeKind::None);4441    else if (SignScope.equals_insensitive("all"))4442      Opts.setSignReturnAddressScope(4443          LangOptions::SignReturnAddressScopeKind::All);4444    else if (SignScope.equals_insensitive("non-leaf"))4445      Opts.setSignReturnAddressScope(4446          LangOptions::SignReturnAddressScopeKind::NonLeaf);4447    else4448      Diags.Report(diag::err_drv_invalid_value)4449          << A->getAsString(Args) << SignScope;4450 4451    if (Arg *A = Args.getLastArg(OPT_msign_return_address_key_EQ)) {4452      StringRef SignKey = A->getValue();4453      if (!SignScope.empty() && !SignKey.empty()) {4454        if (SignKey == "a_key")4455          Opts.setSignReturnAddressKey(4456              LangOptions::SignReturnAddressKeyKind::AKey);4457        else if (SignKey == "b_key")4458          Opts.setSignReturnAddressKey(4459              LangOptions::SignReturnAddressKeyKind::BKey);4460        else4461          Diags.Report(diag::err_drv_invalid_value)4462              << A->getAsString(Args) << SignKey;4463      }4464    }4465  }4466 4467  // The value can be empty, which indicates the system default should be used.4468  StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ);4469  if (!CXXABI.empty()) {4470    if (!TargetCXXABI::isABI(CXXABI)) {4471      Diags.Report(diag::err_invalid_cxx_abi) << CXXABI;4472    } else {4473      auto Kind = TargetCXXABI::getKind(CXXABI);4474      if (!TargetCXXABI::isSupportedCXXABI(T, Kind))4475        Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str();4476      else4477        Opts.CXXABI = Kind;4478    }4479  }4480 4481  Opts.RelativeCXXABIVTables =4482      Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,4483                   options::OPT_fno_experimental_relative_cxx_abi_vtables,4484                   TargetCXXABI::usesRelativeVTables(T));4485 4486  // RTTI is on by default.4487  bool HasRTTI = !Args.hasArg(options::OPT_fno_rtti);4488  Opts.OmitVTableRTTI =4489      Args.hasFlag(options::OPT_fexperimental_omit_vtable_rtti,4490                   options::OPT_fno_experimental_omit_vtable_rtti, false);4491  if (Opts.OmitVTableRTTI && HasRTTI)4492    Diags.Report(diag::err_drv_using_omit_rtti_component_without_no_rtti);4493 4494  for (const auto &A : Args.getAllArgValues(OPT_fmacro_prefix_map_EQ)) {4495    auto Split = StringRef(A).split('=');4496    Opts.MacroPrefixMap.insert(4497        {std::string(Split.first), std::string(Split.second)});4498  }4499 4500  Opts.UseTargetPathSeparator =4501      !Args.getLastArg(OPT_fno_file_reproducible) &&4502      (Args.getLastArg(OPT_ffile_compilation_dir_EQ) ||4503       Args.getLastArg(OPT_fmacro_prefix_map_EQ) ||4504       Args.getLastArg(OPT_ffile_reproducible));4505 4506  // Error if -mvscale-min is unbounded.4507  if (Arg *A = Args.getLastArg(options::OPT_mvscale_min_EQ)) {4508    unsigned VScaleMin;4509    if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)4510      Diags.Report(diag::err_cc1_unbounded_vscale_min);4511  }4512  if (Arg *A = Args.getLastArg(options::OPT_mvscale_streaming_min_EQ)) {4513    unsigned VScaleMin;4514    if (StringRef(A->getValue()).getAsInteger(10, VScaleMin) || VScaleMin == 0)4515      Diags.Report(diag::err_cc1_unbounded_vscale_min);4516  }4517 4518  if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) {4519    std::ifstream SeedFile(A->getValue(0));4520 4521    if (!SeedFile.is_open())4522      Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file)4523          << A->getValue(0);4524 4525    std::getline(SeedFile, Opts.RandstructSeed);4526  }4527 4528  if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ))4529    Opts.RandstructSeed = A->getValue(0);4530 4531  if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_max_EQ)) {4532    StringRef S = Arg->getValue();4533    uint64_t Value = 0;4534    if (S.getAsInteger(0, Value))4535      Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;4536    else4537      Opts.AllocTokenMax = Value;4538  }4539 4540  if (const auto *Arg = Args.getLastArg(options::OPT_falloc_token_mode_EQ)) {4541    StringRef S = Arg->getValue();4542    if (auto Mode = getAllocTokenModeFromString(S))4543      Opts.AllocTokenMode = Mode;4544    else4545      Diags.Report(diag::err_drv_invalid_value) << Arg->getAsString(Args) << S;4546  }4547 4548  // Validate options for HLSL4549  if (Opts.HLSL) {4550    // TODO: Revisit restricting SPIR-V to logical once we've figured out how to4551    // handle PhysicalStorageBuffer64 memory model4552    if (T.isDXIL() || T.isSPIRVLogical()) {4553      enum { ShaderModel, VulkanEnv, ShaderStage };4554      enum { OS, Environment };4555 4556      int ExpectedOS = T.isSPIRVLogical() ? VulkanEnv : ShaderModel;4557 4558      if (T.getOSName().empty()) {4559        Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)4560            << ExpectedOS << OS << T.str();4561      } else if (T.getEnvironmentName().empty()) {4562        Diags.Report(diag::err_drv_hlsl_bad_shader_required_in_target)4563            << ShaderStage << Environment << T.str();4564      } else if (!T.isShaderStageEnvironment()) {4565        Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)4566            << ShaderStage << T.getEnvironmentName() << T.str();4567      }4568 4569      if (T.isDXIL()) {4570        if (!T.isShaderModelOS() || T.getOSVersion() == VersionTuple(0)) {4571          Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)4572              << ShaderModel << T.getOSName() << T.str();4573        }4574        // Validate that if fnative-half-type is given, that4575        // the language standard is at least hlsl2018, and that4576        // the target shader model is at least 6.2.4577        if (Args.getLastArg(OPT_fnative_half_type) ||4578            Args.getLastArg(OPT_fnative_int16_type)) {4579          const LangStandard &Std =4580              LangStandard::getLangStandardForKind(Opts.LangStd);4581          if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 &&4582                T.getOSVersion() >= VersionTuple(6, 2)))4583            Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)4584                << "-enable-16bit-types" << true << Std.getName()4585                << T.getOSVersion().getAsString();4586        }4587      } else if (T.isSPIRVLogical()) {4588        if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) {4589          Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported)4590              << VulkanEnv << T.getOSName() << T.str();4591        }4592        if (Args.getLastArg(OPT_fnative_half_type) ||4593            Args.getLastArg(OPT_fnative_int16_type)) {4594          const char *Str = Args.getLastArg(OPT_fnative_half_type)4595                                ? "-fnative-half-type"4596                                : "-fnative-int16-type";4597          const LangStandard &Std =4598              LangStandard::getLangStandardForKind(Opts.LangStd);4599          if (!(Opts.LangStd >= LangStandard::lang_hlsl2018))4600            Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported)4601                << Str << false << Std.getName();4602        }4603      } else {4604        llvm_unreachable("expected DXIL or SPIR-V target");4605      }4606    } else4607      Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str();4608 4609    if (Opts.LangStd < LangStandard::lang_hlsl202x) {4610      const LangStandard &Requested =4611          LangStandard::getLangStandardForKind(Opts.LangStd);4612      const LangStandard &Recommended =4613          LangStandard::getLangStandardForKind(LangStandard::lang_hlsl202x);4614      Diags.Report(diag::warn_hlsl_langstd_minimal)4615          << Requested.getName() << Recommended.getName();4616    }4617  }4618 4619  return Diags.getNumErrors() == NumErrorsBefore;4620}4621 4622static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {4623  switch (Action) {4624  case frontend::ASTDeclList:4625  case frontend::ASTDump:4626  case frontend::ASTPrint:4627  case frontend::ASTView:4628  case frontend::EmitAssembly:4629  case frontend::EmitBC:4630  case frontend::EmitCIR:4631  case frontend::EmitHTML:4632  case frontend::EmitLLVM:4633  case frontend::EmitLLVMOnly:4634  case frontend::EmitCodeGenOnly:4635  case frontend::EmitObj:4636  case frontend::ExtractAPI:4637  case frontend::FixIt:4638  case frontend::GenerateModule:4639  case frontend::GenerateModuleInterface:4640  case frontend::GenerateReducedModuleInterface:4641  case frontend::GenerateHeaderUnit:4642  case frontend::GeneratePCH:4643  case frontend::GenerateInterfaceStubs:4644  case frontend::ParseSyntaxOnly:4645  case frontend::ModuleFileInfo:4646  case frontend::VerifyPCH:4647  case frontend::PluginAction:4648  case frontend::RewriteObjC:4649  case frontend::RewriteTest:4650  case frontend::RunAnalysis:4651  case frontend::TemplightDump:4652    return false;4653 4654  case frontend::DumpCompilerOptions:4655  case frontend::DumpRawTokens:4656  case frontend::DumpTokens:4657  case frontend::InitOnly:4658  case frontend::PrintPreamble:4659  case frontend::PrintPreprocessedInput:4660  case frontend::RewriteMacros:4661  case frontend::RunPreprocessorOnly:4662  case frontend::PrintDependencyDirectivesSourceMinimizerOutput:4663    return true;4664  }4665  llvm_unreachable("invalid frontend action");4666}4667 4668static bool isCodeGenAction(frontend::ActionKind Action) {4669  switch (Action) {4670  case frontend::EmitAssembly:4671  case frontend::EmitBC:4672  case frontend::EmitCIR:4673  case frontend::EmitHTML:4674  case frontend::EmitLLVM:4675  case frontend::EmitLLVMOnly:4676  case frontend::EmitCodeGenOnly:4677  case frontend::EmitObj:4678  case frontend::GenerateModule:4679  case frontend::GenerateModuleInterface:4680  case frontend::GenerateReducedModuleInterface:4681  case frontend::GenerateHeaderUnit:4682  case frontend::GeneratePCH:4683  case frontend::GenerateInterfaceStubs:4684    return true;4685  case frontend::ASTDeclList:4686  case frontend::ASTDump:4687  case frontend::ASTPrint:4688  case frontend::ASTView:4689  case frontend::ExtractAPI:4690  case frontend::FixIt:4691  case frontend::ParseSyntaxOnly:4692  case frontend::ModuleFileInfo:4693  case frontend::VerifyPCH:4694  case frontend::PluginAction:4695  case frontend::RewriteObjC:4696  case frontend::RewriteTest:4697  case frontend::RunAnalysis:4698  case frontend::TemplightDump:4699  case frontend::DumpCompilerOptions:4700  case frontend::DumpRawTokens:4701  case frontend::DumpTokens:4702  case frontend::InitOnly:4703  case frontend::PrintPreamble:4704  case frontend::PrintPreprocessedInput:4705  case frontend::RewriteMacros:4706  case frontend::RunPreprocessorOnly:4707  case frontend::PrintDependencyDirectivesSourceMinimizerOutput:4708    return false;4709  }4710  llvm_unreachable("invalid frontend action");4711}4712 4713static void GeneratePreprocessorArgs(const PreprocessorOptions &Opts,4714                                     ArgumentConsumer Consumer,4715                                     const LangOptions &LangOpts,4716                                     const FrontendOptions &FrontendOpts,4717                                     const CodeGenOptions &CodeGenOpts) {4718  const PreprocessorOptions *PreprocessorOpts = &Opts;4719 4720#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...)                              \4721  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)4722#include "clang/Options/Options.inc"4723#undef PREPROCESSOR_OPTION_WITH_MARSHALLING4724 4725  if (Opts.PCHWithHdrStop && !Opts.PCHWithHdrStopCreate)4726    GenerateArg(Consumer, OPT_pch_through_hdrstop_use);4727 4728  for (const auto &D : Opts.DeserializedPCHDeclsToErrorOn)4729    GenerateArg(Consumer, OPT_error_on_deserialized_pch_decl, D);4730 4731  if (Opts.PrecompiledPreambleBytes != std::make_pair(0u, false))4732    GenerateArg(Consumer, OPT_preamble_bytes_EQ,4733                Twine(Opts.PrecompiledPreambleBytes.first) + "," +4734                    (Opts.PrecompiledPreambleBytes.second ? "1" : "0"));4735 4736  for (const auto &M : Opts.Macros) {4737    // Don't generate __CET__ macro definitions. They are implied by the4738    // -fcf-protection option that is generated elsewhere.4739    if (M.first == "__CET__=1" && !M.second &&4740        !CodeGenOpts.CFProtectionReturn && CodeGenOpts.CFProtectionBranch)4741      continue;4742    if (M.first == "__CET__=2" && !M.second && CodeGenOpts.CFProtectionReturn &&4743        !CodeGenOpts.CFProtectionBranch)4744      continue;4745    if (M.first == "__CET__=3" && !M.second && CodeGenOpts.CFProtectionReturn &&4746        CodeGenOpts.CFProtectionBranch)4747      continue;4748 4749    GenerateArg(Consumer, M.second ? OPT_U : OPT_D, M.first);4750  }4751 4752  for (const auto &I : Opts.Includes) {4753    // Don't generate OpenCL includes. They are implied by other flags that are4754    // generated elsewhere.4755    if (LangOpts.OpenCL && LangOpts.IncludeDefaultHeader &&4756        ((LangOpts.DeclareOpenCLBuiltins && I == "opencl-c-base.h") ||4757         I == "opencl-c.h"))4758      continue;4759    // Don't generate HLSL includes. They are implied by other flags that are4760    // generated elsewhere.4761    if (LangOpts.HLSL && I == "hlsl.h")4762      continue;4763 4764    GenerateArg(Consumer, OPT_include, I);4765  }4766 4767  for (const auto &CI : Opts.ChainedIncludes)4768    GenerateArg(Consumer, OPT_chain_include, CI);4769 4770  for (const auto &RF : Opts.RemappedFiles)4771    GenerateArg(Consumer, OPT_remap_file, RF.first + ";" + RF.second);4772 4773  if (Opts.SourceDateEpoch)4774    GenerateArg(Consumer, OPT_source_date_epoch, Twine(*Opts.SourceDateEpoch));4775 4776  if (Opts.DefineTargetOSMacros)4777    GenerateArg(Consumer, OPT_fdefine_target_os_macros);4778 4779  for (const auto &EmbedEntry : Opts.EmbedEntries)4780    GenerateArg(Consumer, OPT_embed_dir_EQ, EmbedEntry);4781 4782  // Don't handle LexEditorPlaceholders. It is implied by the action that is4783  // generated elsewhere.4784}4785 4786static bool ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,4787                                  DiagnosticsEngine &Diags,4788                                  frontend::ActionKind Action,4789                                  const FrontendOptions &FrontendOpts) {4790  unsigned NumErrorsBefore = Diags.getNumErrors();4791 4792  PreprocessorOptions *PreprocessorOpts = &Opts;4793 4794#define PREPROCESSOR_OPTION_WITH_MARSHALLING(...)                              \4795  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)4796#include "clang/Options/Options.inc"4797#undef PREPROCESSOR_OPTION_WITH_MARSHALLING4798 4799  Opts.PCHWithHdrStop = Args.hasArg(OPT_pch_through_hdrstop_create) ||4800                        Args.hasArg(OPT_pch_through_hdrstop_use);4801 4802  for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl))4803    Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue());4804 4805  if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {4806    StringRef Value(A->getValue());4807    size_t Comma = Value.find(',');4808    unsigned Bytes = 0;4809    unsigned EndOfLine = 0;4810 4811    if (Comma == StringRef::npos ||4812        Value.substr(0, Comma).getAsInteger(10, Bytes) ||4813        Value.substr(Comma + 1).getAsInteger(10, EndOfLine))4814      Diags.Report(diag::err_drv_preamble_format);4815    else {4816      Opts.PrecompiledPreambleBytes.first = Bytes;4817      Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);4818    }4819  }4820 4821  // Add macros from the command line.4822  for (const auto *A : Args.filtered(OPT_D, OPT_U)) {4823    if (A->getOption().matches(OPT_D))4824      Opts.addMacroDef(A->getValue());4825    else4826      Opts.addMacroUndef(A->getValue());4827  }4828 4829  // Add the ordered list of -includes.4830  for (const auto *A : Args.filtered(OPT_include))4831    Opts.Includes.emplace_back(A->getValue());4832 4833  for (const auto *A : Args.filtered(OPT_chain_include))4834    Opts.ChainedIncludes.emplace_back(A->getValue());4835 4836  for (const auto *A : Args.filtered(OPT_remap_file)) {4837    std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');4838 4839    if (Split.second.empty()) {4840      Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);4841      continue;4842    }4843 4844    Opts.addRemappedFile(Split.first, Split.second);4845  }4846 4847  if (const Arg *A = Args.getLastArg(OPT_source_date_epoch)) {4848    StringRef Epoch = A->getValue();4849    // SOURCE_DATE_EPOCH, if specified, must be a non-negative decimal integer.4850    // On time64 systems, pick 253402300799 (the UNIX timestamp of4851    // 9999-12-31T23:59:59Z) as the upper bound.4852    const uint64_t MaxTimestamp =4853        std::min<uint64_t>(std::numeric_limits<time_t>::max(), 253402300799);4854    uint64_t V;4855    if (Epoch.getAsInteger(10, V) || V > MaxTimestamp) {4856      Diags.Report(diag::err_fe_invalid_source_date_epoch)4857          << Epoch << MaxTimestamp;4858    } else {4859      Opts.SourceDateEpoch = V;4860    }4861  }4862 4863  for (const auto *A : Args.filtered(OPT_embed_dir_EQ)) {4864    StringRef Val = A->getValue();4865    Opts.EmbedEntries.push_back(std::string(Val));4866  }4867 4868  // Always avoid lexing editor placeholders when we're just running the4869  // preprocessor as we never want to emit the4870  // "editor placeholder in source file" error in PP only mode.4871  if (isStrictlyPreprocessorAction(Action))4872    Opts.LexEditorPlaceholders = false;4873 4874  Opts.DefineTargetOSMacros =4875      Args.hasFlag(OPT_fdefine_target_os_macros,4876                   OPT_fno_define_target_os_macros, Opts.DefineTargetOSMacros);4877 4878  return Diags.getNumErrors() == NumErrorsBefore;4879}4880 4881static void4882GeneratePreprocessorOutputArgs(const PreprocessorOutputOptions &Opts,4883                               ArgumentConsumer Consumer,4884                               frontend::ActionKind Action) {4885  const PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;4886 4887#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...)                       \4888  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)4889#include "clang/Options/Options.inc"4890#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING4891 4892  bool Generate_dM = isStrictlyPreprocessorAction(Action) && !Opts.ShowCPP;4893  if (Generate_dM)4894    GenerateArg(Consumer, OPT_dM);4895  if (!Generate_dM && Opts.ShowMacros)4896    GenerateArg(Consumer, OPT_dD);4897  if (Opts.DirectivesOnly)4898    GenerateArg(Consumer, OPT_fdirectives_only);4899}4900 4901static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,4902                                        ArgList &Args, DiagnosticsEngine &Diags,4903                                        frontend::ActionKind Action) {4904  unsigned NumErrorsBefore = Diags.getNumErrors();4905 4906  PreprocessorOutputOptions &PreprocessorOutputOpts = Opts;4907 4908#define PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING(...)                       \4909  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)4910#include "clang/Options/Options.inc"4911#undef PREPROCESSOR_OUTPUT_OPTION_WITH_MARSHALLING4912 4913  Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);4914  Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);4915  Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);4916 4917  return Diags.getNumErrors() == NumErrorsBefore;4918}4919 4920static void GenerateTargetArgs(const TargetOptions &Opts,4921                               ArgumentConsumer Consumer) {4922  const TargetOptions *TargetOpts = &Opts;4923#define TARGET_OPTION_WITH_MARSHALLING(...)                                    \4924  GENERATE_OPTION_WITH_MARSHALLING(Consumer, __VA_ARGS__)4925#include "clang/Options/Options.inc"4926#undef TARGET_OPTION_WITH_MARSHALLING4927 4928  if (!Opts.SDKVersion.empty())4929    GenerateArg(Consumer, OPT_target_sdk_version_EQ,4930                Opts.SDKVersion.getAsString());4931  if (!Opts.DarwinTargetVariantSDKVersion.empty())4932    GenerateArg(Consumer, OPT_darwin_target_variant_sdk_version_EQ,4933                Opts.DarwinTargetVariantSDKVersion.getAsString());4934}4935 4936static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args,4937                            DiagnosticsEngine &Diags) {4938  unsigned NumErrorsBefore = Diags.getNumErrors();4939 4940  TargetOptions *TargetOpts = &Opts;4941 4942#define TARGET_OPTION_WITH_MARSHALLING(...)                                    \4943  PARSE_OPTION_WITH_MARSHALLING(Args, Diags, __VA_ARGS__)4944#include "clang/Options/Options.inc"4945#undef TARGET_OPTION_WITH_MARSHALLING4946 4947  if (Arg *A = Args.getLastArg(options::OPT_target_sdk_version_EQ)) {4948    llvm::VersionTuple Version;4949    if (Version.tryParse(A->getValue()))4950      Diags.Report(diag::err_drv_invalid_value)4951          << A->getAsString(Args) << A->getValue();4952    else4953      Opts.SDKVersion = Version;4954  }4955  if (Arg *A =4956          Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) {4957    llvm::VersionTuple Version;4958    if (Version.tryParse(A->getValue()))4959      Diags.Report(diag::err_drv_invalid_value)4960          << A->getAsString(Args) << A->getValue();4961    else4962      Opts.DarwinTargetVariantSDKVersion = Version;4963  }4964 4965  return Diags.getNumErrors() == NumErrorsBefore;4966}4967 4968bool CompilerInvocation::CreateFromArgsImpl(4969    CompilerInvocation &Res, ArrayRef<const char *> CommandLineArgs,4970    DiagnosticsEngine &Diags, const char *Argv0) {4971  unsigned NumErrorsBefore = Diags.getNumErrors();4972 4973  // Parse the arguments.4974  const OptTable &Opts = getDriverOptTable();4975  llvm::opt::Visibility VisibilityMask(options::CC1Option);4976  unsigned MissingArgIndex, MissingArgCount;4977  InputArgList Args = Opts.ParseArgs(CommandLineArgs, MissingArgIndex,4978                                     MissingArgCount, VisibilityMask);4979  LangOptions &LangOpts = Res.getLangOpts();4980 4981  // Check for missing argument error.4982  if (MissingArgCount)4983    Diags.Report(diag::err_drv_missing_argument)4984        << Args.getArgString(MissingArgIndex) << MissingArgCount;4985 4986  // Issue errors on unknown arguments.4987  for (const auto *A : Args.filtered(OPT_UNKNOWN)) {4988    auto ArgString = A->getAsString(Args);4989    std::string Nearest;4990    if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)4991      Diags.Report(diag::err_drv_unknown_argument) << ArgString;4992    else4993      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)4994          << ArgString << Nearest;4995  }4996 4997  ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);4998  ParseMigratorArgs(Res.getMigratorOpts(), Args, Diags);4999  ParseAnalyzerArgs(Res.getAnalyzerOpts(), Args, Diags);5000  ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,5001                      /*DefaultDiagColor=*/false);5002  ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, LangOpts.IsHeaderFile);5003  // FIXME: We shouldn't have to pass the DashX option around here5004  InputKind DashX = Res.getFrontendOpts().DashX;5005  ParseTargetArgs(Res.getTargetOpts(), Args, Diags);5006  llvm::Triple T(Res.getTargetOpts().Triple);5007  ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Diags);5008  if (Res.getFrontendOpts().GenReducedBMI ||5009      Res.getFrontendOpts().ProgramAction ==5010          frontend::GenerateReducedModuleInterface ||5011      Res.getFrontendOpts().ProgramAction ==5012          frontend::GenerateModuleInterface) {5013    Res.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true;5014    Res.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true;5015  }5016  ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags);5017 5018  ParsePointerAuthArgs(LangOpts, Args, Diags);5019 5020  ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes,5021                Diags);5022  if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)5023    LangOpts.ObjCExceptions = 1;5024 5025  for (auto Warning : Res.getDiagnosticOpts().Warnings) {5026    if (Warning == "misexpect" &&5027        !Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation())) {5028      Res.getCodeGenOpts().MisExpect = true;5029    }5030  }5031 5032  if (LangOpts.CUDA) {5033    // During CUDA device-side compilation, the aux triple is the5034    // triple used for host compilation.5035    if (LangOpts.CUDAIsDevice)5036      Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;5037  }5038 5039  if (LangOpts.OpenACC && !Res.getFrontendOpts().UseClangIRPipeline &&5040      isCodeGenAction(Res.getFrontendOpts().ProgramAction))5041    Diags.Report(diag::warn_drv_openacc_without_cir);5042 5043  // Set the triple of the host for OpenMP device compile.5044  if (LangOpts.OpenMPIsTargetDevice)5045    Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;5046 5047  ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, T,5048                   Res.getFrontendOpts().OutputFile, LangOpts);5049 5050  // FIXME: Override value name discarding when asan or msan is used because the5051  // backend passes depend on the name of the alloca in order to print out5052  // names.5053  Res.getCodeGenOpts().DiscardValueNames &=5054      !LangOpts.Sanitize.has(SanitizerKind::Address) &&5055      !LangOpts.Sanitize.has(SanitizerKind::KernelAddress) &&5056      !LangOpts.Sanitize.has(SanitizerKind::Memory) &&5057      !LangOpts.Sanitize.has(SanitizerKind::KernelMemory);5058 5059  ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags,5060                        Res.getFrontendOpts().ProgramAction,5061                        Res.getFrontendOpts());5062  ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Diags,5063                              Res.getFrontendOpts().ProgramAction);5064 5065  ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args, Diags,5066                            Res.getFrontendOpts().ProgramAction,5067                            Res.getPreprocessorOutputOpts().ShowLineMarkers);5068  if (!Res.getDependencyOutputOpts().OutputFile.empty() &&5069      Res.getDependencyOutputOpts().Targets.empty())5070    Diags.Report(diag::err_fe_dependency_file_requires_MT);5071 5072  // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.5073  if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&5074      !Res.getLangOpts().Sanitize.empty()) {5075    Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;5076    Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);5077  }5078 5079  // Store the command-line for using in the CodeView backend.5080  if (Res.getCodeGenOpts().CodeViewCommandLine) {5081    Res.getCodeGenOpts().Argv0 = Argv0;5082    append_range(Res.getCodeGenOpts().CommandLineArgs, CommandLineArgs);5083  }5084 5085  if (!Res.getCodeGenOpts().ProfileInstrumentUsePath.empty() &&5086      Res.getCodeGenOpts().getProfileUse() ==5087          llvm::driver::ProfileInstrKind::ProfileNone)5088    Diags.Report(diag::err_drv_profile_instrument_use_path_with_no_kind);5089 5090  FixupInvocation(Res, Diags, Args, DashX);5091 5092  return Diags.getNumErrors() == NumErrorsBefore;5093}5094 5095bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Invocation,5096                                        ArrayRef<const char *> CommandLineArgs,5097                                        DiagnosticsEngine &Diags,5098                                        const char *Argv0) {5099  CompilerInvocation DummyInvocation;5100 5101  return RoundTrip(5102      [](CompilerInvocation &Invocation, ArrayRef<const char *> CommandLineArgs,5103         DiagnosticsEngine &Diags, const char *Argv0) {5104        return CreateFromArgsImpl(Invocation, CommandLineArgs, Diags, Argv0);5105      },5106      [](CompilerInvocation &Invocation, SmallVectorImpl<const char *> &Args,5107         StringAllocator SA) {5108        Args.push_back("-cc1");5109        Invocation.generateCC1CommandLine(Args, SA);5110      },5111      Invocation, DummyInvocation, CommandLineArgs, Diags, Argv0);5112}5113 5114std::string CompilerInvocation::getModuleHash() const {5115  // FIXME: Consider using SHA1 instead of MD5.5116  llvm::HashBuilder<llvm::MD5, llvm::endianness::native> HBuilder;5117 5118  // Note: For QoI reasons, the things we use as a hash here should all be5119  // dumped via the -module-info flag.5120 5121  // Start the signature with the compiler version.5122  HBuilder.add(getClangFullRepositoryVersion());5123 5124  // Also include the serialization version, in case LLVM_APPEND_VC_REV is off5125  // and getClangFullRepositoryVersion() doesn't include git revision.5126  HBuilder.add(serialization::VERSION_MAJOR, serialization::VERSION_MINOR);5127 5128  // Extend the signature with the language options5129  // FIXME: Replace with C++20 `using enum LangOptions::CompatibilityKind`.5130  using CK = LangOptions::CompatibilityKind;5131#define LANGOPT(Name, Bits, Default, Compatibility, Description)               \5132  if constexpr (CK::Compatibility != CK::Benign)                               \5133    HBuilder.add(LangOpts->Name);5134#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description)    \5135  if constexpr (CK::Compatibility != CK::Benign)                               \5136    HBuilder.add(static_cast<unsigned>(LangOpts->get##Name()));5137#include "clang/Basic/LangOptions.def"5138 5139  HBuilder.addRange(getLangOpts().ModuleFeatures);5140 5141  HBuilder.add(getLangOpts().ObjCRuntime);5142  HBuilder.addRange(getLangOpts().CommentOpts.BlockCommandNames);5143 5144  // Extend the signature with the target options.5145  HBuilder.add(getTargetOpts().Triple, getTargetOpts().CPU,5146               getTargetOpts().TuneCPU, getTargetOpts().ABI);5147  HBuilder.addRange(getTargetOpts().FeaturesAsWritten);5148 5149  // Extend the signature with preprocessor options.5150  const PreprocessorOptions &ppOpts = getPreprocessorOpts();5151  HBuilder.add(ppOpts.UsePredefines, ppOpts.DetailedRecord);5152 5153  const HeaderSearchOptions &hsOpts = getHeaderSearchOpts();5154  for (const auto &Macro : getPreprocessorOpts().Macros) {5155    // If we're supposed to ignore this macro for the purposes of modules,5156    // don't put it into the hash.5157    if (!hsOpts.ModulesIgnoreMacros.empty()) {5158      // Check whether we're ignoring this macro.5159      StringRef MacroDef = Macro.first;5160      if (hsOpts.ModulesIgnoreMacros.count(5161              llvm::CachedHashString(MacroDef.split('=').first)))5162        continue;5163    }5164 5165    HBuilder.add(Macro);5166  }5167 5168  // Extend the signature with the sysroot and other header search options.5169  HBuilder.add(hsOpts.Sysroot, hsOpts.ModuleFormat, hsOpts.UseDebugInfo,5170               hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes,5171               hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx,5172               hsOpts.ModulesValidateDiagnosticOptions);5173  HBuilder.add(hsOpts.ResourceDir);5174 5175  if (hsOpts.ModulesStrictContextHash) {5176    HBuilder.addRange(hsOpts.SystemHeaderPrefixes);5177    HBuilder.addRange(hsOpts.UserEntries);5178    HBuilder.addRange(hsOpts.VFSOverlayFiles);5179 5180    const DiagnosticOptions &diagOpts = getDiagnosticOpts();5181#define DIAGOPT(Name, Bits, Default) HBuilder.add(diagOpts.Name);5182#define ENUM_DIAGOPT(Name, Type, Bits, Default)                                \5183  HBuilder.add(diagOpts.get##Name());5184#include "clang/Basic/DiagnosticOptions.def"5185#undef DIAGOPT5186#undef ENUM_DIAGOPT5187  }5188 5189  // Extend the signature with the user build path.5190  HBuilder.add(hsOpts.ModuleUserBuildPath);5191 5192  // Extend the signature with the module file extensions.5193  for (const auto &ext : getFrontendOpts().ModuleFileExtensions)5194    ext->hashExtension(HBuilder);5195 5196  // Extend the signature with the Swift version for API notes.5197  const APINotesOptions &APINotesOpts = getAPINotesOpts();5198  if (!APINotesOpts.SwiftVersion.empty()) {5199    HBuilder.add(APINotesOpts.SwiftVersion.getMajor());5200    if (auto Minor = APINotesOpts.SwiftVersion.getMinor())5201      HBuilder.add(*Minor);5202    if (auto Subminor = APINotesOpts.SwiftVersion.getSubminor())5203      HBuilder.add(*Subminor);5204    if (auto Build = APINotesOpts.SwiftVersion.getBuild())5205      HBuilder.add(*Build);5206  }5207 5208  // Extend the signature with affecting codegen options.5209  {5210    using CK = CodeGenOptions::CompatibilityKind;5211#define CODEGENOPT(Name, Bits, Default, Compatibility)                         \5212  if constexpr (CK::Compatibility != CK::Benign)                               \5213    HBuilder.add(CodeGenOpts->Name);5214#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility)              \5215  if constexpr (CK::Compatibility != CK::Benign)                               \5216    HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));5217#define DEBUGOPT(Name, Bits, Default, Compatibility)5218#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)5219#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)5220#include "clang/Basic/CodeGenOptions.def"5221  }5222 5223  // When compiling with -gmodules, also hash -fdebug-prefix-map as it5224  // affects the debug info in the PCM.5225  if (getCodeGenOpts().DebugTypeExtRefs)5226    HBuilder.addRange(getCodeGenOpts().DebugPrefixMap);5227 5228  // Extend the signature with the affecting debug options.5229  if (getHeaderSearchOpts().ModuleFormat == "obj") {5230    // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.5231    using CK = CodeGenOptions::CompatibilityKind;5232#define DEBUGOPT(Name, Bits, Default, Compatibility)                           \5233  if constexpr (CK::Compatibility != CK::Benign)                               \5234    HBuilder.add(CodeGenOpts->Name);5235#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)                     \5236  if constexpr (CK::Compatibility != CK::Benign)                               \5237    HBuilder.add(CodeGenOpts->Name);5238#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)                \5239  if constexpr (CK::Compatibility != CK::Benign)                               \5240    HBuilder.add(static_cast<unsigned>(CodeGenOpts->get##Name()));5241#include "clang/Basic/DebugOptions.def"5242  }5243 5244  // Extend the signature with the enabled sanitizers, if at least one is5245  // enabled. Sanitizers which cannot affect AST generation aren't hashed.5246  SanitizerSet SanHash = getLangOpts().Sanitize;5247  SanHash.clear(getPPTransparentSanitizers());5248  if (!SanHash.empty())5249    HBuilder.add(SanHash.Mask);5250 5251  llvm::MD5::MD5Result Result;5252  HBuilder.getHasher().final(Result);5253  uint64_t Hash = Result.high() ^ Result.low();5254  return toString(llvm::APInt(64, Hash), 36, /*Signed=*/false);5255}5256 5257void CompilerInvocationBase::visitPathsImpl(5258    llvm::function_ref<bool(std::string &)> Predicate) {5259#define RETURN_IF(PATH)                                                        \5260  do {                                                                         \5261    if (Predicate(PATH))                                                       \5262      return;                                                                  \5263  } while (0)5264 5265#define RETURN_IF_MANY(PATHS)                                                  \5266  do {                                                                         \5267    if (llvm::any_of(PATHS, Predicate))                                        \5268      return;                                                                  \5269  } while (0)5270 5271  auto &HeaderSearchOpts = *this->HSOpts;5272  // Header search paths.5273  RETURN_IF(HeaderSearchOpts.Sysroot);5274  for (auto &Entry : HeaderSearchOpts.UserEntries)5275    if (Entry.IgnoreSysRoot)5276      RETURN_IF(Entry.Path);5277  RETURN_IF(HeaderSearchOpts.ResourceDir);5278  RETURN_IF(HeaderSearchOpts.ModuleCachePath);5279  RETURN_IF(HeaderSearchOpts.ModuleUserBuildPath);5280  for (auto &[Name, File] : HeaderSearchOpts.PrebuiltModuleFiles)5281    RETURN_IF(File);5282  RETURN_IF_MANY(HeaderSearchOpts.PrebuiltModulePaths);5283  RETURN_IF_MANY(HeaderSearchOpts.VFSOverlayFiles);5284 5285  // Preprocessor options.5286  auto &PPOpts = *this->PPOpts;5287  RETURN_IF_MANY(PPOpts.MacroIncludes);5288  RETURN_IF_MANY(PPOpts.Includes);5289  RETURN_IF(PPOpts.ImplicitPCHInclude);5290 5291  // Frontend options.5292  auto &FrontendOpts = *this->FrontendOpts;5293  for (auto &Input : FrontendOpts.Inputs) {5294    if (Input.isBuffer())5295      continue;5296 5297    RETURN_IF(Input.File);5298  }5299  // TODO: Also report output files such as FrontendOpts.OutputFile;5300  RETURN_IF(FrontendOpts.CodeCompletionAt.FileName);5301  RETURN_IF_MANY(FrontendOpts.ModuleMapFiles);5302  RETURN_IF_MANY(FrontendOpts.ModuleFiles);5303  RETURN_IF_MANY(FrontendOpts.ModulesEmbedFiles);5304  RETURN_IF_MANY(FrontendOpts.ASTMergeFiles);5305  RETURN_IF(FrontendOpts.OverrideRecordLayoutsFile);5306  RETURN_IF(FrontendOpts.StatsFile);5307 5308  // Filesystem options.5309  auto &FileSystemOpts = *this->FSOpts;5310  RETURN_IF(FileSystemOpts.WorkingDir);5311 5312  // Codegen options.5313  auto &CodeGenOpts = *this->CodeGenOpts;5314  RETURN_IF(CodeGenOpts.DebugCompilationDir);5315  RETURN_IF(CodeGenOpts.CoverageCompilationDir);5316 5317  // Sanitizer options.5318  RETURN_IF_MANY(LangOpts->NoSanitizeFiles);5319 5320  // Coverage mappings.5321  RETURN_IF(CodeGenOpts.ProfileInstrumentUsePath);5322  RETURN_IF(CodeGenOpts.SampleProfileFile);5323  RETURN_IF(CodeGenOpts.ProfileRemappingFile);5324 5325  // Dependency output options.5326  for (auto &ExtraDep : DependencyOutputOpts->ExtraDeps)5327    RETURN_IF(ExtraDep.first);5328}5329 5330void CompilerInvocationBase::visitPaths(5331    llvm::function_ref<bool(StringRef)> Callback) const {5332  // The const_cast here is OK, because visitPathsImpl() itself doesn't modify5333  // the invocation, and our callback takes immutable StringRefs.5334  return const_cast<CompilerInvocationBase *>(this)->visitPathsImpl(5335      [&Callback](std::string &Path) { return Callback(StringRef(Path)); });5336}5337 5338void CompilerInvocationBase::generateCC1CommandLine(5339    ArgumentConsumer Consumer) const {5340  llvm::Triple T(getTargetOpts().Triple);5341 5342  GenerateFileSystemArgs(getFileSystemOpts(), Consumer);5343  GenerateMigratorArgs(getMigratorOpts(), Consumer);5344  GenerateAnalyzerArgs(getAnalyzerOpts(), Consumer);5345  GenerateDiagnosticArgs(getDiagnosticOpts(), Consumer,5346                         /*DefaultDiagColor=*/false);5347  GenerateFrontendArgs(getFrontendOpts(), Consumer, getLangOpts().IsHeaderFile);5348  GenerateTargetArgs(getTargetOpts(), Consumer);5349  GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer);5350  GenerateAPINotesArgs(getAPINotesOpts(), Consumer);5351  GeneratePointerAuthArgs(getLangOpts(), Consumer);5352  GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX);5353  GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T,5354                      getFrontendOpts().OutputFile, &getLangOpts());5355  GeneratePreprocessorArgs(getPreprocessorOpts(), Consumer, getLangOpts(),5356                           getFrontendOpts(), getCodeGenOpts());5357  GeneratePreprocessorOutputArgs(getPreprocessorOutputOpts(), Consumer,5358                                 getFrontendOpts().ProgramAction);5359  GenerateDependencyOutputArgs(getDependencyOutputOpts(), Consumer);5360}5361 5362std::vector<std::string> CompilerInvocationBase::getCC1CommandLine() const {5363  std::vector<std::string> Args{"-cc1"};5364  generateCC1CommandLine(5365      [&Args](const Twine &Arg) { Args.push_back(Arg.str()); });5366  return Args;5367}5368 5369void CompilerInvocation::resetNonModularOptions() {5370  getLangOpts().resetNonModularOptions();5371  getPreprocessorOpts().resetNonModularOptions();5372  getCodeGenOpts().resetNonModularOptions(getHeaderSearchOpts().ModuleFormat);5373}5374 5375void CompilerInvocation::clearImplicitModuleBuildOptions() {5376  getLangOpts().ImplicitModules = false;5377  getHeaderSearchOpts().ImplicitModuleMaps = false;5378  getHeaderSearchOpts().ModuleCachePath.clear();5379  getHeaderSearchOpts().ModulesValidateOncePerBuildSession = false;5380  getHeaderSearchOpts().BuildSessionTimestamp = 0;5381  // The specific values we canonicalize to for pruning don't affect behaviour,5382  /// so use the default values so they may be dropped from the command-line.5383  getHeaderSearchOpts().ModuleCachePruneInterval = 7 * 24 * 60 * 60;5384  getHeaderSearchOpts().ModuleCachePruneAfter = 31 * 24 * 60 * 60;5385}5386 5387IntrusiveRefCntPtr<llvm::vfs::FileSystem>5388clang::createVFSFromCompilerInvocation(const CompilerInvocation &CI,5389                                       DiagnosticsEngine &Diags) {5390  return createVFSFromCompilerInvocation(CI, Diags,5391                                         llvm::vfs::getRealFileSystem());5392}5393 5394IntrusiveRefCntPtr<llvm::vfs::FileSystem>5395clang::createVFSFromCompilerInvocation(5396    const CompilerInvocation &CI, DiagnosticsEngine &Diags,5397    IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {5398  return createVFSFromOverlayFiles(CI.getHeaderSearchOpts().VFSOverlayFiles,5399                                   Diags, std::move(BaseFS));5400}5401 5402IntrusiveRefCntPtr<llvm::vfs::FileSystem> clang::createVFSFromOverlayFiles(5403    ArrayRef<std::string> VFSOverlayFiles, DiagnosticsEngine &Diags,5404    IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) {5405  if (VFSOverlayFiles.empty())5406    return BaseFS;5407 5408  IntrusiveRefCntPtr<llvm::vfs::FileSystem> Result = BaseFS;5409  // earlier vfs files are on the bottom5410  for (const auto &File : VFSOverlayFiles) {5411    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =5412        Result->getBufferForFile(File);5413    if (!Buffer) {5414      Diags.Report(diag::err_missing_vfs_overlay_file) << File;5415      continue;5416    }5417 5418    IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getVFSFromYAML(5419        std::move(Buffer.get()), /*DiagHandler*/ nullptr, File,5420        /*DiagContext*/ nullptr, Result);5421    if (!FS) {5422      Diags.Report(diag::err_invalid_vfs_overlay) << File;5423      continue;5424    }5425 5426    Result = FS;5427  }5428  return Result;5429}5430