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